@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.
Files changed (62) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/cjs/actions/app-config.cjs +3 -3
  3. package/dist/cjs/actions/app-config.d.cts +1 -1
  4. package/dist/cjs/actions/config.cjs +31 -9
  5. package/dist/cjs/actions/installation.cjs +16 -13
  6. package/dist/cjs/actions/installation.d.cts +2 -2
  7. package/dist/cjs/actions/registration.cjs +41 -0
  8. package/dist/cjs/actions/registration.d.cts +33 -0
  9. package/dist/cjs/actions/scope-tree.cjs +5 -4
  10. package/dist/cjs/admin-ui-sdk-BiSopnKI.d.cts +665 -0
  11. package/dist/cjs/{app-DcQMhW2N.d.cts → app-C6kImBl7.d.cts} +242 -16
  12. package/dist/cjs/chunk-DS2yp5vX.cjs +48 -0
  13. package/dist/cjs/commands/index.cjs +582 -321
  14. package/dist/cjs/commands/templates/admin-ui-sdk/registration.js.template +20 -0
  15. package/dist/cjs/config/index.cjs +4 -3
  16. package/dist/cjs/config/index.d.cts +558 -62
  17. package/dist/cjs/{config-BppBKCFj.cjs → config-ct-qMOGj.cjs} +56 -25
  18. package/dist/cjs/{error-Dn7ool6k.cjs → error-C5LNOZ4f.cjs} +1 -1
  19. package/dist/cjs/{index-BVwQk9bx.d.cts → index-B5WKJ3hJ.d.cts} +20 -174
  20. package/dist/cjs/{logging-4s36JTiN.cjs → logging-BTevALnL.cjs} +2 -2
  21. package/dist/cjs/management/index.cjs +1 -1
  22. package/dist/cjs/management/index.d.cts +3 -2
  23. package/dist/cjs/{management-C6xG5bfl.cjs → management-D1QXg4YU.cjs} +128 -75
  24. package/dist/cjs/{router-KeQRduO3.cjs → router-CFErodHU.cjs} +2 -2
  25. package/dist/cjs/{schemas-nkIxa8sL.cjs → schemas-CukVpc19.cjs} +2 -34
  26. package/dist/cjs/step-CWYnKbga.d.cts +187 -0
  27. package/dist/cjs/{validate-CeUCT_7k.cjs → validate-b_bI4mDb.cjs} +4 -3
  28. package/dist/cjs/{webhooks-CLtDxwMa.cjs → webhooks-DS1BtgED.cjs} +157 -17
  29. package/dist/es/actions/app-config.d.mts +1 -1
  30. package/dist/es/actions/app-config.mjs +1 -1
  31. package/dist/es/actions/config.mjs +28 -7
  32. package/dist/es/actions/installation.d.mts +2 -2
  33. package/dist/es/actions/installation.mjs +12 -10
  34. package/dist/es/actions/registration.d.mts +33 -0
  35. package/dist/es/actions/registration.mjs +39 -0
  36. package/dist/es/actions/scope-tree.mjs +1 -1
  37. package/dist/es/admin-ui-sdk-CCo2SWiL.d.mts +667 -0
  38. package/dist/es/{app-DJr-mN9d.d.mts → app-DcY6dJiQ.d.mts} +242 -16
  39. package/dist/es/commands/index.mjs +575 -316
  40. package/dist/es/commands/templates/admin-ui-sdk/registration.js.template +20 -0
  41. package/dist/es/config/index.d.mts +558 -62
  42. package/dist/es/config/index.mjs +4 -4
  43. package/dist/es/{config-BohwKkQS.mjs → config-DGPFTk6w.mjs} +51 -20
  44. package/dist/es/{index-BENO5T7n.d.mts → index-CCov0odd.d.mts} +20 -174
  45. package/dist/es/management/index.d.mts +3 -2
  46. package/dist/es/management/index.mjs +1 -1
  47. package/dist/es/{management-ByHvVJ12.mjs → management-CCsOfniv.mjs} +124 -71
  48. package/dist/es/step-0eI2x4C9.d.mts +187 -0
  49. package/dist/es/{validate-CqJdGzyZ.mjs → validate-Dn3lLTGj.mjs} +2 -2
  50. package/dist/es/{webhooks-CYo-pqbR.mjs → webhooks-Dhrkkip7.mjs} +155 -16
  51. package/package.json +15 -12
  52. /package/dist/cjs/commands/{generate/actions/templates → templates}/app-management/app-config.js.template +0 -0
  53. /package/dist/cjs/commands/{generate/actions/templates → templates}/app-management/custom-scripts.js.template +0 -0
  54. /package/dist/cjs/commands/{generate/actions/templates → templates}/app-management/installation.js.template +0 -0
  55. /package/dist/cjs/commands/{generate/actions/templates → templates}/business-configuration/config.js.template +0 -0
  56. /package/dist/cjs/commands/{generate/actions/templates → templates}/business-configuration/scope-tree.js.template +0 -0
  57. /package/dist/es/commands/{generate/actions/templates → templates}/app-management/app-config.js.template +0 -0
  58. /package/dist/es/commands/{generate/actions/templates → templates}/app-management/custom-scripts.js.template +0 -0
  59. /package/dist/es/commands/{generate/actions/templates → templates}/app-management/installation.js.template +0 -0
  60. /package/dist/es/commands/{generate/actions/templates → templates}/business-configuration/config.js.template +0 -0
  61. /package/dist/es/commands/{generate/actions/templates → templates}/business-configuration/scope-tree.js.template +0 -0
  62. /package/dist/es/{schemas-CVXHgUhv.mjs → schemas-DOcnD16x.mjs} +0 -0
@@ -12,18 +12,18 @@
12
12
  * governing permissions and limitations under the License.
13
13
  */
