@adobe/aio-commerce-lib-app 2.0.0 → 2.0.1-alpha-20260923160203

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 (69) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +4 -0
  3. package/dist/cjs/actions/app-config/index.cjs +3 -3
  4. package/dist/cjs/actions/association/index.cjs +1 -1
  5. package/dist/cjs/actions/config/index.cjs +1 -1
  6. package/dist/cjs/actions/installation/index.cjs +4 -4
  7. package/dist/cjs/actions/scope-tree/index.cjs +4 -3
  8. package/dist/cjs/cli/index.cjs +393 -0
  9. package/dist/cjs/cli/index.d.cts +31 -0
  10. package/dist/cjs/commands/index.cjs +73 -1717
  11. package/dist/cjs/{common-VSsQEHDv.cjs → common-B3KrOG-h.cjs} +1 -1
  12. package/dist/cjs/config/index.node.cjs +3 -3
  13. package/dist/{es/logging-CXesop3u.mjs → cjs/constants-tQUzmimN.cjs} +6 -18
  14. package/dist/cjs/{index.node-vcOo1rt0.cjs → index.node-DwuJfAiP.cjs} +1 -1
  15. package/dist/cjs/{logging-Br3xfBNe.cjs → logging-QTsrSwPc.cjs} +0 -16
  16. package/dist/cjs/management/index.cjs +1 -1
  17. package/dist/cjs/{management-Bki3hlxL.cjs → management-DplOGozL.cjs} +11 -10
  18. package/dist/cjs/{validate-CwWYtRsS.cjs → validate-DkmBVWFX.cjs} +1 -1
  19. package/dist/cjs/web-src-CCzvhSf0.cjs +1515 -0
  20. package/dist/cjs/{webhooks-Bcq2Qy7q.cjs → webhooks-zXjrg32x.cjs} +57 -57
  21. package/dist/es/actions/app-config/index.mjs +3 -3
  22. package/dist/es/actions/association/index.mjs +1 -1
  23. package/dist/es/actions/config/index.mjs +1 -1
  24. package/dist/es/actions/installation/index.mjs +4 -4
  25. package/dist/es/actions/scope-tree/index.mjs +3 -2
  26. package/dist/es/cli/index.d.mts +31 -0
  27. package/dist/es/cli/index.mjs +381 -0
  28. package/dist/es/commands/index.mjs +29 -1666
  29. package/dist/es/{common-dy6NrZt8.mjs → common-BWUDGasu.mjs} +1 -1
  30. package/dist/es/config/index.node.mjs +3 -3
  31. package/dist/es/constants-CSQsZaDP.mjs +25 -0
  32. package/dist/es/{index.node-CW46zuxW.mjs → index.node-DPiidKGS.mjs} +1 -1
  33. package/dist/es/logging-DbJHXSKh.mjs +32 -0
  34. package/dist/es/management/index.mjs +1 -1
  35. package/dist/es/{management-DgwAhaaJ.mjs → management-YDkb15SJ.mjs} +6 -5
  36. package/dist/es/{validate-NzW1FQwL.mjs → validate-Pd7RIA_3.mjs} +1 -1
  37. package/dist/es/web-src-CM_09qwk.mjs +1345 -0
  38. package/dist/es/{webhooks-CHZ1SXxw.mjs → webhooks-BMBfTqwi.mjs} +58 -58
  39. package/package.json +11 -1
  40. /package/dist/cjs/{commands/templates → templates}/admin-ui/tsconfig.json +0 -0
  41. /package/dist/cjs/{commands/templates → templates}/admin-ui/web-src/.babelrc +0 -0
  42. /package/dist/cjs/{commands/templates → templates}/admin-ui/web-src/index.css +0 -0
  43. /package/dist/cjs/{commands/templates → templates}/admin-ui/web-src/index.html +0 -0
  44. /package/dist/cjs/{commands/templates → templates}/admin-ui/web-src/src/app.jsx +0 -0
  45. /package/dist/cjs/{commands/templates → templates}/admin-ui/web-src/src/components/welcome.jsx +0 -0
  46. /package/dist/cjs/{commands/templates → templates}/admin-ui/web-src/src/pages/main-page.jsx +0 -0
  47. /package/dist/cjs/{commands/templates → templates}/admin-ui/web-src-template.d.ts +0 -0
  48. /package/dist/cjs/{commands/templates → templates}/app-management/app-config.js.template +0 -0
  49. /package/dist/cjs/{commands/templates → templates}/app-management/association.js.template +0 -0
  50. /package/dist/cjs/{commands/templates → templates}/app-management/custom-scripts.js.template +0 -0
  51. /package/dist/cjs/{commands/templates → templates}/app-management/installation.js.template +0 -0
  52. /package/dist/cjs/{commands/templates → templates}/business-configuration/config.js.template +0 -0
  53. /package/dist/cjs/{commands/templates → templates}/business-configuration/scope-tree.js.template +0 -0
  54. /package/dist/cjs/{commands/templates → templates}/typescript/webpack-config.cjs +0 -0
  55. /package/dist/es/{commands/templates → templates}/admin-ui/tsconfig.json +0 -0
  56. /package/dist/es/{commands/templates → templates}/admin-ui/web-src/.babelrc +0 -0
  57. /package/dist/es/{commands/templates → templates}/admin-ui/web-src/index.css +0 -0
  58. /package/dist/es/{commands/templates → templates}/admin-ui/web-src/index.html +0 -0
  59. /package/dist/es/{commands/templates → templates}/admin-ui/web-src/src/app.jsx +0 -0
  60. /package/dist/es/{commands/templates → templates}/admin-ui/web-src/src/components/welcome.jsx +0 -0
  61. /package/dist/es/{commands/templates → templates}/admin-ui/web-src/src/pages/main-page.jsx +0 -0
  62. /package/dist/es/{commands/templates → templates}/admin-ui/web-src-template.d.ts +0 -0
  63. /package/dist/es/{commands/templates → templates}/app-management/app-config.js.template +0 -0
  64. /package/dist/es/{commands/templates → templates}/app-management/association.js.template +0 -0
  65. /package/dist/es/{commands/templates → templates}/app-management/custom-scripts.js.template +0 -0
  66. /package/dist/es/{commands/templates → templates}/app-management/installation.js.template +0 -0
  67. /package/dist/es/{commands/templates → templates}/business-configuration/config.js.template +0 -0
  68. /package/dist/es/{commands/templates → templates}/business-configuration/scope-tree.js.template +0 -0
  69. /package/dist/es/{commands/templates → templates}/typescript/webpack-config.cjs +0 -0
@@ -14,1227 +14,20 @@
14
14
  */
15
15
 
16
16
  const require_rolldown_runtime = require('../rolldown-runtime-CDQd2xEI.cjs');
17
+ const require_index_node = require('../index.node-DwuJfAiP.cjs');
18
+ const require_web_src = require('../web-src-CCzvhSf0.cjs');
19
+ const require_webhooks = require('../webhooks-zXjrg32x.cjs');
20
+ const require_logging = require('../logging-QTsrSwPc.cjs');
17
21
  const require_error = require('../error-D-N0PKSl.cjs');
18
- const require_index_node = require('../index.node-vcOo1rt0.cjs');
19
- const require_webhooks = require('../webhooks-Bcq2Qy7q.cjs');
20
- const require_validate = require('../validate-CwWYtRsS.cjs');
21
- const require_common = require('../common-VSsQEHDv.cjs');
22
- const require_logging = require('../logging-Br3xfBNe.cjs');
23
- let _adobe_aio_commerce_lib_config = require("@adobe/aio-commerce-lib-config");
22
+ const require_validate = require('../validate-DkmBVWFX.cjs');
24
23
  let _adobe_aio_commerce_lib_core_error = require("@adobe/aio-commerce-lib-core/error");
25
- let safe_stable_stringify = require("safe-stable-stringify");
26
- let consola = require("consola");
27
- consola = require_rolldown_runtime.__toESM(consola, 1);
28
- let fs = require("fs");
29
24
  let fs_promises = require("fs/promises");
30
25
  let path = require("path");
31
- path = require_rolldown_runtime.__toESM(path, 1);
26
+ let consola = require("consola");
27
+ consola = require_rolldown_runtime.__toESM(consola, 1);
32
28
  let consola_utils = require("consola/utils");
33
- let url = require("url");
34
- let child_process = require("child_process");
35
- let prettier = require("prettier");
36
- prettier = require_rolldown_runtime.__toESM(prettier, 1);
37
- let valibot = require("valibot");
38
- valibot = require_rolldown_runtime.__toESM(valibot, 1);
39
29
  let yaml = require("yaml");
