@adobe/aio-commerce-lib-app 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/actions/index.cjs +815 -170
  3. package/dist/cjs/actions/index.d.cts +2 -2
  4. package/dist/cjs/app-Dx0ca6oL.d.cts +181 -0
  5. package/dist/cjs/commands/generate/actions/templates/business-configuration/get-config-schema.js.template +63 -0
  6. package/dist/cjs/commands/generate/actions/templates/business-configuration/get-configuration.js.template +104 -0
  7. package/dist/cjs/commands/generate/actions/templates/business-configuration/get-scope-tree.js.template +69 -0
  8. package/dist/cjs/commands/generate/actions/templates/business-configuration/set-configuration.js.template +125 -0
  9. package/dist/cjs/commands/generate/actions/templates/business-configuration/set-custom-scope-tree.js.template +83 -0
  10. package/dist/cjs/commands/generate/actions/templates/business-configuration/sync-commerce-scopes.js.template +113 -0
  11. package/dist/cjs/commands/generate/actions/templates/business-configuration/unsync-commerce-scopes.js.template +56 -0
  12. package/dist/cjs/commands/index.cjs +1075 -119
  13. package/dist/cjs/config/index.cjs +20 -1
  14. package/dist/cjs/config/index.d.cts +532 -3
  15. package/dist/cjs/config-JQ_n-5Nk.cjs +565 -0
  16. package/dist/cjs/error-Byj1DVHZ.cjs +344 -0
  17. package/dist/cjs/{index-DS3IlISO.d.cts → index-C5SutkJQ.d.cts} +1 -1
  18. package/dist/cjs/logging-DYwr5WQk.cjs +25 -0
  19. package/dist/cjs/management/index.cjs +9 -1
  20. package/dist/cjs/management/index.d.cts +1 -1
  21. package/dist/cjs/management-Dm5h0E6l.cjs +1246 -0
  22. package/dist/es/actions/index.d.mts +2 -2
  23. package/dist/es/actions/index.mjs +813 -170
  24. package/dist/es/app-Cx1-6dn0.d.mts +181 -0
  25. package/dist/es/commands/generate/actions/templates/business-configuration/get-config-schema.js.template +63 -0
  26. package/dist/es/commands/generate/actions/templates/business-configuration/get-configuration.js.template +104 -0
  27. package/dist/es/commands/generate/actions/templates/business-configuration/get-scope-tree.js.template +69 -0
  28. package/dist/es/commands/generate/actions/templates/business-configuration/set-configuration.js.template +125 -0
  29. package/dist/es/commands/generate/actions/templates/business-configuration/set-custom-scope-tree.js.template +83 -0
  30. package/dist/es/commands/generate/actions/templates/business-configuration/sync-commerce-scopes.js.template +113 -0
  31. package/dist/es/commands/generate/actions/templates/business-configuration/unsync-commerce-scopes.js.template +56 -0
  32. package/dist/es/commands/index.mjs +1070 -119
  33. package/dist/es/config/index.d.mts +532 -3
  34. package/dist/es/config/index.mjs +4 -1
  35. package/dist/es/config-BSGerqCG.mjs +457 -0
  36. package/dist/es/error-P7JgUTds.mjs +251 -0
  37. package/dist/es/{index-DQepSWYP.d.mts → index-Bxr3zvCT.d.mts} +2 -2
  38. package/dist/es/logging-VgerMhp6.mjs +18 -0
  39. package/dist/es/management/index.d.mts +2 -2
  40. package/dist/es/management/index.mjs +3 -1
  41. package/dist/es/management-Y7pwEbNI.mjs +1204 -0
  42. package/package.json +20 -8
  43. package/dist/cjs/app-C4HhkXbP.d.cts +0 -451
  44. package/dist/cjs/error-yAk1zzvx.cjs +0 -1
  45. package/dist/cjs/management-CE3_DJw4.cjs +0 -2
  46. package/dist/cjs/parser-Dovux8ce.cjs +0 -1
  47. package/dist/cjs/schemas-CdaP-Exw.cjs +0 -1
  48. package/dist/es/app-CMpx3D7Y.d.mts +0 -451
  49. package/dist/es/chunk-VmiN0kV1.mjs +0 -1
  50. package/dist/es/error-hBHRgZ9R.mjs +0 -1
  51. package/dist/es/management-BM2WcbV6.mjs +0 -2
  52. package/dist/es/parser-DOVfvr9l.mjs +0 -1
  53. package/dist/es/schemas-eemlD-xS.mjs +0 -1
  54. /package/dist/cjs/commands/generate/actions/templates/{custom-scripts.js.template → app-management/custom-scripts.js.template} +0 -0
  55. /package/dist/cjs/commands/generate/actions/templates/{get-app-config.js.template → app-management/get-app-config.js.template} +0 -0
  56. /package/dist/cjs/commands/generate/actions/templates/{installation.js.template → app-management/installation.js.template} +0 -0
  57. /package/dist/es/commands/generate/actions/templates/{custom-scripts.js.template → app-management/custom-scripts.js.template} +0 -0
  58. /package/dist/es/commands/generate/actions/templates/{get-app-config.js.template → app-management/get-app-config.js.template} +0 -0
  59. /package/dist/es/commands/generate/actions/templates/{installation.js.template → app-management/installation.js.template} +0 -0
