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