40
- let _adobe_aio_lib_ims = require("@adobe/aio-lib-ims");
41
- _adobe_aio_lib_ims = require_rolldown_runtime.__toESM(_adobe_aio_lib_ims, 1);
42
- let _adobe_aio_lib_core_config = require("@adobe/aio-lib-core-config");
43
- _adobe_aio_lib_core_config = require_rolldown_runtime.__toESM(_adobe_aio_lib_core_config, 1);
44
- let ky = require("ky");
45
- ky = require_rolldown_runtime.__toESM(ky, 1);
46
- let timers_promises = require("timers/promises");
47
- let dotenv = require("dotenv");
48
- dotenv = require_rolldown_runtime.__toESM(dotenv, 1);
49
-
50
- //#region source/commands/constants.ts
51
- /** The name of the package containing all the generated runtime actions */
52
- const PACKAGE_NAME = "app-management";
53
- /** The path to the directory containing the generated files */
54
- const GENERATED_PATH = ".generated";
55
- /** The folder name containing the runtime actions */
56
- const ACTIONS_FOLDER = `actions/${PACKAGE_NAME}`;
57
- /** The path to the directory containing the generated actions */
58
- const GENERATED_ACTIONS_PATH = `${GENERATED_PATH}/${ACTIONS_FOLDER}`;
59
- /** The name of the extension point for extensibility. */
60
- const EXTENSIBILITY_EXTENSION_POINT_ID = "commerce/extensibility/1";
61
- /** The name of the extension point for configuration. */
62
- const CONFIGURATION_EXTENSION_POINT_ID = "commerce/configuration/1";
63
- /** The name of the extension point for Admin UI. */
64
- const BACKEND_UI_V2_EXTENSION_POINT_ID = "commerce/backend-ui/2";
65
- /** The name of the configuration schema file */
66
- const APP_MANIFEST_FILE = "app.commerce.manifest.json";
67
- /** The name of the generated runtime-safe app config module (dynamic schemas only). */
68
- const RUNTIME_APP_CONFIG_FILE = "app.commerce.config.js";
69
- /** Package import alias for the generated runtime-safe app config module. */
70
- const APP_CONFIG_IMPORT_ALIAS = "#app.commerce.config";
71
- /** The name of the commerce app configuration file */
72
- const COMMERCE_APP_CONFIG_FILE = "app.commerce.config";
73
- /** TypeScript development dependencies shared by root and web-src scaffolding. */
74
- const SHARED_TYPESCRIPT_DEV_DEPENDENCIES = [{
75
- name: "@tsconfig/bases",
76
- version: "^1.0.26"
77
- }, {
78
- name: "typescript",
79
- version: "^6.0.3"
80
- }];
81
- /** Node.js type definitions required only by root Runtime action scaffolding. */
82
- const TYPESCRIPT_NODE_DEV_DEPENDENCY = {
83
- name: "@types/node",
84
- version: "^24.12.0"
85
- };
86
- /** TypeScript loader required only by root Runtime action scaffolding. */
87
- const TYPESCRIPT_WEBPACK_DEV_DEPENDENCY = {
88
- name: "ts-loader",
89
- version: "^9.6.2"
90
- };
91
- /** The name of the configuration schema file */
92
- const CONFIG_SCHEMA_FILE_NAME = "configuration-schema.json";
93
- /** The name of the project package file */
94
- const PACKAGE_JSON_FILE = "package.json";
95
- /** The name of the app configuration file */
96
- const APP_CONFIG_FILE = "app.config.yaml";
97
- /** The name of the install configuration file */
98
- const INSTALL_YAML_FILE = "install.yaml";
99
- /** Get the path to the extension point folder */
100
- function getExtensionPointFolderPath(extensionPointId) {
101
- return `src/${extensionPointId.replaceAll("/", "-")}`;
102
- }
103
-
104
- //#endregion
105
- //#region source/commands/generate/actions/constants.ts
106
- const __filename$1 = (0, url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
107
- const __dirname$1 = (0, path.dirname)(__filename$1);
108
- /** The path to the action templates directory, sibling to this file. */
109
- const TEMPLATES_DIR = (0, path.join)(__dirname$1, "templates");
110
- /** The list of Commerce variables that are required for the runtime actions. */
111
- const COMMERCE_VARIABLES = [
112
- "AIO_COMMERCE_AUTH_IMS_CLIENT_ID",
113
- "AIO_COMMERCE_AUTH_IMS_CLIENT_SECRETS",
114
- "AIO_COMMERCE_AUTH_IMS_TECHNICAL_ACCOUNT_ID",
115
- "AIO_COMMERCE_AUTH_IMS_TECHNICAL_ACCOUNT_EMAIL",
116
- "AIO_COMMERCE_AUTH_IMS_ORG_ID",
117
- "AIO_COMMERCE_AUTH_IMS_SCOPES"
118
- ];
119
- /** The inputs for the generated runtime actions. */
120
- const COMMERCE_ACTION_INPUTS = Object.fromEntries(COMMERCE_VARIABLES.map((variable) => [variable, `$${variable}`]));
121
- const CUSTOM_IMPORTS_PLACEHOLDER = "// {{CUSTOM_SCRIPTS_IMPORTS}}";
122
- const CUSTOM_SCRIPTS_MAP_PLACEHOLDER = "// {{CUSTOM_SCRIPTS_MAP}}";
123
- const CUSTOM_SCRIPTS_LOADER_PLACEHOLDER = "// {{CUSTOM_SCRIPTS_LOADER}}";
124
-
125
- //#endregion
126
- //#region source/commands/utils.ts
127
- /** Format file content using prettier, inferring the parser from the file path. */
128
- function prettierFormat(content, filepath) {
129
- return prettier.format(content, {
130
- arrowParens: "always",
131
- bracketSameLine: true,
132
- bracketSpacing: true,
133
- filepath,
134
- printWidth: 80,
135
- quoteStyle: "double",
136
- semi: true,
137
- tabWidth: 2,
138
- trailingComma: "all",
139
- useTabs: false
140
- });
141
- }
142
- /**
143
- * Load the app commerce config.
144
- * @param projectRoot - Resolved project root containing the app configuration.
145
- */
146
- async function loadAppManifest(projectRoot) {
147
- const appConfig = await require_index_node.parseCommerceAppConfig(projectRoot);
148
- consola.default.debug("Loaded app commerce config");
149
- return appConfig;
150
- }
151
- /**
152
- * Install the given dependencies.
153
- * @param packageManager - The detected package manager.
154
- * @param dependencies - Package specifiers to install; no-op when empty.
155
- * @param cwd - Working directory for the install command.
156
- * @param options - Install command options.
157
- */
158
- function runInstall(packageManager, dependencies, cwd = process.cwd(), options = {}) {
159
- if (dependencies.length === 0) return;
160
- const dependencyListString = dependencies.map((dependency) => ` - ${dependency}`).join("\n");
161
- consola.default.start([`Installing the following dependencies with ${packageManager}:\n${dependencyListString}\n`, "This may take a few seconds...\n"].join("\n"));
162
- const { command, args } = require_index_node.getInstallCommand(packageManager, dependencies, options);
163
- const displayCommand = [command, ...args].join(" ");
164
- const result = (0, child_process.spawnSync)(command, args, {
165
- cwd,
166
- stdio: "inherit"
167
- });
168
- if (result.error || result.status !== 0) throw new Error(`Failed to install dependencies automatically. Please install manually: ${displayCommand}`, { cause: result.error ?? /* @__PURE__ */ new Error(`Install exited with code ${result.status}`) });
169
- consola.default.log("");
170
- consola.default.success("Dependencies installed successfully");
171
- }
172
- /**
173
- * Install dependencies declared in package.json.
174
- * @param packageManager - The detected package manager.
175
- * @param cwd - Working directory for the install command.
176
- */
177
- function runProjectInstall(packageManager, cwd = process.cwd()) {
178
- consola.default.start([`Installing project dependencies with ${packageManager}...`, "This may take a few seconds...\n"].join("\n"));
179
- const { command, args } = require_index_node.getProjectInstallCommand(packageManager);
180
- const displayCommand = [command, ...args].join(" ");
181
- const result = (0, child_process.spawnSync)(command, args, {
182
- cwd,
183
- stdio: "inherit"
184
- });
185
- if (result.error || result.status !== 0) throw new Error(`Failed to install dependencies automatically. Please install manually: ${displayCommand}`, { cause: result.error ?? /* @__PURE__ */ new Error(`Install exited with code ${result.status}`) });
186
- consola.default.log("");
187
- consola.default.success("Dependencies installed successfully");
188
- }
189
- /**
190
- * Whether the app config contains anything that can't be JSON-serialized as-is
191
- * and therefore requires generating a runtime-safe ESM config module.
192
- */
193
- function hasDynamicAppConfig(appConfig) {
194
- const schema = appConfig.businessConfig?.schema;
195
- return Array.isArray(schema) && (0, _adobe_aio_commerce_lib_config.hasDynamicSchema)(schema);
196
- }
197
- /**
198
- * Whether preserving the app config requires generating a JavaScript module.
199
- * @param appConfig - The parsed app config.
200
- * @param projectRoot - Resolved project root containing the source config.
201
- */
202
- async function requiresJavaScriptAppConfig(appConfig, projectRoot) {
203
- return hasDynamicAppConfig(appConfig) || await require_index_node.hasNamedCommerceAppConfigExports(projectRoot);
204
- }
205
- /**
206
- * Path to an extension point's `.generated` directory, relative to the project root.
207
- * @param extensionPointId - The extension point ID, e.g. "commerce/extensibility/1"
208
- */
209
- function getGeneratedDir(extensionPointId) {
210
- return (0, path.join)(getExtensionPointFolderPath(extensionPointId), GENERATED_PATH);
211
- }
212
- /**
213
- * Path to an extension point's generated actions directory, relative to the project root.
214
- * @param extensionPointId - The extension point ID, e.g. "commerce/extensibility/1"
215
- */
216
- function getActionsDir(extensionPointId) {
217
- return (0, path.join)(getExtensionPointFolderPath(extensionPointId), GENERATED_ACTIONS_PATH);
218
- }
219
- /**
220
- * Path to a specific generated action file, relative to the project root.
221
- * @param extensionPointId - The extension point ID, e.g. "commerce/extensibility/1"
222
- * @param actionName - The name of the action, e.g. "my-action"
223
- */
224
- function getActionPath(extensionPointId, actionName) {
225
- return (0, path.join)(getActionsDir(extensionPointId), `${actionName}.js`);
226
- }
227
- /**
228
- * Path to an extension point's `ext.config.yaml`, relative to the project root.
229
- * @param extensionPointId - The extension point ID, e.g. "commerce/extensibility/1"
230
- */
231
- function getExtConfigPath(extensionPointId) {
232
- return (0, path.join)(getExtensionPointFolderPath(extensionPointId), "ext.config.yaml");
233
- }
234
- /** Path to the generated app manifest JSON file, relative to the project root. */
235
- function getManifestPath() {
236
- return (0, path.join)(getGeneratedDir(EXTENSIBILITY_EXTENSION_POINT_ID), APP_MANIFEST_FILE);
237
- }
238
- /**
239
- * Path to the generated runtime-safe app config ESM module, relative to the
240
- * project root. Used when the business config schema contains dynamic options.
241
- */
242
- function getRuntimeAppConfigPath() {
243
- return (0, path.join)(getGeneratedDir(EXTENSIBILITY_EXTENSION_POINT_ID), RUNTIME_APP_CONFIG_FILE);
244
- }
245
- /** Path to the generated configuration schema file, relative to the project root. */
246
- function getSchemaPath() {
247
- return (0, path.join)(getGeneratedDir(CONFIGURATION_EXTENSION_POINT_ID), CONFIG_SCHEMA_FILE_NAME);
248
- }
249
-
250
- //#endregion
251
- //#region source/commands/typescript.ts
252
- const WEBPACK_CONFIG_PATTERN = /^webpack-config\.(?:cjs|js)$/u;
253
- const WEBPACK_CONFIG_FILE = "webpack-config.cjs";
254
- const TSCONFIG_FILE = "tsconfig.json";
255
- const ROOT_TYPESCRIPT_CONFIG = {
256
- compilerOptions: {
257
- allowJs: true,
258
- checkJs: true,
259
- module: "esnext",
260
- moduleResolution: "bundler",
261
- noEmit: true
262
- },
263
- exclude: ["src/**/web-src/**"],
264
- extends: [
265
- "@tsconfig/bases/recommended",
266
- "@tsconfig/bases/node-ts",
267
- "@tsconfig/bases/node24"
268
- ],
269
- include: [
270
- "src/**/.generated/actions/**/*.js",
271
- "app.commerce.config.ts",
272
- "app.commerce.config.mts",
273
- "app.commerce.config.cts",
274
- "src/**/*.ts",
275
- "src/**/*.mts",
276
- "src/**/*.cts"
277
- ]
278
- };
279
- const TYPESCRIPT_DEV_DEPENDENCIES = [
280
- ...SHARED_TYPESCRIPT_DEV_DEPENDENCIES,
281
- TYPESCRIPT_NODE_DEV_DEPENDENCY,
282
- TYPESCRIPT_WEBPACK_DEV_DEPENDENCY
283
- ];
284
- const ACTIONS_TYPECHECK_SCRIPT = "typecheck:actions";
285
- const WEB_SOURCE_TYPECHECK_SCRIPT = "typecheck:web-src";
286
- const ACTIONS_TYPECHECK_COMMAND = "tsc --noEmit -p tsconfig.json";
287
- const WEB_SOURCE_TYPECHECK_COMMAND = `tsc --noEmit -p ${`${getExtensionPointFolderPath(BACKEND_UI_V2_EXTENSION_POINT_ID)}/web-src/tsconfig.json`}`;
288
- /**
289
- * Create the default Webpack configuration when the project has none.
290
- * @param projectRoot Project root directory.
291
- */
292
- async function scaffoldWebpackConfig(projectRoot) {
293
- const existingConfig = (await (0, fs_promises.readdir)(projectRoot, { withFileTypes: true })).find((entry) => entry.isFile() && WEBPACK_CONFIG_PATTERN.test(entry.name));
294
- if (existingConfig !== void 0) {
295
- consola.consola.info(`Found ${existingConfig.name}; leaving it unchanged.`);
296
- return;
297
- }
298
- await (0, fs_promises.copyFile)((0, path.join)(TEMPLATES_DIR, "typescript", WEBPACK_CONFIG_FILE), (0, path.join)(projectRoot, WEBPACK_CONFIG_FILE));
299
- }
300
- /**
301
- * Create the Runtime actions TypeScript configuration when it does not exist.
302
- * @param projectRoot Project root directory.
303
- */
304
- async function scaffoldTypeScriptConfig(projectRoot) {
305
- const rootConfigPath = (0, path.join)(projectRoot, TSCONFIG_FILE);
306
- if (!(0, fs.existsSync)(rootConfigPath)) await (0, fs_promises.writeFile)(rootConfigPath, `${JSON.stringify(ROOT_TYPESCRIPT_CONFIG, null, 2)}\n`, "utf-8");
307
- }
308
- /**
309
- * Install missing TypeScript tooling after validating installed versions.
310
- * @param packageManager Package manager used by the project.
311
- * @param projectRoot Project root directory.
312
- */
313
- async function installTypeScriptDependencies(packageManager, projectRoot) {
314
- const installPlan = await require_index_node.getPackageDependencyInstallPlan(TYPESCRIPT_DEV_DEPENDENCIES, projectRoot);
315
- if (installPlan.incompatible.length > 0) {
316
- const dependencies = installPlan.incompatible.map(({ name, version, installedVersion }) => `${name}@${installedVersion} does not satisfy ${version}`).join("\n");
317
- throw new Error(`Cannot configure TypeScript because installed dependencies are incompatible:\n${dependencies}`);
318
- }
319
- runInstall(packageManager, installPlan.missing.map(({ name, version }) => `${name}@${version}`), projectRoot, { dev: true });
320
- }
321
- /**
322
- * Scaffold the files and dependencies for a new TypeScript Commerce project.
323
- * @param packageManager Package manager used by the initialized project.
324
- * @param projectRoot Resolved project root.
325
- */
326
- async function scaffoldTypeScriptProject(packageManager, projectRoot) {
327
- await scaffoldWebpackConfig(projectRoot);
328
- await scaffoldTypeScriptConfig(projectRoot);
329
- await installTypeScriptDependencies(packageManager, projectRoot);
330
- }
331
- /**
332
- * Add a generated typecheck script and compose it into the root typecheck script.
333
- * @param scriptName Generated package script name.
334
- * @param command TypeScript command run by the generated script.
335
- * @param projectRoot Resolved project root.
336
- */
337
- async function syncTypecheckScript(scriptName, command, projectRoot) {
338
- const pkg = await require_index_node.loadPackageJson(projectRoot);
339
- if (pkg === null) throw new Error("Could not find package.json.");
340
- const scripts = {
341
- ...pkg.content.scripts,
342
- [scriptName]: command
343
- };
344
- const packageManager = await require_index_node.detectPackageManager(projectRoot);
345
- const typecheck = require_index_node.appendCommand(scripts.typecheck, require_index_node.getRunScriptCommand(packageManager, scriptName));
346
- pkg.update({ scripts: {
347
- ...scripts,
348
- typecheck
349
- } });
350
- await pkg.save();
351
- }
352
- /**
353
- * Add the Runtime actions typecheck script to a project.
354
- * @param projectRoot Resolved project root.
355
- */
356
- async function syncActionsTypecheckScript(projectRoot) {
357
- await syncTypecheckScript(ACTIONS_TYPECHECK_SCRIPT, ACTIONS_TYPECHECK_COMMAND, projectRoot);
358
- }
359
- /**
360
- * Add the web-src typecheck script to a project.
361
- * @param projectRoot Resolved project root.
362
- */
363
- async function syncWebSourceTypecheckScript(projectRoot) {
364
- await syncTypecheckScript(WEB_SOURCE_TYPECHECK_SCRIPT, WEB_SOURCE_TYPECHECK_COMMAND, projectRoot);
365
- }
366
-
367
- //#endregion
368
- //#region source/commands/generate/web-src.ts
369
- const JSX_FILE_EXTENSION = ".jsx";
370
- const TSX_FILE_EXTENSION = ".tsx";
371
- const APP_TITLE_PLACEHOLDER = "APP_TITLE";
372
- const WEB_SOURCE_ENTRYPOINT_FILE = "index.html";
373
- const WEB_SOURCE_IMPORT_ALIAS = "#web/*";
374
- const WEB_SOURCE_REQUIRED_FILES = [".babelrc"];
375
- const WEB_SOURCE_TSCONFIG_FILE = "tsconfig.json";
376
- const LEADING_DOT_SLASH_PATTERN$1 = /^\.\//u;
377
- /** Runtime dependencies required by the generated web-src app. */
378
- const WEB_SOURCE_DEPENDENCIES = [
379
- {
380
- name: "@adobe/aio-commerce-lib-admin-ui",
381
- version: "^1.1.0"
382
- },
383
- {
384
- name: "react",
385
- version: "^19.2.7"
386
- },
387
- {
388
- name: "react-dom",
389
- version: "^19.2.7"
390
- },
391
- {
392
- name: "@react-spectrum/s2",
393
- version: "^1.5.1"
394
- }
395
- ];
396
- const WEB_SOURCE_BABEL_DEV_DEPENDENCIES = [{
397
- name: "@babel/core",
398
- version: "^7.29.7"
399
- }, {
400
- name: "@babel/preset-react",
401
- version: "^7.29.7"
402
- }];
403
- /** Development dependencies required by the generated web-src app. */
404
- const WEB_SOURCE_DEV_DEPENDENCIES = [
405
- ...WEB_SOURCE_BABEL_DEV_DEPENDENCIES,
406
- {
407
- name: "@types/react",
408
- version: "^19.2.17"
409
- },
410
- {
411
- name: "@types/react-dom",
412
- version: "^19.2.3"
413
- }
414
- ];
415
- const WEB_SOURCE_REQUIRED_DEV_DEPENDENCIES = WEB_SOURCE_BABEL_DEV_DEPENDENCIES;
416
- const WEB_SOURCE_SHARED_BUNDLES = [{
417
- assets: ["**/@react-spectrum/s2/**", "src/commerce-backend-ui-2/web-src/*.{js,jsx,ts,tsx}"],
418
- name: "s2-styles",
419
- types: ["css"]
420
- }];
421
- const WEB_SOURCE_TYPESCRIPT_CONFIG = {
422
- compilerOptions: {
423
- allowImportingTsExtensions: true,
424
- allowJs: true,
425
- checkJs: true,
426
- jsx: "react-jsx",
427
- jsxImportSource: "react",
428
- module: "esnext",
429
- moduleResolution: "bundler",
430
- noEmit: true,
431
- rewriteRelativeImportExtensions: false
432
- },
433
- extends: ["@tsconfig/bases/recommended"],
434
- include: [
435
- "src/**/*.js",
436
- "src/**/*.ts",
437
- "src/**/*.tsx",
438
- "src/**/*.jsx"
439
- ]
440
- };
441
- /** Normalize a generated file path for package.json imports. */
442
- function normalizePackageJsonPath$1(path$9) {
443
- const normalizedPath = path$9.split(path.sep).join("/");
444
- return (normalizedPath.startsWith(".") ? normalizedPath : `./${normalizedPath}`).replace(LEADING_DOT_SLASH_PATTERN$1, "./");
445
- }
446
- /**
447
- * Resolve the generated web-src entrypoint path from an extension config.
448
- * @param extConfig - Extension config containing the view operation.
449
- */
450
- function getWebSourceEntrypoint(extConfig) {
451
- const viewEntrypoint = extConfig.operations?.view?.[0]?.impl;
452
- if (viewEntrypoint === void 0) return null;
453
- return (0, path.join)(getExtensionPointFolderPath(BACKEND_UI_V2_EXTENSION_POINT_ID), extConfig.web ?? "web-src", viewEntrypoint);
454
- }
455
- /**
456
- * Ensure package.json has the dependencies and Parcel config needed by web-src.
457
- * @param projectRoot - Resolved project root containing package.json.
458
- * @param extension - Web source extension whose tooling is configured.
459
- */
460
- async function prepareWebSourcePackage(projectRoot, extension, scaffoldRequired) {
461
- const pkg = await require_index_node.loadPackageJson(projectRoot);
462
- if (pkg === null) throw new Error("Could not find package.json.");
463
- const dependencies = scaffoldRequired ? WEB_SOURCE_DEPENDENCIES : [];
464
- const requiredDevDependencies = scaffoldRequired ? [...WEB_SOURCE_DEV_DEPENDENCIES, ...extension === "tsx" ? SHARED_TYPESCRIPT_DEV_DEPENDENCIES : []] : WEB_SOURCE_REQUIRED_DEV_DEPENDENCIES;
465
- const installPlan = await require_index_node.getPackageDependencyInstallPlan([...dependencies, ...requiredDevDependencies], projectRoot);
466
- if (installPlan.incompatible.length > 0) {
467
- const incompatibleDependencies = installPlan.incompatible.map(({ name, version, installedVersion }) => `${name}@${installedVersion} does not satisfy ${version}`).join("\n");
468
- throw new Error(`Cannot scaffold web-src because installed dependencies are incompatible:\n${incompatibleDependencies}`);
469
- }
470
- const existingDependencies = pkg.content.dependencies ?? {};
471
- const devDependencies = pkg.content.devDependencies ?? {};
472
- const dependencyMaps = [existingDependencies, devDependencies];
473
- const declaredDependencyNames = new Set(dependencyMaps.flatMap((depMap) => Object.keys(depMap)));
474
- const dependenciesToDeclare = [...dependencies, ...requiredDevDependencies].filter(({ name }) => !declaredDependencyNames.has(name));
475
- if (dependenciesToDeclare.length > 0) {
476
- consola.consola.info("Adding web-src dependencies in package.json:");
477
- consola.consola.log.raw((0, consola_utils.formatTree)(dependenciesToDeclare.map(({ name, version }) => ` ${name}@${version}`)));
478
- } else consola.consola.info("web-src dependencies are already declared in package.json.");
479
- pkg.update({
480
- ...scaffoldRequired && {
481
- "@parcel/bundler-default": {
482
- ...pkg.content["@parcel/bundler-default"],
483
- manualSharedBundles: WEB_SOURCE_SHARED_BUNDLES
484
- },
485
- "@parcel/resolver-default": {
486
- ...pkg.content["@parcel/resolver-default"],
487
- packageExports: true
488
- },
489
- dependencies: require_index_node.mergePackageJsonDependencies(existingDependencies, WEB_SOURCE_DEPENDENCIES, dependencyMaps)
490
- },
491
- devDependencies: require_index_node.mergePackageJsonDependencies(devDependencies, requiredDevDependencies, dependencyMaps)
492
- });
493
- await pkg.save();
494
- if (installPlan.missing.length === 0) {
495
- consola.consola.info("web-src dependencies are already installed.");
496
- return;
497
- }
498
- consola.consola.info("Installing missing web-src dependencies from package.json:");
499
- consola.consola.log.raw((0, consola_utils.formatTree)(installPlan.missing.map(({ name, version }) => ` ${name}@${version}`)));
500
- const packageManager = await require_index_node.detectPackageManager(projectRoot);
501
- runProjectInstall(packageManager, projectRoot);
502
- }
503
- /**
504
- * Copies required web-src support files that are not already present.
505
- * @param sourceDir - Directory containing required web source files.
506
- * @param targetDir - Generated or existing web source directory.
507
- * @param projectRoot - Resolved project root used to format output paths.
508
- */
509
- async function copyMissingWebSourceFiles(sourceDir, targetDir, projectRoot) {
510
- return (await Promise.all(WEB_SOURCE_REQUIRED_FILES.map(async (file) => {
511
- const targetPath = (0, path.join)(targetDir, file);
512
- if ((0, fs.existsSync)(targetPath)) return null;
513
- await (0, fs_promises.copyFile)((0, path.join)(sourceDir, file), targetPath, fs.constants.COPYFILE_EXCL);
514
- return ` ${(0, path.relative)(projectRoot, targetPath)}`;
515
- }))).filter((path$10) => path$10 !== null);
516
- }
517
- /**
518
- * Add the package import alias for an existing or generated web-src.
519
- * @param extConfig - Extension config containing the view operation.
520
- * @param projectRoot - Resolved project root containing package.json.
521
- */
522
- async function prepareWebSourceImportAlias(extConfig, projectRoot) {
523
- const entrypoint = getWebSourceEntrypoint(extConfig);
524
- if (entrypoint === null) return;
525
- const pkg = await require_index_node.loadPackageJson(projectRoot);
526
- if (pkg === null) throw new Error("Could not find package.json.");
527
- const existingImports = typeof pkg.content.imports === "object" && pkg.content.imports !== null ? pkg.content.imports : {};
528
- const webSourceSrcPath = (0, path.join)((0, path.dirname)(entrypoint), "src");
529
- pkg.update({ imports: {
530
- ...existingImports,
531
- [WEB_SOURCE_IMPORT_ALIAS]: `${normalizePackageJsonPath$1(webSourceSrcPath)}/*`
532
- } });
533
- await pkg.save();
534
- }
535
- /** Resolve the generated web-src file extension from the app config file type. */
536
- async function resolveWebSourceExtension(projectRoot) {
537
- const configFilePath = await require_index_node.resolveCommerceAppConfig(projectRoot);
538
- return configFilePath !== null && require_index_node.isTypeScriptConfig(configFilePath) ? "tsx" : "jsx";
539
- }
540
- async function writeWebSourceTypeScriptConfig(targetDir) {
541
- const tsconfigPath = (0, path.join)(targetDir, WEB_SOURCE_TSCONFIG_FILE);
542
- await (0, fs_promises.writeFile)(tsconfigPath, `${JSON.stringify(WEB_SOURCE_TYPESCRIPT_CONFIG, null, 2)}\n`, "utf-8");
543
- return tsconfigPath;
544
- }
545
- /**
546
- * Resolve the destination path for a web-src template file.
547
- * @param templatePath - Template file path relative to its source directory.
548
- * @param extension - Web source extension to generate.
549
- */
550
- function getWebSourceTemplateTargetPath(templatePath, extension) {
551
- if (extension === "jsx" || !templatePath.endsWith(JSX_FILE_EXTENSION)) return templatePath;
552
- return `${templatePath.slice(0, -4)}${TSX_FILE_EXTENSION}`;
553
- }
554
- /**
555
- * Copy web-src templates directly to the final file extension and entrypoint.
556
- * @param sourceDir - Template web-src directory.
557
- * @param targetDir - Generated web-src directory.
558
- * @param extension - Web source extension to generate.
559
- * @param appTitle - Application title used by the entrypoint template.
560
- * @param projectRoot - Resolved project root used to format output paths.
561
- */
562
- async function copyWebSourceTemplates(sourceDir, targetDir, extension, appTitle, projectRoot) {
563
- await (0, fs_promises.mkdir)(targetDir, { recursive: true });
564
- const entries = await (0, fs_promises.readdir)(sourceDir, { withFileTypes: true });
565
- return (await Promise.all(entries.map(async (entry) => {
566
- const sourcePath = (0, path.join)(sourceDir, entry.name);
567
- const targetPath = (0, path.join)(targetDir, getWebSourceTemplateTargetPath(entry.name, extension));
568
- if (entry.isDirectory()) return await copyWebSourceTemplates(sourcePath, targetPath, extension, appTitle, projectRoot);
569
- let content = await (0, fs_promises.readFile)(sourcePath, "utf-8");
570
- if (extension === "tsx") content = content.replaceAll(`${JSX_FILE_EXTENSION}"`, `${TSX_FILE_EXTENSION}"`);
571
- if (targetPath.endsWith(WEB_SOURCE_ENTRYPOINT_FILE)) content = content.replaceAll(APP_TITLE_PLACEHOLDER, appTitle);
572
- await (0, fs_promises.writeFile)(targetPath, content, {
573
- encoding: "utf-8",
574
- flag: "wx"
575
- });
576
- return ` ${(0, path.relative)(projectRoot, targetPath)}`;
577
- }))).flat();
578
- }
579
- /**
580
- * Generates the web source scaffold for an iframe-based Admin UI extension.
581
- * @param extConfig - Extension config containing the web entrypoint.
582
- * @param appName - Application name inserted into the generated entrypoint.
583
- * @param projectRoot - Resolved project root where web source is generated.
584
- * @param templatesDir - Directory containing web source templates.
585
- */
586
- async function generateWebSrc(extConfig, appName, projectRoot, templatesDir = TEMPLATES_DIR) {
587
- const entrypoint = getWebSourceEntrypoint(extConfig);
588
- if (entrypoint === null) return;
589
- const entrypointPath = (0, path.join)(projectRoot, entrypoint);
590
- const scaffoldRequired = !(0, fs.existsSync)(entrypointPath);
591
- const targetDir = (0, path.dirname)(entrypointPath);
592
- const extension = await resolveWebSourceExtension(projectRoot);
593
- const sourceDir = (0, path.join)(templatesDir, "admin-ui", "web-src");
594
- let outputFiles = [];
595
- if (scaffoldRequired) {
596
- consola.consola.start(`Scaffolding web-src for ${BACKEND_UI_V2_EXTENSION_POINT_ID}...`);
597
- outputFiles = await copyWebSourceTemplates(sourceDir, targetDir, extension, appName, projectRoot);
598
- if (extension === "tsx") {
599
- const tsconfigPath = await writeWebSourceTypeScriptConfig(targetDir);
600
- outputFiles.push(` ${(0, path.relative)(projectRoot, tsconfigPath)}`);
601
- await syncWebSourceTypecheckScript(projectRoot);
602
- }
603
- } else consola.consola.info(`web-src entrypoint already exists, skipping scaffold: ${(0, path.relative)(projectRoot, entrypointPath)}`);
604
- const requiredFiles = await copyMissingWebSourceFiles(sourceDir, targetDir, projectRoot);
605
- if (scaffoldRequired || requiredFiles.length > 0) await prepareWebSourcePackage(projectRoot, extension, scaffoldRequired);
606
- if (scaffoldRequired) {
607
- consola.consola.success(`Scaffolded ${(0, path.relative)(projectRoot, targetDir)}`);
608
- consola.consola.log.raw((0, consola_utils.formatTree)([...outputFiles, ...requiredFiles]));
609
- } else if (requiredFiles.length > 0) {
610
- consola.consola.success(`Added required files to ${(0, path.relative)(projectRoot, targetDir)}`);
611
- consola.consola.log.raw((0, consola_utils.formatTree)(requiredFiles));
612
- }
613
- }
614
-
615
- //#endregion
616
- //#region source/commands/generate/actions/config.ts
617
- /**
618
- * Creates a runtime action configuration.
619
- * @param actionName - The name of the action.
620
- * @param config - Action generation options.
621
- * @param options - Optional configuration options.
622
- */
623
- function createActionDefinition(actionName, config = {}, options = {}) {
624
- const def = {
625
- ...options,
626
- annotations: {
627
- final: true,
628
- "require-adobe-auth": true
629
- },
630
- function: `${GENERATED_ACTIONS_PATH}/${actionName}.js`,
631
- runtime: "nodejs:24",
632
- web: options.web ?? "yes"
633
- };
634
- if (config.requiresEncryptionKey) def.inputs = {
635
- ...def.inputs,
636
- AIO_COMMERCE_CONFIG_ENCRYPTION_KEY: "$AIO_COMMERCE_CONFIG_ENCRYPTION_KEY"
637
- };
638
- return def;
639
- }
640
- /**
641
- * Gets the runtime actions to be generated from the ext.config.yaml configuration.
642
- * @param extConfig - The ext.config.yaml configuration.
643
- * @param dir - Directory containing the runtime action templates.
644
- */
645
- function getRuntimeActions(extConfig, dir) {
646
- return Object.entries(extConfig.runtimeManifest?.packages?.["app-management"]?.actions ?? {}).map(([name]) => ({
647
- name,
648
- templateFile: (0, path.join)(dir, `${name}.js.template`)
649
- }));
650
- }
651
- /**
652
- * Builds the ext.config.yaml configuration for the extensibility extension.
653
- * @param appConfig - Parsed app configuration.
654
- */
655
- function buildAppManagementExtConfig(appConfig) {
656
- const extConfig = {
657
- hooks: {
658
- "post-app-deploy": "EXTENSION=extensibility/1 $packageExec aio-commerce-lib-app hooks post-app-deploy",
659
- "pre-app-build": "EXTENSION=extensibility/1 $packageExec aio-commerce-lib-app hooks pre-app-build"
660
- },
661
- operations: { workerProcess: [{
662
- impl: `${PACKAGE_NAME}/app-config`,
663
- type: "action"
664
- }, {
665
- impl: `${PACKAGE_NAME}/association`,
666
- type: "action"
667
- }] },
668
- runtimeManifest: { packages: { [PACKAGE_NAME]: {
669
- actions: {
670
- "app-config": createActionDefinition("app-config"),
671
- association: createActionDefinition("association")
672
- },
673
- license: "Apache-2.0"
674
- } } }
675
- };
676
- const hasPasswordFieldsInSchema = require_validate.hasBusinessConfigSchema(appConfig) && appConfig.businessConfig.schema.some((field) => field.type === "password");
677
- extConfig.operations.workerProcess.push({
678
- impl: `${PACKAGE_NAME}/installation`,
679
- type: "action"
680
- });
681
- extConfig.runtimeManifest.packages[PACKAGE_NAME].actions.installation = createActionDefinition("installation", { requiresEncryptionKey: hasPasswordFieldsInSchema }, {
682
- inputs: {
683
- ...COMMERCE_ACTION_INPUTS,
684
- LOG_LEVEL: "$LOG_LEVEL"
685
- },
686
- limits: { timeout: 6e5 }
687
- });
688
- return extConfig;
689
- }
690
- /** Builds the ext.config.yaml configuration for the business configuration extension. */
691
- function buildBusinessConfigurationExtConfig() {
692
- const actions = [{
693
- name: "config",
694
- requiresEncryptionKey: true,
695
- templateFile: "config.js.template"
696
- }, {
697
- name: "scope-tree",
698
- templateFile: "scope-tree.js.template"
699
- }];
700
- return {
701
- hooks: { "pre-app-build": "EXTENSION=configuration/1 $packageExec aio-commerce-lib-app hooks pre-app-build" },
702
- operations: { workerProcess: actions.map((action) => ({
703
- impl: `${PACKAGE_NAME}/${action.name}`,
704
- type: "action"
705
- })) },
706
- runtimeManifest: { packages: { [PACKAGE_NAME]: {
707
- actions: Object.fromEntries(actions.map((action) => [action.name, createActionDefinition(action.name, action)])),
708
- license: "Apache-2.0"
709
- } } }
710
- };
711
- }
712
- /** Collects unique `runtimeAction` strings from all worker entries in an `adminUi` config. */
713
- function collectUniqueRuntimeActions(adminUi) {
714
- const entities = [
715
- "order",
716
- "product",
717
- "customer"
718
- ].map((key) => adminUi?.[key]);
719
- const gridRuntimeActions = entities.map((entity) => entity?.gridColumns?.runtimeAction).filter((action) => action !== void 0);
720
- const massActionRuntimeActions = entities.flatMap((entity) => entity?.massActions ?? []).filter((action) => action.type === "worker").map((action) => action.runtimeAction);
721
- const viewButtonRuntimeActions = (adminUi?.order?.viewButtons ?? []).filter((button) => button.type === "worker").map((button) => button.runtimeAction);
722
- return [.../* @__PURE__ */ new Set([
723
- ...gridRuntimeActions,
724
- ...massActionRuntimeActions,
725
- ...viewButtonRuntimeActions
726
- ])];
727
- }
728
- /** Returns true if the `adminUi` config requires a `view` operation and `web` source in ext.config.yaml. */
729
- function requiresWebSource(adminUi) {
730
- if (adminUi?.menu !== void 0) return true;
731
- if ((adminUi?.order?.viewButtons ?? []).some((button) => button.type === "view")) return true;
732
- return [
733
- "order",
734
- "product",
735
- "customer"
736
- ].map((key) => adminUi?.[key]).flatMap((entity) => entity?.massActions ?? []).some((action) => action.type === "view");
737
- }
738
- /**
739
- * Builds the ext.config.yaml for the Admin UI v2 extension (`commerce/backend-ui/2`).
740
- * Derives `workerProcess` and `view` operation declarations from `adminUi` config.
741
- * Adds a `view` operation and `web` source when view-type entries or `adminUi.menu` is configured.
742
- * @param appConfig - Parsed app configuration.
743
- */
744
- function buildAdminUiV2ExtConfig(appConfig) {
745
- const { adminUi } = appConfig;
746
- const runtimeActions = collectUniqueRuntimeActions(adminUi);
747
- const requiresWeb = requiresWebSource(adminUi);
748
- return {
749
- hooks: {
750
- "pre-app-build": "EXTENSION=backend-ui/2 $packageExec aio-commerce-lib-app hooks pre-app-build",
751
- "pre-app-dev": "EXTENSION=backend-ui/2 $packageExec aio-commerce-lib-app hooks pre-app-dev",
752
- "pre-app-run": "EXTENSION=backend-ui/2 $packageExec aio-commerce-lib-app hooks pre-app-run"
753
- },
754
- operations: {
755
- ...requiresWeb && { view: [{
756
- impl: "index.html",
757
- type: "web"
758
- }] },
759
- ...runtimeActions.length > 0 && { workerProcess: runtimeActions.map((impl) => ({
760
- impl,
761
- type: "action"
762
- })) }
763
- },
764
- ...requiresWeb && { web: "web-src" }
765
- };
766
- }
767
-
768
- //#endregion
769
- //#region ../../packages-private/scripting-utils/source/yaml/helpers.ts
770
- /**
771
- * Read a YAML file and return a {@link Document}
772
- * @param path - The path to the YAML file
773
- */
774
- async function readYamlFile(path$5) {
775
- let doc = new yaml.Document();
776
- if ((0, fs.existsSync)(path$5)) try {
777
- const fileContent = await (0, fs_promises.readFile)(path$5, "utf-8");
778
- doc = (0, yaml.parseDocument)(fileContent, { keepSourceTokens: true });
779
- } catch (err) {
780
- const file = (0, path.basename)(path$5);
781
- throw new Error(`Failed to parse ${file}`, { cause: err });
782
- }
783
- if (doc.contents === null) doc.contents = new yaml.YAMLMap();
784
- return doc;
785
- }
786
- /**
787
- * Generic helper to get or create a YAML node at the given path
788
- * @param doc - The YAML document
789
- * @param path - The path to the node
790
- * @param options - The options for the node
791
- * @param typeConfig - Configuration for the node type
792
- * @returns The existing or newly created node
793
- */
794
- function getOrCreateNode(doc, path$6, options, typeConfig) {
795
- const node = doc.getIn(path$6);
796
- if (node) {
797
- if (!typeConfig.typeGuard(node)) throw new Error(`Expected ${typeConfig.typeName} at path "${path$6.join(".")}".`);
798
- return node;
799
- }
800
- if (doc.hasIn(path$6)) doc.deleteIn(path$6);
801
- const pair = doc.createPair(path$6.at(-1), typeConfig.createNode());
802
- options.onBeforeCreate?.(pair);
803
- if (path$6.length === 1) doc.add(pair);
804
- else doc.addIn(path$6.slice(0, -1), pair);
805
- return doc.getIn(path$6);
806
- }
807
- /**
808
- * Get or create a sequence at the given path
809
- * @param doc - The YAML document
810
- * @param path - The path to the sequence
811
- * @param options - The options for the sequence
812
- */
813
- function getOrCreateSeq(doc, path$7, options) {
814
- return getOrCreateNode(doc, path$7, options ?? {}, {
815
- createNode: () => new yaml.YAMLSeq(),
816
- typeGuard: yaml.isSeq,
817
- typeName: "sequence"
818
- });
819
- }
820
- /**
821
- * Get or create a map at the given path
822
- * @param doc - The YAML document
823
- * @param path - The path to the map
824
- * @param options - The options for the map
825
- */
826
- function getOrCreateMap(doc, path$8, options) {
827
- return getOrCreateNode(doc, path$8, options ?? {}, {
828
- createNode: () => new yaml.YAMLMap(),
829
- typeGuard: yaml.isMap,
830
- typeName: "map"
831
- });
832
- }
833
- /**
834
- * Read the `inputs` map from an existing YAML action definition into a plain
835
- * object. Used by codegen to merge developer-added inputs with the ones the
836
- * generator manages, so regeneration does not strip user-added entries.
837
- *
838
- * @param existingAction - The YAML map representing the existing action.
839
- */
840
- function getExistingInputs(existingAction) {
841
- const inputs = existingAction?.get("inputs");
842
- if (!(0, yaml.isMap)(inputs)) return {};
843
- return Object.fromEntries(inputs.items.map((item) => {
844
- if (!(0, yaml.isPair)(item)) return [];
845
- return [String(item.key), item.value];
846
- }));
847
- }
848
- /**
849
- * Read a string field from an existing YAML action definition. Used by codegen
850
- * to preserve developer-set values (e.g. `runtime`) across regeneration
851
- * instead of overwriting them.
852
- *
853
- * @param key - The field to read.
854
- * @param existingAction - The YAML map representing the existing action.
855
- */
856
- function getExistingString(key, existingAction) {
857
- const value = existingAction?.get(key);
858
- return typeof value === "string" ? value : void 0;
859
- }
860
-
861
- //#endregion
862
- //#region ../../packages-private/scripting-utils/source/yaml/codegen.ts
863
- /**
864
- * Create an ext.config.yaml file
865
- * @param path - The path to the ext.config.yaml file
866
- * @param config - The config to build
867
- * @param doc - The document to modify (a new one is created if not provided)
868
- */
869
- async function createOrUpdateExtConfig(path, config, doc) {
870
- const extConfigDoc = doc ?? new yaml.Document({});
871
- if (config.web !== void 0) buildWeb(extConfigDoc, config.web);
872
- config.hooks ??= {};
873
- await buildHooks(extConfigDoc, config.hooks);
874
- if (config.operations !== void 0) buildOperations(extConfigDoc, config.operations);
875
- if (config.runtimeManifest !== void 0) buildRuntimeManifest(extConfigDoc, config.runtimeManifest);
876
- await writeExtConfig(path, extConfigDoc);
877
- return extConfigDoc;
878
- }
879
- /**
880
- * Set the top-level `web` scalar only if it's missing.
881
- * Preserves any user-customized value already present.
882
- */
883
- function buildWeb(extConfig, web) {
884
- if (!extConfig.hasIn(["web"])) extConfig.add(extConfig.createPair("web", web));
885
- }
886
- /**
887
- * Build the definition for a runtime action.
888
- *
889
- * Developer-added `inputs` keys (anything not in the generator-managed set) on
890
- * `existingAction` are preserved so that hand-written entries — for example
891
- * factory credentials for `dynamicList` fields — survive regeneration.
892
- *
893
- * A `runtime` already set on `existingAction` is likewise preserved, so a
894
- * developer can pin a different Node runtime (e.g. `nodejs:24`) in
895
- * `ext.config.yaml` once without codegen reverting it on the next run.
896
- *
897
- * @param action - The action definition to build.
898
- * @param existingAction - The action's previous YAML definition, if any.
899
- */
900
- function buildActionDefinition(action, existingAction) {
901
- const actionDef = new yaml.YAMLMap();
902
- const existingInputs = getExistingInputs(existingAction);
903
- const existingRuntime = getExistingString("runtime", existingAction);
904
- const managedInputs = { LOG_LEVEL: "$LOG_LEVEL" };
905
- actionDef.set("function", action.function);
906
- actionDef.set("web", action.web ?? "yes");
907
- actionDef.set("runtime", existingRuntime ?? action.runtime ?? "nodejs:24");
908
- actionDef.set("inputs", {
909
- ...existingInputs,
910
- ...managedInputs,
911
- ...action.inputs ?? {}
912
- });
913
- actionDef.set("annotations", { ...action.annotations ?? {
914
- final: true,
915
- "require-adobe-auth": true
916
- } });
917
- const includes = action.include ?? [];
918
- if (includes.length > 0) {
919
- const itemSeq = new yaml.YAMLSeq();
920
- itemSeq.flow = true;
921
- for (const [source, target] of includes) itemSeq.items.push(source, target);
922
- const seq = new yaml.YAMLSeq();
923
- seq.items.push(itemSeq);
924
- actionDef.set("include", seq);
925
- }
926
- if (action.limits !== void 0) actionDef.set("limits", action.limits);
927
- return actionDef;
928
- }
929
- /**
930
- * Build the `operations` section of the `ext.config.yaml` file
931
- * @param extConfig - The ext.config.yaml file
932
- * @param operations - The operations to build
933
- */
934
- function buildOperations(extConfig, operations) {
935
- const ourOps = operations.workerProcess ?? [];
936
- if (ourOps.length > 0) {
937
- getOrCreateMap(extConfig, ["operations"], { onBeforeCreate: (pair) => {
938
- pair.key.spaceBefore = true;
939
- } });
940
- const workerProcess = getOrCreateSeq(extConfig, ["operations", "workerProcess"], { onBeforeCreate: (pair) => {
941
- pair.key.commentBefore = " These worker processes definitions are auto-generated. Do not remove or manually edit.";
942
- } });
943
- workerProcess.items = [];
944
- workerProcess.items.push(...ourOps.map((op) => {
945
- const map = new yaml.YAMLMap();
946
- map.set("type", op.type);
947
- map.set("impl", op.impl);
948
- return map;
949
- }));
950
- } else if (extConfig.hasIn(["operations", "workerProcess"])) extConfig.deleteIn(["operations", "workerProcess"]);
951
- if (operations.view !== void 0) {
952
- getOrCreateMap(extConfig, ["operations"], { onBeforeCreate: (pair) => {
953
- pair.key.spaceBefore = true;
954
- } });
955
- const view = getOrCreateSeq(extConfig, ["operations", "view"]);
956
- if (view.items.length === 0) view.items.push(...operations.view.map((v) => {
957
- const map = new yaml.YAMLMap();
958
- map.set("type", v.type);
959
- map.set("impl", v.impl);
960
- return map;
961
- }));
962
- }
963
- const operationsMap = extConfig.getIn(["operations"]);
964
- if (operationsMap instanceof yaml.YAMLMap && operationsMap.items.length === 0) extConfig.deleteIn(["operations"]);
965
- }
966
- /**
967
- * Build the `runtimeManifest` section of the `ext.config.yaml` file
968
- * @param extConfig - The ext.config.yaml file
969
- * @param packages - The packages to build
970
- */
971
- function buildRuntimeManifest(extConfig, manifest) {
972
- const packages = manifest.packages ?? {};
973
- if (Object.keys(packages).length === 0) return;
974
- getOrCreateMap(extConfig, ["runtimeManifest"], { onBeforeCreate: (pair) => {
975
- pair.key.spaceBefore = true;
976
- } });
977
- getOrCreateMap(extConfig, ["runtimeManifest", "packages"]);
978
- for (const [name, pkg] of Object.entries(packages)) {
979
- const packageDef = getOrCreateMap(extConfig, [
980
- "runtimeManifest",
981
- "packages",
982
- name
983
- ], { onBeforeCreate: (pair) => {
984
- pair.key.commentBefore = " This package definition is auto-generated. Do not remove or manually edit.";
985
- } });
986
- const existingActions = packageDef.get("actions");
987
- const actions = new yaml.YAMLMap();
988
- packageDef.set("license", pkg.license ?? "Apache-2.0");
989
- packageDef.set("actions", actions);
990
- for (const [actionName, action] of Object.entries(pkg.actions ?? {})) {
991
- const existingAction = (0, yaml.isMap)(existingActions) ? existingActions.get(actionName) : void 0;
992
- const actionDef = buildActionDefinition(action, (0, yaml.isMap)(existingAction) ? existingAction : void 0);
993
- actions.set(actionName, actionDef);
994
- }
995
- }
996
- }
997
- /**
998
- * Build the `hooks` section of the `ext.config.yaml` file
999
- * @param extConfig - The ext.config.yaml file
1000
- * @param hooks - The hooks to build
1001
- */
1002
- async function buildHooks(extConfig, hooks) {
1003
- const generatedHooks = `[${Object.keys(hooks).join(", ")}]`;
1004
- const hooksMap = getOrCreateMap(extConfig, ["hooks"], { onBeforeCreate: (pair) => {
1005
- pair.key.spaceBefore = true;
1006
- pair.key.commentBefore = ` The ${generatedHooks} hooks are auto-generated. Do not remove or manually edit.`;
1007
- } });
1008
- const projectRoot = await require_index_node.getProjectRootDirectory();
1009
- const packageManager = await require_index_node.detectPackageManager(projectRoot);
1010
- const execCommand = require_index_node.getExecCommand(packageManager);
1011
- for (const [name, command] of Object.entries(hooks)) {
1012
- const fullCommand = `${command.replaceAll("$packageExec", execCommand)}`;
1013
- const prevValue = (hooksMap.get(name) ?? "").trim();
1014
- if (prevValue.endsWith("js") || prevValue.endsWith("ts")) throw new Error(`Conflicting hook definition found. The "${name}" hook needs to be a command, not a script.`);
1015
- hooksMap.set(name, require_index_node.appendCommand(prevValue || void 0, fullCommand));
1016
- }
1017
- }
1018
- /**
1019
- * Write the ext.config.yaml file
1020
- * @param configPath - The path to the ext.config.yaml file
1021
- * @param config - The config to write
1022
- */
1023
- async function writeExtConfig(configPath, doc) {
1024
- const yamlContent = doc.toString({
1025
- defaultStringType: "PLAIN",
1026
- indent: 2,
1027
- lineWidth: 0
1028
- });
1029
- await (0, fs_promises.writeFile)(configPath, yamlContent, "utf-8");
1030
- }
1031
-
1032
- //#endregion
1033
- //#region source/commands/generate/actions/lib.ts
1034
- const ESBUILD_PACKAGE = "esbuild@0.28.0";
1035
- const LEADING_DOT_SLASH_PATTERN = /^\.\//u;
1036
- /** Normalize a path for use as an ESM import specifier. */
1037
- function normalizeImportPath(path$3) {
1038
- const normalizedPath = path$3.split(path.sep).join("/");
1039
- return normalizedPath.startsWith(".") ? normalizedPath : `./${normalizedPath}`;
1040
- }
1041
- /** Normalize a generated file path for package.json imports. */
1042
- function normalizePackageJsonPath(path$4) {
1043
- return normalizeImportPath(path$4).replace(LEADING_DOT_SLASH_PATTERN, "./");
1044
- }
1045
- /** Add or update the package import alias used by dynamic generated actions. */
1046
- async function updateAppConfigImportAlias(projectRoot, runtimeConfigPath) {
1047
- const pkg = await require_index_node.loadPackageJson(projectRoot);
1048
- if (pkg === null) throw new Error("Could not find package.json.");
1049
- const existingImports = typeof pkg.content.imports === "object" && pkg.content.imports !== null ? pkg.content.imports : {};
1050
- pkg.update({ imports: {
1051
- ...existingImports,
1052
- [APP_CONFIG_IMPORT_ALIAS]: normalizePackageJsonPath(runtimeConfigPath)
1053
- } });
1054
- await pkg.save();
1055
- }
1056
- /** Write an ESM passthrough module that re-exports an app config file. */
1057
- async function writeJavaScriptAppConfigModule(configFilePath, outputPath) {
1058
- const configImportPath = normalizeImportPath((0, path.relative)((0, path.dirname)(outputPath), configFilePath));
1059
- const isJson = (0, path.extname)(configFilePath) === ".json";
1060
- const importAttributes = isJson ? " with { type: \"json\" }" : "";
1061
- const defaultExport = isJson ? `export default /** @type {import("@adobe/aio-commerce-lib-app/config").CommerceAppConfig} */ (appConfig);` : "export default appConfig;";
1062
- await (0, fs_promises.writeFile)(outputPath, [
1063
- "// This file has been auto-generated by `@adobe/aio-commerce-lib-app`",
1064
- "// Do not modify this file directly",
1065
- "",
1066
- `import appConfig from "${configImportPath}"${importAttributes};`,
1067
- "",
1068
- isJson ? null : `export * from "${configImportPath}";`,
1069
- defaultExport,
1070
- ""
1071
- ].filter((item) => item !== null).join("\n"), "utf-8");
1072
- }
1073
- /**
1074
- * Bundles a TypeScript app config file into runtime-safe ESM.
1075
- * @param configFilePath - Source TypeScript app config path.
1076
- * @param outputPath - Generated ESM module path.
1077
- * @param projectRoot - Resolved project root used to run the bundler.
1078
- */
1079
- async function bundleTypeScriptAppConfigModule(configFilePath, outputPath, projectRoot) {
1080
- const packageManager = await require_index_node.detectPackageManager(projectRoot);
1081
- const { command, args } = require_index_node.getPackageExecutionCommand(packageManager, [
1082
- ESBUILD_PACKAGE,
1083
- configFilePath,
1084
- "--bundle",
1085
- "--format=esm",
1086
- "--log-level=silent",
1087
- `--outfile=${outputPath}`,
1088
- "--packages=external",
1089
- "--platform=node",
1090
- "--target=node22"
1091
- ], { allowBuild: "esbuild" });
1092
- const result = (0, child_process.spawnSync)(command, args, {
1093
- cwd: projectRoot,
1094
- stdio: "inherit"
1095
- });
1096
- if (result.error || result.status !== 0) throw new Error(`Could not bundle the TypeScript app config with ${ESBUILD_PACKAGE}.`, { cause: result.error ?? /* @__PURE__ */ new Error(`Bundle command exited with code ${result.status}`) });
1097
- }
1098
- /**
1099
- * Write an ESM module that re-exports the static app manifest JSON so generated
1100
- * actions can import it via the alias without needing a JSON import attribute.
1101
- * @param projectRoot - Resolved project root where the module is generated.
1102
- */
1103
- async function prepareStaticAppConfigImportAlias(projectRoot) {
1104
- const runtimeConfigPath = getRuntimeAppConfigPath();
1105
- const outputPath = (0, path.join)(projectRoot, runtimeConfigPath);
1106
- await require_index_node.makeOutputDirFor((0, path.dirname)(runtimeConfigPath), projectRoot);
1107
- await writeJavaScriptAppConfigModule((0, path.join)(projectRoot, getManifestPath()), outputPath);
1108
- }
1109
- /**
1110
- * Prepare the runtime config module consumed by generated actions and its
1111
- * `#app.commerce.config` package import alias.
1112
- *
1113
- * TypeScript configs are bundled into a generated runtime module. JavaScript
1114
- * configs use a passthrough module, while serializable default-only configs use
1115
- * a re-export of the validated JSON manifest.
1116
- * @param appManifest - App configuration used to select the module format.
1117
- * @param projectRoot - Resolved project root where the module is generated.
1118
- */
1119
- async function prepareRuntimeAppConfigModule(appManifest, projectRoot) {
1120
- const configFilePath = await require_index_node.resolveCommerceAppConfig(projectRoot);
1121
- if (await requiresJavaScriptAppConfig(appManifest, projectRoot)) {
1122
- if (configFilePath === null) throw new Error("Generating a runtime config module requires an app.commerce.config.* file.");
1123
- await require_index_node.makeOutputDirFor((0, path.dirname)(getRuntimeAppConfigPath()), projectRoot);
1124
- const outputPath = (0, path.join)(projectRoot, getRuntimeAppConfigPath());
1125
- if (require_index_node.isTypeScriptConfig(configFilePath)) await bundleTypeScriptAppConfigModule(configFilePath, outputPath, projectRoot);
1126
- else await writeJavaScriptAppConfigModule(configFilePath, outputPath);
1127
- } else await prepareStaticAppConfigImportAlias(projectRoot);
1128
- await updateAppConfigImportAlias(projectRoot, getRuntimeAppConfigPath());
1129
- }
1130
- /**
1131
- * Reads an extension point's ext.config.yaml document and path.
1132
- * @param extensionPointId - The extension point ID to read the config for.
1133
- * @param projectRoot - Resolved project root containing the extension config.
1134
- */
1135
- async function readExtConfig(extensionPointId, projectRoot) {
1136
- const extConfigPath = (0, path.join)(projectRoot, getExtConfigPath(extensionPointId));
1137
- try {
1138
- return {
1139
- doc: await readYamlFile(extConfigPath),
1140
- path: extConfigPath
1141
- };
1142
- } catch (error) {
1143
- const reason = error instanceof Error ? error.message : "Unexpected error while reading the file.";
1144
- throw new Error([
1145
- `Could not read ext.config.yaml for ${extensionPointId} at ${extConfigPath}.`,
1146
- `Make sure the file exists and is valid YAML. You can regenerate it with "aio-commerce-lib-app generate actions".`,
1147
- `Reason: ${reason}`
1148
- ].join("\n"), { cause: error });
1149
- }
1150
- }
1151
- /**
1152
- * Updates an extension point's ext.config.yaml with generated configuration.
1153
- * @param appConfig - App configuration used to build the extension config.
1154
- * @param extensionPointId - Extension point whose config is updated.
1155
- * @param projectRoot - Resolved project root containing the extension config.
1156
- */
1157
- async function updateExtConfig(appConfig, extensionPointId, projectRoot) {
1158
- consola.consola.info(`Updating ext.config.yaml for ${extensionPointId}...`);
1159
- await require_index_node.makeOutputDirFor(getExtensionPointFolderPath(extensionPointId), projectRoot);
1160
- const { path: extConfigPath, doc: extConfigDoc } = await readExtConfig(extensionPointId, projectRoot);
1161
- let extConfig;
1162
- switch (extensionPointId) {
1163
- case EXTENSIBILITY_EXTENSION_POINT_ID:
1164
- extConfig = buildAppManagementExtConfig(appConfig);
1165
- break;
1166
- case CONFIGURATION_EXTENSION_POINT_ID:
1167
- extConfig = buildBusinessConfigurationExtConfig();
1168
- break;
1169
- case BACKEND_UI_V2_EXTENSION_POINT_ID:
1170
- extConfig = buildAdminUiV2ExtConfig(appConfig);
1171
- break;
1172
- default: throw new Error(`Unsupported extension point: ${extensionPointId}`);
1173
- }
1174
- await createOrUpdateExtConfig(extConfigPath, extConfig, extConfigDoc);
1175
- return extConfig;
1176
- }
1177
- /**
1178
- * Generates runtime action files from templates.
1179
- * @param appManifest - App configuration used to populate action templates.
1180
- * @param actions - Runtime actions to generate.
1181
- * @param extensionPointId - Extension point receiving the generated actions.
1182
- * @param templatesDir - Directory containing action templates.
1183
- * @param projectRoot - Resolved project root where actions are generated.
1184
- */
1185
- async function generateActionFiles(appManifest, actions, extensionPointId, templatesDir, projectRoot) {
1186
- consola.consola.start("Generating runtime actions...");
1187
- await require_index_node.makeOutputDirFor(getActionsDir(extensionPointId), projectRoot);
1188
- const outputFiles = await Promise.all(actions.map(async (action) => {
1189
- const templatePath = (0, path.join)(templatesDir, action.templateFile);
1190
- let template = await (0, fs_promises.readFile)(templatePath, "utf-8");
1191
- if (action.name === "installation") {
1192
- const customScriptsTemplatePath = (0, path.join)(templatesDir, "app-management", "custom-scripts.js.template");
1193
- const scriptsTemplate = await generateCustomScriptsTemplate(await (0, fs_promises.readFile)(customScriptsTemplatePath, "utf-8"), appManifest, projectRoot);
1194
- template = applyCustomScripts(template, scriptsTemplate);
1195
- }
1196
- const actionPath = (0, path.join)(projectRoot, getActionPath(extensionPointId, action.name));
1197
- await (0, fs_promises.writeFile)(actionPath, template, "utf-8");
1198
- return ` ${(0, path.relative)(projectRoot, actionPath)}`;
1199
- }));
1200
- consola.consola.success(`Generated ${actions.length} action(s)`);
1201
- consola.consola.log.raw((0, consola_utils.formatTree)(outputFiles));
1202
- }
1203
- /**
1204
- * Applies the given custom scripts template code to the given installation template.
1205
- * @param installationTemplate - The installation code runtime action template
1206
- * @param customScriptsTemplate - The custom scripts dynamically generated template.
1207
- */
1208
- function applyCustomScripts(installationTemplate, customScriptsTemplate) {
1209
- if (customScriptsTemplate !== null) return installationTemplate.replace(CUSTOM_SCRIPTS_LOADER_PLACEHOLDER, customScriptsTemplate).replace("const args = { appConfig };", "const args = { appConfig, customScriptsLoader };");
1210
- consola.consola.debug("No custom installation steps found, skipping custom-scripts.js generation...");
1211
- return installationTemplate.replace(CUSTOM_SCRIPTS_LOADER_PLACEHOLDER, "// No custom installation scripts configured");
1212
- }
1213
- /**
1214
- * Generates installation code that imports configured custom scripts.
1215
- * @param template - Custom scripts template content.
1216
- * @param appManifest - App configuration containing custom installation steps.
1217
- * @param projectRoot - Resolved project root used to resolve script paths.
1218
- */
1219
- async function generateCustomScriptsTemplate(template, appManifest, projectRoot) {
1220
- if (!require_webhooks.hasCustomInstallationSteps(appManifest)) return null;
1221
- const installationActionDir = (0, path.join)(projectRoot, getActionsDir(EXTENSIBILITY_EXTENSION_POINT_ID));
1222
- const customSteps = appManifest.installation.customInstallationSteps;
1223
- const importStatements = customSteps.map((step, index) => {
1224
- const absoluteScriptPath = (0, path.join)(projectRoot, step.script);
1225
- let relativeImportPath = (0, path.relative)(installationActionDir, absoluteScriptPath);
1226
- if (!relativeImportPath.startsWith(".")) relativeImportPath = `./${relativeImportPath}`;
1227
- relativeImportPath = relativeImportPath.replace(/\\/g, "/");
1228
- return `import * as ${`customScript${index}`} from "${relativeImportPath}";`;
1229
- }).join("\n");
1230
- const scriptMap = customSteps.map((step, index) => {
1231
- const entry = `"${step.script}": ${`customScript${index}`},`;
1232
- return entry.padStart(entry.length + 6);
1233
- }).join("\n");
1234
- return template.replace(CUSTOM_IMPORTS_PLACEHOLDER, importStatements).replace(CUSTOM_SCRIPTS_MAP_PLACEHOLDER, scriptMap);
1235
- }
1236
30
 
1237
- //#endregion
1238
31
  //#region source/commands/generate/actions/main.ts
1239
32
  /**
1240
33
  * Generates extension configs, runtime actions, and Admin UI web source for the configured domains.
@@ -1242,283 +35,27 @@ async function generateCustomScriptsTemplate(template, appManifest, projectRoot)
1242
35
  * @param projectRoot - Resolved project root where files are generated.
1243
36
  * @param templatesDir - Directory containing generation templates.
1244
37
  */
1245
- async function run$8(appManifest, projectRoot, templatesDir = TEMPLATES_DIR) {
1246
- await prepareRuntimeAppConfigModule(appManifest, projectRoot);
1247
- const appManagementExtConfig = await updateExtConfig(appManifest, EXTENSIBILITY_EXTENSION_POINT_ID, projectRoot);
1248
- await generateActionFiles(appManifest, getRuntimeActions(appManagementExtConfig, "app-management"), EXTENSIBILITY_EXTENSION_POINT_ID, templatesDir, projectRoot);
38
+ async function run$2(appManifest, projectRoot, templatesDir = require_web_src.TEMPLATES_DIR) {
39
+ await require_web_src.prepareRuntimeAppConfigModule(appManifest, projectRoot);
40
+ const appManagementExtConfig = await require_web_src.updateExtConfig(appManifest, require_web_src.EXTENSIBILITY_EXTENSION_POINT_ID, projectRoot);
41
+ await require_web_src.generateActionFiles(appManifest, require_web_src.getRuntimeActions(appManagementExtConfig, "app-management"), require_web_src.EXTENSIBILITY_EXTENSION_POINT_ID, templatesDir, projectRoot);
1249
42
  if (require_validate.hasBusinessConfigSchema(appManifest)) {
1250
- const businessConfigExtConfig = await updateExtConfig(appManifest, CONFIGURATION_EXTENSION_POINT_ID, projectRoot);
1251
- await generateActionFiles(appManifest, getRuntimeActions(businessConfigExtConfig, "business-configuration"), CONFIGURATION_EXTENSION_POINT_ID, templatesDir, projectRoot);
43
+ const businessConfigExtConfig = await require_web_src.updateExtConfig(appManifest, require_web_src.CONFIGURATION_EXTENSION_POINT_ID, projectRoot);
44
+ await require_web_src.generateActionFiles(appManifest, require_web_src.getRuntimeActions(businessConfigExtConfig, "business-configuration"), require_web_src.CONFIGURATION_EXTENSION_POINT_ID, templatesDir, projectRoot);
1252
45
  }
1253
46
  if (require_webhooks.hasBackendUiV2Components(appManifest)) {
1254
- const extConfig = await updateExtConfig(appManifest, BACKEND_UI_V2_EXTENSION_POINT_ID, projectRoot);
47
+ const extConfig = await require_web_src.updateExtConfig(appManifest, require_web_src.BACKEND_UI_V2_EXTENSION_POINT_ID, projectRoot);
1255
48
  if (extConfig.operations?.view) {
1256
- await prepareWebSourceImportAlias(extConfig, projectRoot);
1257
- await generateWebSrc(extConfig, appManifest.metadata.displayName, projectRoot, templatesDir);
49
+ await require_web_src.prepareWebSourceImportAlias(extConfig, projectRoot);
50
+ await require_web_src.generateWebSrc(extConfig, appManifest.metadata.displayName, projectRoot, templatesDir);
1258
51
  }
1259
52
  }
1260
53
  }
1261
54
  /** Run the generate actions command */
1262
- async function exec$8() {
1263
- try {
1264
- const projectRoot = await require_index_node.getProjectRootDirectory();
1265
- await run$8(await loadAppManifest(projectRoot), projectRoot);
1266
- } catch (error) {
1267
- if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.consola.error(error.display());
1268
- else consola.consola.error(error);
1269
- process.exit(1);
1270
- }
1271
- }
1272
-
1273
- //#endregion
1274
- //#region source/commands/generate/manifest/main.ts
1275
- /**
1276
- * Generates or removes the static app manifest as required by the app config.
1277
- * @param appConfig - Validated app configuration to serialize.
1278
- * @param projectRoot - Resolved project root where the manifest is generated.
1279
- */
1280
- async function run$7(appConfig, projectRoot) {
1281
- if (await requiresJavaScriptAppConfig(appConfig, projectRoot)) {
1282
- const stalePath = (0, path.join)(projectRoot, getManifestPath());
1283
- if (await (0, fs_promises.access)(stalePath).then(() => true, () => false)) {
1284
- await (0, fs_promises.rm)(stalePath, { force: true });
1285
- consola.consola.success(`Removed stale ${APP_MANIFEST_FILE}`);
1286
- }
1287
- return;
1288
- }
1289
- consola.consola.info("Generating app manifest...");
1290
- const contents = (0, safe_stable_stringify.stringify)(appConfig, null, 2);
1291
- const outputDir = await require_index_node.makeOutputDirFor(getGeneratedDir(EXTENSIBILITY_EXTENSION_POINT_ID), projectRoot);
1292
- const manifestPath = (0, path.join)(outputDir, APP_MANIFEST_FILE);
1293
- await (0, fs_promises.writeFile)(manifestPath, contents, "utf-8");
1294
- consola.consola.success(`Generated ${APP_MANIFEST_FILE}\n`);
1295
- }
1296
- /** Run the generate manifest command */
1297
- async function exec$7() {
1298
- try {
1299
- const projectRoot = await require_index_node.getProjectRootDirectory();
1300
- await run$7(await loadAppManifest(projectRoot), projectRoot);
1301
- } catch (error) {
1302
- if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.consola.error(error.display());
1303
- else consola.consola.error(error);
1304
- process.exit(1);
1305
- }
1306
- }
1307
-
1308
- //#endregion
1309
- //#region ../../packages-private/scripting-utils/source/filesystem/helpers.ts
1310
- /**
1311
- * Touch a file, creating it if it doesn't exist.
1312
- * @param filePath The path of the file to touch
1313
- */
1314
- async function touch(filePath) {
1315
- await (0, fs_promises.writeFile)(filePath, "", { flag: "wx" }).catch((e) => {
1316
- if (e.code !== "EEXIST") throw e;
1317
- });
1318
- }
1319
-
1320
- //#endregion
1321
- //#region source/commands/generate/schema/main.ts
1322
- /**
1323
- * Generates the business configuration schema and prepares encryption when needed.
1324
- * @param appConfig - Validated app configuration containing the schema.
1325
- * @param projectRoot - Resolved project root where schema files are managed.
1326
- */
1327
- async function run$6(appConfig, projectRoot) {
1328
- if (!require_validate.hasBusinessConfigSchema(appConfig)) {
1329
- consola.consola.debug("Business configuration schema not found in application configuration. Nothing to do.");
1330
- return;
1331
- }
1332
- const envPath = (0, path.join)(projectRoot, ".env");
1333
- await touch(envPath);
1334
- process.loadEnvFile(envPath);
1335
- if (appConfig.businessConfig.schema.some((field) => field.type === "password")) {
1336
- const packageExec = require_index_node.getExecCommand(await require_index_node.detectPackageManager(projectRoot));
1337
- if ("AIO_COMMERCE_CONFIG_ENCRYPTION_KEY" in process.env && String(process.env.AIO_COMMERCE_CONFIG_ENCRYPTION_KEY).trim().length > 0) (0, child_process.execSync)(`${packageExec} aio-commerce-lib-config encryption validate`);
1338
- else (0, child_process.execSync)(`${packageExec} aio-commerce-lib-config encryption setup`);
1339
- }
1340
- if (hasDynamicAppConfig(appConfig)) {
1341
- const stalePath = (0, path.join)(projectRoot, getSchemaPath());
1342
- if (await (0, fs_promises.access)(stalePath).then(() => true, () => false)) {
1343
- await (0, fs_promises.rm)(stalePath, { force: true });
1344
- consola.consola.success(`Removed stale ${CONFIG_SCHEMA_FILE_NAME}`);
1345
- }
1346
- return;
1347
- }
1348
- consola.consola.info("Generating configuration schema...");
1349
- const outputDir = await require_index_node.makeOutputDirFor(getGeneratedDir(CONFIGURATION_EXTENSION_POINT_ID), projectRoot);
1350
- const contents = (0, safe_stable_stringify.stringify)(appConfig.businessConfig.schema, null, 2);
1351
- const schemaPath = (0, path.join)(outputDir, CONFIG_SCHEMA_FILE_NAME);
1352
- await (0, fs_promises.writeFile)(schemaPath, contents, "utf-8");
1353
- consola.consola.success(`Generated ${CONFIG_SCHEMA_FILE_NAME}\n`);
1354
- }
1355
- /** Run the generate schema command */
1356
- async function exec$6() {
55
+ async function exec$2() {
1357
56
  try {
1358
57
  const projectRoot = await require_index_node.getProjectRootDirectory();
1359
- await run$6(await loadAppManifest(projectRoot), projectRoot);
1360
- } catch (error) {
1361
- if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.consola.error(error.display());
1362
- else consola.consola.error(error);
1363
- process.exit(1);
1364
- }
1365
- }
1366
-
1367
- //#endregion
1368
- //#region ../../packages-private/scripting-utils/source/aio/auth.ts
1369
- const { context: context$1, getToken } = _adobe_aio_lib_ims.default;
1370
- /** Gets an IMS access token for the current CLI IMS context. */
1371
- async function getUserToken() {
1372
- const contextName = await context$1.getCurrent() ?? "cli";
1373
- return getToken(contextName, {});
1374
- }
1375
-
1376
- //#endregion
1377
- //#region ../../packages-private/scripting-utils/source/aio/context.ts
1378
- /**
1379
- * Reads the current App Builder project and Runtime namespace from the local AIO CLI config.
1380
- * @throws If either the project or the runtime namespace is not configured.
1381
- */
1382
- function getAioProjectContext() {
1383
- const project = _adobe_aio_lib_core_config.default.get("project");
1384
- const namespace = _adobe_aio_lib_core_config.default.get("runtime.namespace");
1385
- if (!(project && namespace)) throw new Error("The current App Builder project and Runtime namespace are required");
1386
- return {
1387
- namespace,
1388
- project
1389
- };
1390
- }
1391
- /** Reads the configured AIO CLI environment, defaulting to `"prod"`. */
1392
- function getAioCliEnv() {
1393
- return _adobe_aio_lib_core_config.default.get("cli.env") === "stage" ? "stage" : "prod";
1394
- }
1395
-
1396
- //#endregion
1397
- //#region source/commands/hooks/post-app-deploy/polling.ts
1398
- const POLL_INTERVAL_MS = 1e3;
1399
- const UpgradeStateSchema = valibot.object({
1400
- failure: valibot.optional(valibot.object({
1401
- key: valibot.string(),
1402
- message: valibot.optional(valibot.string())
1403
- })),
1404
- id: valibot.string(),
1405
- status: valibot.picklist([
1406
- "pending",
1407
- "in-progress",
1408
- "succeeded",
1409
- "failed"
1410
- ])
1411
- });
1412
- /** Reads the latest upgrade state from the installation action. */
1413
- async function getUpgradeState(request) {
1414
- try {
1415
- const response = await ky.default.get(request.endpoint, { headers: request.headers });
1416
- if (response.status === 204) return null;
1417
- const parsed = valibot.safeParse(UpgradeStateSchema, await response.json());
1418
- return parsed.success ? parsed.output : null;
1419
- } catch (error) {
1420
- consola.consola.debug("Unable to read upgrade status; stopping upgrade polling.", { error });
1421
- return null;
1422
- }
1423
- }
1424
- /** Waits for an automatic upgrade when its status remains available. */
1425
- async function waitForAutomaticUpgrade(request) {
1426
- const state = await getUpgradeState(request);
1427
- if (!state) return;
1428
- if (state.status === "succeeded") {
1429
- consola.consola.success("App upgrade completed.\n");
1430
- return;
1431
- }
1432
- if (state.status === "failed") {
1433
- const reason = state.failure?.message ?? state.failure?.key ?? "The lifecycle attempt failed";
1434
- throw new Error(`App upgrade failed: ${reason}`);
1435
- }
1436
- consola.consola.start("App upgrade is in progress...");
1437
- await (0, timers_promises.setTimeout)(POLL_INTERVAL_MS);
1438
- return waitForAutomaticUpgrade(request);
1439
- }
1440
-
1441
- //#endregion
1442
- //#region source/commands/hooks/post-app-deploy/main.ts
1443
- /** Returns true for a no-op reason defined by the upgrade API contract. */
1444
- function isSkippedReason(reason) {
1445
- return reason === "already-current" || reason === "not-associated" || reason === "not-installed";
1446
- }
1447
- /** Returns true if the result indicates that the upgrade was skipped. */
1448
- function isSkippedResult(result) {
1449
- return "skipped" in result;
1450
- }
1451
- /** Invokes the upgrade action. */
1452
- async function createUpgradeRequest() {
1453
- const { project, namespace } = getAioProjectContext();
1454
- const token = await getUserToken();
1455
- const endpoint = `https://${namespace}.adobeioruntime.net/api/v1/web/app-management/installation`;
1456
- const ioEventsEnv = getAioCliEnv();
1457
- const ioEventsUrl = ioEventsEnv === "stage" ? "https://events-stage.adobe.io" : "https://events.adobe.io";
1458
- return {
1459
- body: {
1460
- appData: {
1461
- consumerOrgId: project.org.id,
1462
- orgName: project.org.name,
1463
- projectId: project.id,
1464
- projectName: project.name,
1465
- projectTitle: project.title,
1466
- workspaceId: project.workspace.id,
1467
- workspaceName: project.workspace.name,
1468
- workspaceTitle: project.workspace.title
1469
- },
1470
- ioEventsEnv,
1471
- ioEventsUrl
1472
- },
1473
- endpoint,
1474
- headers: {
1475
- Authorization: `Bearer ${token}`,
1476
- [require_common.INSTALLATION_INVOCATION_SOURCE_HEADER]: require_common.POST_APP_DEPLOY_INVOCATION_SOURCE,
1477
- "x-gw-ims-org-id": project.org.ims_org_id
1478
- }
1479
- };
1480
- }
1481
- /** Invokes the upgrade action. */
1482
- async function invokeAction(request) {
1483
- consola.consola.debug(`Upgrade endpoint: ${request.endpoint}`);
1484
- try {
1485
- return await ky.default.post(request.endpoint, {
1486
- headers: request.headers,
1487
- json: request.body
1488
- }).json();
1489
- } catch (error) {
1490
- if (error instanceof ky.HTTPError) {
1491
- const details = await error.response.json();
1492
- if (error.response.status === 409 && isSkippedReason(details.reason)) return {
1493
- reason: details.reason,
1494
- skipped: true
1495
- };
1496
- throw new Error(`Failed to trigger app upgrade (HTTP ${error.response.status}): ${JSON.stringify(details, null, 2)}`, { cause: error });
1497
- }
1498
- throw error;
1499
- }
1500
- }
1501
- /** Invokes the deployed app's upgrade endpoint. */
1502
- async function run$5() {
1503
- const { upgradeMode } = (await require_index_node.parseCommerceAppConfig()).metadata;
1504
- consola.consola.log("");
1505
- consola.consola.start("Checking for app upgrades...");
1506
- const request = await createUpgradeRequest();
1507
- const result = await invokeAction(request);
1508
- if (isSkippedResult(result)) {
1509
- consola.consola.info(`No upgrade was run: ${result.reason}.\n`);
1510
- return result;
1511
- }
1512
- if (upgradeMode === "manual") consola.consola.success(`You have set ${consola_utils.colors.cyan("metadata.upgradeMode")} to ${consola_utils.colors.cyan("manual")}. The upgrade plan has been created but will not be executed.`);
1513
- else consola.consola.success(`You have set ${consola_utils.colors.cyan("metadata.upgradeMode")} to ${consola_utils.colors.cyan("auto")}. The upgrade plan has been created. Execution will begin shortly.`);
1514
- consola.consola.box(["Upgrade plan", JSON.stringify(result.plan, null, 2)].join("\n\n"));
1515
- if (upgradeMode === "auto") await waitForAutomaticUpgrade(request);
1516
- return result;
1517
- }
1518
- /** Runs the post-app-deploy hook. */
1519
- async function exec$5() {
1520
- try {
1521
- await run$5();
58
+ await run$2(await require_web_src.loadAppManifest(projectRoot), projectRoot);
1522
59
  } catch (error) {
1523
60
  if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.consola.error(error.display());
1524
61
  else consola.consola.error(error);
@@ -1534,192 +71,17 @@ async function exec$5() {
1534
71
  * @param projectRoot - Resolved project root where artifacts are generated.
1535
72
  * @param templatesDir - Optional directory containing generation templates.
1536
73
  */
1537
- async function run$4(appManifest, projectRoot, templatesDir) {
1538
- await run$8(appManifest, projectRoot, templatesDir);
1539
- await run$7(appManifest, projectRoot);
1540
- await run$6(appManifest, projectRoot);
74
+ async function run$1(appManifest, projectRoot, templatesDir) {
75
+ await run$2(appManifest, projectRoot, templatesDir);
76
+ await require_web_src.run$1(appManifest, projectRoot);
77
+ await require_web_src.run(appManifest, projectRoot);
1541
78
  }
1542
79
  /** Runs the postinstall hook */
1543
- async function exec$4() {
80
+ async function exec$1() {
1544
81
  consola.default.debug("Running lib-app postinstall hook");
1545
82
  try {
1546
83
  const projectRoot = await require_index_node.getProjectRootDirectory();
1547
- await run$4(await loadAppManifest(projectRoot), projectRoot);
1548
- } catch (error) {
1549
- if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.default.error(error.display());
1550
- else consola.default.error(error);
1551
- process.exit(1);
1552
- }
1553
- }
1554
-
1555
- //#endregion
1556
- //#region ../../packages-private/scripting-utils/source/env.ts
1557
- /**
1558
- * This module exports shared environment utilities for the AIO Commerce SDK.
1559
- * @packageDocumentation
1560
- */
1561
- const { context } = _adobe_aio_lib_ims.default;
1562
- const IMS_KEYS = {
1563
- client_id: "AIO_COMMERCE_AUTH_IMS_CLIENT_ID",
1564
- client_secrets: "AIO_COMMERCE_AUTH_IMS_CLIENT_SECRETS",
1565
- ims_org_id: "AIO_COMMERCE_AUTH_IMS_ORG_ID",
1566
- scopes: "AIO_COMMERCE_AUTH_IMS_SCOPES",
1567
- technical_account_email: "AIO_COMMERCE_AUTH_IMS_TECHNICAL_ACCOUNT_EMAIL",
1568
- technical_account_id: "AIO_COMMERCE_AUTH_IMS_TECHNICAL_ACCOUNT_ID"
1569
- };
1570
- /**
1571
- * Replaces or creates an environment variable in a .env file
1572
- * @param filePath - The path to the .env file
1573
- * @param key - The environment variable key to replace or create
1574
- * @param value - The new value for the environment variable
1575
- */
1576
- function replaceEnvVar(filePath, key, value) {
1577
- const envPath = path.default.resolve(filePath);
1578
- const envLines = (0, fs.readFileSync)(envPath, "utf8").split("\n");
1579
- const formattedValue = value.includes(" ") ? `"${value}"` : value;
1580
- let keyExists = false;
1581
- const updatedLines = envLines.map((line) => {
1582
- if (line.trim().startsWith("#") || !line.includes("=")) return line;
1583
- const [currentKey] = line.split("=");
1584
- if (currentKey === key) {
1585
- keyExists = true;
1586
- return `${key}=${formattedValue}`;
1587
- }
1588
- return line;
1589
- });
1590
- if (!keyExists) updatedLines.push(`${key}=${formattedValue}`);
1591
- (0, fs.writeFileSync)(envPath, updatedLines.join("\n"), "utf8");
1592
- }
1593
- /**
1594
- * Sets the `NODE_ENV` environment variable in the app `.env` file, so the web
1595
- * bundler (Parcel) ships the matching React build. Creates the `.env` if absent.
1596
- * @param mode - The environment mode to write into `NODE_ENV`.
1597
- * @param projectRoot - Resolved project root containing the `.env` file.
1598
- */
1599
- function setNodeEnv(mode, projectRoot) {
1600
- const envPath = path.default.join(projectRoot, ".env");
1601
- if (!(0, fs.existsSync)(envPath)) (0, fs.writeFileSync)(envPath, "", "utf8");
1602
- replaceEnvVar(envPath, "NODE_ENV", mode);
1603
- }
1604
- /** Resolves the IMS server to server context from the project workspace credentials. */
1605
- function resolveImsS2SContext() {
1606
- const [credential] = (_adobe_aio_lib_core_config.default.get("project.workspace.details.credentials") ?? []).filter(({ integration_type }) => integration_type === "oauth_server_to_server").map(({ name }) => name);
1607
- if (!credential) return Promise.resolve(null);
1608
- return context.get(credential);
1609
- }
1610
- /**
1611
- * Syncs the IMS credentials environment variables from the configured IMS context in
1612
- * the .env file, in a way that is compatible with `@adobe/aio-commerce-lib-auth`.
1613
- * @param projectRoot - Resolved project root containing the `.env` file.
1614
- */
1615
- async function syncImsCredentials(projectRoot) {
1616
- const envPath = path.default.join(projectRoot, ".env");
1617
- if (!(0, fs.existsSync)(envPath)) return {
1618
- ok: false,
1619
- reason: "missing-env"
1620
- };
1621
- const envVars = dotenv.default.parse((0, fs.readFileSync)(envPath, "utf8"));
1622
- const imsContext = await resolveImsS2SContext();
1623
- if (!imsContext) return {
1624
- ok: false,
1625
- reason: "no-ims-context"
1626
- };
1627
- const { data } = imsContext;
1628
- for (const [key, value] of Object.entries(data)) {
1629
- const oauthKey = IMS_KEYS[key];
1630
- if (!oauthKey) continue;
1631
- if (!envVars[oauthKey] || envVars[oauthKey] !== value) replaceEnvVar(envPath, oauthKey, value);
1632
- }
1633
- return { ok: true };
1634
- }
1635
-
1636
- //#endregion
1637
- //#region source/commands/hooks/pre-app-build.ts
1638
- /**
1639
- * Runs the pre-app-build hook for the given extension.
1640
- * @param extension - The extension to run the hook for.
1641
- * @param projectRoot - Resolved project root containing extension files.
1642
- * @param templatesDir - Directory containing action templates.
1643
- */
1644
- async function run$3(extension, projectRoot, templatesDir = TEMPLATES_DIR) {
1645
- const appManifest = await loadAppManifest(projectRoot);
1646
- await prepareRuntimeAppConfigModule(appManifest, projectRoot);
1647
- if (extension === "extensibility/1") {
1648
- const { doc: extensibilityExtConfig } = await readExtConfig(EXTENSIBILITY_EXTENSION_POINT_ID, projectRoot);
1649
- await run$7(appManifest, projectRoot);
1650
- await generateActionFiles(appManifest, getRuntimeActions(extensibilityExtConfig.toJS(), "app-management"), EXTENSIBILITY_EXTENSION_POINT_ID, templatesDir, projectRoot);
1651
- consola.default.info("Syncing IMS credentials...");
1652
- await syncImsCredentials(projectRoot);
1653
- return;
1654
- }
1655
- if (extension === "configuration/1") {
1656
- const { doc: businessConfigExtConfig } = await readExtConfig(CONFIGURATION_EXTENSION_POINT_ID, projectRoot);
1657
- await run$6(appManifest, projectRoot);
1658
- await generateActionFiles(appManifest, getRuntimeActions(businessConfigExtConfig.toJS(), "business-configuration"), CONFIGURATION_EXTENSION_POINT_ID, templatesDir, projectRoot);
1659
- return;
1660
- }
1661
- if (extension === "backend-ui/2") {
1662
- if (require_webhooks.hasBackendUiV2Components(appManifest)) {
1663
- const extConfig = await updateExtConfig(appManifest, BACKEND_UI_V2_EXTENSION_POINT_ID, projectRoot);
1664
- if (extConfig.operations?.view) {
1665
- await prepareWebSourceImportAlias(extConfig, projectRoot);
1666
- await generateWebSrc(extConfig, appManifest.metadata.displayName, projectRoot, templatesDir);
1667
- await setNodeEnv("production", projectRoot);
1668
- }
1669
- }
1670
- return;
1671
- }
1672
- throw new Error(`Unsupported extension: ${extension}`);
1673
- }
1674
- /** Runs the pre-app-build hook */
1675
- async function exec$3() {
1676
- consola.default.debug("Running lib-app pre-app-build hook");
1677
- const rawExtension = process.env.EXTENSION;
1678
- try {
1679
- if (!rawExtension) throw new Error("EXTENSION environment variable is not set");
1680
- await run$3(rawExtension, await require_index_node.getProjectRootDirectory());
1681
- } catch (error) {
1682
- if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.default.error(error.display());
1683
- else consola.default.error(error);
1684
- process.exit(1);
1685
- }
1686
- }
1687
-
1688
- //#endregion
1689
- //#region source/commands/hooks/pre-app-dev.ts
1690
- /**
1691
- * Resets the web build back to development by writing `NODE_ENV` to the project `.env`.
1692
- * @param projectRoot - Resolved project root containing the `.env` file.
1693
- */
1694
- async function run$2(projectRoot) {
1695
- await setNodeEnv("development", projectRoot);
1696
- }
1697
- /** Runs the pre-app-dev hook. */
1698
- async function exec$2() {
1699
- consola.default.debug("Running lib-app pre-app-dev hook");
1700
- try {
1701
- await run$2(await require_index_node.getProjectRootDirectory());
1702
- } catch (error) {
1703
- if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.default.error(error.display());
1704
- else consola.default.error(error);
1705
- process.exit(1);
1706
- }
1707
- }
1708
-
1709
- //#endregion
1710
- //#region source/commands/hooks/pre-app-run.ts
1711
- /**
1712
- * Resets the web build back to development by writing `NODE_ENV` to the project `.env`.
1713
- * @param projectRoot - Resolved project root containing the `.env` file.
1714
- */
1715
- async function run$1(projectRoot) {
1716
- await setNodeEnv("development", projectRoot);
1717
- }
1718
- /** Runs the pre-app-run hook. */
1719
- async function exec$1() {
1720
- consola.default.debug("Running lib-app pre-app-run hook");
1721
- try {
1722
- await run$1(await require_index_node.getProjectRootDirectory());
84
+ await run$1(await require_web_src.loadAppManifest(projectRoot), projectRoot);
1723
85
  } catch (error) {
1724
86
  if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.default.error(error.display());
1725
87
  else consola.default.error(error);
@@ -1814,7 +176,7 @@ const DOMAIN_DEFAULTS = {
1814
176
  * @param flags - The initialization options
1815
177
  */
1816
178
  function initFlagsToScaffoldAppAnswers(flags) {
1817
- const configFile = `${COMMERCE_APP_CONFIG_FILE}.${flags.configFormat}`;
179
+ const configFile = `${require_web_src.COMMERCE_APP_CONFIG_FILE}.${flags.configFormat}`;
1818
180
  return {
1819
181
  appName: flags.appName,
1820
182
  configFile,
@@ -1872,7 +234,7 @@ async function promptForCommerceAppConfig() {
1872
234
  required: true,
1873
235
  type: "multiselect"
1874
236
  });
1875
- const configFile = `${COMMERCE_APP_CONFIG_FILE}.${configFormat}`;
237
+ const configFile = `${require_web_src.COMMERCE_APP_CONFIG_FILE}.${configFormat}`;
1876
238
  const domains = new Set(featuresToAdd);
1877
239
  consola.default.log("");
1878
240
  return {
@@ -1917,28 +279,28 @@ async function getDefaultCommerceAppConfig(cwd, { appName, configFormat, domains
1917
279
  * @param commentBefore - The comment to add before the extension point include pair.
1918
280
  */
1919
281
  async function addExtensionPointToAppConfig(extensionPointId, rootDirectory, commentBefore) {
1920
- const appConfigPath = (0, path.join)(rootDirectory, APP_CONFIG_FILE);
282
+ const appConfigPath = (0, path.join)(rootDirectory, require_web_src.APP_CONFIG_FILE);
1921
283
  let doc;
1922
- const includePath = (0, path.relative)(rootDirectory, (0, path.join)(rootDirectory, getExtConfigPath(extensionPointId)));
284
+ const includePath = (0, path.relative)(rootDirectory, (0, path.join)(rootDirectory, require_web_src.getExtConfigPath(extensionPointId)));
1923
285
  try {
1924
- doc = await readYamlFile(appConfigPath);
286
+ doc = await require_web_src.readYamlFile(appConfigPath);
1925
287
  } catch (error) {
1926
288
  const fallbackContent = `extensions:\n ${extensionPointId}:\n $include: "${includePath}"`;
1927
- throw new Error(`Failed to parse ${APP_CONFIG_FILE}. \nPlease add manually: \n\n${fallbackContent}`, { cause: error });
289
+ throw new Error(`Failed to parse ${require_web_src.APP_CONFIG_FILE}. \nPlease add manually: \n\n${fallbackContent}`, { cause: error });
1928
290
  }
1929
291
  if (doc.getIn([
1930
292
  "extensions",
1931
293
  extensionPointId,
1932
294
  "$include"
1933
295
  ]) === includePath) {
1934
- consola.default.success(`Extension "${extensionPointId}" already configured in ${APP_CONFIG_FILE}`);
296
+ consola.default.success(`Extension "${extensionPointId}" already configured in ${require_web_src.APP_CONFIG_FILE}`);
1935
297
  return;
1936
298
  }
1937
- consola.default.info(`Adding extension "${extensionPointId}" to ${APP_CONFIG_FILE}...`);
1938
- const extensions = getOrCreateMap(doc, ["extensions"], { onBeforeCreate: (pair) => {
299
+ consola.default.info(`Adding extension "${extensionPointId}" to ${require_web_src.APP_CONFIG_FILE}...`);
300
+ const extensions = require_web_src.getOrCreateMap(doc, ["extensions"], { onBeforeCreate: (pair) => {
1939
301
  pair.key.spaceBefore = true;
1940
302
  } });
1941
- getOrCreateMap(doc, ["extensions", extensionPointId], { onBeforeCreate: (pair) => {
303
+ require_web_src.getOrCreateMap(doc, ["extensions", extensionPointId], { onBeforeCreate: (pair) => {
1942
304
  pair.key.spaceBefore = extensions.items.length > 0;
1943
305
  pair.key.commentBefore = commentBefore;
1944
306
  } }).set("$include", includePath);
@@ -1951,23 +313,23 @@ async function addExtensionPointToAppConfig(extensionPointId, rootDirectory, com
1951
313
  * @param commentBefore - The comment to add before the extension point include pair.
1952
314
  */
1953
315
  async function addExtensionPointToInstallYaml(extensionPointId, rootDirectory, commentBefore) {
1954
- const installYamlPath = (0, path.join)(rootDirectory, INSTALL_YAML_FILE);
316
+ const installYamlPath = (0, path.join)(rootDirectory, require_web_src.INSTALL_YAML_FILE);
1955
317
  let doc;
1956
318
  let extensions;
1957
319
  try {
1958
- doc = await readYamlFile(installYamlPath);
1959
- extensions = getOrCreateSeq(doc, ["extensions"], { onBeforeCreate: (pair) => {
320
+ doc = await require_web_src.readYamlFile(installYamlPath);
321
+ extensions = require_web_src.getOrCreateSeq(doc, ["extensions"], { onBeforeCreate: (pair) => {
1960
322
  pair.key.spaceBefore = true;
1961
323
  } });
1962
324
  } catch (error) {
1963
325
  const fallbackContent = `\nextensions:\n - extensionPointId: ${extensionPointId}`;
1964
- throw new Error(`Failed to parse ${INSTALL_YAML_FILE}. \nPlease add manually: \n\n${fallbackContent}`, { cause: error });
326
+ throw new Error(`Failed to parse ${require_web_src.INSTALL_YAML_FILE}. \nPlease add manually: \n\n${fallbackContent}`, { cause: error });
1965
327
  }
1966
328
  if (extensions.items.some((item) => (0, yaml.isMap)(item) && item.get("extensionPointId") === extensionPointId)) {
1967
- consola.default.success(`Extension "${extensionPointId}" already configured in ${INSTALL_YAML_FILE}`);
329
+ consola.default.success(`Extension "${extensionPointId}" already configured in ${require_web_src.INSTALL_YAML_FILE}`);
1968
330
  return;
1969
331
  }
1970
- consola.default.info(`Adding extension "${extensionPointId}" to ${INSTALL_YAML_FILE}...`);
332
+ consola.default.info(`Adding extension "${extensionPointId}" to ${require_web_src.INSTALL_YAML_FILE}...`);
1971
333
  const extension = doc.createPair("extensionPointId", extensionPointId);
1972
334
  extension.key.spaceBefore = extensions.items.length > 0;
1973
335
  extension.key.commentBefore = commentBefore;
@@ -1988,17 +350,17 @@ async function ensureCommerceAppConfig(projectRoot, formatConfig = true, flags)
1988
350
  if (configFilePath !== null) try {
1989
351
  const config = await require_index_node.readCommerceAppConfig(projectRoot);
1990
352
  const validatedConfig = require_validate.validateCommerceAppConfig(config);
1991
- consola.consola.success(`${COMMERCE_APP_CONFIG_FILE} found and is valid. Continuing...`);
353
+ consola.consola.success(`${require_web_src.COMMERCE_APP_CONFIG_FILE} found and is valid. Continuing...`);
1992
354
  return {
1993
355
  config: validatedConfig,
1994
356
  configFormat: require_index_node.isTypeScriptConfig(configFilePath) ? "ts" : "js",
1995
357
  domains: require_validate.getConfigDomains(validatedConfig)
1996
358
  };
1997
359
  } catch (error) {
1998
- throw new Error(`${COMMERCE_APP_CONFIG_FILE} is invalid`, { cause: error });
360
+ throw new Error(`${require_web_src.COMMERCE_APP_CONFIG_FILE} is invalid`, { cause: error });
1999
361
  }
2000
362
  if (!flags) {
2001
- consola.consola.warn(`${COMMERCE_APP_CONFIG_FILE} not found.`);
363
+ consola.consola.warn(`${require_web_src.COMMERCE_APP_CONFIG_FILE} not found.`);
2002
364
  if (!await consola.consola.prompt(`Do you want to create a ${"app.commerce.config"} file? (y/n)`, {
2003
365
  default: false,
2004
366
  initial: true,
@@ -2008,12 +370,12 @@ async function ensureCommerceAppConfig(projectRoot, formatConfig = true, flags)
2008
370
  const answers = flags ? initFlagsToScaffoldAppAnswers(flags) : await promptForCommerceAppConfig();
2009
371
  try {
2010
372
  const configContent = await getDefaultCommerceAppConfig(projectRoot, answers);
2011
- const path$2 = (0, path.join)(projectRoot, answers.configFile);
373
+ const path$1 = (0, path.join)(projectRoot, answers.configFile);
2012
374
  consola.consola.info(`Creating ${answers.configFile}...`);
2013
375
  if (formatConfig) {
2014
- const formattedConfig = await prettierFormat(configContent, path$2);
2015
- await (0, fs_promises.writeFile)(path$2, formattedConfig, "utf-8");
2016
- } else await (0, fs_promises.writeFile)(path$2, configContent, "utf-8");
376
+ const formattedConfig = await require_web_src.prettierFormat(configContent, path$1);
377
+ await (0, fs_promises.writeFile)(path$1, formattedConfig, "utf-8");
378
+ } else await (0, fs_promises.writeFile)(path$1, configContent, "utf-8");
2017
379
  const createdConfig = await require_index_node.parseCommerceAppConfig(projectRoot);
2018
380
  consola.consola.success(`Created ${answers.configFile}`);
2019
381
  return {
@@ -2040,7 +402,7 @@ async function ensurePackageJson(cwd = process.cwd()) {
2040
402
  private: true,
2041
403
  version: "1.0.0"
2042
404
  };
2043
- await (0, fs_promises.writeFile)((0, path.join)((0, path.resolve)(cwd), PACKAGE_JSON_FILE), JSON.stringify(packageJson, null, 2), "utf-8");
405
+ await (0, fs_promises.writeFile)((0, path.join)((0, path.resolve)(cwd), require_web_src.PACKAGE_JSON_FILE), JSON.stringify(packageJson, null, 2), "utf-8");
2044
406
  consola.consola.success("Wrote package.json");
2045
407
  }
2046
408
  const projectRoot = await require_index_node.getProjectRootDirectory(cwd);
@@ -2063,18 +425,18 @@ async function writePostinstallHook(execCommand, projectRoot) {
2063
425
  if (pkg === null) throw new Error("Could not find package.json.");
2064
426
  const existing = pkg.content.scripts?.postinstall;
2065
427
  if (existing === postinstallScript || existing?.includes(postinstallScript)) {
2066
- consola.consola.success(`postinstall script already configured in ${PACKAGE_JSON_FILE}`);
428
+ consola.consola.success(`postinstall script already configured in ${require_web_src.PACKAGE_JSON_FILE}`);
2067
429
  return;
2068
430
  }
2069
431
  const nextPostinstall = require_index_node.appendCommand(existing, postinstallScript);
2070
- if (existing) consola.consola.warn(`${PACKAGE_JSON_FILE} already has a postinstall script. Adding a new one...`);
2071
- else consola.consola.info(`Adding postinstall script to ${PACKAGE_JSON_FILE}...`);
432
+ if (existing) consola.consola.warn(`${require_web_src.PACKAGE_JSON_FILE} already has a postinstall script. Adding a new one...`);
433
+ else consola.consola.info(`Adding postinstall script to ${require_web_src.PACKAGE_JSON_FILE}...`);
2072
434
  pkg.update({ scripts: {
2073
435
  ...pkg.content.scripts,
2074
436
  postinstall: nextPostinstall
2075
437
  } });
2076
438
  await pkg.save();
2077
- consola.consola.success(`Added postinstall script to ${PACKAGE_JSON_FILE}`);
439
+ consola.consola.success(`Added postinstall script to ${require_web_src.PACKAGE_JSON_FILE}`);
2078
440
  }
2079
441
  /**
2080
442
  * Ensures app.config.yaml references the enabled domain extensions.
@@ -2083,9 +445,9 @@ async function writePostinstallHook(execCommand, projectRoot) {
2083
445
  * @param projectRoot - Resolved project root containing app.config.yaml.
2084
446
  */
2085
447
  async function ensureAppConfig(domains, config, projectRoot) {
2086
- if (domains.has("businessConfig.schema")) await addExtensionPointToAppConfig(CONFIGURATION_EXTENSION_POINT_ID, projectRoot, " This extension is required for business configuration. Do not remove.");
2087
- if (require_webhooks.hasBackendUiV2Components(config)) await addExtensionPointToAppConfig(BACKEND_UI_V2_EXTENSION_POINT_ID, projectRoot, " This extension is required for Admin UI. Do not remove.");
2088
- await addExtensionPointToAppConfig(EXTENSIBILITY_EXTENSION_POINT_ID, projectRoot, " This extension is required for app management. Do not remove.");
448
+ if (domains.has("businessConfig.schema")) await addExtensionPointToAppConfig(require_web_src.CONFIGURATION_EXTENSION_POINT_ID, projectRoot, " This extension is required for business configuration. Do not remove.");
449
+ if (require_webhooks.hasBackendUiV2Components(config)) await addExtensionPointToAppConfig(require_web_src.BACKEND_UI_V2_EXTENSION_POINT_ID, projectRoot, " This extension is required for Admin UI. Do not remove.");
450
+ await addExtensionPointToAppConfig(require_web_src.EXTENSIBILITY_EXTENSION_POINT_ID, projectRoot, " This extension is required for app management. Do not remove.");
2089
451
  }
2090
452
  /**
2091
453
  * Install the domain-specific dependencies derived from the selected domains.
@@ -2100,7 +462,7 @@ function installDependencies(packageManager, domains, projectRoot) {
2100
462
  consola.consola.info("No additional domain dependencies to install.");
2101
463
  return;
2102
464
  }
2103
- runInstall(packageManager, packages, projectRoot);
465
+ require_web_src.runInstall(packageManager, packages, projectRoot);
2104
466
  }
2105
467
  /**
2106
468
  * Generates all project artifacts during initialization.
@@ -2110,9 +472,9 @@ function installDependencies(packageManager, domains, projectRoot) {
2110
472
  */
2111
473
  async function runGeneration(appConfig, execCommand, projectRoot) {
2112
474
  try {
2113
- await run$8(appConfig, projectRoot);
2114
- await run$7(appConfig, projectRoot);
2115
- await run$6(appConfig, projectRoot);
475
+ await run$2(appConfig, projectRoot);
476
+ await require_web_src.run$1(appConfig, projectRoot);
477
+ await require_web_src.run(appConfig, projectRoot);
2116
478
  } catch (error) {
2117
479
  throw new Error(`Failed to run generation command. Please run manually: ${execCommand} aio-commerce-lib-app generate all`, { cause: error });
2118
480
  }
@@ -2124,14 +486,14 @@ async function runGeneration(appConfig, execCommand, projectRoot) {
2124
486
  * @param projectRoot - Resolved project root containing install.yaml.
2125
487
  */
2126
488
  async function ensureInstallYaml(domains, config, projectRoot) {
2127
- if (domains.has("businessConfig.schema")) await addExtensionPointToInstallYaml(CONFIGURATION_EXTENSION_POINT_ID, projectRoot, " This extension is required for business configuration. Do not remove.");
2128
- if (require_webhooks.hasBackendUiV2Components(config)) await addExtensionPointToInstallYaml(BACKEND_UI_V2_EXTENSION_POINT_ID, projectRoot, " This extension is required for Admin UI. Do not remove.");
2129
- await addExtensionPointToInstallYaml(EXTENSIBILITY_EXTENSION_POINT_ID, projectRoot, " This extension is required for app management. Do not remove.");
489
+ if (domains.has("businessConfig.schema")) await addExtensionPointToInstallYaml(require_web_src.CONFIGURATION_EXTENSION_POINT_ID, projectRoot, " This extension is required for business configuration. Do not remove.");
490
+ if (require_webhooks.hasBackendUiV2Components(config)) await addExtensionPointToInstallYaml(require_web_src.BACKEND_UI_V2_EXTENSION_POINT_ID, projectRoot, " This extension is required for Admin UI. Do not remove.");
491
+ await addExtensionPointToInstallYaml(require_web_src.EXTENSIBILITY_EXTENSION_POINT_ID, projectRoot, " This extension is required for app management. Do not remove.");
2130
492
  }
2131
493
 
2132
494
  //#endregion
2133
495
  //#region source/commands/init/main.ts
2134
- const REQUIRED_DEPENDENCIES = ["@adobe/aio-commerce-sdk", `@adobe/aio-commerce-lib-app@2.0.0`];
496
+ const REQUIRED_DEPENDENCIES = ["@adobe/aio-commerce-sdk", `@adobe/aio-commerce-lib-app@2.0.1-alpha-20260923160203`];
2135
497
  /**
2136
498
  * Initializes a Commerce App project.
2137
499
  * @param flags - Non-interactive initialization answers.
@@ -2141,11 +503,11 @@ async function run(flags, extraOptions) {
2141
503
  consola.consola.start("Initializing app...");
2142
504
  const cwd = extraOptions?.cwd ?? process.cwd();
2143
505
  const { execCommand, packageManager, projectRoot } = await ensurePackageJson(cwd);
2144
- runInstall(packageManager, REQUIRED_DEPENDENCIES, projectRoot);
506
+ require_web_src.runInstall(packageManager, REQUIRED_DEPENDENCIES, projectRoot);
2145
507
  const { config, domains, configFormat } = await ensureCommerceAppConfig(projectRoot, extraOptions?.formatConfig ?? true, flags);
2146
508
  const isTypeScriptProject = configFormat === "ts";
2147
509
  installDependencies(packageManager, domains, projectRoot);
2148
- if (isTypeScriptProject) await scaffoldTypeScriptProject(packageManager, projectRoot);
510
+ if (isTypeScriptProject) await require_web_src.scaffoldTypeScriptProject(packageManager, projectRoot);
2149
511
  const pkg = await require_index_node.loadPackageJson(projectRoot);
2150
512
  if (pkg === null) throw new Error("Could not find package.json.");
2151
513
  pkg.update({
@@ -2154,7 +516,7 @@ async function run(flags, extraOptions) {
2154
516
  version: config.metadata.version
2155
517
  });
2156
518
  await pkg.save();
2157
- if (isTypeScriptProject) await syncActionsTypecheckScript(projectRoot);
519
+ if (isTypeScriptProject) await require_web_src.syncActionsTypecheckScript(projectRoot);
2158
520
  await runGeneration(config, execCommand, projectRoot);
2159
521
  await ensureAppConfig(domains, config, projectRoot);
2160
522
  await ensureInstallYaml(domains, config, projectRoot);
@@ -2204,25 +566,19 @@ Examples:
2204
566
  `;
2205
567
  /** Run all generate targets in sequence */
2206
568
  async function generateAll() {
2207
- await exec$8();
2208
- await exec$7();
2209
- await exec$6();
569
+ await exec$2();
570
+ await require_web_src.exec$1();
571
+ await require_web_src.exec();
2210
572
  }
2211
573
  /** Command handlers registry mapping command names to their subcommand handlers */
2212
574
  const COMMANDS = {
2213
575
  generate: {
2214
- actions: exec$8,
576
+ actions: exec$2,
2215
577
  all: generateAll,
2216
- manifest: exec$7,
2217
- schema: exec$6
2218
- },
2219
- hooks: {
2220
- "post-app-deploy": exec$5,
2221
- postinstall: exec$4,
2222
- "pre-app-build": exec$3,
2223
- "pre-app-dev": exec$2,
2224
- "pre-app-run": exec$1
578
+ manifest: require_web_src.exec$1,
579
+ schema: require_web_src.exec
2225
580
  },
581
+ hooks: { postinstall: exec$1 },
2226
582
  init: exec
2227
583
  };
2228
584
  /**