@adobe-commerce/aio-toolkit 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
+ AdminUiSdk: () => AdminUiSdk,
34
35
  AdobeAuth: () => adobe_auth_default,
35
36
  AdobeCommerceClient: () => adobe_commerce_client_default,
36
37
  BasicAuthConnection: () => basic_auth_connection_default,
@@ -54,6 +55,7 @@ __export(index_exports, {
54
55
  OpenwhiskAction: () => openwhisk_action_default,
55
56
  Parameters: () => parameters_default,
56
57
  ProviderManager: () => provider_default,
58
+ PublishEvent: () => publish_event_default,
57
59
  RegistrationManager: () => registration_default,
58
60
  RestClient: () => rest_client_default,
59
61
  RuntimeAction: () => runtime_action_default,
@@ -484,39 +486,44 @@ var _FileRepository = class _FileRepository {
484
486
  /**
485
487
  * Saves a file record to the repository
486
488
  * @param payload - The data to save
487
- * @returns Promise<boolean> True if save was successful, false otherwise
489
+ * @param id - Optional ID for the file (sanitized to alphanumeric + underscore, takes precedence over payload.id)
490
+ * @returns Promise<string | null> The filename on success, null on failure
488
491
  */
489
- async save(payload = {}) {
492
+ async save(payload = {}, id) {
490
493
  try {
491
494
  const filesLib = await this.getFiles();
492
- let requestFileId = (/* @__PURE__ */ new Date()).getTime();
493
- if ("id" in payload && payload.id !== void 0) {
494
- requestFileId = Number(payload.id);
495
+ let fileId;
496
+ if (id) {
497
+ fileId = this.sanitizeFileId(id);
498
+ } else if ("id" in payload && payload.id !== void 0) {
499
+ fileId = String(payload.id);
500
+ } else {
501
+ fileId = String((/* @__PURE__ */ new Date()).getTime());
495
502
  }
496
- const filepath = `${this.filepath}/${requestFileId}.json`;
503
+ const filepath = `${this.filepath}/${fileId}.json`;
497
504
  const existingFile = await filesLib.list(filepath);
498
505
  if (existingFile.length) {
499
506
  const buffer = await filesLib.read(filepath);
500
507
  const existingData = JSON.parse(buffer.toString());
501
508
  payload = {
502
509
  ...payload,
503
- updated_at: (/* @__PURE__ */ new Date()).toDateString()
510
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
504
511
  };
505
512
  payload = { ...existingData, ...payload };
506
513
  await filesLib.delete(filepath);
507
514
  } else {
508
515
  payload = {
509
516
  ...payload,
510
- id: requestFileId,
511
- created_at: (/* @__PURE__ */ new Date()).toDateString(),
512
- updated_at: (/* @__PURE__ */ new Date()).toDateString()
517
+ id: fileId,
518
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
519
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
513
520
  };
514
521
  }
515
522
  await filesLib.write(filepath, JSON.stringify(payload));
516
- return true;
523
+ return fileId;
517
524
  } catch (error) {
518
525
  console.error("Error saving file:", error);
519
- return false;
526
+ return null;
520
527
  }
521
528
  }
522
529
  /**
@@ -531,6 +538,21 @@ var _FileRepository = class _FileRepository {
531
538
  }
532
539
  return await this.list();
533
540
  }
541
+ /**
542
+ * Sanitizes the file ID to contain only alphanumeric characters and underscores
543
+ * @param id - The ID to sanitize
544
+ * @returns Sanitized ID with invalid characters replaced by underscores
545
+ */
546
+ sanitizeFileId(id) {
547
+ if (!id || typeof id !== "string") {
548
+ return String((/* @__PURE__ */ new Date()).getTime());
549
+ }
550
+ const sanitized = id.replace(/[^a-zA-Z0-9_]/g, "_");
551
+ if (!sanitized || /^_+$/.test(sanitized)) {
552
+ return String((/* @__PURE__ */ new Date()).getTime());
553
+ }
554
+ return sanitized;
555
+ }
534
556
  /**
535
557
  * Initializes and returns the Files library instance
536
558
  * @returns Promise<any> Initialized Files library instance
@@ -546,6 +568,143 @@ __name(_FileRepository, "FileRepository");
546
568
  var FileRepository = _FileRepository;
547
569
  var file_repository_default = FileRepository;
548
570
 
571
+ // src/framework/publish-event/index.ts
572
+ var import_aio_sdk5 = require("@adobe/aio-sdk");
573
+ var import_cloudevents = require("cloudevents");
574
+ var import_uuid = require("uuid");
575
+
576
+ // src/framework/custom-logger/index.ts
577
+ var _CustomLogger = class _CustomLogger {
578
+ /**
579
+ * @param logger - External logger instance (can be null)
580
+ */
581
+ constructor(logger = null) {
582
+ this.logger = logger;
583
+ }
584
+ /**
585
+ * Log debug message if logger is available
586
+ * @param message - Debug message to log
587
+ */
588
+ debug(message) {
589
+ if (this.logger && typeof this.logger.debug === "function") {
590
+ this.logger.debug(message);
591
+ }
592
+ }
593
+ /**
594
+ * Log info message if logger is available
595
+ * @param message - Info message to log
596
+ */
597
+ info(message) {
598
+ if (this.logger && typeof this.logger.info === "function") {
599
+ this.logger.info(message);
600
+ }
601
+ }
602
+ /**
603
+ * Log error message if logger is available
604
+ * @param message - Error message to log
605
+ */
606
+ error(message) {
607
+ if (this.logger && typeof this.logger.error === "function") {
608
+ this.logger.error(message);
609
+ }
610
+ }
611
+ /**
612
+ * Get the underlying logger instance
613
+ * @returns the logger instance or null
614
+ */
615
+ getLogger() {
616
+ return this.logger;
617
+ }
618
+ };
619
+ __name(_CustomLogger, "CustomLogger");
620
+ var CustomLogger = _CustomLogger;
621
+ var custom_logger_default = CustomLogger;
622
+
623
+ // src/framework/publish-event/index.ts
624
+ var _PublishEvent = class _PublishEvent {
625
+ /**
626
+ * Creates a new PublishEvent instance
627
+ *
628
+ * @param imsOrgId - Adobe IMS Organization ID
629
+ * @param apiKey - Adobe API Key (Client ID)
630
+ * @param accessToken - Adobe Access Token
631
+ * @param logger - Optional logger instance
632
+ */
633
+ constructor(imsOrgId, apiKey, accessToken, logger = null) {
634
+ if (!imsOrgId?.trim()) {
635
+ throw new Error("imsOrgId is required and cannot be empty");
636
+ }
637
+ if (!apiKey?.trim()) {
638
+ throw new Error("apiKey is required and cannot be empty");
639
+ }
640
+ if (!accessToken?.trim()) {
641
+ throw new Error("accessToken is required and cannot be empty");
642
+ }
643
+ this.imsOrgId = imsOrgId;
644
+ this.apiKey = apiKey;
645
+ this.accessToken = accessToken;
646
+ this.customLogger = new custom_logger_default(logger);
647
+ this.customLogger.debug("PublishEvent initialized with valid configuration");
648
+ }
649
+ /**
650
+ * Publishes a CloudEvent to Adobe I/O Events
651
+ *
652
+ * @param providerId - The Adobe I/O Events provider ID
653
+ * @param eventCode - The event type identifier (e.g., 'commerce.order.created')
654
+ * @param payload - The event payload data
655
+ * @param subject - Optional subject for the event
656
+ * @returns Promise<PublishEventResult> - The publish result
657
+ *
658
+ * @throws Error when providerId or eventCode is invalid or publishing fails
659
+ */
660
+ async execute(providerId, eventCode, payload, subject) {
661
+ try {
662
+ if (!providerId?.trim()) {
663
+ throw new Error("providerId is required and cannot be empty");
664
+ }
665
+ if (!eventCode?.trim()) {
666
+ throw new Error("eventCode is required and cannot be empty");
667
+ }
668
+ if (payload === null || payload === void 0) {
669
+ throw new Error("payload is required");
670
+ }
671
+ this.customLogger.info(`Publishing event to provider: ${providerId}`);
672
+ const eventId = (0, import_uuid.v4)();
673
+ const cloudEvent = new import_cloudevents.CloudEvent({
674
+ id: eventId,
675
+ source: `urn:uuid:${providerId}`,
676
+ datacontenttype: "application/json",
677
+ type: eventCode,
678
+ data: payload,
679
+ ...subject && { subject }
680
+ });
681
+ this.customLogger.debug(`Constructed CloudEvent with ID: ${eventId}`);
682
+ const eventsClient = await import_aio_sdk5.Events.init(this.imsOrgId, this.apiKey, this.accessToken);
683
+ this.customLogger.debug("Adobe I/O Events client initialized successfully");
684
+ await eventsClient.publishEvent(cloudEvent);
685
+ const publishedAt = (/* @__PURE__ */ new Date()).toISOString();
686
+ this.customLogger.info(`Event published successfully with ID: ${eventId}`);
687
+ return {
688
+ eventId,
689
+ status: "published",
690
+ publishedAt
691
+ };
692
+ } catch (error) {
693
+ this.customLogger.error(`Failed to publish event: ${error.message}`);
694
+ return {
695
+ eventId: (0, import_uuid.v4)(),
696
+ // Generate ID for tracking even failed events
697
+ status: "failed",
698
+ publishedAt: (/* @__PURE__ */ new Date()).toISOString(),
699
+ error: error.message
700
+ };
701
+ }
702
+ }
703
+ };
704
+ __name(_PublishEvent, "PublishEvent");
705
+ var PublishEvent = _PublishEvent;
706
+ var publish_event_default = PublishEvent;
707
+
549
708
  // src/integration/bearer-token/index.ts
550
709
  var _BearerToken = class _BearerToken {
551
710
  /**
@@ -708,13 +867,32 @@ var _RestClient = class _RestClient {
708
867
  headers
709
868
  };
710
869
  if (payload !== null) {
870
+ let body;
871
+ let contentType;
872
+ if (payload instanceof URLSearchParams) {
873
+ body = payload.toString();
874
+ contentType = headers["Content-Type"] || "application/x-www-form-urlencoded";
875
+ } else if (typeof FormData !== "undefined" && payload instanceof FormData) {
876
+ body = payload;
877
+ contentType = headers["Content-Type"];
878
+ } else if (typeof payload === "string") {
879
+ body = payload;
880
+ contentType = headers["Content-Type"] || "text/plain";
881
+ } else if (payload instanceof Buffer || payload instanceof ArrayBuffer || typeof Uint8Array !== "undefined" && payload instanceof Uint8Array) {
882
+ body = payload;
883
+ contentType = headers["Content-Type"] || "application/octet-stream";
884
+ } else {
885
+ body = JSON.stringify(payload);
886
+ contentType = headers["Content-Type"] || "application/json";
887
+ }
888
+ const requestHeaders = { ...headers };
889
+ if (contentType) {
890
+ requestHeaders["Content-Type"] = contentType;
891
+ }
711
892
  options = {
712
893
  ...options,
713
- body: JSON.stringify(payload),
714
- headers: {
715
- ...headers,
716
- "Content-Type": "application/json"
717
- }
894
+ body,
895
+ headers: requestHeaders
718
896
  };
719
897
  }
720
898
  return await (0, import_node_fetch.default)(endpoint, options);
@@ -844,7 +1022,7 @@ var RestClient = _RestClient;
844
1022
  var rest_client_default = RestClient;
845
1023
 
846
1024
  // src/integration/onboard-events/index.ts
847
- var import_aio_sdk5 = require("@adobe/aio-sdk");
1025
+ var import_aio_sdk6 = require("@adobe/aio-sdk");
848
1026
 
849
1027
  // src/io-events/types.ts
850
1028
  var IoEventsGlobals = {
@@ -4159,7 +4337,7 @@ var _OnboardEvents = class _OnboardEvents {
4159
4337
  throw new Error("Access token is required");
4160
4338
  }
4161
4339
  const loggerName = projectName.toLowerCase().replace(/[^a-z0-9\s-_]/g, "").replace(/\s+/g, "-").replace(/_{2,}/g, "_").replace(/-{2,}/g, "-").trim().concat("-onboard-events");
4162
- this.logger = import_aio_sdk5.Core.Logger(loggerName, { level: "debug" });
4340
+ this.logger = import_aio_sdk6.Core.Logger(loggerName, { level: "debug" });
4163
4341
  this.createProviders = new create_providers_default(
4164
4342
  consumerId,
4165
4343
  projectId,
@@ -4355,7 +4533,7 @@ var OnboardEvents = _OnboardEvents;
4355
4533
  var onboard_events_default = OnboardEvents;
4356
4534
 
4357
4535
  // src/integration/infinite-loop-breaker/index.ts
4358
- var import_aio_sdk6 = require("@adobe/aio-sdk");
4536
+ var import_aio_sdk7 = require("@adobe/aio-sdk");
4359
4537
  var import_crypto2 = __toESM(require("crypto"));
4360
4538
  var _InfiniteLoopBreaker = class _InfiniteLoopBreaker {
4361
4539
  // seconds
@@ -4373,7 +4551,7 @@ var _InfiniteLoopBreaker = class _InfiniteLoopBreaker {
4373
4551
  event
4374
4552
  }) {
4375
4553
  const logLevel = process.env.LOG_LEVEL || "info";
4376
- const logger = import_aio_sdk6.Core.Logger("infiniteLoopBreaker", { level: logLevel });
4554
+ const logger = import_aio_sdk7.Core.Logger("infiniteLoopBreaker", { level: logLevel });
4377
4555
  logger.debug(`Checking for potential infinite loop for event: ${event}`);
4378
4556
  if (!eventTypes.includes(event)) {
4379
4557
  logger.debug(`Event type ${event} is not in the infinite loop event types list`);
@@ -4381,7 +4559,7 @@ var _InfiniteLoopBreaker = class _InfiniteLoopBreaker {
4381
4559
  }
4382
4560
  const key = typeof keyFn === "function" ? keyFn() : keyFn;
4383
4561
  const data = typeof fingerprintFn === "function" ? fingerprintFn() : fingerprintFn;
4384
- const state = await import_aio_sdk6.State.init();
4562
+ const state = await import_aio_sdk7.State.init();
4385
4563
  const persistedFingerPrint = await state.get(key);
4386
4564
  if (!persistedFingerPrint) {
4387
4565
  logger.debug(`No persisted fingerprint found for key ${key}`);
@@ -4402,7 +4580,7 @@ var _InfiniteLoopBreaker = class _InfiniteLoopBreaker {
4402
4580
  static async storeFingerPrint(keyFn, fingerprintFn, ttl) {
4403
4581
  const key = typeof keyFn === "function" ? keyFn() : keyFn;
4404
4582
  const data = typeof fingerprintFn === "function" ? fingerprintFn() : fingerprintFn;
4405
- const state = await import_aio_sdk6.State.init();
4583
+ const state = await import_aio_sdk7.State.init();
4406
4584
  await state.put(key, _InfiniteLoopBreaker.fingerPrint(data), {
4407
4585
  ttl: ttl !== void 0 ? ttl : _InfiniteLoopBreaker.DEFAULT_INFINITE_LOOP_BREAKER_TTL
4408
4586
  });
@@ -4495,7 +4673,7 @@ var AdobeAuth = _AdobeAuth;
4495
4673
  var adobe_auth_default = AdobeAuth;
4496
4674
 
4497
4675
  // src/commerce/adobe-commerce-client/index.ts
4498
- var import_aio_sdk7 = require("@adobe/aio-sdk");
4676
+ var import_aio_sdk8 = require("@adobe/aio-sdk");
4499
4677
  var import_got = __toESM(require("got"));
4500
4678
  var _AdobeCommerceClient = class _AdobeCommerceClient {
4501
4679
  /**
@@ -4510,7 +4688,7 @@ var _AdobeCommerceClient = class _AdobeCommerceClient {
4510
4688
  this.baseUrl = baseUrl;
4511
4689
  this.connection = connection;
4512
4690
  if (logger === null) {
4513
- logger = import_aio_sdk7.Core.Logger("adobe-commerce-client", {
4691
+ logger = import_aio_sdk8.Core.Logger("adobe-commerce-client", {
4514
4692
  level: "debug"
4515
4693
  });
4516
4694
  }
@@ -4637,10 +4815,10 @@ var AdobeCommerceClient = _AdobeCommerceClient;
4637
4815
  var adobe_commerce_client_default = AdobeCommerceClient;
4638
4816
 
4639
4817
  // src/commerce/adobe-commerce-client/basic-auth-connection/index.ts
4640
- var import_aio_sdk9 = require("@adobe/aio-sdk");
4818
+ var import_aio_sdk10 = require("@adobe/aio-sdk");
4641
4819
 
4642
4820
  // src/commerce/adobe-commerce-client/basic-auth-connection/generate-basic-auth-token/index.ts
4643
- var import_aio_sdk8 = require("@adobe/aio-sdk");
4821
+ var import_aio_sdk9 = require("@adobe/aio-sdk");
4644
4822
  var _GenerateBasicAuthToken = class _GenerateBasicAuthToken {
4645
4823
  /**
4646
4824
  * @param baseUrl
@@ -4654,7 +4832,7 @@ var _GenerateBasicAuthToken = class _GenerateBasicAuthToken {
4654
4832
  this.password = password;
4655
4833
  this.key = "adobe_commerce_basic_auth_token";
4656
4834
  if (logger === null) {
4657
- logger = import_aio_sdk8.Core.Logger("adobe-commerce-client", {
4835
+ logger = import_aio_sdk9.Core.Logger("adobe-commerce-client", {
4658
4836
  level: "debug"
4659
4837
  });
4660
4838
  }
@@ -4686,7 +4864,7 @@ var _GenerateBasicAuthToken = class _GenerateBasicAuthToken {
4686
4864
  * @return TokenResult | null
4687
4865
  */
4688
4866
  async getCommerceToken() {
4689
- const endpoint = this.createEndpoint("rest/V1/integration/admin/token");
4867
+ const endpoint = this.createTokenEndpoint();
4690
4868
  this.logger.debug(`Endpoint: ${endpoint}`);
4691
4869
  try {
4692
4870
  const restClient = new rest_client_default();
@@ -4732,6 +4910,19 @@ var _GenerateBasicAuthToken = class _GenerateBasicAuthToken {
4732
4910
  return null;
4733
4911
  }
4734
4912
  }
4913
+ /**
4914
+ * Create the Adobe Commerce integration admin token endpoint.
4915
+ * Handles cases where baseUrl may or may not already include /rest.
4916
+ * @return string
4917
+ */
4918
+ createTokenEndpoint() {
4919
+ const normalizedBaseUrl = this.baseUrl.replace(/\/+$/, "");
4920
+ if (normalizedBaseUrl.endsWith("/rest")) {
4921
+ return `${normalizedBaseUrl}/V1/integration/admin/token`;
4922
+ } else {
4923
+ return `${normalizedBaseUrl}/rest/V1/integration/admin/token`;
4924
+ }
4925
+ }
4735
4926
  /**
4736
4927
  * @param endpoint
4737
4928
  * @return string
@@ -4782,7 +4973,7 @@ var _GenerateBasicAuthToken = class _GenerateBasicAuthToken {
4782
4973
  async getState() {
4783
4974
  if (this.state === void 0) {
4784
4975
  try {
4785
- this.state = await import_aio_sdk8.State.init();
4976
+ this.state = await import_aio_sdk9.State.init();
4786
4977
  } catch (error) {
4787
4978
  this.logger.debug("State API initialization failed, running without caching");
4788
4979
  this.state = null;
@@ -4808,7 +4999,7 @@ var _BasicAuthConnection = class _BasicAuthConnection {
4808
4999
  this.username = username;
4809
5000
  this.password = password;
4810
5001
  if (logger === null) {
4811
- logger = import_aio_sdk9.Core.Logger("adobe-commerce-client", {
5002
+ logger = import_aio_sdk10.Core.Logger("adobe-commerce-client", {
4812
5003
  level: "debug"
4813
5004
  });
4814
5005
  }
@@ -4838,7 +5029,7 @@ var BasicAuthConnection = _BasicAuthConnection;
4838
5029
  var basic_auth_connection_default = BasicAuthConnection;
4839
5030
 
4840
5031
  // src/commerce/adobe-commerce-client/oauth1a-connection/index.ts
4841
- var import_aio_sdk10 = require("@adobe/aio-sdk");
5032
+ var import_aio_sdk11 = require("@adobe/aio-sdk");
4842
5033
  var import_oauth_1 = __toESM(require("oauth-1.0a"));
4843
5034
  var crypto2 = __toESM(require("crypto"));
4844
5035
  var _Oauth1aConnection = class _Oauth1aConnection {
@@ -4855,7 +5046,7 @@ var _Oauth1aConnection = class _Oauth1aConnection {
4855
5046
  this.accessToken = accessToken;
4856
5047
  this.accessTokenSecret = accessTokenSecret;
4857
5048
  if (logger === null) {
4858
- logger = import_aio_sdk10.Core.Logger("adobe-commerce-client", {
5049
+ logger = import_aio_sdk11.Core.Logger("adobe-commerce-client", {
4859
5050
  level: "debug"
4860
5051
  });
4861
5052
  }
@@ -4902,8 +5093,161 @@ __name(_Oauth1aConnection, "Oauth1aConnection");
4902
5093
  var Oauth1aConnection = _Oauth1aConnection;
4903
5094
  var oauth1a_connection_default = Oauth1aConnection;
4904
5095
 
5096
+ // src/commerce/adobe-commerce-client/ims-connection/generate-ims-token/index.ts
5097
+ var import_aio_sdk12 = require("@adobe/aio-sdk");
5098
+ var _GenerateImsToken = class _GenerateImsToken {
5099
+ /**
5100
+ * @param clientId
5101
+ * @param clientSecret
5102
+ * @param technicalAccountId
5103
+ * @param technicalAccountEmail
5104
+ * @param imsOrgId
5105
+ * @param scopes
5106
+ * @param logger
5107
+ */
5108
+ constructor(clientId, clientSecret, technicalAccountId, technicalAccountEmail, imsOrgId, scopes, logger = null) {
5109
+ this.key = "adobe_ims_auth_token";
5110
+ this.tokenContext = "adobe-commerce-client";
5111
+ this.clientId = clientId;
5112
+ this.clientSecret = clientSecret;
5113
+ this.technicalAccountId = technicalAccountId;
5114
+ this.technicalAccountEmail = technicalAccountEmail;
5115
+ this.imsOrgId = imsOrgId;
5116
+ this.scopes = scopes;
5117
+ this.customLogger = new custom_logger_default(logger);
5118
+ }
5119
+ /**
5120
+ * @return string | null
5121
+ */
5122
+ async execute() {
5123
+ try {
5124
+ this.customLogger.info("Starting IMS token generation/retrieval process");
5125
+ const currentValue = await this.getValue();
5126
+ if (currentValue !== null) {
5127
+ this.customLogger.info("Found cached IMS token, returning cached value");
5128
+ return currentValue;
5129
+ }
5130
+ this.customLogger.info("No cached token found, generating new IMS token");
5131
+ let result = {
5132
+ token: null,
5133
+ expire_in: 86399
5134
+ // Default fallback, will be overridden by actual token expiry
5135
+ };
5136
+ const response = await this.getImsToken();
5137
+ if (response !== null) {
5138
+ result = response;
5139
+ }
5140
+ if (result.token !== null) {
5141
+ this.customLogger.info(`Generated new IMS token, caching for ${result.expire_in} seconds`);
5142
+ await this.setValue(result);
5143
+ }
5144
+ return result.token;
5145
+ } catch (error) {
5146
+ this.customLogger.error(`Failed to execute IMS token generation: ${error.message}`);
5147
+ return null;
5148
+ }
5149
+ }
5150
+ /**
5151
+ * @return ImsTokenResult | null
5152
+ */
5153
+ async getImsToken() {
5154
+ try {
5155
+ this.customLogger.debug(`Calling AdobeAuth.getToken with context: ${this.tokenContext}`);
5156
+ const token = await adobe_auth_default.getToken(
5157
+ this.clientId,
5158
+ this.clientSecret,
5159
+ this.technicalAccountId,
5160
+ this.technicalAccountEmail,
5161
+ this.imsOrgId,
5162
+ this.scopes,
5163
+ this.tokenContext
5164
+ );
5165
+ if (token !== null && token !== void 0) {
5166
+ this.customLogger.debug("Received token from AdobeAuth, parsing with BearerToken.info");
5167
+ const tokenInfo = bearer_token_default.info(token);
5168
+ if (!tokenInfo.isValid) {
5169
+ this.customLogger.error("Received invalid or expired token from IMS");
5170
+ return null;
5171
+ }
5172
+ const expireInSeconds = tokenInfo.timeUntilExpiry ? Math.floor(tokenInfo.timeUntilExpiry / 1e3) : 86399;
5173
+ this.customLogger.debug(`Token expires in ${expireInSeconds} seconds`);
5174
+ return {
5175
+ token,
5176
+ expire_in: expireInSeconds
5177
+ };
5178
+ }
5179
+ this.customLogger.error("Received null or undefined token from IMS");
5180
+ return null;
5181
+ } catch (error) {
5182
+ this.customLogger.error(`Failed to get IMS token: ${error.message}`);
5183
+ return null;
5184
+ }
5185
+ }
5186
+ /**
5187
+ * @param result
5188
+ * @return boolean
5189
+ */
5190
+ async setValue(result) {
5191
+ try {
5192
+ const state = await this.getState();
5193
+ if (state === null) {
5194
+ this.customLogger.info("State API not available, skipping token caching");
5195
+ return true;
5196
+ }
5197
+ const ttlWithBuffer = Math.max(result.expire_in - 300, 60);
5198
+ this.customLogger.debug(
5199
+ `Caching IMS token with TTL: ${ttlWithBuffer} seconds (original: ${result.expire_in})`
5200
+ );
5201
+ await state.put(this.key, result.token, { ttl: ttlWithBuffer });
5202
+ return true;
5203
+ } catch (error) {
5204
+ this.customLogger.error(`Failed to cache IMS token: ${error.message}`);
5205
+ return true;
5206
+ }
5207
+ }
5208
+ /**
5209
+ * @return string | null
5210
+ */
5211
+ async getValue() {
5212
+ try {
5213
+ this.customLogger.debug("Checking for cached IMS token");
5214
+ const state = await this.getState();
5215
+ if (state === null) {
5216
+ this.customLogger.debug("State API not available, cannot retrieve cached token");
5217
+ return null;
5218
+ }
5219
+ const value = await state.get(this.key);
5220
+ if (value !== void 0 && value.value) {
5221
+ this.customLogger.debug("Found cached IMS token");
5222
+ return value.value;
5223
+ }
5224
+ this.customLogger.debug("No cached IMS token found");
5225
+ } catch (error) {
5226
+ this.customLogger.error(`Failed to retrieve cached IMS token: ${error.message}`);
5227
+ }
5228
+ return null;
5229
+ }
5230
+ /**
5231
+ * @return any
5232
+ */
5233
+ async getState() {
5234
+ if (this.state === void 0) {
5235
+ try {
5236
+ this.customLogger.debug("Initializing State API for token caching");
5237
+ this.state = await import_aio_sdk12.State.init();
5238
+ } catch (error) {
5239
+ this.customLogger.error(`Failed to initialize State API: ${error.message}`);
5240
+ this.state = null;
5241
+ }
5242
+ }
5243
+ return this.state;
5244
+ }
5245
+ };
5246
+ __name(_GenerateImsToken, "GenerateImsToken");
5247
+ var GenerateImsToken = _GenerateImsToken;
5248
+ var generate_ims_token_default = GenerateImsToken;
5249
+
4905
5250
  // src/commerce/adobe-commerce-client/ims-connection/index.ts
4906
- var import_aio_sdk11 = require("@adobe/aio-sdk");
4907
5251
  var _ImsConnection = class _ImsConnection {
4908
5252
  /**
4909
5253
  * @param clientId
@@ -4913,38 +5257,35 @@ var _ImsConnection = class _ImsConnection {
4913
5257
  * @param imsOrgId
4914
5258
  * @param scopes
4915
5259
  * @param logger
4916
- * @param currentContext
4917
5260
  */
4918
- constructor(clientId, clientSecret, technicalAccountId, technicalAccountEmail, imsOrgId, scopes, logger = null, currentContext = "adobe-commerce-client") {
5261
+ constructor(clientId, clientSecret, technicalAccountId, technicalAccountEmail, imsOrgId, scopes, logger = null) {
4919
5262
  this.clientId = clientId;
4920
5263
  this.clientSecret = clientSecret;
4921
5264
  this.technicalAccountId = technicalAccountId;
4922
5265
  this.technicalAccountEmail = technicalAccountEmail;
4923
5266
  this.imsOrgId = imsOrgId;
4924
5267
  this.scopes = scopes;
4925
- this.currentContext = currentContext;
4926
- if (logger === null) {
4927
- logger = import_aio_sdk11.Core.Logger(currentContext, {
4928
- level: "debug"
4929
- });
4930
- }
4931
- this.logger = logger;
5268
+ this.customLogger = new custom_logger_default(logger);
4932
5269
  }
4933
5270
  /**
4934
5271
  * @param commerceGot
4935
5272
  */
4936
5273
  async extend(commerceGot) {
4937
- this.logger.debug("Using Commerce client with IMS authentication");
4938
- const token = await adobe_auth_default.getToken(
5274
+ this.customLogger.info("Using Commerce client with IMS authentication");
5275
+ const tokenGenerator = new generate_ims_token_default(
4939
5276
  this.clientId,
4940
5277
  this.clientSecret,
4941
5278
  this.technicalAccountId,
4942
5279
  this.technicalAccountEmail,
4943
5280
  this.imsOrgId,
4944
5281
  this.scopes,
4945
- this.currentContext
5282
+ this.customLogger.getLogger()
4946
5283
  );
4947
- this.logger.debug(`IMS token being extended to header: ${token}`);
5284
+ const token = await tokenGenerator.execute();
5285
+ if (token === null) {
5286
+ throw new Error("Failed to generate or retrieve IMS token");
5287
+ }
5288
+ this.customLogger.info(`IMS token being extended to header: ${token.substring(0, 10)}...`);
4948
5289
  return commerceGot.extend({
4949
5290
  headers: {
4950
5291
  Authorization: `Bearer ${token}`
@@ -4955,8 +5296,169 @@ var _ImsConnection = class _ImsConnection {
4955
5296
  __name(_ImsConnection, "ImsConnection");
4956
5297
  var ImsConnection = _ImsConnection;
4957
5298
  var ims_connection_default = ImsConnection;
5299
+
5300
+ // src/experience/admin-ui-sdk/index.ts
5301
+ var _AdminUiSdk = class _AdminUiSdk {
5302
+ /**
5303
+ * Creates a new AdminUiSdk instance
5304
+ * @param extensionId - Unique identifier for the extension
5305
+ * @throws {Error} If extensionId is empty or invalid
5306
+ */
5307
+ constructor(extensionId) {
5308
+ this.menuItems = [];
5309
+ if (!extensionId?.trim()) {
5310
+ throw new Error("Extension ID is required and cannot be empty");
5311
+ }
5312
+ const trimmedId = extensionId.trim();
5313
+ if (!this.isValidExtensionId(trimmedId)) {
5314
+ throw new Error(
5315
+ "Extension ID must be alphanumeric with underscores only (no spaces, hyphens, or special characters)"
5316
+ );
5317
+ }
5318
+ this.extensionId = trimmedId;
5319
+ }
5320
+ /**
5321
+ * Validates that an extension ID contains only alphanumeric characters and underscores
5322
+ * @param id - The extension ID to validate
5323
+ * @returns true if valid, false otherwise
5324
+ */
5325
+ isValidExtensionId(id) {
5326
+ return /^[a-zA-Z0-9_]+$/.test(id);
5327
+ }
5328
+ /**
5329
+ * Validates that a menu ID is valid (can contain :: separator for namespacing)
5330
+ * @param id - The menu ID to validate
5331
+ * @returns true if valid, false otherwise
5332
+ */
5333
+ isValidMenuId(id) {
5334
+ return /^[a-zA-Z0-9_:]+$/.test(id);
5335
+ }
5336
+ /**
5337
+ * Adds a menu item to the extension
5338
+ * @param id - Full identifier for the menu item (e.g., 'extensionId::menuItem')
5339
+ * @param title - Display title for the menu item
5340
+ * @param sortOrder - Sort order for menu positioning
5341
+ * @param parent - Parent menu identifier (optional, full ID like 'extensionId::parent')
5342
+ * @throws {Error} If parameters are invalid or ID already exists
5343
+ */
5344
+ addMenuItem(id, title, sortOrder, parent) {
5345
+ if (!id?.trim()) {
5346
+ throw new Error("Menu item ID is required and cannot be empty");
5347
+ }
5348
+ if (!this.isValidMenuId(id.trim())) {
5349
+ throw new Error(
5350
+ "Menu item ID must be alphanumeric with underscores and colons only (no spaces, hyphens, or other special characters)"
5351
+ );
5352
+ }
5353
+ if (!title?.trim()) {
5354
+ throw new Error("Menu item title is required and cannot be empty");
5355
+ }
5356
+ if (parent !== void 0 && !parent?.trim()) {
5357
+ throw new Error("Menu item parent cannot be empty if provided");
5358
+ }
5359
+ if (parent !== void 0 && !this.isValidMenuId(parent.trim())) {
5360
+ throw new Error(
5361
+ "Menu item parent must be alphanumeric with underscores and colons only (no spaces, hyphens, or other special characters)"
5362
+ );
5363
+ }
5364
+ if (typeof sortOrder !== "number" || sortOrder < 0) {
5365
+ throw new Error("Menu item sortOrder must be a non-negative number");
5366
+ }
5367
+ const trimmedId = id.trim();
5368
+ if (this.menuItems.some((item) => item.id === trimmedId)) {
5369
+ throw new Error(`Menu item with ID '${trimmedId}' already exists`);
5370
+ }
5371
+ const menuItem = {
5372
+ id: trimmedId,
5373
+ title: title.trim(),
5374
+ sortOrder
5375
+ };
5376
+ if (parent?.trim()) {
5377
+ menuItem.parent = parent.trim();
5378
+ }
5379
+ this.menuItems.push(menuItem);
5380
+ }
5381
+ /**
5382
+ * Adds a menu section to the extension
5383
+ * @param id - Full identifier for the menu section (e.g., 'extensionId::section')
5384
+ * @param title - Display title for the menu section
5385
+ * @param sortOrder - Sort order for section positioning
5386
+ * @param parent - Parent menu identifier (optional, full ID like 'Magento_Backend::system')
5387
+ * @throws {Error} If parameters are invalid or ID already exists
5388
+ */
5389
+ addMenuSection(id, title, sortOrder, parent) {
5390
+ if (!id?.trim()) {
5391
+ throw new Error("Menu section ID is required and cannot be empty");
5392
+ }
5393
+ if (!this.isValidMenuId(id.trim())) {
5394
+ throw new Error(
5395
+ "Menu section ID must be alphanumeric with underscores and colons only (no spaces, hyphens, or other special characters)"
5396
+ );
5397
+ }
5398
+ if (!title?.trim()) {
5399
+ throw new Error("Menu section title is required and cannot be empty");
5400
+ }
5401
+ if (parent !== void 0 && !parent?.trim()) {
5402
+ throw new Error("Menu section parent cannot be empty if provided");
5403
+ }
5404
+ if (parent !== void 0 && !this.isValidMenuId(parent.trim())) {
5405
+ throw new Error(
5406
+ "Menu section parent must be alphanumeric with underscores and colons only (no spaces, hyphens, or other special characters)"
5407
+ );
5408
+ }
5409
+ if (typeof sortOrder !== "number" || sortOrder < 0) {
5410
+ throw new Error("Menu section sortOrder must be a non-negative number");
5411
+ }
5412
+ const trimmedId = id.trim();
5413
+ if (this.menuItems.some((item) => item.id === trimmedId)) {
5414
+ throw new Error(`Menu item with ID '${trimmedId}' already exists`);
5415
+ }
5416
+ const menuSection = {
5417
+ id: trimmedId,
5418
+ title: title.trim(),
5419
+ sortOrder,
5420
+ isSection: true
5421
+ };
5422
+ if (parent?.trim()) {
5423
+ menuSection.parent = parent.trim();
5424
+ }
5425
+ this.menuItems.push(menuSection);
5426
+ }
5427
+ /**
5428
+ * Sets the page title for the extension
5429
+ * @param title - The page title
5430
+ * @throws {Error} If title is empty or invalid
5431
+ */
5432
+ addPage(title) {
5433
+ if (!title?.trim()) {
5434
+ throw new Error("Page title is required and cannot be empty");
5435
+ }
5436
+ this.pageTitle = title.trim();
5437
+ }
5438
+ /**
5439
+ * Gets the complete registration object for the extension
5440
+ * @returns The registration object with optional menu items and page configuration
5441
+ */
5442
+ getRegistration() {
5443
+ const registration = {};
5444
+ if (this.menuItems.length > 0) {
5445
+ registration.menuItems = [...this.menuItems];
5446
+ }
5447
+ if (this.pageTitle) {
5448
+ registration.page = {
5449
+ title: this.pageTitle
5450
+ };
5451
+ }
5452
+ return {
5453
+ registration
5454
+ };
5455
+ }
5456
+ };
5457
+ __name(_AdminUiSdk, "AdminUiSdk");
5458
+ var AdminUiSdk = _AdminUiSdk;
4958
5459
  // Annotate the CommonJS export names for ESM import in node:
4959
5460
  0 && (module.exports = {
5461
+ AdminUiSdk,
4960
5462
  AdobeAuth,
4961
5463
  AdobeCommerceClient,
4962
5464
  BasicAuthConnection,
@@ -4980,6 +5482,7 @@ var ims_connection_default = ImsConnection;
4980
5482
  OpenwhiskAction,
4981
5483
  Parameters,
4982
5484
  ProviderManager,
5485
+ PublishEvent,
4983
5486
  RegistrationManager,
4984
5487
  RestClient,
4985
5488
  RuntimeAction,