14
14
 
15
- const require_schemas = require('./schemas-nkIxa8sL.cjs');
16
- const require_webhooks = require('./webhooks-CLtDxwMa.cjs');
17
- const require_error = require('./error-Dn7ool6k.cjs');
18
- const require_logging = require('./logging-4s36JTiN.cjs');
15
+ const require_chunk = require('./chunk-DS2yp5vX.cjs');
16
+ const require_webhooks = require('./webhooks-DS1BtgED.cjs');
17
+ const require_error = require('./error-C5LNOZ4f.cjs');
18
+ const require_logging = require('./logging-BTevALnL.cjs');
19
+ let _adobe_aio_commerce_lib_api_utils = require("@adobe/aio-commerce-lib-api/utils");
19
20
  let camelcase = require("camelcase");
20
- camelcase = require_schemas.__toESM(camelcase);
21
+ camelcase = require_chunk.__toESM(camelcase, 1);
21
22
  let _adobe_aio_commerce_lib_api = require("@adobe/aio-commerce-lib-api");
22
23
  let _adobe_aio_commerce_lib_auth = require("@adobe/aio-commerce-lib-auth");
23
24
  let _adobe_aio_commerce_lib_events_commerce = require("@adobe/aio-commerce-lib-events/commerce");
24
25
  let _adobe_aio_commerce_lib_events_io_events = require("@adobe/aio-commerce-lib-events/io-events");
25
26
  let _adobe_aio_commerce_lib_webhooks_api = require("@adobe/aio-commerce-lib-webhooks/api");
26
- let ky = require("ky");
27
27
 
28
28
  //#region source/management/installation/workflow/hooks.ts
29
29
  /** Helper to call a hook if it exists. */
@@ -122,11 +122,11 @@ function getAtPath(data, path) {
122
122
  return current;
123
123
  }
124
124
  /** Creates an installation error from an exception. */
125
- function createInstallationError(err, path, key = "STEP_EXECUTION_FAILED") {
125
+ async function createInstallationError(err, path, key = "STEP_EXECUTION_FAILED") {
126
126
  return {
127
127
  path,
128
128
  key,
129
- message: err instanceof Error ? err.message : String(err)
129
+ message: await (0, _adobe_aio_commerce_lib_api_utils.unwrapHttpError)(err)
130
130
  };
131
131
  }
132
132
  /** Creates a succeeded installation state. */
@@ -166,6 +166,28 @@ function createInitialState(options) {
166
166
  };
167
167
  }
168
168
  /**
169
+ * Creates a retry state from a failed state.
170
+ * Preserves succeeded steps and their data so the workflow resumes from
171
+ * the failed step rather than restarting from scratch.
172
+ */
173
+ function createRetryState(failedState) {
174
+ return {
175
+ id: failedState.id,
176
+ startedAt: failedState.startedAt,
177
+ status: "in-progress",
178
+ step: resetFailedSteps(failedState.step),
179
+ data: failedState.data
180
+ };
181
+ }
182
+ /** Recursively resets non-succeeded steps back to "pending". */
183
+ function resetFailedSteps(step) {
184
+ return {
185
+ ...step,
186
+ status: step.status === "succeeded" ? "succeeded" : "pending",
187
+ children: step.children.map(resetFailedSteps)
188
+ };
189
+ }
190
+ /**
169
191
  * Executes a workflow from an initial state. Returns the final state (never throws).
170
192
  */
