@salesforce/source-tracking 2.1.0 → 2.2.0

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,36 @@
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.0](https://github.com/forcedotcom/source-tracking/compare/v2.1.2...v2.2.0) (2022-06-29)
6
+
7
+ ### Features
8
+
9
+ - event subscription and convenience method for push ([0c2135b](https://github.com/forcedotcom/source-tracking/commit/0c2135ba3076d3d7a3efd1e4d3c41a468e349728))
10
+ - local repo cache breaking for get status, and a generic method ([6645b72](https://github.com/forcedotcom/source-tracking/commit/6645b72c4695a15caca8aa6d3dc158a600fd15de))
11
+ - never track utam ([6e71f03](https://github.com/forcedotcom/source-tracking/commit/6e71f031c27c4e690d8538253b751da13da0b6e3))
12
+ - option to use SDR events ([d86f698](https://github.com/forcedotcom/source-tracking/commit/d86f69896185b68af7e489f6026589957e06f29d))
13
+ - top-level cache config of local cache behavior ([236ac28](https://github.com/forcedotcom/source-tracking/commit/236ac28314b45c42eff83b9ab8003d0c39efbbb0))
14
+ - track based on sdr events ([1238a68](https://github.com/forcedotcom/source-tracking/commit/1238a686f1d2c6091154ac6370c3d3d019c3a7a7))
15
+
16
+ ### Bug Fixes
17
+
18
+ - async lifecycle subscribe ([75031f3](https://github.com/forcedotcom/source-tracking/commit/75031f3bbe753001a42f7abcfec1415bfb62547e))
19
+ - custom field was not polling correctly (logic error on del\_\_c) ([1ff2341](https://github.com/forcedotcom/source-tracking/commit/1ff23419d737cb2a22bcf070f5b2790b9ef0536d))
20
+ - logic on local ignored ([9667a6e](https://github.com/forcedotcom/source-tracking/commit/9667a6e8b442a6df0a42fd42dde4dfc289928f90))
21
+ - use fixed jsforce autoFetch, restore ut ([0b32d21](https://github.com/forcedotcom/source-tracking/commit/0b32d217013a346ef8826d3820566b7d70dba3c1))
22
+
23
+ ### [2.1.2](https://github.com/forcedotcom/source-tracking/compare/v2.1.1...v2.1.2) (2022-06-23)
24
+
25
+ ### Bug Fixes
26
+
27
+ - bump core for autofetch ([3567c69](https://github.com/forcedotcom/source-tracking/commit/3567c69dd49444ef757b9699bb676a0a1a25561c))
28
+
29
+ ### [2.1.1](https://github.com/forcedotcom/source-tracking/compare/v2.1.0...v2.1.1) (2022-06-22)
30
+
31
+ ### Bug Fixes
32
+
33
+ - core for jsforce autofetch ([406c519](https://github.com/forcedotcom/source-tracking/commit/406c519827571fc8f9be2e8008b1cdd8b7827634))
34
+
5
35
  ## [2.1.0](https://github.com/forcedotcom/source-tracking/compare/v2.0.0...v2.1.0) (2022-06-22)
6
36
 
7
37
  ### Features
package/README.md CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  JavaScript library for tracking local and remote Salesforce metadata changes.
4
4
 
5
- **_ UNDER DEVELOPMENT _**
6
-
7
5
  You should use the class named SourceTracking.
8
6
 
9
7
  Start like this:
@@ -14,7 +12,6 @@ import { SourceTracking } from '@salesforce/source-tracking';
14
12
  const tracking = await SourceTracking.create({
15
13
  org: this.org, // Org from sfdx-core
16
14
  project: this.project, // Project from sfdx-core
17
- apiVersion: this.flags.apiversion as string, // can be undefined, will figure it out if you don't allow users to override
18
15
  });
19
16
  ```
20
17
 
@@ -87,26 +84,3 @@ await tracking.updateRemoteTracking(
87
84
  false
88
85
  );
89
86
  ```
90
-
91
- ## TODO
92
-
93
- NUT for tracking file compatibility check logic
94
- pollSourceMembers should better handle aggregated types. ex:
95
-
96
- ```txt
97
- DEBUG Could not find 2 SourceMembers (using ebikes): AuraDefinition__pageTemplate_2_7_3/pageTemplate_2_7_3.cmp-meta.xml,[object Object],CustomObject__Account,[object Object]
98
- ```
99
-
100
- ### Enhancements
101
-
102
- - for updating ST after deploy/retrieve, we need a quick way for those commands to ask, "is this an ST org?" OR a graceful "ifSupported" wrapper for those methods.
103
- - ensureRemoteTracking could have 2 options in an object
104
- 1. `ensureQueryHasReturned` which will make sure the query has run at least once
105
- 2. `forceQuery` will re-query even if the query already ran (cache-buster typically)
106
-
107
- ### Cleanup
108
-
109
- - review commented code
110
- - review public methods for whether they should be public
111
- - organize any shared types
112
- - export top-level stuff
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export * from './sourceTracking';
2
2
  export * from './compatibility';
3
- export { RemoteSyncInput, ChangeOptionType, ChangeOptions, LocalUpdateOptions, ChangeResult, ConflictError, StatusOutputRow, } from './shared/types';
3
+ export { RemoteSyncInput, ChangeOptionType, ChangeOptions, LocalUpdateOptions, ChangeResult, StatusOutputRow, ConflictResponse, SourceConflictError, } from './shared/types';
4
4
  export { getKeyFromObject } from './shared/functions';
package/lib/index.js CHANGED
@@ -20,9 +20,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
20
20
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
21
21
  };
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.getKeyFromObject = void 0;
23
+ exports.getKeyFromObject = exports.SourceConflictError = void 0;
24
24
  __exportStar(require("./sourceTracking"), exports);
25
25
  __exportStar(require("./compatibility"), exports);
26
+ var types_1 = require("./shared/types");
27
+ Object.defineProperty(exports, "SourceConflictError", { enumerable: true, get: function () { return types_1.SourceConflictError; } });
26
28
  var functions_1 = require("./shared/functions");
27
29
  Object.defineProperty(exports, "getKeyFromObject", { enumerable: true, get: function () { return functions_1.getKeyFromObject; } });
28
30
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,16 @@
1
+ import { ComponentSet, ForceIgnore } from '@salesforce/source-deploy-retrieve';
2
+ import { ConflictResponse, ChangeResult } from './types';
3
+ export declare const throwIfConflicts: (conflicts: ConflictResponse[]) => void;
4
+ /**
5
+ *
6
+ * @param cs ComponentSet to compare
7
+ * @param conflicts ChangeResult[] representing conflicts from SourceTracking.getConflicts
8
+ * @returns ConflictResponse[] de-duped and formatted for json or table display
9
+ */
10
+ export declare const findConflictsInComponentSet: (cs: ComponentSet, conflicts: ChangeResult[]) => ConflictResponse[];
11
+ export declare const getDedupedConflictsFromChanges: ({ localChanges, remoteChanges, projectPath, forceIgnore, }: {
12
+ localChanges: ChangeResult[];
13
+ remoteChanges: ChangeResult[];
14
+ projectPath: string;
15
+ forceIgnore: ForceIgnore;
16
+ }) => ChangeResult[];
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDedupedConflictsFromChanges = exports.findConflictsInComponentSet = exports.throwIfConflicts = void 0;
4
+ /*
5
+ * Copyright (c) 2020, salesforce.com, inc.
6
+ * All rights reserved.
7
+ * Licensed under the BSD 3-Clause license.
8
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
9
+ */
10
+ const path_1 = require("path");
11
+ const types_1 = require("./types");
12
+ const functions_1 = require("./functions");
13
+ const populateTypesAndNames_1 = require("./populateTypesAndNames");
14
+ const throwIfConflicts = (conflicts) => {
15
+ if (conflicts.length > 0) {
16
+ const conflictError = new types_1.SourceConflictError(`${conflicts.length} conflicts detected`, 'SourceConflictError');
17
+ conflictError.setData(conflicts);
18
+ throw conflictError;
19
+ }
20
+ };
21
+ exports.throwIfConflicts = throwIfConflicts;
22
+ /**
23
+ *
24
+ * @param cs ComponentSet to compare
25
+ * @param conflicts ChangeResult[] representing conflicts from SourceTracking.getConflicts
26
+ * @returns ConflictResponse[] de-duped and formatted for json or table display
27
+ */
28
+ const findConflictsInComponentSet = (cs, conflicts) => {
29
+ // map do dedupe by name-type-filename
30
+ const conflictMap = new Map();
31
+ conflicts
32
+ .filter((cr) => cr.name && cr.type && cs.has({ fullName: cr.name, type: cr.type }))
33
+ .forEach((cr) => {
34
+ var _a;
35
+ (_a = cr.filenames) === null || _a === void 0 ? void 0 : _a.forEach((f) => {
36
+ conflictMap.set(`${cr.name}#${cr.type}#${f}`, {
37
+ state: 'Conflict',
38
+ // the following 2 type assertions are valid because of previous filter statement
39
+ // they can be removed once TS is smarter about filtering
40
+ fullName: cr.name,
41
+ type: cr.type,
42
+ filePath: (0, path_1.resolve)(f),
43
+ });
44
+ });
45
+ });
46
+ const reformattedConflicts = Array.from(conflictMap.values());
47
+ return reformattedConflicts;
48
+ };
49
+ exports.findConflictsInComponentSet = findConflictsInComponentSet;
50
+ const getDedupedConflictsFromChanges = ({ localChanges = [], remoteChanges = [], projectPath, forceIgnore, }) => {
51
+ // index the remoteChanges by filename
52
+ const fileNameIndex = new Map();
53
+ const metadataKeyIndex = new Map();
54
+ remoteChanges.map((change) => {
55
+ var _a;
56
+ if (change.name && change.type) {
57
+ metadataKeyIndex.set((0, functions_1.getMetadataKey)(change.name, change.type), change);
58
+ }
59
+ (_a = change.filenames) === null || _a === void 0 ? void 0 : _a.map((filename) => {
60
+ fileNameIndex.set(filename, change);
61
+ });
62
+ });
63
+ const conflicts = new Set();
64
+ (0, populateTypesAndNames_1.populateTypesAndNames)({ elements: localChanges, excludeUnresolvable: true, projectPath, forceIgnore }).map((change) => {
65
+ var _a;
66
+ const metadataKey = (0, functions_1.getMetadataKey)(change.name, change.type);
67
+ // option 1: name and type match
68
+ if (metadataKeyIndex.has(metadataKey)) {
69
+ conflicts.add({ ...metadataKeyIndex.get(metadataKey) });
70
+ }
71
+ else {
72
+ // option 2: some of the filenames match
73
+ (_a = change.filenames) === null || _a === void 0 ? void 0 : _a.map((filename) => {
74
+ if (fileNameIndex.has(filename)) {
75
+ conflicts.add({ ...fileNameIndex.get(filename) });
76
+ }
77
+ });
78
+ }
79
+ });
80
+ // deeply de-dupe
81
+ return Array.from(conflicts);
82
+ };
83
+ exports.getDedupedConflictsFromChanges = getDedupedConflictsFromChanges;
84
+ //# sourceMappingURL=conflicts.js.map
@@ -0,0 +1,2 @@
1
+ import { RemoteSyncInput } from './types';
2
+ export declare const calculateExpectedSourceMembers: (expectedMembers: RemoteSyncInput[]) => Map<string, RemoteSyncInput>;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2020, salesforce.com, inc.
4
+ * All rights reserved.
5
+ * Licensed under the BSD 3-Clause license.
6
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.calculateExpectedSourceMembers = void 0;
10
+ const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
11
+ const metadataKeys_1 = require("./metadataKeys");
12
+ const typesToNoPollFor = [
13
+ 'CustomObject',
14
+ 'EmailFolder',
15
+ 'EmailTemplateFolder',
16
+ 'StandardValueSet',
17
+ 'Portal',
18
+ 'StandardValueSetTranslation',
19
+ 'SharingRules',
20
+ 'SharingCriteriaRule',
21
+ 'GlobalValueSetTranslation',
22
+ 'AssignmentRules',
23
+ 'InstalledPackage',
24
+ ];
25
+ const typesNotToPollForIfNamespace = ['CustomLabels', 'CustomMetadata', 'DuplicateRule', 'WebLink'];
26
+ const isEncodedTypeWithPercentSign = (type, filePath) => ['Layout', 'Profile', 'HomePageComponent', 'HomePageLayout', 'MilestoneType'].includes(type) &&
27
+ Boolean(filePath === null || filePath === void 0 ? void 0 : filePath.includes('%'));
28
+ // aura xml aren't tracked as SourceMembers
29
+ const isSpecialAuraXml = (filePath) => Boolean(filePath &&
30
+ (filePath.endsWith('.cmp-meta.xml') ||
31
+ filePath.endsWith('.tokens-meta.xml') ||
32
+ filePath.endsWith('.evt-meta.xml') ||
33
+ filePath.endsWith('.app-meta.xml') ||
34
+ filePath.endsWith('.intf-meta.xml')));
35
+ const calculateExpectedSourceMembers = (expectedMembers) => {
36
+ const outstandingSourceMembers = new Map();
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
+ })
61
+ .map((member) => {
62
+ (0, metadataKeys_1.getMetadataKeyFromFileResponse)(member)
63
+ // remove some individual members known to not work with tracking even when their type does
64
+ .filter((key) =>
65
+ // CustomObject could have been re-added by the key generator from one of its fields
66
+ !key.startsWith('CustomObject') &&
67
+ key !== 'Profile__Standard' &&
68
+ key !== 'CustomTab__standard-home' &&
69
+ key !== 'AssignmentRules__Case' &&
70
+ key !== 'ListView__CollaborationGroup.All_ChatterGroups')
71
+ .map((key) => outstandingSourceMembers.set(key, member));
72
+ });
73
+ return outstandingSourceMembers;
74
+ };
75
+ exports.calculateExpectedSourceMembers = calculateExpectedSourceMembers;
76
+ //# sourceMappingURL=expectedSourceMembers.js.map
@@ -3,9 +3,11 @@ import { RemoteChangeElement, ChangeResult } from './types';
3
3
  export declare const getMetadataKey: (metadataType: string, metadataName: string) => string;
4
4
  export declare const getKeyFromObject: (element: RemoteChangeElement | ChangeResult) => string;
5
5
  export declare const isBundle: (cmp: SourceComponent) => boolean;
6
+ export declare const isLwcLocalOnlyTest: (filePath: string) => boolean;
6
7
  /**
7
8
  * Verify that a filepath starts exactly with a complete parent path
8
9
  * ex: '/foo/bar-extra/baz'.startsWith('foo/bar') would be true, but this function understands that they are not in the same folder
9
10
  */
10
11
  export declare const pathIsInFolder: (filePath: string, folder: string) => boolean;
11
12
  export declare const chunkArray: <T>(arr: T[], size: number) => T[][];
13
+ export declare const ensureRelative: (filePath: string, projectPath: string) => string;
@@ -6,7 +6,7 @@
6
6
  * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.chunkArray = exports.pathIsInFolder = exports.isBundle = exports.getKeyFromObject = exports.getMetadataKey = void 0;
9
+ exports.ensureRelative = exports.chunkArray = exports.pathIsInFolder = exports.isLwcLocalOnlyTest = exports.isBundle = exports.getKeyFromObject = exports.getMetadataKey = void 0;
10
10
  const path_1 = require("path");
11
11
  const ts_types_1 = require("@salesforce/ts-types");
12
12
  const getMetadataKey = (metadataType, metadataName) => {
@@ -22,6 +22,8 @@ const getKeyFromObject = (element) => {
22
22
  exports.getKeyFromObject = getKeyFromObject;
23
23
  const isBundle = (cmp) => { var _a; return ((_a = cmp.type.strategies) === null || _a === void 0 ? void 0 : _a.adapter) === 'bundle'; };
24
24
  exports.isBundle = isBundle;
25
+ const isLwcLocalOnlyTest = (filePath) => filePath.includes('__utam__') || filePath.includes('__tests__');
26
+ exports.isLwcLocalOnlyTest = isLwcLocalOnlyTest;
25
27
  /**
26
28
  * Verify that a filepath starts exactly with a complete parent path
27
29
  * ex: '/foo/bar-extra/baz'.startsWith('foo/bar') would be true, but this function understands that they are not in the same folder
@@ -40,4 +42,6 @@ const nonEmptyStringFilter = (value) => {
40
42
  // adapted for TS from https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/chunk.md
41
43
  const chunkArray = (arr, size) => Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => arr.slice(i * size, i * size + size));
42
44
  exports.chunkArray = chunkArray;
45
+ const ensureRelative = (filePath, projectPath) => (0, path_1.isAbsolute)(filePath) ? (0, path_1.relative)(projectPath, filePath) : filePath;
46
+ exports.ensureRelative = ensureRelative;
43
47
  //# sourceMappingURL=functions.js.map
@@ -0,0 +1,15 @@
1
+ import { NamedPackageDir } from '@salesforce/core';
2
+ import { ComponentSet } from '@salesforce/source-deploy-retrieve';
3
+ interface GroupedFileInput {
4
+ packageDirs: NamedPackageDir[];
5
+ nonDeletes: string[];
6
+ deletes: string[];
7
+ }
8
+ interface GroupedFile {
9
+ path: string;
10
+ nonDeletes: string[];
11
+ deletes: string[];
12
+ }
13
+ export declare const getGroupedFiles: (input: GroupedFileInput, byPackageDir?: boolean) => GroupedFile[];
14
+ export declare const getComponentSets: (groupings: GroupedFile[], sourceApiVersion?: string) => ComponentSet[];
15
+ export {};
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getComponentSets = exports.getGroupedFiles = void 0;
4
+ /*
5
+ * Copyright (c) 2020, salesforce.com, inc.
6
+ * All rights reserved.
7
+ * Licensed under the BSD 3-Clause license.
8
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
9
+ */
10
+ const fs = require("fs");
11
+ const path_1 = require("path");
12
+ const core_1 = require("@salesforce/core");
13
+ const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
14
+ const guards_1 = require("./guards");
15
+ const functions_1 = require("./functions");
16
+ const getGroupedFiles = (input, byPackageDir = false) => {
17
+ return (byPackageDir ? getSequential(input) : getNonSequential(input)).filter((group) => group.deletes.length || group.nonDeletes.length);
18
+ };
19
+ exports.getGroupedFiles = getGroupedFiles;
20
+ const getSequential = ({ packageDirs, nonDeletes, deletes }) => packageDirs.map((pkgDir) => ({
21
+ path: pkgDir.name,
22
+ nonDeletes: nonDeletes.filter((f) => (0, functions_1.pathIsInFolder)(f, pkgDir.name)),
23
+ deletes: deletes.filter((f) => (0, functions_1.pathIsInFolder)(f, pkgDir.name)),
24
+ }));
25
+ const getNonSequential = ({ packageDirs, nonDeletes: nonDeletes, deletes: deletes, }) => [
26
+ {
27
+ nonDeletes,
28
+ deletes,
29
+ path: packageDirs.map((dir) => dir.name).join(';'),
30
+ },
31
+ ];
32
+ const getComponentSets = (groupings, sourceApiVersion) => {
33
+ const logger = core_1.Logger.childFromRoot('localComponentSetArray');
34
+ // optimistic resolution...some files may not be possible to resolve
35
+ const resolverForNonDeletes = new source_deploy_retrieve_1.MetadataResolver();
36
+ return groupings
37
+ .map((grouping) => {
38
+ logger.debug(`building componentSet for ${grouping.path} (deletes: ${grouping.deletes.length} nonDeletes: ${grouping.nonDeletes.length})`);
39
+ const componentSet = new source_deploy_retrieve_1.ComponentSet();
40
+ if (sourceApiVersion) {
41
+ componentSet.sourceApiVersion = sourceApiVersion;
42
+ }
43
+ // we need virtual components for the deletes.
44
+ // TODO: could we use the same for the non-deletes?
45
+ const resolverForDeletes = new source_deploy_retrieve_1.MetadataResolver(undefined, source_deploy_retrieve_1.VirtualTreeContainer.fromFilePaths(grouping.deletes));
46
+ grouping.deletes
47
+ .flatMap((filename) => resolverForDeletes.getComponentsFromPath(filename))
48
+ .filter(guards_1.sourceComponentGuard)
49
+ .map((component) => {
50
+ // if the component is a file in a bundle type AND there are files from the bundle that are not deleted, set the bundle for deploy, not for delete
51
+ if ((0, functions_1.isBundle)(component) && component.content && fs.existsSync(component.content)) {
52
+ // all bundle types have a directory name
53
+ try {
54
+ resolverForNonDeletes
55
+ .getComponentsFromPath((0, path_1.resolve)(component.content))
56
+ .filter(guards_1.sourceComponentGuard)
57
+ .map((nonDeletedComponent) => componentSet.add(nonDeletedComponent));
58
+ }
59
+ catch (e) {
60
+ logger.warn(`unable to find component at ${component.content}. That's ok if it was supposed to be deleted`);
61
+ }
62
+ }
63
+ else {
64
+ componentSet.add(component, source_deploy_retrieve_1.DestructiveChangesType.POST);
65
+ }
66
+ });
67
+ grouping.nonDeletes
68
+ .flatMap((filename) => {
69
+ try {
70
+ return resolverForNonDeletes.getComponentsFromPath((0, path_1.resolve)(filename));
71
+ }
72
+ catch (e) {
73
+ logger.warn(`unable to resolve ${filename}`);
74
+ return undefined;
75
+ }
76
+ })
77
+ .filter(guards_1.sourceComponentGuard)
78
+ .map((component) => componentSet.add(component));
79
+ return componentSet;
80
+ })
81
+ .filter((componentSet) => componentSet.size > 0);
82
+ };
83
+ exports.getComponentSets = getComponentSets;
84
+ //# sourceMappingURL=localComponentSetArray.js.map
@@ -97,7 +97,7 @@ class ShadowRepo {
97
97
  // no hidden files
98
98
  !f.includes(`${path.sep}.`) &&
99
99
  // no lwc tests
100
- !f.includes('__tests__') &&
100
+ !(0, functions_1.isLwcLocalOnlyTest)(f) &&
101
101
  // no gitignore files
102
102
  !f.endsWith('.gitignore') &&
103
103
  // isogit uses `startsWith` for filepaths so it's possible to get a false positive
@@ -1,3 +1,4 @@
1
1
  import { RemoteSyncInput } from './types';
2
2
  export declare const getMetadataKeyFromFileResponse: (fileResponse: RemoteSyncInput) => string[];
3
3
  export declare const mappingsForSourceMemberTypesToMetadataType: Map<string, string>;
4
+ export declare const registrySupportsType: (type: string) => boolean;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mappingsForSourceMemberTypesToMetadataType = exports.getMetadataKeyFromFileResponse = void 0;
3
+ exports.registrySupportsType = exports.mappingsForSourceMemberTypesToMetadataType = exports.getMetadataKeyFromFileResponse = void 0;
4
4
  /*
5
5
  * Copyright (c) 2020, salesforce.com, inc.
6
6
  * All rights reserved.
@@ -9,6 +9,7 @@ exports.mappingsForSourceMemberTypesToMetadataType = exports.getMetadataKeyFromF
9
9
  */
10
10
  const path_1 = require("path");
11
11
  const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
12
+ const core_1 = require("@salesforce/core");
12
13
  const functions_1 = require("./functions");
13
14
  // See UT for examples of the complexity this must handle
14
15
  // keys always use forward slashes, even on Windows
@@ -69,4 +70,19 @@ exports.mappingsForSourceMemberTypesToMetadataType = new Map([
69
70
  ['AuraDefinition', 'AuraDefinitionBundle'],
70
71
  ['LightningComponentResource', 'LightningComponentBundle'],
71
72
  ]);
73
+ const registrySupportsType = (type) => {
74
+ try {
75
+ if (exports.mappingsForSourceMemberTypesToMetadataType.has(type)) {
76
+ return true;
77
+ }
78
+ // this must use getTypeByName because findType doesn't support addressable child types (ex: customField!)
79
+ registry.getTypeByName(type);
80
+ return true;
81
+ }
82
+ catch (e) {
83
+ void core_1.Lifecycle.getInstance().emitWarning(`Unable to find type ${type} in registry`);
84
+ return false;
85
+ }
86
+ };
87
+ exports.registrySupportsType = registrySupportsType;
72
88
  //# sourceMappingURL=metadataKeys.js.map
@@ -0,0 +1,9 @@
1
+ import { ChangeResult } from './types';
2
+ /**
3
+ * Will build a component set, crawling your local directory, to get paths for remote changes
4
+ *
5
+ * @param elements ChangeResults that may or may not have filepaths in their filenames parameters
6
+ * @param packageDirPaths Array of paths from PackageDirectories
7
+ * @returns
8
+ */
9
+ export declare const populateFilePaths: (elements: ChangeResult[], packageDirPaths: string[]) => ChangeResult[];
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.populateFilePaths = void 0;
4
+ /*
5
+ * Copyright (c) 2020, salesforce.com, inc.
6
+ * All rights reserved.
7
+ * Licensed under the BSD 3-Clause license.
8
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
9
+ */
10
+ const os_1 = require("os");
11
+ const core_1 = require("@salesforce/core");
12
+ const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
13
+ const guards_1 = require("./guards");
14
+ const functions_1 = require("./functions");
15
+ const logger = core_1.Logger.childFromRoot('SourceTracking.PopulateFilePaths');
16
+ /**
17
+ * Will build a component set, crawling your local directory, to get paths for remote changes
18
+ *
19
+ * @param elements ChangeResults that may or may not have filepaths in their filenames parameters
20
+ * @param packageDirPaths Array of paths from PackageDirectories
21
+ * @returns
22
+ */
23
+ const populateFilePaths = (elements, packageDirPaths) => {
24
+ if (elements.length === 0) {
25
+ return [];
26
+ }
27
+ logger.debug('populateFilePaths for change elements', elements);
28
+ // component set generated from an array of MetadataMember from all the remote changes
29
+ // but exclude the ones that aren't in the registry
30
+ const remoteChangesAsMetadataMember = elements
31
+ .map((element) => {
32
+ if (typeof element.type === 'string' && typeof element.name === 'string') {
33
+ return {
34
+ type: element.type,
35
+ fullName: element.name,
36
+ };
37
+ }
38
+ })
39
+ .filter(guards_1.metadataMemberGuard);
40
+ const remoteChangesAsComponentSet = new source_deploy_retrieve_1.ComponentSet(remoteChangesAsMetadataMember);
41
+ logger.debug(` the generated component set has ${remoteChangesAsComponentSet.size.toString()} items`);
42
+ if (remoteChangesAsComponentSet.size < elements.length) {
43
+ // there *could* be something missing
44
+ // some types (ex: LWC) show up as multiple files in the remote changes, but only one in the component set
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 }));
47
+ // Throw if anything was actually missing
48
+ if (missingComponents.length > 0) {
49
+ throw new Error(`unable to generate complete component set for ${elements
50
+ .map((element) => `${element.name} (${element.type})`)
51
+ .join(os_1.EOL)}`);
52
+ }
53
+ }
54
+ const matchingLocalSourceComponentsSet = source_deploy_retrieve_1.ComponentSet.fromSource({
55
+ fsPaths: packageDirPaths,
56
+ include: remoteChangesAsComponentSet,
57
+ });
58
+ logger.debug(` local source-backed component set has ${matchingLocalSourceComponentsSet.size.toString()} items from remote`);
59
+ // make it simpler to find things later
60
+ const elementMap = new Map(elements.map((e) => [(0, functions_1.getKeyFromObject)(e), e]));
61
+ // iterates the local components and sets their filenames
62
+ for (const matchingComponent of matchingLocalSourceComponentsSet.getSourceComponents().toArray()) {
63
+ if (matchingComponent.fullName && matchingComponent.type.name) {
64
+ logger.debug(`${matchingComponent.fullName}|${matchingComponent.type.name} matches ${matchingComponent.xml} and maybe ${matchingComponent.walkContent().toString()}`);
65
+ const key = (0, functions_1.getMetadataKey)(matchingComponent.type.name, matchingComponent.fullName);
66
+ elementMap.set(key, {
67
+ ...elementMap.get(key),
68
+ modified: true,
69
+ origin: 'remote',
70
+ filenames: [matchingComponent.xml, ...matchingComponent.walkContent()].filter((filename) => filename),
71
+ });
72
+ }
73
+ }
74
+ return Array.from(elementMap.values());
75
+ };
76
+ exports.populateFilePaths = populateFilePaths;
77
+ //# sourceMappingURL=populateFilePaths.js.map
@@ -0,0 +1,18 @@
1
+ import { ForceIgnore } from '@salesforce/source-deploy-retrieve';
2
+ import { ChangeResult } from './types';
3
+ /**
4
+ * uses SDR to translate remote metadata records into local file paths (which only typically have the filename).
5
+ *
6
+ * @input elements: ChangeResult[]
7
+ * @input projectPath
8
+ * @input forceIgnore: ForceIgnore. If provided, result will indicate whether the file is ignored
9
+ * @input excludeUnresolvable: boolean Filter out components where you can't get the name and type (that is, it's probably not a valid source component)
10
+ * @input resolveDeleted: constructs a virtualTree instead of the actual filesystem--useful when the files no longer exist
11
+ */
12
+ export declare const populateTypesAndNames: ({ elements, projectPath, forceIgnore, excludeUnresolvable, resolveDeleted, }: {
13
+ elements: ChangeResult[];
14
+ projectPath: string;
15
+ forceIgnore?: ForceIgnore | undefined;
16
+ excludeUnresolvable?: boolean | undefined;
17
+ resolveDeleted?: boolean | undefined;
18
+ }) => ChangeResult[];