@adobe/create-ccweb-add-on 2.5.0 → 3.1.0

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.
Files changed (136) hide show
  1. package/.c8rc.json +4 -1
  2. package/.mocharc.json +9 -2
  3. package/README.md +2 -2
  4. package/bin/run.js +2 -2
  5. package/dist/app/AddOnFactory.d.ts +30 -3
  6. package/dist/app/AddOnFactory.d.ts.map +1 -1
  7. package/dist/app/AddOnFactory.js +140 -1
  8. package/dist/app/{AddOnManager.d.ts → PackageManager.d.ts} +4 -4
  9. package/dist/app/PackageManager.d.ts.map +1 -0
  10. package/dist/app/{AddOnManager.js → PackageManager.js} +5 -6
  11. package/dist/app/TemplateSelector.d.ts +20 -4
  12. package/dist/app/TemplateSelector.d.ts.map +1 -1
  13. package/dist/app/TemplateSelector.js +142 -1
  14. package/dist/app/index.d.ts +1 -3
  15. package/dist/app/index.d.ts.map +1 -1
  16. package/dist/app/index.js +1 -3
  17. package/dist/commands/create.d.ts +6 -10
  18. package/dist/commands/create.d.ts.map +1 -1
  19. package/dist/commands/create.js +11 -37
  20. package/dist/config/inversify.config.d.ts +2 -1
  21. package/dist/config/inversify.config.d.ts.map +1 -1
  22. package/dist/config/inversify.config.js +8 -6
  23. package/dist/config/inversify.types.d.ts.map +1 -1
  24. package/dist/constants.d.ts.map +1 -1
  25. package/dist/index.d.ts +25 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +25 -0
  28. package/dist/models/CLIOptions.d.ts +4 -4
  29. package/dist/models/CLIOptions.d.ts.map +1 -1
  30. package/dist/models/CLIOptions.js +5 -5
  31. package/dist/templates/react-javascript/template/src/components/App.jsx +2 -2
  32. package/dist/templates/react-javascript/template/webpack.config.js +1 -0
  33. package/dist/templates/react-javascript/template.json +4 -4
  34. package/dist/templates/react-javascript-with-document-sandbox/template/src/ui/components/App.jsx +2 -2
  35. package/dist/templates/react-javascript-with-document-sandbox/template/webpack.config.js +1 -0
  36. package/dist/templates/react-javascript-with-document-sandbox/template.json +4 -4
  37. package/dist/templates/react-typescript/template/src/components/App.tsx +2 -2
  38. package/dist/templates/react-typescript/template/webpack.config.js +1 -0
  39. package/dist/templates/react-typescript/template.json +4 -4
  40. package/dist/templates/react-typescript-with-document-sandbox/template/src/ui/components/App.tsx +2 -2
  41. package/dist/templates/react-typescript-with-document-sandbox/template/webpack.config.js +1 -0
  42. package/dist/templates/react-typescript-with-document-sandbox/template.json +4 -4
  43. package/dist/templates/swc-javascript/template/src/components/App.js +2 -2
  44. package/dist/templates/swc-javascript/template/webpack.config.js +1 -0
  45. package/dist/templates/swc-javascript/template.json +4 -4
  46. package/dist/templates/swc-javascript-with-document-sandbox/template/src/ui/components/App.js +2 -2
  47. package/dist/templates/swc-javascript-with-document-sandbox/template/webpack.config.js +1 -0
  48. package/dist/templates/swc-javascript-with-document-sandbox/template.json +4 -4
  49. package/dist/templates/swc-typescript/template/src/components/App.css.ts +2 -2
  50. package/dist/templates/swc-typescript/template/src/components/App.ts +4 -4
  51. package/dist/templates/swc-typescript/template/src/index.ts +2 -2
  52. package/dist/templates/swc-typescript/template/webpack.config.js +1 -0
  53. package/dist/templates/swc-typescript/template.json +4 -4
  54. package/dist/templates/swc-typescript-with-document-sandbox/template/src/ui/components/App.css.ts +2 -2
  55. package/dist/templates/swc-typescript-with-document-sandbox/template/src/ui/components/App.ts +4 -4
  56. package/dist/templates/swc-typescript-with-document-sandbox/template/src/ui/index.ts +2 -2
  57. package/dist/templates/swc-typescript-with-document-sandbox/template/webpack.config.js +1 -0
  58. package/dist/templates/swc-typescript-with-document-sandbox/template.json +4 -4
  59. package/dist/tsconfig.tsbuildinfo +1 -1
  60. package/dist/validators/DirectoryValidator.d.ts +22 -11
  61. package/dist/validators/DirectoryValidator.d.ts.map +1 -1
  62. package/dist/validators/DirectoryValidator.js +152 -1
  63. package/dist/validators/EnvironmentValidator.d.ts +17 -2
  64. package/dist/validators/EnvironmentValidator.d.ts.map +1 -1
  65. package/dist/validators/EnvironmentValidator.js +149 -1
  66. package/dist/validators/index.d.ts +0 -2
  67. package/dist/validators/index.d.ts.map +1 -1
  68. package/dist/validators/index.js +0 -2
  69. package/package.json +26 -20
  70. package/src/app/AddOnFactory.ts +164 -4
  71. package/src/app/{AddOnManager.ts → PackageManager.ts} +4 -6
  72. package/src/app/TemplateSelector.ts +157 -5
  73. package/src/app/index.ts +1 -3
  74. package/src/commands/create.ts +24 -48
  75. package/src/config/inversify.config.ts +11 -9
  76. package/src/config/inversify.types.ts +7 -1
  77. package/src/constants.ts +2 -2
  78. package/src/index.ts +25 -0
  79. package/src/models/CLIOptions.ts +5 -5
  80. package/src/test/app/{WxpAddOnFactory.spec.ts → AddOnFactory.spec.ts} +18 -17
  81. package/src/test/app/{AddOnManager.spec.ts → PackageManager.spec.ts} +6 -6
  82. package/src/test/app/{AddOnTemplateSelector.spec.ts → TemplateSelector.spec.ts} +57 -26
  83. package/src/test/commands/command.spec.ts +80 -0
  84. package/src/test/commands/create.spec.ts +44 -18
  85. package/src/test/models/CLIOptions.spec.ts +4 -4
  86. package/src/test/validators/{AddOnDirectoryValidator.spec.ts → DirectoryValidator.spec.ts} +29 -21
  87. package/src/test/validators/{NodeEnvironmentValidator.spec.ts → EnvironmentValidator.spec.ts} +11 -24
  88. package/src/validators/DirectoryValidator.ts +172 -11
  89. package/src/validators/EnvironmentValidator.ts +157 -5
  90. package/src/validators/index.ts +0 -2
  91. package/templates/react-javascript/template/src/components/App.jsx +2 -2
  92. package/templates/react-javascript/template/webpack.config.js +1 -0
  93. package/templates/react-javascript/template.json +4 -4
  94. package/templates/react-javascript-with-document-sandbox/template/src/ui/components/App.jsx +2 -2
  95. package/templates/react-javascript-with-document-sandbox/template/webpack.config.js +1 -0
  96. package/templates/react-javascript-with-document-sandbox/template.json +4 -4
  97. package/templates/react-typescript/template/src/components/App.tsx +2 -2
  98. package/templates/react-typescript/template/webpack.config.js +1 -0
  99. package/templates/react-typescript/template.json +4 -4
  100. package/templates/react-typescript-with-document-sandbox/template/src/ui/components/App.tsx +2 -2
  101. package/templates/react-typescript-with-document-sandbox/template/webpack.config.js +1 -0
  102. package/templates/react-typescript-with-document-sandbox/template.json +4 -4
  103. package/templates/swc-javascript/template/src/components/App.js +2 -2
  104. package/templates/swc-javascript/template/webpack.config.js +1 -0
  105. package/templates/swc-javascript/template.json +4 -4
  106. package/templates/swc-javascript-with-document-sandbox/template/src/ui/components/App.js +2 -2
  107. package/templates/swc-javascript-with-document-sandbox/template/webpack.config.js +1 -0
  108. package/templates/swc-javascript-with-document-sandbox/template.json +4 -4
  109. package/templates/swc-typescript/template/src/components/App.css.ts +2 -2
  110. package/templates/swc-typescript/template/src/components/App.ts +4 -4
  111. package/templates/swc-typescript/template/src/index.ts +2 -2
  112. package/templates/swc-typescript/template/webpack.config.js +1 -0
  113. package/templates/swc-typescript/template.json +4 -4
  114. package/templates/swc-typescript-with-document-sandbox/template/src/ui/components/App.css.ts +2 -2
  115. package/templates/swc-typescript-with-document-sandbox/template/src/ui/components/App.ts +4 -4
  116. package/templates/swc-typescript-with-document-sandbox/template/src/ui/index.ts +2 -2
  117. package/templates/swc-typescript-with-document-sandbox/template/webpack.config.js +1 -0
  118. package/templates/swc-typescript-with-document-sandbox/template.json +4 -4
  119. package/tsconfig.json +3 -1
  120. package/dist/app/AddOnManager.d.ts.map +0 -1
  121. package/dist/app/AddOnTemplateSelector.d.ts +0 -54
  122. package/dist/app/AddOnTemplateSelector.d.ts.map +0 -1
  123. package/dist/app/AddOnTemplateSelector.js +0 -168
  124. package/dist/app/WxpAddOnFactory.d.ts +0 -62
  125. package/dist/app/WxpAddOnFactory.d.ts.map +0 -1
  126. package/dist/app/WxpAddOnFactory.js +0 -159
  127. package/dist/validators/AddOnDirectoryValidator.d.ts +0 -55
  128. package/dist/validators/AddOnDirectoryValidator.d.ts.map +0 -1
  129. package/dist/validators/AddOnDirectoryValidator.js +0 -176
  130. package/dist/validators/NodeEnvironmentValidator.d.ts +0 -58
  131. package/dist/validators/NodeEnvironmentValidator.d.ts.map +0 -1
  132. package/dist/validators/NodeEnvironmentValidator.js +0 -173
  133. package/src/app/AddOnTemplateSelector.ts +0 -193
  134. package/src/app/WxpAddOnFactory.ts +0 -196
  135. package/src/validators/AddOnDirectoryValidator.ts +0 -207
  136. package/src/validators/NodeEnvironmentValidator.ts +0 -197
