@salesforce/source-tracking 5.1.18 → 5.2.1
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/lib/index.d.ts +1 -1
- package/lib/index.js +3 -16
- package/lib/shared/conflicts.d.ts +3 -2
- package/lib/shared/conflicts.js +18 -31
- package/lib/shared/functions.d.ts +15 -5
- package/lib/shared/functions.js +38 -10
- package/lib/shared/guards.d.ts +9 -1
- package/lib/shared/guards.js +13 -1
- package/lib/shared/localComponentSetArray.d.ts +6 -2
- package/lib/shared/localComponentSetArray.js +6 -6
- package/lib/shared/localShadowRepo.js +13 -10
- package/lib/shared/metadataKeys.js +1 -0
- package/lib/shared/populateFilePaths.d.ts +6 -1
- package/lib/shared/populateFilePaths.js +24 -26
- package/lib/shared/populateTypesAndNames.d.ts +4 -4
- package/lib/shared/populateTypesAndNames.js +21 -30
- package/lib/shared/remoteChangeIgnoring.d.ts +3 -3
- package/lib/shared/remoteChangeIgnoring.js +16 -22
- package/lib/shared/remoteSourceTrackingService.d.ts +2 -2
- package/lib/shared/remoteSourceTrackingService.js +10 -9
- package/lib/shared/types.d.ts +1 -0
- package/lib/sourceTracking.d.ts +3 -4
- package/lib/sourceTracking.js +79 -111
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
|
@@ -21,7 +21,7 @@ const functions_1 = require("./functions");
|
|
|
21
21
|
* @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)
|
|
22
22
|
* @input resolveDeleted: constructs a virtualTree instead of the actual filesystem--useful when the files no longer exist
|
|
23
23
|
*/
|
|
24
|
-
const populateTypesAndNames = ({
|
|
24
|
+
const populateTypesAndNames = ({ projectPath, forceIgnore, excludeUnresolvable = false, resolveDeleted = false, registry, }) => (elements) => {
|
|
25
25
|
if (elements.length === 0) {
|
|
26
26
|
return [];
|
|
27
27
|
}
|
|
@@ -29,7 +29,7 @@ const populateTypesAndNames = ({ elements, projectPath, forceIgnore, excludeUnre
|
|
|
29
29
|
logger.debug(`populateTypesAndNames for ${elements.length} change elements`);
|
|
30
30
|
const filenames = elements.flatMap((element) => element.filenames).filter(ts_types_1.isString);
|
|
31
31
|
// component set generated from the filenames on all local changes
|
|
32
|
-
const resolver = new source_deploy_retrieve_1.MetadataResolver(
|
|
32
|
+
const resolver = new source_deploy_retrieve_1.MetadataResolver(registry, resolveDeleted ? source_deploy_retrieve_1.VirtualTreeContainer.fromFilePaths(filenames) : undefined, !!forceIgnore);
|
|
33
33
|
const sourceComponents = filenames
|
|
34
34
|
.flatMap((filename) => {
|
|
35
35
|
try {
|
|
@@ -42,37 +42,28 @@ const populateTypesAndNames = ({ elements, projectPath, forceIgnore, excludeUnre
|
|
|
42
42
|
})
|
|
43
43
|
.filter(guards_1.sourceComponentGuard);
|
|
44
44
|
logger.debug(` matching SourceComponents have ${sourceComponents.length} items from local`);
|
|
45
|
-
|
|
46
|
-
const elementMap = new Map();
|
|
47
|
-
elements.map((element) => {
|
|
48
|
-
element.filenames?.map((filename) => {
|
|
49
|
-
elementMap.set((0, functions_1.ensureRelative)(filename, projectPath), element);
|
|
50
|
-
});
|
|
51
|
-
});
|
|
45
|
+
const elementMap = new Map(elements.flatMap((e) => (e.filenames ?? []).map((f) => [(0, functions_1.ensureRelative)(projectPath)(f), e])));
|
|
52
46
|
// iterates the local components and sets their filenames
|
|
53
|
-
sourceComponents.map((matchingComponent) => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
elementMap.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
}
|
|
47
|
+
sourceComponents.filter(functions_1.sourceComponentHasFullNameAndType).map((matchingComponent) => {
|
|
48
|
+
const filenamesFromMatchingComponent = (0, functions_1.getAllFiles)(matchingComponent);
|
|
49
|
+
const ignored = filenamesFromMatchingComponent
|
|
50
|
+
.filter(functions_1.excludeLwcLocalOnlyTest)
|
|
51
|
+
.some((0, functions_1.forceIgnoreDenies)(forceIgnore));
|
|
52
|
+
filenamesFromMatchingComponent.map((filename) => {
|
|
53
|
+
if (filename && elementMap.has(filename)) {
|
|
54
|
+
// add the type/name from the componentSet onto the element
|
|
55
|
+
elementMap.set(filename, {
|
|
56
|
+
origin: 'remote',
|
|
57
|
+
...elementMap.get(filename),
|
|
58
|
+
type: matchingComponent.type.name,
|
|
59
|
+
name: matchingComponent.fullName,
|
|
60
|
+
ignored,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
});
|
|
73
64
|
});
|
|
74
65
|
return excludeUnresolvable
|
|
75
|
-
? Array.from(new Set(elementMap.values())).filter(
|
|
66
|
+
? Array.from(new Set(elementMap.values())).filter(guards_1.isChangeResultWithNameAndType)
|
|
76
67
|
: Array.from(new Set(elementMap.values()));
|
|
77
68
|
};
|
|
78
69
|
exports.populateTypesAndNames = populateTypesAndNames;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ForceIgnore,
|
|
1
|
+
import { ForceIgnore, MetadataMember } from '@salesforce/source-deploy-retrieve';
|
|
2
2
|
import { ChangeResult } from './types';
|
|
3
|
-
|
|
3
|
+
import { ChangeResultWithNameAndType } from './types';
|
|
4
4
|
export declare const removeIgnored: (changeResults: ChangeResult[], forceIgnore: ForceIgnore, defaultPkgDir: string) => MetadataMember[];
|
|
5
|
-
export declare const
|
|
5
|
+
export declare const ensureNameAndType: (cr: ChangeResult) => ChangeResultWithNameAndType;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ensureNameAndType = exports.removeIgnored = void 0;
|
|
4
4
|
/*
|
|
5
5
|
* Copyright (c) 2023, salesforce.com, inc.
|
|
6
6
|
* All rights reserved.
|
|
@@ -10,32 +10,26 @@ exports.remoteChangeToMetadataMember = exports.removeIgnored = exports.changeRes
|
|
|
10
10
|
const source_deploy_retrieve_1 = require("@salesforce/source-deploy-retrieve");
|
|
11
11
|
const core_1 = require("@salesforce/core");
|
|
12
12
|
const filePathGenerator_1 = require("@salesforce/source-deploy-retrieve/lib/src/utils/filePathGenerator");
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
throw new core_1.SfError(`Change Result is missing name or type: ${JSON.stringify(cr)}`);
|
|
16
|
-
}
|
|
17
|
-
return {
|
|
18
|
-
fullName: cr.name,
|
|
19
|
-
type: registry.getTypeByName(cr.type),
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
exports.changeResultToMetadataComponent = changeResultToMetadataComponent;
|
|
13
|
+
const guards_1 = require("./guards");
|
|
14
|
+
const functions_1 = require("./functions");
|
|
23
15
|
const removeIgnored = (changeResults, forceIgnore, defaultPkgDir) => {
|
|
24
16
|
const registry = new source_deploy_retrieve_1.RegistryAccess();
|
|
25
17
|
return changeResults
|
|
26
|
-
.map(
|
|
27
|
-
.
|
|
28
|
-
.
|
|
18
|
+
.map(exports.ensureNameAndType)
|
|
19
|
+
.map((0, functions_1.changeResultToMetadataComponent)(registry))
|
|
20
|
+
.filter((mc) => !(0, filePathGenerator_1.filePathsFromMetadataComponent)(mc, defaultPkgDir).some((0, functions_1.forceIgnoreDenies)(forceIgnore)))
|
|
21
|
+
.map(metadataComponentToMetadataMember);
|
|
29
22
|
};
|
|
30
23
|
exports.removeIgnored = removeIgnored;
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
const metadataComponentToMetadataMember = (mc) => ({
|
|
25
|
+
type: mc.type.name,
|
|
26
|
+
fullName: mc.fullName,
|
|
27
|
+
});
|
|
28
|
+
const ensureNameAndType = (cr) => {
|
|
29
|
+
if ((0, guards_1.isChangeResultWithNameAndType)(cr)) {
|
|
30
|
+
return cr;
|
|
34
31
|
}
|
|
35
|
-
|
|
36
|
-
fullName: cr.name,
|
|
37
|
-
type: cr.type,
|
|
38
|
-
};
|
|
32
|
+
throw new core_1.SfError(`Change Result is missing name or type: ${JSON.stringify(cr)}`);
|
|
39
33
|
};
|
|
40
|
-
exports.
|
|
34
|
+
exports.ensureNameAndType = ensureNameAndType;
|
|
41
35
|
//# sourceMappingURL=remoteChangeIgnoring.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Org, Connection } from '@salesforce/core';
|
|
1
|
+
import { Logger, Org, Connection } from '@salesforce/core';
|
|
2
2
|
import { Duration } from '@salesforce/kit';
|
|
3
3
|
import { ChangeResult, RemoteChangeElement, MemberRevision, SourceMember, RemoteSyncInput } from './types';
|
|
4
4
|
/** represents the contents of the config file stored in 'maxRevision.json' */
|
|
@@ -128,6 +128,6 @@ export declare class RemoteSourceTrackingService {
|
|
|
128
128
|
* Useful for correcing bundle types where the files show change results with types but aren't resolvable
|
|
129
129
|
*/
|
|
130
130
|
export declare const remoteChangeElementToChangeResult: (rce: RemoteChangeElement) => ChangeResult;
|
|
131
|
-
export declare const calculateTimeout: (memberCount: number) => Duration;
|
|
131
|
+
export declare const calculateTimeout: (logger: Logger) => (memberCount: number) => Duration;
|
|
132
132
|
/** exported only for spy/mock */
|
|
133
133
|
export declare const querySourceMembersTo: (conn: Connection, toRevision: number) => Promise<SourceMember[]>;
|
|
@@ -123,7 +123,7 @@ class RemoteSourceTrackingService {
|
|
|
123
123
|
if (!revision) {
|
|
124
124
|
this.logger.warn(`found no matching revision for ${metadataKey}`);
|
|
125
125
|
}
|
|
126
|
-
else if (revision
|
|
126
|
+
else if (doesNotMatchServer(revision)) {
|
|
127
127
|
if (!quiet) {
|
|
128
128
|
this.logger.debug(`Syncing ${metadataKey} revision from ${revision.lastRetrievedFromServer} to ${revision.serverRevisionCounter}`);
|
|
129
129
|
}
|
|
@@ -171,8 +171,8 @@ class RemoteSourceTrackingService {
|
|
|
171
171
|
// Look for any changed that haven't been synced. I.e, the lastRetrievedFromServer
|
|
172
172
|
// does not match the serverRevisionCounter.
|
|
173
173
|
const returnElements = Array.from(this.sourceMembers.entries())
|
|
174
|
-
.filter(
|
|
175
|
-
.map(
|
|
174
|
+
.filter(revisionDoesNotMatch)
|
|
175
|
+
.map(revisionToRemoteChangeElement);
|
|
176
176
|
this.logger.debug(returnElements.length
|
|
177
177
|
? `Found ${returnElements.length} elements not synced with org`
|
|
178
178
|
: 'Remote source tracking is up to date');
|
|
@@ -198,7 +198,7 @@ class RemoteSourceTrackingService {
|
|
|
198
198
|
const originalOutstandingSize = outstandingSourceMembers.size;
|
|
199
199
|
// this will be the absolute timeout from the start of the poll. We can also exit early if it doesn't look like more results are coming in
|
|
200
200
|
let highestRevisionSoFar = this.serverMaxRevisionCounter;
|
|
201
|
-
const pollingTimeout = (0, exports.calculateTimeout)(outstandingSourceMembers.size);
|
|
201
|
+
const pollingTimeout = (0, exports.calculateTimeout)(this.logger)(outstandingSourceMembers.size);
|
|
202
202
|
let pollAttempts = 0;
|
|
203
203
|
let consecutiveEmptyResults = 0;
|
|
204
204
|
let someResultsReturned = false;
|
|
@@ -425,7 +425,7 @@ const remoteChangeElementToChangeResult = (rce) => ({
|
|
|
425
425
|
origin: 'remote', // we know they're remote
|
|
426
426
|
});
|
|
427
427
|
exports.remoteChangeElementToChangeResult = remoteChangeElementToChangeResult;
|
|
428
|
-
const
|
|
428
|
+
const revisionToRemoteChangeElement = ([memberKey, memberRevision]) => ({
|
|
429
429
|
type: memberRevision.memberType,
|
|
430
430
|
name: memberKey.replace(`${memberRevision.memberType}__`, ''),
|
|
431
431
|
deleted: memberRevision.isNameObsolete,
|
|
@@ -462,8 +462,7 @@ const readFileContents = async (filePath) => {
|
|
|
462
462
|
return {};
|
|
463
463
|
}
|
|
464
464
|
};
|
|
465
|
-
const calculateTimeout = (memberCount) => {
|
|
466
|
-
const logger = core_1.Logger.childFromRoot('remoteSourceTrackingService:calculateTimeout');
|
|
465
|
+
const calculateTimeout = (logger) => (memberCount) => {
|
|
467
466
|
const overriddenTimeout = kit_1.env.getNumber('SFDX_SOURCE_MEMBER_POLLING_TIMEOUT', 0);
|
|
468
467
|
if (overriddenTimeout > 0) {
|
|
469
468
|
logger.debug(`Overriding SourceMember polling timeout to ${overriddenTimeout}`);
|
|
@@ -485,10 +484,10 @@ const querySourceMembersTo = async (conn, toRevision) => {
|
|
|
485
484
|
exports.querySourceMembersTo = querySourceMembersTo;
|
|
486
485
|
const queryFn = async (conn, query) => {
|
|
487
486
|
try {
|
|
488
|
-
return (await conn.tooling.query(query, { autoFetch: true, maxFetch:
|
|
487
|
+
return (await conn.tooling.query(query, { autoFetch: true, maxFetch: 50_000 })).records;
|
|
489
488
|
}
|
|
490
489
|
catch (error) {
|
|
491
|
-
throw core_1.SfError.wrap(error);
|
|
490
|
+
throw error instanceof Error ? core_1.SfError.wrap(error) : error;
|
|
492
491
|
}
|
|
493
492
|
};
|
|
494
493
|
/** organize by type and format for warning output */
|
|
@@ -502,4 +501,6 @@ const formatSourceMemberWarnings = (outstandingSourceMembers) => {
|
|
|
502
501
|
.map(([type, names]) => ` - ${type}: ${names.join(', ')}`)
|
|
503
502
|
.join(node_os_1.EOL);
|
|
504
503
|
};
|
|
504
|
+
const revisionDoesNotMatch = ([, member]) => doesNotMatchServer(member);
|
|
505
|
+
const doesNotMatchServer = (member) => member.serverRevisionCounter !== member.lastRetrievedFromServer;
|
|
505
506
|
//# sourceMappingURL=remoteSourceTrackingService.js.map
|
package/lib/shared/types.d.ts
CHANGED
package/lib/sourceTracking.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Org, SfProject } from '@salesforce/core';
|
|
2
2
|
import { AsyncCreatable } from '@salesforce/kit';
|
|
3
|
-
import { ComponentSet, SourceComponent, FileResponse, DeployResult, RetrieveResult } from '@salesforce/source-deploy-retrieve';
|
|
3
|
+
import { ComponentSet, SourceComponent, FileResponse, DeployResult, RetrieveResult, RegistryAccess } from '@salesforce/source-deploy-retrieve';
|
|
4
4
|
import { RemoteSyncInput, StatusOutputRow, ChangeOptions, ChangeResult, LocalUpdateOptions } from './shared/types';
|
|
5
5
|
export interface SourceTrackingOptions {
|
|
6
6
|
org: Org;
|
|
@@ -30,9 +30,10 @@ type RemoteChangesResults = {
|
|
|
30
30
|
*
|
|
31
31
|
*/
|
|
32
32
|
export declare class SourceTracking extends AsyncCreatable {
|
|
33
|
+
readonly registry: RegistryAccess;
|
|
34
|
+
readonly projectPath: string;
|
|
33
35
|
private org;
|
|
34
36
|
private project;
|
|
35
|
-
private projectPath;
|
|
36
37
|
private packagesDirs;
|
|
37
38
|
private logger;
|
|
38
39
|
private localRepo;
|
|
@@ -189,8 +190,6 @@ export declare class SourceTracking extends AsyncCreatable {
|
|
|
189
190
|
setIgnoreConflicts(value: boolean): void;
|
|
190
191
|
private maybeSubscribeLifecycleEvents;
|
|
191
192
|
private getLocalStatusRows;
|
|
192
|
-
private getLocalChangesAsFilenames;
|
|
193
|
-
private localChangesToOutputRow;
|
|
194
193
|
private remoteChangesToOutputRows;
|
|
195
194
|
}
|
|
196
195
|
export {};
|
package/lib/sourceTracking.js
CHANGED
|
@@ -22,10 +22,12 @@ const conflicts_1 = require("./shared/conflicts");
|
|
|
22
22
|
const guards_1 = require("./shared/guards");
|
|
23
23
|
const remoteChangeIgnoring_1 = require("./shared/remoteChangeIgnoring");
|
|
24
24
|
const functions_1 = require("./shared/functions");
|
|
25
|
+
const functions_2 = require("./shared/functions");
|
|
25
26
|
const metadataKeys_1 = require("./shared/metadataKeys");
|
|
26
27
|
const populateFilePaths_1 = require("./shared/populateFilePaths");
|
|
27
28
|
const populateTypesAndNames_1 = require("./shared/populateTypesAndNames");
|
|
28
29
|
const localComponentSetArray_1 = require("./shared/localComponentSetArray");
|
|
30
|
+
const functions_3 = require("./shared/functions");
|
|
29
31
|
/**
|
|
30
32
|
* Manages source tracking files (remote and local)
|
|
31
33
|
*
|
|
@@ -44,6 +46,7 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
44
46
|
this.ignoreConflicts = options.ignoreConflicts ?? false;
|
|
45
47
|
this.ignoreLocalCache = options.ignoreLocalCache ?? false;
|
|
46
48
|
this.subscribeSDREvents = options.subscribeSDREvents ?? false;
|
|
49
|
+
this.registry = new source_deploy_retrieve_1.RegistryAccess(undefined, this.projectPath);
|
|
47
50
|
}
|
|
48
51
|
async init() {
|
|
49
52
|
await this.maybeSubscribeLifecycleEvents();
|
|
@@ -72,7 +75,7 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
72
75
|
deletes,
|
|
73
76
|
}, byPackageDir ?? Boolean(projectConfig.pushPackageDirectoriesSequentially)); // if the users specified true or false for the param, that overrides the project config
|
|
74
77
|
this.logger.debug(`will build array of ${groupings.length} componentSet(s)`);
|
|
75
|
-
return (0, localComponentSetArray_1.getComponentSets)(groupings, sourceApiVersion);
|
|
78
|
+
return (0, localComponentSetArray_1.getComponentSets)({ groupings, sourceApiVersion, registry: this.registry });
|
|
76
79
|
}
|
|
77
80
|
/** reads tracking files for remote changes. It DOES NOT consider the effects of .forceignore unless told to */
|
|
78
81
|
async remoteNonDeletesAsComponentSet({ applyIgnore = false, } = {}) {
|
|
@@ -94,13 +97,11 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
94
97
|
}),
|
|
95
98
|
this.project.resolveProjectConfig(),
|
|
96
99
|
]);
|
|
97
|
-
const componentSet = new source_deploy_retrieve_1.ComponentSet(applyIgnore
|
|
98
|
-
? sourceBackedComponents.filter((sc) => ![sc.content, sc.xml].some((f) => f && this.forceIgnore.denies(f)))
|
|
99
|
-
: sourceBackedComponents);
|
|
100
|
+
const componentSet = new source_deploy_retrieve_1.ComponentSet(applyIgnore ? sourceBackedComponents.filter(noFileIsIgnored(this.forceIgnore)) : sourceBackedComponents, this.registry);
|
|
100
101
|
// there may be remote adds not in the SBC. So we add those manually
|
|
101
102
|
(applyIgnore
|
|
102
103
|
? (0, remoteChangeIgnoring_1.removeIgnored)(changeResults, this.forceIgnore, this.project.getDefaultPackage().fullPath)
|
|
103
|
-
: changeResults.map(
|
|
104
|
+
: changeResults.map(functions_1.remoteChangeToMetadataMember)).map((mm) => {
|
|
104
105
|
componentSet.add(mm);
|
|
105
106
|
});
|
|
106
107
|
if (projectConfig.sourceApiVersion) {
|
|
@@ -131,10 +132,10 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
131
132
|
}
|
|
132
133
|
if (local && remote) {
|
|
133
134
|
// keys like ApexClass__MyClass.cls
|
|
134
|
-
const conflictFiles = (await this.getConflicts()).flatMap((conflict) => conflict.filenames).filter(ts_types_1.isString);
|
|
135
|
+
const conflictFiles = new Set((await this.getConflicts()).flatMap((conflict) => conflict.filenames).filter(ts_types_1.isString));
|
|
135
136
|
results = results.map((row) => ({
|
|
136
137
|
...row,
|
|
137
|
-
conflict: !!row.filePath && conflictFiles.
|
|
138
|
+
conflict: !!row.filePath && conflictFiles.has(row.filePath),
|
|
138
139
|
}));
|
|
139
140
|
}
|
|
140
141
|
return results;
|
|
@@ -142,7 +143,7 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
142
143
|
async getChanges(options) {
|
|
143
144
|
if (options?.origin === 'local') {
|
|
144
145
|
await this.ensureLocalTracking();
|
|
145
|
-
const filenames = await this.
|
|
146
|
+
const filenames = await getLocalChangesAsFilenames(this.localRepo)(options.state);
|
|
146
147
|
if (options.format === 'string') {
|
|
147
148
|
return filenames;
|
|
148
149
|
}
|
|
@@ -153,9 +154,7 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
153
154
|
}));
|
|
154
155
|
}
|
|
155
156
|
if (options.format === 'SourceComponent') {
|
|
156
|
-
const resolver = options.state === 'delete'
|
|
157
|
-
? new source_deploy_retrieve_1.MetadataResolver(undefined, source_deploy_retrieve_1.VirtualTreeContainer.fromFilePaths(filenames))
|
|
158
|
-
: new source_deploy_retrieve_1.MetadataResolver();
|
|
157
|
+
const resolver = new source_deploy_retrieve_1.MetadataResolver(this.registry, options.state === 'delete' ? source_deploy_retrieve_1.VirtualTreeContainer.fromFilePaths(filenames) : undefined);
|
|
159
158
|
return filenames
|
|
160
159
|
.flatMap((filename) => {
|
|
161
160
|
try {
|
|
@@ -178,25 +177,27 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
178
177
|
// skip any remote types not in the registry. Will emit warnings
|
|
179
178
|
.filter((rce) => (0, metadataKeys_1.registrySupportsType)(rce.type));
|
|
180
179
|
if (options.format === 'ChangeResult') {
|
|
181
|
-
return filteredChanges.map(
|
|
180
|
+
return filteredChanges.map(remoteSourceTrackingService_1.remoteChangeElementToChangeResult);
|
|
182
181
|
}
|
|
183
182
|
if (options.format === 'ChangeResultWithPaths') {
|
|
184
|
-
return (0, populateFilePaths_1.populateFilePaths)(
|
|
183
|
+
return (0, populateFilePaths_1.populateFilePaths)({
|
|
184
|
+
elements: filteredChanges.map(remoteSourceTrackingService_1.remoteChangeElementToChangeResult),
|
|
185
|
+
packageDirPaths: this.project.getPackageDirectories().map((pkgDir) => pkgDir.path),
|
|
186
|
+
registry: this.registry,
|
|
187
|
+
});
|
|
185
188
|
}
|
|
186
189
|
// turn it into a componentSet to resolve filenames
|
|
187
190
|
const remoteChangesAsComponentSet = new source_deploy_retrieve_1.ComponentSet(filteredChanges.map((element) => ({
|
|
188
191
|
type: element?.type,
|
|
189
192
|
fullName: element?.name,
|
|
190
|
-
})));
|
|
193
|
+
})), this.registry);
|
|
191
194
|
const matchingLocalSourceComponentsSet = source_deploy_retrieve_1.ComponentSet.fromSource({
|
|
192
195
|
fsPaths: this.packagesDirs.map((dir) => (0, node_path_1.resolve)(dir.fullPath)),
|
|
193
196
|
include: remoteChangesAsComponentSet,
|
|
197
|
+
registry: this.registry,
|
|
194
198
|
});
|
|
195
199
|
if (options.format === 'string') {
|
|
196
|
-
return matchingLocalSourceComponentsSet
|
|
197
|
-
.getSourceComponents()
|
|
198
|
-
.toArray()
|
|
199
|
-
.flatMap((component) => [component.xml, ...component.walkContent()].filter((filename) => filename));
|
|
200
|
+
return matchingLocalSourceComponentsSet.getSourceComponents().toArray().flatMap(functions_2.getAllFiles);
|
|
200
201
|
}
|
|
201
202
|
else if (options.format === 'SourceComponent') {
|
|
202
203
|
return matchingLocalSourceComponentsSet.getSourceComponents().toArray();
|
|
@@ -224,12 +225,9 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
224
225
|
if (changesToDelete.length === 0) {
|
|
225
226
|
return [];
|
|
226
227
|
}
|
|
227
|
-
const sourceComponentByFileName = new Map();
|
|
228
|
-
changesToDelete.flatMap((component) => [component.xml, ...component.walkContent()]
|
|
229
|
-
.filter((filename) => filename)
|
|
230
|
-
.map((filename) => sourceComponentByFileName.set(filename, component)));
|
|
228
|
+
const sourceComponentByFileName = new Map(changesToDelete.flatMap((component) => (0, functions_2.getAllFiles)(component).map((filename) => [filename, component])));
|
|
231
229
|
// calculate what to return before we delete any files and .walkContent is no longer valid
|
|
232
|
-
const changedToBeDeleted = changesToDelete.flatMap((component) =>
|
|
230
|
+
const changedToBeDeleted = changesToDelete.flatMap((component) => (0, functions_2.getAllFiles)(component).map((file) => ({
|
|
233
231
|
state: source_deploy_retrieve_1.ComponentStatus.Deleted,
|
|
234
232
|
filePath: file,
|
|
235
233
|
type: component.type.name,
|
|
@@ -237,14 +235,9 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
237
235
|
})));
|
|
238
236
|
const filenames = Array.from(sourceComponentByFileName.keys());
|
|
239
237
|
// delete the files
|
|
240
|
-
await Promise.all(filenames.map(
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
return fs.promises.unlink(filename);
|
|
246
|
-
}
|
|
247
|
-
}));
|
|
238
|
+
await Promise.all(filenames.map((filename) => sourceComponentByFileName.get(filename)?.type.id === 'customlabel'
|
|
239
|
+
? (0, functions_2.deleteCustomLabels)(filename, changesToDelete.filter(functions_3.sourceComponentIsCustomLabel))
|
|
240
|
+
: fs.promises.unlink(filename)));
|
|
248
241
|
// update the tracking files. We're simulating SDR-style fileResponse
|
|
249
242
|
await Promise.all([
|
|
250
243
|
this.updateLocalTracking({ deletedFiles: filenames }),
|
|
@@ -267,10 +260,11 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
267
260
|
const marker = core_2.Performance.mark('@salesforce/source-tracking', 'SourceTracking.updateLocalTracking');
|
|
268
261
|
marker?.addDetails({ nonDeletes: options.files?.length ?? 0, deletes: options.deletedFiles?.length ?? 0 });
|
|
269
262
|
await this.ensureLocalTracking();
|
|
263
|
+
this.logger.trace('files', options.files);
|
|
270
264
|
// relative paths make smaller trees AND isogit wants them relative
|
|
271
265
|
const relativeOptions = {
|
|
272
|
-
files: (options.files ?? []).map((
|
|
273
|
-
deletedFiles: (options.deletedFiles ?? []).map((
|
|
266
|
+
files: (options.files ?? []).map((0, functions_2.ensureRelative)(this.projectPath)),
|
|
267
|
+
deletedFiles: (options.deletedFiles ?? []).map((0, functions_2.ensureRelative)(this.projectPath)),
|
|
274
268
|
};
|
|
275
269
|
// 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
|
|
276
270
|
// what got deleted? Any local changes NOT in the fileResponses but part of a successfully deployed bundle
|
|
@@ -278,16 +272,17 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
278
272
|
// resolve from highest possible level. TODO: can we use [.]
|
|
279
273
|
fsPaths: relativeOptions.files.length ? [relativeOptions.files[0].split(node_path_1.sep)[0]] : [],
|
|
280
274
|
tree: source_deploy_retrieve_1.VirtualTreeContainer.fromFilePaths(relativeOptions.files),
|
|
275
|
+
registry: this.registry,
|
|
281
276
|
});
|
|
282
277
|
// these are top-level bundle paths like lwc/foo
|
|
283
278
|
const bundlesWithDeletedFiles = (await this.getChanges({ origin: 'local', state: 'delete', format: 'SourceComponent' }))
|
|
284
|
-
.filter(
|
|
279
|
+
.filter(functions_2.supportsPartialDelete)
|
|
285
280
|
.filter((cmp) => deployedFilesAsVirtualComponentSet.has({ type: cmp.type, fullName: cmp.fullName }))
|
|
286
281
|
.map((cmp) => cmp.content)
|
|
287
282
|
.filter(ts_types_1.isString);
|
|
288
283
|
await this.localRepo.commitChanges({
|
|
289
284
|
deployedFiles: relativeOptions.files,
|
|
290
|
-
deletedFiles: relativeOptions.deletedFiles.concat((await this.localRepo.getDeleteFilenames()).filter((deployedFile) => bundlesWithDeletedFiles.some((
|
|
285
|
+
deletedFiles: relativeOptions.deletedFiles.concat((await this.localRepo.getDeleteFilenames()).filter((deployedFile) => bundlesWithDeletedFiles.some((0, functions_2.folderContainsPath)(deployedFile)) &&
|
|
291
286
|
!relativeOptions.files.includes(deployedFile))),
|
|
292
287
|
});
|
|
293
288
|
marker?.stop();
|
|
@@ -421,6 +416,7 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
421
416
|
remoteChanges,
|
|
422
417
|
projectPath: this.projectPath,
|
|
423
418
|
forceIgnore: this.forceIgnore,
|
|
419
|
+
registry: this.registry,
|
|
424
420
|
});
|
|
425
421
|
marker?.stop();
|
|
426
422
|
return result;
|
|
@@ -431,23 +427,17 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
431
427
|
* @param result FileResponse[]
|
|
432
428
|
*/
|
|
433
429
|
async updateTrackingFromDeploy(deployResult) {
|
|
434
|
-
const successes = deployResult
|
|
435
|
-
.getFileResponses()
|
|
436
|
-
.filter((fileResponse) => fileResponse.state !== source_deploy_retrieve_1.ComponentStatus.Failed && fileResponse.filePath);
|
|
430
|
+
const successes = deployResult.getFileResponses().filter(guards_1.isSdrSuccess).filter(guards_1.FileResponseHasPath);
|
|
437
431
|
if (!successes.length) {
|
|
438
432
|
return;
|
|
439
433
|
}
|
|
440
434
|
await Promise.all([
|
|
441
435
|
this.updateLocalTracking({
|
|
442
436
|
// assertions allowed because filtered above
|
|
443
|
-
files: successes
|
|
444
|
-
|
|
445
|
-
.map((fileResponse) => fileResponse.filePath),
|
|
446
|
-
deletedFiles: successes
|
|
447
|
-
.filter((fileResponse) => fileResponse.state === source_deploy_retrieve_1.ComponentStatus.Deleted)
|
|
448
|
-
.map((fileResponse) => fileResponse.filePath),
|
|
437
|
+
files: successes.filter(guards_1.FileResponseIsNotDeleted).map(filePathFromFileResponse),
|
|
438
|
+
deletedFiles: successes.filter(guards_1.FileResponseIsDeleted).map(filePathFromFileResponse),
|
|
449
439
|
}),
|
|
450
|
-
this.updateRemoteTracking(successes.map(
|
|
440
|
+
this.updateRemoteTracking(successes.map(functions_1.FileResponseSuccessToRemoteSyncInput)),
|
|
451
441
|
]);
|
|
452
442
|
}
|
|
453
443
|
/**
|
|
@@ -456,25 +446,17 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
456
446
|
* @param result FileResponse[]
|
|
457
447
|
*/
|
|
458
448
|
async updateTrackingFromRetrieve(retrieveResult) {
|
|
459
|
-
const successes = retrieveResult
|
|
460
|
-
.getFileResponses()
|
|
461
|
-
.filter((fileResponse) => fileResponse.state !== source_deploy_retrieve_1.ComponentStatus.Failed);
|
|
449
|
+
const successes = retrieveResult.getFileResponses().filter(guards_1.isSdrSuccess);
|
|
462
450
|
if (!successes.length) {
|
|
463
451
|
return;
|
|
464
452
|
}
|
|
465
453
|
await Promise.all([
|
|
466
454
|
this.updateLocalTracking({
|
|
467
455
|
// assertion allowed because it's filtering out undefined
|
|
468
|
-
files: successes
|
|
469
|
-
|
|
470
|
-
.map((fileResponse) => fileResponse.filePath)
|
|
471
|
-
.filter(Boolean),
|
|
472
|
-
deletedFiles: successes
|
|
473
|
-
.filter((fileResponse) => fileResponse.state === source_deploy_retrieve_1.ComponentStatus.Deleted)
|
|
474
|
-
.map((fileResponse) => fileResponse.filePath)
|
|
475
|
-
.filter(Boolean),
|
|
456
|
+
files: successes.filter(guards_1.FileResponseIsNotDeleted).filter(guards_1.FileResponseHasPath).map(filePathFromFileResponse),
|
|
457
|
+
deletedFiles: successes.filter(guards_1.FileResponseIsDeleted).filter(guards_1.FileResponseHasPath).map(filePathFromFileResponse),
|
|
476
458
|
}),
|
|
477
|
-
this.updateRemoteTracking(successes.map(
|
|
459
|
+
this.updateRemoteTracking(successes.map(functions_1.FileResponseSuccessToRemoteSyncInput), true // retrieves don't need to poll for SourceMembers
|
|
478
460
|
),
|
|
479
461
|
]);
|
|
480
462
|
}
|
|
@@ -526,55 +508,15 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
526
508
|
}
|
|
527
509
|
async getLocalStatusRows() {
|
|
528
510
|
await this.ensureLocalTracking();
|
|
529
|
-
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
excludeUnresolvable: true,
|
|
539
|
-
projectPath: this.projectPath,
|
|
540
|
-
});
|
|
541
|
-
const localModifies = (0, populateTypesAndNames_1.populateTypesAndNames)({
|
|
542
|
-
elements: await this.getChanges({ origin: 'local', state: 'modify', format: 'ChangeResult' }),
|
|
543
|
-
excludeUnresolvable: true,
|
|
544
|
-
projectPath: this.projectPath,
|
|
545
|
-
});
|
|
546
|
-
results = results.concat(localAdds.flatMap((item) => this.localChangesToOutputRow(item, 'add')), localModifies.flatMap((item) => this.localChangesToOutputRow(item, 'modify')), localDeletes.flatMap((item) => this.localChangesToOutputRow(item, 'delete')));
|
|
547
|
-
return results;
|
|
548
|
-
}
|
|
549
|
-
async getLocalChangesAsFilenames(state) {
|
|
550
|
-
if (state === 'modify') {
|
|
551
|
-
return this.localRepo.getModifyFilenames();
|
|
552
|
-
}
|
|
553
|
-
if (state === 'nondelete') {
|
|
554
|
-
return this.localRepo.getNonDeleteFilenames();
|
|
555
|
-
}
|
|
556
|
-
if (state === 'delete') {
|
|
557
|
-
return this.localRepo.getDeleteFilenames();
|
|
558
|
-
}
|
|
559
|
-
if (state === 'add') {
|
|
560
|
-
return this.localRepo.getAddFilenames();
|
|
561
|
-
}
|
|
562
|
-
throw new Error(`unable to get local changes for state ${state}`);
|
|
563
|
-
}
|
|
564
|
-
localChangesToOutputRow(input, localType) {
|
|
565
|
-
this.logger.debug('converting ChangeResult to a row', input);
|
|
566
|
-
this.forceIgnore ??= source_deploy_retrieve_1.ForceIgnore.findAndCreate(this.project.getDefaultPackage().path);
|
|
567
|
-
if (input.filenames) {
|
|
568
|
-
return input.filenames.map((filename) => ({
|
|
569
|
-
type: input.type ?? '',
|
|
570
|
-
state: localType,
|
|
571
|
-
fullName: input.name ?? '',
|
|
572
|
-
filePath: filename,
|
|
573
|
-
origin: 'local',
|
|
574
|
-
ignored: this.forceIgnore.denies(filename),
|
|
575
|
-
}));
|
|
576
|
-
}
|
|
577
|
-
throw new Error('no filenames found for local ChangeResult');
|
|
511
|
+
this.forceIgnore ??= source_deploy_retrieve_1.ForceIgnore.findAndCreate(this.project.getDefaultPackage().path); // ensure forceignore is initialized
|
|
512
|
+
const [adds, modifies, deletes] = await Promise.all(['add', 'modify', 'delete'].map((state) => this.getChanges({ origin: 'local', state, format: 'ChangeResult' })));
|
|
513
|
+
const base = { projectPath: this.projectPath, registry: this.registry, excludeUnresolvable: true };
|
|
514
|
+
const toOutput = localChangesToOutputRow(this.logger)(this.forceIgnore);
|
|
515
|
+
return [
|
|
516
|
+
...(0, populateTypesAndNames_1.populateTypesAndNames)(base)(adds).flatMap(toOutput('add')),
|
|
517
|
+
...(0, populateTypesAndNames_1.populateTypesAndNames)(base)(modifies).flatMap(toOutput('modify')),
|
|
518
|
+
...(0, populateTypesAndNames_1.populateTypesAndNames)({ ...base, resolveDeleted: true })(deletes).flatMap(toOutput('delete')),
|
|
519
|
+
];
|
|
578
520
|
}
|
|
579
521
|
// reserve the right to do something more sophisticated in the future
|
|
580
522
|
// via async for figuring out hypothetical filenames (ex: getting default packageDir)
|
|
@@ -598,14 +540,12 @@ class SourceTracking extends kit_1.AsyncCreatable {
|
|
|
598
540
|
}
|
|
599
541
|
// when the file doesn't exist locally, there are no filePaths
|
|
600
542
|
// SDR can generate the hypothetical place it *would* go and check that
|
|
601
|
-
if (
|
|
543
|
+
if ((0, guards_1.isChangeResultWithNameAndType)(input)) {
|
|
544
|
+
const ignored = (0, filePathGenerator_1.filePathsFromMetadataComponent)((0, functions_1.changeResultToMetadataComponent)(registry)(input)).some((0, functions_2.forceIgnoreDenies)(this.forceIgnore));
|
|
602
545
|
return [
|
|
603
546
|
{
|
|
604
547
|
...baseObject,
|
|
605
|
-
ignored
|
|
606
|
-
fullName: input.name,
|
|
607
|
-
type: registry.getTypeByName(input.type),
|
|
608
|
-
}).some((hypotheticalFilePath) => this.forceIgnore.denies(hypotheticalFilePath)),
|
|
548
|
+
ignored,
|
|
609
549
|
},
|
|
610
550
|
];
|
|
611
551
|
}
|
|
@@ -628,4 +568,32 @@ const stateFromChangeResult = (input) => {
|
|
|
628
568
|
}
|
|
629
569
|
return 'add';
|
|
630
570
|
};
|
|
571
|
+
const getLocalChangesAsFilenames = (localRepo) => async (state) => {
|
|
572
|
+
switch (state) {
|
|
573
|
+
case 'modify':
|
|
574
|
+
return localRepo.getModifyFilenames();
|
|
575
|
+
case 'nondelete':
|
|
576
|
+
return localRepo.getNonDeleteFilenames();
|
|
577
|
+
case 'delete':
|
|
578
|
+
return localRepo.getDeleteFilenames();
|
|
579
|
+
case 'add':
|
|
580
|
+
return localRepo.getAddFilenames();
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
const filePathFromFileResponse = (input) => input.filePath;
|
|
584
|
+
const noFileIsIgnored = (forceIgnore) => (cmp) => !(0, functions_2.getAllFiles)(cmp).some((0, functions_2.forceIgnoreDenies)(forceIgnore));
|
|
585
|
+
const localChangesToOutputRow = (logger) => (forceIgnore) => (localType) => (input) => {
|
|
586
|
+
logger.debug('converting ChangeResult to a row', input);
|
|
587
|
+
if (input.filenames) {
|
|
588
|
+
return input.filenames.map((filename) => ({
|
|
589
|
+
type: input.type ?? '',
|
|
590
|
+
state: localType,
|
|
591
|
+
fullName: input.name ?? '',
|
|
592
|
+
filePath: filename,
|
|
593
|
+
origin: 'local',
|
|
594
|
+
ignored: forceIgnore.denies(filename),
|
|
595
|
+
}));
|
|
596
|
+
}
|
|
597
|
+
throw new Error('no filenames found for local ChangeResult');
|
|
598
|
+
};
|
|
631
599
|
//# sourceMappingURL=sourceTracking.js.map
|