@adobe-commerce/aio-toolkit 1.0.0 → 1.0.2

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
@@ -15,13 +15,13 @@ var HttpStatus = /* @__PURE__ */ ((HttpStatus2) => {
15
15
  return HttpStatus2;
16
16
  })(HttpStatus || {});
17
17
  var HttpMethod = /* @__PURE__ */ ((HttpMethod3) => {
18
- HttpMethod3["GET"] = "get";
19
- HttpMethod3["POST"] = "post";
20
- HttpMethod3["PUT"] = "put";
21
- HttpMethod3["DELETE"] = "delete";
22
- HttpMethod3["PATCH"] = "patch";
23
- HttpMethod3["HEAD"] = "head";
24
- HttpMethod3["OPTIONS"] = "options";
18
+ HttpMethod3["GET"] = "GET";
19
+ HttpMethod3["POST"] = "POST";
20
+ HttpMethod3["PUT"] = "PUT";
21
+ HttpMethod3["DELETE"] = "DELETE";
22
+ HttpMethod3["PATCH"] = "PATCH";
23
+ HttpMethod3["HEAD"] = "HEAD";
24
+ HttpMethod3["OPTIONS"] = "OPTIONS";
25
25
  return HttpMethod3;
26
26
  })(HttpMethod || {});
27
27
 
