Skip to content

Commit fbcf39d

Browse files
Merge pull request #1236 from forcedotcom/packagingDistribution/packageBundles
@W-19441295 Bundles CLI - sfdx-core
2 parents a7b2c00 + 1d66a28 commit fbcf39d

File tree

4 files changed

+353
-20
lines changed

4 files changed

+353
-20
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
"dependencies": {
5858
"@jsforce/jsforce-node": "^3.10.4",
5959
"@salesforce/kit": "^3.2.2",
60-
"@salesforce/schemas": "^1.9.1",
60+
"@salesforce/schemas": "^1.10.0",
6161
"@salesforce/ts-types": "^2.0.11",
6262
"ajv": "^8.17.1",
6363
"change-case": "^4.1.2",

src/sfProject.ts

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import { basename, dirname, isAbsolute, normalize, resolve, sep } from 'node:path';
88
import { defaults, env } from '@salesforce/kit';
99
import { Dictionary, ensure, JsonMap, Nullable, Optional } from '@salesforce/ts-types';
10-
import { PackageDir, ProjectJson as ProjectJsonSchema, PackagePackageDir } from '@salesforce/schemas';
10+
import { PackageDir, ProjectJson as ProjectJsonSchema, PackagePackageDir, BundleEntry } from '@salesforce/schemas';
1111
import { fs } from './fs/fs';
1212
import { SfdcUrl } from './util/sfdcUrl';
1313
import { ConfigAggregator } from './config/configAggregator';
@@ -37,6 +37,7 @@ type NameAndFullPath = {
3737

3838
export type NamedPackagingDir = PackagePackageDir & NameAndFullPath;
3939
export type NamedPackageDir = PackageDir & NameAndFullPath;
40+
export type { BundleEntry };
4041

4142
export type ProjectJson = ConfigContents & ProjectJsonSchema;
4243

@@ -66,7 +67,7 @@ export type ProjectJson = ConfigContents & ProjectJsonSchema;
6667
*/
6768
export class SfProjectJson extends ConfigFile<ConfigFile.Options, ProjectJson> {
6869
/** json properties that are uppercase, or allow uppercase keys inside them */
69-
public static BLOCKLIST = ['packageAliases', 'plugins'];
70+
public static BLOCKLIST = ['packageAliases', 'plugins', 'packageBundleAliases'];
7071

7172
public static getFileName(): string {
7273
return SFDX_PROJECT_JSON;
@@ -275,11 +276,18 @@ export class SfProjectJson extends ConfigFile<ConfigFile.Options, ProjectJson> {
275276
return this.getContents()?.packageDirectories?.length > 1;
276277
}
277278

279+
/**
280+
* Has multiple package bundles defined in the project.
281+
*/
282+
public hasMultiplePackageBundles(): boolean {
283+
return (this.getContents()?.packageBundles?.length ?? 0) > 1;
284+
}
285+
278286
/**
279287
* Has at least one package alias defined in the project.
280288
*/
281-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/require-await
282-
public async hasPackageAliases() {
289+
// eslint-disable-next-line @typescript-eslint/require-await
290+
public async hasPackageAliases(): Promise<boolean> {
283291
return Object.keys(this.getContents().packageAliases ?? {}).length > 0;
284292
}
285293

@@ -333,6 +341,63 @@ export class SfProjectJson extends ConfigFile<ConfigFile.Options, ProjectJson> {
333341
this.set('packageDirectories', modifiedPackagesDirs);
334342
}
335343

344+
/**
345+
* Get package bundles defined in the project.
346+
*/
347+
public getPackageBundles(): BundleEntry[] {
348+
return this.get('packageBundles') ?? [];
349+
}
350+
/**
351+
* Add a bundle entry to the project.
352+
* If the bundle entry already exists, the new entry
353+
* properties will be merged with the existing properties.
354+
*
355+
* @param bundleEntry
356+
*/
357+
public addPackageBundle(bundleEntry: BundleEntry): void {
358+
const bundles = this.getPackageBundles();
359+
360+
const bundleIndex = bundles.findIndex((b: BundleEntry) => b.name === bundleEntry.name);
361+
362+
const bundleEntryJson: BundleEntry = {
363+
...(bundleIndex > -1 ? bundles[bundleIndex] : bundleEntry),
364+
...bundleEntry,
365+
};
366+
367+
const modifiedBundles =
368+
bundleIndex > -1
369+
? bundles.map((b: BundleEntry) => (b.name === bundleEntry.name ? bundleEntryJson : b))
370+
: [...bundles, bundleEntryJson];
371+
372+
this.set('packageBundles', modifiedBundles);
373+
}
374+
375+
/**
376+
* Has at least one package bundle alias defined in the project.
377+
*/
378+
public hasPackageBundleAliases(): boolean {
379+
return Object.keys(this.getContents().packageBundleAliases ?? {}).length > 0;
380+
}
381+
382+
/**
383+
* Get package bundle aliases defined in the project.
384+
*/
385+
public getPackageBundleAliases(): Nullable<Dictionary<string>> {
386+
return this.get('packageBundleAliases') as Nullable<Dictionary<string>>;
387+
}
388+
389+
/**
390+
* Add a bundle alias to the project.
391+
* If the bundle alias already exists, it will be overwritten.
392+
*
393+
* @param alias The alias name
394+
* @param id The bundle ID
395+
*/
396+
public addPackageBundleAlias(alias: string, id: string): void {
397+
const newAliases = { ...(this.get('packageBundleAliases') ?? {}), [alias]: id };
398+
this.set('packageBundleAliases', newAliases);
399+
}
400+
336401
// keep it because testSetup stubs it!
337402
// eslint-disable-next-line class-methods-use-this
338403
private doesPackageExist(packagePath: string): boolean {
@@ -367,6 +432,7 @@ export class SfProject {
367432
private packageDirectories?: NamedPackageDir[];
368433
private activePackage: Nullable<NamedPackageDir>;
369434
private packageAliases: Nullable<Dictionary<string>>;
435+
private packageBundleAliases: Nullable<Dictionary<string>>;
370436

371437
/**
372438
* Do not directly construct instances of this class -- use {@link SfProject.resolve} instead.
@@ -619,6 +685,13 @@ export class SfProject {
619685
return this.getSfProjectJson().hasMultiplePackages();
620686
}
621687

688+
/**
689+
* Has multiple package bundles defined in the project.
690+
*/
691+
public hasMultiplePackageBundles(): boolean {
692+
return this.getSfProjectJson().hasMultiplePackageBundles();
693+
}
694+
622695
/**
623696
* Get the currently activated package on the project. This has no implication on sfdx-project.json
624697
* but is useful for keeping track of package and source specific options in a process.
@@ -734,6 +807,27 @@ export class SfProject {
734807
.map(([key]) => key);
735808
}
736809

810+
public getPackageBundleAliases(): Nullable<Dictionary<string>> {
811+
if (!this.packageBundleAliases) {
812+
this.packageBundleAliases = this.getSfProjectJson().getPackageBundleAliases();
813+
}
814+
return this.packageBundleAliases;
815+
}
816+
817+
public getPackageBundleIdFromAlias(alias: string): Optional<string> {
818+
const packageBundleAliases = this.getPackageBundleAliases();
819+
return packageBundleAliases ? packageBundleAliases[alias] : undefined;
820+
}
821+
822+
public getAliasesFromPackageBundleId(id: string): string[] {
823+
if (!/^.{15,18}$/.test(id)) {
824+
throw messages.createError('invalidId', [id]);
825+
}
826+
return Object.entries(this.getPackageBundleAliases() ?? {})
827+
.filter(([, value]) => value?.startsWith(id))
828+
.map(([key]) => key);
829+
}
830+
737831
/**
738832
* retrieve the configuration for a named plugin from sfdx-project.json.plugins.pluginName
739833
*

0 commit comments

Comments
 (0)