Skip to content

Commit 7d09db0

Browse files
feat: created bundle list command
near copy and paste of package list command unit test based off of bundle create
1 parent f4061d3 commit 7d09db0

5 files changed

Lines changed: 246 additions & 0 deletions

File tree

command-snapshot.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@
6363
"flags": ["api-version", "description", "flags-dir", "json", "loglevel", "name", "target-dev-hub"],
6464
"plugin": "@salesforce/plugin-packaging"
6565
},
66+
{
67+
"alias": ["force:bundle:list"],
68+
"command": "package:bundles:list",
69+
"flagAliases": ["apiversion", "target-hub-org", "targetdevhubusername"],
70+
"flagChars": ["v"],
71+
"flags": ["api-version", "flags-dir", "json", "loglevel", "target-dev-hub", "verbose"],
72+
"plugin": "@salesforce/plugin-packaging"
73+
},
6674
{
6775
"alias": ["force:package:convert"],
6876
"command": "package:convert",

messages/bundle_list.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# summary
2+
3+
List all bundles in the Dev Hub org.
4+
5+
# description
6+
7+
You can view the namespace, IDs, and other details for each bundle.
8+
9+
# examples
10+
11+
- List all bundles in the specified Dev Hub org:
12+
13+
<%= config.bin %> <%= command.id %> --target-dev-hub devhub@example.com
14+
15+
- List all bundles details in the specified Dev Hub org, and show extended details about each bundle:
16+
17+
<%= config.bin %> <%= command.id %> --target-dev-hub devhub@example.com --verbose
18+
19+
# namespace
20+
21+
Namespace Prefix
22+
23+
# name
24+
25+
Name
26+
27+
# id
28+
29+
Id
30+
31+
# bundle-id
32+
33+
Subscriber bundle Id
34+
35+
# alias
36+
37+
Alias
38+
39+
# description
40+
41+
Description
42+
43+
# flags.verbose.summary
44+
45+
Display extended bundle detail.
46+
47+
# convertedFrombundleId
48+
49+
Converted From bundle Id
50+
51+
# isOrgDependent
52+
53+
Org-Dependent Unlocked bundle
54+
55+
# error-notification-username
56+
57+
Error Notification Username
58+
59+
# createdBy
60+
61+
Created By

schemas/package-bundles-list.json

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$ref": "#/definitions/BundleListCommandResults",
4+
"definitions": {
5+
"BundleListCommandResults": {
6+
"type": "array",
7+
"items": {
8+
"$ref": "#/definitions/BundleListCommandResult"
9+
}
10+
},
11+
"BundleListCommandResult": {
12+
"$ref": "#/definitions/BundleSObjects.Bundle"
13+
},
14+
"BundleSObjects.Bundle": {
15+
"type": "object",
16+
"properties": {
17+
"BundleName": {
18+
"type": "string"
19+
},
20+
"Description": {
21+
"type": "string"
22+
},
23+
"Id": {
24+
"type": "string"
25+
},
26+
"IsDeleted": {
27+
"type": "boolean"
28+
},
29+
"CreatedDate": {
30+
"type": "string"
31+
},
32+
"CreatedById": {
33+
"type": "string"
34+
},
35+
"LastModifiedDate": {
36+
"type": "string"
37+
},
38+
"LastModifiedById": {
39+
"type": "string"
40+
},
41+
"SystemModstamp": {
42+
"type": "string"
43+
}
44+
},
45+
"required": [
46+
"BundleName",
47+
"Id",
48+
"IsDeleted",
49+
"CreatedDate",
50+
"CreatedById",
51+
"LastModifiedDate",
52+
"LastModifiedById",
53+
"SystemModstamp"
54+
],
55+
"additionalProperties": false
56+
}
57+
}
58+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) 2023, salesforce.com, inc.
3+
* All rights reserved.
4+
* Licensed under the BSD 3-Clause license.
5+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
8+
import { Flags, loglevel, orgApiVersionFlagWithDeprecations, SfCommand } from '@salesforce/sf-plugins-core';
9+
import { Messages } from '@salesforce/core/messages';
10+
import { PackageBundle, BundleSObjects } from '@salesforce/packaging';
11+
import chalk from 'chalk';
12+
import { requiredHubFlag } from '../../../utils/hubFlag.js';
13+
14+
// This is a near copy of the package list command, but with the package bundle class and messages.
15+
// If you are looking to copy this command, mabye make an abstract class for the commands that are similar.(please)
16+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
17+
const messages = Messages.loadMessages('@salesforce/plugin-packaging', 'bundle_list');
18+
19+
export type BundleListCommandResult = BundleSObjects.Bundle;
20+
export type BundleListCommandResults = BundleListCommandResult[];
21+
22+
export class BundleListCommand extends SfCommand<BundleListCommandResults> {
23+
public static readonly summary = messages.getMessage('summary');
24+
public static readonly description = messages.getMessage('description');
25+
public static readonly examples = messages.getMessages('examples');
26+
public static readonly deprecateAliases = true;
27+
public static readonly aliases = ['force:bundle:list'];
28+
public static readonly flags = {
29+
loglevel,
30+
'target-dev-hub': requiredHubFlag,
31+
'api-version': orgApiVersionFlagWithDeprecations,
32+
verbose: Flags.boolean({
33+
summary: messages.getMessage('flags.verbose.summary'),
34+
}),
35+
};
36+
37+
public async run(): Promise<BundleListCommandResults> {
38+
const { flags } = await this.parse(BundleListCommand);
39+
const connection = flags['target-dev-hub'].getConnection(flags['api-version']);
40+
const results = await PackageBundle.list(connection);
41+
this.displayResults(results, flags.verbose);
42+
return results;
43+
}
44+
45+
private displayResults(results: BundleListCommandResults, verbose = false): void {
46+
const data = results.map((r) => ({
47+
'Bundle Name': r.BundleName,
48+
Id: r.Id,
49+
Description: r.Description,
50+
...(verbose
51+
? {
52+
'Created Date': r.CreatedDate,
53+
'Created By': r.CreatedById,
54+
'Last Modified Date': r.LastModifiedDate,
55+
'Last Modified By': r.LastModifiedById,
56+
'System Modstamp': r.SystemModstamp,
57+
'Is Deleted': r.IsDeleted,
58+
}
59+
: {}),
60+
}));
61+
this.table({ data, title: chalk.blue(`Package Bundles [${results.length}]`) });
62+
}
63+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (c) 2025, salesforce.com, inc.
3+
* All rights reserved.
4+
* Licensed under the BSD 3-Clause license.
5+
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6+
*/
7+
import { Config } from '@oclif/core';
8+
import { TestContext, MockTestOrgData } from '@salesforce/core/testSetup';
9+
import { expect } from 'chai';
10+
import { PackageBundle } from '@salesforce/packaging';
11+
import { stubSfCommandUx } from '@salesforce/sf-plugins-core';
12+
import sinon from 'sinon';
13+
import { BundleListCommand } from '../../../src/commands/package/bundles/list.js';
14+
describe('force:bundle:list - tests', () => {
15+
const $$ = new TestContext();
16+
const testOrg = new MockTestOrgData();
17+
let sfCommandStubs: ReturnType<typeof stubSfCommandUx>;
18+
let listStub: sinon.SinonStub;
19+
const config = new Config({ root: import.meta.url });
20+
21+
beforeEach(async () => {
22+
await $$.stubAuths(testOrg);
23+
await config.load();
24+
sfCommandStubs = stubSfCommandUx($$.SANDBOX);
25+
26+
listStub = $$.SANDBOX.stub(PackageBundle, 'list');
27+
});
28+
29+
afterEach(() => {
30+
$$.restore();
31+
});
32+
33+
it('should list a bundle', async () => {
34+
const cmd = new BundleListCommand(['-v', testOrg.username], config);
35+
36+
listStub.resolves([{ BundleName: 'test-bundle', Id: 'test-id', Description: 'test-description' }]);
37+
38+
await cmd.run();
39+
40+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
41+
expect(sfCommandStubs.table.calledOnce).to.be.true;
42+
});
43+
44+
it('should throw error when test org flag is missing', async () => {
45+
const cmd = new BundleListCommand([], config);
46+
47+
listStub.resolves([{ BundleName: 'test-bundle', Id: 'test-id', Description: 'test-description' }]);
48+
49+
try {
50+
await cmd.run();
51+
expect.fail('Expected error was not thrown');
52+
} catch (error) {
53+
expect((error as Error).message).to.include('No default dev hub found');
54+
}
55+
});
56+
});

0 commit comments

Comments
 (0)