@@ -195,9 +195,9 @@ var _RuntimeAction = class _RuntimeAction {
195
195
  if (errorMessage) {
196
196
  return response_default.error(400 /* BAD_REQUEST */, errorMessage);
197
197
  }
198
- const requestMethod = params.__ow_method;
198
+ const requestMethod = params.__ow_method?.toUpperCase();
199
199
  if (httpMethods.length > 0 && !httpMethods.includes(requestMethod)) {
200
- const errorMessage2 = `Invalid HTTP method: ${requestMethod}. Allowed methods are: ${httpMethods.join(", ")}`;
200
+ const errorMessage2 = `Invalid HTTP method: ${params.__ow_method}. Allowed methods are: ${httpMethods.join(", ")}`;
201
201
  logger.error(errorMessage2);
202
202
  return response_default.error(405 /* METHOD_NOT_ALLOWED */, errorMessage2);
203
203
  }
@@ -258,7 +258,7 @@ var _GraphQlAction = class _GraphQlAction {
258
258
  }, name = "main", disableIntrospection = false) {
259
259
  return runtime_action_default.execute(
260
260
  `graphql-${name}`,
261
- ["get" /* GET */, "post" /* POST */],
261
+ ["GET" /* GET */, "POST" /* POST */],
262
262
  ["query"],
263
263
  [],
264
264
  async (params, ctx) => {
@@ -423,39 +423,44 @@ var _FileRepository = class _FileRepository {
423
423
  /**
424
424
  * Saves a file record to the repository
425
425
  * @param payload - The data to save
426
- * @returns Promise<boolean> True if save was successful, false otherwise
426
+ * @param id - Optional ID for the file (sanitized to alphanumeric + underscore, takes precedence over payload.id)
427
+ * @returns Promise<string | null> The filename on success, null on failure
427
428
  */
428
- async save(payload = {}) {
429
+ async save(payload = {}, id) {
429
430
  try {
430
431
  const filesLib = await this.getFiles();
431
- let requestFileId = (/* @__PURE__ */ new Date()).getTime();
432
- if ("id" in payload && payload.id !== void 0) {
433
- requestFileId = Number(payload.id);
432
+ let fileId;
433
+ if (id) {
434
+ fileId = this.sanitizeFileId(id);
435
+ } else if ("id" in payload && payload.id !== void 0) {
436
+ fileId = String(payload.id);
437
+ } else {
438
+ fileId = String((/* @__PURE__ */ new Date()).getTime());
434
439
  }
435
- const filepath = `${this.filepath}/${requestFileId}.json`;
440
+ const filepath = `${this.filepath}/${fileId}.json`;
436
441
  const existingFile = await filesLib.list(filepath);
437
442
  if (existingFile.length) {
438
443
  const buffer = await filesLib.read(filepath);
439
444
  const existingData = JSON.parse(buffer.toString());
440
445
  payload = {
441
446
  ...payload,
442
- updated_at: (/* @__PURE__ */ new Date()).toDateString()
447
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
443
448
  };
444
449
  payload = { ...existingData, ...payload };
445
450
  await filesLib.delete(filepath);
446
451
  } else {
447
452
  payload = {
448
453
  ...payload,
449
- id: requestFileId,
450
- created_at: (/* @__PURE__ */ new Date()).toDateString(),
451
- updated_at: (/* @__PURE__ */ new Date()).toDateString()
454
+ id: fileId,
455
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
456
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
452
457
  };
453
458
  }
454
459
  await filesLib.write(filepath, JSON.stringify(payload));
455
- return true;
460
+ return fileId;
456
461
  } catch (error) {
457
462
  console.error("Error saving file:", error);
458
- return false;
463
+ return null;
459
464
  }
460
465
  }
461
466
  /**
@@ -470,6 +475,21 @@ var _FileRepository = class _FileRepository {
470
475
  }
471
476
  return await this.list();
472
477
  }
478
+ /**
479
+ * Sanitizes the file ID to contain only alphanumeric characters and underscores
480
+ * @param id - The ID to sanitize
481
+ * @returns Sanitized ID with invalid characters replaced by underscores
482
+ */
483
+ sanitizeFileId(id) {
484
+ if (!id || typeof id !== "string") {
485
+ return String((/* @__PURE__ */ new Date()).getTime());
486
+ }
487
+ const sanitized = id.replace(/[^a-zA-Z0-9_]/g, "_");
488
+ if (!sanitized || /^_+$/.test(sanitized)) {
489
+ return String((/* @__PURE__ */ new Date()).getTime());
490
+ }
491
+ return sanitized;
492
+ }
473
493
  /**
474
494
  * Initializes and returns the Files library instance
475
495
  * @returns Promise<any> Initialized Files library instance
@@ -488,21 +508,31 @@ var file_repository_default = FileRepository;
488
508
  // src/integration/bearer-token/index.ts
489
509
  var _BearerToken = class _BearerToken {
490
510
  /**
491
- * Extracts the Bearer token from OpenWhisk action parameters and returns detailed token information.
492
- * Looks for the authorization header in __ow_headers and extracts the token value
493
- * after the "Bearer " prefix.
511
+ * Extracts the Bearer token from HTTP request headers and returns detailed token information.
512
+ * Supports both standard HTTP headers and OpenWhisk action parameter formats.
494
513
  *
495
- * @param params - OpenWhisk action input parameters containing headers
514
+ * @param headersOrParams - Either a standard headers object or OpenWhisk action parameters
496
515
  * @returns Detailed token information object
497
516
  *
498
517
  * @example
518
+ * // Standard HTTP headers approach
519
+ * const headers = {
520
+ * authorization: 'Bearer abc123token'
521
+ * };
522
+ * const tokenInfo = BearerToken.extract(headers);
523
+ *
524
+ * @example
525
+ * // OpenWhisk action parameters (backward compatibility)
499
526
  * const params = {
500
527
  * __ow_headers: {
501
528
  * authorization: 'Bearer abc123token'
502
529
  * }
503
530
  * };
504
531
  * const tokenInfo = BearerToken.extract(params);
505
- * // returns: {
532
+ *
533
+ * @example
534
+ * // Both return the same result:
535
+ * // {
506
536
  * // token: 'abc123token',
507
537
  * // tokenLength: 11,
508
538
  * // isValid: true,
@@ -510,26 +540,54 @@ var _BearerToken = class _BearerToken {
510
540
  * // timeUntilExpiry: 3600000
511
541
  * // }
512
542
  */
513
- static extract(params) {
543
+ static extract(headersOrParams) {
514
544
  let token = null;
515
- if (params.__ow_headers?.authorization?.startsWith("Bearer ")) {
516
- token = params.__ow_headers.authorization.substring("Bearer ".length);
545
+ if (headersOrParams.authorization?.startsWith("Bearer ")) {
546
+ token = headersOrParams.authorization.substring("Bearer ".length);
547
+ } else if (headersOrParams.__ow_headers?.authorization?.startsWith("Bearer ")) {
548
+ token = headersOrParams.__ow_headers.authorization.substring("Bearer ".length);
517
549
  }
518
550
  return _BearerToken.info(token);
519
551
  }
520
552
  /**
521
- * Gets detailed information about a Bearer token
522
- * @param token - The Bearer token string (or null)
523
- * @returns {BearerTokenInfo} Detailed token information including validity and expiry
553
+ * Analyzes a Bearer token and returns detailed information including validity and expiry.
554
+ * Supports both JWT tokens (with automatic expiry detection) and plain tokens (24h default expiry).
555
+ *
556
+ * @param token - The Bearer token string (or null). Can be JWT or plain token.
557
+ * @returns Detailed token information object
524
558
  *
525
559
  * @example
526
- * const tokenInfo = BearerToken.info('abc123token');
560
+ * // Plain token (gets 24h default expiry)
561
+ * const plainTokenInfo = BearerToken.info('abc123token');
527
562
  * // returns: {
528
563
  * // token: 'abc123token',
529
564
  * // tokenLength: 11,
530
565
  * // isValid: true,
531
- * // expiry: '2024-01-01T12:00:00.000Z',
532
- * // timeUntilExpiry: 3600000
566
+ * // expiry: '2024-01-02T12:00:00.000Z', // 24h from now
567
+ * // timeUntilExpiry: 86400000 // milliseconds until expiry
568
+ * // }
569
+ *
570
+ * @example
571
+ * // JWT token (automatic expiry detection from 'exp' or 'expires_in' claims)
572
+ * const jwtToken = 'eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDQ0Njc2MDB9.signature';
573
+ * const jwtTokenInfo = BearerToken.info(jwtToken);
574
+ * // returns: {
575
+ * // token: 'eyJhbGciOiJIUzI1NiJ9...',
576
+ * // tokenLength: 45,
577
+ * // isValid: true, // false if expired
578
+ * // expiry: '2024-01-05T12:00:00.000Z', // from JWT exp claim
579
+ * // timeUntilExpiry: 172800000 // actual time until expiry
580
+ * // }
581
+ *
582
+ * @example
583
+ * // Null or invalid token
584
+ * const nullTokenInfo = BearerToken.info(null);
585
+ * // returns: {
586
+ * // token: null,
587
+ * // tokenLength: 0,
588
+ * // isValid: false,
589
+ * // expiry: null,
590
+ * // timeUntilExpiry: null
533
591
  * // }
534
592
  */
535
593
  static info(token) {
@@ -595,14 +653,86 @@ var bearer_token_default = BearerToken;
595
653
  import fetch from "node-fetch";
596
654
  var _RestClient = class _RestClient {
597
655
  /**
598
- * A generic method to make GET rest call
656
+ * A completely raw method to make HTTP requests
599
657
  *
600
658
  * @param endpoint
659
+ * @param method
601
660
  * @param headers
661
+ * @param payload
662
+ * @returns {Promise<Response>}
663
+ */
664
+ async makeRequest(endpoint, method = "GET", headers = {}, payload = null) {
665
+ let options = {
666
+ method,
667
+ headers
668
+ };
669
+ if (payload !== null) {
670
+ let body;
671
+ let contentType;
672
+ if (payload instanceof URLSearchParams) {
673
+ body = payload.toString();
674
+ contentType = headers["Content-Type"] || "application/x-www-form-urlencoded";
675
+ } else if (typeof FormData !== "undefined" && payload instanceof FormData) {
676
+ body = payload;
677
+ contentType = headers["Content-Type"];
678
+ } else if (typeof payload === "string") {
679
+ body = payload;
680
+ contentType = headers["Content-Type"] || "text/plain";
681
+ } else if (payload instanceof Buffer || payload instanceof ArrayBuffer || typeof Uint8Array !== "undefined" && payload instanceof Uint8Array) {
682
+ body = payload;
683
+ contentType = headers["Content-Type"] || "application/octet-stream";
684
+ } else {
685
+ body = JSON.stringify(payload);
686
+ contentType = headers["Content-Type"] || "application/json";
687
+ }
688
+ const requestHeaders = { ...headers };
689
+ if (contentType) {
690
+ requestHeaders["Content-Type"] = contentType;
691
+ }
692
+ options = {
693
+ ...options,
694
+ body,
695
+ headers: requestHeaders
696
+ };
697
+ }
698
+ return await fetch(endpoint, options);
699
+ }
700
+ /**
701
+ * A method to parse HTTP response
702
+ *
703
+ * @param response
602
704
  * @returns {Promise<any>}
603
705
  */
604
- async get(endpoint, headers = {}) {
605
- return await this.apiCall(endpoint, "GET", headers);
706
+ async parseResponse(response) {
707
+ if (!response.ok) {
708
+ throw new Error(`HTTP error! status: ${response.status}`);
709
+ }
710
+ if (response.status === 204 || response.headers?.get("content-length") === "0") {
711
+ return null;
712
+ }
713
+ if (typeof response.json === "function") {
714
+ const contentType = response.headers?.get("content-type");
715
+ if (!contentType || contentType.includes("application/json") || contentType.includes("application/hal+json")) {
716
+ return await response.json();
717
+ }
718
+ }
719
+ if (typeof response.text === "function") {
720
+ const text = await response.text();
721
+ return text;
722
+ }
723
+ return null;
724
+ }
725
+ /**
726
+ * A generic method to make GET rest call
727
+ *
728
+ * @param endpoint
729
+ * @param headers
730
+ * @param parsed
731
+ * @returns {Promise<Response | any>}
732
+ */
733
+ async get(endpoint, headers = {}, parsed = true) {
734
+ const response = await this.makeRequest(endpoint, "GET", headers);
735
+ return parsed ? await this.parseResponse(response) : response;
606
736
  }
607
737
  /**
608
738
  * A generic method to make POST rest call
@@ -610,10 +740,12 @@ var _RestClient = class _RestClient {
610
740
  * @param endpoint
611
741
  * @param headers
612
742
  * @param payload
613
- * @returns {Promise<any>}
743
+ * @param parsed
744
+ * @returns {Promise<Response | any>}
614
745
  */
615
- async post(endpoint, headers = {}, payload = null) {
616
- return await this.apiCall(endpoint, "POST", headers, payload);
746
+ async post(endpoint, headers = {}, payload = null, parsed = true) {
747
+ const response = await this.makeRequest(endpoint, "POST", headers, payload);
748
+ return parsed ? await this.parseResponse(response) : response;
617
749
  }
618
750
  /**
619
751
  * A generic method to make PUT rest call
@@ -621,20 +753,24 @@ var _RestClient = class _RestClient {
621
753
  * @param endpoint
622
754
  * @param headers
623
755
  * @param payload
624
- * @returns {Promise<any>}
756
+ * @param parsed
757
+ * @returns {Promise<Response | any>}
625
758
  */
626
- async put(endpoint, headers = {}, payload = null) {
627
- return await this.apiCall(endpoint, "PUT", headers, payload);
759
+ async put(endpoint, headers = {}, payload = null, parsed = true) {
760
+ const response = await this.makeRequest(endpoint, "PUT", headers, payload);
761
+ return parsed ? await this.parseResponse(response) : response;
628
762
  }
629
763
  /**
630
764
  * A generic method to make DELETE rest call
631
765
  *
632
766
  * @param endpoint
633
767
  * @param headers
634
- * @returns {Promise<any>}
768
+ * @param parsed
769
+ * @returns {Promise<Response | any>}
635
770
  */
636
- async delete(endpoint, headers = {}) {
637
- return await this.apiCall(endpoint, "DELETE", headers);
771
+ async delete(endpoint, headers = {}, parsed = true) {
772
+ const response = await this.makeRequest(endpoint, "DELETE", headers);
773
+ return parsed ? await this.parseResponse(response) : response;
638
774
  }
639
775
  /**
640
776
  * A generic method to make rest call
@@ -644,6 +780,7 @@ var _RestClient = class _RestClient {
644
780
  * @param headers
645
781
  * @param payload
646
782
  * @returns {Promise<any>}
783
+ * @deprecated Use makeRequest() and parseResponse() methods instead
647
784
  */
648
785
  async apiCall(endpoint, method = "POST", headers = {}, payload = null) {
649
786
  let options = {