@@ -30,6 +30,7 @@ export type Contents = {
30
30
sourceMembers : Record < string , MemberRevision > ;
31
31
} ;
32
32
type MemberRevisionMapEntry = [ string , MemberRevision ] ;
33
+ type PinoLogger = ReturnType < ( typeof Logger ) [ 'getRawRootLogger' ] > ;
33
34
34
35
const FILENAME = 'maxRevision.json' ;
35
36
@@ -88,7 +89,7 @@ export class RemoteSourceTrackingService {
88
89
private static instanceMap = new Map < string , RemoteSourceTrackingService > ( ) ;
89
90
public readonly filePath : string ;
90
91
91
- private logger ! : Logger ;
92
+ private logger ! : PinoLogger ;
92
93
private serverMaxRevisionCounter = 0 ;
93
94
private sourceMembers = new Map < string , MemberRevision > ( ) ;
94
95
@@ -146,10 +147,8 @@ export class RemoteSourceTrackingService {
146
147
if ( elements . length === 0 ) {
147
148
return ;
148
149
}
149
- const quiet = elements . length > 100 ;
150
- if ( quiet ) {
151
- this . logger . debug ( `Syncing ${ elements . length } Revisions by key` ) ;
152
- }
150
+ const quietLogger = elements . length > 100 ? this . logger . silent : this . logger . debug ;
151
+ quietLogger ( `Syncing ${ elements . length } Revisions by key` ) ;
153
152
154
153
// this can be super-repetitive on a large ExperienceBundle where there is an element for each file but only one Revision for the entire bundle
155
154
// any item in an aura/LWC bundle needs to represent the top (bundle) level and the file itself
@@ -159,11 +158,9 @@ export class RemoteSourceTrackingService {
159
158
if ( ! revision ) {
160
159
this . logger . warn ( `found no matching revision for ${ metadataKey } ` ) ;
161
160
} else if ( doesNotMatchServer ( revision ) ) {
162
- if ( ! quiet ) {
163
- this . logger . debug (
164
- `Syncing ${ metadataKey } revision from ${ revision . lastRetrievedFromServer } to ${ revision . serverRevisionCounter } `
165
- ) ;
166
- }
161
+ quietLogger (
162
+ `Syncing ${ metadataKey } revision from ${ revision . lastRetrievedFromServer } to ${ revision . serverRevisionCounter } `
163
+ ) ;
167
164
this . setMemberRevision ( metadataKey , { ...revision , lastRetrievedFromServer : revision . serverRevisionCounter } ) ;
168
165
}
169
166
} ) ;
@@ -377,13 +374,17 @@ ${formatSourceMemberWarnings(outstandingSourceMembers)}`
377
374
if ( sourceMembers . length === 0 ) {
378
375
return ;
379
376
}
380
- const quiet = sourceMembers . length > 100 ;
381
- if ( quiet ) {
382
- this . logger . debug ( `Upserting ${ sourceMembers . length } SourceMembers to maxRevision.json` ) ;
383
- }
377
+ const quietLogger = sourceMembers . length > 100 ? this . logger . silent : this . logger . debug ;
378
+ quietLogger ( `Upserting ${ sourceMembers . length } SourceMembers to maxRevision.json` ) ;
384
379
385
- let serverMaxRevisionCounter = this . serverMaxRevisionCounter ;
386
- sourceMembers . forEach ( ( change ) => {
380
+ // Update the serverMaxRevisionCounter to the highest RevisionCounter
381
+ this . serverMaxRevisionCounter = Math . max (
382
+ this . serverMaxRevisionCounter ,
383
+ ...sourceMembers . map ( ( m ) => m . RevisionCounter )
384
+ ) ;
385
+ this . logger . debug ( `Updating serverMaxRevisionCounter to ${ this . serverMaxRevisionCounter } ` ) ;
386
+
387
+ sourceMembers . map ( ( change ) => {
387
388
// try accessing the sourceMembers object at the index of the change's name
388
389
// if it exists, we'll update the fields - if it doesn't, we'll create and insert it
389
390
const key = getMetadataKey ( change . MemberType , change . MemberName ) ;
@@ -395,35 +396,23 @@ ${formatSourceMemberWarnings(outstandingSourceMembers)}`
395
396
} ;
396
397
if ( sourceMember . lastRetrievedFromServer ) {
397
398
// We are already tracking this element so we'll update it
398
- if ( ! quiet ) {
399
- this . logger . debug (
400
- `Updating ${ key } to RevisionCounter: ${ change . RevisionCounter } ${ sync ? ' and syncing' : '' } `
401
- ) ;
402
- }
399
+ quietLogger ( `Updating ${ key } to RevisionCounter: ${ change . RevisionCounter } ${ sync ? ' and syncing' : '' } ` ) ;
403
400
sourceMember . serverRevisionCounter = change . RevisionCounter ;
404
401
sourceMember . isNameObsolete = change . IsNameObsolete ;
405
- } else if ( ! quiet ) {
402
+ } else {
406
403
// We are not yet tracking it so we'll insert a new record
407
- this . logger . debug (
408
- `Inserting ${ key } with RevisionCounter: ${ change . RevisionCounter } ${ sync ? ' and syncing' : '' } `
409
- ) ;
404
+ quietLogger ( `Inserting ${ key } with RevisionCounter: ${ change . RevisionCounter } ${ sync ? ' and syncing' : '' } ` ) ;
410
405
}
411
406
412
407
// If we are syncing changes then we need to update the lastRetrievedFromServer field to
413
408
// match the RevisionCounter from the SourceMember.
414
409
if ( sync ) {
415
410
sourceMember . lastRetrievedFromServer = change . RevisionCounter ;
416
411
}
417
- // Keep track of the highest RevisionCounter for setting the serverMaxRevisionCounter
418
- if ( change . RevisionCounter > serverMaxRevisionCounter ) {
419
- serverMaxRevisionCounter = change . RevisionCounter ;
420
- }
412
+
421
413
// Update the state with the latest SourceMember data
422
414
this . setMemberRevision ( key , sourceMember ) ;
423
415
} ) ;
424
- // Update the serverMaxRevisionCounter to the highest RevisionCounter
425
- this . serverMaxRevisionCounter = serverMaxRevisionCounter ;
426
- this . logger . debug ( `Updating serverMaxRevisionCounter to ${ serverMaxRevisionCounter } ` ) ;
427
416
428
417
await this . write ( ) ;
429
418
}
@@ -435,7 +424,7 @@ ${formatSourceMemberWarnings(outstandingSourceMembers)}`
435
424
const messages = Messages . loadMessages ( '@salesforce/source-tracking' , 'source' ) ;
436
425
throw new SfError ( messages . getMessage ( 'NonSourceTrackedOrgError' ) , 'NonSourceTrackedOrgError' ) ;
437
426
}
438
- this . logger = await Logger . child ( this . constructor . name ) ;
427
+ this . logger = Logger . getRawRootLogger ( ) . child ( { name : this . constructor . name } ) ;
439
428
if ( fs . existsSync ( this . filePath ) ) {
440
429
// read the file contents and turn it into the map
441
430
const rawContents = await readFileContents ( this . filePath ) ;
@@ -486,9 +475,7 @@ ${formatSourceMemberWarnings(outstandingSourceMembers)}`
486
475
487
476
// because `serverMaxRevisionCounter` is always updated, we need to select > to catch the most recent change
488
477
const query = `SELECT MemberType, MemberName, IsNameObsolete, RevisionCounter FROM SourceMember WHERE RevisionCounter > ${ rev } ` ;
489
- if ( ! quiet ) {
490
- this . logger . debug ( `Query: ${ query } ` ) ;
491
- }
478
+ this . logger [ quiet ? 'silent' : 'debug' ] ( `Query: ${ query } ` ) ;
492
479
const queryResult = await queryFn ( this . org . getConnection ( ) , query ) ;
493
480
this . queryCache . set ( rev , queryResult ) ;
494
481
@@ -536,15 +523,15 @@ const revisionToRemoteChangeElement = ([memberKey, memberRevision]: MemberRevisi
536
523
* iterate SourceMember keys and compare their decoded value with the decoded key.
537
524
* if there's a match, return the matching decoded key, otherwise, return the original key
538
525
*/
539
- function getDecodedKeyIfSourceMembersHas ( {
526
+ const getDecodedKeyIfSourceMembersHas = ( {
540
527
key,
541
528
sourceMembers,
542
529
logger,
543
530
} : {
544
531
sourceMembers : Map < string , MemberRevision > ;
545
532
key : string ;
546
- logger : Logger ;
547
- } ) : string {
533
+ logger : PinoLogger ;
534
+ } ) : string => {
548
535
try {
549
536
const originalKeyDecoded = decodeURIComponent ( key ) ;
550
537
const match = Array . from ( sourceMembers . keys ( ) ) . find (
@@ -560,7 +547,7 @@ function getDecodedKeyIfSourceMembersHas({
560
547
logger . debug ( `Could not decode metadata key: ${ key } due to: ${ errMsg } ` ) ;
561
548
}
562
549
return key ;
563
- }
550
+ } ;
564
551
565
552
const getFilePath = ( orgId : string ) : string => path . join ( '.sf' , 'orgs' , orgId , FILENAME ) ;
566
553
@@ -579,7 +566,7 @@ const readFileContents = async (filePath: string): Promise<Contents | Record<str
579
566
} ;
580
567
581
568
export const calculateTimeout =
582
- ( logger : Logger ) =>
569
+ ( logger : PinoLogger ) =>
583
570
( memberCount : number ) : Duration => {
584
571
const overriddenTimeout = env . getNumber ( 'SFDX_SOURCE_MEMBER_POLLING_TIMEOUT' , 0 ) ;
585
572
if ( overriddenTimeout > 0 ) {
@@ -603,9 +590,11 @@ export const querySourceMembersTo = async (conn: Connection, toRevision: number)
603
590
604
591
const queryFn = async ( conn : Connection , query : string ) : Promise < SourceMember [ ] > => {
605
592
try {
606
- return ( await conn . tooling . query < SourceMember > ( query , { autoFetch : true , maxFetch : 50_000 } ) ) . records ;
593
+ return ( await conn . tooling . query < SourceMember > ( query , { autoFetch : true , maxFetch : 50_000 } ) ) . records . map (
594
+ sourceMemberCorrections
595
+ ) ;
607
596
} catch ( error ) {
608
- throw error instanceof Error ? SfError . wrap ( error ) : error ;
597
+ throw SfError . wrap ( error ) ;
609
598
}
610
599
} ;
611
600
@@ -625,3 +614,11 @@ const revisionDoesNotMatch = ([, member]: MemberRevisionMapEntry): boolean => do
625
614
626
615
const doesNotMatchServer = ( member : MemberRevision ) : boolean =>
627
616
member . serverRevisionCounter !== member . lastRetrievedFromServer ;
617
+
618
+ /** A series of workarounds for server-side bugs. Each bug should be filed against a team, with a WI, so we know when these are fixed and can be removed */
619
+ const sourceMemberCorrections = ( sourceMember : SourceMember ) : SourceMember => {
620
+ if ( sourceMember . MemberType === 'QuickActionDefinition' ) {
621
+ return { ...sourceMember , MemberType : 'QuickAction' } ; // W-15837125
622
+ }
623
+ return sourceMember ;
624
+ } ;
0 commit comments