@adobe/aio-commerce-lib-app 1.3.1 → 1.5.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 +53 -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 -321
- 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 -316
- 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 +15 -12
- /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
|
+
}
|
|
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
|
+
}
|
|
42
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,177 +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
|
-
"webhooks",
|
|
351
|
-
"adminUiSdk"
|
|
352
|
-
].some((feature) => features.has(feature))) {
|
|
353
|
-
extConfig.operations.workerProcess.push({
|
|
354
|
-
type: "action",
|
|
355
|
-
impl: `${PACKAGE_NAME}/installation`
|
|
356
|
-
});
|
|
357
|
-
extConfig.runtimeManifest.packages[PACKAGE_NAME].actions.installation = createActionDefinition("installation", { requiresEncryptionKey: hasPasswordFieldsInSchema }, {
|
|
358
|
-
inputs: {
|
|
359
|
-
...COMMERCE_ACTION_INPUTS,
|
|
360
|
-
LOG_LEVEL: "$LOG_LEVEL"
|
|
361
|
-
},
|
|
362
|
-
limits: { timeout: 6e5 }
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
return extConfig;
|
|
366
|
-
}
|
|
367
|
-
/** Builds the ext.config.yaml configuration for the business configuration extension. */
|
|
368
|
-
function buildBusinessConfigurationExtConfig() {
|
|
369
|
-
const actions = [{
|
|
370
|
-
name: "config",
|
|
371
|
-
templateFile: "config.js.template",
|
|
372
|
-
requiresEncryptionKey: true
|
|
373
|
-
}, {
|
|
374
|
-
name: "scope-tree",
|
|
375
|
-
templateFile: "scope-tree.js.template"
|
|
376
|
-
}];
|
|
377
|
-
return {
|
|
378
|
-
hooks: { "pre-app-build": "EXTENSION=configuration/1 $packageExec aio-commerce-lib-app hooks pre-app-build" },
|
|
379
|
-
operations: { workerProcess: actions.map((action) => ({
|
|
380
|
-
type: "action",
|
|
381
|
-
impl: `${PACKAGE_NAME}/${action.name}`
|
|
382
|
-
})) },
|
|
383
|
-
runtimeManifest: { packages: { [PACKAGE_NAME]: {
|
|
384
|
-
license: "Apache-2.0",
|
|
385
|
-
actions: Object.fromEntries(actions.map((action) => [action.name, createActionDefinition(action.name, action)]))
|
|
386
|
-
} } }
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
//#endregion
|
|
391
|
-
//#region source/commands/generate/actions/main.ts
|
|
392
|
-
const __dirname$1 = (0, path.dirname)((0, url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
|
|
393
|
-
async function run$4(appManifest) {
|
|
394
|
-
await generateActionFiles(appManifest, getRuntimeActions(await updateExtConfig(appManifest, EXTENSIBILITY_EXTENSION_POINT_ID), "app-management"), EXTENSIBILITY_EXTENSION_POINT_ID);
|
|
395
|
-
if (require_validate.hasBusinessConfigSchema(appManifest)) await generateActionFiles(appManifest, getRuntimeActions(await updateExtConfig(appManifest, CONFIGURATION_EXTENSION_POINT_ID), "business-configuration"), CONFIGURATION_EXTENSION_POINT_ID);
|
|
396
|
-
}
|
|
397
|
-
/** Run the generate actions command */
|
|
398
|
-
async function exec$5() {
|
|
515
|
+
async function readExtConfig(extensionPointId) {
|
|
516
|
+
const extConfigPath = (0, path.join)(await require_config.getProjectRootDirectory(), getExtConfigPath(extensionPointId));
|
|
399
517
|
try {
|
|
400
|
-
|
|
518
|
+
return {
|
|
519
|
+
path: extConfigPath,
|
|
520
|
+
doc: await readYamlFile(extConfigPath)
|
|
521
|
+
};
|
|
401
522
|
} catch (error) {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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"));
|
|
405
529
|
}
|
|
406
530
|
}
|
|
407
531
|
/** Update the ext.config.yaml file */
|
|
408
532
|
async function updateExtConfig(appConfig, extensionPointId) {
|
|
409
533
|
consola.consola.info(`Updating ext.config.yaml for ${extensionPointId}...`);
|
|
410
|
-
|
|
411
|
-
const extConfigDoc = await
|
|
534
|
+
await require_config.makeOutputDirFor(getExtensionPointFolderPath(extensionPointId));
|
|
535
|
+
const { path: extConfigPath, doc: extConfigDoc } = await readExtConfig(extensionPointId);
|
|
412
536
|
let extConfig;
|
|
413
537
|
switch (extensionPointId) {
|
|
414
538
|
case EXTENSIBILITY_EXTENSION_POINT_ID:
|
|
@@ -417,24 +541,26 @@ async function updateExtConfig(appConfig, extensionPointId) {
|
|
|
417
541
|
case CONFIGURATION_EXTENSION_POINT_ID:
|
|
418
542
|
extConfig = buildBusinessConfigurationExtConfig();
|
|
419
543
|
break;
|
|
420
|
-
|
|
544
|
+
case BACKEND_UI_EXTENSION_POINT_ID:
|
|
545
|
+
extConfig = buildAdminUiSdkExtConfig();
|
|
546
|
+
break;
|
|
421
547
|
}
|
|
422
548
|
await createOrUpdateExtConfig(extConfigPath, extConfig, extConfigDoc);
|
|
423
549
|
return extConfig;
|
|
424
550
|
}
|
|
425
551
|
/** Generate the action files */
|
|
426
|
-
async function generateActionFiles(appManifest, actions, extensionPointId) {
|
|
552
|
+
async function generateActionFiles(appManifest, actions, extensionPointId, templatesDir) {
|
|
427
553
|
consola.consola.start("Generating runtime actions...");
|
|
428
|
-
|
|
554
|
+
await require_config.makeOutputDirFor(getActionsDir(extensionPointId));
|
|
555
|
+
const projectRoot = await require_config.getProjectRootDirectory();
|
|
429
556
|
const outputFiles = [];
|
|
430
|
-
const templatesDir = (0, path.join)(__dirname$1, "generate/actions/templates");
|
|
431
557
|
for (const action of actions) {
|
|
432
558
|
let template = await (0, fs_promises.readFile)((0, path.join)(templatesDir, action.templateFile), "utf-8");
|
|
433
559
|
if (action.name === "installation") {
|
|
434
560
|
const scriptsTemplate = await generateCustomScriptsTemplate(await (0, fs_promises.readFile)((0, path.join)(templatesDir, "app-management", "custom-scripts.js.template"), "utf-8"), appManifest);
|
|
435
561
|
template = applyCustomScripts(template, scriptsTemplate);
|
|
436
562
|
}
|
|
437
|
-
const actionPath = (0, path.join)(
|
|
563
|
+
const actionPath = (0, path.join)(projectRoot, getActionPath(extensionPointId, action.name));
|
|
438
564
|
await (0, fs_promises.writeFile)(actionPath, template, "utf-8");
|
|
439
565
|
outputFiles.push(` ${(0, path.relative)(process.cwd(), actionPath)}`);
|
|
440
566
|
}
|
|
@@ -457,7 +583,7 @@ function applyCustomScripts(installationTemplate, customScriptsTemplate) {
|
|
|
457
583
|
async function generateCustomScriptsTemplate(template, appManifest) {
|
|
458
584
|
if (!require_webhooks.hasCustomInstallationSteps(appManifest)) return null;
|
|
459
585
|
const projectRoot = await require_config.getProjectRootDirectory();
|
|
460
|
-
const installationActionDir = (0, path.join)(projectRoot,
|
|
586
|
+
const installationActionDir = (0, path.join)(projectRoot, getActionsDir(EXTENSIBILITY_EXTENSION_POINT_ID));
|
|
461
587
|
const customSteps = appManifest.installation.customInstallationSteps;
|
|
462
588
|
const importStatements = customSteps.map((step, index) => {
|
|
463
589
|
let relativeImportPath = (0, path.relative)(installationActionDir, (0, path.join)(projectRoot, step.script));
|
|
@@ -471,36 +597,92 @@ async function generateCustomScriptsTemplate(template, appManifest) {
|
|
|
471
597
|
}).join("\n");
|
|
472
598
|
return template.replace(CUSTOM_IMPORTS_PLACEHOLDER, importStatements).replace(CUSTOM_SCRIPTS_MAP_PLACEHOLDER, scriptMap);
|
|
473
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
|
+
}
|
|
474
643
|
|
|
475
644
|
//#endregion
|
|
476
645
|
//#region source/commands/generate/manifest/main.ts
|
|
477
|
-
async function run$
|
|
646
|
+
async function run$4(appConfig) {
|
|
478
647
|
consola.consola.info("Generating app manifest...");
|
|
479
648
|
const contents = (0, safe_stable_stringify.stringify)(appConfig, null, 2);
|
|
480
|
-
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");
|
|
481
650
|
consola.consola.success(`Generated ${APP_MANIFEST_FILE}`);
|
|
482
651
|
}
|
|
483
652
|
/** Run the generate manifest command */
|
|
484
653
|
async function exec$4() {
|
|
485
654
|
try {
|
|
486
|
-
await run$
|
|
655
|
+
await run$4(await loadAppManifest());
|
|
487
656
|
} catch (error) {
|
|
488
657
|
if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.consola.error(error.display());
|
|
489
|
-
consola.consola.error(error);
|
|
658
|
+
else consola.consola.error(error);
|
|
490
659
|
process.exit(1);
|
|
491
660
|
}
|
|
492
661
|
}
|
|
493
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
|
+
|
|
494
675
|
//#endregion
|
|
495
676
|
//#region source/commands/generate/schema/main.ts
|
|
496
|
-
async function run$
|
|
497
|
-
consola.consola.info("Generating configuration schema...");
|
|
677
|
+
async function run$3(appConfig) {
|
|
498
678
|
if (!require_validate.hasBusinessConfigSchema(appConfig)) {
|
|
499
|
-
consola.consola.
|
|
679
|
+
consola.consola.debug("Business configuration schema not found in application configuration. Nothing to do.");
|
|
500
680
|
return;
|
|
501
681
|
}
|
|
502
|
-
|
|
682
|
+
consola.consola.info("Generating configuration schema...");
|
|
683
|
+
const projectDir = await require_config.getProjectRootDirectory();
|
|
503
684
|
const envPath = (0, path.join)(projectDir, ".env");
|
|
685
|
+
await touch(envPath);
|
|
504
686
|
process.loadEnvFile(envPath);
|
|
505
687
|
if (appConfig.businessConfig.schema.some((field) => field.type === "password")) {
|
|
506
688
|
const packageExec = require_config.getExecCommand(await require_config.detectPackageManager(projectDir));
|
|
@@ -508,35 +690,35 @@ async function run$2(appConfig) {
|
|
|
508
690
|
else (0, child_process.execSync)(`${packageExec} aio-commerce-lib-config encryption setup`);
|
|
509
691
|
}
|
|
510
692
|
const contents = (0, safe_stable_stringify.stringify)(appConfig.businessConfig.schema, null, 2);
|
|
511
|
-
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");
|
|
512
694
|
consola.consola.success(`Generated ${CONFIG_SCHEMA_FILE_NAME}`);
|
|
513
695
|
}
|
|
514
|
-
/** Run the generate
|
|
696
|
+
/** Run the generate schema command */
|
|
515
697
|
async function exec$3() {
|
|
516
698
|
try {
|
|
517
|
-
await run$
|
|
699
|
+
await run$3(await loadAppManifest());
|
|
518
700
|
} catch (error) {
|
|
519
701
|
if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.consola.error(error.display());
|
|
520
|
-
consola.consola.error(error);
|
|
702
|
+
else consola.consola.error(error);
|
|
521
703
|
process.exit(1);
|
|
522
704
|
}
|
|
523
705
|
}
|
|
524
706
|
|
|
525
707
|
//#endregion
|
|
526
708
|
//#region source/commands/hooks/postinstall.ts
|
|
527
|
-
async function run$
|
|
709
|
+
async function run$2(appManifest, templatesDir) {
|
|
710
|
+
await run$5(appManifest, templatesDir);
|
|
528
711
|
await run$4(appManifest);
|
|
529
712
|
await run$3(appManifest);
|
|
530
|
-
await run$2(appManifest);
|
|
531
713
|
}
|
|
532
714
|
/** Runs the postinstall hook */
|
|
533
715
|
async function exec$2() {
|
|
534
716
|
consola.default.debug("Running lib-app postinstall hook");
|
|
535
717
|
try {
|
|
536
|
-
await run$
|
|
718
|
+
await run$2(await loadAppManifest());
|
|
537
719
|
} catch (error) {
|
|
538
720
|
if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.default.error(error.display());
|
|
539
|
-
consola.default.error(error);
|
|
721
|
+
else consola.default.error(error);
|
|
540
722
|
process.exit(1);
|
|
541
723
|
}
|
|
542
724
|
}
|
|
@@ -592,19 +774,27 @@ function resolveImsS2SContext() {
|
|
|
592
774
|
}
|
|
593
775
|
/**
|
|
594
776
|
* Syncs the IMS credentials environment variables from the configured IMS context in
|
|
595
|
-
* 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`.
|
|
596
778
|
*/
|
|
597
779
|
async function syncImsCredentials() {
|
|
598
780
|
const envPath = resolveEnvPath();
|
|
781
|
+
if (!(0, fs.existsSync)(envPath)) return {
|
|
782
|
+
ok: false,
|
|
783
|
+
reason: "missing-env"
|
|
784
|
+
};
|
|
599
785
|
const envVars = dotenv.default.parse((0, fs.readFileSync)(envPath, "utf8"));
|
|
600
786
|
const imsContext = await resolveImsS2SContext();
|
|
601
|
-
if (!imsContext) return
|
|
787
|
+
if (!imsContext) return {
|
|
788
|
+
ok: false,
|
|
789
|
+
reason: "no-ims-context"
|
|
790
|
+
};
|
|
602
791
|
const { data } = imsContext;
|
|
603
792
|
for (const [key, value] of Object.entries(data)) {
|
|
604
793
|
const oauthKey = IMS_KEYS[key];
|
|
605
794
|
if (!oauthKey) continue;
|
|
606
795
|
if (!envVars[oauthKey] || envVars[oauthKey] !== value) replaceEnvVar(envPath, oauthKey, value);
|
|
607
796
|
}
|
|
797
|
+
return { ok: true };
|
|
608
798
|
}
|
|
609
799
|
|
|
610
800
|
//#endregion
|
|
@@ -612,17 +802,26 @@ async function syncImsCredentials() {
|
|
|
612
802
|
/**
|
|
613
803
|
* Runs the pre-app-build hook for the given extension.
|
|
614
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.
|
|
615
806
|
*/
|
|
616
|
-
async function run(extension) {
|
|
807
|
+
async function run$1(extension, templatesDir = TEMPLATES_DIR) {
|
|
617
808
|
const appManifest = await loadAppManifest();
|
|
618
809
|
if (extension === "extensibility/1") {
|
|
619
|
-
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);
|
|
620
813
|
consola.default.info("Syncing IMS credentials...");
|
|
621
814
|
await syncImsCredentials();
|
|
622
815
|
return;
|
|
623
816
|
}
|
|
624
817
|
if (extension === "configuration/1") {
|
|
625
|
-
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);
|
|
626
825
|
return;
|
|
627
826
|
}
|
|
628
827
|
throw new Error(`Unsupported extension: ${extension}`);
|
|
@@ -633,10 +832,10 @@ async function exec$1() {
|
|
|
633
832
|
const extension = process.env.EXTENSION;
|
|
634
833
|
try {
|
|
635
834
|
if (!extension) throw new Error("EXTENSION environment variable is not set");
|
|
636
|
-
await run(extension);
|
|
835
|
+
await run$1(extension);
|
|
637
836
|
} catch (error) {
|
|
638
837
|
if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.default.error(error.display());
|
|
639
|
-
consola.default.error(error);
|
|
838
|
+
else consola.default.error(error);
|
|
640
839
|
process.exit(1);
|
|
641
840
|
}
|
|
642
841
|
}
|
|
@@ -671,7 +870,7 @@ const DOMAIN_DEFAULTS = {
|
|
|
671
870
|
},
|
|
672
871
|
events: [{
|
|
673
872
|
name: "plugin.sample_event",
|
|
674
|
-
fields: [],
|
|
873
|
+
fields: [{ name: "*" }],
|
|
675
874
|
label: "Sample Event",
|
|
676
875
|
description: "Use case description for the event.",
|
|
677
876
|
runtimeActions: ["my-package/handle-sample-event"]
|
|
@@ -693,12 +892,50 @@ const DOMAIN_DEFAULTS = {
|
|
|
693
892
|
name: "sample-step",
|
|
694
893
|
description: "Use case description for the step.",
|
|
695
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
|
+
}
|
|
696
920
|
}]
|
|
697
921
|
};
|
|
698
922
|
|
|
699
923
|
//#endregion
|
|
700
924
|
//#region source/commands/init/utils.ts
|
|
701
|
-
/**
|
|
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. */
|
|
702
939
|
async function promptForCommerceAppConfig() {
|
|
703
940
|
const configFormat = await consola.default.prompt("What format do you want to use for the config file?", {
|
|
704
941
|
type: "select",
|
|
@@ -734,6 +971,10 @@ async function promptForCommerceAppConfig() {
|
|
|
734
971
|
label: "Commerce Events",
|
|
735
972
|
value: "eventing.commerce"
|
|
736
973
|
},
|
|
974
|
+
{
|
|
975
|
+
label: "Commerce Webhooks",
|
|
976
|
+
value: "webhooks"
|
|
977
|
+
},
|
|
737
978
|
{
|
|
738
979
|
label: "External Events",
|
|
739
980
|
value: "eventing.external"
|
|
@@ -744,10 +985,13 @@ async function promptForCommerceAppConfig() {
|
|
|
744
985
|
}
|
|
745
986
|
]
|
|
746
987
|
});
|
|
988
|
+
const configFile = `${COMMERCE_APP_CONFIG_FILE}.${configFormat}`;
|
|
989
|
+
const domains = new Set(featuresToAdd);
|
|
990
|
+
consola.default.log("");
|
|
747
991
|
return {
|
|
748
992
|
appName,
|
|
749
|
-
configFile
|
|
750
|
-
domains
|
|
993
|
+
configFile,
|
|
994
|
+
domains,
|
|
751
995
|
configFormat
|
|
752
996
|
};
|
|
753
997
|
}
|
|
@@ -772,6 +1016,7 @@ async function getDefaultCommerceAppConfig(cwd, { appName, configFormat, domains
|
|
|
772
1016
|
external: DOMAIN_DEFAULTS["eventing.external"]
|
|
773
1017
|
};
|
|
774
1018
|
if (domains.has("installation.customInstallationSteps")) defaultConfig.installation = { customInstallationSteps: DOMAIN_DEFAULTS["installation.customInstallationSteps"] };
|
|
1019
|
+
if (domains.has("webhooks")) defaultConfig.webhooks = DOMAIN_DEFAULTS.webhooks;
|
|
775
1020
|
return [
|
|
776
1021
|
importStatement,
|
|
777
1022
|
"",
|
|
@@ -786,9 +1031,8 @@ async function getDefaultCommerceAppConfig(cwd, { appName, configFormat, domains
|
|
|
786
1031
|
*/
|
|
787
1032
|
async function addExtensionPointToAppConfig(extensionPointId, rootDirectory, commentBefore) {
|
|
788
1033
|
const appConfigPath = (0, path.join)(rootDirectory, APP_CONFIG_FILE);
|
|
789
|
-
const extensionPointFolderPath = (0, path.join)(rootDirectory, getExtensionPointFolderPath(extensionPointId));
|
|
790
1034
|
let doc;
|
|
791
|
-
const includePath = (0, path.relative)(rootDirectory, (0, path.join)(
|
|
1035
|
+
const includePath = (0, path.relative)(rootDirectory, (0, path.join)(rootDirectory, getExtConfigPath(extensionPointId)));
|
|
792
1036
|
try {
|
|
793
1037
|
doc = await readYamlFile(appConfigPath);
|
|
794
1038
|
} catch (error) {
|
|
@@ -846,12 +1090,12 @@ async function addExtensionPointToInstallYaml(extensionPointId, rootDirectory, c
|
|
|
846
1090
|
|
|
847
1091
|
//#endregion
|
|
848
1092
|
//#region source/commands/init/lib.ts
|
|
849
|
-
/** Ensure app.commerce.config file exists, allow creating if it doesn't */
|
|
850
|
-
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) {
|
|
851
1095
|
let config = null;
|
|
852
1096
|
try {
|
|
853
1097
|
config = await require_config.readCommerceAppConfig(cwd);
|
|
854
|
-
} catch
|
|
1098
|
+
} catch {}
|
|
855
1099
|
if (config) try {
|
|
856
1100
|
const validatedConfig = require_validate.validateCommerceAppConfig(config);
|
|
857
1101
|
consola.consola.success(`${COMMERCE_APP_CONFIG_FILE} found and is valid. Continuing...`);
|
|
@@ -862,119 +1106,126 @@ async function ensureCommerceAppConfig(cwd = process.cwd()) {
|
|
|
862
1106
|
} catch (error) {
|
|
863
1107
|
throw new Error(`${COMMERCE_APP_CONFIG_FILE} is invalid`, { cause: error });
|
|
864
1108
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
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();
|
|
872
1118
|
try {
|
|
873
1119
|
const configContent = await getDefaultCommerceAppConfig(cwd, answers);
|
|
874
|
-
consola.consola.info(`Creating ${answers.configFile}...`);
|
|
875
1120
|
const path$2 = (0, path.join)(await require_config.getProjectRootDirectory(cwd), answers.configFile);
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
bracketSameLine: true,
|
|
881
|
-
bracketSpacing: true,
|
|
882
|
-
trailingComma: "all",
|
|
883
|
-
tabWidth: 2,
|
|
884
|
-
useTabs: false,
|
|
885
|
-
printWidth: 80,
|
|
886
|
-
filepath: path$2
|
|
887
|
-
}), "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);
|
|
888
1125
|
consola.consola.success(`Created ${answers.configFile}`);
|
|
889
1126
|
return {
|
|
890
|
-
config
|
|
1127
|
+
config,
|
|
891
1128
|
domains: answers.domains
|
|
892
1129
|
};
|
|
893
1130
|
} catch (error) {
|
|
894
1131
|
throw new Error(`Failed to create ${answers.configFile}`, { cause: error });
|
|
895
1132
|
}
|
|
896
1133
|
}
|
|
897
|
-
/**
|
|
1134
|
+
/**
|
|
1135
|
+
* Ensure a package.json exists and detect the package manager.
|
|
1136
|
+
* @param cwd - Directory to check; defaults to `process.cwd()`
|
|
1137
|
+
*/
|
|
898
1138
|
async function ensurePackageJson(cwd = process.cwd()) {
|
|
899
|
-
const
|
|
900
|
-
|
|
1139
|
+
const existing = await require_config.readPackageJson(cwd);
|
|
1140
|
+
let packageJson;
|
|
1141
|
+
if (existing) packageJson = existing;
|
|
1142
|
+
else {
|
|
901
1143
|
consola.consola.warn("package.json not found. Creating one...");
|
|
902
|
-
|
|
1144
|
+
packageJson = {
|
|
903
1145
|
name: "my-commerce-app",
|
|
904
1146
|
version: "1.0.0",
|
|
905
|
-
private: true
|
|
906
|
-
scripts: { postinstall: "npx aio-commerce-lib-app hooks postinstall" }
|
|
1147
|
+
private: true
|
|
907
1148
|
};
|
|
908
|
-
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");
|
|
909
1150
|
consola.consola.success("Wrote package.json");
|
|
910
|
-
return {
|
|
911
|
-
packageJson: packageJsonContent,
|
|
912
|
-
packageManager: "npm",
|
|
913
|
-
execCommand: "npx"
|
|
914
|
-
};
|
|
915
1151
|
}
|
|
916
|
-
const packageManager = await require_config.detectPackageManager();
|
|
1152
|
+
const packageManager = await require_config.detectPackageManager(cwd);
|
|
917
1153
|
const execCommand = require_config.getExecCommand(packageManager);
|
|
918
|
-
const postinstallScript = `${execCommand} aio-commerce-lib-app hooks postinstall`;
|
|
919
|
-
packageJson.scripts ??= {};
|
|
920
|
-
if (packageJson.scripts.postinstall === postinstallScript || packageJson.scripts.postinstall?.includes(postinstallScript)) {
|
|
921
|
-
consola.consola.success(`postinstall script already configured in ${PACKAGE_JSON_FILE}`);
|
|
922
|
-
return {
|
|
923
|
-
packageJson,
|
|
924
|
-
packageManager,
|
|
925
|
-
execCommand
|
|
926
|
-
};
|
|
927
|
-
}
|
|
928
|
-
if (packageJson.scripts.postinstall) {
|
|
929
|
-
consola.consola.warn(`${PACKAGE_JSON_FILE} already has a postinstall script. Adding a new one...`);
|
|
930
|
-
(0, child_process.execSync)(`npm pkg set scripts.postinstall="${`${packageJson.scripts.postinstall} && ${postinstallScript}`}"`);
|
|
931
|
-
} else {
|
|
932
|
-
consola.consola.info(`Adding postinstall script to ${PACKAGE_JSON_FILE}...`);
|
|
933
|
-
(0, child_process.execSync)(`npm pkg set scripts.postinstall="${postinstallScript}"`);
|
|
934
|
-
}
|
|
935
|
-
consola.consola.success(`Added postinstall script to ${PACKAGE_JSON_FILE}`);
|
|
936
1154
|
return {
|
|
937
1155
|
packageJson,
|
|
938
1156
|
packageManager,
|
|
939
1157
|
execCommand
|
|
940
1158
|
};
|
|
941
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
|
+
}
|
|
942
1183
|
/** Ensure app.config.yaml has the extension reference */
|
|
943
1184
|
async function ensureAppConfig(domains, cwd = process.cwd()) {
|
|
944
1185
|
const rootDirectory = await require_config.getProjectRootDirectory(cwd);
|
|
945
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.");
|
|
946
1188
|
await addExtensionPointToAppConfig(EXTENSIBILITY_EXTENSION_POINT_ID, rootDirectory, " This extension is required for app management. Do not remove.");
|
|
947
1189
|
}
|
|
948
|
-
/**
|
|
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
|
+
*/
|
|
949
1196
|
function runInstall(packageManager, dependencies, cwd = process.cwd()) {
|
|
1197
|
+
if (dependencies.length === 0) return;
|
|
950
1198
|
const dependencyListString = dependencies.map((dependency) => ` - ${dependency}`).join("\n");
|
|
951
|
-
consola.consola.
|
|
952
|
-
const
|
|
953
|
-
const
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
cwd,
|
|
962
|
-
stdio: "inherit"
|
|
963
|
-
});
|
|
964
|
-
consola.consola.success("Dependencies installed successfully");
|
|
965
|
-
} catch (error) {
|
|
966
|
-
throw new Error(`Failed to install dependencies automatically. Please install manually: ${installCommand}`, { cause: error });
|
|
967
|
-
}
|
|
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");
|
|
968
1209
|
}
|
|
969
|
-
/**
|
|
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
|
+
*/
|
|
970
1216
|
function installDependencies(packageManager, domains, cwd = process.cwd()) {
|
|
971
1217
|
const packages = [];
|
|
972
|
-
if (domains.has("businessConfig.schema")) packages.push(
|
|
1218
|
+
if (domains.has("businessConfig.schema")) packages.push(`@adobe/aio-commerce-lib-config@^1.4.0`);
|
|
1219
|
+
if (packages.length === 0) {
|
|
1220
|
+
consola.consola.info("No additional domain dependencies to install.");
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
973
1223
|
runInstall(packageManager, packages, cwd);
|
|
974
1224
|
}
|
|
975
1225
|
/** Run the generation command */
|
|
976
1226
|
async function runGeneration(appConfig, execCommand) {
|
|
977
1227
|
try {
|
|
1228
|
+
await run$5(appConfig);
|
|
978
1229
|
await run$4(appConfig);
|
|
979
1230
|
await run$3(appConfig);
|
|
980
1231
|
} catch (error) {
|
|
@@ -985,35 +1236,45 @@ async function runGeneration(appConfig, execCommand) {
|
|
|
985
1236
|
async function ensureInstallYaml(domains, cwd = process.cwd()) {
|
|
986
1237
|
const rootDirectory = await require_config.getProjectRootDirectory(cwd);
|
|
987
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.");
|
|
988
1240
|
await addExtensionPointToInstallYaml(EXTENSIBILITY_EXTENSION_POINT_ID, rootDirectory, " This extension is required for app management. Do not remove.");
|
|
989
1241
|
}
|
|
990
1242
|
|
|
991
1243
|
//#endregion
|
|
992
1244
|
//#region source/commands/init/main.ts
|
|
993
|
-
const REQUIRED_DEPENDENCIES = ["@adobe/aio-commerce-
|
|
994
|
-
/** Initialize the project
|
|
1245
|
+
const REQUIRED_DEPENDENCIES = ["@adobe/aio-commerce-sdk", `@adobe/aio-commerce-lib-app@1.5.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 */
|
|
995
1272
|
async function exec() {
|
|
996
1273
|
try {
|
|
997
|
-
|
|
998
|
-
const { execCommand, packageManager } = await ensurePackageJson();
|
|
999
|
-
runInstall(packageManager, REQUIRED_DEPENDENCIES);
|
|
1000
|
-
const { config, domains } = await ensureCommerceAppConfig();
|
|
1001
|
-
installDependencies(packageManager, domains);
|
|
1002
|
-
(0, child_process.execSync)(`npm pkg set name="${config.metadata.id}"`);
|
|
1003
|
-
(0, child_process.execSync)(`npm pkg set version="${config.metadata.version}"`);
|
|
1004
|
-
(0, child_process.execSync)(`npm pkg set description="${config.metadata.description}"`);
|
|
1005
|
-
await runGeneration(config, execCommand);
|
|
1006
|
-
await ensureAppConfig(domains);
|
|
1007
|
-
await ensureInstallYaml(domains);
|
|
1008
|
-
consola.consola.success("Initialization complete!");
|
|
1009
|
-
consola.consola.box([
|
|
1010
|
-
"Next steps:",
|
|
1011
|
-
" - Review and customize app.commerce.config.*",
|
|
1012
|
-
" - Build and deploy your app"
|
|
1013
|
-
].join("\n"));
|
|
1274
|
+
await run();
|
|
1014
1275
|
} catch (error) {
|
|
1015
1276
|
if (error instanceof _adobe_aio_commerce_lib_core_error.CommerceSdkValidationError) consola.consola.error(error.display());
|
|
1016
|
-
consola.consola.error(error);
|
|
1277
|
+
else consola.consola.error(error);
|
|
1017
1278
|
process.exit(1);
|
|
1018
1279
|
}
|
|
1019
1280
|
}
|