@salesforce/source-tracking 2.2.1 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [2.2.2](https://github.com/forcedotcom/source-tracking/compare/v2.2.1...v2.2.2) (2022-08-10)
6
+
7
+ ### ⚠ BREAKING CHANGES
8
+
9
+ - return componentSet and File Responses
10
+
11
+ ### Features
12
+
13
+ - local CmpSet from changes tracks ignored files like normal CmpSet ([aaa707f](https://github.com/forcedotcom/source-tracking/commit/aaa707fb2e68f5b7199d79d8ea8213068bea09b1))
14
+ - local componentSet can show ignored local files ([c230437](https://github.com/forcedotcom/source-tracking/commit/c23043726dcee304a3b550c0d463719e11f6d9ef))
15
+ - overload to preserve backwards compatibility ([cfc53e3](https://github.com/forcedotcom/source-tracking/commit/cfc53e3ecf0b037cbe7c7ada2588c2e4ead2ab88))
16
+ - return componentSet and File Responses ([b8dc01e](https://github.com/forcedotcom/source-tracking/commit/b8dc01eb0e01ed0aa010c554beae35fa0613d628))
17
+
18
+ ### Bug Fixes
19
+
20
+ - bump eslint/jsdoc to get automerges flowing again ([afd85ff](https://github.com/forcedotcom/source-tracking/commit/afd85ff420877b7fb969085cf5f59d9c3f80555f))
21
+ - ensure remote changes have a value for ignored (plugin expects it) ([bc1379f](https://github.com/forcedotcom/source-tracking/commit/bc1379f8f020fed5bfca721330f4404662d1b300))
22
+ - force version change ([5483cd3](https://github.com/forcedotcom/source-tracking/commit/5483cd317614aea6aeb50c5544cede92fa9c2cb2))
23
+ - remote changes display ignoredness ([d3533f9](https://github.com/forcedotcom/source-tracking/commit/d3533f9275d2a290b3c34019e204718e16ceaa75))
24
+
5
25
  ### [2.2.1](https://github.com/forcedotcom/source-tracking/compare/v2.2.0...v2.2.1) (2022-07-05)
6
26
 
7
27
  ### Bug Fixes
@@ -31,8 +31,7 @@ const findConflictsInComponentSet = (cs, conflicts) => {
31
31
  conflicts
32
32
  .filter((cr) => cr.name && cr.type && cs.has({ fullName: cr.name, type: cr.type }))
33
33
  .forEach((cr) => {
34
- var _a;
35
- (_a = cr.filenames) === null || _a === void 0 ? void 0 : _a.forEach((f) => {
34
+ cr.filenames?.forEach((f) => {
36
35
  conflictMap.set(`${cr.name}#${cr.type}#${f}`, {
37
36
  state: 'Conflict',
38
37
  // the following 2 type assertions are valid because of previous filter statement
@@ -52,17 +51,15 @@ const getDedupedConflictsFromChanges = ({ localChanges = [], remoteChanges = [],
52
51
  const fileNameIndex = new Map();
53
52
  const metadataKeyIndex = new Map();
54
53
  remoteChanges.map((change) => {
55
- var _a;
56
54
  if (change.name && change.type) {
57
55
  metadataKeyIndex.set((0, functions_1.getMetadataKey)(change.name, change.type), change);
58
56
  }
59
- (_a = change.filenames) === null || _a === void 0 ? void 0 : _a.map((filename) => {
57
+ change.filenames?.map((filename) => {
60
58
  fileNameIndex.set(filename, change);
61
59
  });
62
60
  });
63
61
  const conflicts = new Set();
64
62
  (0, populateTypesAndNames_1.populateTypesAndNames)({ elements: localChanges, excludeUnresolvable: true, projectPath, forceIgnore }).map((change) => {
65
- var _a;
66
63
  const metadataKey = (0, functions_1.getMetadataKey)(change.name, change.type);
67
64
  // option 1: name and type match
68
65
  if (metadataKeyIndex.has(metadataKey)) {
@@ -70,7 +67,7 @@ const getDedupedConflictsFromChanges = ({ localChanges = [], remoteChanges = [],
70
67
  }
71
68
  else {
72
69
  // option 2: some of the filenames match
73
- (_a = change.filenames) === null || _a === void 0 ? void 0 : _a.map((filename) => {
70
+ change.filenames?.map((filename) => {
74
71
  if (fileNameIndex.has(filename)) {
75
72
  conflicts.add({ ...fileNameIndex.get(filename) });
76
73
  }
@@ -24,7 +24,7 @@ const typesToNoPollFor = [
24
24
  ];
25
25
  const typesNotToPollForIfNamespace = ['CustomLabels', 'CustomMetadata', 'DuplicateRule', 'WebLink'];
26
26
  const isEncodedTypeWithPercentSign = (type, filePath) => ['Layout', 'Profile', 'HomePageComponent', 'HomePageLayout', 'MilestoneType'].includes(type) &&
27
- Boolean(filePath === null || filePath === void 0 ? void 0 : filePath.includes('%'));
27
+ Boolean(filePath?.includes('%'));
28
28
  // aura xml aren't tracked as SourceMembers
29
29
  const isSpecialAuraXml = (filePath) => Boolean(filePath &&
30
30
  (filePath.endsWith('.cmp-meta.xml') ||
@@ -35,29 +35,27 @@ const isSpecialAuraXml = (filePath) => Boolean(filePath &&
35
35
  const calculateExpectedSourceMembers = (expectedMembers) => {
36
36
  const outstandingSourceMembers = new Map();
37
37
  expectedMembers
38
- .filter((fileResponse) => {
39
- var _a, _b, _c, _d;
40
- // unchanged files will never be in the sourceMembers. Not really sure why SDR returns them.
41
- return fileResponse.state !== source_deploy_retrieve_1.ComponentStatus.Unchanged &&
42
- // if a listView is the only change inside an object, the object won't have a sourceMember change. We won't wait for those to be found
43
- // we don't know which email folder type might be there, so don't require either
44
- // Portal doesn't support source tracking, according to the coverage report
45
- !typesToNoPollFor.includes(fileResponse.type) &&
46
- // don't wait for standard fields on standard objects
47
- !(fileResponse.type === 'CustomField' && !((_a = fileResponse.filePath) === null || _a === void 0 ? void 0 : _a.includes('__c'))) &&
48
- // deleted fields
49
- !(fileResponse.type === 'CustomField' && ((_b = fileResponse.filePath) === null || _b === void 0 ? void 0 : _b.includes('_del__c'))) &&
50
- // built-in report type ReportType__screen_flows_prebuilt_crt
51
- !(fileResponse.type === 'ReportType' && ((_c = fileResponse.filePath) === null || _c === void 0 ? void 0 : _c.includes('screen_flows_prebuilt_crt'))) &&
52
- // they're settings to mdapi, and FooSettings in sourceMembers
53
- !fileResponse.type.includes('Settings') &&
54
- // mdapi encodes these, sourceMembers don't have encoding
55
- !isEncodedTypeWithPercentSign(fileResponse.type, fileResponse.filePath) &&
56
- !(typesNotToPollForIfNamespace.includes(fileResponse.type) && ((_d = fileResponse.filePath) === null || _d === void 0 ? void 0 : _d.includes('__'))) &&
57
- // don't wait on workflow children
58
- !fileResponse.type.startsWith('Workflow') &&
59
- !isSpecialAuraXml(fileResponse.filePath);
60
- })
38
+ .filter((fileResponse) =>
39
+ // unchanged files will never be in the sourceMembers. Not really sure why SDR returns them.
40
+ fileResponse.state !== source_deploy_retrieve_1.ComponentStatus.Unchanged &&
41
+ // if a listView is the only change inside an object, the object won't have a sourceMember change. We won't wait for those to be found
42
+ // we don't know which email folder type might be there, so don't require either
43
+ // Portal doesn't support source tracking, according to the coverage report
44
+ !typesToNoPollFor.includes(fileResponse.type) &&
45
+ // don't wait for standard fields on standard objects
46
+ !(fileResponse.type === 'CustomField' && !fileResponse.filePath?.includes('__c')) &&
47
+ // deleted fields
48
+ !(fileResponse.type === 'CustomField' && fileResponse.filePath?.includes('_del__c')) &&
49
+ // built-in report type ReportType__screen_flows_prebuilt_crt
50
+ !(fileResponse.type === 'ReportType' && fileResponse.filePath?.includes('screen_flows_prebuilt_crt')) &&
51
+ // they're settings to mdapi, and FooSettings in sourceMembers
52
+ !fileResponse.type.includes('Settings') &&
53
+ // mdapi encodes these, sourceMembers don't have encoding
54
+ !isEncodedTypeWithPercentSign(fileResponse.type, fileResponse.filePath) &&
55
+ !(typesNotToPollForIfNamespace.includes(fileResponse.type) && fileResponse.filePath?.includes('__')) &&
56
+ // don't wait on workflow children
57
+ !fileResponse.type.startsWith('Workflow') &&
58
+ !isSpecialAuraXml(fileResponse.filePath))
61
59
  .map((member) => {
62
60
  (0, metadataKeys_1.getMetadataKeyFromFileResponse)(member)
63
61
  // remove some individual members known to not work with tracking even when their type does
@@ -20,7 +20,7 @@ const getKeyFromObject = (element) => {
20
20
  throw new Error(`unable to complete key from ${JSON.stringify(element)}`);
21
21
  };
22
22
  exports.getKeyFromObject = getKeyFromObject;
23
- const isBundle = (cmp) => { var _a; return ((_a = cmp.type.strategies) === null || _a === void 0 ? void 0 : _a.adapter) === 'bundle'; };
23
+ const isBundle = (cmp) => cmp.type.strategies?.adapter === 'bundle';
24
24
  exports.isBundle = isBundle;
25
25
  const isLwcLocalOnlyTest = (filePath) => filePath.includes('__utam__') || filePath.includes('__tests__');
26
26
  exports.isLwcLocalOnlyTest = isLwcLocalOnlyTest;
@@ -76,9 +76,12 @@ const getComponentSets = (groupings, sourceApiVersion) => {
76
76
  })
77
77
  .filter(guards_1.sourceComponentGuard)
78
78
  .map((component) => componentSet.add(component));
79
+ // there may have been ignored files, but componentSet.add doesn't automatically track them.
80
+ // We'll manually set the ignored paths from what the resolver has been tracking
81
+ componentSet.forceIgnoredPaths = new Set([...(componentSet.forceIgnoredPaths ?? [])].concat(Array.from(resolverForNonDeletes.forceIgnoredPaths)));
79
82
  return componentSet;
80
83
  })
81
- .filter((componentSet) => componentSet.size > 0);
84
+ .filter((componentSet) => componentSet.size > 0 || componentSet.forceIgnoredPaths?.size);
82
85
  };
83
86
  exports.getComponentSets = getComponentSets;
84
87
  //# sourceMappingURL=localComponentSetArray.js.map
@@ -13,7 +13,7 @@ const core_1 = require("@salesforce/core");
13
13
  const functions_1 = require("./functions");
14
14
  // See UT for examples of the complexity this must handle
15
15
  // keys always use forward slashes, even on Windows
16
- const pathAfterFullName = (fileResponse) => (fileResponse === null || fileResponse === void 0 ? void 0 : fileResponse.filePath)
16
+ const pathAfterFullName = (fileResponse) => fileResponse?.filePath
17
17
  ? (0, path_1.join)((0, path_1.dirname)(fileResponse.filePath).substring((0, path_1.dirname)(fileResponse.filePath).lastIndexOf(fileResponse.fullName)), (0, path_1.basename)(fileResponse.filePath)).replace(/\\/gi, '/')
18
18
  : '';
19
19
  const registry = new source_deploy_retrieve_1.RegistryAccess();
@@ -43,7 +43,7 @@ const populateFilePaths = (elements, packageDirPaths) => {
43
43
  // there *could* be something missing
44
44
  // some types (ex: LWC) show up as multiple files in the remote changes, but only one in the component set
45
45
  // iterate the elements to see which ones didn't make it into the component set
46
- const missingComponents = elements.filter((element) => !remoteChangesAsComponentSet.has({ type: element === null || element === void 0 ? void 0 : element.type, fullName: element === null || element === void 0 ? void 0 : element.name }));
46
+ const missingComponents = elements.filter((element) => !remoteChangesAsComponentSet.has({ type: element?.type, fullName: element?.name }));
47
47
  // Throw if anything was actually missing
48
48
  if (missingComponents.length > 0) {
49
49
  throw new Error(`unable to generate complete component set for ${elements
@@ -45,19 +45,18 @@ const populateTypesAndNames = ({ elements, projectPath, forceIgnore, excludeUnre
45
45
  // make it simpler to find things later
46
46
  const elementMap = new Map();
47
47
  elements.map((element) => {
48
- var _a;
49
- (_a = element.filenames) === null || _a === void 0 ? void 0 : _a.map((filename) => {
48
+ element.filenames?.map((filename) => {
50
49
  elementMap.set((0, functions_1.ensureRelative)(filename, projectPath), element);
51
50
  });
52
51
  });
53
52
  // iterates the local components and sets their filenames
54
53
  sourceComponents.map((matchingComponent) => {
55
- if ((matchingComponent === null || matchingComponent === void 0 ? void 0 : matchingComponent.fullName) && (matchingComponent === null || matchingComponent === void 0 ? void 0 : matchingComponent.type.name)) {
54
+ if (matchingComponent?.fullName && matchingComponent?.type.name) {
56
55
  const filenamesFromMatchingComponent = [matchingComponent.xml, ...matchingComponent.walkContent()];
57
56
  const ignored = filenamesFromMatchingComponent
58
57
  .filter(ts_types_1.isString)
59
58
  .filter((f) => !(0, functions_1.isLwcLocalOnlyTest)(f))
60
- .some((f) => forceIgnore === null || forceIgnore === void 0 ? void 0 : forceIgnore.denies(f));
59
+ .some((f) => forceIgnore?.denies(f));
61
60
  filenamesFromMatchingComponent.map((filename) => {
62
61
  if (filename && elementMap.has(filename)) {
63
62
  // add the type/name from the componentSet onto the element
@@ -7,7 +7,6 @@
7
7
  */
8
8
  /* eslint-disable no-underscore-dangle */
9
9
  /* eslint-disable @typescript-eslint/member-ordering */
10
- var _a;
11
10
  Object.defineProperty(exports, "__esModule", { value: true });
12
11
  exports.remoteChangeElementToChangeResult = exports.RemoteSourceTrackingService = void 0;
13
12
  const path = require("path");
@@ -23,7 +22,7 @@ const expectedSourceMembers_1 = require("./expectedSourceMembers");
23
22
  * even when there is a longer timeout remaining (because the deployment is very large)
24
23
  */
25
24
  const POLLING_DELAY_MS = 1000;
26
- const CONSECUTIVE_EMPTY_POLLING_RESULT_LIMIT = ((_a = kit_1.env.getNumber('SFDX_SOURCE_MEMBER_POLLING_TIMEOUT')) !== null && _a !== void 0 ? _a : 120) / kit_1.Duration.milliseconds(POLLING_DELAY_MS).seconds;
25
+ const CONSECUTIVE_EMPTY_POLLING_RESULT_LIMIT = (kit_1.env.getNumber('SFDX_SOURCE_MEMBER_POLLING_TIMEOUT') ?? 120) / kit_1.Duration.milliseconds(POLLING_DELAY_MS).seconds;
27
26
  /**
28
27
  * This service handles source tracking of metadata between a local project and an org.
29
28
  * Source tracking state is persisted to .sfdx/orgs/<orgId>/maxRevision.json.
@@ -264,11 +263,10 @@ class RemoteSourceTrackingService extends core_1.ConfigFile {
264
263
  }
265
264
  let serverMaxRevisionCounter = this.getServerMaxRevision();
266
265
  sourceMembers.forEach((change) => {
267
- var _a;
268
266
  // try accessing the sourceMembers object at the index of the change's name
269
267
  // if it exists, we'll update the fields - if it doesn't, we'll create and insert it
270
268
  const key = (0, functions_1.getMetadataKey)(change.MemberType, change.MemberName);
271
- const sourceMember = (_a = this.getSourceMember(key)) !== null && _a !== void 0 ? _a : {
269
+ const sourceMember = this.getSourceMember(key) ?? {
272
270
  serverRevisionCounter: change.RevisionCounter,
273
271
  lastRetrievedFromServer: null,
274
272
  memberType: change.MemberType,
@@ -432,8 +430,7 @@ class RemoteSourceTrackingService extends core_1.ConfigFile {
432
430
  }
433
431
  }
434
432
  calculateTimeout(memberCount) {
435
- var _a;
436
- const overriddenTimeout = (_a = kit_1.env.getNumber('SFDX_SOURCE_MEMBER_POLLING_TIMEOUT', 0)) !== null && _a !== void 0 ? _a : 0;
433
+ const overriddenTimeout = kit_1.env.getNumber('SFDX_SOURCE_MEMBER_POLLING_TIMEOUT', 0) ?? 0;
437
434
  if (overriddenTimeout > 0) {
438
435
  this.logger.debug(`Overriding SourceMember polling timeout to ${overriddenTimeout}`);
439
436
  return kit_1.Duration.seconds(overriddenTimeout);
@@ -19,6 +19,10 @@ export interface SourceTrackingOptions {
19
19
  */
20
20
  ignoreLocalCache?: boolean;
21
21
  }
22
+ declare type RemoteChangesResults = {
23
+ componentSetFromNonDeletes: ComponentSet;
24
+ fileResponsesFromDelete: FileResponse[];
25
+ };
22
26
  /**
23
27
  * Manages source tracking files (remote and local)
24
28
  *
@@ -104,11 +108,12 @@ export declare class SourceTracking extends AsyncCreatable {
104
108
  *
105
109
  * Convenience method to reduce duplicated steps required to do a fka pull
106
110
  * It's full of side effects: retrieving remote deletes, deleting those files locall, and then updating tracking files
107
- * Most bizarrely, it then returns a ComponentSet of the remote nonDeletes.
111
+ * Most bizarrely, it then returns a ComponentSet of the remote nonDeletes and the FileResponses from the delete
108
112
  *
109
- * @returns the ComponentSet for what you would retrieve now that the deletes are done
113
+ * @returns the ComponentSet for what you would retrieve now that the deletes are done, and optionally, a FileResponses array for the deleted files
110
114
  */
111
- maybeApplyRemoteDeletesToLocal(): Promise<ComponentSet>;
115
+ maybeApplyRemoteDeletesToLocal(returnDeleteFileResponses: true): Promise<RemoteChangesResults>;
116
+ maybeApplyRemoteDeletesToLocal(returnDeleteFileResponses?: false): Promise<ComponentSet>;
112
117
  /**
113
118
  *
114
119
  * returns immediately if there are no changesToDelete
@@ -186,3 +191,4 @@ export declare class SourceTracking extends AsyncCreatable {
186
191
  private localChangesToOutputRow;
187
192
  private remoteChangesToOutputRows;
188
193
  }
194
+ export {};
@@ -13,6 +13,8 @@ const core_1 = require("@salesforce/core");
13
13
  const kit_1 = require("@salesforce/kit");
14
14
  const ts_types_1 = require("@salesforce/ts-types");
15
15
  const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
16
+ // this is not exported by SDR (see the comments in SDR regarding its limitations)
17
+ const filePathGenerator_1 = require("@salesforce/source-deploy-retrieve/lib/src/utils/filePathGenerator");
16
18
  const remoteSourceTrackingService_1 = require("./shared/remoteSourceTrackingService");
17
19
  const localShadowRepo_1 = require("./shared/localShadowRepo");
18
20
  const conflicts_1 = require("./shared/conflicts");
@@ -31,7 +33,6 @@ const localComponentSetArray_1 = require("./shared/localComponentSetArray");
31
33
  */
32
34
  class SourceTracking extends kit_1.AsyncCreatable {
33
35
  constructor(options) {
34
- var _a, _b, _c;
35
36
  super(options);
36
37
  this.org = options.org;
37
38
  this.orgId = this.org.getOrgId();
@@ -39,9 +40,9 @@ class SourceTracking extends kit_1.AsyncCreatable {
39
40
  this.packagesDirs = options.project.getPackageDirectories();
40
41
  this.logger = core_1.Logger.childFromRoot('SourceTracking');
41
42
  this.project = options.project;
42
- this.ignoreConflicts = (_a = options.ignoreConflicts) !== null && _a !== void 0 ? _a : false;
43
- this.ignoreLocalCache = (_b = options.ignoreLocalCache) !== null && _b !== void 0 ? _b : false;
44
- this.subscribeSDREvents = (_c = options.subscribeSDREvents) !== null && _c !== void 0 ? _c : false;
43
+ this.ignoreConflicts = options.ignoreConflicts ?? false;
44
+ this.ignoreLocalCache = options.ignoreLocalCache ?? false;
45
+ this.subscribeSDREvents = options.subscribeSDREvents ?? false;
45
46
  this.hasSfdxTrackingFiles = (0, compatibility_1.hasSfdxTrackingFiles)(this.orgId, this.projectPath);
46
47
  }
47
48
  // eslint-disable-next-line class-methods-use-this
@@ -70,7 +71,7 @@ class SourceTracking extends kit_1.AsyncCreatable {
70
71
  packageDirs: this.packagesDirs,
71
72
  nonDeletes,
72
73
  deletes,
73
- }, byPackageDir !== null && byPackageDir !== void 0 ? byPackageDir : Boolean(projectConfig.pushPackageDirectoriesSequentially)); // if the users specified true or false for the param, that overrides the project config
74
+ }, byPackageDir ?? Boolean(projectConfig.pushPackageDirectoriesSequentially)); // if the users specified true or false for the param, that overrides the project config
74
75
  this.logger.debug(`will build array of ${groupings.length} componentSet(s)`);
75
76
  return (0, localComponentSetArray_1.getComponentSets)(groupings, sourceApiVersion);
76
77
  }
@@ -133,7 +134,7 @@ class SourceTracking extends kit_1.AsyncCreatable {
133
134
  return results;
134
135
  }
135
136
  async getChanges(options) {
136
- if ((options === null || options === void 0 ? void 0 : options.origin) === 'local') {
137
+ if (options?.origin === 'local') {
137
138
  await this.ensureLocalTracking();
138
139
  const filenames = await this.getLocalChangesAsFilenames(options.state);
139
140
  if (options.format === 'string') {
@@ -162,7 +163,7 @@ class SourceTracking extends kit_1.AsyncCreatable {
162
163
  .filter(guards_1.sourceComponentGuard);
163
164
  }
164
165
  }
165
- if ((options === null || options === void 0 ? void 0 : options.origin) === 'remote') {
166
+ if (options?.origin === 'remote') {
166
167
  await this.ensureRemoteTracking();
167
168
  const remoteChanges = await this.remoteSourceTrackingService.retrieveUpdates();
168
169
  this.logger.debug('remoteChanges', remoteChanges);
@@ -178,8 +179,8 @@ class SourceTracking extends kit_1.AsyncCreatable {
178
179
  }
179
180
  // turn it into a componentSet to resolve filenames
180
181
  const remoteChangesAsComponentSet = new source_deploy_retrieve_1.ComponentSet(filteredChanges.map((element) => ({
181
- type: element === null || element === void 0 ? void 0 : element.type,
182
- fullName: element === null || element === void 0 ? void 0 : element.name,
182
+ type: element?.type,
183
+ fullName: element?.name,
183
184
  })));
184
185
  const matchingLocalSourceComponentsSet = source_deploy_retrieve_1.ComponentSet.fromSource({
185
186
  fsPaths: this.packagesDirs.map((dir) => (0, path_1.resolve)(dir.fullPath)),
@@ -197,18 +198,12 @@ class SourceTracking extends kit_1.AsyncCreatable {
197
198
  }
198
199
  throw new Error(`unsupported options: ${JSON.stringify(options)}`);
199
200
  }
200
- /**
201
- *
202
- * Convenience method to reduce duplicated steps required to do a fka pull
203
- * It's full of side effects: retrieving remote deletes, deleting those files locall, and then updating tracking files
204
- * Most bizarrely, it then returns a ComponentSet of the remote nonDeletes.
205
- *
206
- * @returns the ComponentSet for what you would retrieve now that the deletes are done
207
- */
208
- async maybeApplyRemoteDeletesToLocal() {
201
+ async maybeApplyRemoteDeletesToLocal(returnDeleteFileResponses) {
209
202
  const changesToDelete = await this.getChanges({ origin: 'remote', state: 'delete', format: 'SourceComponent' });
210
- await this.deleteFilesAndUpdateTracking(changesToDelete);
211
- return this.remoteNonDeletesAsComponentSet();
203
+ const fileResponsesFromDelete = await this.deleteFilesAndUpdateTracking(changesToDelete);
204
+ return returnDeleteFileResponses
205
+ ? { componentSetFromNonDeletes: await this.remoteNonDeletesAsComponentSet(), fileResponsesFromDelete }
206
+ : this.remoteNonDeletesAsComponentSet();
212
207
  }
213
208
  /**
214
209
  *
@@ -237,15 +232,12 @@ class SourceTracking extends kit_1.AsyncCreatable {
237
232
  })), true // skip polling because it's a pull
238
233
  ),
239
234
  ]);
240
- return filenames.map((filename) => {
241
- var _a, _b;
242
- return ({
243
- state: 'Deleted',
244
- filename,
245
- type: (_a = sourceComponentByFileName.get(filename)) === null || _a === void 0 ? void 0 : _a.type.name,
246
- fullName: (_b = sourceComponentByFileName.get(filename)) === null || _b === void 0 ? void 0 : _b.fullName,
247
- });
248
- });
235
+ return filenames.map((filename) => ({
236
+ state: 'Deleted',
237
+ filename,
238
+ type: sourceComponentByFileName.get(filename)?.type.name,
239
+ fullName: sourceComponentByFileName.get(filename)?.fullName,
240
+ }));
249
241
  }
250
242
  /**
251
243
  * Update tracking for the options passed.
@@ -253,12 +245,11 @@ class SourceTracking extends kit_1.AsyncCreatable {
253
245
  * @param options the files to update
254
246
  */
255
247
  async updateLocalTracking(options) {
256
- var _a, _b;
257
248
  await this.ensureLocalTracking();
258
249
  // relative paths make smaller trees AND isogit wants them relative
259
250
  const relativeOptions = {
260
- files: ((_a = options.files) !== null && _a !== void 0 ? _a : []).map((file) => (0, functions_1.ensureRelative)(file, this.projectPath)),
261
- deletedFiles: ((_b = options.deletedFiles) !== null && _b !== void 0 ? _b : []).map((file) => (0, functions_1.ensureRelative)(file, this.projectPath)),
251
+ files: (options.files ?? []).map((file) => (0, functions_1.ensureRelative)(file, this.projectPath)),
252
+ deletedFiles: (options.deletedFiles ?? []).map((file) => (0, functions_1.ensureRelative)(file, this.projectPath)),
262
253
  };
263
254
  // plot twist: if you delete a member of a bundle (ex: lwc/foo/foo.css) and push, it'll not be in the fileResponses (deployedFiles) or deletedFiles
264
255
  // what got deleted? Any local changes NOT in the fileResponses but part of a successfully deployed bundle
@@ -378,7 +369,6 @@ class SourceTracking extends kit_1.AsyncCreatable {
378
369
  * Compares local and remote changes to detect conflicts
379
370
  */
380
371
  async getConflicts() {
381
- var _a;
382
372
  // we're going to need have both initialized
383
373
  await Promise.all([this.ensureRemoteTracking(), this.ensureLocalTracking()]);
384
374
  // Strategy: check local changes first (since it'll be faster) to avoid callout
@@ -400,7 +390,7 @@ class SourceTracking extends kit_1.AsyncCreatable {
400
390
  if (remoteChanges.length === 0) {
401
391
  return [];
402
392
  }
403
- (_a = this.forceIgnore) !== null && _a !== void 0 ? _a : (this.forceIgnore = source_deploy_retrieve_1.ForceIgnore.findAndCreate(this.project.getDefaultPackage().path));
393
+ this.forceIgnore ?? (this.forceIgnore = source_deploy_retrieve_1.ForceIgnore.findAndCreate(this.project.getDefaultPackage().path));
404
394
  return (0, conflicts_1.getDedupedConflictsFromChanges)({
405
395
  localChanges,
406
396
  remoteChanges,
@@ -538,38 +528,34 @@ class SourceTracking extends kit_1.AsyncCreatable {
538
528
  throw new Error(`unable to get local changes for state ${state}`);
539
529
  }
540
530
  localChangesToOutputRow(input, localType) {
541
- var _a;
542
531
  this.logger.debug('converting ChangeResult to a row', input);
543
- (_a = this.forceIgnore) !== null && _a !== void 0 ? _a : (this.forceIgnore = source_deploy_retrieve_1.ForceIgnore.findAndCreate(this.project.getDefaultPackage().path));
532
+ this.forceIgnore ?? (this.forceIgnore = source_deploy_retrieve_1.ForceIgnore.findAndCreate(this.project.getDefaultPackage().path));
544
533
  if (input.filenames) {
545
- return input.filenames.map((filename) => {
546
- var _a, _b;
547
- return ({
548
- type: (_a = input.type) !== null && _a !== void 0 ? _a : '',
549
- state: localType,
550
- fullName: (_b = input.name) !== null && _b !== void 0 ? _b : '',
551
- filePath: filename,
552
- origin: 'local',
553
- ignored: this.forceIgnore.denies(filename),
554
- });
555
- });
534
+ return input.filenames.map((filename) => ({
535
+ type: input.type ?? '',
536
+ state: localType,
537
+ fullName: input.name ?? '',
538
+ filePath: filename,
539
+ origin: 'local',
540
+ ignored: this.forceIgnore.denies(filename),
541
+ }));
556
542
  }
557
543
  throw new Error('no filenames found for local ChangeResult');
558
544
  }
559
- // this will eventually have async call to figure out the target file locations for remote changes
545
+ // reserve the right to do something more sophisticated in the future
546
+ // via async for figuring out hypothetical filenames (ex: getting default packageDir)
560
547
  // eslint-disable-next-line @typescript-eslint/require-await
561
548
  async remoteChangesToOutputRows(input) {
562
- var _a, _b, _c, _d;
563
549
  this.logger.debug('converting ChangeResult to a row', input);
564
- (_a = this.forceIgnore) !== null && _a !== void 0 ? _a : (this.forceIgnore = source_deploy_retrieve_1.ForceIgnore.findAndCreate(this.project.getDefaultPackage().path));
550
+ this.forceIgnore ?? (this.forceIgnore = source_deploy_retrieve_1.ForceIgnore.findAndCreate(this.project.getDefaultPackage().path));
565
551
  const baseObject = {
566
- type: (_b = input.type) !== null && _b !== void 0 ? _b : '',
552
+ type: input.type ?? '',
567
553
  origin: input.origin,
568
554
  state: stateFromChangeResult(input),
569
- fullName: (_c = input.name) !== null && _c !== void 0 ? _c : '',
555
+ fullName: input.name ?? '',
570
556
  };
571
557
  // it's easy to check ignores if the filePaths exist locally
572
- if ((_d = input.filenames) === null || _d === void 0 ? void 0 : _d.length) {
558
+ if (input.filenames?.length) {
573
559
  return input.filenames.map((filename) => ({
574
560
  ...baseObject,
575
561
  filePath: filename,
@@ -577,7 +563,18 @@ class SourceTracking extends kit_1.AsyncCreatable {
577
563
  }));
578
564
  }
579
565
  // when the file doesn't exist locally, there are no filePaths
580
- // So we can't say whether it's ignored or not
566
+ // SDR can generate the hypothetical place it *would* go and check that
567
+ if (input.name && input.type) {
568
+ return [
569
+ {
570
+ ...baseObject,
571
+ ignored: (0, filePathGenerator_1.filePathsFromMetadataComponent)({
572
+ fullName: input.name,
573
+ type: new source_deploy_retrieve_1.RegistryAccess().getTypeByName(input.type),
574
+ }).some((hypotheticalFilePath) => this.forceIgnore.denies(hypotheticalFilePath)),
575
+ },
576
+ ];
577
+ }
581
578
  return [baseObject];
582
579
  }
583
580
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@salesforce/source-tracking",
3
3
  "description": "API for tracking local and remote Salesforce metadata changes",
4
- "version": "2.2.1",
4
+ "version": "2.2.2",
5
5
  "author": "Salesforce",
6
6
  "license": "BSD-3-Clause",
7
7
  "main": "lib/index.js",
@@ -43,17 +43,17 @@
43
43
  "/oclif.manifest.json"
44
44
  ],
45
45
  "dependencies": {
46
- "@salesforce/core": "^3.23.1",
47
- "@salesforce/kit": "^1.5.42",
48
- "@salesforce/source-deploy-retrieve": "^6.1.0",
46
+ "@salesforce/core": "^3.26.1",
47
+ "@salesforce/kit": "^1.5.45",
48
+ "@salesforce/source-deploy-retrieve": "^6.2.7",
49
49
  "graceful-fs": "^4.2.9",
50
50
  "isomorphic-git": "1.17.0",
51
51
  "ts-retry-promise": "^0.6.0"
52
52
  },
53
53
  "devDependencies": {
54
- "@salesforce/cli-plugins-testkit": "^2.3.0",
55
- "@salesforce/dev-config": "^3.0.0",
56
- "@salesforce/dev-scripts": "^2.0.0",
54
+ "@salesforce/cli-plugins-testkit": "^2.3.10",
55
+ "@salesforce/dev-config": "^3.1.0",
56
+ "@salesforce/dev-scripts": "^2.0.4",
57
57
  "@salesforce/prettier-config": "^0.0.2",
58
58
  "@salesforce/ts-sinon": "^1.3.21",
59
59
  "@types/shelljs": "^0.8.9",
@@ -68,7 +68,7 @@
68
68
  "eslint-config-salesforce-typescript": "^1.0.0",
69
69
  "eslint-plugin-header": "^3.1.1",
70
70
  "eslint-plugin-import": "2.25.4",
71
- "eslint-plugin-jsdoc": "^37.0.1",
71
+ "eslint-plugin-jsdoc": "^39.3.6",
72
72
  "eslint-plugin-prettier": "^3.4.0",
73
73
  "husky": "^7.0.4",
74
74
  "mocha": "^9.1.3",
@@ -78,7 +78,7 @@
78
78
  "shelljs": "^0.8.4",
79
79
  "shx": "^0.3.3",
80
80
  "sinon": "^10.0.0",
81
- "ts-node": "^10.1.0",
81
+ "ts-node": "^10.9.1",
82
82
  "ts-prune": "^0.10.0",
83
83
  "typescript": "^4.7.4"
84
84
  },