@@ -0,0 +1,1246 @@
1
+ const require_error = require('./error-Byj1DVHZ.cjs');
2
+ const require_logging = require('./logging-DYwr5WQk.cjs');
3
+ let camelcase = require("camelcase");
4
+ camelcase = require_error.__toESM(camelcase);
5
+ let _adobe_aio_commerce_lib_auth = require("@adobe/aio-commerce-lib-auth");
6
+ let _adobe_aio_commerce_lib_api = require("@adobe/aio-commerce-lib-api");
7
+ let _adobe_aio_commerce_lib_events_commerce = require("@adobe/aio-commerce-lib-events/commerce");
8
+ let _adobe_aio_commerce_lib_events_io_events = require("@adobe/aio-commerce-lib-events/io-events");
9
+
10
+ //#region source/management/installation/workflow/hooks.ts
11
+ /** Helper to call a hook if it exists. */
12
+ async function callHook(hooks, hookName, ...args) {
13
+ const hook = hooks?.[hookName];
14
+ if (hook) await hook(...args);
15
+ }
16
+
17
+ //#endregion
18
+ //#region source/management/installation/workflow/step.ts
19
+ /** Check if a step is a leaf step. */
20
+ function isLeafStep(step) {
21
+ return step.type === "leaf";
22
+ }
23
+ /** Check if a step is a branch step. */
24
+ function isBranchStep(step) {
25
+ return step.type === "branch";
26
+ }
27
+ /**
28
+ * Define a leaf step (executable, no children).
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const createProviders = defineLeafStep({
33
+ * name: "providers",
34
+ * meta: { label: "Create Providers", description: "Creates I/O Events providers" },
35
+ * run: async ({ config, stepContext }) => {
36
+ * const { eventsClient } = stepContext;
37
+ * return eventsClient.createProvider(config.eventing);
38
+ * },
39
+ * });
40
+ * ```
41
+ */
42
+ function defineLeafStep(options) {
43
+ return {
44
+ type: "leaf",
45
+ name: options.name,
46
+ meta: options.meta,
47
+ when: options.when,
48
+ run: options.run
49
+ };
50
+ }
51
+ /**
52
+ * Define a branch step (container with children, no runner).
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const eventing = defineBranchStep({
57
+ * name: "eventing",
58
+ * meta: { label: "Eventing", description: "Sets up I/O Events" },
59
+ * when: hasEventing,
60
+ * context: async (ctx) => ({ eventsClient: await createEventsClient(ctx) }),
61
+ * children: [commerceEventsStep, externalEventsStep],
62
+ * });
63
+ * ```
64
+ */
65
+ function defineBranchStep(options) {
66
+ return {
67
+ type: "branch",
68
+ name: options.name,
69
+ meta: options.meta,
70
+ when: options.when,
71
+ context: options.context,
72
+ children: options.children
73
+ };
74
+ }
75
+
76
+ //#endregion
77
+ //#region source/management/installation/workflow/utils.ts
78
+ /** Returns the current time as an ISO string. */
79
+ function nowIsoString() {
80
+ return (/* @__PURE__ */ new Date()).toISOString();
81
+ }
82
+ /** Sets a value at a nested path in the data object. */
83
+ function setAtPath(data, path, value) {
84
+ const lastKey = path.at(-1);
85
+ if (!lastKey) return;
86
+ let current = data;
87
+ for (let i = 0; i < path.length - 1; i++) {
88
+ const key = path[i];
89
+ current[key] ??= {};
90
+ current = current[key];
91
+ }
92
+ current[lastKey] = value;
93
+ }
94
+ /** Gets a value at a nested path in the data object. */
95
+ function getAtPath(data, path) {
96
+ let current = data;
97
+ for (const key of path) {
98
+ if (current == null || typeof current !== "object") return;
99
+ current = current[key];
100
+ }
101
+ return current;
102
+ }
103
+ /** Creates an installation error from an exception. */
104
+ function createInstallationError(err, path, key = "STEP_EXECUTION_FAILED") {
105
+ return {
106
+ path,
107
+ key,
108
+ message: err instanceof Error ? err.message : String(err)
109
+ };
110
+ }
111
+ /** Creates a succeeded installation state. */
112
+ function createSucceededState(base) {
113
+ return {
114
+ ...base,
115
+ status: "succeeded",
116
+ completedAt: nowIsoString()
117
+ };
118
+ }
119
+ /** Creates a failed installation state. */
120
+ function createFailedState(base, error) {
121
+ return {
122
+ ...base,
123
+ status: "failed",
124
+ completedAt: nowIsoString(),
125
+ error
126
+ };
127
+ }
128
+
129
+ //#endregion
130
+ //#region source/management/installation/workflow/runner.ts
131
+ /**
132
+ * Creates an initial installation state from a root step and config.
133
+ *
134
+ * Filters steps based on their `when` conditions and builds a
135
+ * tree structure with all steps set to "pending".
136
+ */
137
+ function createInitialState(options) {
138
+ const { rootStep, config } = options;
139
+ return {
140
+ id: crypto.randomUUID(),
141
+ startedAt: nowIsoString(),
142
+ status: "in-progress",
143
+ step: buildInitialStepStatus(rootStep, config, []),
144
+ data: null
145
+ };
146
+ }
147
+ /**
148
+ * Executes a workflow from an initial state. Returns the final state (never throws).
149
+ */
150
+ async function executeWorkflow(options) {
151
+ const { rootStep, installationContext, config, initialState, hooks } = options;
152
+ const step = structuredClone(initialState.step);
153
+ const context = {
154
+ installationContext,
155
+ config,
156
+ id: initialState.id,
157
+ startedAt: initialState.startedAt,
158
+ step,
159
+ data: null,
160
+ error: null,
161
+ hooks
162
+ };
163
+ await callHook(hooks, "onInstallationStart", snapshot(context));
164
+ try {
165
+ await executeStep(rootStep, context.step, {}, context);
166
+ const succeeded = createSucceededState({
167
+ id: context.id,
168
+ startedAt: context.startedAt,
169
+ step: context.step,
170
+ data: context.data
171
+ });
172
+ await callHook(hooks, "onInstallationSuccess", succeeded);
173
+ return succeeded;
174
+ } catch (err) {
175
+ const error = context.error ?? createInstallationError(err, [], "INSTALLATION_FAILED");
176
+ const failed = createFailedState({
177
+ step: context.step,
178
+ id: context.id,
179
+ startedAt: context.startedAt,
180
+ data: context.data
181
+ }, error);
182
+ await callHook(hooks, "onInstallationFailure", failed);
183
+ return failed;
184
+ }
185
+ }
186
+ /**
187
+ * Builds initial step status from a step definition.
188
+ * Filters steps based on their `when` conditions.
189
+ */
190
+ function buildInitialStepStatus(step, config, parentPath) {
191
+ const path = [...parentPath, step.name];
192
+ const children = [];
193
+ if (isBranchStep(step) && step.children.length > 0) for (const child of step.children) {
194
+ if (child.when && !child.when(config)) continue;
195
+ children.push(buildInitialStepStatus(child, config, path));
196
+ }
197
+ return {
198
+ id: crypto.randomUUID(),
199
+ name: step.name,
200
+ path,
201
+ meta: step.meta,
202
+ status: "pending",
203
+ children
204
+ };
205
+ }
206
+ /** Snapshot current execution as InProgressInstallationState. */
207
+ function snapshot(context) {
208
+ return {
209
+ id: context.id,
210
+ startedAt: context.startedAt,
211
+ status: "in-progress",
212
+ step: context.step,
213
+ data: context.data
214
+ };
215
+ }
216
+ /** Executes a single step (branch or leaf) recursively. */
217
+ async function executeStep(step, stepStatus, inherited, context) {
218
+ const { path } = stepStatus;
219
+ const isLeaf = isLeafStep(step);
220
+ stepStatus.status = "in-progress";
221
+ await callHook(context.hooks, "onStepStart", {
222
+ path,
223
+ stepName: step.name,
224
+ isLeaf
225
+ }, snapshot(context));
226
+ try {
227
+ if (isBranchStep(step)) await executeBranchStep(step, stepStatus, inherited, context);
228
+ else if (isLeafStep(step)) await executeLeafStep(step, stepStatus, inherited, context);
229
+ stepStatus.status = "succeeded";
230
+ context.data ??= {};
231
+ await callHook(context.hooks, "onStepSuccess", {
232
+ path,
233
+ stepName: step.name,
234
+ isLeaf,
235
+ result: getAtPath(context.data, path)
236
+ }, snapshot(context));
237
+ } catch (err) {
238
+ stepStatus.status = "failed";
239
+ context.error ??= createInstallationError(err, path);
240
+ await callHook(context.hooks, "onStepFailure", {
241
+ path,
242
+ stepName: step.name,
243
+ isLeaf,
244
+ error: context.error
245
+ }, snapshot(context));
246
+ throw err;
247
+ }
248
+ }
249
+ /** Executes a branch step by processing its children. */
250
+ async function executeBranchStep(step, stepStatus, inherited, context) {
251
+ let childContext = inherited;
252
+ if (step.context) {
253
+ const stepContext = await step.context(context.installationContext);
254
+ childContext = {
255
+ ...inherited,
256
+ ...stepContext
257
+ };
258
+ }
259
+ for (const child of stepStatus.children) {
260
+ const childStep = step.children.find((c) => c.name === child.name);
261
+ if (!childStep) throw new Error(`Step "${child.name}" not found`);
262
+ await executeStep(childStep, child, childContext, context);
263
+ }
264
+ }
265
+ /** Executes a leaf step and stores its result. */
266
+ async function executeLeafStep(step, stepStatus, inherited, context) {
267
+ const executionContext = {
268
+ ...context.installationContext,
269
+ ...inherited
270
+ };
271
+ const result = await step.run(context.config, executionContext);
272
+ context.data ??= {};
273
+ setAtPath(context.data, stepStatus.path, result);
274
+ }
275
+
276
+ //#endregion
277
+ //#region source/management/installation/workflow/types.ts
278
+ /** Type guard for pending installation state. */
279
+ /** Type guard for in-progress installation state. */
280
+ function isInProgressState(state) {
281
+ return state.status === "in-progress";
282
+ }
283
+ /** Type guard for succeeded installation state. */
284
+ function isSucceededState(state) {
285
+ return state.status === "succeeded";
286
+ }
287
+ /** Type guard for failed installation state. */
288
+ function isFailedState(state) {
289
+ return state.status === "failed";
290
+ }
291
+ /** Type guard for completed installation state (succeeded or failed). */
292
+ function isCompletedState(state) {
293
+ return state.status === "succeeded" || state.status === "failed";
294
+ }
295
+
296
+ //#endregion
297
+ //#region source/management/installation/custom-installation/custom-scripts.ts
298
+ /**
299
+ * Creates a leaf step for executing a single custom installation script.
300
+ */
301
+ function createCustomScriptStep(scriptConfig) {
302
+ const { script, name, description } = scriptConfig;
303
+ return defineLeafStep({
304
+ name: (0, camelcase.default)(name),
305
+ meta: {
306
+ label: name,
307
+ description
308
+ },
309
+ run: async (config, context) => {
310
+ const { logger } = context;
311
+ const customScripts = context.customScripts || {};
312
+ logger.info(`Executing custom installation script: ${name}`);
313
+ logger.debug(`Script path: ${script}`);
314
+ const scriptModule = customScripts[script];
315
+ if (!scriptModule) throw new Error(`Script ${script} not found in customScripts context. Make sure the script is defined in the configuration and the action was generated with custom scripts support.`);
316
+ if (typeof scriptModule !== "object" || !("default" in scriptModule)) throw new Error(`Script ${script} must export a default function. Use defineCustomInstallationStep helper.`);
317
+ const runFunction = scriptModule.default;
318
+ if (typeof runFunction !== "function") throw new Error(`Script ${script} default export must be a function, got ${typeof runFunction}`);
319
+ const scriptResult = await runFunction(config, context);
320
+ logger.info(`Successfully executed script: ${name}`);
321
+ return {
322
+ script,
323
+ data: scriptResult
324
+ };
325
+ }
326
+ });
327
+ }
328
+ /**
329
+ * Creates child steps dynamically based on the custom installation scripts
330
+ * defined in the configuration. Each script becomes a separate leaf step.
331
+ */
332
+ function createCustomScriptSteps(config) {
333
+ if (!require_error.hasCustomInstallationSteps(config)) return [];
334
+ const steps = config.installation.customInstallationSteps;
335
+ if (new Set(steps.map((step) => step.name)).size !== steps.length) throw new Error("Duplicate step names detected in custom installation steps. Each step must have a unique name.");
336
+ return steps.map((scriptConfig) => createCustomScriptStep(scriptConfig));
337
+ }
338
+
339
+ //#endregion
340
+ //#region source/management/installation/custom-installation/branch.ts
341
+ /** Root custom installation step that executes custom installation scripts. */
342
+ const customInstallationStepBase = defineBranchStep({
343
+ name: "customInstallationSteps",
344
+ meta: {
345
+ label: "Custom Installation Steps",
346
+ description: "Executes custom installation scripts defined in the application configuration"
347
+ },
348
+ when: require_error.hasCustomInstallationSteps,
349
+ children: []
350
+ });
351
+ /**
352
+ * Creates the custom installation step with dynamic children based on config.
353
+ * Each custom script becomes a direct child step.
354
+ */
355
+ function createCustomInstallationStep(config) {
356
+ return {
357
+ ...customInstallationStepBase,
358
+ children: createCustomScriptSteps(config)
359
+ };
360
+ }
361
+
362
+ //#endregion
363
+ //#region source/management/installation/custom-installation/define.ts
364
+ /**
365
+ * Define a custom installation step with type-safe parameters.
366
+ *
367
+ * This helper provides type safety and IDE autocompletion for custom installation scripts.
368
+ * The handler function receives properly typed `config` and `context` parameters.
369
+ *
370
+ * @param handler - The installation step handler function
371
+ * @returns The same handler function (for use as default export)
372
+ *
373
+ * @example
374
+ * ```typescript
375
+ * import { defineCustomInstallationStep } from "@adobe/aio-commerce-lib-app/management";
376
+ *
377
+ * export default defineCustomInstallationStep(async (config, context) => {
378
+ * const { logger, params } = context;
379
+ *
380
+ * logger.info(`Setting up ${config.metadata.displayName}...`);
381
+ *
382
+ * // Your installation logic here
383
+ * // TypeScript will provide autocompletion for config and context
384
+ *
385
+ * return {
386
+ * status: "success",
387
+ * message: "Setup completed",
388
+ * };
389
+ * });
390
+ * ```
391
+ */
392
+ function defineCustomInstallationStep(handler) {
393
+ return handler;
394
+ }
395
+
396
+ //#endregion
397
+ //#region source/management/installation/events/utils.ts
398
+ const COMMERCE_PROVIDER_TYPE = "dx_commerce_events";
399
+ const EXTERNAL_PROVIDER_TYPE = "3rd_party_custom_events";
400
+ const PROVIDER_TYPE_TO_LABEL = {
401
+ [COMMERCE_PROVIDER_TYPE]: "Commerce",
402
+ [EXTERNAL_PROVIDER_TYPE]: "External"
403
+ };
404
+ /**
405
+ * Generates a unique instance ID for the given event provider within the context of the provided config.
406
+ * @param metadata - The metadata of the application
407
+ * @param provider - The event provider for which to generate the instance ID
408
+ */
409
+ function generateInstanceId(metadata, provider) {
410
+ const slugLabel = provider.label.toLowerCase().replace(/\s+/g, "-");
411
+ return `${metadata.id}-${provider.key ?? slugLabel}`;
412
+ }
413
+ /**
414
+ * Find an existing event provider by its instance ID.
415
+ * @param allProviders - The list of all existing event providers.
416
+ * @param instanceId - The instance ID to search for.
417
+ */
418
+ function findExistingProvider(allProviders, instanceId) {
419
+ return allProviders.find((provider) => provider.instance_id === instanceId) ?? null;
420
+ }
421
+ /**
422
+ * Find existing event metadata by its event name.
423
+ * @param allMetadata - The list of all existing event metadata.
424
+ * @param eventName - The event name to search for.
425
+ */
426
+ function findExistingProviderMetadata(allMetadata, eventName) {
427
+ return allMetadata.find((meta) => meta.event_code === eventName) ?? null;
428
+ }
429
+ /**
430
+ <<<<<<< HEAD
431
+ * Find existing event registrations by client ID and name.
432
+ * @param allRegistrations - The list of all existing event registrations.
433
+ * @param clientId - The client ID of the workspace where the registration was created.
434
+ * @param name - The name of the registration to search for.
435
+ */
436
+ function findExistingRegistrations(allRegistrations, clientId, name) {
437
+ return allRegistrations.find((reg) => reg.client_id === clientId && reg.name === name);
438
+ }
439
+ /**
440
+ * Generates a namespaced event name by combining the application ID with the event name.
441
+ * @param metadata
442
+ * @param name
443
+ */
444
+ function getNamespacedEvent(metadata, name) {
445
+ return `${metadata.id}.${name}`;
446
+ }
447
+ /**
448
+ * Get the fully qualified name of an event for I/O Events based on the provider type.
449
+ * @param name - The name of the event.
450
+ * @param providerType - The type of the event provider.
451
+ */
452
+ function getIoEventCode(name, providerType) {
453
+ return providerType === COMMERCE_PROVIDER_TYPE ? `com.adobe.commerce.${name}` : name;
454
+ }
455
+ /**
456
+ * Generates a registration name and description based on the provider, events, and runtime action.
457
+ * @param provider - The provider this registration is associated to.
458
+ * @param runtimeAction - The runtime action this registration points to.
459
+ */
460
+ function getRegistrationName(provider, runtimeAction) {
461
+ const providerLabel = PROVIDER_TYPE_TO_LABEL[provider.provider_metadata] ?? "Unknown";
462
+ const [packageName, actionName] = runtimeAction.split("/").map(kebabToTitleCase);
463
+ return `${providerLabel} Event Registration: ${actionName} (${packageName})`;
464
+ }
465
+ /**
466
+ * Generates a registration name and description based on the provider, events, and runtime action.
467
+ * @param provider - The provider this registration is associated to.
468
+ * @param events - The events routed by this registration.
469
+ * @param runtimeAction - The runtime action this registration points to.
470
+ */
471
+ function getRegistrationDescription(provider, events, runtimeAction) {
472
+ return [
473
+ "This registration was automatically created by @adobe/aio-commerce-lib-app. ",
474
+ `It belongs to the provider "${provider.label}" (instance ID: ${provider.instance_id}). `,
475
+ `It routes ${events.length} event(s) to the runtime action "${runtimeAction}".`
476
+ ].join("\n");
477
+ }
478
+ /**
479
+ * Converts a kebab-case string to Title Case.
480
+ * @param str - The kebab-case string to convert.
481
+ */
482
+ function kebabToTitleCase(str) {
483
+ return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
484
+ }
485
+ /**
486
+ * Groups events by their runtime actions. Since each event can have multiple
487
+ * runtime actions, this function creates a mapping where each unique runtime
488
+ * action points to all events that target it.
489
+ *
490
+ * @param events - The events to group by runtime actions.
491
+ */
492
+ function groupEventsByRuntimeActions(events) {
493
+ const actionEventsMap = /* @__PURE__ */ new Map();
494
+ for (const event of events) for (const runtimeAction of event.runtimeActions) {
495
+ const existingEvents = actionEventsMap.get(runtimeAction) ?? [];
496
+ actionEventsMap.set(runtimeAction, [...existingEvents, event]);
497
+ }
498
+ return actionEventsMap;
499
+ }
500
+ function findExistingSubscription(allSubscriptions, eventName) {
501
+ return allSubscriptions.get(eventName) ?? null;
502
+ }
503
+ /**
504
+ * Creates a partially filled workspace configuration object based on the app credentials and parameters.
505
+ * This configuration is used when creating an event provider in Commerce.
506
+ *
507
+ * @param context - The execution context containing app credentials and parameters.
508
+ */
509
+ function makeWorkspaceConfig(context) {
510
+ const { appData, params } = context;
511
+ const { consumerOrgId, orgName, projectId, projectName, projectTitle, workspaceId, workspaceName, workspaceTitle } = appData;
512
+ const authParams = (0, _adobe_aio_commerce_lib_auth.resolveAuthParams)(params);
513
+ if (authParams.strategy !== "ims") throw new Error("Failed to resolve IMS authentication parameters from the runtime action inputs.");
514
+ const { clientId, clientSecrets, technicalAccountEmail, technicalAccountId, imsOrgId, scopes } = authParams;
515
+ return { project: {
516
+ id: projectId,
517
+ name: projectName,
518
+ title: projectTitle,
519
+ org: {
520
+ id: consumerOrgId,
521
+ name: orgName,
522
+ ims_org_id: imsOrgId
523
+ },
524
+ workspace: {
525
+ id: workspaceId,
526
+ name: workspaceName,
527
+ title: workspaceTitle,
528
+ action_url: `https://${process.env.__OW_NAMESPACE}.adobeioruntime.net`,
529
+ app_url: `https://${process.env.__OW_NAMESPACE}.adobeio-static.net`,
530
+ details: { credentials: [{
531
+ id: "000000",
532
+ name: `aio-${workspaceId}`,
533
+ integration_type: "oauth_server_to_server",
534
+ oauth_server_to_server: {
535
+ client_id: clientId,
536
+ client_secrets: clientSecrets,
537
+ technical_account_email: technicalAccountEmail,
538
+ technical_account_id: technicalAccountId,
539
+ scopes: scopes.map((scope) => scope.trim())
540
+ }
541
+ }] }
542
+ }
543
+ } };
544
+ }
545
+ /**
546
+ * Retrieves the current existing data and returns it in a normalized way.
547
+ * @param context The execution context.
548
+ */
549
+ async function getIoEventsExistingData(context) {
550
+ const { ioEventsClient, appData } = context;
551
+ const appCredentials = {
552
+ consumerOrgId: appData.consumerOrgId,
553
+ projectId: appData.projectId,
554
+ workspaceId: appData.workspaceId
555
+ };
556
+ const { _embedded: { providers: existingProviders } } = await ioEventsClient.getAllEventProviders({
557
+ consumerOrgId: appData.consumerOrgId,
558
+ withEventMetadata: true
559
+ });
560
+ const providersWithMetadata = existingProviders.map((providerHal) => {
561
+ const { _embedded, _links, ...providerData } = providerHal;
562
+ const actualMetadata = (_embedded?.eventmetadata ?? []).map(({ _embedded: _embedded$1, _links: _links$1, ...meta }) => ({
563
+ ...meta,
564
+ sample: _embedded$1?.sample_event ?? null
565
+ }));
566
+ return {
567
+ ...providerData,
568
+ metadata: actualMetadata
569
+ };
570
+ });
571
+ const { _embedded: { registrations: registrationsHal } } = await ioEventsClient.getAllRegistrations(appCredentials);
572
+ return {
573
+ providersWithMetadata,
574
+ registrations: registrationsHal.map(({ _links, ...reg }) => reg)
575
+ };
576
+ }
577
+ /**
578
+ * Retrieves the current existing Commerce eventing data and returns it in a normalized way.
579
+ * @param context - The execution context.
580
+ */
581
+ async function getCommerceEventingExistingData(context) {
582
+ const { commerceEventsClient } = context;
583
+ const existingProviders = await commerceEventsClient.getAllEventProviders();
584
+ const existingSubscriptions = await commerceEventsClient.getAllEventSubscriptions();
585
+ return {
586
+ isDefaultWorkspaceConfigurationEmpty: existingProviders.some((provider) => !("id" in provider) && !provider.workspace_configuration?.trim()),
587
+ providers: existingProviders,
588
+ subscriptions: new Map(existingSubscriptions.map((subscription) => [subscription.name, subscription]))
589
+ };
590
+ }
591
+
592
+ //#endregion
593
+ //#region source/management/installation/events/helpers.ts
594
+ /**
595
+ * Creates an event provider if it does not already exist.
596
+ * @param params - The parameters necessary to create the provider.
597
+ */
598
+ async function createIoEventProvider(params) {
599
+ const { context, provider } = params;
600
+ const { appData, ioEventsClient, logger } = context;
601
+ const appCredentials = {
602
+ consumerOrgId: appData.consumerOrgId,
603
+ projectId: appData.projectId,
604
+ workspaceId: appData.workspaceId
605
+ };
606
+ logger.info(`Creating provider "${provider.label}" with instance ID "${provider.instanceId}"`);
607
+ return ioEventsClient.createEventProvider({
608
+ ...appCredentials,
609
+ label: provider.label,
610
+ providerType: provider.type,
611
+ instanceId: provider.instanceId,
612
+ description: provider.description
613
+ }).then((res) => {
614
+ logger.info(`Provider "${provider.label}" created with ID '${res.id}'`);
615
+ return res;
616
+ }).catch((error) => {
617
+ logger.error(`Failed to create provider "${provider.label}": ${require_error.stringifyError(error)}`);
618
+ throw error;
619
+ });
620
+ }
621
+ /**
622
+ * Creates or retrieves an existing I/O Events provider.
623
+ * @param params - Parameters needed to create or get the provider.
624
+ * @param existingData - Existing I/O Events data.
625
+ */
626
+ async function createOrGetIoEventProvider(params, existingData) {
627
+ const { context, provider } = params;
628
+ const { logger } = context;
629
+ const { instanceId, ...providerData } = provider;
630
+ const existing = findExistingProvider(existingData, instanceId);
631
+ if (existing) {
632
+ logger.info(`Provider "${provider.label}" already exists with ID "${existing.id}", skipping creation.`);
633
+ return existing;
634
+ }
635
+ return createIoEventProvider({
636
+ context,
637
+ provider: {
638
+ ...providerData,
639
+ instanceId
640
+ }
641
+ });
642
+ }
643
+ /**
644
+ * Creates an event metadata for a given provider and event.
645
+ * @param params - The parameters necessary to create the event metadata.
646
+ */
647
+ async function createIoEventProviderEventMetadata(params) {
648
+ const { context, event, provider, type, metadata } = params;
649
+ const { appData, ioEventsClient, logger } = context;
650
+ const appCredentials = {
651
+ consumerOrgId: appData.consumerOrgId,
652
+ projectId: appData.projectId,
653
+ workspaceId: appData.workspaceId
654
+ };
655
+ const eventCode = getIoEventCode(getNamespacedEvent(metadata, event.name), type);
656
+ logger.info(`Creating event metadata (${eventCode}) for provider "${provider.label}" (instance ID: ${provider.instance_id}))`);
657
+ return ioEventsClient.createEventMetadataForProvider({
658
+ ...appCredentials,
659
+ providerId: provider.id,
660
+ label: event.label,
661
+ description: event.description,
662
+ eventCode
663
+ }).then((res) => {
664
+ logger.info(`Event metadata "${event.label}" created for provider "${provider.label}"`);
665
+ return res;
666
+ }).catch((error) => {
667
+ logger.error(`Failed to create event metadata "${event.label}" for provider "${provider.label}": ${require_error.stringifyError(error)}`);
668
+ throw error;
669
+ });
670
+ }
671
+ /**
672
+ * Creates or retrieves existing I/O Events metadata for a given provider and event.
673
+ * @param params - The parameters necessary to create or get the event metadata.
674
+ * @param existingData - Existing I/O Events metadata for the provider.
675
+ */
676
+ async function createOrGetIoProviderEventMetadata(params, existingData) {
677
+ const { context, event, provider, type, metadata } = params;
678
+ const { logger } = context;
679
+ const existing = findExistingProviderMetadata(existingData, getIoEventCode(getNamespacedEvent(metadata, event.name), type));
680
+ if (existing) {
681
+ logger.info(`Event metadata "${event.label}" already exists for provider "${provider.label}" (instance ID: ${provider.instance_id}), skipping creation.`);
682
+ return existing;
683
+ }
684
+ return createIoEventProviderEventMetadata(params);
685
+ }
686
+ /**
687
+ * Creates an event registration bound to the given provider ID for a set of events targeting the given runtime action.
688
+ * @param params - The parameters necessary to create the registration.
689
+ */
690
+ async function createIoEventRegistration(params) {
691
+ const { context, events, provider, runtimeAction, metadata } = params;
692
+ const { appData, ioEventsClient, logger, params: runtimeParams } = context;
693
+ const appCredentials = {
694
+ consumerOrgId: appData.consumerOrgId,
695
+ projectId: appData.projectId,
696
+ workspaceId: appData.workspaceId
697
+ };
698
+ logger.info(`Creating registration(s) to runtime action "${runtimeAction}" for ${events.length} event(s) with provider "${provider.label}" (instance ID: ${provider.instance_id}))`);
699
+ const name = getRegistrationName(provider, runtimeAction);
700
+ const description = getRegistrationDescription(provider, events, runtimeAction);
701
+ const payload = {
702
+ ...appCredentials,
703
+ name,
704
+ clientId: runtimeParams.AIO_COMMERCE_AUTH_IMS_CLIENT_ID,
705
+ description,
706
+ deliveryType: "webhook",
707
+ runtimeAction,
708
+ enabled: true,
709
+ eventsOfInterest: events.map((event) => ({
710
+ providerId: provider.id,
711
+ eventCode: getIoEventCode(getNamespacedEvent(metadata, event.name), provider.provider_metadata)
712
+ }))
713
+ };
714
+ return ioEventsClient.createRegistration(payload).then((res) => {
715
+ logger.info(`Registration "${name}" created for provider "${provider.label}" with ID '${res.id}'`);
716
+ return res;
717
+ }).catch((error) => {
718
+ logger.error(`Failed to create registration "${name}" for provider "${provider.label}": ${require_error.stringifyError(error)}`);
719
+ throw error;
720
+ });
721
+ }
722
+ /**
723
+ * Creates or retrieves an existing I/O Events registration.
724
+ * @param params - Parameters needed to create or get the registration.
725
+ * @param existingData - Existing I/O Events data.
726
+ */
727
+ async function createOrGetIoEventRegistration(params, registrations) {
728
+ const { context, provider, runtimeAction } = params;
729
+ const { logger, params: runtimeParams } = context;
730
+ const name = getRegistrationName(provider, runtimeAction);
731
+ const existing = findExistingRegistrations(registrations, runtimeParams.AIO_COMMERCE_AUTH_IMS_CLIENT_ID, name);
732
+ if (existing) {
733
+ logger.info(`Registration "${name}" already exists for provider "${provider.label}" with ID '${existing.id}', skipping creation.`);
734
+ return existing;
735
+ }
736
+ return createIoEventRegistration(params);
737
+ }
738
+ /**
739
+ * Ensures Commerce Eventing is configured with the given configuration, updating it if it already exists.
740
+ * @param eventsClient
741
+ * @param params
742
+ * @param existingData
743
+ */
744
+ async function configureCommerceEventing(params, existingData) {
745
+ const { context, config } = params;
746
+ const { commerceEventsClient, logger } = context;
747
+ logger.info("Starting configuration of the Commerce Eventing Module");
748
+ let updateParams = {
749
+ ...config,
750
+ enabled: true
751
+ };
752
+ if (existingData.isDefaultWorkspaceConfigurationEmpty) {
753
+ if (!config.workspaceConfiguration) {
754
+ const message = "Workspace configuration is required to enable Commerce Eventing when there is not an existing one.";
755
+ logger.error(message);
756
+ throw new Error(message);
757
+ }
758
+ logger.info("Default provider workspace configuration already present, it will not be overriden");
759
+ const { workspaceConfiguration, ...rest } = updateParams;
760
+ updateParams = rest;
761
+ }
762
+ logger.info("Updating Commerce Eventing configuration with provided workspace configuration.");
763
+ return commerceEventsClient.updateEventingConfiguration(updateParams).then((success) => {
764
+ if (success) {
765
+ logger.info("Commerce Eventing Module configured successfully.");
766
+ return;
767
+ }
768
+ throw new Error("Something went wrong while configuring Commerce Eventing Module. Response was not successful but no error was thrown.");
769
+ }).catch((err) => {
770
+ logger.error(`Failed to configure Commerce Eventing Module: ${require_error.stringifyError(err)}`);
771
+ throw err;
772
+ });
773
+ }
774
+ /**
775
+ * Creates an event provider in Commerce for a given {@link IoEventProvider}.
776
+ * @param params - The parameters necessary to create the Commerce provider.
777
+ */
778
+ async function createCommerceProvider(params) {
779
+ const { context, provider } = params;
780
+ const { commerceEventsClient, logger } = context;
781
+ logger.info(`Creating Commerce provider "${provider.label}" with instance ID "${provider.instance_id}"`);
782
+ return commerceEventsClient.createEventProvider({
783
+ providerId: provider.id,
784
+ instanceId: provider.instance_id,
785
+ label: provider.label,
786
+ description: provider.description,
787
+ associatedWorkspaceConfiguration: provider.workspaceConfiguration
788
+ }).then((res) => {
789
+ logger.info(`Commerce provider "${provider.label}" created with ID '${res.provider_id}'`);
790
+ return res;
791
+ }).catch((err) => {
792
+ logger.error(`Failed to create Commerce provider "${provider.label}": ${require_error.stringifyError(err)}`);
793
+ throw err;
794
+ });
795
+ }
796
+ /**
797
+ * Creates or retrieves an existing Commerce event provider.
798
+ * @param params - Parameters needed to create or get the Commerce provider.
799
+ * @param existingData - Existing Commerce providers.
800
+ */
801
+ async function createOrGetCommerceProvider(params, existingProviders) {
802
+ const { context, provider } = params;
803
+ const { logger } = context;
804
+ const existing = findExistingProvider(existingProviders, provider.instance_id);
805
+ if (existing) {
806
+ logger.info(`Provider "${provider.label}" already exists with ID "${existing.id}", skipping creation.`);
807
+ return existing;
808
+ }
809
+ return createCommerceProvider(params);
810
+ }
811
+ /**
812
+ * Creates an event subscription in Commerce for the given event and provider.
813
+ * @param params - The parameters necessary to create the Commerce event subscription.
814
+ */
815
+ async function createCommerceEventSubscription(params) {
816
+ const { context, metadata, provider, event } = params;
817
+ const { logger, commerceEventsClient } = context;
818
+ const eventName = getNamespacedEvent(metadata, event.config.name);
819
+ logger.info(`Creating event subscription for event "${event.config.name}" to provider "${provider.label}" (instance ID: ${provider.instance_id})`);
820
+ const eventSpec = {
821
+ name: eventName,
822
+ parent: event.config.name,
823
+ fields: event.config.fields,
824
+ providerId: provider.id,
825
+ destination: event.config.destination,
826
+ hipaaAuditRequired: event.config.hipaaAuditRequired,
827
+ prioritary: event.config.prioritary,
828
+ force: event.config.force
829
+ };
830
+ logger.debug(`Event subscription specification for event "${event.config.name}": ${require_logging.inspect(eventSpec)}`);
831
+ return commerceEventsClient.createEventSubscription(eventSpec).then((_res) => {
832
+ logger.info(`Created event subscription for event "${event.config.name}" to provider "${provider.label} (instance ID: ${provider.instance_id})"`);
833
+ return eventSpec;
834
+ }).catch((err) => {
835
+ logger.error(`Failed to create event subscription for event "${event.config.name}" to provider "${provider.label}": ${require_error.stringifyError(err)}`);
836
+ throw err;
837
+ });
838
+ }
839
+ /**
840
+ * Creates or retrieves an existing Commerce event subscription.
841
+ * @param params - Parameters needed to create or get the subscription.
842
+ * @param existingData - Map of existing Commerce subscriptions keyed by event name.
843
+ */
844
+ async function createOrGetCommerceEventSubscription(params, existingData) {
845
+ const { context, metadata, event } = params;
846
+ const { logger } = context;
847
+ const existing = findExistingSubscription(existingData, getNamespacedEvent(metadata, event.config.name));
848
+ if (existing) {
849
+ logger.info(`Subscription for event "${event.config.name}" already exists, skipping creation.`);
850
+ return {
851
+ name: existing.name,
852
+ parent: existing.parent,
853
+ fields: existing.fields,
854
+ providerId: existing.provider_id
855
+ };
856
+ }
857
+ return createCommerceEventSubscription(params);
858
+ }
859
+ /**
860
+ * Onboards a single event source to I/O Events by creating/retrieving the provider and its event metadata.
861
+ * This is the shared logic inside the loop for both commerce and external event installation steps.
862
+ *
863
+ * @param params - Configuration for onboarding a single event source
864
+ * @param existingData - Existing I/O Events data
865
+ */
866
+ async function onboardIoEvents(params, existingData) {
867
+ const { providersWithMetadata, registrations } = existingData;
868
+ const { context, metadata, provider, providerType, events } = params;
869
+ const instanceId = generateInstanceId(metadata, provider);
870
+ const providerData = await createOrGetIoEventProvider({
871
+ context,
872
+ provider: {
873
+ ...provider,
874
+ instanceId,
875
+ type: providerType
876
+ }
877
+ }, providersWithMetadata);
878
+ const metadataPromises = events.map((event) => createOrGetIoProviderEventMetadata({
879
+ metadata,
880
+ context,
881
+ type: providerType,
882
+ provider: providerData,
883
+ event
884
+ }, providersWithMetadata.find((p) => p.id === providerData.id)?.metadata ?? []));
885
+ const actionEventsMap = groupEventsByRuntimeActions(events);
886
+ const registrationPromises = Array.from(actionEventsMap.entries()).map(([runtimeAction, groupedEvents]) => createOrGetIoEventRegistration({
887
+ metadata,
888
+ context,
889
+ events: groupedEvents,
890
+ provider: providerData,
891
+ runtimeAction
892
+ }, registrations));
893
+ const [metadataData, registrationsData] = await Promise.all([Promise.all(metadataPromises), Promise.all(registrationPromises)]);
894
+ return {
895
+ providerData,
896
+ eventsData: events.map((event, index) => {
897
+ const eventRegistrations = event.runtimeActions.map((runtimeAction) => {
898
+ return registrationsData[Array.from(actionEventsMap.keys()).indexOf(runtimeAction)];
899
+ });
900
+ return {
901
+ config: {
902
+ ...event,
903
+ providerType
904
+ },
905
+ data: {
906
+ metadata: metadataData[index],
907
+ registrations: eventRegistrations
908
+ }
909
+ };
910
+ })
911
+ };
912
+ }
913
+ /**
914
+ * Onboards Commerce Eventing by creating event subscriptions and configuring the Eventing Module.
915
+ * @param params - The parameters necessary to onboard Commerce Eventing.
916
+ */
917
+ async function onboardCommerceEventing(params, existingData) {
918
+ const { context, metadata, ioData } = params;
919
+ const { events, provider, workspaceConfiguration } = ioData;
920
+ const instanceId = provider.instance_id;
921
+ const subscriptions = [];
922
+ await configureCommerceEventing({
923
+ context,
924
+ config: { workspaceConfiguration }
925
+ }, existingData);
926
+ const { workspace_configuration: _, ...commerceProviderData } = await createOrGetCommerceProvider({
927
+ context,
928
+ provider: {
929
+ id: provider.id,
930
+ instance_id: instanceId,
931
+ label: provider.label,
932
+ description: provider.description,
933
+ workspaceConfiguration
934
+ }
935
+ }, existingData.providers);
936
+ for (const event of events) subscriptions.push(await createOrGetCommerceEventSubscription({
937
+ context,
938
+ metadata,
939
+ provider,
940
+ event
941
+ }, existingData.subscriptions));
942
+ return {
943
+ commerceProvider: commerceProviderData,
944
+ subscriptions
945
+ };
946
+ }
947
+
948
+ //#endregion
949
+ //#region source/management/installation/events/commerce.ts
950
+ /** Leaf step for installing commerce event sources. */
951
+ const commerceEventsStep = defineLeafStep({
952
+ name: "commerce",
953
+ meta: {
954
+ label: "Configure Commerce Events",
955
+ description: "Sets up I/O Events for Adobe Commerce event sources"
956
+ },
957
+ when: require_error.hasCommerceEvents,
958
+ run: async (config, context) => {
959
+ const { logger } = context;
960
+ logger.debug("Starting installation of Commerce Events with config:", config);
961
+ const stepData = [];
962
+ const workspaceConfiguration = JSON.stringify(makeWorkspaceConfig(context));
963
+ const existingIoEventsData = await getIoEventsExistingData(context);
964
+ const commerceEventingExistingData = await getCommerceEventingExistingData(context);
965
+ for (const { provider, events } of config.eventing.commerce) {
966
+ const { providerData, eventsData } = await onboardIoEvents({
967
+ context,
968
+ metadata: config.metadata,
969
+ provider,
970
+ events,
971
+ providerType: COMMERCE_PROVIDER_TYPE
972
+ }, existingIoEventsData);
973
+ const { commerceProvider, subscriptions } = await onboardCommerceEventing({
974
+ context,
975
+ metadata: config.metadata,
976
+ provider,
977
+ ioData: {
978
+ provider: providerData,
979
+ events: eventsData,
980
+ workspaceConfiguration
981
+ }
982
+ }, commerceEventingExistingData);
983
+ stepData.push({ provider: {
984
+ config: provider,
985
+ data: {
986
+ ioEvents: providerData,
987
+ commerce: commerceProvider,
988
+ events: eventsData.map(({ config: config$1, data }, index) => {
989
+ return {
990
+ config: config$1,
991
+ data: {
992
+ ...data,
993
+ subscription: subscriptions[index]
994
+ }
995
+ };
996
+ })
997
+ }
998
+ } });
999
+ }
1000
+ logger.debug("Completed Commerce Events installation step.");
1001
+ return stepData;
1002
+ }
1003
+ });
1004
+
1005
+ //#endregion
1006
+ //#region source/management/installation/events/context.ts
1007
+ /**
1008
+ * Create a custom Commerce API Client with only the operations we need for optimal package size.
1009
+ * @param params - The runtime action params to resolve the client params from.
1010
+ */
1011
+ function createCommerceEventsApiClient(params) {
1012
+ const commerceClientParams = (0, _adobe_aio_commerce_lib_api.resolveCommerceHttpClientParams)(params, { tryForwardAuthProvider: true });
1013
+ commerceClientParams.fetchOptions ??= {};
1014
+ commerceClientParams.fetchOptions.timeout = 1e3 * 60 * 2;
1015
+ return (0, _adobe_aio_commerce_lib_events_commerce.createCustomCommerceEventsApiClient)(commerceClientParams, {
1016
+ createEventProvider: _adobe_aio_commerce_lib_events_commerce.createEventProvider,
1017
+ getAllEventProviders: _adobe_aio_commerce_lib_events_commerce.getAllEventProviders,
1018
+ createEventSubscription: _adobe_aio_commerce_lib_events_commerce.createEventSubscription,
1019
+ getAllEventSubscriptions: _adobe_aio_commerce_lib_events_commerce.getAllEventSubscriptions,
1020
+ updateEventingConfiguration: _adobe_aio_commerce_lib_events_commerce.updateEventingConfiguration
1021
+ });
1022
+ }
1023
+ /**
1024
+ * Create a custom Adobe I/O Events API Client with only the operations we need for optimal package size.
1025
+ * @param params - The runtime action params to resolve the client params from.
1026
+ */
1027
+ function createIoEventsApiClient(params) {
1028
+ const ioEventsClientParams = (0, _adobe_aio_commerce_lib_api.resolveIoEventsHttpClientParams)(params);
1029
+ ioEventsClientParams.fetchOptions ??= {};
1030
+ ioEventsClientParams.fetchOptions.timeout = 1e3 * 60 * 2;
1031
+ return (0, _adobe_aio_commerce_lib_events_io_events.createCustomAdobeIoEventsApiClient)(ioEventsClientParams, {
1032
+ createEventProvider: _adobe_aio_commerce_lib_events_io_events.createEventProvider,
1033
+ createEventMetadataForProvider: _adobe_aio_commerce_lib_events_io_events.createEventMetadataForProvider,
1034
+ createRegistration: _adobe_aio_commerce_lib_events_io_events.createRegistration,
1035
+ getAllEventProviders: _adobe_aio_commerce_lib_events_io_events.getAllEventProviders,
1036
+ getAllRegistrations: _adobe_aio_commerce_lib_events_io_events.getAllRegistrations
1037
+ });
1038
+ }
1039
+ /** Creates the events step context with lazy-initialized API clients. */
1040
+ function createEventsStepContext(installation) {
1041
+ const { params } = installation;
1042
+ let commerceEventsClient = null;
1043
+ let ioEventsClient = null;
1044
+ return {
1045
+ get commerceEventsClient() {
1046
+ if (commerceEventsClient === null) commerceEventsClient = createCommerceEventsApiClient(params);
1047
+ return commerceEventsClient;
1048
+ },
1049
+ get ioEventsClient() {
1050
+ if (ioEventsClient === null) ioEventsClient = createIoEventsApiClient(params);
1051
+ return ioEventsClient;
1052
+ }
1053
+ };
1054
+ }
1055
+
1056
+ //#endregion
1057
+ //#region source/management/installation/events/external.ts
1058
+ /** Leaf step for installing external event sources. */
1059
+ const externalEventsStep = defineLeafStep({
1060
+ name: "external",
1061
+ meta: {
1062
+ label: "Configure External Events",
1063
+ description: "Sets up I/O Events for external event sources"
1064
+ },
1065
+ when: require_error.hasExternalEvents,
1066
+ run: async (config, context) => {
1067
+ const { logger } = context;
1068
+ logger.debug("Starting installation of External Events with config:", config);
1069
+ const stepData = [];
1070
+ const existingIoEventsData = await getIoEventsExistingData(context);
1071
+ for (const { provider, events } of config.eventing.external) {
1072
+ const { providerData, eventsData } = await onboardIoEvents({
1073
+ context,
1074
+ metadata: config.metadata,
1075
+ provider,
1076
+ events,
1077
+ providerType: EXTERNAL_PROVIDER_TYPE
1078
+ }, existingIoEventsData);
1079
+ stepData.push({ provider: {
1080
+ config: provider,
1081
+ data: {
1082
+ ioEvents: providerData,
1083
+ events: {
1084
+ config: events,
1085
+ data: eventsData
1086
+ }
1087
+ }
1088
+ } });
1089
+ }
1090
+ logger.debug("Completed External Events installation step.");
1091
+ return stepData;
1092
+ }
1093
+ });
1094
+
1095
+ //#endregion
1096
+ //#region source/management/installation/events/branch.ts
1097
+ /** Root eventing step that contains commerce and external event sub-steps. */
1098
+ const eventingStep = defineBranchStep({
1099
+ name: "eventing",
1100
+ meta: {
1101
+ label: "Eventing",
1102
+ description: "Sets up the I/O Events and the Commerce events required by the application"
1103
+ },
1104
+ when: require_error.hasEventing,
1105
+ context: createEventsStepContext,
1106
+ children: [commerceEventsStep, externalEventsStep]
1107
+ });
1108
+
1109
+ //#endregion
1110
+ //#region source/management/installation/webhooks/helpers.ts
1111
+ function createWebhookSubscriptions(context) {
1112
+ const { logger } = context;
1113
+ logger.info("Creating webhooks in Commerce");
1114
+ return { subscriptionsCreated: true };
1115
+ }
1116
+
1117
+ //#endregion
1118
+ //#region source/management/installation/webhooks/utils.ts
1119
+ /** Check if config has webhooks. */
1120
+ function hasWebhooks(config) {
1121
+ "webhooks" in config && Array.isArray(config.webhooks) && config.webhooks.length;
1122
+ return false;
1123
+ }
1124
+
1125
+ //#endregion
1126
+ //#region source/management/installation/webhooks/branch.ts
1127
+ const subscriptionsStep = defineLeafStep({
1128
+ name: "subscriptions",
1129
+ meta: {
1130
+ label: "Create Subscriptions",
1131
+ description: "Creates webhook subscriptions in Adobe Commerce"
1132
+ },
1133
+ run: (config, context) => {
1134
+ const { logger } = context;
1135
+ logger.debug(config);
1136
+ return createWebhookSubscriptions(context);
1137
+ }
1138
+ });
1139
+ /** Branch step for setting up Commerce webhooks. */
1140
+ const webhooksStep = defineBranchStep({
1141
+ name: "webhooks",
1142
+ meta: {
1143
+ label: "Webhooks",
1144
+ description: "Sets up Commerce webhooks"
1145
+ },
1146
+ when: hasWebhooks,
1147
+ children: [subscriptionsStep]
1148
+ });
1149
+
1150
+ //#endregion
1151
+ //#region source/management/installation/root.ts
1152
+ /**
1153
+ * Creates the default child steps built-in in the library with dynamic children based on the config.
1154
+ */
1155
+ function createDefaultChildSteps(config) {
1156
+ return [
1157
+ eventingStep,
1158
+ webhooksStep,
1159
+ createCustomInstallationStep(config)
1160
+ ];
1161
+ }
1162
+ /**
1163
+ * Creates a root installation step with dynamic children based on the config.
1164
+ */
1165
+ function createRootInstallationStep(config) {
1166
+ return defineBranchStep({
1167
+ name: "installation",
1168
+ meta: {
1169
+ label: "Installation",
1170
+ description: "App installation workflow"
1171
+ },
1172
+ children: createDefaultChildSteps(config)
1173
+ });
1174
+ }
1175
+
1176
+ //#endregion
1177
+ //#region source/management/installation/runner.ts
1178
+ /**
1179
+ * Creates an initial installation state from the config and step definitions.
1180
+ * Filters steps based on their `when` conditions and builds a tree structure
1181
+ * with all steps set to "pending".
1182
+ */
1183
+ function createInitialInstallationState(options) {
1184
+ const { config } = options;
1185
+ return createInitialState({
1186
+ rootStep: createRootInstallationStep(config),
1187
+ config
1188
+ });
1189
+ }
1190
+ /**
1191
+ * Runs the full installation workflow. Returns the final state (never throws).
1192
+ */
1193
+ function runInstallation(options) {
1194
+ const { installationContext, config, initialState, hooks } = options;
1195
+ return executeWorkflow({
1196
+ rootStep: createRootInstallationStep(config),
1197
+ installationContext,
1198
+ config,
1199
+ initialState,
1200
+ hooks
1201
+ });
1202
+ }
1203
+
1204
+ //#endregion
1205
+ Object.defineProperty(exports, 'createInitialInstallationState', {
1206
+ enumerable: true,
1207
+ get: function () {
1208
+ return createInitialInstallationState;
1209
+ }
1210
+ });
1211
+ Object.defineProperty(exports, 'defineCustomInstallationStep', {
1212
+ enumerable: true,
1213
+ get: function () {
1214
+ return defineCustomInstallationStep;
1215
+ }
1216
+ });
1217
+ Object.defineProperty(exports, 'isCompletedState', {
1218
+ enumerable: true,
1219
+ get: function () {
1220
+ return isCompletedState;
1221
+ }
1222
+ });
1223
+ Object.defineProperty(exports, 'isFailedState', {
1224
+ enumerable: true,
1225
+ get: function () {
1226
+ return isFailedState;
1227
+ }
1228
+ });
1229
+ Object.defineProperty(exports, 'isInProgressState', {
1230
+ enumerable: true,
1231
+ get: function () {
1232
+ return isInProgressState;
1233
+ }
1234
+ });
1235
+ Object.defineProperty(exports, 'isSucceededState', {
1236
+ enumerable: true,
1237
+ get: function () {
1238
+ return isSucceededState;
1239
+ }
1240
+ });
1241
+ Object.defineProperty(exports, 'runInstallation', {
1242
+ enumerable: true,
1243
+ get: function () {
1244
+ return runInstallation;
1245
+ }
1246
+ });