Skip to content

Commit 4a29b08

Browse files
fix: change CSB to build from all sources combined
1 parent 1572a8c commit 4a29b08

File tree

3 files changed

+108
-50
lines changed

3 files changed

+108
-50
lines changed

src/collections/componentSetBuilder.ts

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { SourceComponent } from '../resolve/sourceComponent';
1414
import { ComponentSet } from '../collections/componentSet';
1515
import { RegistryAccess } from '../registry/registryAccess';
1616
import type { FileProperties } from '../client/types';
17-
import { MetadataType } from '../registry/types';
17+
import type { MetadataType } from '../registry/types';
1818
import { MetadataResolver } from '../resolve';
1919
import { DestructiveChangesType, FromConnectionOptions } from './types';
2020

@@ -91,15 +91,15 @@ export class ComponentSetBuilder {
9191
*/
9292

9393
public static async build(options: ComponentSetOptions): Promise<ComponentSet> {
94-
let componentSet: ComponentSet | undefined;
95-
9694
const { sourcepath, manifest, metadata, packagenames, org } = options;
9795
const registry = new RegistryAccess(undefined, options.projectDir);
96+
let componentSetToReturn = new ComponentSet(undefined, registry);
9897

9998
if (sourcepath) {
10099
getLogger().debug(`Building ComponentSet from sourcepath: ${sourcepath.join(', ')}`);
101100
const fsPaths = sourcepath.map(validateAndResolvePath);
102-
componentSet = ComponentSet.fromSource({
101+
// first possible option, so we can just set it, next CSB options, must add to this componentSet
102+
componentSetToReturn = ComponentSet.fromSource({
103103
fsPaths,
104104
registry,
105105
});
@@ -108,7 +108,6 @@ export class ComponentSetBuilder {
108108
// Return empty ComponentSet and use packageNames in the connection via `.retrieve` options
109109
if (packagenames) {
110110
getLogger().debug(`Building ComponentSet for packagenames: ${packagenames.toString()}`);
111-
componentSet ??= new ComponentSet(undefined, registry);
112111
}
113112

114113
// Resolve manifest with source in package directories.
@@ -117,29 +116,47 @@ export class ComponentSetBuilder {
117116
assertFileExists(manifest.manifestPath);
118117

119118
getLogger().debug(`Searching in packageDir: ${manifest.directoryPaths.join(', ')} for matching metadata`);
120-
componentSet = await ComponentSet.fromManifest({
119+
const constructiveCS = await ComponentSet.fromManifest({
121120
manifestPath: manifest.manifestPath,
122121
resolveSourcePaths: manifest.directoryPaths,
123122
forceAddWildcards: true,
124-
destructivePre: manifest.destructiveChangesPre,
125-
destructivePost: manifest.destructiveChangesPost,
126123
registry,
127124
});
125+
constructiveCS.toArray().map(addToComponentSet(componentSetToReturn));
126+
127+
if (manifest.destructiveChangesPre) {
128+
// build this up as if it were constructive, to satisfy fromManifest parameter types
129+
const destructivePre = await ComponentSet.fromManifest({
130+
resolveSourcePaths: manifest.directoryPaths,
131+
manifestPath: manifest.destructiveChangesPre,
132+
registry,
133+
});
134+
destructivePre.toArray().map(addToComponentSet(componentSetToReturn, DestructiveChangesType.PRE));
135+
}
136+
137+
if (manifest.destructiveChangesPost) {
138+
const destrutivePost = await ComponentSet.fromManifest({
139+
manifestPath: manifest.destructiveChangesPost,
140+
resolveSourcePaths: manifest.directoryPaths,
141+
registry,
142+
});
143+
destrutivePost.toArray().map(addToComponentSet(componentSetToReturn, DestructiveChangesType.POST));
144+
}
145+
componentSetToReturn.sourceApiVersion ??= constructiveCS.sourceApiVersion;
146+
componentSetToReturn.apiVersion ??= constructiveCS.apiVersion;
128147
}
129148

130-
// Resolve metadata entries with source in package directories, unless we are building a ComponentSet
131-
// from metadata in an org.
132-
if (metadata && !org) {
149+
// Resolve metadata entries with source in package directories
150+
if (metadata) {
133151
getLogger().debug(`Building ComponentSet from metadata: ${metadata.metadataEntries.toString()}`);
134152
const directoryPaths = metadata.directoryPaths;
135-
componentSet ??= new ComponentSet(undefined, registry);
136153
const componentSetFilter = new ComponentSet(undefined, registry);
137154

138155
// Build a Set of metadata entries
139-
metadata.metadataEntries
140-
.map(entryToTypeAndName(registry))
156+
const l = metadata.metadataEntries.filter(filterPsuedoTypes);
157+
l.map(entryToTypeAndName(registry))
141158
.flatMap(typeAndNameToMetadataComponents({ directoryPaths, registry }))
142-
.map(addToComponentSet(componentSet))
159+
.map(addToComponentSet(componentSetToReturn))
143160
.map(addToComponentSet(componentSetFilter));
144161

145162
getLogger().debug(`Searching for matching metadata in directories: ${directoryPaths.join(', ')}`);
@@ -148,19 +165,21 @@ export class ComponentSetBuilder {
148165
// are resolved to SourceComponents
149166
if (metadata.destructiveEntriesPre) {
150167
metadata.destructiveEntriesPre
168+
.filter(filterPsuedoTypes)
151169
.map(entryToTypeAndName(registry))
152170
.map(assertNoWildcardInDestructiveEntries)
153171
.flatMap(typeAndNameToMetadataComponents({ directoryPaths, registry }))
154172
.map((mdComponent) => new SourceComponent({ type: mdComponent.type, name: mdComponent.fullName }))
155-
.map(addToComponentSet(componentSet, DestructiveChangesType.PRE));
173+
.map(addToComponentSet(componentSetToReturn, DestructiveChangesType.PRE));
156174
}
157175
if (metadata.destructiveEntriesPost) {
158176
metadata.destructiveEntriesPost
177+
.filter(filterPsuedoTypes)
159178
.map(entryToTypeAndName(registry))
160179
.map(assertNoWildcardInDestructiveEntries)
161180
.flatMap(typeAndNameToMetadataComponents({ directoryPaths, registry }))
162181
.map((mdComponent) => new SourceComponent({ type: mdComponent.type, name: mdComponent.fullName }))
163-
.map(addToComponentSet(componentSet, DestructiveChangesType.POST));
182+
.map(addToComponentSet(componentSetToReturn, DestructiveChangesType.POST));
164183
}
165184

166185
const resolvedComponents = ComponentSet.fromSource({
@@ -169,39 +188,38 @@ export class ComponentSetBuilder {
169188
registry,
170189
});
171190

172-
if (resolvedComponents.forceIgnoredPaths) {
191+
if (resolvedComponents?.forceIgnoredPaths) {
173192
// if useFsForceIgnore = true, then we won't be able to resolve a forceignored path,
174193
// which we need to do to get the ignored source component
175194
const resolver = new MetadataResolver(registry, undefined, false);
176195

177196
for (const ignoredPath of resolvedComponents.forceIgnoredPaths ?? []) {
178197
resolver.getComponentsFromPath(ignoredPath).map((ignored) => {
179-
componentSet = componentSet?.filter(
198+
componentSetToReturn = componentSetToReturn?.filter(
180199
(resolved) => !(resolved.fullName === ignored.name && resolved.type === ignored.type)
181200
);
182201
});
183202
}
184-
componentSet.forceIgnoredPaths = resolvedComponents.forceIgnoredPaths;
203+
componentSetToReturn.forceIgnoredPaths = resolvedComponents.forceIgnoredPaths;
185204
}
186205

187-
resolvedComponents.toArray().map(addToComponentSet(componentSet));
206+
resolvedComponents?.toArray().map(addToComponentSet(componentSetToReturn));
188207
}
189208

190209
// Resolve metadata entries with an org connection
191210
if (org) {
192-
componentSet ??= new ComponentSet(undefined, registry);
193211
const orgComponentSet = await this.resolveOrgComponents(registry, options);
194-
orgComponentSet.toArray().map(addToComponentSet(componentSet));
212+
orgComponentSet.toArray().map(addToComponentSet(componentSetToReturn));
195213
}
196214

197215
// there should have been a componentSet created by this point.
198-
componentSet = assertComponentSetIsNotUndefined(componentSet);
199-
componentSet.apiVersion ??= options.apiversion;
200-
componentSet.sourceApiVersion ??= options.sourceapiversion;
201-
componentSet.projectDirectory = options.projectDir;
216+
componentSetToReturn = assertComponentSetIsNotUndefined(componentSetToReturn);
217+
componentSetToReturn.apiVersion ??= options.apiversion;
218+
componentSetToReturn.sourceApiVersion ??= options.sourceapiversion;
219+
componentSetToReturn.projectDirectory = options.projectDir;
202220

203-
logComponents(componentSet);
204-
return componentSet;
221+
logComponents(componentSetToReturn);
222+
return componentSetToReturn;
205223
}
206224

207225
private static async resolveOrgComponents(
@@ -331,6 +349,12 @@ export const entryToTypeAndName =
331349
return { type, metadataName: name.length ? name.join(':').trim() : '*' };
332350
};
333351

352+
const filterPsuedoTypes = (value: string): boolean => {
353+
const x = Object.values(PSEUDO_TYPES).map((p) => p.toLowerCase());
354+
const [typeName] = value.split(':');
355+
return !x.includes(typeName.toLowerCase());
356+
};
357+
334358
const typeAndNameToMetadataComponents =
335359
(context: { directoryPaths: ManifestOption['directoryPaths']; registry: RegistryAccess }) =>
336360
({ type, metadataName }: MetadataTypeAndMetadataName): MetadataComponent[] =>

test/collections/componentSet.test.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import {
3434
import { decomposedtoplevel, digitalExperienceBundle, matchingContentFile, mixedContentSingleFile } from '../mock';
3535
import { MATCHING_RULES_COMPONENT } from '../mock/type-constants/customlabelsConstant';
3636
import * as manifestFiles from '../mock/manifestConstants';
37-
import { testApiVersion, testApiVersionAsString } from '../mock/manifestConstants';
3837
import * as coverage from '../../src/registry/coverage';
3938

4039
const registryAccess = new RegistryAccess();
@@ -436,7 +435,7 @@ describe('ComponentSet', () => {
436435
];
437436
const resolveStub = $$.SANDBOX.stub(ManifestResolver.prototype, 'resolve').resolves({
438437
components: expected,
439-
apiVersion: testApiVersionAsString,
438+
apiVersion: manifestFiles.testApiVersionAsString,
440439
});
441440
$$.SANDBOX.stub(RegistryAccess.prototype, 'getTypeByName').returns(registry.types.apexclass);
442441
const manifest = manifestFiles.ONE_FOLDER_MEMBER;
@@ -581,7 +580,7 @@ describe('ComponentSet', () => {
581580
];
582581
const resolveStub = $$.SANDBOX.stub(ConnectionResolver.prototype, 'resolve').resolves({
583582
components: expected,
584-
apiVersion: testApiVersionAsString,
583+
apiVersion: manifestFiles.testApiVersionAsString,
585584
});
586585
$$.SANDBOX.stub(RegistryAccess.prototype, 'getTypeByName').returns(registry.types.apexclass);
587586
const set = await ComponentSet.fromConnection({ usernameOrConnection: connection });
@@ -684,7 +683,9 @@ describe('ComponentSet', () => {
684683
let getCurrentApiVersionStub: SinonStub;
685684

686685
beforeEach(() => {
687-
getCurrentApiVersionStub = $$.SANDBOX.stub(coverage, 'getCurrentApiVersion').resolves(testApiVersion);
686+
getCurrentApiVersionStub = $$.SANDBOX.stub(coverage, 'getCurrentApiVersion').resolves(
687+
manifestFiles.testApiVersion
688+
);
688689
});
689690

690691
afterEach(() => {
@@ -712,7 +713,7 @@ describe('ComponentSet', () => {
712713
members: ['b', 'c'],
713714
},
714715
],
715-
version: testApiVersionAsString,
716+
version: manifestFiles.testApiVersionAsString,
716717
},
717718
});
718719
expect(getCurrentApiVersionStub.calledOnce).to.be.true;
@@ -725,7 +726,7 @@ describe('ComponentSet', () => {
725726
registry: registryAccess,
726727
tree: manifestFiles.TREE,
727728
});
728-
set.apiVersion = testApiVersionAsString;
729+
set.apiVersion = manifestFiles.testApiVersionAsString;
729730
expect(await set.getObject()).to.deep.equal({
730731
Package: {
731732
types: [
@@ -738,7 +739,7 @@ describe('ComponentSet', () => {
738739
members: ['b', 'c'],
739740
},
740741
],
741-
version: testApiVersionAsString,
742+
version: manifestFiles.testApiVersionAsString,
742743
},
743744
});
744745
expect(resolveSpy.called).to.be.false;
@@ -778,7 +779,7 @@ describe('ComponentSet', () => {
778779
registry: registryAccess,
779780
tree: manifestFiles.TREE,
780781
});
781-
process.env.SF_ORG_API_VERSION = testApiVersionAsString;
782+
process.env.SF_ORG_API_VERSION = manifestFiles.testApiVersionAsString;
782783
expect(await set.getObject()).to.deep.equal({
783784
Package: {
784785
types: [
@@ -791,7 +792,7 @@ describe('ComponentSet', () => {
791792
members: ['b', 'c'],
792793
},
793794
],
794-
version: testApiVersionAsString,
795+
version: manifestFiles.testApiVersionAsString,
795796
},
796797
});
797798
expect(getCurrentApiVersionStub.called).to.be.false;
@@ -843,7 +844,7 @@ describe('ComponentSet', () => {
843844
members: ['b', 'c'],
844845
},
845846
],
846-
version: testApiVersionAsString,
847+
version: manifestFiles.testApiVersionAsString,
847848
},
848849
});
849850
});
@@ -868,7 +869,7 @@ describe('ComponentSet', () => {
868869
members: ['b', 'c'],
869870
},
870871
],
871-
version: testApiVersionAsString,
872+
version: manifestFiles.testApiVersionAsString,
872873
},
873874
});
874875
});
@@ -1003,7 +1004,7 @@ describe('ComponentSet', () => {
10031004

10041005
describe('getPackageXml', () => {
10051006
beforeEach(() => {
1006-
$$.SANDBOX.stub(coverage, 'getCurrentApiVersion').resolves(testApiVersion);
1007+
$$.SANDBOX.stub(coverage, 'getCurrentApiVersion').resolves(manifestFiles.testApiVersion);
10071008
});
10081009
it('should return manifest string when initialized from manifest file', async () => {
10091010
const manifest = manifestFiles.ONE_OF_EACH;

test/collections/componentSetBuilder.test.ts

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@ import { assert, expect, config } from 'chai';
1313
import { Connection, SfError } from '@salesforce/core';
1414
import { instantiateContext, MockTestOrgData, restoreContext, stubContext } from '@salesforce/core/testSetup';
1515
import { RegistryAccess } from '../../src/registry/registryAccess';
16-
import { ComponentSetBuilder, entryToTypeAndName } from '../../src/collections/componentSetBuilder';
16+
import {
17+
ComponentSetBuilder,
18+
ComponentSetOptions,
19+
entryToTypeAndName,
20+
} from '../../src/collections/componentSetBuilder';
1721
import { ComponentSet } from '../../src/collections/componentSet';
18-
import { FromSourceOptions } from '../../src/collections/types';
22+
import type { FromSourceOptions } from '../../src/collections/types';
1923
import { MetadataResolver, SourceComponent } from '../../src';
2024

2125
config.truncateThreshold = 0;
@@ -434,8 +438,6 @@ describe('ComponentSetBuilder', () => {
434438
forceAddWildcards: true,
435439
manifestPath: options.manifest.manifestPath,
436440
resolveSourcePaths: [packageDir1],
437-
destructivePre: undefined,
438-
destructivePost: undefined,
439441
});
440442
expect(compSet.size).to.equal(1);
441443
expect(compSet.has(apexClassComponent)).to.equal(true);
@@ -467,8 +469,6 @@ describe('ComponentSetBuilder', () => {
467469
forceAddWildcards: true,
468470
manifestPath: options.manifest.manifestPath,
469471
resolveSourcePaths: [packageDir1, packageDir2],
470-
destructivePre: undefined,
471-
destructivePost: undefined,
472472
});
473473
expect(compSet.size).to.equal(2);
474474
expect(compSet.has(apexClassComponent)).to.equal(true);
@@ -491,6 +491,39 @@ describe('ComponentSetBuilder', () => {
491491
restoreContext($$);
492492
});
493493

494+
it('should create a CS from every option possible', async () => {
495+
fileExistsSyncStub.returns(true);
496+
fromSourceStub.returns(new ComponentSet([customObjectComponent]));
497+
fromManifestStub.resolves(new ComponentSet([apexClassWildcardMatch]));
498+
fromConnectionStub.resolves(new ComponentSet([apexClassWildcardNoMatch]));
499+
500+
const packageDir1 = path.resolve('force-app');
501+
const sourcepath = ['force-app', 'my-app'];
502+
503+
const options: ComponentSetOptions = {
504+
sourcepath,
505+
org: {
506+
username: testOrg.username,
507+
exclude: [],
508+
},
509+
metadata: { directoryPaths: [packageDir1], metadataEntries: ['ApexClass:MyClass'] },
510+
manifest: {
511+
manifestPath: 'apex-package.xml',
512+
directoryPaths: [packageDir1],
513+
},
514+
};
515+
516+
const compSet = await ComponentSetBuilder.build(options);
517+
expect(fromManifestStub.callCount).to.equal(1);
518+
expect(fromSourceStub.callCount).to.equal(2);
519+
520+
expect(compSet.size).to.equal(4);
521+
expect(compSet.has(apexClassComponent)).to.equal(true);
522+
expect(compSet.has(customObjectComponent)).to.equal(true);
523+
expect(compSet.has(apexClassWildcardNoMatch)).to.equal(true);
524+
expect(compSet.has(apexClassWildcardMatch)).to.equal(true);
525+
});
526+
494527
it('should create ComponentSet from org connection', async () => {
495528
componentSet.add(apexClassComponent);
496529
fromConnectionStub.resolves(componentSet);
@@ -538,10 +571,10 @@ describe('ComponentSetBuilder', () => {
538571
};
539572

540573
const compSet = await ComponentSetBuilder.build(options);
541-
expect(fromSourceStub.callCount).to.equal(0);
574+
expect(fromSourceStub.callCount).to.equal(2);
542575
expect(fromConnectionStub.callCount).to.equal(1);
543-
expect(compSet.size).to.equal(1);
544-
expect(compSet.has(apexClassComponent)).to.equal(false);
576+
expect(compSet.size).to.equal(2);
577+
expect(compSet.has(apexClassComponent)).to.equal(true);
545578
expect(compSet.has(apexClassWildcardMatch)).to.equal(true);
546579
});
547580

0 commit comments

Comments
 (0)