Skip to content

Commit 854e2bd

Browse files
committed
implement topics in lieu of a code-type flag
1 parent 7bfca44 commit 854e2bd

File tree

6 files changed

+219
-47
lines changed

6 files changed

+219
-47
lines changed

README.md

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,25 +110,99 @@ sf plugins
110110
## Commands
111111

112112
<!-- commands -->
113+
* [`sf data-code-extension function init`](#sf-data-code-extension-function-init)
114+
* [`sf data-code-extension script init`](#sf-data-code-extension-script-init)
115+
* [`sf hello world`](#sf-hello-world)
113116

114-
- [`sf hello world`](#sf-hello-world)
117+
## `sf data-code-extension function init`
118+
119+
Initialize the Data Code Extension environment.
120+
121+
```
122+
USAGE
123+
$ sf data-code-extension function init -p <value> [--json] [--flags-dir <value>]
124+
125+
FLAGS
126+
-p, --package-dir=<value> (required) Directory path where the package will be created.
127+
128+
GLOBAL FLAGS
129+
--flags-dir=<value> Import flag values from a directory.
130+
--json Format output as json.
131+
132+
DESCRIPTION
133+
Initialize the Data Code Extension environment.
134+
135+
Initializes the Data Code Extension by checking system requirements and setting up the necessary environment.
136+
137+
EXAMPLES
138+
Initialize a script-based Data Cloud package:
139+
140+
$ sf data-code-extension script init --package-dir ./my-script-package
141+
142+
Initialize a function-based Data Cloud package:
143+
144+
$ sf data-code-extension function init --package-dir ./my-function-package
145+
146+
FLAG DESCRIPTIONS
147+
-p, --package-dir=<value> Directory path where the package will be created.
148+
149+
The directory path where the new package will be initialized.
150+
The directory will be created if it does not exist.
151+
```
152+
153+
## `sf data-code-extension script init`
154+
155+
Initialize the Data Code Extension environment.
156+
157+
```
158+
USAGE
159+
$ sf data-code-extension script init -p <value> [--json] [--flags-dir <value>]
160+
161+
FLAGS
162+
-p, --package-dir=<value> (required) Directory path where the package will be created.
163+
164+
GLOBAL FLAGS
165+
--flags-dir=<value> Import flag values from a directory.
166+
--json Format output as json.
167+
168+
DESCRIPTION
169+
Initialize the Data Code Extension environment.
170+
171+
Initializes the Data Code Extension by checking system requirements and setting up the necessary environment.
172+
173+
EXAMPLES
174+
Initialize a script-based Data Cloud package:
175+
176+
$ sf data-code-extension script init --package-dir ./my-script-package
177+
178+
Initialize a function-based Data Cloud package:
179+
180+
$ sf data-code-extension function init --package-dir ./my-function-package
181+
182+
FLAG DESCRIPTIONS
183+
-p, --package-dir=<value> Directory path where the package will be created.
184+
185+
The directory path where the new package will be initialized.
186+
The directory will be created if it does not exist.
187+
```
115188

116189
## `sf hello world`
117190

118-
Say hello either to the world or someone you know.
191+
Say hello.
119192

120193
```
121194
USAGE
122-
$ sf hello world [--json] [-n <value>]
195+
$ sf hello world [--json] [--flags-dir <value>] [-n <value>]
123196
124197
FLAGS
125198
-n, --name=<value> [default: World] The name of the person you'd like to say hello to.
126199
127200
GLOBAL FLAGS
128-
--json Format output as json.
201+
--flags-dir=<value> Import flag values from a directory.
202+
--json Format output as json.
129203
130204
DESCRIPTION
131-
Say hello either to the world or someone you know.
205+
Say hello.
132206
133207
Say hello either to the world or someone you know.
134208
@@ -140,6 +214,10 @@ EXAMPLES
140214
Say hello to someone you know:
141215
142216
$ sf hello world --name Astro
143-
```
144217
218+
FLAG DESCRIPTIONS
219+
-n, --name=<value> The name of the person you'd like to say hello to.
220+
221+
This person can be anyone in the world!
222+
```
145223
<!-- commandsstop -->

messages/data-code-extension.init.md

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ Initializes the Data Code Extension by checking system requirements and setting
88

99
# examples
1010

11-
- Initialize the Data Code Extension:
11+
- Initialize a script-based Data Cloud package:
1212

13-
<%= config.bin %> <%= command.id %>
13+
<%= config.bin %> data-code-extension script init --package-dir ./my-script-package
14+
15+
- Initialize a function-based Data Cloud package:
16+
17+
<%= config.bin %> data-code-extension function init --package-dir ./my-function-package
1418

1519
# info.checkingPython
1620

@@ -44,15 +48,6 @@ Data Code Extension initialized successfully!
4448

4549
Failed to initialize Data Code Extension
4650

47-
# flags.codeType.summary
48-
49-
Specify the code type for the package.
50-
51-
# flags.codeType.description
52-
53-
The code type determines the structure and configuration of the package.
54-
Choose 'script' for standalone script packages or 'function' for function-based packages.
55-
5651
# flags.packageDir.summary
5752

5853
Directory path where the package will be created.

package.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@
4545
"topics": {
4646
"hello": {
4747
"description": "Commands to say hello."
48+
},
49+
"data-code-extension": {
50+
"description": "Commands for Data Cloud Code Extension."
51+
},
52+
"data-code-extension script": {
53+
"description": "Initialize and manage script-based Data Cloud packages."
54+
},
55+
"data-code-extension function": {
56+
"description": "Initialize and manage function-based Data Cloud packages."
4857
}
4958
},
5059
"flexibleTaxonomy": true

src/commands/data-code-extension/init.ts renamed to src/commands/data-code-extension/function/init.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
22
import { Messages } from '@salesforce/core';
3-
import { PythonChecker, type PythonVersionInfo } from '../../utils/pythonChecker.js';
4-
import { PipChecker, type PipPackageInfo } from '../../utils/pipChecker.js';
5-
import { DatacodeBinaryChecker, type DatacodeBinaryInfo } from '../../utils/datacodeBinaryChecker.js';
3+
import { PythonChecker, type PythonVersionInfo } from '../../../utils/pythonChecker.js';
4+
import { PipChecker, type PipPackageInfo } from '../../../utils/pipChecker.js';
5+
import { DatacodeBinaryChecker, type DatacodeBinaryInfo } from '../../../utils/datacodeBinaryChecker.js';
66

77
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
88
const messages = Messages.loadMessages('data-code-extension', 'data-code-extension.init');
@@ -23,13 +23,6 @@ export default class Init extends SfCommand<InitResult> {
2323
public static readonly examples = messages.getMessages('examples');
2424

2525
public static readonly flags = {
26-
'code-type': Flags.string({
27-
char: 'c',
28-
summary: messages.getMessage('flags.codeType.summary'),
29-
description: messages.getMessage('flags.codeType.description'),
30-
options: ['script', 'function'],
31-
default: 'script',
32-
}),
3326
'package-dir': Flags.directory({
3427
char: 'p',
3528
summary: messages.getMessage('flags.packageDir.summary'),
@@ -41,7 +34,7 @@ export default class Init extends SfCommand<InitResult> {
4134

4235
public async run(): Promise<InitResult> {
4336
const { flags } = await this.parse(Init);
44-
const codeType = flags['code-type'] as 'script' | 'function';
37+
const codeType = 'function' as const;
4538
const packageDir = flags['package-dir'];
4639

4740
this.spinner.start(messages.getMessage('info.checkingPython'));
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
2+
import { Messages } from '@salesforce/core';
3+
import { PythonChecker, type PythonVersionInfo } from '../../../utils/pythonChecker.js';
4+
import { PipChecker, type PipPackageInfo } from '../../../utils/pipChecker.js';
5+
import { DatacodeBinaryChecker, type DatacodeBinaryInfo } from '../../../utils/datacodeBinaryChecker.js';
6+
7+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
8+
const messages = Messages.loadMessages('data-code-extension', 'data-code-extension.init');
9+
10+
export type InitResult = {
11+
success: boolean;
12+
pythonVersion: PythonVersionInfo;
13+
packageInfo?: PipPackageInfo;
14+
binaryInfo?: DatacodeBinaryInfo;
15+
codeType: 'script' | 'function';
16+
packageDir: string;
17+
message: string;
18+
};
19+
20+
export default class Init extends SfCommand<InitResult> {
21+
public static readonly summary = messages.getMessage('summary');
22+
public static readonly description = messages.getMessage('description');
23+
public static readonly examples = messages.getMessages('examples');
24+
25+
public static readonly flags = {
26+
'package-dir': Flags.directory({
27+
char: 'p',
28+
summary: messages.getMessage('flags.packageDir.summary'),
29+
description: messages.getMessage('flags.packageDir.description'),
30+
required: true,
31+
exists: false, // Allow non-existing directories (will be created)
32+
}),
33+
};
34+
35+
public async run(): Promise<InitResult> {
36+
const { flags } = await this.parse(Init);
37+
const codeType = 'script' as const;
38+
const packageDir = flags['package-dir'];
39+
40+
this.spinner.start(messages.getMessage('info.checkingPython'));
41+
42+
try {
43+
// Check Python 3.11+ is installed
44+
const pythonInfo = await PythonChecker.checkPython311();
45+
46+
this.spinner.stop();
47+
this.log(messages.getMessage('info.pythonFound', [pythonInfo.version, pythonInfo.command]));
48+
49+
// Check required pip packages
50+
this.spinner.start(messages.getMessage('info.checkingPackages'));
51+
const packageInfo = await PipChecker.checkPackage('salesforce-data-customcode');
52+
53+
this.spinner.stop();
54+
this.log(messages.getMessage('info.packageFound', [packageInfo.name, packageInfo.version]));
55+
56+
// Check datacustomcode binary
57+
this.spinner.start(messages.getMessage('info.checkingBinary'));
58+
const binaryInfo = await DatacodeBinaryChecker.checkBinary();
59+
60+
this.spinner.stop();
61+
this.log(messages.getMessage('info.binaryFound', [binaryInfo.version]));
62+
63+
this.log(messages.getMessage('info.initSuccess'));
64+
65+
return {
66+
success: true,
67+
pythonVersion: pythonInfo,
68+
packageInfo,
69+
binaryInfo,
70+
codeType,
71+
packageDir,
72+
message: messages.getMessage('info.initSuccess'),
73+
};
74+
} catch (error) {
75+
this.spinner.stop();
76+
77+
// The error will be properly handled by the Salesforce CLI framework
78+
// as an SfError with actions, so we just throw it
79+
throw error;
80+
}
81+
}
82+
}

test/commands/data-code-extension/init.test.ts

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { TestContext } from '@salesforce/core/testSetup';
22
import { expect } from 'chai';
33
import { stubSfCommandUx } from '@salesforce/sf-plugins-core';
4-
import Init from '../../../src/commands/data-code-extension/init.js';
4+
import ScriptInit from '../../../src/commands/data-code-extension/script/init.js';
5+
import FunctionInit from '../../../src/commands/data-code-extension/function/init.js';
56

6-
describe('data-code-extension init', () => {
7+
describe('data-code-extension init commands', () => {
78
const $$ = new TestContext();
89
let sfCommandStubs: ReturnType<typeof stubSfCommandUx>;
910

@@ -15,12 +16,13 @@ describe('data-code-extension init', () => {
1516
$$.restore();
1617
});
1718

18-
it('runs init command successfully', async () => {
19+
it('runs script init command successfully', async () => {
1920
try {
20-
const result = await Init.run(['--package-dir', './test-dir']);
21+
const result = await ScriptInit.run(['--package-dir', './test-dir']);
2122

2223
// If Python 3.11+ is installed, check the success result
2324
expect(result.success).to.be.true;
25+
expect(result.codeType).to.equal('script');
2426
expect(result.pythonVersion).to.have.property('command');
2527
expect(result.pythonVersion).to.have.property('version');
2628
expect(result.pythonVersion).to.have.property('major');
@@ -76,9 +78,9 @@ describe('data-code-extension init', () => {
7678
}
7779
});
7880

79-
it('returns JSON result when --json flag is used', async () => {
81+
it('returns JSON result when --json flag is used for script init', async () => {
8082
try {
81-
const result = await Init.run(['--json', '--package-dir', './test-json']);
83+
const result = await ScriptInit.run(['--json', '--package-dir', './test-json']);
8284

8385
// Should return a structured result
8486
expect(result).to.be.an('object');
@@ -96,11 +98,12 @@ describe('data-code-extension init', () => {
9698
}
9799
});
98100

99-
it('runs init with default code-type (script) and package-dir', async () => {
101+
it('runs function init command successfully', async () => {
100102
try {
101-
const result = await Init.run(['--package-dir', './test-package']);
102-
expect(result.codeType).to.equal('script'); // default value
103-
expect(result.packageDir).to.equal('./test-package');
103+
const result = await FunctionInit.run(['--package-dir', './test-function']);
104+
expect(result.codeType).to.equal('function');
105+
expect(result.packageDir).to.equal('./test-function');
106+
expect(result.success).to.be.true;
104107
} catch (error) {
105108
// Handle case where Python is not installed
106109
if (error instanceof Error) {
@@ -109,11 +112,11 @@ describe('data-code-extension init', () => {
109112
}
110113
});
111114

112-
it('runs init with --code-type function', async () => {
115+
it('script init returns codeType as script', async () => {
113116
try {
114-
const result = await Init.run(['--code-type', 'function', '--package-dir', './my-function']);
115-
expect(result.codeType).to.equal('function');
116-
expect(result.packageDir).to.equal('./my-function');
117+
const result = await ScriptInit.run(['--package-dir', './test-script']);
118+
expect(result.codeType).to.equal('script');
119+
expect(result.packageDir).to.equal('./test-script');
117120
} catch (error) {
118121
// Handle case where Python is not installed
119122
if (error instanceof Error) {
@@ -122,11 +125,11 @@ describe('data-code-extension init', () => {
122125
}
123126
});
124127

125-
it('runs init with -c and -p shorthand flags', async () => {
128+
it('function init returns codeType as function', async () => {
126129
try {
127-
const result = await Init.run(['-c', 'function', '-p', './short-test']);
130+
const result = await FunctionInit.run(['--package-dir', './test-function-type']);
128131
expect(result.codeType).to.equal('function');
129-
expect(result.packageDir).to.equal('./short-test');
132+
expect(result.packageDir).to.equal('./test-function-type');
130133
} catch (error) {
131134
// Handle case where Python is not installed
132135
if (error instanceof Error) {
@@ -135,9 +138,21 @@ describe('data-code-extension init', () => {
135138
}
136139
});
137140

138-
it('fails when package-dir is not provided', async () => {
141+
it('fails when package-dir is not provided for script init', async () => {
142+
try {
143+
await ScriptInit.run([]);
144+
expect.fail('Should have thrown an error for missing required flag');
145+
} catch (error) {
146+
expect(error).to.exist;
147+
if (error instanceof Error) {
148+
expect(error.message).to.include('package-dir');
149+
}
150+
}
151+
});
152+
153+
it('fails when package-dir is not provided for function init', async () => {
139154
try {
140-
await Init.run(['--code-type', 'script']);
155+
await FunctionInit.run([]);
141156
expect.fail('Should have thrown an error for missing required flag');
142157
} catch (error) {
143158
expect(error).to.exist;

0 commit comments

Comments
 (0)