171
193
  async function executeWorkflow(options) {
@@ -190,7 +212,7 @@ async function executeWorkflowWithMode(options, mode) {
190
212
  id: initialState.id,
191
213
  startedAt: initialState.startedAt,
192
214
  step,
193
- data: null,
215
+ data: initialState.data,
194
216
  error: null,
195
217
  hooks,
196
218
  mode
@@ -207,7 +229,7 @@ async function executeWorkflowWithMode(options, mode) {
207
229
  await callHook(hooks, "onInstallationSuccess", succeeded);
208
230
  return succeeded;
209
231
  } catch (err) {
210
- const error = context.error ?? createInstallationError(err, [], "INSTALLATION_FAILED");
232
+ const error = context.error ?? await createInstallationError(err, [], "INSTALLATION_FAILED");
211
233
  const failed = createFailedState({
212
234
  step: context.step,
213
235
  id: context.id,
@@ -250,6 +272,7 @@ function snapshot(context) {
250
272
  }
251
273
  /** Executes a single step (branch or leaf) recursively. */
252
274
  async function executeStep(step, stepStatus, inherited, context) {
275
+ if (stepStatus.status === "succeeded") return;
253
276
  const { path } = stepStatus;
254
277
  const isLeaf = isLeafStep(step);
255
278
  stepStatus.status = "in-progress";
@@ -271,7 +294,7 @@ async function executeStep(step, stepStatus, inherited, context) {
271
294
  }, snapshot(context));
272
295
  } catch (err) {
273
296
  stepStatus.status = "failed";
274
- context.error ??= createInstallationError(err, path);
297
+ context.error ??= await createInstallationError(err, path);
275
298
  await callHook(context.hooks, "onStepFailure", {
276
299
  path,
277
300
  stepName: step.name,
@@ -569,6 +592,19 @@ function defineCustomInstallationStep(handlerOrDefinition) {
569
592
  return handlerOrDefinition;
570
593
  }
571
594
 
595
+ //#endregion
596
+ //#region source/management/installation/utils/http-error.ts
597
+ /**
598
+ * Unwraps an error via `unwrapHttpError`, prefixes it, logs it at error level,
599
+ * and throws a new `Error` with the enriched message. Returns `Promise<never>`
600
+ * so it composes cleanly inside `.catch()` without widening the surrounding type.
601
+ */
602
+ async function throwHttpError(logger, error, prefix) {
603
+ const message = `${prefix}: ${await (0, _adobe_aio_commerce_lib_api_utils.unwrapHttpError)(error)}`;
604
+ logger.error(message);
605
+ throw new Error(message);
606
+ }
607
+
572
608
  //#endregion
573
609
  //#region source/management/installation/admin-ui-sdk/helpers.ts
574
610
  /**
@@ -585,7 +621,7 @@ async function registerExtension(context) {
585
621
  extensionTitle: appData.projectTitle,
586
622
  extensionUrl: `https://${process.env.__OW_NAMESPACE}.adobeio-static.net/index.html`,
587
623
  extensionWorkspace: appData.workspaceName
588
- } } }).json();
624
+ } } }).json().catch((error) => throwHttpError(logger, error, "Failed to register Admin UI SDK extension"));
589
625
  logger.info(`Admin UI SDK extension registered successfully: ${response.extensionId}`);
590
626
  return response;
591
627
  }
@@ -604,7 +640,8 @@ async function uninstallExtension(context) {
604
640
  await commerceClient.delete(endpoint);
605
641
  logger.info(`Admin UI SDK extension "${extensionName}" unregistered successfully.`);
606
642
  } catch (error) {
607
- logger.warn(`Failed to unregister Admin UI SDK extension "${extensionName}": ${require_error.stringifyError(error)}. Continuing uninstall.`);
643
+ const msg = await (0, _adobe_aio_commerce_lib_api_utils.unwrapHttpError)(error);
644
+ logger.warn(`Failed to unregister Admin UI SDK extension "${extensionName}": ${msg}. Continuing uninstall.`);
608
645
  }
609
646
  }
610
647
 
@@ -926,10 +963,7 @@ async function createIoEventProvider(params) {
926
963
  }).then((res) => {
927
964
  logger.info(`Provider "${provider.label}" created with ID '${res.id}'`);
928
965
  return res;
929
- }).catch((error) => {
930
- logger.error(`Failed to create provider "${provider.label}": ${require_error.stringifyError(error)}`);
931
- throw error;
932
- });
966
+ }).catch((error) => throwHttpError(logger, error, `Failed to create I/O Events provider '${provider.label}'`));
933
967
  }
934
968
  /**
935
969
  * Creates or retrieves an existing I/O Events provider.
@@ -976,10 +1010,7 @@ async function createIoEventProviderEventMetadata(params) {
976
1010
  }).then((res) => {
977
1011
  logger.info(`Event metadata "${event.label}" created for provider "${provider.label}"`);
978
1012
  return res;
979
- }).catch((error) => {
980
- logger.error(`Failed to create event metadata "${event.label}" for provider "${provider.label}": ${require_error.stringifyError(error)}`);
981
- throw error;
982
- });
1013
+ }).catch((error) => throwHttpError(logger, error, `Failed to register I/O Events metadata for '${eventCode}'`));
983
1014
  }
984
1015
  /**
985
1016
  * Creates or retrieves existing I/O Events metadata for a given provider and event.
@@ -1027,10 +1058,7 @@ async function createIoEventRegistration(params) {
1027
1058
  return ioEventsClient.createRegistration(payload).then((res) => {
1028
1059
  logger.info(`Registration "${name}" created for provider "${provider.label}" with ID '${res.id}'`);
1029
1060
  return res;
1030
- }).catch((error) => {
1031
- logger.error(`Failed to create registration "${name}" for provider "${provider.label}": ${require_error.stringifyError(error)}`);
1032
- throw error;
1033
- });
1061
+ }).catch((error) => throwHttpError(logger, error, `Failed to create I/O Events registration '${name}'`));
1034
1062
  }
1035
1063
  /**
1036
1064
  * Creates or retrieves an existing I/O Events registration.
@@ -1069,10 +1097,7 @@ async function configureCommerceEventing(params, existingData) {
1069
1097
  return;
1070
1098
  }
1071
1099
  throw new Error("Something went wrong while configuring Commerce Eventing Module. Response was not successful but no error was thrown.");
1072
- }).catch((err) => {
1073
- logger.error(`Failed to configure Commerce Eventing Module: ${require_error.stringifyError(err)}`);
1074
- throw err;
1075
- });
1100
+ }).catch((err) => throwHttpError(logger, err, "Failed to configure Adobe Commerce eventing"));
1076
1101
  }
1077
1102
  /**
1078
1103
  * Creates an event provider in Commerce for a given {@link IoEventProvider}.
@@ -1088,24 +1113,29 @@ async function createCommerceProvider(params) {
1088
1113
  }).then((res) => {
1089
1114
  logger.info(`Commerce provider "${provider.label}" created with ID '${res.provider_id}'`);
1090
1115
  return res;
1091
- }).catch((err) => {
1092
- logger.error(`Failed to create Commerce provider "${provider.label}": ${require_error.stringifyError(err)}`);
1093
- throw err;
1094
- });
1116
+ }).catch((err) => throwHttpError(logger, err, `Failed to create Adobe Commerce event provider '${provider.label}'`));
1095
1117
  }
1096
1118
  /**
1097
1119
  * Creates or retrieves an existing Commerce event provider.
1120
+ *
1121
+ * Checks by `provider_id` first, since Commerce validates subscriptions against that field.
1122
+ * A previous partial run may have left multiple records sharing the same `instance_id` but
1123
+ * with different `provider_id` values; checking by `provider_id` first avoids re-creating a
1124
+ * provider that is already correctly registered.
1125
+ *
1098
1126
  * @param params - Parameters needed to create or get the Commerce provider.
1099
- * @param existingData - Existing Commerce providers.
1127
+ * @param existingProviders - Existing Commerce providers.
1100
1128
  */
1101
1129
  async function createOrGetCommerceProvider(params, existingProviders) {
1102
1130
  const { context, provider } = params;
1103
1131
  const { logger } = context;
1104
- const existing = findExistingProvider(existingProviders, provider.instance_id);
1105
- if (existing) {
1106
- logger.info(`Provider "${provider.label}" already exists with ID "${existing.id}", skipping creation.`);
1107
- return existing;
1132
+ const existingByProviderId = existingProviders.find((p) => p.provider_id === provider.id);
1133
+ if (existingByProviderId) {
1134
+ logger.info(`Provider "${provider.label}" already exists with provider ID "${provider.id}", skipping creation.`);
1135
+ return existingByProviderId;
1108
1136
  }
1137
+ const existingByInstanceId = findExistingProvider(existingProviders, provider.instance_id);
1138
+ if (existingByInstanceId) logger.warn(`Provider "${provider.label}" exists (instance ID: ${provider.instance_id}) but with a different provider ID ("${existingByInstanceId.provider_id}" → "${provider.id}"). Registering updated provider in Commerce.`);
1109
1139
  return createCommerceProvider(params);
1110
1140
  }
1111
1141
  /**
@@ -1131,10 +1161,7 @@ async function createCommerceEventSubscription(params) {
1131
1161
  return commerceEventsClient.createEventSubscription(eventSpec).then((_res) => {
1132
1162
  logger.info(`Created event subscription for event "${event.config.name}" to provider "${provider.label} (instance ID: ${provider.instance_id})"`);
1133
1163
  return eventSpec;
1134
- }).catch((err) => {
1135
- logger.error(`Failed to create event subscription for event "${event.config.name}" to provider "${provider.label}": ${require_error.stringifyError(err)}`);
1136
- throw err;
1137
- });
1164
+ }).catch((err) => throwHttpError(logger, err, `Failed to create Adobe Commerce event subscription for '${event.config.name}'`));
1138
1165
  }
1139
1166
  /**
1140
1167
  * Creates or retrieves an existing Commerce event subscription.
@@ -1264,7 +1291,8 @@ async function deleteIoEventRegistrations(providerData, provider, events, regist
1264
1291
  });
1265
1292
  logger.info(`Deleted registration "${registration.name}" (ID: ${registration.id}).`);
1266
1293
  } catch (error) {
1267
- logger.warn(`Failed to delete registration "${registration.name}" (ID: ${registration.id}): ${require_error.stringifyError(error)}. Continuing uninstall.`);
1294
+ const msg = await (0, _adobe_aio_commerce_lib_api_utils.unwrapHttpError)(error);
1295
+ logger.warn(`Failed to delete I/O Events registration "${registration.name}" (ID: ${registration.id}): ${msg}. Continuing uninstall.`);
1268
1296
  }
1269
1297
  }
1270
1298
  }
@@ -1295,7 +1323,8 @@ async function deleteIoEventMetadata(providerData, provider, context) {
1295
1323
  });
1296
1324
  logger.info(`Deleted event metadata "${eventMetadata.event_code}" from provider "${providerData.id}".`);
1297
1325
  } catch (error) {
1298
- logger.warn(`Failed to delete event metadata "${eventMetadata.event_code}" from provider "${providerData.id}": ${require_error.stringifyError(error)}. Continuing uninstall.`);
1326
+ const msg = await (0, _adobe_aio_commerce_lib_api_utils.unwrapHttpError)(error);
1327
+ logger.warn(`Failed to delete I/O Events metadata "${eventMetadata.event_code}" from provider "${providerData.id}": ${msg}. Continuing uninstall.`);
1299
1328
  }
1300
1329
  }
1301
1330
  }
@@ -1318,7 +1347,8 @@ async function deleteIoEventProvider(providerData, provider, context) {
1318
1347
  });
1319
1348
  logger.info(`Deleted I/O Events provider "${provider.label}" (ID: ${providerData.id}).`);
1320
1349
  } catch (error) {
1321
- logger.warn(`Failed to delete I/O Events provider "${provider.label}" (ID: ${providerData.id}): ${require_error.stringifyError(error)}. Continuing uninstall.`);
1350
+ const msg = await (0, _adobe_aio_commerce_lib_api_utils.unwrapHttpError)(error);
1351
+ logger.warn(`Failed to delete I/O Events provider "${provider.label}" (ID: ${providerData.id}): ${msg}. Continuing uninstall.`);
1322
1352
  }
1323
1353
  }
1324
1354
  /**
@@ -1366,7 +1396,8 @@ async function deleteCommerceEventSubscriptions(events, metadata, provider, exis
1366
1396
  await commerceEventsClient.deleteEventSubscription({ name: eventName });
1367
1397
  logger.info(`Unsubscribed Commerce event subscription for "${eventName}".`);
1368
1398
  } catch (error) {
1369
- logger.warn(`Failed to unsubscribe Commerce event subscription for "${eventName}": ${require_error.stringifyError(error)}. Continuing uninstall.`);
1399
+ const msg = await (0, _adobe_aio_commerce_lib_api_utils.unwrapHttpError)(error);
1400
+ logger.warn(`Failed to unsubscribe Adobe Commerce event subscription for "${eventName}": ${msg}. Continuing uninstall.`);
1370
1401
  }
1371
1402
  }
1372
1403
  }
@@ -1389,7 +1420,8 @@ async function deleteCommerceEventProvider(metadata, provider, existingProviders
1389
1420
  await commerceEventsClient.deleteEventProvider({ provider_id: commerceProvider.provider_id });
1390
1421
  logger.info(`Deleted Commerce event provider "${provider.label}" (provider_id: ${commerceProvider.provider_id}).`);
1391
1422
  } catch (error) {
1392
- logger.warn(`Failed to delete Commerce event provider "${provider.label}" (provider_id: ${commerceProvider.provider_id}): ${require_error.stringifyError(error)}. Continuing uninstall.`);
1423
+ const msg = await (0, _adobe_aio_commerce_lib_api_utils.unwrapHttpError)(error);
1424
+ logger.warn(`Failed to delete Adobe Commerce event provider "${provider.label}" (provider_id: ${commerceProvider.provider_id}): ${msg}. Continuing uninstall.`);
1393
1425
  }
1394
1426
  }
1395
1427
  /**
@@ -1476,15 +1508,13 @@ async function createCommerceEvents(config, context) {
1476
1508
  data: {
1477
1509
  ioEvents: providerData,
1478
1510
  commerce: commerceProvider,
1479
- events: eventsData.map(({ config, data }, index) => {
1480
- return {
1481
- config,
1482
- data: {
1483
- ...data,
1484
- subscription: subscriptions[index]
1485
- }
1486
- };
1487
- })
1511
+ events: eventsData.map(({ config, data }, index) => ({
1512
+ config,
1513
+ data: {
1514
+ ...data,
1515
+ subscription: subscriptions[index]
1516
+ }
1517
+ }))
1488
1518
  }
1489
1519
  } });
1490
1520
  }
@@ -1804,7 +1834,7 @@ async function deleteWebhookSubscriptions(config, context) {
1804
1834
  logger.info(`Unsubscribed webhook: ${getWebhookName(webhook)}`);
1805
1835
  unsubscribedWebhooks.push(params);
1806
1836
  } catch (error) {
1807
- logger.warn(`Failed to unsubscribe webhook "${getWebhookName(webhook)}": ${require_error.stringifyError(error)}. Continuing uninstall.`);
1837
+ logger.warn(`${require_error.stringifyError(error)}. Continuing uninstall.`);
1808
1838
  }
1809
1839
  }
1810
1840
  logger.info(`Webhook unsubscriptions complete: ${unsubscribedWebhooks.length} unsubscribed.`);
@@ -1824,20 +1854,12 @@ async function createOrGetWebhookSubscription(existingWebhooks, client, resolved
1824
1854
  return subscribed;
1825
1855
  }
1826
1856
  /**
1827
- * Re-throws `err`, enriching the message with the webhook name if the error is an
1828
- * `HTTPError` with a JSON body containing a string `message` field.
1857
+ * Re-throws `err` as a new Error with an enriched message that includes the webhook name
1858
+ * and the unwrapped HTTP response body (if available).
1829
1859
  */
1830
1860
  async function rethrowWithWebhookName(err, webhookName, operation) {
1831
- if (err instanceof ky.HTTPError) {
1832
- let body;
1833
- try {
1834
- body = await err.response.json();
1835
- } catch {
1836
- throw err;
1837
- }
1838
- if (typeof body?.message === "string") throw new Error(`Webhook ${operation} failed for "${webhookName}": ${body.message}`);
1839
- }
1840
- throw err;
1861
+ const msg = await (0, _adobe_aio_commerce_lib_api_utils.unwrapHttpError)(err);
1862
+ throw new Error(`Failed to ${operation} webhook subscription for "${webhookName}": ${msg}`);
1841
1863
  }
1842
1864
  /**
1843
1865
  * Subscribes a single webhook to Commerce, enriching the error with the webhook name
@@ -1848,7 +1870,7 @@ async function createWebhookSubscription(client, resolvedWebhook) {
1848
1870
  await client.subscribeWebhook(resolvedWebhook);
1849
1871
  return resolvedWebhook;
1850
1872
  } catch (err) {
1851
- return await rethrowWithWebhookName(err, getWebhookName(resolvedWebhook), "subscription");
1873
+ return await rethrowWithWebhookName(err, getWebhookName(resolvedWebhook), "create");
1852
1874
  }
1853
1875
  }
1854
1876
  /**
@@ -1859,7 +1881,7 @@ async function deleteWebhookSubscription(client, resolvedWebhook, params) {
1859
1881
  try {
1860
1882
  await client.unsubscribeWebhook(params);
1861
1883
  } catch (err) {
1862
- await rethrowWithWebhookName(err, getWebhookName(resolvedWebhook), "unsubscription");
1884
+ return rethrowWithWebhookName(err, getWebhookName(resolvedWebhook), "delete");
1863
1885
  }
1864
1886
  }
1865
1887
  /**
@@ -2034,16 +2056,47 @@ function createInitialInstallationState(options) {
2034
2056
  }
2035
2057
  /**
2036
2058
  * Runs the full installation workflow. Returns the final state (never throws).
2059
+ *
2060
+ * Retries once on failure. `onInstallationFailure` only fires if both attempts fail;
2061
+ * `isRetry: true` is set on the result when the retry succeeds.
2037
2062
  */
2038
- function runInstallation(options) {
2063
+ async function runInstallation(options) {
2039
2064
  const { installationContext, config, initialState, hooks } = options;
2040
- return executeWorkflow({
2041
- rootStep: createRootInstallationStep(config),
2065
+ const rootStep = createRootInstallationStep(config);
2066
+ const firstResult = await executeWorkflow({
2067
+ rootStep,
2042
2068
  installationContext,
2043
2069
  config,
2044
2070
  initialState,
2045
- hooks
2071
+ hooks: {
2072
+ ...hooks,
2073
+ onInstallationFailure: void 0,
2074
+ onStepFailure: void 0
2075
+ }
2046
2076
  });
2077
+ if (firstResult.status === "succeeded") return firstResult;
2078
+ const { error } = firstResult;
2079
+ installationContext.logger.warn(`Installation attempt 1 failed: step "${error.path.join(".")}", key "${error.key}"${error.message ? `, message "${error.message}"` : ""}. Retrying once.`);
2080
+ return {
2081
+ ...await executeWorkflow({
2082
+ rootStep,
2083
+ installationContext,
2084
+ config,
2085
+ initialState: createRetryState(firstResult),
2086
+ hooks: hooks && {
2087
+ ...hooks,
2088
+ onInstallationSuccess: (state) => hooks.onInstallationSuccess?.({
2089
+ ...state,
2090
+ metadata: { isRetry: true }
2091
+ }),
2092
+ onInstallationFailure: (state) => hooks.onInstallationFailure?.({
2093
+ ...state,
2094
+ metadata: { isRetry: true }
2095
+ })
2096
+ }
2097
+ }),
2098
+ metadata: { isRetry: true }
2099
+ };
2047
2100
  }
2048
2101
  /**
2049
2102
  * Creates an initial uninstallation state from the config and step definitions.
@@ -12,10 +12,10 @@
12
12
  * governing permissions and limitations under the License.
13
13
  */
14
14
 
15
- const require_schemas = require('./schemas-nkIxa8sL.cjs');
15
+ const require_chunk = require('./chunk-DS2yp5vX.cjs');
16
16
  let _adobe_aio_commerce_lib_core_responses = require("@adobe/aio-commerce-lib-core/responses");
17
17
  let _adobe_aio_lib_core_logging = require("@adobe/aio-lib-core-logging");
18
- _adobe_aio_lib_core_logging = require_schemas.__toESM(_adobe_aio_lib_core_logging);
18
+ _adobe_aio_lib_core_logging = require_chunk.__toESM(_adobe_aio_lib_core_logging, 1);
19
19
  let regexparam = require("regexparam");
20
20
 
21
21
  //#region ../../packages-private/common-utils/source/actions/http/middleware/logger.ts
@@ -12,35 +12,9 @@
12
12
  * governing permissions and limitations under the License.
13
13
  */
14
14
 
15
- //#region \0rolldown/runtime.js
16
- var __create = Object.create;
17
- var __defProp = Object.defineProperty;
18
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
19
- var __getOwnPropNames = Object.getOwnPropertyNames;
20
- var __getProtoOf = Object.getPrototypeOf;
21
- var __hasOwnProp = Object.prototype.hasOwnProperty;
22
- var __copyProps = (to, from, except, desc) => {
23
- if (from && typeof from === "object" || typeof from === "function") {
24
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
25
- key = keys[i];
26
- if (!__hasOwnProp.call(to, key) && key !== except) {
27
- __defProp(to, key, {
28
- get: ((k) => from[k]).bind(null, key),
29
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
30
- });
31
- }
32
- }
33
- }
34
- return to;
35
- };
36
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
37
- value: mod,
38
- enumerable: true
39
- }) : target, mod));
40
-
41
- //#endregion
15
+ const require_chunk = require('./chunk-DS2yp5vX.cjs');
42
16
  let valibot = require("valibot");
43
- valibot = __toESM(valibot);
17
+ valibot = require_chunk.__toESM(valibot, 1);
44
18
 
45
19
  //#region ../../packages-private/common-utils/source/valibot/schemas.ts
46
20
  const ALPHANUMERIC_OR_HYPHEN_REGEX = {
@@ -94,12 +68,6 @@ function alphaNumericOrHyphenSchema(name, casing = "any") {
94
68
  }
95
69
 
96
70
  //#endregion
97
- Object.defineProperty(exports, '__toESM', {
98
- enumerable: true,
99
- get: function () {
100
- return __toESM;
101
- }
102
- });
103
71
  Object.defineProperty(exports, 'alphaNumericOrHyphenSchema', {
104
72
  enumerable: true,
105
73
  get: function () {
@@ -0,0 +1,187 @@
1
+ /**
2
+ * @license
3
+ *
4
+ * Copyright 2026 Adobe. All rights reserved.
5
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License. You may obtain a copy
7
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software distributed under
10
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
11
+ * OF ANY KIND, either express or implied. See the License for the specific language
12
+ * governing permissions and limitations under the License.
13
+ */
14
+
15
+ import { n as CommerceAppConfigOutputModel } from "./app-C6kImBl7.cjs";
16
+ import { RuntimeActionParams } from "@adobe/aio-commerce-lib-core/params";
17
+ import * as v from "valibot";
18
+ import AioLogger from "@adobe/aio-lib-core-logging";
19
+
20
+ //#region source/management/installation/schema.d.ts
21
+ /** Schema for validating Adobe I/O app credentials required for installation. */
22
+ declare const AppDataSchema: v.ObjectSchema<{
23
+ readonly consumerOrgId: v.SchemaWithPipe<readonly [v.StringSchema<`Expected a string value for '${string}'`>, v.NonEmptyAction<string, `The value of "${string}" must not be empty`>]>;
24
+ readonly orgName: v.SchemaWithPipe<readonly [v.StringSchema<`Expected a string value for '${string}'`>, v.NonEmptyAction<string, `The value of "${string}" must not be empty`>]>;
25
+ readonly projectId: v.SchemaWithPipe<readonly [v.StringSchema<`Expected a string value for '${string}'`>, v.NonEmptyAction<string, `The value of "${string}" must not be empty`>]>;
26
+ readonly projectName: v.SchemaWithPipe<readonly [v.StringSchema<`Expected a string value for '${string}'`>, v.NonEmptyAction<string, `The value of "${string}" must not be empty`>]>;
27
+ readonly projectTitle: v.SchemaWithPipe<readonly [v.StringSchema<`Expected a string value for '${string}'`>, v.NonEmptyAction<string, `The value of "${string}" must not be empty`>]>;
28
+ readonly workspaceId: v.SchemaWithPipe<readonly [v.StringSchema<`Expected a string value for '${string}'`>, v.NonEmptyAction<string, `The value of "${string}" must not be empty`>]>;
29
+ readonly workspaceName: v.SchemaWithPipe<readonly [v.StringSchema<`Expected a string value for '${string}'`>, v.NonEmptyAction<string, `The value of "${string}" must not be empty`>]>;
30
+ readonly workspaceTitle: v.SchemaWithPipe<readonly [v.StringSchema<`Expected a string value for '${string}'`>, v.NonEmptyAction<string, `The value of "${string}" must not be empty`>]>;
31
+ }, undefined>;
32
+ /** Type for Adobe I/O app credentials. */
33
+ type AppData = v.InferOutput<typeof AppDataSchema>;
34
+ //#endregion
35
+ //#region source/management/installation/workflow/step.d.ts
36
+ /** Severity level of a validation issue. */
37
+ type ValidationIssueSeverity = "error" | "warning" | "info";
38
+ /** A single validation issue reported by a step's validate handler. */
39
+ type ValidationIssue = {
40
+ /** Machine-readable code identifying the issue type. */code: string; /** Human-readable description of the issue. */
41
+ message: string; /** Severity of the issue. Only "error" severity blocks installation. */
42
+ severity: ValidationIssueSeverity; /** Optional additional context about the issue. */
43
+ details?: Record<string, unknown>;
44
+ };
45
+ /** Shared context available to all steps during installation. */
46
+ type InstallationContext = {
47
+ /** The credentials of the app being installed */appData: AppData; /** The raw action parameters from the App Builder runtime action. */
48
+ params: RuntimeActionParams & {
49
+ AIO_COMMERCE_AUTH_IMS_CLIENT_ID: string;
50
+ AIO_COMMERCE_AUTH_IMS_CLIENT_SECRETS: string | string[];
51
+ AIO_COMMERCE_AUTH_IMS_TECHNICAL_ACCOUNT_ID: string;
52
+ AIO_COMMERCE_AUTH_IMS_TECHNICAL_ACCOUNT_EMAIL: string;
53
+ AIO_COMMERCE_AUTH_IMS_ORG_ID: string;
54
+ AIO_COMMERCE_AUTH_IMS_SCOPES: string | string[];
55
+ }; /** Logger instance for installation logging. */
56
+ logger: ReturnType<typeof AioLogger>; /** Custom scripts defined in the configuration (if any). */
57
+ customScripts?: Record<string, unknown>;
58
+ };
59
+ /** Factory function type for creating step-specific context. */
60
+ type StepContextFactory<TStepCtx extends Record<string, unknown> = Record<string, unknown>> = (context: InstallationContext) => TStepCtx | Promise<TStepCtx>;
61
+ /** The execution context passed to leaf step run handlers. */
62
+ type ExecutionContext<TStepCtx extends Record<string, unknown> = Record<string, unknown>> = InstallationContext & TStepCtx;
63
+ /**
64
+ * A narrowed context available to step `validate` handlers.
65
+ * Excludes `customScripts` — those only apply during installation, not pre-flight validation.
66
+ */
67
+ type ValidationContext = Omit<InstallationContext, "customScripts">;
68
+ /** The context passed to step `validate` handlers (base validation context merged with step-level context). */
69
+ type ValidationExecutionContext<TStepCtx extends Record<string, unknown> = Record<string, unknown>> = ValidationContext & TStepCtx;
70
+ /** Metadata info for a step (used for UI display). */
71
+ type StepMetaInfo = {
72
+ label: string;
73
+ description?: string;
74
+ };
75
+ /** Step metadata keyed by execution mode. */
76
+ type StepMeta = {
77
+ install: StepMetaInfo;
78
+ uninstall?: StepMetaInfo;
79
+ };
80
+ /** Defines the base properties of a step. */
81
+ type StepBase<TName extends string = string, TConfig extends CommerceAppConfigOutputModel = CommerceAppConfigOutputModel> = {
82
+ /** The name of this step. */name: TName; /** Metadata associated with the step, keyed by execution mode. */
83
+ meta: StepMeta; /** Whether the step should be taken into consideration. */
84
+ when?: (config: CommerceAppConfigOutputModel) => config is TConfig;
85
+ };
86
+ /** A leaf step that executes work (no children). */
87
+ type LeafStep<TName extends string = string, TConfig extends CommerceAppConfigOutputModel = CommerceAppConfigOutputModel, TStepCtx extends Record<string, unknown> = Record<string, unknown>, TOutput = unknown> = StepBase<TName, TConfig> & {
88
+ type: "leaf"; /** The execution handler for the step. */
89
+ install: (config: TConfig, context: ExecutionContext<TStepCtx>) => TOutput | Promise<TOutput>;
90
+ /**
91
+ * Optional pre-installation validation handler.
92
+ * Called before installation begins to surface issues (errors or warnings).
93
+ * Returning an empty array means the step has no issues.
94
+ */
95
+ validate?: (config: TConfig, context: ValidationExecutionContext<TStepCtx>) => ValidationIssue[] | Promise<ValidationIssue[]>;
96
+ /**
97
+ * Optional uninstall handler for the step.
98
+ * Called during uninstallation to reverse the work done by `install`.
99
+ * If absent, the step is silently skipped during uninstallation.
100
+ */
101
+ uninstall?: (config: TConfig, context: ExecutionContext<TStepCtx>) => void | Promise<void>;
102
+ };
103
+ /** A branch step that contains children (no execution). */
104
+ type BranchStep<TName extends string = string, TConfig extends CommerceAppConfigOutputModel = CommerceAppConfigOutputModel, TStepCtx extends Record<string, unknown> = Record<string, unknown>, TChildren extends AnyStep[] = AnyStep[]> = StepBase<TName, TConfig> & {
105
+ type: "branch"; /** An optional factory function to setup shared context for the children steps. */
106
+ context?: StepContextFactory<TStepCtx>; /** The children steps of this branch. */
107
+ children: TChildren;
108
+ /**
109
+ * Optional pre-installation validation handler for the branch itself.
110
+ * Called before children are validated. Returning an empty array means
111
+ * the branch has no issues at this level.
112
+ */
113
+ validate?: (config: TConfig, context: ValidationExecutionContext<TStepCtx>) => ValidationIssue[] | Promise<ValidationIssue[]>;
114
+ };
115
+ /** A step in the installation tree (discriminated union by `type`). */
116
+ type Step<TName extends string = string, TConfig extends CommerceAppConfigOutputModel = CommerceAppConfigOutputModel, TStepCtx extends Record<string, unknown> = Record<string, unknown>, TOutput = unknown> = LeafStep<TName, TConfig, TStepCtx, TOutput> | BranchStep<TName, TConfig, TStepCtx>;
117
+ /** Loosely-typed step for use in non type-safe contexts. */
118
+ interface AnyStep {
119
+ children?: AnyStep[];
120
+ context?: (context: InstallationContext) => any;
121
+ install?: (config: any, context: any) => unknown | Promise<unknown>;
122
+ meta: StepMeta;
123
+ name: string;
124
+ type: "leaf" | "branch";
125
+ uninstall?: (config: any, context: any) => void | Promise<void>;
126
+ validate?: (config: any, context: any) => ValidationIssue[] | Promise<ValidationIssue[]>;
127
+ when?: (config: CommerceAppConfigOutputModel) => boolean;
128
+ }
129
+ /** Check if a step is a leaf step. */
130
+ declare function isLeafStep(step: AnyStep): step is LeafStep;
131
+ /** Check if a step is a branch step. */
132
+ declare function isBranchStep(step: AnyStep): step is BranchStep;
133
+ /** Options for defining a leaf step. */
134
+ type LeafStepOptions<TName extends string, TConfig extends CommerceAppConfigOutputModel, TStepCtx extends Record<string, unknown> = Record<string, unknown>, TOutput = unknown> = Omit<LeafStep<TName, TConfig, TStepCtx, TOutput>, "type">;
135
+ /** Options for defining a branch step. */
136
+ type BranchStepOptions<TName extends string, TConfig extends CommerceAppConfigOutputModel, TStepCtx extends Record<string, unknown> = Record<string, unknown>, TChildren extends AnyStep[] = AnyStep[]> = Omit<BranchStep<TName, TConfig, TStepCtx, TChildren>, "type">;
137
+ /**
138
+ * Define a leaf step (executable, no children).
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * const createProviders = defineLeafStep({
143
+ * name: "providers",
144
+ * meta: { install: { label: "Create Providers", description: "Creates I/O Events providers" } },
145
+ * install: async ({ config, stepContext }) => {
146
+ * const { eventsClient } = stepContext;
147
+ * return eventsClient.createProvider(config.eventing);
148
+ * },
149
+ * });
150
+ * ```
151
+ */
152
+ declare function defineLeafStep<TName extends string, TConfig extends CommerceAppConfigOutputModel, TStepCtx extends Record<string, unknown> = Record<string, unknown>, TOutput = unknown>(options: LeafStepOptions<TName, TConfig, TStepCtx, TOutput>): {
153
+ type: "leaf";
154
+ name: TName;
155
+ meta: StepMeta;
156
+ when: ((config: CommerceAppConfigOutputModel) => config is TConfig) | undefined;
157
+ install: (config: TConfig, context: ExecutionContext<TStepCtx>) => TOutput | Promise<TOutput>;
158
+ uninstall: ((config: TConfig, context: ExecutionContext<TStepCtx>) => void | Promise<void>) | undefined;
159
+ validate: ((config: TConfig, context: ValidationExecutionContext<TStepCtx>) => ValidationIssue[] | Promise<ValidationIssue[]>) | undefined;
160
+ };
161
+ /**
162
+ * Define a branch step (container with children, no runner).
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * const eventing = defineBranchStep({
167
+ * name: "eventing",
168
+ * meta: { install: { label: "Eventing", description: "Sets up I/O Events" } },
169
+ * when: hasEventing,
170
+ * context: async (ctx) => ({ eventsClient: await createEventsClient(ctx) }),
171
+ * children: [commerceEventsStep, externalEventsStep],
172
+ * });
173
+ * ```
174
+ */
175
+ declare function defineBranchStep<TName extends string, TConfig extends CommerceAppConfigOutputModel, TStepCtx extends Record<string, unknown> = Record<string, unknown>, const TChildren extends AnyStep[] = AnyStep[]>(options: BranchStepOptions<TName, TConfig, TStepCtx, TChildren>): {
176
+ type: "branch";
177
+ name: TName;
178
+ meta: StepMeta;
179
+ when: ((config: CommerceAppConfigOutputModel) => config is TConfig) | undefined;
180
+ context: StepContextFactory<TStepCtx> | undefined;
181
+ children: TChildren;
182
+ validate: ((config: TConfig, context: ValidationExecutionContext<TStepCtx>) => ValidationIssue[] | Promise<ValidationIssue[]>) | undefined;
183
+ };
184
+ /** Infer the output type from a leaf step. */
185
+ type InferStepOutput<TStep> = TStep extends LeafStep<infer _TName, infer _TConfig, infer _TStepCtx, infer TOutput> ? Awaited<TOutput> : never;
186
+ //#endregion
187
+ export { defineBranchStep as _, InferStepOutput as a, isLeafStep as b, LeafStepOptions as c, StepMeta as d, StepMetaInfo as f, ValidationIssueSeverity as g, ValidationIssue as h, ExecutionContext as i, Step as l, ValidationExecutionContext as m, BranchStep as n, InstallationContext as o, ValidationContext as p, BranchStepOptions as r, LeafStep as s, AnyStep as t, StepContextFactory as u, defineLeafStep as v, isBranchStep as y };