@adobe-commerce/aio-toolkit 1.0.2 → 1.0.4

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.mjs CHANGED
@@ -396,15 +396,34 @@ var _FileRepository = class _FileRepository {
396
396
  async list() {
397
397
  const filesLib = await this.getFiles();
398
398
  const results = [];
399
- const existingFiles = await filesLib.list(`${this.filepath}/`);
399
+ const existingFiles = await this.metadata();
400
400
  if (existingFiles.length) {
401
- for (const { name } of existingFiles) {
402
- const buffer = await filesLib.read(`${name}`);
403
- results.push(JSON.parse(buffer.toString()));
401
+ for (const file of existingFiles) {
402
+ const buffer = await filesLib.read(`${file.name}`);
403
+ const data = JSON.parse(buffer.toString());
404
+ results.push({
405
+ ...data,
406
+ createdAt: file.creationTime.toISOString(),
407
+ updatedAt: file.lastModified.toISOString()
408
+ });
404
409
  }
405
410
  }
406
411
  return results;
407
412
  }
413
+ /**
414
+ * Lists file metadata without reading file contents
415
+ * Provides a lightweight alternative to list() for performance-critical operations
416
+ * @param id - Optional ID of a specific file to get metadata for
417
+ * @returns Promise<FileMetadata | FileMetadata[]> Single file metadata if id provided, array of all files otherwise
418
+ */
419
+ async metadata(id) {
420
+ const filesLib = await this.getFiles();
421
+ if (id) {
422
+ const filepath = `${this.filepath}/${id}.json`;
423
+ return await filesLib.getProperties(filepath);
424
+ }
425
+ return await filesLib.list(`${this.filepath}/`);
426
+ }
408
427
  /**
409
428
  * Loads a specific file by ID
410
429
  * @param id - The ID of the file to load
@@ -416,7 +435,13 @@ var _FileRepository = class _FileRepository {
416
435
  const existingFile = await filesLib.list(filepath);
417
436
  if (existingFile.length) {
418
437
  const buffer = await filesLib.read(filepath);
419
- return JSON.parse(buffer.toString());
438
+ const data = JSON.parse(buffer.toString());
439
+ const fileProps = await filesLib.getProperties(filepath);
440
+ return {
441
+ ...data,
442
+ createdAt: fileProps.creationTime.toISOString(),
443
+ updatedAt: fileProps.lastModified.toISOString()
444
+ };
420
445
  }
421
446
  return {};
422
447
  }
@@ -424,9 +449,12 @@ var _FileRepository = class _FileRepository {
424
449
  * Saves a file record to the repository
425
450
  * @param payload - The data to save
426
451
  * @param id - Optional ID for the file (sanitized to alphanumeric + underscore, takes precedence over payload.id)
452
+ * @param overwrite - Optional flag to control file write behavior:
453
+ * - true: Replace file entirely with payload (no merge)
454
+ * - false (default): Merge payload with existing file content
427
455
  * @returns Promise<string | null> The filename on success, null on failure
428
456
  */
429
- async save(payload = {}, id) {
457
+ async save(payload = {}, id, overwrite = false) {
430
458
  try {
431
459
  const filesLib = await this.getFiles();
432
460
  let fileId;
@@ -440,23 +468,26 @@ var _FileRepository = class _FileRepository {
440
468
  const filepath = `${this.filepath}/${fileId}.json`;
441
469
  const existingFile = await filesLib.list(filepath);
442
470
  if (existingFile.length) {
443
- const buffer = await filesLib.read(filepath);
444
- const existingData = JSON.parse(buffer.toString());
445
- payload = {
446
- ...payload,
447
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
448
- };
449
- payload = { ...existingData, ...payload };
471
+ if (overwrite) {
472
+ console.log(`Overwriting existing file: ${filepath}`);
473
+ payload = {
474
+ id: fileId,
475
+ ...payload
476
+ };
477
+ } else {
478
+ const buffer = await filesLib.read(filepath);
479
+ const existingData = JSON.parse(buffer.toString());
480
+ payload = { ...existingData, ...payload };
481
+ }
450
482
  await filesLib.delete(filepath);
451
483
  } else {
452
484
  payload = {
453
- ...payload,
454
485
  id: fileId,
455
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
456
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
486
+ ...payload
457
487
  };
458
488
  }
459
- await filesLib.write(filepath, JSON.stringify(payload));
489
+ const { createdAt, updatedAt, ...payloadWithoutTimestamps } = payload;
490
+ await filesLib.write(filepath, JSON.stringify(payloadWithoutTimestamps));
460
491
  return fileId;
461
492
  } catch (error) {
462
493
  console.error("Error saving file:", error);
@@ -505,6 +536,418 @@ __name(_FileRepository, "FileRepository");
505
536
  var FileRepository = _FileRepository;
506
537
  var file_repository_default = FileRepository;
507
538
 
539
+ // src/framework/publish-event/index.ts
540
+ import { Events } from "@adobe/aio-sdk";
541
+ import { CloudEvent } from "cloudevents";
542
+ import { v4 as uuidv4 } from "uuid";
543
+
544
+ // src/framework/custom-logger/index.ts
545
+ var _CustomLogger = class _CustomLogger {
546
+ /**
547
+ * @param logger - External logger instance (can be null)
548
+ */
549
+ constructor(logger = null) {
550
+ this.logger = logger;
551
+ }
552
+ /**
553
+ * Log debug message if logger is available
554
+ * @param message - Debug message to log
555
+ */
556
+ debug(message) {
557
+ if (this.logger && typeof this.logger.debug === "function") {
558
+ this.logger.debug(message);
559
+ }
560
+ }
561
+ /**
562
+ * Log info message if logger is available
563
+ * @param message - Info message to log
564
+ */
565
+ info(message) {
566
+ if (this.logger && typeof this.logger.info === "function") {
567
+ this.logger.info(message);
568
+ }
569
+ }
570
+ /**
571
+ * Log error message if logger is available
572
+ * @param message - Error message to log
573
+ */
574
+ error(message) {
575
+ if (this.logger && typeof this.logger.error === "function") {
576
+ this.logger.error(message);
577
+ }
578
+ }
579
+ /**
580
+ * Get the underlying logger instance
581
+ * @returns the logger instance or null
582
+ */
583
+ getLogger() {
584
+ return this.logger;
585
+ }
586
+ };
587
+ __name(_CustomLogger, "CustomLogger");
588
+ var CustomLogger = _CustomLogger;
589
+ var custom_logger_default = CustomLogger;
590
+
591
+ // src/framework/publish-event/index.ts
592
+ var _PublishEvent = class _PublishEvent {
593
+ /**
594
+ * Creates a new PublishEvent instance
595
+ *
596
+ * @param imsOrgId - Adobe IMS Organization ID
597
+ * @param apiKey - Adobe API Key (Client ID)
598
+ * @param accessToken - Adobe Access Token
599
+ * @param logger - Optional logger instance
600
+ */
601
+ constructor(imsOrgId, apiKey, accessToken, logger = null) {
602
+ if (!imsOrgId?.trim()) {
603
+ throw new Error("imsOrgId is required and cannot be empty");
604
+ }
605
+ if (!apiKey?.trim()) {
606
+ throw new Error("apiKey is required and cannot be empty");
607
+ }
608
+ if (!accessToken?.trim()) {
609
+ throw new Error("accessToken is required and cannot be empty");
610
+ }
611
+ this.imsOrgId = imsOrgId;
612
+ this.apiKey = apiKey;
613
+ this.accessToken = accessToken;
614
+ this.customLogger = new custom_logger_default(logger);
615
+ this.customLogger.debug("PublishEvent initialized with valid configuration");
616
+ }
617
+ /**
618
+ * Publishes a CloudEvent to Adobe I/O Events
619
+ *
620
+ * @param providerId - The Adobe I/O Events provider ID
621
+ * @param eventCode - The event type identifier (e.g., 'commerce.order.created')
622
+ * @param payload - The event payload data
623
+ * @param subject - Optional subject for the event
624
+ * @returns Promise<PublishEventResult> - The publish result
625
+ *
626
+ * @throws Error when providerId or eventCode is invalid or publishing fails
627
+ */
628
+ async execute(providerId, eventCode, payload, subject) {
629
+ try {
630
+ if (!providerId?.trim()) {
631
+ throw new Error("providerId is required and cannot be empty");
632
+ }
633
+ if (!eventCode?.trim()) {
634
+ throw new Error("eventCode is required and cannot be empty");
635
+ }
636
+ if (payload === null || payload === void 0) {
637
+ throw new Error("payload is required");
638
+ }
639
+ this.customLogger.info(`Publishing event to provider: ${providerId}`);
640
+ const eventId = uuidv4();
641
+ const cloudEvent = new CloudEvent({
642
+ id: eventId,
643
+ source: `urn:uuid:${providerId}`,
644
+ datacontenttype: "application/json",
645
+ type: eventCode,
646
+ data: payload,
647
+ ...subject && { subject }
648
+ });
649
+ this.customLogger.debug(`Constructed CloudEvent with ID: ${eventId}`);
650
+ const eventsClient = await Events.init(this.imsOrgId, this.apiKey, this.accessToken);
651
+ this.customLogger.debug("Adobe I/O Events client initialized successfully");
652
+ await eventsClient.publishEvent(cloudEvent);
653
+ const publishedAt = (/* @__PURE__ */ new Date()).toISOString();
654
+ this.customLogger.info(`Event published successfully with ID: ${eventId}`);
655
+ return {
656
+ eventId,
657
+ status: "published",
658
+ publishedAt
659
+ };
660
+ } catch (error) {
661
+ this.customLogger.error(`Failed to publish event: ${error.message}`);
662
+ return {
663
+ eventId: uuidv4(),
664
+ // Generate ID for tracking even failed events
665
+ status: "failed",
666
+ publishedAt: (/* @__PURE__ */ new Date()).toISOString(),
667
+ error: error.message
668
+ };
669
+ }
670
+ }
671
+ };
672
+ __name(_PublishEvent, "PublishEvent");
673
+ var PublishEvent = _PublishEvent;
674
+ var publish_event_default = PublishEvent;
675
+
676
+ // src/framework/webhook-action/response/types.ts
677
+ var WebhookActionOperation = /* @__PURE__ */ ((WebhookActionOperation2) => {
678
+ WebhookActionOperation2["SUCCESS"] = "success";
679
+ WebhookActionOperation2["EXCEPTION"] = "exception";
680
+ WebhookActionOperation2["ADD"] = "add";
681
+ WebhookActionOperation2["REPLACE"] = "replace";
682
+ WebhookActionOperation2["REMOVE"] = "remove";
683
+ return WebhookActionOperation2;
684
+ })(WebhookActionOperation || {});
685
+
686
+ // src/framework/webhook-action/response/index.ts
687
+ var _WebhookActionResponse = class _WebhookActionResponse {
688
+ /**
689
+ * Creates a success response indicating the webhook was processed successfully.
690
+ *
691
+ * Use this method when the webhook has been processed without errors and
692
+ * no modifications to the payload are needed.
693
+ *
694
+ * @returns A success response object
695
+ *
696
+ * @example
697
+ * ```typescript
698
+ * const handler = WebhookAction.execute('process-order', [], [], async (params) => {
699
+ * // Process the order...
700
+ * await processOrder(params.order);
701
+ *
702
+ * // Return success
703
+ * return {
704
+ * statusCode: 200,
705
+ * body: WebhookActionResponse.success()
706
+ * };
707
+ * });
708
+ * ```
709
+ */
710
+ static success() {
711
+ return {
712
+ op: "success" /* SUCCESS */
713
+ };
714
+ }
715
+ /**
716
+ * Creates an exception response to report an error during webhook processing.
717
+ *
718
+ * Use this method to notify Adobe Commerce that an error occurred while
719
+ * processing the webhook. This helps with debugging and error tracking.
720
+ *
721
+ * @param message - Optional error message describing what went wrong
722
+ * @param exceptionClass - Optional exception class name for categorization (e.g., 'Magento\\Framework\\Exception\\LocalizedException')
723
+ * @returns An exception response object
724
+ *
725
+ * @example
726
+ * ```typescript
727
+ * const handler = WebhookAction.execute('validate-product', [], [], async (params) => {
728
+ * const product = await findProduct(params.sku);
729
+ *
730
+ * if (!product) {
731
+ * return {
732
+ * statusCode: 404,
733
+ * body: WebhookActionResponse.exception(
734
+ * `Product with SKU ${params.sku} not found`,
735
+ * 'Magento\\Framework\\Exception\\NoSuchEntityException'
736
+ * )
737
+ * };
738
+ * }
739
+ *
740
+ * return { statusCode: 200, body: WebhookActionResponse.success() };
741
+ * });
742
+ * ```
743
+ */
744
+ static exception(message, exceptionClass) {
745
+ const response = {
746
+ op: "exception" /* EXCEPTION */
747
+ };
748
+ if (message !== void 0) {
749
+ response.message = message;
750
+ }
751
+ if (exceptionClass !== void 0) {
752
+ response.class = exceptionClass;
753
+ }
754
+ return response;
755
+ }
756
+ /**
757
+ * Creates a response to add new data to the webhook payload.
758
+ *
759
+ * Use this method to inject additional data into the webhook payload that
760
+ * will be processed by Adobe Commerce. The data is added at the specified
761
+ * path using dot notation.
762
+ *
763
+ * @param path - Dot-notation path where the value should be added (e.g., 'order.items', 'customer.addresses')
764
+ * @param value - The value to add at the specified path
765
+ * @param instance - Optional instance identifier for tracking or reference purposes
766
+ * @returns An add response object
767
+ *
768
+ * @example
769
+ * ```typescript
770
+ * const handler = WebhookAction.execute('enrich-order', [], [], async (params) => {
771
+ * // Add loyalty points to the order
772
+ * return {
773
+ * statusCode: 200,
774
+ * body: WebhookActionResponse.add(
775
+ * 'order.loyalty',
776
+ * { points: 150, tier: 'gold' },
777
+ * params.order.id
778
+ * )
779
+ * };
780
+ * });
781
+ * ```
782
+ */
783
+ static add(path, value, instance) {
784
+ const response = {
785
+ op: "add" /* ADD */,
786
+ path,
787
+ value
788
+ };
789
+ if (instance !== void 0) {
790
+ response.instance = instance;
791
+ }
792
+ return response;
793
+ }
794
+ /**
795
+ * Creates a response to replace existing data in the webhook payload.
796
+ *
797
+ * Use this method to modify existing fields in the webhook payload.
798
+ * The existing value at the specified path will be replaced with the new value.
799
+ *
800
+ * @param path - Dot-notation path to the field that should be replaced (e.g., 'product.price', 'order.status')
801
+ * @param value - The new value to replace the existing value
802
+ * @param instance - Optional instance identifier for tracking or reference purposes
803
+ * @returns A replace response object
804
+ *
805
+ * @example
806
+ * ```typescript
807
+ * const handler = WebhookAction.execute('adjust-price', [], [], async (params) => {
808
+ * // Apply dynamic pricing
809
+ * const newPrice = await calculateDiscountedPrice(params.product.price);
810
+ *
811
+ * return {
812
+ * statusCode: 200,
813
+ * body: WebhookActionResponse.replace(
814
+ * 'product.price',
815
+ * newPrice,
816
+ * params.product.id
817
+ * )
818
+ * };
819
+ * });
820
+ * ```
821
+ */
822
+ static replace(path, value, instance) {
823
+ const response = {
824
+ op: "replace" /* REPLACE */,
825
+ path,
826
+ value
827
+ };
828
+ if (instance !== void 0) {
829
+ response.instance = instance;
830
+ }
831
+ return response;
832
+ }
833
+ /**
834
+ * Creates a response to remove data from the webhook payload.
835
+ *
836
+ * Use this method to remove fields from the webhook payload before it's
837
+ * processed by Adobe Commerce. This is useful for filtering sensitive data
838
+ * or removing unnecessary information.
839
+ *
840
+ * @param path - Dot-notation path to the field that should be removed (e.g., 'items.0', 'customer.internal_notes')
841
+ * @returns A remove response object
842
+ *
843
+ * @example
844
+ * ```typescript
845
+ * const handler = WebhookAction.execute('sanitize-customer', [], [], async (params) => {
846
+ * // Remove internal notes before processing
847
+ * return {
848
+ * statusCode: 200,
849
+ * body: WebhookActionResponse.remove('customer.internal_notes')
850
+ * };
851
+ * });
852
+ * ```
853
+ *
854
+ * @example
855
+ * ```typescript
856
+ * // Remove an item from an array
857
+ * return {
858
+ * statusCode: 200,
859
+ * body: WebhookActionResponse.remove('order.items.2')
860
+ * };
861
+ * ```
862
+ */
863
+ static remove(path) {
864
+ return {
865
+ op: "remove" /* REMOVE */,
866
+ path
867
+ };
868
+ }
869
+ };
870
+ __name(_WebhookActionResponse, "WebhookActionResponse");
871
+ var WebhookActionResponse = _WebhookActionResponse;
872
+ var response_default2 = WebhookActionResponse;
873
+
874
+ // src/framework/webhook-action/types.ts
875
+ var SignatureVerification = /* @__PURE__ */ ((SignatureVerification2) => {
876
+ SignatureVerification2["ENABLED"] = "enabled";
877
+ SignatureVerification2["DISABLED"] = "disabled";
878
+ return SignatureVerification2;
879
+ })(SignatureVerification || {});
880
+
881
+ // src/framework/webhook-action/index.ts
882
+ import crypto from "crypto";
883
+ var _WebhookAction = class _WebhookAction {
884
+ /**
885
+ * Execute a webhook action with validation and response handling.
886
+ *
887
+ * @param name - Name of the webhook action
888
+ * @param requiredParams - Required parameters in the webhook payload
889
+ * @param requiredHeaders - Required headers (e.g., signature headers)
890
+ * @param signatureVerification - Enable/disable signature verification
891
+ * @param action - Webhook action function returning WebhookActionResponse
892
+ * @returns Function that handles the webhook HTTP request
893
+ */
894
+ static execute(name = "webhook", requiredParams = [], requiredHeaders = [], signatureVerification = "disabled" /* DISABLED */, action = async () => response_default2.success()) {
895
+ const httpMethods = ["POST" /* POST */];
896
+ const verifySignature = /* @__PURE__ */ __name(async (params) => {
897
+ const signature = params.__ow_headers["x-adobe-commerce-webhook-signature"] || "";
898
+ if (!signature) {
899
+ return "Header `x-adobe-commerce-webhook-signature` not found. Make sure Webhooks signature is enabled in the Commerce instance.";
900
+ }
901
+ const body = params.__ow_body;
902
+ if (!body) {
903
+ return "Request body not found. Make sure the action is configured with `raw-http: true`.";
904
+ }
905
+ let publicKey = params.PUBLIC_KEY;
906
+ if (!publicKey && params.PUBLIC_KEY_BASE64) {
907
+ publicKey = atob(params.PUBLIC_KEY_BASE64);
908
+ }
909
+ if (!publicKey) {
910
+ return "Public key not found. Make sure the action is configured with the input `PUBLIC_KEY` or `PUBLIC_KEY_BASE64` and it is defined in .env file.";
911
+ }
912
+ try {
913
+ const verifier = crypto.createVerify("SHA256");
914
+ verifier.update(body);
915
+ const isSignatureValid = verifier.verify(publicKey, signature, "base64");
916
+ if (!isSignatureValid) {
917
+ return "The signature is invalid.";
918
+ }
919
+ } catch (error) {
920
+ return "The signature is invalid.";
921
+ }
922
+ return null;
923
+ }, "verifySignature");
924
+ const callback = /* @__PURE__ */ __name(async (params, ctx) => {
925
+ if (signatureVerification === "enabled" /* ENABLED */) {
926
+ const verificationErrorMessage = await verifySignature(params);
927
+ if (verificationErrorMessage) {
928
+ const verificationErrorResponse = response_default2.exception(verificationErrorMessage);
929
+ return response_default.success(JSON.stringify(verificationErrorResponse));
930
+ }
931
+ params = {
932
+ ...params,
933
+ ...JSON.parse(atob(params.__ow_body))
934
+ };
935
+ }
936
+ const errorMessage = validator_default.checkMissingRequestInputs(params, requiredParams, requiredHeaders) ?? "";
937
+ if (errorMessage) {
938
+ const errorMessageResponse = response_default2.exception(errorMessage);
939
+ return response_default.success(JSON.stringify(errorMessageResponse));
940
+ }
941
+ const response = await action(params, ctx);
942
+ return response_default.success(JSON.stringify(response));
943
+ }, "callback");
944
+ return runtime_action_default.execute(name, httpMethods, [], [], callback);
945
+ }
946
+ };
947
+ __name(_WebhookAction, "WebhookAction");
948
+ var WebhookAction = _WebhookAction;
949
+ var webhook_action_default = WebhookAction;
950
+
508
951
  // src/integration/bearer-token/index.ts
509
952
  var _BearerToken = class _BearerToken {
510
953
  /**
@@ -4334,7 +4777,7 @@ var onboard_events_default = OnboardEvents;
4334
4777
 
4335
4778
  // src/integration/infinite-loop-breaker/index.ts
4336
4779
  import { Core as Core5, State } from "@adobe/aio-sdk";
4337
- import crypto from "crypto";
4780
+ import crypto2 from "crypto";
4338
4781
  var _InfiniteLoopBreaker = class _InfiniteLoopBreaker {
4339
4782
  // seconds
4340
4783
  /**
@@ -4414,7 +4857,7 @@ var _InfiniteLoopBreaker = class _InfiniteLoopBreaker {
4414
4857
  * @returns The fingerprint
4415
4858
  */
4416
4859
  static fingerPrint(data) {
4417
- const hash = crypto.createHash(_InfiniteLoopBreaker.FINGERPRINT_ALGORITHM);
4860
+ const hash = crypto2.createHash(_InfiniteLoopBreaker.FINGERPRINT_ALGORITHM);
4418
4861
  hash.update(JSON.stringify(data));
4419
4862
  return hash.digest(_InfiniteLoopBreaker.FINGERPRINT_ENCODING);
4420
4863
  }
@@ -4664,7 +5107,7 @@ var _GenerateBasicAuthToken = class _GenerateBasicAuthToken {
4664
5107
  * @return TokenResult | null
4665
5108
  */
4666
5109
  async getCommerceToken() {
4667
- const endpoint = this.createEndpoint("rest/V1/integration/admin/token");
5110
+ const endpoint = this.createTokenEndpoint();
4668
5111
  this.logger.debug(`Endpoint: ${endpoint}`);
4669
5112
  try {
4670
5113
  const restClient = new rest_client_default();
@@ -4710,6 +5153,19 @@ var _GenerateBasicAuthToken = class _GenerateBasicAuthToken {
4710
5153
  return null;
4711
5154
  }
4712
5155
  }
5156
+ /**
5157
+ * Create the Adobe Commerce integration admin token endpoint.
5158
+ * Handles cases where baseUrl may or may not already include /rest.
5159
+ * @return string
5160
+ */
5161
+ createTokenEndpoint() {
5162
+ const normalizedBaseUrl = this.baseUrl.replace(/\/+$/, "");
5163
+ if (normalizedBaseUrl.endsWith("/rest")) {
5164
+ return `${normalizedBaseUrl}/V1/integration/admin/token`;
5165
+ } else {
5166
+ return `${normalizedBaseUrl}/rest/V1/integration/admin/token`;
5167
+ }
5168
+ }
4713
5169
  /**
4714
5170
  * @param endpoint
4715
5171
  * @return string
@@ -4818,7 +5274,7 @@ var basic_auth_connection_default = BasicAuthConnection;
4818
5274
  // src/commerce/adobe-commerce-client/oauth1a-connection/index.ts
4819
5275
  import { Core as Core9 } from "@adobe/aio-sdk";
4820
5276
  import Oauth1a from "oauth-1.0a";
4821
- import * as crypto2 from "crypto";
5277
+ import * as crypto3 from "crypto";
4822
5278
  var _Oauth1aConnection = class _Oauth1aConnection {
4823
5279
  /**
4824
5280
  * @param consumerKey
@@ -4867,7 +5323,7 @@ var _Oauth1aConnection = class _Oauth1aConnection {
4867
5323
  secret: this.consumerSecret
4868
5324
  },
4869
5325
  signature_method: "HMAC-SHA256",
4870
- hash_function: /* @__PURE__ */ __name((baseString, key) => crypto2.createHmac("sha256", key).update(baseString).digest("base64"), "hash_function")
5326
+ hash_function: /* @__PURE__ */ __name((baseString, key) => crypto3.createHmac("sha256", key).update(baseString).digest("base64"), "hash_function")
4871
5327
  });
4872
5328
  const oauthToken = {
4873
5329
  key: this.accessToken,
@@ -4880,8 +5336,161 @@ __name(_Oauth1aConnection, "Oauth1aConnection");
4880
5336
  var Oauth1aConnection = _Oauth1aConnection;
4881
5337
  var oauth1a_connection_default = Oauth1aConnection;
4882
5338
 
5339
+ // src/commerce/adobe-commerce-client/ims-connection/generate-ims-token/index.ts
5340
+ import { State as State3 } from "@adobe/aio-sdk";
5341
+ var _GenerateImsToken = class _GenerateImsToken {
5342
+ /**
5343
+ * @param clientId
5344
+ * @param clientSecret
5345
+ * @param technicalAccountId
5346
+ * @param technicalAccountEmail
5347
+ * @param imsOrgId
5348
+ * @param scopes
5349
+ * @param logger
5350
+ */
5351
+ constructor(clientId, clientSecret, technicalAccountId, technicalAccountEmail, imsOrgId, scopes, logger = null) {
5352
+ this.key = "adobe_ims_auth_token";
5353
+ this.tokenContext = "adobe-commerce-client";
5354
+ this.clientId = clientId;
5355
+ this.clientSecret = clientSecret;
5356
+ this.technicalAccountId = technicalAccountId;
5357
+ this.technicalAccountEmail = technicalAccountEmail;
5358
+ this.imsOrgId = imsOrgId;
5359
+ this.scopes = scopes;
5360
+ this.customLogger = new custom_logger_default(logger);
5361
+ }
5362
+ /**
5363
+ * @return string | null
5364
+ */
5365
+ async execute() {
5366
+ try {
5367
+ this.customLogger.info("Starting IMS token generation/retrieval process");
5368
+ const currentValue = await this.getValue();
5369
+ if (currentValue !== null) {
5370
+ this.customLogger.info("Found cached IMS token, returning cached value");
5371
+ return currentValue;
5372
+ }
5373
+ this.customLogger.info("No cached token found, generating new IMS token");
5374
+ let result = {
5375
+ token: null,
5376
+ expire_in: 86399
5377
+ // Default fallback, will be overridden by actual token expiry
5378
+ };
5379
+ const response = await this.getImsToken();
5380
+ if (response !== null) {
5381
+ result = response;
5382
+ }
5383
+ if (result.token !== null) {
5384
+ this.customLogger.info(`Generated new IMS token, caching for ${result.expire_in} seconds`);
5385
+ await this.setValue(result);
5386
+ }
5387
+ return result.token;
5388
+ } catch (error) {
5389
+ this.customLogger.error(`Failed to execute IMS token generation: ${error.message}`);
5390
+ return null;
5391
+ }
5392
+ }
5393
+ /**
5394
+ * @return ImsTokenResult | null
5395
+ */
5396
+ async getImsToken() {
5397
+ try {
5398
+ this.customLogger.debug(`Calling AdobeAuth.getToken with context: ${this.tokenContext}`);
5399
+ const token = await adobe_auth_default.getToken(
5400
+ this.clientId,
5401
+ this.clientSecret,
5402
+ this.technicalAccountId,
5403
+ this.technicalAccountEmail,
5404
+ this.imsOrgId,
5405
+ this.scopes,
5406
+ this.tokenContext
5407
+ );
5408
+ if (token !== null && token !== void 0) {
5409
+ this.customLogger.debug("Received token from AdobeAuth, parsing with BearerToken.info");
5410
+ const tokenInfo = bearer_token_default.info(token);
5411
+ if (!tokenInfo.isValid) {
5412
+ this.customLogger.error("Received invalid or expired token from IMS");
5413
+ return null;
5414
+ }
5415
+ const expireInSeconds = tokenInfo.timeUntilExpiry ? Math.floor(tokenInfo.timeUntilExpiry / 1e3) : 86399;
5416
+ this.customLogger.debug(`Token expires in ${expireInSeconds} seconds`);
5417
+ return {
5418
+ token,
5419
+ expire_in: expireInSeconds
5420
+ };
5421
+ }
5422
+ this.customLogger.error("Received null or undefined token from IMS");
5423
+ return null;
5424
+ } catch (error) {
5425
+ this.customLogger.error(`Failed to get IMS token: ${error.message}`);
5426
+ return null;
5427
+ }
5428
+ }
5429
+ /**
5430
+ * @param result
5431
+ * @return boolean
5432
+ */
5433
+ async setValue(result) {
5434
+ try {
5435
+ const state = await this.getState();
5436
+ if (state === null) {
5437
+ this.customLogger.info("State API not available, skipping token caching");
5438
+ return true;
5439
+ }
5440
+ const ttlWithBuffer = Math.max(result.expire_in - 300, 60);
5441
+ this.customLogger.debug(
5442
+ `Caching IMS token with TTL: ${ttlWithBuffer} seconds (original: ${result.expire_in})`
5443
+ );
5444
+ await state.put(this.key, result.token, { ttl: ttlWithBuffer });
5445
+ return true;
5446
+ } catch (error) {
5447
+ this.customLogger.error(`Failed to cache IMS token: ${error.message}`);
5448
+ return true;
5449
+ }
5450
+ }
5451
+ /**
5452
+ * @return string | null
5453
+ */
5454
+ async getValue() {
5455
+ try {
5456
+ this.customLogger.debug("Checking for cached IMS token");
5457
+ const state = await this.getState();
5458
+ if (state === null) {
5459
+ this.customLogger.debug("State API not available, cannot retrieve cached token");
5460
+ return null;
5461
+ }
5462
+ const value = await state.get(this.key);
5463
+ if (value !== void 0 && value.value) {
5464
+ this.customLogger.debug("Found cached IMS token");
5465
+ return value.value;
5466
+ }
5467
+ this.customLogger.debug("No cached IMS token found");
5468
+ } catch (error) {
5469
+ this.customLogger.error(`Failed to retrieve cached IMS token: ${error.message}`);
5470
+ }
5471
+ return null;
5472
+ }
5473
+ /**
5474
+ * @return any
5475
+ */
5476
+ async getState() {
5477
+ if (this.state === void 0) {
5478
+ try {
5479
+ this.customLogger.debug("Initializing State API for token caching");
5480
+ this.state = await State3.init();
5481
+ } catch (error) {
5482
+ this.customLogger.error(`Failed to initialize State API: ${error.message}`);
5483
+ this.state = null;
5484
+ }
5485
+ }
5486
+ return this.state;
5487
+ }
5488
+ };
5489
+ __name(_GenerateImsToken, "GenerateImsToken");
5490
+ var GenerateImsToken = _GenerateImsToken;
5491
+ var generate_ims_token_default = GenerateImsToken;
5492
+
4883
5493
  // src/commerce/adobe-commerce-client/ims-connection/index.ts
4884
- import { Core as Core10 } from "@adobe/aio-sdk";
4885
5494
  var _ImsConnection = class _ImsConnection {
4886
5495
  /**
4887
5496
  * @param clientId
@@ -4891,38 +5500,35 @@ var _ImsConnection = class _ImsConnection {
4891
5500
  * @param imsOrgId
4892
5501
  * @param scopes
4893
5502
  * @param logger
4894
- * @param currentContext
4895
5503
  */
4896
- constructor(clientId, clientSecret, technicalAccountId, technicalAccountEmail, imsOrgId, scopes, logger = null, currentContext = "adobe-commerce-client") {
5504
+ constructor(clientId, clientSecret, technicalAccountId, technicalAccountEmail, imsOrgId, scopes, logger = null) {
4897
5505
  this.clientId = clientId;
4898
5506
  this.clientSecret = clientSecret;
4899
5507
  this.technicalAccountId = technicalAccountId;
4900
5508
  this.technicalAccountEmail = technicalAccountEmail;
4901
5509
  this.imsOrgId = imsOrgId;
4902
5510
  this.scopes = scopes;
4903
- this.currentContext = currentContext;
4904
- if (logger === null) {
4905
- logger = Core10.Logger(currentContext, {
4906
- level: "debug"
4907
- });
4908
- }
4909
- this.logger = logger;
5511
+ this.customLogger = new custom_logger_default(logger);
4910
5512
  }
4911
5513
  /**
4912
5514
  * @param commerceGot
4913
5515
  */
4914
5516
  async extend(commerceGot) {
4915
- this.logger.debug("Using Commerce client with IMS authentication");
4916
- const token = await adobe_auth_default.getToken(
5517
+ this.customLogger.info("Using Commerce client with IMS authentication");
5518
+ const tokenGenerator = new generate_ims_token_default(
4917
5519
  this.clientId,
4918
5520
  this.clientSecret,
4919
5521
  this.technicalAccountId,
4920
5522
  this.technicalAccountEmail,
4921
5523
  this.imsOrgId,
4922
5524
  this.scopes,
4923
- this.currentContext
5525
+ this.customLogger.getLogger()
4924
5526
  );
4925
- this.logger.debug(`IMS token being extended to header: ${token}`);
5527
+ const token = await tokenGenerator.execute();
5528
+ if (token === null) {
5529
+ throw new Error("Failed to generate or retrieve IMS token");
5530
+ }
5531
+ this.customLogger.info(`IMS token being extended to header: ${token.substring(0, 10)}...`);
4926
5532
  return commerceGot.extend({
4927
5533
  headers: {
4928
5534
  Authorization: `Bearer ${token}`
@@ -4933,7 +5539,551 @@ var _ImsConnection = class _ImsConnection {
4933
5539
  __name(_ImsConnection, "ImsConnection");
4934
5540
  var ImsConnection = _ImsConnection;
4935
5541
  var ims_connection_default = ImsConnection;
5542
+
5543
+ // src/commerce/shipping-carrier/method/index.ts
5544
+ var _ShippingCarrierMethod = class _ShippingCarrierMethod {
5545
+ constructor(carrierCode, method) {
5546
+ this.methodData = { carrier_code: carrierCode, method, additional_data: [] };
5547
+ }
5548
+ /**
5549
+ * Sets the display name for the shipping method
5550
+ *
5551
+ * @param methodTitle - Display name for the shipping method
5552
+ * @returns The rate builder instance for method chaining
5553
+ */
5554
+ setMethodTitle(methodTitle) {
5555
+ this.methodData.method_title = methodTitle;
5556
+ return this;
5557
+ }
5558
+ /**
5559
+ * Sets the price charged to the customer
5560
+ *
5561
+ * @param price - Price charged to the customer
5562
+ * @returns The rate builder instance for method chaining
5563
+ */
5564
+ setPrice(price) {
5565
+ this.methodData.price = price;
5566
+ return this;
5567
+ }
5568
+ /**
5569
+ * Sets the cost to the merchant
5570
+ *
5571
+ * @param cost - Cost to the merchant
5572
+ * @returns The rate builder instance for method chaining
5573
+ */
5574
+ setCost(cost) {
5575
+ this.methodData.cost = cost;
5576
+ return this;
5577
+ }
5578
+ /**
5579
+ * Adds additional data to the shipping method
5580
+ *
5581
+ * @param key - Key for the additional data
5582
+ * @param value - Value for the additional data
5583
+ * @returns The rate builder instance for method chaining
5584
+ *
5585
+ * @example
5586
+ * ```typescript
5587
+ * rate.addAdditionalData('delivery_time', '3-5 business days')
5588
+ * .addAdditionalData('tracking_available', true);
5589
+ * ```
5590
+ */
5591
+ addAdditionalData(key, value) {
5592
+ const additionalDataItem = { key, value };
5593
+ this.methodData.additional_data?.push(additionalDataItem);
5594
+ return this;
5595
+ }
5596
+ /**
5597
+ * Gets and returns the shipping carrier method data
5598
+ *
5599
+ * @returns The shipping carrier method data
5600
+ */
5601
+ getData() {
5602
+ return this.methodData;
5603
+ }
5604
+ };
5605
+ __name(_ShippingCarrierMethod, "ShippingCarrierMethod");
5606
+ var ShippingCarrierMethod = _ShippingCarrierMethod;
5607
+ var method_default = ShippingCarrierMethod;
5608
+
5609
+ // src/commerce/shipping-carrier/index.ts
5610
+ var _ShippingCarrier = class _ShippingCarrier {
5611
+ constructor(code, callback) {
5612
+ this.addedMethods = [];
5613
+ this.removedMethods = [];
5614
+ this.validateCarrierCode(code);
5615
+ this.carrierData = {
5616
+ code,
5617
+ active: true,
5618
+ tracking_available: true,
5619
+ shipping_labels_available: true
5620
+ };
5621
+ this.addedMethods = [];
5622
+ this.removedMethods = [];
5623
+ if (callback) {
5624
+ callback(this);
5625
+ }
5626
+ }
5627
+ /**
5628
+ * Validates that the carrier code contains only alphanumeric characters and underscores
5629
+ *
5630
+ * @param code - Carrier code to validate
5631
+ * @throws Error if code is invalid
5632
+ */
5633
+ validateCarrierCode(code) {
5634
+ if (!code || code.trim() === "") {
5635
+ throw new Error("Carrier code cannot be empty");
5636
+ }
5637
+ const validPattern = /^[a-zA-Z0-9_]+$/;
5638
+ if (!validPattern.test(code)) {
5639
+ throw new Error("Carrier code must contain only alphanumeric characters and underscores");
5640
+ }
5641
+ }
5642
+ /**
5643
+ * Validates that the method code contains only alphanumeric characters and underscores
5644
+ *
5645
+ * @param method - Method code to validate
5646
+ * @throws Error if method code is invalid
5647
+ */
5648
+ validateMethodCode(method) {
5649
+ if (!method || method.trim() === "") {
5650
+ throw new Error("Method code cannot be empty");
5651
+ }
5652
+ const validPattern = /^[a-zA-Z0-9_]+$/;
5653
+ if (!validPattern.test(method)) {
5654
+ throw new Error("Method code must contain only alphanumeric characters and underscores");
5655
+ }
5656
+ }
5657
+ /**
5658
+ * Sets the title for the shipping carrier
5659
+ *
5660
+ * @param title - Display title for the carrier
5661
+ * @returns The builder instance for method chaining
5662
+ *
5663
+ * @example
5664
+ * ```typescript
5665
+ * carrier.setTitle('FedEx Express');
5666
+ * ```
5667
+ */
5668
+ setTitle(title) {
5669
+ this.carrierData.title = title;
5670
+ return this;
5671
+ }
5672
+ /**
5673
+ * Sets the stores for the shipping carrier
5674
+ *
5675
+ * @param stores - Array of store codes
5676
+ * @returns The builder instance for method chaining
5677
+ *
5678
+ * @example
5679
+ * ```typescript
5680
+ * carrier.setStores(['default', 'store1', 'store2']);
5681
+ * ```
5682
+ */
5683
+ setStores(stores) {
5684
+ this.carrierData.stores = stores;
5685
+ return this;
5686
+ }
5687
+ /**
5688
+ * Sets the countries for the shipping carrier
5689
+ *
5690
+ * @param countries - Array of country codes
5691
+ * @returns The builder instance for method chaining
5692
+ *
5693
+ * @example
5694
+ * ```typescript
5695
+ * carrier.setCountries(['US', 'CA', 'MX']);
5696
+ * ```
5697
+ */
5698
+ setCountries(countries) {
5699
+ this.carrierData.countries = countries;
5700
+ return this;
5701
+ }
5702
+ /**
5703
+ * Sets the sort order for the shipping carrier
5704
+ *
5705
+ * @param sortOrder - Sort order number
5706
+ * @returns The builder instance for method chaining
5707
+ *
5708
+ * @example
5709
+ * ```typescript
5710
+ * carrier.setSortOrder(10);
5711
+ * ```
5712
+ */
5713
+ setSortOrder(sortOrder) {
5714
+ this.carrierData.sort_order = sortOrder;
5715
+ return this;
5716
+ }
5717
+ /**
5718
+ * Sets the active status for the shipping carrier
5719
+ *
5720
+ * @param active - Active status
5721
+ * @returns The builder instance for method chaining
5722
+ *
5723
+ * @example
5724
+ * ```typescript
5725
+ * carrier.setActive(true);
5726
+ * carrier.setActive(false);
5727
+ * ```
5728
+ */
5729
+ setActive(active) {
5730
+ this.carrierData.active = active;
5731
+ return this;
5732
+ }
5733
+ /**
5734
+ * Sets the tracking availability for the shipping carrier
5735
+ *
5736
+ * @param trackingAvailable - Tracking availability status
5737
+ * @returns The builder instance for method chaining
5738
+ *
5739
+ * @example
5740
+ * ```typescript
5741
+ * carrier.setTrackingAvailable(true);
5742
+ * carrier.setTrackingAvailable(false);
5743
+ * ```
5744
+ */
5745
+ setTrackingAvailable(trackingAvailable) {
5746
+ this.carrierData.tracking_available = trackingAvailable;
5747
+ return this;
5748
+ }
5749
+ /**
5750
+ * Sets the shipping labels availability for the shipping carrier
5751
+ *
5752
+ * @param shippingLabelsAvailable - Shipping labels availability status
5753
+ * @returns The builder instance for method chaining
5754
+ *
5755
+ * @example
5756
+ * ```typescript
5757
+ * carrier.setShippingLabelsAvailable(true);
5758
+ * carrier.setShippingLabelsAvailable(false);
5759
+ * ```
5760
+ */
5761
+ setShippingLabelsAvailable(shippingLabelsAvailable) {
5762
+ this.carrierData.shipping_labels_available = shippingLabelsAvailable;
5763
+ return this;
5764
+ }
5765
+ /**
5766
+ * Sets the carrier data from a ShippingCarrierData object
5767
+ *
5768
+ * @param carrierData - Carrier data object
5769
+ * @returns The builder instance for method chaining
5770
+ *
5771
+ * @example
5772
+ * ```typescript
5773
+ * carrier.setData({
5774
+ * code: 'fedex',
5775
+ * title: 'FedEx Express',
5776
+ * stores: ['default'],
5777
+ * countries: ['US', 'CA'],
5778
+ * sort_order: 10,
5779
+ * active: true,
5780
+ * tracking_available: true,
5781
+ * shipping_labels_available: true
5782
+ * });
5783
+ * ```
5784
+ */
5785
+ setData(carrierData) {
5786
+ this.validateCarrierCode(carrierData.code);
5787
+ this.carrierData = { ...carrierData };
5788
+ return this;
5789
+ }
5790
+ /**
5791
+ * Adds a shipping method to the carrier using a callback pattern
5792
+ *
5793
+ * @param method - Unique method for the shipping rate
5794
+ * @param callback - Optional callback function to configure the method
5795
+ * @returns The builder instance for method chaining
5796
+ *
5797
+ * @example
5798
+ * ```typescript
5799
+ * builder.addMethod('standard', (method) => {
5800
+ * method.setMethodTitle('Standard Shipping')
5801
+ * .setPrice(9.99)
5802
+ * .setCost(5.00)
5803
+ * .addAdditionalData('delivery_time', '3-5 business days');
5804
+ * });
5805
+ * ```
5806
+ */
5807
+ addMethod(method, callback) {
5808
+ this.validateMethodCode(method);
5809
+ const methodBuilder = new method_default(this.carrierData.code, method);
5810
+ if (callback) {
5811
+ callback(methodBuilder);
5812
+ }
5813
+ this.addedMethods.push(methodBuilder.getData());
5814
+ return this;
5815
+ }
5816
+ /**
5817
+ * Removes a shipping method from the carrier
5818
+ *
5819
+ * @param method - Method code to remove
5820
+ * @returns The builder instance for method chaining
5821
+ *
5822
+ * @example
5823
+ * ```typescript
5824
+ * builder.removeMethod('express');
5825
+ * ```
5826
+ */
5827
+ removeMethod(method) {
5828
+ this.validateMethodCode(method);
5829
+ this.removedMethods.push(method);
5830
+ return this;
5831
+ }
5832
+ /**
5833
+ * Resets the carrier and re-initializes it with new code and optional callback
5834
+ *
5835
+ * @param code - Carrier code
5836
+ * @param callback - Optional callback function to configure the carrier
5837
+ * @returns The builder instance for method chaining
5838
+ *
5839
+ * @example
5840
+ * ```typescript
5841
+ * carrier.reset('ups', (carrier) => {
5842
+ * carrier.addMethod('ground', (method) => {
5843
+ * method.setMethodTitle('UPS Ground').setPrice(12.99).setCost(8.00);
5844
+ * });
5845
+ * });
5846
+ * ```
5847
+ */
5848
+ reset(code, callback) {
5849
+ this.validateCarrierCode(code);
5850
+ this.carrierData = {
5851
+ code,
5852
+ active: true,
5853
+ tracking_available: true,
5854
+ shipping_labels_available: true
5855
+ };
5856
+ this.addedMethods = [];
5857
+ this.removedMethods = [];
5858
+ if (callback) {
5859
+ callback(this);
5860
+ }
5861
+ return this;
5862
+ }
5863
+ /**
5864
+ * Gets and returns the shipping carrier data as a JSON object
5865
+ *
5866
+ * @returns The shipping carrier data
5867
+ *
5868
+ * @example
5869
+ * ```typescript
5870
+ * const carrierData = carrier.getData();
5871
+ * // Returns:
5872
+ * // {
5873
+ * // code: 'DPS',
5874
+ * // title: 'Demo Postal Service',
5875
+ * // stores: ['default'],
5876
+ * // countries: ['US', 'CA'],
5877
+ * // sort_order: 10,
5878
+ * // active: true,
5879
+ * // tracking_available: true,
5880
+ * // shipping_labels_available: true
5881
+ * // }
5882
+ * ```
5883
+ */
5884
+ getData() {
5885
+ return this.carrierData;
5886
+ }
5887
+ };
5888
+ __name(_ShippingCarrier, "ShippingCarrier");
5889
+ var ShippingCarrier = _ShippingCarrier;
5890
+ var shipping_carrier_default = ShippingCarrier;
5891
+
5892
+ // src/commerce/shipping-carrier/response/index.ts
5893
+ var _ShippingCarrierResponse = class _ShippingCarrierResponse {
5894
+ constructor(carrier) {
5895
+ this.carrier = carrier;
5896
+ }
5897
+ /**
5898
+ * Generates and returns an array of WebhookActionResponse operations
5899
+ *
5900
+ * @returns Array of WebhookActionResponse operations
5901
+ *
5902
+ * @example
5903
+ * ```typescript
5904
+ * const carrier = new ShippingCarrier('fedex');
5905
+ * const response = new ShippingCarrierResponse(carrier);
5906
+ * const operations = response.generate();
5907
+ * ```
5908
+ */
5909
+ generate() {
5910
+ const operations = [];
5911
+ const addedMethods = this.carrier["addedMethods"];
5912
+ for (const method of addedMethods) {
5913
+ operations.push(response_default2.add("result", method));
5914
+ }
5915
+ const removedMethods = this.carrier["removedMethods"];
5916
+ for (const method of removedMethods) {
5917
+ operations.push(response_default2.add("result", { method, remove: true }));
5918
+ }
5919
+ return operations;
5920
+ }
5921
+ };
5922
+ __name(_ShippingCarrierResponse, "ShippingCarrierResponse");
5923
+ var ShippingCarrierResponse = _ShippingCarrierResponse;
5924
+ var response_default3 = ShippingCarrierResponse;
5925
+
5926
+ // src/experience/admin-ui-sdk/index.ts
5927
+ var _AdminUiSdk = class _AdminUiSdk {
5928
+ /**
5929
+ * Creates a new AdminUiSdk instance
5930
+ * @param extensionId - Unique identifier for the extension
5931
+ * @throws {Error} If extensionId is empty or invalid
5932
+ */
5933
+ constructor(extensionId) {
5934
+ this.menuItems = [];
5935
+ if (!extensionId?.trim()) {
5936
+ throw new Error("Extension ID is required and cannot be empty");
5937
+ }
5938
+ const trimmedId = extensionId.trim();
5939
+ if (!this.isValidExtensionId(trimmedId)) {
5940
+ throw new Error(
5941
+ "Extension ID must be alphanumeric with underscores only (no spaces, hyphens, or special characters)"
5942
+ );
5943
+ }
5944
+ this.extensionId = trimmedId;
5945
+ }
5946
+ /**
5947
+ * Validates that an extension ID contains only alphanumeric characters and underscores
5948
+ * @param id - The extension ID to validate
5949
+ * @returns true if valid, false otherwise
5950
+ */
5951
+ isValidExtensionId(id) {
5952
+ return /^[a-zA-Z0-9_]+$/.test(id);
5953
+ }
5954
+ /**
5955
+ * Validates that a menu ID is valid (can contain :: separator for namespacing)
5956
+ * @param id - The menu ID to validate
5957
+ * @returns true if valid, false otherwise
5958
+ */
5959
+ isValidMenuId(id) {
5960
+ return /^[a-zA-Z0-9_:]+$/.test(id);
5961
+ }
5962
+ /**
5963
+ * Adds a menu item to the extension
5964
+ * @param id - Full identifier for the menu item (e.g., 'extensionId::menuItem')
5965
+ * @param title - Display title for the menu item
5966
+ * @param sortOrder - Sort order for menu positioning
5967
+ * @param parent - Parent menu identifier (optional, full ID like 'extensionId::parent')
5968
+ * @throws {Error} If parameters are invalid or ID already exists
5969
+ */
5970
+ addMenuItem(id, title, sortOrder, parent) {
5971
+ if (!id?.trim()) {
5972
+ throw new Error("Menu item ID is required and cannot be empty");
5973
+ }
5974
+ if (!this.isValidMenuId(id.trim())) {
5975
+ throw new Error(
5976
+ "Menu item ID must be alphanumeric with underscores and colons only (no spaces, hyphens, or other special characters)"
5977
+ );
5978
+ }
5979
+ if (!title?.trim()) {
5980
+ throw new Error("Menu item title is required and cannot be empty");
5981
+ }
5982
+ if (parent !== void 0 && !parent?.trim()) {
5983
+ throw new Error("Menu item parent cannot be empty if provided");
5984
+ }
5985
+ if (parent !== void 0 && !this.isValidMenuId(parent.trim())) {
5986
+ throw new Error(
5987
+ "Menu item parent must be alphanumeric with underscores and colons only (no spaces, hyphens, or other special characters)"
5988
+ );
5989
+ }
5990
+ if (typeof sortOrder !== "number" || sortOrder < 0) {
5991
+ throw new Error("Menu item sortOrder must be a non-negative number");
5992
+ }
5993
+ const trimmedId = id.trim();
5994
+ if (this.menuItems.some((item) => item.id === trimmedId)) {
5995
+ throw new Error(`Menu item with ID '${trimmedId}' already exists`);
5996
+ }
5997
+ const menuItem = {
5998
+ id: trimmedId,
5999
+ title: title.trim(),
6000
+ sortOrder
6001
+ };
6002
+ if (parent?.trim()) {
6003
+ menuItem.parent = parent.trim();
6004
+ }
6005
+ this.menuItems.push(menuItem);
6006
+ }
6007
+ /**
6008
+ * Adds a menu section to the extension
6009
+ * @param id - Full identifier for the menu section (e.g., 'extensionId::section')
6010
+ * @param title - Display title for the menu section
6011
+ * @param sortOrder - Sort order for section positioning
6012
+ * @param parent - Parent menu identifier (optional, full ID like 'Magento_Backend::system')
6013
+ * @throws {Error} If parameters are invalid or ID already exists
6014
+ */
6015
+ addMenuSection(id, title, sortOrder, parent) {
6016
+ if (!id?.trim()) {
6017
+ throw new Error("Menu section ID is required and cannot be empty");
6018
+ }
6019
+ if (!this.isValidMenuId(id.trim())) {
6020
+ throw new Error(
6021
+ "Menu section ID must be alphanumeric with underscores and colons only (no spaces, hyphens, or other special characters)"
6022
+ );
6023
+ }
6024
+ if (!title?.trim()) {
6025
+ throw new Error("Menu section title is required and cannot be empty");
6026
+ }
6027
+ if (parent !== void 0 && !parent?.trim()) {
6028
+ throw new Error("Menu section parent cannot be empty if provided");
6029
+ }
6030
+ if (parent !== void 0 && !this.isValidMenuId(parent.trim())) {
6031
+ throw new Error(
6032
+ "Menu section parent must be alphanumeric with underscores and colons only (no spaces, hyphens, or other special characters)"
6033
+ );
6034
+ }
6035
+ if (typeof sortOrder !== "number" || sortOrder < 0) {
6036
+ throw new Error("Menu section sortOrder must be a non-negative number");
6037
+ }
6038
+ const trimmedId = id.trim();
6039
+ if (this.menuItems.some((item) => item.id === trimmedId)) {
6040
+ throw new Error(`Menu item with ID '${trimmedId}' already exists`);
6041
+ }
6042
+ const menuSection = {
6043
+ id: trimmedId,
6044
+ title: title.trim(),
6045
+ sortOrder,
6046
+ isSection: true
6047
+ };
6048
+ if (parent?.trim()) {
6049
+ menuSection.parent = parent.trim();
6050
+ }
6051
+ this.menuItems.push(menuSection);
6052
+ }
6053
+ /**
6054
+ * Sets the page title for the extension
6055
+ * @param title - The page title
6056
+ * @throws {Error} If title is empty or invalid
6057
+ */
6058
+ addPage(title) {
6059
+ if (!title?.trim()) {
6060
+ throw new Error("Page title is required and cannot be empty");
6061
+ }
6062
+ this.pageTitle = title.trim();
6063
+ }
6064
+ /**
6065
+ * Gets the complete registration object for the extension
6066
+ * @returns The registration object with optional menu items and page configuration
6067
+ */
6068
+ getRegistration() {
6069
+ const registration = {};
6070
+ if (this.menuItems.length > 0) {
6071
+ registration.menuItems = [...this.menuItems];
6072
+ }
6073
+ if (this.pageTitle) {
6074
+ registration.page = {
6075
+ title: this.pageTitle
6076
+ };
6077
+ }
6078
+ return {
6079
+ registration
6080
+ };
6081
+ }
6082
+ };
6083
+ __name(_AdminUiSdk, "AdminUiSdk");
6084
+ var AdminUiSdk = _AdminUiSdk;
4936
6085
  export {
6086
+ AdminUiSdk,
4937
6087
  adobe_auth_default as AdobeAuth,
4938
6088
  adobe_commerce_client_default as AdobeCommerceClient,
4939
6089
  basic_auth_connection_default as BasicAuthConnection,
@@ -4957,10 +6107,18 @@ export {
4957
6107
  openwhisk_action_default as OpenwhiskAction,
4958
6108
  parameters_default as Parameters,
4959
6109
  provider_default as ProviderManager,
6110
+ publish_event_default as PublishEvent,
4960
6111
  registration_default as RegistrationManager,
4961
6112
  rest_client_default as RestClient,
4962
6113
  runtime_action_default as RuntimeAction,
4963
6114
  response_default as RuntimeActionResponse,
4964
- validator_default as Validator
6115
+ shipping_carrier_default as ShippingCarrier,
6116
+ method_default as ShippingCarrierMethod,
6117
+ response_default3 as ShippingCarrierResponse,
6118
+ SignatureVerification,
6119
+ validator_default as Validator,
6120
+ webhook_action_default as WebhookAction,
6121
+ WebhookActionOperation,
6122
+ response_default2 as WebhookActionResponse
4965
6123
  };
4966
6124
  //# sourceMappingURL=index.mjs.map