@@ -34,12 +34,11 @@ import sinon from "sinon";
34
34
  import type { StubbedInstance } from "ts-sinon";
35
35
  import { stubInterface } from "ts-sinon";
36
36
  import { AnalyticsErrorMarkers } from "../../AnalyticsMarkers.js";
37
- import { AddOnTemplateSelector } from "../../app/AddOnTemplateSelector.js";
38
- import type { TemplateSelector } from "../../app/TemplateSelector.js";
37
+ import { TemplateSelector } from "../../app/TemplateSelector.js";
39
38
  import { ADD_ON_TEMPLATES, PROGRAM_NAME, WITH_DOCUMENT_SANDBOX } from "../../constants.js";
40
- import { CLIOptions } from "../../models/index.js";
39
+ import { CLIOptions } from "../../models/CLIOptions.js";
41
40
 
42
- describe("AddOnTemplateSelector", () => {
41
+ describe("TemplateSelector", () => {
43
42
  let sandbox: SinonSandbox;
44
43
 
45
44
  let logger: StubbedInstance<Logger>;
@@ -70,21 +69,30 @@ describe("AddOnTemplateSelector", () => {
70
69
  sandbox.restore();
71
70
  });
72
71
 
73
- it("should return error if the Add-on kind is not valid.", async () => {
72
+ it("should return error if the Add-on entrypoint is not valid.", async () => {
74
73
  const processExitStub = sandbox.stub(process, "exit");
75
- const options = new CLIOptions("test-add-on-kind" as EntrypointType, "test-add-on", templateName, false);
74
+ const options = new CLIOptions(
75
+ "test-add-on-entrypoint" as EntrypointType,
76
+ "test-add-on",
77
+ templateName,
78
+ false
79
+ );
76
80
 
77
- const templateSelector: TemplateSelector = new AddOnTemplateSelector(logger, analyticsService);
81
+ const templateSelector: TemplateSelector = new TemplateSelector(logger, analyticsService);
78
82
 
79
83
  await templateSelector.setupTemplate(options);
80
84
 
81
85
  assert.equal(logger.warning.callCount, 2);
82
86
  assert.equal(
83
- logger.warning.getCall(0).calledWith("Please choose a valid Add-on kind (valid kind: panel)"),
87
+ logger.warning
88
+ .getCall(0)
89
+ .calledWith("Please choose a valid Add-on entrypoint (valid entrypoint: panel)"),
84
90
  true
85
91
  );
86
92
  assert.equal(
87
- logger.warning.getCall(1).calledWith(`${PROGRAM_NAME} <add-on-name> --kind <panel>`, { prefix: " " }),
93
+ logger.warning
94
+ .getCall(1)
95
+ .calledWith(`${PROGRAM_NAME} <add-on-name> --entrypoint <panel>`, { prefix: " " }),
88
96
  true
89
97
  );
90
98
 
@@ -93,7 +101,7 @@ describe("AddOnTemplateSelector", () => {
93
101
 
94
102
  assert.equal(logger.information.callCount, 1);
95
103
  assert.equal(
96
- logger.information.calledWith(`${PROGRAM_NAME} my-add-on --kind panel`, {
104
+ logger.information.calledWith(`${PROGRAM_NAME} my-add-on --entrypoint panel`, {
97
105
  prefix: " "
98
106
  }),
99
107
  true
@@ -102,28 +110,37 @@ describe("AddOnTemplateSelector", () => {
102
110
  assert.equal(
103
111
  analyticsService.postEvent.calledWith(
104
112
  AnalyticsErrorMarkers.ERROR_INVALID_KIND,
105
- "Invalid Add-on kind specified"
113
+ "Invalid Add-on entrypoint specified"
106
114
  ),
107
115
  true
108
116
  );
109
117
  assert.equal(processExitStub.calledWith(0), true);
110
118
  });
111
119
 
112
- it("should return error if the app kind is not valid.", async () => {
120
+ it("should return error if the app entrypoint is not valid.", async () => {
113
121
  const processExitStub = sandbox.stub(process, "exit");
114
122
 
115
- const cliOptions = new CLIOptions("test-add-on-kind" as EntrypointType, "test-add-on", templateName, false);
123
+ const cliOptions = new CLIOptions(
124
+ "test-add-on-entrypoint" as EntrypointType,
125
+ "test-add-on",
126
+ templateName,
127
+ false
128
+ );
116
129
 
117
- const templateSelector: TemplateSelector = new AddOnTemplateSelector(logger, analyticsService);
130
+ const templateSelector: TemplateSelector = new TemplateSelector(logger, analyticsService);
118
131
  await templateSelector.setupTemplate(cliOptions);
119
132
 
120
133
  assert.equal(logger.warning.callCount, 2);
121
134
  assert.equal(
122
- logger.warning.getCall(0).calledWith("Please choose a valid Add-on kind (valid kind: panel)"),
135
+ logger.warning
136
+ .getCall(0)
137
+ .calledWith("Please choose a valid Add-on entrypoint (valid entrypoint: panel)"),
123
138
  true
124
139
  );
125
140
  assert.equal(
126
- logger.warning.getCall(1).calledWith(`${PROGRAM_NAME} <add-on-name> --kind <panel>`, { prefix: " " }),
141
+ logger.warning
142
+ .getCall(1)
143
+ .calledWith(`${PROGRAM_NAME} <add-on-name> --entrypoint <panel>`, { prefix: " " }),
127
144
  true
128
145
  );
129
146
 
@@ -132,7 +149,7 @@ describe("AddOnTemplateSelector", () => {
132
149
 
133
150
  assert.equal(logger.information.callCount, 1);
134
151
  assert.equal(
135
- logger.information.calledWith(`${PROGRAM_NAME} my-add-on --kind panel`, {
152
+ logger.information.calledWith(`${PROGRAM_NAME} my-add-on --entrypoint panel`, {
136
153
  prefix: " "
137
154
  }),
138
155
  true
@@ -141,7 +158,7 @@ describe("AddOnTemplateSelector", () => {
141
158
  assert.equal(
142
159
  analyticsService.postEvent.calledWith(
143
160
  AnalyticsErrorMarkers.ERROR_INVALID_KIND,
144
- "Invalid Add-on kind specified"
161
+ "Invalid Add-on entrypoint specified"
145
162
  ),
146
163
  true
147
164
  );
@@ -151,7 +168,7 @@ describe("AddOnTemplateSelector", () => {
151
168
  it("should return the passed template name if present in CLIOptions and is a valid one.", async () => {
152
169
  const cliOptions = new CLIOptions(EntrypointType.PANEL, "test-app", templateName, false);
153
170
 
154
- const templateSelector: TemplateSelector = new AddOnTemplateSelector(logger, analyticsService);
171
+ const templateSelector: TemplateSelector = new TemplateSelector(logger, analyticsService);
155
172
  const template = await templateSelector.setupTemplate(cliOptions);
156
173
 
157
174
  assert.equal(analyticsService.postEvent.callCount, 0);
@@ -178,7 +195,7 @@ describe("AddOnTemplateSelector", () => {
178
195
 
179
196
  const cliOptions = new CLIOptions(EntrypointType.PANEL, "test-app", "incorrect-template", false);
180
197
 
181
- const templateSelector: TemplateSelector = new AddOnTemplateSelector(logger, analyticsService);
198
+ const templateSelector: TemplateSelector = new TemplateSelector(logger, analyticsService);
182
199
  const template = await templateSelector.setupTemplate(cliOptions);
183
200
 
184
201
  assert.equal(template, templateChoices[1].value);
@@ -206,7 +223,7 @@ describe("AddOnTemplateSelector", () => {
206
223
  });
207
224
 
208
225
  const cliOptions = new CLIOptions(EntrypointType.PANEL, "test-app", "", false);
209
- const templateSelector: TemplateSelector = new AddOnTemplateSelector(logger, analyticsService);
226
+ const templateSelector: TemplateSelector = new TemplateSelector(logger, analyticsService);
210
227
  const template = await templateSelector.setupTemplate(cliOptions);
211
228
 
212
229
  assert.equal(logger.warning.callCount, 0);
@@ -234,7 +251,7 @@ describe("AddOnTemplateSelector", () => {
234
251
 
235
252
  const cliOptions = new CLIOptions(EntrypointType.PANEL, "test-app", "", false);
236
253
 
237
- const templateSelector: TemplateSelector = new AddOnTemplateSelector(logger, analyticsService);
254
+ const templateSelector: TemplateSelector = new TemplateSelector(logger, analyticsService);
238
255
  const template = await templateSelector.setupTemplate(cliOptions);
239
256
 
240
257
  assert.equal(logger.warning.callCount, 0);
@@ -242,14 +259,28 @@ describe("AddOnTemplateSelector", () => {
242
259
  assert.equal(analyticsService.postEvent.callCount, 0);
243
260
  });
244
261
 
245
- it("should exit if user doesnt select any prompted value and template is not passed.", async () => {
262
+ it("should return the custom template if the variant is not available.", async () => {
263
+ const customTemplate = "custom-template";
264
+ const promptsStub = sandbox.stub(prompts, "prompt");
265
+ promptsStub.resolves({ selectedTemplate: customTemplate });
266
+
267
+ const cliOptions = new CLIOptions(EntrypointType.PANEL, "test-app", "", false);
268
+ const templateSelector: TemplateSelector = new TemplateSelector(logger, analyticsService);
269
+ const template = await templateSelector.setupTemplate(cliOptions);
270
+
271
+ assert.equal(template, customTemplate);
272
+ assert.equal(logger.warning.callCount, 0);
273
+ assert.equal(analyticsService.postEvent.callCount, 0);
274
+ });
275
+
276
+ it("should exit if user does not select any prompted value and template is not passed.", async () => {
246
277
  const promptsStub = sandbox.stub(prompts, "prompt");
247
278
  const exitProcessStub = sandbox.stub(process, "exit");
248
279
  promptsStub.resolves({ selectedTemplate: undefined });
249
280
 
250
281
  const cliOptions = new CLIOptions(EntrypointType.PANEL, "test-app", "", false);
251
282
 
252
- const templateSelector: TemplateSelector = new AddOnTemplateSelector(logger, analyticsService);
283
+ const templateSelector: TemplateSelector = new TemplateSelector(logger, analyticsService);
253
284
  await templateSelector.setupTemplate(cliOptions);
254
285
 
255
286
  assert.equal(logger.warning.callCount, 0);
@@ -257,14 +288,14 @@ describe("AddOnTemplateSelector", () => {
257
288
  assert.equal(analyticsService.postEvent.callCount, 0);
258
289
  });
259
290
 
260
- it("should exit if user doesnt select any option in document sandbox prompt.", async () => {
291
+ it("should exit if user does not select any option in document sandbox prompt.", async () => {
261
292
  const promptsStub = sandbox.stub(prompts, "prompt");
262
293
  const exitProcessStub = sandbox.stub(process, "exit");
263
294
  promptsStub.resolves({ selectedTemplate: templateChoices[1].value, includeDocumentSandbox: undefined });
264
295
 
265
296
  const cliOptions = new CLIOptions(EntrypointType.PANEL, "test-app", "", false);
266
297
 
267
- const templateSelector: TemplateSelector = new AddOnTemplateSelector(logger, analyticsService);
298
+ const templateSelector: TemplateSelector = new TemplateSelector(logger, analyticsService);
268
299
  await templateSelector.setupTemplate(cliOptions);
269
300
 
270
301
  assert.equal(logger.warning.callCount, 0);
@@ -0,0 +1,80 @@
1
+ /********************************************************************************
2
+ * MIT License
3
+
4
+ * © Copyright 2025 Adobe. All rights reserved.
5
+
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in all
14
+ * copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ * SOFTWARE.
23
+ ********************************************************************************/
24
+
25
+ import type { AnalyticsConsent, AnalyticsService } from "@adobe/ccweb-add-on-analytics";
26
+ import { ITypes as IAnalyticsTypes } from "@adobe/ccweb-add-on-analytics";
27
+ import { EntrypointType } from "@adobe/ccweb-add-on-manifest";
28
+ import { runCommand } from "@oclif/test";
29
+ import { assert } from "chai";
30
+ import "mocha";
31
+ import sinon from "sinon";
32
+ import type { StubbedInstance } from "ts-sinon";
33
+ import { stubInterface } from "ts-sinon";
34
+ import type { AddOnFactory } from "../../app/AddOnFactory.js";
35
+ import { IContainer, ITypes } from "../../config/index.js";
36
+ import { CLIOptions } from "../../models/CLIOptions.js";
37
+
38
+ describe("create-ccweb-add-on", () => {
39
+ let sandbox: sinon.SinonSandbox;
40
+
41
+ let container: sinon.SinonStub;
42
+
43
+ let addOnFactory: StubbedInstance<AddOnFactory>;
44
+
45
+ let analyticsConsent: StubbedInstance<AnalyticsConsent>;
46
+ let analyticsService: StubbedInstance<AnalyticsService>;
47
+
48
+ beforeEach(() => {
49
+ sandbox = sinon.createSandbox();
50
+
51
+ addOnFactory = stubInterface();
52
+ addOnFactory.create.resolves();
53
+
54
+ analyticsConsent = stubInterface();
55
+ analyticsService = stubInterface();
56
+
57
+ container = sandbox.stub(IContainer, "get");
58
+ container.withArgs(ITypes.AddOnFactory).returns(addOnFactory);
59
+
60
+ container.withArgs(IAnalyticsTypes.AnalyticsConsent).returns(analyticsConsent);
61
+ container.withArgs(IAnalyticsTypes.AnalyticsService).returns(analyticsService);
62
+ });
63
+
64
+ afterEach(() => {
65
+ sandbox.restore();
66
+ });
67
+
68
+ describe("create", () => {
69
+ it("should execute succesfully when correct parameters are passed.", async () => {
70
+ analyticsConsent.set.resolves();
71
+
72
+ await runCommand(["hello-world", "--entrypoint=panel", "--template=react-javascript"], {
73
+ root: "."
74
+ });
75
+
76
+ const options = new CLIOptions(EntrypointType.PANEL, "hello-world", "react-javascript", false);
77
+ assert.equal(addOnFactory.create.calledOnceWith(options), true);
78
+ });
79
+ });
80
+ });
@@ -25,6 +25,7 @@
25
25
  import type { AnalyticsConsent, AnalyticsService } from "@adobe/ccweb-add-on-analytics";
26
26
  import { ITypes as IAnalyticsTypes } from "@adobe/ccweb-add-on-analytics";
27
27
  import { EntrypointType } from "@adobe/ccweb-add-on-manifest";
28
+ import { PROGRAM_NAME } from "@adobe/ccweb-add-on-scaffolder";
28
29
  import { Config } from "@oclif/core";
29
30
  import chai, { assert, expect } from "chai";
30
31
  import chaiAsPromised from "chai-as-promised";
@@ -33,14 +34,14 @@ import sinon from "sinon";
33
34
  import type { StubbedInstance } from "ts-sinon";
34
35
  import { stubInterface } from "ts-sinon";
35
36
  import { AnalyticsErrorMarkers } from "../../AnalyticsMarkers.js";
36
- import type { AddOnFactory } from "../../app/index.js";
37
- import { CreateCCWebAddOn } from "../../commands/create.js";
37
+ import type { AddOnFactory } from "../../app/AddOnFactory.js";
38
+ import { Create } from "../../commands/create.js";
38
39
  import { IContainer, ITypes } from "../../config/index.js";
39
- import { CLIOptions } from "../../models/index.js";
40
+ import { CLIOptions } from "../../models/CLIOptions.js";
40
41
 
41
42
  chai.use(chaiAsPromised);
42
43
 
43
- describe("CreateCCWebAddOn", () => {
44
+ describe("Create", () => {
44
45
  let sandbox: sinon.SinonSandbox;
45
46
 
46
47
  let container: sinon.SinonStub;
@@ -52,6 +53,7 @@ describe("CreateCCWebAddOn", () => {
52
53
 
53
54
  beforeEach(() => {
54
55
  sandbox = sinon.createSandbox();
56
+ sandbox.stub(console, "log");
55
57
 
56
58
  addOnFactory = stubInterface();
57
59
  addOnFactory.create.resolves();
@@ -74,12 +76,24 @@ describe("CreateCCWebAddOn", () => {
74
76
  it("should execute succesfully when correct parameters are passed without analytics.", async () => {
75
77
  analyticsConsent.get.resolves(true);
76
78
 
77
- const createCCWebAddOn = new CreateCCWebAddOn(
78
- ["hello-world", "--kind=panel", "--template=react-javascript", "--verbose"],
79
- new Config({ root: "." })
79
+ const create = new Create(
80
+ ["hello-world", "--entrypoint=panel", "--template=react-javascript", "--verbose"],
81
+ new Config({ name: PROGRAM_NAME, version: "1.0.0", root: "." })
80
82
  );
81
-
82
- await createCCWebAddOn.run();
83
+ sandbox
84
+ // @ts-ignore - Sidestep `this.parse()` error when calling `run()` directly.
85
+ .stub(create, "parse")
86
+ .resolves({
87
+ args: { name: "hello-world" },
88
+ flags: {
89
+ entrypoint: EntrypointType.PANEL,
90
+ template: "react-javascript",
91
+ analytics: undefined,
92
+ verbose: true
93
+ }
94
+ });
95
+
96
+ await create.run();
83
97
 
84
98
  assert.equal(analyticsConsent.get.callCount, 1);
85
99
 
@@ -91,12 +105,24 @@ describe("CreateCCWebAddOn", () => {
91
105
  analyticsConsent.get.resolves(true);
92
106
  analyticsConsent.set.withArgs(false).resolves();
93
107
 
94
- const createCCWebAddOn = new CreateCCWebAddOn(
95
- ["hello-world", "--kind=panel", "--template=react-javascript", "--analytics=off", "--verbose"],
96
- new Config({ root: "." })
108
+ const create = new Create(
109
+ ["hello-world", "--entrypoint=panel", "--template=react-javascript", "--analytics=off", "--verbose"],
110
+ new Config({ name: PROGRAM_NAME, version: "1.0.0", root: "." })
97
111
  );
98
-
99
- await createCCWebAddOn.run();
112
+ sandbox
113
+ // @ts-ignore - Sidestep `this.parse()` error when calling `run()` directly.
114
+ .stub(create, "parse")
115
+ .resolves({
116
+ args: { name: "hello-world" },
117
+ flags: {
118
+ entrypoint: EntrypointType.PANEL,
119
+ template: "react-javascript",
120
+ analytics: "off",
121
+ verbose: true
122
+ }
123
+ });
124
+
125
+ await create.run();
100
126
 
101
127
  assert.equal(analyticsConsent.set.calledOnceWith(false), true);
102
128
 
@@ -106,11 +132,11 @@ describe("CreateCCWebAddOn", () => {
106
132
  });
107
133
 
108
134
  describe("catch", () => {
109
- it("should fail when incorrect parameters are passed.", async () => {
110
- const createCCWebAddOn = new CreateCCWebAddOn(["--incorrect-flag"], new Config({ root: "." }));
135
+ it("should fail for any errors in command execution.", async () => {
136
+ const create = new Create([], new Config({ name: PROGRAM_NAME, version: "1.0.0", root: "." }));
111
137
 
112
- const error = new Error("Nonexistent flag: --incorrect-flag\nSee more help with --help");
113
- await expect(createCCWebAddOn.catch(error)).to.be.rejectedWith();
138
+ const error = new Error("Something went wrong.");
139
+ await expect(create.catch(error)).to.be.rejectedWith(error);
114
140
 
115
141
  assert.equal(
116
142
  analyticsService.postEvent.calledOnceWith(
@@ -25,19 +25,19 @@
25
25
  import { EntrypointType } from "@adobe/ccweb-add-on-manifest";
26
26
  import { assert } from "chai";
27
27
  import "mocha";
28
- import { CLIOptions } from "../../models/index.js";
28
+ import { CLIOptions } from "../../models/CLIOptions.js";
29
29
 
30
30
  describe("CLIOptions", () => {
31
31
  describe("constructor", () => {
32
32
  it("should create a new instance of CLIOptions.", () => {
33
- const addOnKind = EntrypointType.PANEL;
33
+ const entrypointType = EntrypointType.PANEL;
34
34
  const addOnName = "test-app";
35
35
  const templateName = "javascript";
36
36
  const verbose = false;
37
37
 
38
- const cliOptions = new CLIOptions(addOnKind as EntrypointType, addOnName, templateName, verbose);
38
+ const cliOptions = new CLIOptions(entrypointType as EntrypointType, addOnName, templateName, verbose);
39
39
 
40
- assert.equal(cliOptions.addOnKind, addOnKind);
40
+ assert.equal(cliOptions.entrypointType, entrypointType);
41
41
  assert.equal(cliOptions.addOnName, addOnName);
42
42
  assert.equal(cliOptions.templateName, templateName);
43
43
  assert.equal(cliOptions.verbose, verbose);
@@ -37,10 +37,9 @@ import { stubInterface } from "ts-sinon";
37
37
  import { AnalyticsErrorMarkers } from "../../AnalyticsMarkers.js";
38
38
  import { PROGRAM_NAME } from "../../constants.js";
39
39
  import { CLIOptions } from "../../models/CLIOptions.js";
40
- import type { DirectoryValidator } from "../../validators/index.js";
41
- import { AddOnDirectoryValidator } from "../../validators/index.js";
40
+ import { DirectoryValidator } from "../../validators/DirectoryValidator.js";
42
41
 
43
- describe("AddOnDirectoryValidator", () => {
42
+ describe("DirectoryValidator", () => {
44
43
  let sandbox: SinonSandbox;
45
44
 
46
45
  let analyticsService: StubbedInstance<AnalyticsService>;
@@ -54,7 +53,7 @@ describe("AddOnDirectoryValidator", () => {
54
53
  analyticsService = stubInterface<AnalyticsService>();
55
54
  logger = stubInterface<Logger>();
56
55
 
57
- validator = new AddOnDirectoryValidator(logger, analyticsService);
56
+ validator = new DirectoryValidator(logger, analyticsService);
58
57
  });
59
58
 
60
59
  afterEach(() => {
@@ -65,7 +64,7 @@ describe("AddOnDirectoryValidator", () => {
65
64
  let runs = [{ addOnName: "" }, { addOnName: " " }];
66
65
  runs.forEach(run => {
67
66
  it(`should exit for empty addOn name: ${run.addOnName}.`, async () => {
68
- const validator: DirectoryValidator = new AddOnDirectoryValidator(logger, analyticsService);
67
+ const validator: DirectoryValidator = new DirectoryValidator(logger, analyticsService);
69
68
  const processExitStub = sandbox.stub(process, "exit");
70
69
 
71
70
  await validator.validateAddOnName(run.addOnName);
@@ -76,7 +75,7 @@ describe("AddOnDirectoryValidator", () => {
76
75
  assert.equal(
77
76
  logger.warning
78
77
  .getCall(1)
79
- .calledWith(`${PROGRAM_NAME} <add-on-name> --kind <panel> --template <javascript>`, {
78
+ .calledWith(`${PROGRAM_NAME} <add-on-name> --entrypoint <panel> --template <javascript>`, {
80
79
  prefix: " "
81
80
  }),
82
81
  true
@@ -92,10 +91,13 @@ describe("AddOnDirectoryValidator", () => {
92
91
 
93
92
  assert.equal(logger.information.callCount, 1);
94
93
  assert.equal(
95
- logger.information.calledWith(`${PROGRAM_NAME} my-add-on --kind panel --template javascript`, {
96
- prefix: " ",
97
- postfix: "\n"
98
- }),
94
+ logger.information.calledWith(
95
+ `${PROGRAM_NAME} my-add-on --entrypoint panel --template javascript`,
96
+ {
97
+ prefix: " ",
98
+ postfix: "\n"
99
+ }
100
+ ),
99
101
  true
100
102
  );
101
103
  assert.equal(analyticsService.postEvent.callCount, 1);
@@ -130,7 +132,7 @@ describe("AddOnDirectoryValidator", () => {
130
132
  assert.equal(
131
133
  logger.warning
132
134
  .getCall(1)
133
- .calledWith(`${PROGRAM_NAME} <add-on-name> --kind <panel> --template <javascript>`, {
135
+ .calledWith(`${PROGRAM_NAME} <add-on-name> --entrypoint <panel> --template <javascript>`, {
134
136
  prefix: " "
135
137
  }),
136
138
  true
@@ -146,10 +148,13 @@ describe("AddOnDirectoryValidator", () => {
146
148
 
147
149
  assert.equal(logger.information.callCount, 1);
148
150
  assert.equal(
149
- logger.information.calledWith(`${PROGRAM_NAME} my-add-on --kind panel --template javascript`, {
150
- prefix: " ",
151
- postfix: "\n"
152
- }),
151
+ logger.information.calledWith(
152
+ `${PROGRAM_NAME} my-add-on --entrypoint panel --template javascript`,
153
+ {
154
+ prefix: " ",
155
+ postfix: "\n"
156
+ }
157
+ ),
153
158
  true
154
159
  );
155
160
  assert.equal(analyticsService.postEvent.callCount, 1);
@@ -191,7 +196,7 @@ describe("AddOnDirectoryValidator", () => {
191
196
  assert.equal(
192
197
  logger.warning
193
198
  .getCall(1)
194
- .calledWith(`${PROGRAM_NAME} <add-on-name> --kind <panel> --template <javascript>`, {
199
+ .calledWith(`${PROGRAM_NAME} <add-on-name> --entrypoint <panel> --template <javascript>`, {
195
200
  prefix: " "
196
201
  }),
197
202
  true
@@ -207,10 +212,13 @@ describe("AddOnDirectoryValidator", () => {
207
212
 
208
213
  assert.equal(logger.information.callCount, 1);
209
214
  assert.equal(
210
- logger.information.calledWith(`${PROGRAM_NAME} my-add-on --kind panel --template javascript`, {
211
- prefix: " ",
212
- postfix: "\n"
213
- }),
215
+ logger.information.calledWith(
216
+ `${PROGRAM_NAME} my-add-on --entrypoint panel --template javascript`,
217
+ {
218
+ prefix: " ",
219
+ postfix: "\n"
220
+ }
221
+ ),
214
222
  true
215
223
  );
216
224
  assert.equal(analyticsService.postEvent.callCount, 1);
@@ -230,7 +238,7 @@ describe("AddOnDirectoryValidator", () => {
230
238
 
231
239
  analyticsService.postEvent.resolves();
232
240
 
233
- const validator: DirectoryValidator = new AddOnDirectoryValidator(logger, analyticsService);
241
+ const validator: DirectoryValidator = new DirectoryValidator(logger, analyticsService);
234
242
 
235
243
  const cliOptions = new CLIOptions(EntrypointType.PANEL, "test-add-on", "javascript", false);
236
244
  await validator.validateAddOnName(cliOptions.addOnName);
@@ -33,10 +33,9 @@ import type { StubbedInstance } from "ts-sinon";
33
33
  import { stubInterface } from "ts-sinon";
34
34
  import { AnalyticsErrorMarkers } from "../../AnalyticsMarkers.js";
35
35
  import { PROGRAM_NAME } from "../../constants.js";
36
- import type { EnvironmentValidator } from "../../validators/index.js";
37
- import { NodeEnvironmentValidator } from "../../validators/index.js";
36
+ import { EnvironmentValidator } from "../../validators/EnvironmentValidator.js";
38
37
 
39
- describe("NodeEnvironmentValidator", () => {
38
+ describe("EnvironmentValidator", () => {
40
39
  let sandbox: SinonSandbox;
41
40
 
42
41
  let cliProcess: StubbedInstance<Process>;
@@ -55,7 +54,7 @@ describe("NodeEnvironmentValidator", () => {
55
54
 
56
55
  logger = stubInterface();
57
56
 
58
- validator = new NodeEnvironmentValidator(cliProcess, logger, analyticsService);
57
+ validator = new EnvironmentValidator(cliProcess, logger, analyticsService);
59
58
  });
60
59
 
61
60
  afterEach(() => {
@@ -63,14 +62,10 @@ describe("NodeEnvironmentValidator", () => {
63
62
  });
64
63
 
65
64
  describe("validateNodeVersion", () => {
66
- const runs = [{ version: "10.0.0" }, { version: "15.9.9" }];
65
+ const runs = [{ version: "10.0.0" }, { version: "17.9.9" }];
67
66
  runs.forEach(({ version }) => {
68
67
  it(`should exit for lower node version: ${version}.`, async () => {
69
- const validator: EnvironmentValidator = new NodeEnvironmentValidator(
70
- cliProcess,
71
- logger,
72
- analyticsService
73
- );
68
+ const validator: EnvironmentValidator = new EnvironmentValidator(cliProcess, logger, analyticsService);
74
69
  const processExitStub = sandbox.stub(process, "exit");
75
70
 
76
71
  cliProcess.executeSync
@@ -84,7 +79,7 @@ describe("NodeEnvironmentValidator", () => {
84
79
 
85
80
  assert.equal(logger.information.callCount, 2);
86
81
  assert.equal(
87
- logger.information.getCall(0).calledWith(`${PROGRAM_NAME} requires node 16.0.0 or higher.`),
82
+ logger.information.getCall(0).calledWith(`${PROGRAM_NAME} requires node 18.0.0 or higher.`),
88
83
  true
89
84
  );
90
85
  assert.equal(logger.information.getCall(1).calledWith("Please update your version of node."), true);
@@ -116,11 +111,7 @@ describe("NodeEnvironmentValidator", () => {
116
111
  const dataList = [{ data: undefined }, { data: "" }];
117
112
  dataList.forEach(({ data }) => {
118
113
  it("should exit for no npm version.", async () => {
119
- const validator: EnvironmentValidator = new NodeEnvironmentValidator(
120
- cliProcess,
121
- logger,
122
- analyticsService
123
- );
114
+ const validator: EnvironmentValidator = new EnvironmentValidator(cliProcess, logger, analyticsService);
124
115
  const processExitStub = sandbox.stub(process, "exit");
125
116
 
126
117
  cliProcess.executeSync
@@ -134,7 +125,7 @@ describe("NodeEnvironmentValidator", () => {
134
125
 
135
126
  assert.equal(logger.information.callCount, 2);
136
127
  assert.equal(
137
- logger.information.getCall(0).calledWith(`${PROGRAM_NAME} requires npm 8.0.0 or higher.`),
128
+ logger.information.getCall(0).calledWith(`${PROGRAM_NAME} requires npm 10.0.0 or higher.`),
138
129
  true
139
130
  );
140
131
  assert.equal(logger.information.getCall(1).calledWith("Please install npm."), true);
@@ -147,14 +138,10 @@ describe("NodeEnvironmentValidator", () => {
147
138
  });
148
139
  });
149
140
 
150
- const runs = [{ version: "3.0.0" }, { version: "7.9.9" }];
141
+ const runs = [{ version: "3.0.0" }, { version: "9.9.9" }];
151
142
  runs.forEach(run => {
152
143
  it(`should exit for lower npm version: ${run.version}.`, async () => {
153
- const validator: EnvironmentValidator = new NodeEnvironmentValidator(
154
- cliProcess,
155
- logger,
156
- analyticsService
157
- );
144
+ const validator: EnvironmentValidator = new EnvironmentValidator(cliProcess, logger, analyticsService);
158
145
  const processExitStub = sandbox.stub(process, "exit");
159
146
 
160
147
  cliProcess.executeSync
@@ -168,7 +155,7 @@ describe("NodeEnvironmentValidator", () => {
168
155
 
169
156
  assert.equal(logger.information.callCount, 2);
170
157
  assert.equal(
171
- logger.information.getCall(0).calledWith(`${PROGRAM_NAME} requires npm 8.0.0 or higher.`),
158
+ logger.information.getCall(0).calledWith(`${PROGRAM_NAME} requires npm 10.0.0 or higher.`),
172
159
  true
173
160
  );
174
161
  assert.equal(logger.information.getCall(1).calledWith("Please update your version of npm."), true);