@adobe/aio-commerce-lib-app 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -0
- package/dist/cjs/actions/app-config.cjs +3 -3
- package/dist/cjs/actions/app-config.d.cts +1 -1
- package/dist/cjs/actions/config.cjs +31 -9
- package/dist/cjs/actions/installation.cjs +16 -13
- package/dist/cjs/actions/installation.d.cts +2 -2
- package/dist/cjs/actions/registration.cjs +41 -0
- package/dist/cjs/actions/registration.d.cts +33 -0
- package/dist/cjs/actions/scope-tree.cjs +5 -4
- package/dist/cjs/admin-ui-sdk-BiSopnKI.d.cts +665 -0
- package/dist/cjs/{app-DcQMhW2N.d.cts → app-C6kImBl7.d.cts} +242 -16
- package/dist/cjs/chunk-DS2yp5vX.cjs +48 -0
- package/dist/cjs/commands/index.cjs +582 -319
- package/dist/cjs/commands/templates/admin-ui-sdk/registration.js.template +20 -0
- package/dist/cjs/config/index.cjs +4 -3
- package/dist/cjs/config/index.d.cts +558 -62
- package/dist/cjs/{config-BppBKCFj.cjs → config-ct-qMOGj.cjs} +56 -25
- package/dist/cjs/{error-Dn7ool6k.cjs → error-C5LNOZ4f.cjs} +1 -1
- package/dist/cjs/{index-BVwQk9bx.d.cts → index-B5WKJ3hJ.d.cts} +20 -174
- package/dist/cjs/{logging-4s36JTiN.cjs → logging-BTevALnL.cjs} +2 -2
- package/dist/cjs/management/index.cjs +1 -1
- package/dist/cjs/management/index.d.cts +3 -2
- package/dist/cjs/{management-C6xG5bfl.cjs → management-D1QXg4YU.cjs} +128 -75
- package/dist/cjs/{router-KeQRduO3.cjs → router-CFErodHU.cjs} +2 -2
- package/dist/cjs/{schemas-nkIxa8sL.cjs → schemas-CukVpc19.cjs} +2 -34
- package/dist/cjs/step-CWYnKbga.d.cts +187 -0
- package/dist/cjs/{validate-CeUCT_7k.cjs → validate-b_bI4mDb.cjs} +4 -3
- package/dist/cjs/{webhooks-CLtDxwMa.cjs → webhooks-DS1BtgED.cjs} +157 -17
- package/dist/es/actions/app-config.d.mts +1 -1
- package/dist/es/actions/app-config.mjs +1 -1
- package/dist/es/actions/config.mjs +28 -7
- package/dist/es/actions/installation.d.mts +2 -2
- package/dist/es/actions/installation.mjs +12 -10
- package/dist/es/actions/registration.d.mts +33 -0
- package/dist/es/actions/registration.mjs +39 -0
- package/dist/es/actions/scope-tree.mjs +1 -1
- package/dist/es/admin-ui-sdk-CCo2SWiL.d.mts +667 -0
- package/dist/es/{app-DJr-mN9d.d.mts → app-DcY6dJiQ.d.mts} +242 -16
- package/dist/es/commands/index.mjs +575 -314
- package/dist/es/commands/templates/admin-ui-sdk/registration.js.template +20 -0
- package/dist/es/config/index.d.mts +558 -62
- package/dist/es/config/index.mjs +4 -4
- package/dist/es/{config-BohwKkQS.mjs → config-DGPFTk6w.mjs} +51 -20
- package/dist/es/{index-BENO5T7n.d.mts → index-CCov0odd.d.mts} +20 -174
- package/dist/es/management/index.d.mts +3 -2
- package/dist/es/management/index.mjs +1 -1
- package/dist/es/{management-ByHvVJ12.mjs → management-CCsOfniv.mjs} +124 -71
- package/dist/es/step-0eI2x4C9.d.mts +187 -0
- package/dist/es/{validate-CqJdGzyZ.mjs → validate-Dn3lLTGj.mjs} +2 -2
- package/dist/es/{webhooks-CYo-pqbR.mjs → webhooks-Dhrkkip7.mjs} +155 -16
- package/package.json +12 -9
- /package/dist/cjs/commands/{generate/actions/templates → templates}/app-management/app-config.js.template +0 -0
- /package/dist/cjs/commands/{generate/actions/templates → templates}/app-management/custom-scripts.js.template +0 -0
- /package/dist/cjs/commands/{generate/actions/templates → templates}/app-management/installation.js.template +0 -0
- /package/dist/cjs/commands/{generate/actions/templates → templates}/business-configuration/config.js.template +0 -0
- /package/dist/cjs/commands/{generate/actions/templates → templates}/business-configuration/scope-tree.js.template +0 -0
- /package/dist/es/commands/{generate/actions/templates → templates}/app-management/app-config.js.template +0 -0
- /package/dist/es/commands/{generate/actions/templates → templates}/app-management/custom-scripts.js.template +0 -0
- /package/dist/es/commands/{generate/actions/templates → templates}/app-management/installation.js.template +0 -0
- /package/dist/es/commands/{generate/actions/templates → templates}/business-configuration/config.js.template +0 -0
- /package/dist/es/commands/{generate/actions/templates → templates}/business-configuration/scope-tree.js.template +0 -0
- /package/dist/es/{schemas-CVXHgUhv.mjs → schemas-DOcnD16x.mjs} +0 -0
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
* governing permissions and limitations under the License.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { a as hasCustomInstallationSteps } from "../webhooks-
|
|
17
|
-
import { c as hasBusinessConfigSchema, i as getConfigDomains, t as validateCommerceAppConfig } from "../validate-
|
|
18
|
-
import { a as
|
|
16
|
+
import { a as hasCustomInstallationSteps, d as hasAdminUiSdk } from "../webhooks-Dhrkkip7.mjs";
|
|
17
|
+
import { c as hasBusinessConfigSchema, i as getConfigDomains, t as validateCommerceAppConfig } from "../validate-Dn3lLTGj.mjs";
|
|
18
|
+
import { a as getExecCommand, c as isESM, i as detectPackageManager, l as makeOutputDirFor, n as readCommerceAppConfig, o as getInstallCommand, s as getProjectRootDirectory, t as parseCommerceAppConfig, u as readPackageJson } from "../config-DGPFTk6w.mjs";
|
|
19
19
|
import { t as stringifyError } from "../error-DHlYzkbb.mjs";
|
|
20
20
|
import { t as inspect } from "../logging-XIUXDK5T.mjs";
|
|
21
21
|
import { CommerceSdkValidationError } from "@adobe/aio-commerce-lib-core/error";
|
|
@@ -23,16 +23,257 @@ import path, { basename, dirname, join, relative, resolve } from "path";
|
|
|
23
23
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
24
24
|
import { readFile, writeFile } from "fs/promises";
|
|
25
25
|
import consola, { consola as consola$1 } from "consola";
|
|
26
|
+
import * as prettier from "prettier";
|
|
26
27
|
import { fileURLToPath } from "url";
|
|
27
28
|
import { Document, YAMLMap, YAMLSeq, isMap, isSeq, parseDocument } from "yaml";
|
|
28
29
|
import { colorize, formatTree } from "consola/utils";
|
|
29
|
-
import { stringify } from "safe-stable-stringify";
|
|
30
|
-
import { execSync } from "child_process";
|
|
30
|
+
import stringify, { stringify as stringify$1 } from "safe-stable-stringify";
|
|
31
|
+
import { execSync, spawnSync } from "child_process";
|
|
31
32
|
import config from "@adobe/aio-lib-core-config";
|
|
32
33
|
import aioIms from "@adobe/aio-lib-ims";
|
|
33
34
|
import dotenv from "dotenv";
|
|
34
|
-
import
|
|
35
|
+
import NpmPackageJson from "@npmcli/package-json";
|
|
36
|
+
|
|
37
|
+
//#region source/commands/constants.ts
|
|
38
|
+
/** The name of the package containing all the generated runtime actions */
|
|
39
|
+
const PACKAGE_NAME = "app-management";
|
|
40
|
+
/** The path to the directory containing the generated files */
|
|
41
|
+
const GENERATED_PATH = ".generated";
|
|
42
|
+
/** The folder name containing the runtime actions */
|
|
43
|
+
const ACTIONS_FOLDER = `actions/${PACKAGE_NAME}`;
|
|
44
|
+
/** The path to the directory containing the generated actions */
|
|
45
|
+
const GENERATED_ACTIONS_PATH = `${GENERATED_PATH}/${ACTIONS_FOLDER}`;
|
|
46
|
+
/** The name of the extension point for extensibility. */
|
|
47
|
+
const EXTENSIBILITY_EXTENSION_POINT_ID = "commerce/extensibility/1";
|
|
48
|
+
/** The name of the extension point for configuration. */
|
|
49
|
+
const CONFIGURATION_EXTENSION_POINT_ID = "commerce/configuration/1";
|
|
50
|
+
/** The name of the extension point for Admin UI SDK. */
|
|
51
|
+
const BACKEND_UI_EXTENSION_POINT_ID = "commerce/backend-ui/1";
|
|
52
|
+
/** The name of the package containing the admin UI SDK generated actions */
|
|
53
|
+
const ADMIN_UI_SDK_PACKAGE_NAME = "admin-ui-sdk";
|
|
54
|
+
/** The path to the directory containing the generated Admin UI SDK actions. */
|
|
55
|
+
const ADMIN_UI_SDK_ACTIONS_PATH = `${GENERATED_PATH}/actions/registration`;
|
|
56
|
+
/** The name of the configuration schema file */
|
|
57
|
+
const APP_MANIFEST_FILE = "app.commerce.manifest.json";
|
|
58
|
+
/** The name of the commerce app configuration file */
|
|
59
|
+
const COMMERCE_APP_CONFIG_FILE = "app.commerce.config";
|
|
60
|
+
/** The name of the configuration schema file */
|
|
61
|
+
const CONFIG_SCHEMA_FILE_NAME = "configuration-schema.json";
|
|
62
|
+
/** The name of the project package file */
|
|
63
|
+
const PACKAGE_JSON_FILE = "package.json";
|
|
64
|
+
/** The name of the app configuration file */
|
|
65
|
+
const APP_CONFIG_FILE = "app.config.yaml";
|
|
66
|
+
/** The name of the install configuration file */
|
|
67
|
+
const INSTALL_YAML_FILE = "install.yaml";
|
|
68
|
+
/** Get the path to the extension point folder */
|
|
69
|
+
function getExtensionPointFolderPath(extensionPointId) {
|
|
70
|
+
return `src/${extensionPointId.replaceAll("/", "-")}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region source/commands/utils.ts
|
|
75
|
+
/** Format file content using prettier, inferring the parser from the file path. */
|
|
76
|
+
function prettierFormat(content, filepath) {
|
|
77
|
+
return prettier.format(content, {
|
|
78
|
+
semi: true,
|
|
79
|
+
quoteStyle: "double",
|
|
80
|
+
arrowParens: "always",
|
|
81
|
+
bracketSameLine: true,
|
|
82
|
+
bracketSpacing: true,
|
|
83
|
+
trailingComma: "all",
|
|
84
|
+
tabWidth: 2,
|
|
85
|
+
useTabs: false,
|
|
86
|
+
printWidth: 80,
|
|
87
|
+
filepath
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/** Load the app commerce config */
|
|
91
|
+
async function loadAppManifest() {
|
|
92
|
+
const appConfig = await parseCommerceAppConfig();
|
|
93
|
+
consola.debug("Loaded app commerce config");
|
|
94
|
+
return appConfig;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Path to an extension point's `.generated` directory, relative to the project root.
|
|
98
|
+
* @param extensionPointId - The extension point ID, e.g. "commerce/extensibility/1"
|
|
99
|
+
*/
|
|
100
|
+
function getGeneratedDir(extensionPointId) {
|
|
101
|
+
return join(getExtensionPointFolderPath(extensionPointId), GENERATED_PATH);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Path to an extension point's generated actions directory, relative to the project root.
|
|
105
|
+
* @param extensionPointId - The extension point ID, e.g. "commerce/extensibility/1"
|
|
106
|
+
*/
|
|
107
|
+
function getActionsDir(extensionPointId) {
|
|
108
|
+
return join(getExtensionPointFolderPath(extensionPointId), GENERATED_ACTIONS_PATH);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Path to a specific generated action file, relative to the project root.
|
|
112
|
+
* @param extensionPointId - The extension point ID, e.g. "commerce/extensibility/1"
|
|
113
|
+
* @param actionName - The name of the action, e.g. "my-action"
|
|
114
|
+
*/
|
|
115
|
+
function getActionPath(extensionPointId, actionName) {
|
|
116
|
+
return join(getActionsDir(extensionPointId), `${actionName}.js`);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Path to an extension point's `ext.config.yaml`, relative to the project root.
|
|
120
|
+
* @param extensionPointId - The extension point ID, e.g. "commerce/extensibility/1"
|
|
121
|
+
*/
|
|
122
|
+
function getExtConfigPath(extensionPointId) {
|
|
123
|
+
return join(getExtensionPointFolderPath(extensionPointId), "ext.config.yaml");
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Path to an Admin UI SDK generated actions directory, relative to the project root.
|
|
127
|
+
* @param extensionPointId - The extension point ID, e.g. "commerce/backend-ui/1"
|
|
128
|
+
*/
|
|
129
|
+
function getAdminUiSdkActionsDir(extensionPointId) {
|
|
130
|
+
return join(getExtensionPointFolderPath(extensionPointId), ADMIN_UI_SDK_ACTIONS_PATH);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Path to the generated Admin UI SDK registration action file, relative to the project root.
|
|
134
|
+
* @param extensionPointId - The extension point ID, e.g. "commerce/backend-ui/1"
|
|
135
|
+
*/
|
|
136
|
+
function getAdminUiSdkRegistrationActionPath(extensionPointId) {
|
|
137
|
+
return join(getAdminUiSdkActionsDir(extensionPointId), "index.js");
|
|
138
|
+
}
|
|
35
139
|
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region source/commands/generate/actions/config.ts
|
|
142
|
+
/** The list of Commerce variables that are required for the runtime actions */
|
|
143
|
+
const COMMERCE_VARIABLES = [
|
|
144
|
+
"AIO_COMMERCE_AUTH_IMS_CLIENT_ID",
|
|
145
|
+
"AIO_COMMERCE_AUTH_IMS_CLIENT_SECRETS",
|
|
146
|
+
"AIO_COMMERCE_AUTH_IMS_TECHNICAL_ACCOUNT_ID",
|
|
147
|
+
"AIO_COMMERCE_AUTH_IMS_TECHNICAL_ACCOUNT_EMAIL",
|
|
148
|
+
"AIO_COMMERCE_AUTH_IMS_ORG_ID",
|
|
149
|
+
"AIO_COMMERCE_AUTH_IMS_SCOPES"
|
|
150
|
+
];
|
|
151
|
+
/** The inputs for the generated runtime actions */
|
|
152
|
+
const COMMERCE_ACTION_INPUTS = Object.fromEntries(COMMERCE_VARIABLES.map((variable) => [variable, `$${variable}`]));
|
|
153
|
+
const CUSTOM_IMPORTS_PLACEHOLDER = "// {{CUSTOM_SCRIPTS_IMPORTS}}";
|
|
154
|
+
const CUSTOM_SCRIPTS_MAP_PLACEHOLDER = "// {{CUSTOM_SCRIPTS_MAP}}";
|
|
155
|
+
const CUSTOM_SCRIPTS_LOADER_PLACEHOLDER = "// {{CUSTOM_SCRIPTS_LOADER}}";
|
|
156
|
+
const REGISTRATION_JSON_PLACEHOLDER = "// {{REGISTRATION_JSON}}";
|
|
157
|
+
/**
|
|
158
|
+
* Creates a runtime action configuration.
|
|
159
|
+
* @param actionName - The name of the action.
|
|
160
|
+
* @param options - Optional configuration options.
|
|
161
|
+
*/
|
|
162
|
+
function createActionDefinition(actionName, config = {}, options = {}) {
|
|
163
|
+
const def = {
|
|
164
|
+
...options,
|
|
165
|
+
function: `${GENERATED_ACTIONS_PATH}/${actionName}.js`,
|
|
166
|
+
web: options.web ?? "yes",
|
|
167
|
+
runtime: "nodejs:22",
|
|
168
|
+
annotations: {
|
|
169
|
+
"require-adobe-auth": true,
|
|
170
|
+
final: true
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
if (config.requiresEncryptionKey) def.inputs = {
|
|
174
|
+
...def.inputs,
|
|
175
|
+
AIO_COMMERCE_CONFIG_ENCRYPTION_KEY: "$AIO_COMMERCE_CONFIG_ENCRYPTION_KEY"
|
|
176
|
+
};
|
|
177
|
+
return def;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Gets the runtime actions to be generated from the ext.config.yaml configuration.
|
|
181
|
+
* @param extConfig - The ext.config.yaml configuration.
|
|
182
|
+
*/
|
|
183
|
+
function getRuntimeActions(extConfig, dir) {
|
|
184
|
+
return Object.entries(extConfig.runtimeManifest?.packages?.["app-management"]?.actions ?? {}).map(([name, _]) => ({
|
|
185
|
+
name,
|
|
186
|
+
templateFile: join(dir, `${name}.js.template`)
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Builds the ext.config.yaml configuration for the extensibility extension.
|
|
191
|
+
* @param features - The features that are enabled for the app.
|
|
192
|
+
*/
|
|
193
|
+
function buildAppManagementExtConfig(appConfig) {
|
|
194
|
+
const features = getConfigDomains(appConfig);
|
|
195
|
+
const hasPasswordFieldsInSchema = hasBusinessConfigSchema(appConfig) && appConfig.businessConfig.schema.some((field) => field.type === "password");
|
|
196
|
+
const extConfig = {
|
|
197
|
+
hooks: { "pre-app-build": "EXTENSION=extensibility/1 $packageExec aio-commerce-lib-app hooks pre-app-build" },
|
|
198
|
+
operations: { workerProcess: [{
|
|
199
|
+
type: "action",
|
|
200
|
+
impl: `${PACKAGE_NAME}/app-config`
|
|
201
|
+
}] },
|
|
202
|
+
runtimeManifest: { packages: { [PACKAGE_NAME]: {
|
|
203
|
+
license: "Apache-2.0",
|
|
204
|
+
actions: { "app-config": createActionDefinition("app-config") }
|
|
205
|
+
} } }
|
|
206
|
+
};
|
|
207
|
+
if ([
|
|
208
|
+
"installation.customInstallationSteps",
|
|
209
|
+
"eventing.commerce",
|
|
210
|
+
"eventing.external",
|
|
211
|
+
"webhooks",
|
|
212
|
+
"adminUiSdk"
|
|
213
|
+
].some((feature) => features.has(feature))) {
|
|
214
|
+
extConfig.operations.workerProcess.push({
|
|
215
|
+
type: "action",
|
|
216
|
+
impl: `${PACKAGE_NAME}/installation`
|
|
217
|
+
});
|
|
218
|
+
extConfig.runtimeManifest.packages[PACKAGE_NAME].actions.installation = createActionDefinition("installation", { requiresEncryptionKey: hasPasswordFieldsInSchema }, {
|
|
219
|
+
inputs: {
|
|
220
|
+
...COMMERCE_ACTION_INPUTS,
|
|
221
|
+
LOG_LEVEL: "$LOG_LEVEL"
|
|
222
|
+
},
|
|
223
|
+
limits: { timeout: 6e5 }
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return extConfig;
|
|
227
|
+
}
|
|
228
|
+
/** Builds the ext.config.yaml configuration for the business configuration extension. */
|
|
229
|
+
function buildBusinessConfigurationExtConfig() {
|
|
230
|
+
const actions = [{
|
|
231
|
+
name: "config",
|
|
232
|
+
templateFile: "config.js.template",
|
|
233
|
+
requiresEncryptionKey: true
|
|
234
|
+
}, {
|
|
235
|
+
name: "scope-tree",
|
|
236
|
+
templateFile: "scope-tree.js.template"
|
|
237
|
+
}];
|
|
238
|
+
return {
|
|
239
|
+
hooks: { "pre-app-build": "EXTENSION=configuration/1 $packageExec aio-commerce-lib-app hooks pre-app-build" },
|
|
240
|
+
operations: { workerProcess: actions.map((action) => ({
|
|
241
|
+
type: "action",
|
|
242
|
+
impl: `${PACKAGE_NAME}/${action.name}`
|
|
243
|
+
})) },
|
|
244
|
+
runtimeManifest: { packages: { [PACKAGE_NAME]: {
|
|
245
|
+
license: "Apache-2.0",
|
|
246
|
+
actions: Object.fromEntries(actions.map((action) => [action.name, createActionDefinition(action.name, action)]))
|
|
247
|
+
} } }
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Builds the ext.config.yaml configuration for the Admin UI SDK backend-ui extension.
|
|
252
|
+
*/
|
|
253
|
+
function buildAdminUiSdkExtConfig() {
|
|
254
|
+
return {
|
|
255
|
+
hooks: { "pre-app-build": "EXTENSION=backend-ui/1 $packageExec aio-commerce-lib-app hooks pre-app-build" },
|
|
256
|
+
operations: { view: [{
|
|
257
|
+
type: "web",
|
|
258
|
+
impl: "index.html"
|
|
259
|
+
}] },
|
|
260
|
+
web: "web-src",
|
|
261
|
+
runtimeManifest: { packages: { [ADMIN_UI_SDK_PACKAGE_NAME]: {
|
|
262
|
+
license: "Apache-2.0",
|
|
263
|
+
actions: { registration: {
|
|
264
|
+
function: `${ADMIN_UI_SDK_ACTIONS_PATH}/index.js`,
|
|
265
|
+
web: "yes",
|
|
266
|
+
runtime: "nodejs:22",
|
|
267
|
+
annotations: {
|
|
268
|
+
"require-adobe-auth": true,
|
|
269
|
+
final: true
|
|
270
|
+
}
|
|
271
|
+
} }
|
|
272
|
+
} } }
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
//#endregion
|
|
36
277
|
//#region ../../packages-private/scripting-utils/source/yaml/helpers.ts
|
|
37
278
|
/**
|
|
38
279
|
* Read a YAML file and return a {@link Document}
|
|
@@ -42,7 +283,7 @@ async function readYamlFile(path) {
|
|
|
42
283
|
let doc = new Document();
|
|
43
284
|
if (existsSync(path)) try {
|
|
44
285
|
doc = parseDocument(await readFile(path, "utf-8"), { keepSourceTokens: true });
|
|
45
|
-
} catch
|
|
286
|
+
} catch {
|
|
46
287
|
const file = basename(path);
|
|
47
288
|
throw new Error(`Failed to parse ${file}`);
|
|
48
289
|
}
|
|
@@ -107,16 +348,23 @@ function getOrCreateMap(doc, path, options) {
|
|
|
107
348
|
*/
|
|
108
349
|
async function createOrUpdateExtConfig(path, config, doc) {
|
|
109
350
|
const extConfigDoc = doc ?? new Document({});
|
|
351
|
+
if (config.web !== void 0) buildWeb(extConfigDoc, config.web);
|
|
110
352
|
config.hooks ??= {};
|
|
111
|
-
config.operations ??= { workerProcess: [] };
|
|
112
353
|
config.runtimeManifest ??= { packages: {} };
|
|
113
354
|
await buildHooks(extConfigDoc, config.hooks);
|
|
114
|
-
buildOperations(extConfigDoc, config.operations);
|
|
355
|
+
if (config.operations !== void 0) buildOperations(extConfigDoc, config.operations);
|
|
115
356
|
buildRuntimeManifest(extConfigDoc, config.runtimeManifest);
|
|
116
357
|
await writeExtConfig(path, extConfigDoc);
|
|
117
358
|
return extConfigDoc;
|
|
118
359
|
}
|
|
119
360
|
/**
|
|
361
|
+
* Set the top-level `web` scalar only if it's missing.
|
|
362
|
+
* Preserves any user-customized value already present.
|
|
363
|
+
*/
|
|
364
|
+
function buildWeb(extConfig, web) {
|
|
365
|
+
if (!extConfig.hasIn(["web"])) extConfig.add(extConfig.createPair("web", web));
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
120
368
|
* Build the definition for a runtime action
|
|
121
369
|
* @param name - The name of the action
|
|
122
370
|
* @param path - The path where the action is located
|
|
@@ -154,20 +402,36 @@ function buildActionDefinition(action) {
|
|
|
154
402
|
* @param operations - The operations to build
|
|
155
403
|
*/
|
|
156
404
|
function buildOperations(extConfig, operations) {
|
|
157
|
-
getOrCreateMap(extConfig, ["operations"], { onBeforeCreate: (pair) => {
|
|
158
|
-
pair.key.spaceBefore = true;
|
|
159
|
-
} });
|
|
160
|
-
const workerProcess = getOrCreateSeq(extConfig, ["operations", "workerProcess"], { onBeforeCreate: (pair) => {
|
|
161
|
-
pair.key.commentBefore = " These worker processes definitions are auto-generated. Do not remove or manually edit.";
|
|
162
|
-
} });
|
|
163
|
-
workerProcess.items = [];
|
|
164
405
|
const ourOps = operations.workerProcess ?? [];
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
406
|
+
if (ourOps.length > 0) {
|
|
407
|
+
getOrCreateMap(extConfig, ["operations"], { onBeforeCreate: (pair) => {
|
|
408
|
+
pair.key.spaceBefore = true;
|
|
409
|
+
} });
|
|
410
|
+
const workerProcess = getOrCreateSeq(extConfig, ["operations", "workerProcess"], { onBeforeCreate: (pair) => {
|
|
411
|
+
pair.key.commentBefore = " These worker processes definitions are auto-generated. Do not remove or manually edit.";
|
|
412
|
+
} });
|
|
413
|
+
workerProcess.items = [];
|
|
414
|
+
workerProcess.items.push(...ourOps.map((op) => {
|
|
415
|
+
const map = new YAMLMap();
|
|
416
|
+
map.set("type", op.type);
|
|
417
|
+
map.set("impl", op.impl);
|
|
418
|
+
return map;
|
|
419
|
+
}));
|
|
420
|
+
} else if (extConfig.hasIn(["operations", "workerProcess"])) extConfig.deleteIn(["operations", "workerProcess"]);
|
|
421
|
+
if (operations.view !== void 0) {
|
|
422
|
+
getOrCreateMap(extConfig, ["operations"], { onBeforeCreate: (pair) => {
|
|
423
|
+
pair.key.spaceBefore = true;
|
|
424
|
+
} });
|
|
425
|
+
const view = getOrCreateSeq(extConfig, ["operations", "view"]);
|
|
426
|
+
if (view.items.length === 0) view.items.push(...operations.view.map((v) => {
|
|
427
|
+
const map = new YAMLMap();
|
|
428
|
+
map.set("type", v.type);
|
|
429
|
+
map.set("impl", v.impl);
|
|
430
|
+
return map;
|
|
431
|
+
}));
|
|
432
|
+
}
|
|
433
|
+
const operationsMap = extConfig.getIn(["operations"]);
|
|
434
|
+
if (operationsMap instanceof YAMLMap && operationsMap.items.length === 0) extConfig.deleteIn(["operations"]);
|
|
171
435
|
}
|
|
172
436
|
/**
|
|
173
437
|
* Build the `runtimeManifest` section of the `ext.config.yaml` file
|
|
@@ -231,175 +495,35 @@ async function writeExtConfig(configPath, doc) {
|
|
|
231
495
|
}
|
|
232
496
|
|
|
233
497
|
//#endregion
|
|
234
|
-
//#region source/commands/
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const GENERATED_PATH = ".generated";
|
|
239
|
-
/** The folder name containing the runtime actions */
|
|
240
|
-
const ACTIONS_FOLDER = `actions/${PACKAGE_NAME}`;
|
|
241
|
-
/** The path to the directory containing the generated actions */
|
|
242
|
-
const GENERATED_ACTIONS_PATH = `${GENERATED_PATH}/${ACTIONS_FOLDER}`;
|
|
243
|
-
/** The name of the extension point for extensibility. */
|
|
244
|
-
const EXTENSIBILITY_EXTENSION_POINT_ID = "commerce/extensibility/1";
|
|
245
|
-
/** The name of the extension point for configuration. */
|
|
246
|
-
const CONFIGURATION_EXTENSION_POINT_ID = "commerce/configuration/1";
|
|
247
|
-
/** The name of the configuration schema file */
|
|
248
|
-
const APP_MANIFEST_FILE = "app.commerce.manifest.json";
|
|
249
|
-
/** The name of the commerce app configuration file */
|
|
250
|
-
const COMMERCE_APP_CONFIG_FILE = "app.commerce.config";
|
|
251
|
-
/** The name of the configuration schema file */
|
|
252
|
-
const CONFIG_SCHEMA_FILE_NAME = "configuration-schema.json";
|
|
253
|
-
/** The name of the project package file */
|
|
254
|
-
const PACKAGE_JSON_FILE = "package.json";
|
|
255
|
-
/** The name of the app configuration file */
|
|
256
|
-
const APP_CONFIG_FILE = "app.config.yaml";
|
|
257
|
-
/** The name of the install configuration file */
|
|
258
|
-
const INSTALL_YAML_FILE = "install.yaml";
|
|
259
|
-
/** Get the path to the extension point folder */
|
|
260
|
-
function getExtensionPointFolderPath(extensionPointId) {
|
|
261
|
-
return `src/${extensionPointId.replaceAll("/", "-")}`;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
//#endregion
|
|
265
|
-
//#region source/commands/utils.ts
|
|
266
|
-
/** Load the app commerce config */
|
|
267
|
-
async function loadAppManifest() {
|
|
268
|
-
const appConfig = await parseCommerceAppConfig();
|
|
269
|
-
consola.debug("Loaded app commerce config");
|
|
270
|
-
return appConfig;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
//#endregion
|
|
274
|
-
//#region source/commands/generate/actions/config.ts
|
|
275
|
-
/** The list of Commerce variables that are required for the runtime actions */
|
|
276
|
-
const COMMERCE_VARIABLES = [
|
|
277
|
-
"AIO_COMMERCE_AUTH_IMS_CLIENT_ID",
|
|
278
|
-
"AIO_COMMERCE_AUTH_IMS_CLIENT_SECRETS",
|
|
279
|
-
"AIO_COMMERCE_AUTH_IMS_TECHNICAL_ACCOUNT_ID",
|
|
280
|
-
"AIO_COMMERCE_AUTH_IMS_TECHNICAL_ACCOUNT_EMAIL",
|
|
281
|
-
"AIO_COMMERCE_AUTH_IMS_ORG_ID",
|
|
282
|
-
"AIO_COMMERCE_AUTH_IMS_SCOPES"
|
|
283
|
-
];
|
|
284
|
-
/** The inputs for the generated runtime actions */
|
|
285
|
-
const COMMERCE_ACTION_INPUTS = Object.fromEntries(COMMERCE_VARIABLES.map((variable) => [variable, `$${variable}`]));
|
|
286
|
-
const CUSTOM_IMPORTS_PLACEHOLDER = "// {{CUSTOM_SCRIPTS_IMPORTS}}";
|
|
287
|
-
const CUSTOM_SCRIPTS_MAP_PLACEHOLDER = "// {{CUSTOM_SCRIPTS_MAP}}";
|
|
288
|
-
const CUSTOM_SCRIPTS_LOADER_PLACEHOLDER = "// {{CUSTOM_SCRIPTS_LOADER}}";
|
|
289
|
-
/**
|
|
290
|
-
* Creates a runtime action configuration.
|
|
291
|
-
* @param actionName - The name of the action.
|
|
292
|
-
* @param options - Optional configuration options.
|
|
293
|
-
*/
|
|
294
|
-
function createActionDefinition(actionName, config = {}, options = {}) {
|
|
295
|
-
const def = {
|
|
296
|
-
...options,
|
|
297
|
-
function: `${GENERATED_ACTIONS_PATH}/${actionName}.js`,
|
|
298
|
-
web: options.web ?? "yes",
|
|
299
|
-
runtime: "nodejs:22",
|
|
300
|
-
annotations: {
|
|
301
|
-
"require-adobe-auth": true,
|
|
302
|
-
final: true
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
if (config.requiresEncryptionKey) def.inputs = {
|
|
306
|
-
...def.inputs,
|
|
307
|
-
AIO_COMMERCE_CONFIG_ENCRYPTION_KEY: "$AIO_COMMERCE_CONFIG_ENCRYPTION_KEY"
|
|
308
|
-
};
|
|
309
|
-
return def;
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Gets the runtime actions to be generated from the ext.config.yaml configuration.
|
|
313
|
-
* @param extConfig - The ext.config.yaml configuration.
|
|
314
|
-
*/
|
|
315
|
-
function getRuntimeActions(extConfig, dir) {
|
|
316
|
-
return Object.entries(extConfig.runtimeManifest?.packages?.["app-management"]?.actions ?? {}).map(([name, _]) => ({
|
|
317
|
-
name,
|
|
318
|
-
templateFile: join(dir, `${name}.js.template`)
|
|
319
|
-
}));
|
|
320
|
-
}
|
|
498
|
+
//#region source/commands/generate/actions/lib.ts
|
|
499
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
500
|
+
/** The path to the action templates directory, sibling to this file. */
|
|
501
|
+
const TEMPLATES_DIR = join(__dirname, "templates");
|
|
321
502
|
/**
|
|
322
|
-
*
|
|
323
|
-
* @param
|
|
503
|
+
* Read an extension point's ext.config.yaml file and return it as a JS object.
|
|
504
|
+
* @param extensionPointId - The extension point ID to read the config for.
|
|
324
505
|
*/
|
|
325
|
-
function
|
|
326
|
-
const
|
|
327
|
-
const hasPasswordFieldsInSchema = hasBusinessConfigSchema(appConfig) && appConfig.businessConfig.schema.some((field) => field.type === "password");
|
|
328
|
-
const extConfig = {
|
|
329
|
-
hooks: { "pre-app-build": "EXTENSION=extensibility/1 $packageExec aio-commerce-lib-app hooks pre-app-build" },
|
|
330
|
-
operations: { workerProcess: [{
|
|
331
|
-
type: "action",
|
|
332
|
-
impl: `${PACKAGE_NAME}/app-config`
|
|
333
|
-
}] },
|
|
334
|
-
runtimeManifest: { packages: { [PACKAGE_NAME]: {
|
|
335
|
-
license: "Apache-2.0",
|
|
336
|
-
actions: { "app-config": createActionDefinition("app-config") }
|
|
337
|
-
} } }
|
|
338
|
-
};
|
|
339
|
-
if ([
|
|
340
|
-
"installation.customInstallationSteps",
|
|
341
|
-
"eventing.commerce",
|
|
342
|
-
"eventing.external"
|
|
343
|
-
].some((feature) => features.has(feature))) {
|
|
344
|
-
extConfig.operations.workerProcess.push({
|
|
345
|
-
type: "action",
|
|
346
|
-
impl: `${PACKAGE_NAME}/installation`
|
|
347
|
-
});
|
|
348
|
-
extConfig.runtimeManifest.packages[PACKAGE_NAME].actions.installation = createActionDefinition("installation", { requiresEncryptionKey: hasPasswordFieldsInSchema }, {
|
|
349
|
-
inputs: {
|
|
350
|
-
...COMMERCE_ACTION_INPUTS,
|
|
351
|
-
LOG_LEVEL: "$LOG_LEVEL"
|
|
352
|
-
},
|
|
353
|
-
limits: { timeout: 6e5 }
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
return extConfig;
|
|
357
|
-
}
|
|
358
|
-
/** Builds the ext.config.yaml configuration for the business configuration extension. */
|
|
359
|
-
function buildBusinessConfigurationExtConfig() {
|
|
360
|
-
const actions = [{
|
|
361
|
-
name: "config",
|
|
362
|
-
templateFile: "config.js.template",
|
|
363
|
-
requiresEncryptionKey: true
|
|
364
|
-
}, {
|
|
365
|
-
name: "scope-tree",
|
|
366
|
-
templateFile: "scope-tree.js.template"
|
|
367
|
-
}];
|
|
368
|
-
return {
|
|
369
|
-
hooks: { "pre-app-build": "EXTENSION=configuration/1 $packageExec aio-commerce-lib-app hooks pre-app-build" },
|
|
370
|
-
operations: { workerProcess: actions.map((action) => ({
|
|
371
|
-
type: "action",
|
|
372
|
-
impl: `${PACKAGE_NAME}/${action.name}`
|
|
373
|
-
})) },
|
|
374
|
-
runtimeManifest: { packages: { [PACKAGE_NAME]: {
|
|
375
|
-
license: "Apache-2.0",
|
|
376
|
-
actions: Object.fromEntries(actions.map((action) => [action.name, createActionDefinition(action.name, action)]))
|
|
377
|
-
} } }
|
|
378
|
-
};
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
//#endregion
|
|
382
|
-
//#region source/commands/generate/actions/main.ts
|
|
383
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
384
|
-
async function run$4(appManifest) {
|
|
385
|
-
await generateActionFiles(appManifest, getRuntimeActions(await updateExtConfig(appManifest, EXTENSIBILITY_EXTENSION_POINT_ID), "app-management"), EXTENSIBILITY_EXTENSION_POINT_ID);
|
|
386
|
-
if (hasBusinessConfigSchema(appManifest)) await generateActionFiles(appManifest, getRuntimeActions(await updateExtConfig(appManifest, CONFIGURATION_EXTENSION_POINT_ID), "business-configuration"), CONFIGURATION_EXTENSION_POINT_ID);
|
|
387
|
-
}
|
|
388
|
-
/** Run the generate actions command */
|
|
389
|
-
async function exec$5() {
|
|
506
|
+
async function readExtConfig(extensionPointId) {
|
|
507
|
+
const extConfigPath = join(await getProjectRootDirectory(), getExtConfigPath(extensionPointId));
|
|
390
508
|
try {
|
|
391
|
-
|
|
509
|
+
return {
|
|
510
|
+
path: extConfigPath,
|
|
511
|
+
doc: await readYamlFile(extConfigPath)
|
|
512
|
+
};
|
|
392
513
|
} catch (error) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
514
|
+
const reason = error instanceof Error ? error.message : "Unexpected error while reading the file.";
|
|
515
|
+
throw new Error([
|
|
516
|
+
`Could not read ext.config.yaml for ${extensionPointId} at ${extConfigPath}.`,
|
|
517
|
+
`Make sure the file exists and is valid YAML. You can regenerate it with "aio-commerce-lib-app generate actions".`,
|
|
518
|
+
`Reason: ${reason}`
|
|
519
|
+
].join("\n"));
|
|
396
520
|
}
|
|
397
521
|
}
|
|
398
522
|
/** Update the ext.config.yaml file */
|
|
399
523
|
async function updateExtConfig(appConfig, extensionPointId) {
|
|
400
524
|
consola$1.info(`Updating ext.config.yaml for ${extensionPointId}...`);
|
|
401
|
-
|
|
402
|
-
const extConfigDoc = await
|
|
525
|
+
await makeOutputDirFor(getExtensionPointFolderPath(extensionPointId));
|
|
526
|
+
const { path: extConfigPath, doc: extConfigDoc } = await readExtConfig(extensionPointId);
|
|
403
527
|
let extConfig;
|
|
404
528
|
switch (extensionPointId) {
|
|
405
529
|
case EXTENSIBILITY_EXTENSION_POINT_ID:
|
|
@@ -408,24 +532,26 @@ async function updateExtConfig(appConfig, extensionPointId) {
|
|
|
408
532
|
case CONFIGURATION_EXTENSION_POINT_ID:
|
|
409
533
|
extConfig = buildBusinessConfigurationExtConfig();
|
|
410
534
|
break;
|
|
411
|
-
|
|
535
|
+
case BACKEND_UI_EXTENSION_POINT_ID:
|
|
536
|
+
extConfig = buildAdminUiSdkExtConfig();
|
|
537
|
+
break;
|
|
412
538
|
}
|
|
413
539
|
await createOrUpdateExtConfig(extConfigPath, extConfig, extConfigDoc);
|
|
414
540
|
return extConfig;
|
|
415
541
|
}
|
|
416
542
|
/** Generate the action files */
|
|
417
|
-
async function generateActionFiles(appManifest, actions, extensionPointId) {
|
|
543
|
+
async function generateActionFiles(appManifest, actions, extensionPointId, templatesDir) {
|
|
418
544
|
consola$1.start("Generating runtime actions...");
|
|
419
|
-
|
|
545
|
+
await makeOutputDirFor(getActionsDir(extensionPointId));
|
|
546
|
+
const projectRoot = await getProjectRootDirectory();
|
|
420
547
|
const outputFiles = [];
|
|
421
|
-
const templatesDir = join(__dirname, "generate/actions/templates");
|
|
422
548
|
for (const action of actions) {
|
|
423
549
|
let template = await readFile(join(templatesDir, action.templateFile), "utf-8");
|
|
424
550
|
if (action.name === "installation") {
|
|
425
551
|
const scriptsTemplate = await generateCustomScriptsTemplate(await readFile(join(templatesDir, "app-management", "custom-scripts.js.template"), "utf-8"), appManifest);
|
|
426
552
|
template = applyCustomScripts(template, scriptsTemplate);
|
|
427
553
|
}
|
|
428
|
-
const actionPath = join(
|
|
554
|
+
const actionPath = join(projectRoot, getActionPath(extensionPointId, action.name));
|
|
429
555
|
await writeFile(actionPath, template, "utf-8");
|
|
430
556
|
outputFiles.push(` ${relative(process.cwd(), actionPath)}`);
|
|
431
557
|
}
|
|
@@ -448,7 +574,7 @@ function applyCustomScripts(installationTemplate, customScriptsTemplate) {
|
|
|
448
574
|
async function generateCustomScriptsTemplate(template, appManifest) {
|
|
449
575
|
if (!hasCustomInstallationSteps(appManifest)) return null;
|
|
450
576
|
const projectRoot = await getProjectRootDirectory();
|
|
451
|
-
const installationActionDir = join(projectRoot,
|
|
577
|
+
const installationActionDir = join(projectRoot, getActionsDir(EXTENSIBILITY_EXTENSION_POINT_ID));
|
|
452
578
|
const customSteps = appManifest.installation.customInstallationSteps;
|
|
453
579
|
const importStatements = customSteps.map((step, index) => {
|
|
454
580
|
let relativeImportPath = relative(installationActionDir, join(projectRoot, step.script));
|
|
@@ -462,72 +588,128 @@ async function generateCustomScriptsTemplate(template, appManifest) {
|
|
|
462
588
|
}).join("\n");
|
|
463
589
|
return template.replace(CUSTOM_IMPORTS_PLACEHOLDER, importStatements).replace(CUSTOM_SCRIPTS_MAP_PLACEHOLDER, scriptMap);
|
|
464
590
|
}
|
|
591
|
+
/**
|
|
592
|
+
* Generates `registration/index.js` with the Admin UI SDK registration config
|
|
593
|
+
* inlined as a JS object literal.
|
|
594
|
+
* @param appManifest - The validated app config; must satisfy `hasAdminUiSdk`.
|
|
595
|
+
* @param extensionPointId - The extension point ID that owns the registration action.
|
|
596
|
+
* @param templatesDir - The root directory containing the action templates.
|
|
597
|
+
*/
|
|
598
|
+
async function generateRegistrationActionFile(appManifest, extensionPointId, templatesDir = TEMPLATES_DIR) {
|
|
599
|
+
consola$1.start("Generating Admin UI SDK registration action...");
|
|
600
|
+
await makeOutputDirFor(getAdminUiSdkActionsDir(extensionPointId));
|
|
601
|
+
const projectRoot = await getProjectRootDirectory();
|
|
602
|
+
const template = await readFile(join(templatesDir, "admin-ui-sdk", "registration.js.template"), "utf-8");
|
|
603
|
+
const { registration } = appManifest.adminUiSdk;
|
|
604
|
+
const actionPath = join(projectRoot, getAdminUiSdkRegistrationActionPath(extensionPointId));
|
|
605
|
+
await writeFile(actionPath, await prettierFormat(template.replace(REGISTRATION_JSON_PLACEHOLDER, `const registration = ${stringify(registration)};`), actionPath), "utf-8");
|
|
606
|
+
consola$1.success(`Generated registration action at ${relative(process.cwd(), actionPath)}`);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
//#endregion
|
|
610
|
+
//#region source/commands/generate/actions/main.ts
|
|
611
|
+
/**
|
|
612
|
+
* Runs the generate actions command for the given extension point.
|
|
613
|
+
* @param appManifest - The app manifest, used to determine which actions to generate and their content.
|
|
614
|
+
* @param templatesDir - The directory to load templates from, for testing purposes. Defaults to the generated actions template root.
|
|
615
|
+
*/
|
|
616
|
+
async function run$5(appManifest, templatesDir = TEMPLATES_DIR) {
|
|
617
|
+
await generateActionFiles(appManifest, getRuntimeActions(await updateExtConfig(appManifest, EXTENSIBILITY_EXTENSION_POINT_ID), "app-management"), EXTENSIBILITY_EXTENSION_POINT_ID, templatesDir);
|
|
618
|
+
if (hasBusinessConfigSchema(appManifest)) await generateActionFiles(appManifest, getRuntimeActions(await updateExtConfig(appManifest, CONFIGURATION_EXTENSION_POINT_ID), "business-configuration"), CONFIGURATION_EXTENSION_POINT_ID, templatesDir);
|
|
619
|
+
if (hasAdminUiSdk(appManifest)) {
|
|
620
|
+
await updateExtConfig(appManifest, BACKEND_UI_EXTENSION_POINT_ID);
|
|
621
|
+
await generateRegistrationActionFile(appManifest, BACKEND_UI_EXTENSION_POINT_ID, templatesDir);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
/** Run the generate actions command */
|
|
625
|
+
async function exec$5() {
|
|
626
|
+
try {
|
|
627
|
+
await run$5(await loadAppManifest());
|
|
628
|
+
} catch (error) {
|
|
629
|
+
if (error instanceof CommerceSdkValidationError) consola$1.error(error.display());
|
|
630
|
+
else consola$1.error(error);
|
|
631
|
+
process.exit(1);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
465
634
|
|
|
466
635
|
//#endregion
|
|
467
636
|
//#region source/commands/generate/manifest/main.ts
|
|
468
|
-
async function run$
|
|
637
|
+
async function run$4(appConfig) {
|
|
469
638
|
consola$1.info("Generating app manifest...");
|
|
470
|
-
const contents = stringify(appConfig, null, 2);
|
|
471
|
-
await writeFile(join(await makeOutputDirFor(
|
|
639
|
+
const contents = stringify$1(appConfig, null, 2);
|
|
640
|
+
await writeFile(join(await makeOutputDirFor(getGeneratedDir(EXTENSIBILITY_EXTENSION_POINT_ID)), APP_MANIFEST_FILE), contents, "utf-8");
|
|
472
641
|
consola$1.success(`Generated ${APP_MANIFEST_FILE}`);
|
|
473
642
|
}
|
|
474
643
|
/** Run the generate manifest command */
|
|
475
644
|
async function exec$4() {
|
|
476
645
|
try {
|
|
477
|
-
await run$
|
|
646
|
+
await run$4(await loadAppManifest());
|
|
478
647
|
} catch (error) {
|
|
479
648
|
if (error instanceof CommerceSdkValidationError) consola$1.error(error.display());
|
|
480
|
-
consola$1.error(error);
|
|
649
|
+
else consola$1.error(error);
|
|
481
650
|
process.exit(1);
|
|
482
651
|
}
|
|
483
652
|
}
|
|
484
653
|
|
|
654
|
+
//#endregion
|
|
655
|
+
//#region ../../packages-private/scripting-utils/source/filesystem/helpers.ts
|
|
656
|
+
/**
|
|
657
|
+
* Touch a file, creating it if it doesn't exist.
|
|
658
|
+
* @param filePath The path of the file to touch
|
|
659
|
+
*/
|
|
660
|
+
async function touch(filePath) {
|
|
661
|
+
await writeFile(filePath, "", { flag: "wx" }).catch((e) => {
|
|
662
|
+
if (e.code !== "EEXIST") throw e;
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
|
|
485
666
|
//#endregion
|
|
486
667
|
//#region source/commands/generate/schema/main.ts
|
|
487
|
-
async function run$
|
|
488
|
-
consola$1.info("Generating configuration schema...");
|
|
668
|
+
async function run$3(appConfig) {
|
|
489
669
|
if (!hasBusinessConfigSchema(appConfig)) {
|
|
490
|
-
consola$1.
|
|
670
|
+
consola$1.debug("Business configuration schema not found in application configuration. Nothing to do.");
|
|
491
671
|
return;
|
|
492
672
|
}
|
|
493
|
-
|
|
673
|
+
consola$1.info("Generating configuration schema...");
|
|
674
|
+
const projectDir = await getProjectRootDirectory();
|
|
494
675
|
const envPath = join(projectDir, ".env");
|
|
676
|
+
await touch(envPath);
|
|
495
677
|
process.loadEnvFile(envPath);
|
|
496
678
|
if (appConfig.businessConfig.schema.some((field) => field.type === "password")) {
|
|
497
679
|
const packageExec = getExecCommand(await detectPackageManager(projectDir));
|
|
498
680
|
if ("AIO_COMMERCE_CONFIG_ENCRYPTION_KEY" in process.env && String(process.env.AIO_COMMERCE_CONFIG_ENCRYPTION_KEY).trim().length > 0) execSync(`${packageExec} aio-commerce-lib-config encryption validate`);
|
|
499
681
|
else execSync(`${packageExec} aio-commerce-lib-config encryption setup`);
|
|
500
682
|
}
|
|
501
|
-
const contents = stringify(appConfig.businessConfig.schema, null, 2);
|
|
502
|
-
await writeFile(join(await makeOutputDirFor(
|
|
683
|
+
const contents = stringify$1(appConfig.businessConfig.schema, null, 2);
|
|
684
|
+
await writeFile(join(await makeOutputDirFor(getGeneratedDir(CONFIGURATION_EXTENSION_POINT_ID)), CONFIG_SCHEMA_FILE_NAME), contents, "utf-8");
|
|
503
685
|
consola$1.success(`Generated ${CONFIG_SCHEMA_FILE_NAME}`);
|
|
504
686
|
}
|
|
505
|
-
/** Run the generate
|
|
687
|
+
/** Run the generate schema command */
|
|
506
688
|
async function exec$3() {
|
|
507
689
|
try {
|
|
508
|
-
await run$
|
|
690
|
+
await run$3(await loadAppManifest());
|
|
509
691
|
} catch (error) {
|
|
510
692
|
if (error instanceof CommerceSdkValidationError) consola$1.error(error.display());
|
|
511
|
-
consola$1.error(error);
|
|
693
|
+
else consola$1.error(error);
|
|
512
694
|
process.exit(1);
|
|
513
695
|
}
|
|
514
696
|
}
|
|
515
697
|
|
|
516
698
|
//#endregion
|
|
517
699
|
//#region source/commands/hooks/postinstall.ts
|
|
518
|
-
async function run$
|
|
700
|
+
async function run$2(appManifest, templatesDir) {
|
|
701
|
+
await run$5(appManifest, templatesDir);
|
|
519
702
|
await run$4(appManifest);
|
|
520
703
|
await run$3(appManifest);
|
|
521
|
-
await run$2(appManifest);
|
|
522
704
|
}
|
|
523
705
|
/** Runs the postinstall hook */
|
|
524
706
|
async function exec$2() {
|
|
525
707
|
consola.debug("Running lib-app postinstall hook");
|
|
526
708
|
try {
|
|
527
|
-
await run$
|
|
709
|
+
await run$2(await loadAppManifest());
|
|
528
710
|
} catch (error) {
|
|
529
711
|
if (error instanceof CommerceSdkValidationError) consola.error(error.display());
|
|
530
|
-
consola.error(error);
|
|
712
|
+
else consola.error(error);
|
|
531
713
|
process.exit(1);
|
|
532
714
|
}
|
|
533
715
|
}
|
|
@@ -583,19 +765,27 @@ function resolveImsS2SContext() {
|
|
|
583
765
|
}
|
|
584
766
|
/**
|
|
585
767
|
* Syncs the IMS credentials environment variables from the configured IMS context in
|
|
586
|
-
* the .env file, in a way that is compatible with `@adobe/aio-commerce-lib-auth
|
|
768
|
+
* the .env file, in a way that is compatible with `@adobe/aio-commerce-lib-auth`.
|
|
587
769
|
*/
|
|
588
770
|
async function syncImsCredentials() {
|
|
589
771
|
const envPath = resolveEnvPath();
|
|
772
|
+
if (!existsSync(envPath)) return {
|
|
773
|
+
ok: false,
|
|
774
|
+
reason: "missing-env"
|
|
775
|
+
};
|
|
590
776
|
const envVars = dotenv.parse(readFileSync(envPath, "utf8"));
|
|
591
777
|
const imsContext = await resolveImsS2SContext();
|
|
592
|
-
if (!imsContext) return
|
|
778
|
+
if (!imsContext) return {
|
|
779
|
+
ok: false,
|
|
780
|
+
reason: "no-ims-context"
|
|
781
|
+
};
|
|
593
782
|
const { data } = imsContext;
|
|
594
783
|
for (const [key, value] of Object.entries(data)) {
|
|
595
784
|
const oauthKey = IMS_KEYS[key];
|
|
596
785
|
if (!oauthKey) continue;
|
|
597
786
|
if (!envVars[oauthKey] || envVars[oauthKey] !== value) replaceEnvVar(envPath, oauthKey, value);
|
|
598
787
|
}
|
|
788
|
+
return { ok: true };
|
|
599
789
|
}
|
|
600
790
|
|
|
601
791
|
//#endregion
|
|
@@ -603,17 +793,26 @@ async function syncImsCredentials() {
|
|
|
603
793
|
/**
|
|
604
794
|
* Runs the pre-app-build hook for the given extension.
|
|
605
795
|
* @param extension - The extension to run the hook for.
|
|
796
|
+
* @param templatesDir - The directory to load templates from, for testing purposes. Defaults to the generated actions template root.
|
|
606
797
|
*/
|
|
607
|
-
async function run(extension) {
|
|
798
|
+
async function run$1(extension, templatesDir = TEMPLATES_DIR) {
|
|
608
799
|
const appManifest = await loadAppManifest();
|
|
609
800
|
if (extension === "extensibility/1") {
|
|
610
|
-
await
|
|
801
|
+
const { doc: extensibilityExtConfig } = await readExtConfig(EXTENSIBILITY_EXTENSION_POINT_ID);
|
|
802
|
+
await run$4(appManifest);
|
|
803
|
+
await generateActionFiles(appManifest, getRuntimeActions(extensibilityExtConfig.toJS(), "app-management"), EXTENSIBILITY_EXTENSION_POINT_ID, templatesDir);
|
|
611
804
|
consola.info("Syncing IMS credentials...");
|
|
612
805
|
await syncImsCredentials();
|
|
613
806
|
return;
|
|
614
807
|
}
|
|
615
808
|
if (extension === "configuration/1") {
|
|
616
|
-
await
|
|
809
|
+
const { doc: businessConfigExtConfig } = await readExtConfig(CONFIGURATION_EXTENSION_POINT_ID);
|
|
810
|
+
await run$3(appManifest);
|
|
811
|
+
await generateActionFiles(appManifest, getRuntimeActions(businessConfigExtConfig.toJS(), "business-configuration"), CONFIGURATION_EXTENSION_POINT_ID, templatesDir);
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
if (extension === "backend-ui/1") {
|
|
815
|
+
if (hasAdminUiSdk(appManifest)) await generateRegistrationActionFile(appManifest, BACKEND_UI_EXTENSION_POINT_ID);
|
|
617
816
|
return;
|
|
618
817
|
}
|
|
619
818
|
throw new Error(`Unsupported extension: ${extension}`);
|
|
@@ -624,10 +823,10 @@ async function exec$1() {
|
|
|
624
823
|
const extension = process.env.EXTENSION;
|
|
625
824
|
try {
|
|
626
825
|
if (!extension) throw new Error("EXTENSION environment variable is not set");
|
|
627
|
-
await run(extension);
|
|
826
|
+
await run$1(extension);
|
|
628
827
|
} catch (error) {
|
|
629
828
|
if (error instanceof CommerceSdkValidationError) consola.error(error.display());
|
|
630
|
-
consola.error(error);
|
|
829
|
+
else consola.error(error);
|
|
631
830
|
process.exit(1);
|
|
632
831
|
}
|
|
633
832
|
}
|
|
@@ -662,7 +861,7 @@ const DOMAIN_DEFAULTS = {
|
|
|
662
861
|
},
|
|
663
862
|
events: [{
|
|
664
863
|
name: "plugin.sample_event",
|
|
665
|
-
fields: [],
|
|
864
|
+
fields: [{ name: "*" }],
|
|
666
865
|
label: "Sample Event",
|
|
667
866
|
description: "Use case description for the event.",
|
|
668
867
|
runtimeActions: ["my-package/handle-sample-event"]
|
|
@@ -684,12 +883,50 @@ const DOMAIN_DEFAULTS = {
|
|
|
684
883
|
name: "sample-step",
|
|
685
884
|
description: "Use case description for the step.",
|
|
686
885
|
script: "./path/to/script.js"
|
|
886
|
+
}],
|
|
887
|
+
webhooks: [{
|
|
888
|
+
label: "Sample Webhook",
|
|
889
|
+
description: "A sample Commerce Webhook handler.",
|
|
890
|
+
runtimeAction: "my-package/handle-webhook",
|
|
891
|
+
category: "modification",
|
|
892
|
+
webhook: {
|
|
893
|
+
webhook_method: "plugin.sample.event",
|
|
894
|
+
webhook_type: "after",
|
|
895
|
+
batch_name: "my_app",
|
|
896
|
+
hook_name: "sample_hook",
|
|
897
|
+
method: "POST"
|
|
898
|
+
}
|
|
899
|
+
}, {
|
|
900
|
+
label: "Sample Webhook with URL",
|
|
901
|
+
description: "A sample Commerce Webhook handler using an explicit URL.",
|
|
902
|
+
category: "modification",
|
|
903
|
+
webhook: {
|
|
904
|
+
webhook_method: "plugin.sample.event",
|
|
905
|
+
webhook_type: "after",
|
|
906
|
+
batch_name: "my_app",
|
|
907
|
+
hook_name: "sample_hook_url",
|
|
908
|
+
method: "POST",
|
|
909
|
+
url: "https://example.com/webhook"
|
|
910
|
+
}
|
|
687
911
|
}]
|
|
688
912
|
};
|
|
689
913
|
|
|
690
914
|
//#endregion
|
|
691
915
|
//#region source/commands/init/utils.ts
|
|
692
|
-
/**
|
|
916
|
+
/**
|
|
917
|
+
* Convert the given init options to answers for scaffolding the app config. This is useful for non-interactive use cases, such as running the command with a config file or from another script.
|
|
918
|
+
* @param flags - The initialization options
|
|
919
|
+
*/
|
|
920
|
+
function initFlagsToScaffoldAppAnswers(flags) {
|
|
921
|
+
const configFile = `${COMMERCE_APP_CONFIG_FILE}.${flags.configFormat}`;
|
|
922
|
+
return {
|
|
923
|
+
appName: flags.appName,
|
|
924
|
+
configFile,
|
|
925
|
+
configFormat: flags.configFormat,
|
|
926
|
+
domains: new Set(flags.domains)
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
/** Prompt the user to scaffold a new Commerce App configuration. When options are provided, prompts are skipped. */
|
|
693
930
|
async function promptForCommerceAppConfig() {
|
|
694
931
|
const configFormat = await consola.prompt("What format do you want to use for the config file?", {
|
|
695
932
|
type: "select",
|
|
@@ -725,6 +962,10 @@ async function promptForCommerceAppConfig() {
|
|
|
725
962
|
label: "Commerce Events",
|
|
726
963
|
value: "eventing.commerce"
|
|
727
964
|
},
|
|
965
|
+
{
|
|
966
|
+
label: "Commerce Webhooks",
|
|
967
|
+
value: "webhooks"
|
|
968
|
+
},
|
|
728
969
|
{
|
|
729
970
|
label: "External Events",
|
|
730
971
|
value: "eventing.external"
|
|
@@ -735,10 +976,13 @@ async function promptForCommerceAppConfig() {
|
|
|
735
976
|
}
|
|
736
977
|
]
|
|
737
978
|
});
|
|
979
|
+
const configFile = `${COMMERCE_APP_CONFIG_FILE}.${configFormat}`;
|
|
980
|
+
const domains = new Set(featuresToAdd);
|
|
981
|
+
consola.log("");
|
|
738
982
|
return {
|
|
739
983
|
appName,
|
|
740
|
-
configFile
|
|
741
|
-
domains
|
|
984
|
+
configFile,
|
|
985
|
+
domains,
|
|
742
986
|
configFormat
|
|
743
987
|
};
|
|
744
988
|
}
|
|
@@ -763,6 +1007,7 @@ async function getDefaultCommerceAppConfig(cwd, { appName, configFormat, domains
|
|
|
763
1007
|
external: DOMAIN_DEFAULTS["eventing.external"]
|
|
764
1008
|
};
|
|
765
1009
|
if (domains.has("installation.customInstallationSteps")) defaultConfig.installation = { customInstallationSteps: DOMAIN_DEFAULTS["installation.customInstallationSteps"] };
|
|
1010
|
+
if (domains.has("webhooks")) defaultConfig.webhooks = DOMAIN_DEFAULTS.webhooks;
|
|
766
1011
|
return [
|
|
767
1012
|
importStatement,
|
|
768
1013
|
"",
|
|
@@ -777,9 +1022,8 @@ async function getDefaultCommerceAppConfig(cwd, { appName, configFormat, domains
|
|
|
777
1022
|
*/
|
|
778
1023
|
async function addExtensionPointToAppConfig(extensionPointId, rootDirectory, commentBefore) {
|
|
779
1024
|
const appConfigPath = join(rootDirectory, APP_CONFIG_FILE);
|
|
780
|
-
const extensionPointFolderPath = join(rootDirectory, getExtensionPointFolderPath(extensionPointId));
|
|
781
1025
|
let doc;
|
|
782
|
-
const includePath = relative(rootDirectory, join(
|
|
1026
|
+
const includePath = relative(rootDirectory, join(rootDirectory, getExtConfigPath(extensionPointId)));
|
|
783
1027
|
try {
|
|
784
1028
|
doc = await readYamlFile(appConfigPath);
|
|
785
1029
|
} catch (error) {
|
|
@@ -837,12 +1081,12 @@ async function addExtensionPointToInstallYaml(extensionPointId, rootDirectory, c
|
|
|
837
1081
|
|
|
838
1082
|
//#endregion
|
|
839
1083
|
//#region source/commands/init/lib.ts
|
|
840
|
-
/** Ensure app.commerce.config file exists, allow creating if it doesn't */
|
|
841
|
-
async function ensureCommerceAppConfig(cwd = process.cwd()) {
|
|
1084
|
+
/** Ensure app.commerce.config file exists, allow creating if it doesn't. When options are provided, prompts are skipped. */
|
|
1085
|
+
async function ensureCommerceAppConfig(cwd = process.cwd(), formatConfig = true, flags) {
|
|
842
1086
|
let config = null;
|
|
843
1087
|
try {
|
|
844
1088
|
config = await readCommerceAppConfig(cwd);
|
|
845
|
-
} catch
|
|
1089
|
+
} catch {}
|
|
846
1090
|
if (config) try {
|
|
847
1091
|
const validatedConfig = validateCommerceAppConfig(config);
|
|
848
1092
|
consola$1.success(`${COMMERCE_APP_CONFIG_FILE} found and is valid. Continuing...`);
|
|
@@ -853,119 +1097,126 @@ async function ensureCommerceAppConfig(cwd = process.cwd()) {
|
|
|
853
1097
|
} catch (error) {
|
|
854
1098
|
throw new Error(`${COMMERCE_APP_CONFIG_FILE} is invalid`, { cause: error });
|
|
855
1099
|
}
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
1100
|
+
if (!flags) {
|
|
1101
|
+
consola$1.warn(`${COMMERCE_APP_CONFIG_FILE} not found.`);
|
|
1102
|
+
if (!await consola$1.prompt(`Do you want to create a ${"app.commerce.config"} file? (y/n)`, {
|
|
1103
|
+
type: "confirm",
|
|
1104
|
+
initial: true,
|
|
1105
|
+
default: false
|
|
1106
|
+
})) throw new Error("Initialization cancelled.");
|
|
1107
|
+
}
|
|
1108
|
+
const answers = flags ? initFlagsToScaffoldAppAnswers(flags) : await promptForCommerceAppConfig();
|
|
863
1109
|
try {
|
|
864
1110
|
const configContent = await getDefaultCommerceAppConfig(cwd, answers);
|
|
865
|
-
consola$1.info(`Creating ${answers.configFile}...`);
|
|
866
1111
|
const path = join(await getProjectRootDirectory(cwd), answers.configFile);
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
bracketSameLine: true,
|
|
872
|
-
bracketSpacing: true,
|
|
873
|
-
trailingComma: "all",
|
|
874
|
-
tabWidth: 2,
|
|
875
|
-
useTabs: false,
|
|
876
|
-
printWidth: 80,
|
|
877
|
-
filepath: path
|
|
878
|
-
}), "utf-8");
|
|
1112
|
+
consola$1.info(`Creating ${answers.configFile}...`);
|
|
1113
|
+
if (formatConfig) await writeFile(path, await prettierFormat(configContent, path), "utf-8");
|
|
1114
|
+
else await writeFile(path, configContent, "utf-8");
|
|
1115
|
+
const config = await parseCommerceAppConfig(cwd);
|
|
879
1116
|
consola$1.success(`Created ${answers.configFile}`);
|
|
880
1117
|
return {
|
|
881
|
-
config
|
|
1118
|
+
config,
|
|
882
1119
|
domains: answers.domains
|
|
883
1120
|
};
|
|
884
1121
|
} catch (error) {
|
|
885
1122
|
throw new Error(`Failed to create ${answers.configFile}`, { cause: error });
|
|
886
1123
|
}
|
|
887
1124
|
}
|
|
888
|
-
/**
|
|
1125
|
+
/**
|
|
1126
|
+
* Ensure a package.json exists and detect the package manager.
|
|
1127
|
+
* @param cwd - Directory to check; defaults to `process.cwd()`
|
|
1128
|
+
*/
|
|
889
1129
|
async function ensurePackageJson(cwd = process.cwd()) {
|
|
890
|
-
const
|
|
891
|
-
|
|
1130
|
+
const existing = await readPackageJson(cwd);
|
|
1131
|
+
let packageJson;
|
|
1132
|
+
if (existing) packageJson = existing;
|
|
1133
|
+
else {
|
|
892
1134
|
consola$1.warn("package.json not found. Creating one...");
|
|
893
|
-
|
|
1135
|
+
packageJson = {
|
|
894
1136
|
name: "my-commerce-app",
|
|
895
1137
|
version: "1.0.0",
|
|
896
|
-
private: true
|
|
897
|
-
scripts: { postinstall: "npx aio-commerce-lib-app hooks postinstall" }
|
|
1138
|
+
private: true
|
|
898
1139
|
};
|
|
899
|
-
await writeFile(join(resolve(cwd), PACKAGE_JSON_FILE), JSON.stringify(
|
|
1140
|
+
await writeFile(join(resolve(cwd), PACKAGE_JSON_FILE), JSON.stringify(packageJson, null, 2), "utf-8");
|
|
900
1141
|
consola$1.success("Wrote package.json");
|
|
901
|
-
return {
|
|
902
|
-
packageJson: packageJsonContent,
|
|
903
|
-
packageManager: "npm",
|
|
904
|
-
execCommand: "npx"
|
|
905
|
-
};
|
|
906
1142
|
}
|
|
907
|
-
const packageManager = await detectPackageManager();
|
|
1143
|
+
const packageManager = await detectPackageManager(cwd);
|
|
908
1144
|
const execCommand = getExecCommand(packageManager);
|
|
909
|
-
const postinstallScript = `${execCommand} aio-commerce-lib-app hooks postinstall`;
|
|
910
|
-
packageJson.scripts ??= {};
|
|
911
|
-
if (packageJson.scripts.postinstall === postinstallScript || packageJson.scripts.postinstall?.includes(postinstallScript)) {
|
|
912
|
-
consola$1.success(`postinstall script already configured in ${PACKAGE_JSON_FILE}`);
|
|
913
|
-
return {
|
|
914
|
-
packageJson,
|
|
915
|
-
packageManager,
|
|
916
|
-
execCommand
|
|
917
|
-
};
|
|
918
|
-
}
|
|
919
|
-
if (packageJson.scripts.postinstall) {
|
|
920
|
-
consola$1.warn(`${PACKAGE_JSON_FILE} already has a postinstall script. Adding a new one...`);
|
|
921
|
-
execSync(`npm pkg set scripts.postinstall="${`${packageJson.scripts.postinstall} && ${postinstallScript}`}"`);
|
|
922
|
-
} else {
|
|
923
|
-
consola$1.info(`Adding postinstall script to ${PACKAGE_JSON_FILE}...`);
|
|
924
|
-
execSync(`npm pkg set scripts.postinstall="${postinstallScript}"`);
|
|
925
|
-
}
|
|
926
|
-
consola$1.success(`Added postinstall script to ${PACKAGE_JSON_FILE}`);
|
|
927
1145
|
return {
|
|
928
1146
|
packageJson,
|
|
929
1147
|
packageManager,
|
|
930
1148
|
execCommand
|
|
931
1149
|
};
|
|
932
1150
|
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Register the `hooks postinstall` script in package.json.
|
|
1153
|
+
* @param execCommand - Prefix for running local binaries (e.g. `pnpm exec`, `npx`)
|
|
1154
|
+
* @param cwd - Directory containing the package.json to update
|
|
1155
|
+
*/
|
|
1156
|
+
async function writePostinstallHook(execCommand, cwd = process.cwd()) {
|
|
1157
|
+
const postinstallScript = `${execCommand} aio-commerce-lib-app hooks postinstall`;
|
|
1158
|
+
const pkg = await NpmPackageJson.load(cwd);
|
|
1159
|
+
const existing = pkg.content.scripts?.postinstall;
|
|
1160
|
+
if (existing === postinstallScript || existing?.includes(postinstallScript)) {
|
|
1161
|
+
consola$1.success(`postinstall script already configured in ${PACKAGE_JSON_FILE}`);
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
const nextPostinstall = existing ? `${existing} && ${postinstallScript}` : postinstallScript;
|
|
1165
|
+
if (existing) consola$1.warn(`${PACKAGE_JSON_FILE} already has a postinstall script. Adding a new one...`);
|
|
1166
|
+
else consola$1.info(`Adding postinstall script to ${PACKAGE_JSON_FILE}...`);
|
|
1167
|
+
pkg.update({ scripts: {
|
|
1168
|
+
...pkg.content.scripts,
|
|
1169
|
+
postinstall: nextPostinstall
|
|
1170
|
+
} });
|
|
1171
|
+
await pkg.save();
|
|
1172
|
+
consola$1.success(`Added postinstall script to ${PACKAGE_JSON_FILE}`);
|
|
1173
|
+
}
|
|
933
1174
|
/** Ensure app.config.yaml has the extension reference */
|
|
934
1175
|
async function ensureAppConfig(domains, cwd = process.cwd()) {
|
|
935
1176
|
const rootDirectory = await getProjectRootDirectory(cwd);
|
|
936
1177
|
if (domains.has("businessConfig.schema")) await addExtensionPointToAppConfig(CONFIGURATION_EXTENSION_POINT_ID, rootDirectory, " This extension is required for business configuration. Do not remove.");
|
|
1178
|
+
if (domains.has("adminUiSdk")) await addExtensionPointToAppConfig(BACKEND_UI_EXTENSION_POINT_ID, rootDirectory, " This extension is required for Admin UI SDK. Do not remove.");
|
|
937
1179
|
await addExtensionPointToAppConfig(EXTENSIBILITY_EXTENSION_POINT_ID, rootDirectory, " This extension is required for app management. Do not remove.");
|
|
938
1180
|
}
|
|
939
|
-
/**
|
|
1181
|
+
/**
|
|
1182
|
+
* Install the given dependencies.
|
|
1183
|
+
* @param packageManager - The detected package manager
|
|
1184
|
+
* @param dependencies - Package specifiers to install; no-op when empty
|
|
1185
|
+
* @param cwd - Working directory for the install command
|
|
1186
|
+
*/
|
|
940
1187
|
function runInstall(packageManager, dependencies, cwd = process.cwd()) {
|
|
1188
|
+
if (dependencies.length === 0) return;
|
|
941
1189
|
const dependencyListString = dependencies.map((dependency) => ` - ${dependency}`).join("\n");
|
|
942
|
-
consola$1.
|
|
943
|
-
const
|
|
944
|
-
const
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
cwd,
|
|
953
|
-
stdio: "inherit"
|
|
954
|
-
});
|
|
955
|
-
consola$1.success("Dependencies installed successfully");
|
|
956
|
-
} catch (error) {
|
|
957
|
-
throw new Error(`Failed to install dependencies automatically. Please install manually: ${installCommand}`, { cause: error });
|
|
958
|
-
}
|
|
1190
|
+
consola$1.start([`Installing the following dependencies with ${packageManager}:\n${dependencyListString}\n`, "This may take a few seconds...\n"].join("\n"));
|
|
1191
|
+
const { command, args } = getInstallCommand(packageManager, dependencies);
|
|
1192
|
+
const displayCommand = [command, ...args].join(" ");
|
|
1193
|
+
const result = spawnSync(command, args, {
|
|
1194
|
+
cwd,
|
|
1195
|
+
stdio: "inherit"
|
|
1196
|
+
});
|
|
1197
|
+
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}`) });
|
|
1198
|
+
consola$1.log("");
|
|
1199
|
+
consola$1.success("Dependencies installed successfully");
|
|
959
1200
|
}
|
|
960
|
-
/**
|
|
1201
|
+
/**
|
|
1202
|
+
* Install the domain-specific dependencies derived from the selected domains.
|
|
1203
|
+
* @param packageManager - The detected package manager
|
|
1204
|
+
* @param domains - Domains enabled in the commerce app config
|
|
1205
|
+
* @param cwd - Working directory for the install command
|
|
1206
|
+
*/
|
|
961
1207
|
function installDependencies(packageManager, domains, cwd = process.cwd()) {
|
|
962
1208
|
const packages = [];
|
|
963
|
-
if (domains.has("businessConfig.schema")) packages.push(
|
|
1209
|
+
if (domains.has("businessConfig.schema")) packages.push(`@adobe/aio-commerce-lib-config@^1.3.0`);
|
|
1210
|
+
if (packages.length === 0) {
|
|
1211
|
+
consola$1.info("No additional domain dependencies to install.");
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
964
1214
|
runInstall(packageManager, packages, cwd);
|
|
965
1215
|
}
|
|
966
1216
|
/** Run the generation command */
|
|
967
1217
|
async function runGeneration(appConfig, execCommand) {
|
|
968
1218
|
try {
|
|
1219
|
+
await run$5(appConfig);
|
|
969
1220
|
await run$4(appConfig);
|
|
970
1221
|
await run$3(appConfig);
|
|
971
1222
|
} catch (error) {
|
|
@@ -976,35 +1227,45 @@ async function runGeneration(appConfig, execCommand) {
|
|
|
976
1227
|
async function ensureInstallYaml(domains, cwd = process.cwd()) {
|
|
977
1228
|
const rootDirectory = await getProjectRootDirectory(cwd);
|
|
978
1229
|
if (domains.has("businessConfig.schema")) await addExtensionPointToInstallYaml(CONFIGURATION_EXTENSION_POINT_ID, rootDirectory, " This extension is required for business configuration. Do not remove.");
|
|
1230
|
+
if (domains.has("adminUiSdk")) await addExtensionPointToInstallYaml(BACKEND_UI_EXTENSION_POINT_ID, rootDirectory, " This extension is required for Admin UI SDK. Do not remove.");
|
|
979
1231
|
await addExtensionPointToInstallYaml(EXTENSIBILITY_EXTENSION_POINT_ID, rootDirectory, " This extension is required for app management. Do not remove.");
|
|
980
1232
|
}
|
|
981
1233
|
|
|
982
1234
|
//#endregion
|
|
983
1235
|
//#region source/commands/init/main.ts
|
|
984
|
-
const REQUIRED_DEPENDENCIES = ["@adobe/aio-commerce-
|
|
985
|
-
/** Initialize the project
|
|
1236
|
+
const REQUIRED_DEPENDENCIES = ["@adobe/aio-commerce-sdk", `@adobe/aio-commerce-lib-app@1.4.0`];
|
|
1237
|
+
/** Initialize the project */
|
|
1238
|
+
async function run(flags, extraOptions) {
|
|
1239
|
+
consola$1.start("Initializing app...");
|
|
1240
|
+
const { execCommand, packageManager } = await ensurePackageJson();
|
|
1241
|
+
runInstall(packageManager, REQUIRED_DEPENDENCIES);
|
|
1242
|
+
const { config, domains } = await ensureCommerceAppConfig(process.cwd(), extraOptions?.formatConfig ?? true, flags);
|
|
1243
|
+
installDependencies(packageManager, domains);
|
|
1244
|
+
const pkg = await NpmPackageJson.load(process.cwd());
|
|
1245
|
+
pkg.update({
|
|
1246
|
+
name: config.metadata.id,
|
|
1247
|
+
version: config.metadata.version,
|
|
1248
|
+
description: config.metadata.description
|
|
1249
|
+
});
|
|
1250
|
+
await pkg.save();
|
|
1251
|
+
await runGeneration(config, execCommand);
|
|
1252
|
+
await ensureAppConfig(domains);
|
|
1253
|
+
await ensureInstallYaml(domains);
|
|
1254
|
+
await writePostinstallHook(execCommand);
|
|
1255
|
+
consola$1.success("Initialization complete!");
|
|
1256
|
+
consola$1.box([
|
|
1257
|
+
"Next steps:",
|
|
1258
|
+
" - Review and customize app.commerce.config.*",
|
|
1259
|
+
" - Build and deploy your app"
|
|
1260
|
+
].join("\n"));
|
|
1261
|
+
}
|
|
1262
|
+
/** Run the init command */
|
|
986
1263
|
async function exec() {
|
|
987
1264
|
try {
|
|
988
|
-
|
|
989
|
-
const { execCommand, packageManager } = await ensurePackageJson();
|
|
990
|
-
runInstall(packageManager, REQUIRED_DEPENDENCIES);
|
|
991
|
-
const { config, domains } = await ensureCommerceAppConfig();
|
|
992
|
-
installDependencies(packageManager, domains);
|
|
993
|
-
execSync(`npm pkg set name="${config.metadata.id}"`);
|
|
994
|
-
execSync(`npm pkg set version="${config.metadata.version}"`);
|
|
995
|
-
execSync(`npm pkg set description="${config.metadata.description}"`);
|
|
996
|
-
await runGeneration(config, execCommand);
|
|
997
|
-
await ensureAppConfig(domains);
|
|
998
|
-
await ensureInstallYaml(domains);
|
|
999
|
-
consola$1.success("Initialization complete!");
|
|
1000
|
-
consola$1.box([
|
|
1001
|
-
"Next steps:",
|
|
1002
|
-
" - Review and customize app.commerce.config.*",
|
|
1003
|
-
" - Build and deploy your app"
|
|
1004
|
-
].join("\n"));
|
|
1265
|
+
await run();
|
|
1005
1266
|
} catch (error) {
|
|
1006
1267
|
if (error instanceof CommerceSdkValidationError) consola$1.error(error.display());
|
|
1007
|
-
consola$1.error(error);
|
|
1268
|
+
else consola$1.error(error);
|
|
1008
1269
|
process.exit(1);
|
|
1009
1270
|
}
|
|
1010
1271
|
}
|