@@ -9,7 +9,17 @@ import path from 'node:path';
9
9
import fs from 'node:fs' ;
10
10
import { EOL } from 'node:os' ;
11
11
import { retryDecorator , NotRetryableError } from 'ts-retry-promise' ;
12
- import { envVars as env , Logger , Org , Messages , Lifecycle , SfError , Connection , lockInit } from '@salesforce/core' ;
12
+ import {
13
+ envVars as env ,
14
+ Logger ,
15
+ Org ,
16
+ Messages ,
17
+ Lifecycle ,
18
+ SfError ,
19
+ Connection ,
20
+ lockInit ,
21
+ trimTo15 ,
22
+ } from '@salesforce/core' ;
13
23
import { Duration , parseJsonMap } from '@salesforce/kit' ;
14
24
import { isString } from '@salesforce/ts-types' ;
15
25
import {
@@ -105,6 +115,7 @@ export class RemoteSourceTrackingService {
105
115
// A short term cache (within the same process) of query results based on a revision.
106
116
// Useful for source:pull, which makes 3 of the same queries; during status, building manifests, after pull success.
107
117
private queryCache = new Map < number , SourceMember [ ] > ( ) ;
118
+ private userQueryCache = new Map < string , string > ( ) ;
108
119
109
120
/**
110
121
* Initializes the service with existing remote source tracking data, or sets
@@ -477,10 +488,16 @@ ${formatSourceMemberWarnings(outstandingSourceMembers)}`
477
488
// because `serverMaxRevisionCounter` is always updated, we need to select > to catch the most recent change
478
489
const query = `SELECT ${ SOURCE_MEMBER_FIELDS . join ( ', ' ) } FROM SourceMember WHERE RevisionCounter > ${ rev } ` ;
479
490
this . logger [ quiet ? 'silent' : 'debug' ] ( `Query: ${ query } ` ) ;
480
- const queryResult = await queryFn ( this . org . getConnection ( ) , query ) ;
481
- this . queryCache . set ( rev , queryResult ) ;
482
-
483
- return queryResult ;
491
+ const conn = this . org . getConnection ( ) ;
492
+ const queryResult = await queryFn ( conn , query ) ;
493
+ await updateCacheWithUnknownUsers ( conn , queryResult , this . userQueryCache ) ;
494
+ const queryResultWithResolvedUsers = queryResult . map ( ( member ) => ( {
495
+ ...member ,
496
+ ChangedBy : this . userQueryCache . get ( member . ChangedBy ) ?? member . ChangedBy ,
497
+ } ) ) ;
498
+ this . queryCache . set ( rev , queryResultWithResolvedUsers ) ;
499
+
500
+ return queryResultWithResolvedUsers ;
484
501
}
485
502
486
503
private async write ( ) : Promise < void > {
@@ -499,6 +516,19 @@ ${formatSourceMemberWarnings(outstandingSourceMembers)}`
499
516
}
500
517
}
501
518
519
+ const updateCacheWithUnknownUsers = async (
520
+ conn : Connection ,
521
+ queryResult : SourceMember [ ] ,
522
+ userCache : Map < string , string >
523
+ ) : Promise < void > => {
524
+ const unknownUsers = new Set < string > ( queryResult . map ( ( member ) => member . ChangedBy ) . filter ( ( u ) => ! userCache . has ( u ) ) ) ;
525
+ if ( unknownUsers . size > 0 ) {
526
+ const userQuery = `SELECT Id, Name FROM User WHERE Id IN ('${ Array . from ( unknownUsers ) . join ( "','" ) } ')` ;
527
+ ( await conn . query < { Id : string ; Name : string } > ( userQuery , { autoFetch : true , maxFetch : 50_000 } ) ) . records . map (
528
+ ( u ) => userCache . set ( trimTo15 ( u . Id ) , u . Name )
529
+ ) ;
530
+ }
531
+ } ;
502
532
/**
503
533
* pass in an RCE, and this will return a pullable ChangeResult.
504
534
* Useful for correcing bundle types where the files show change results with types but aren't resolvable
0 commit comments