@scayle/storefront-core 8.38.4 → 8.39.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @scayle/storefront-core
2
2
 
3
+ ## 8.39.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Added `'token'` and `'code'` to the list of default `blacklistedKeys`. This will more proactively redact server logs to prevent leaked data.
8
+
9
+ **Dependencies**
10
+
11
+ - Updated dependency to @scayle/storefront-api@18.12.0
12
+ - Updated dependency to @scayle/unstorage-scayle-kv-driver@1.0.3
13
+
14
+ ## 8.39.0
15
+
16
+ ### Patch Changes
17
+
18
+ - Use a custom error type for OAuth API errors to improve troubleshooting OAuth errors.
19
+
3
20
  ## 8.38.4
4
21
 
5
22
  ## 8.38.3
@@ -10,6 +10,12 @@ export interface OAuthOptions {
10
10
  apiHost: string;
11
11
  additionalHeaders?: HeadersInit;
12
12
  }
13
+ /**
14
+ * Error thrown when OAuth API request fails.
15
+ */
16
+ export declare class OAuthRequestError extends Error {
17
+ constructor(message: string, options?: ErrorOptions);
18
+ }
13
19
  /**
14
20
  * Creates and returns an OAuthClient instance using the provided RPC context.
15
21
  *
@@ -7,10 +7,30 @@ class MissingCredentialsError extends Error {
7
7
  this.name = "MissingCredentialsError";
8
8
  }
9
9
  }
10
+ export class OAuthRequestError extends Error {
11
+ constructor(message, options) {
12
+ super(message, options);
13
+ this.name = "OAuthRequestError";
14
+ }
15
+ }
16
+ function stringifyOAuthError(error) {
17
+ if (error.message) {
18
+ return error.hint ? `${error.error}: ${error.message} (hint: ${error.hint})` : `${error.error}: ${error.message}`;
19
+ } else {
20
+ return error.error;
21
+ }
22
+ }
10
23
  async function oauthResponseHandler(response) {
11
24
  const data = await response.json();
12
25
  if (!response.ok) {
13
- throw new FetchError(response, data);
26
+ const fetchError = new FetchError(response, data);
27
+ if (data) {
28
+ const error = new OAuthRequestError(stringifyOAuthError(data), {
29
+ cause: fetchError
30
+ });
31
+ throw error;
32
+ }
33
+ throw fetchError;
14
34
  }
15
35
  return data;
16
36
  }
@@ -140,11 +140,11 @@ export const getVariantCrosssellingValues = (variants) => {
140
140
  if (!variants?.length) {
141
141
  return [];
142
142
  }
143
- const crossellings = variants.map((variant) => variant.advancedAttributes?.variantCrosssellings).filter(Boolean);
144
- const uniqueCrossellings = [
145
- ...new Map(crossellings.map((item) => [item?.id ?? item, item])).values()
143
+ const crossSellings = variants.map((variant) => variant.advancedAttributes?.variantCrosssellings).filter(Boolean);
144
+ const uniqueCrossSellings = [
145
+ ...new Map(crossSellings.map((item) => [item?.id ?? item, item])).values()
146
146
  ];
147
- const values = uniqueCrossellings.map((r) => r?.values);
147
+ const values = uniqueCrossSellings.map((r) => r?.values);
148
148
  const fieldSets = flattenDeep(values).map((r) => r?.fieldSet);
149
149
  return flattenDeep(fieldSets).map((r) => r?.value).filter((it) => !!it);
150
150
  };
@@ -4,7 +4,7 @@ export const stripShopLocaleFromPath = (locale, path, splitter = "/") => path.sp
4
4
  export const purifySensitiveValue = (value, showFirstAndLastChar = false) => {
5
5
  return showFirstAndLastChar && value.length > 2 ? value.replace(regex, "*") : SANITIZATION_MASK;
6
6
  };
7
- export const purifySensitiveData = (data = {}, blacklistedKeys = ["password"], showFirstAndLastChar = false) => {
7
+ export const purifySensitiveData = (data = {}, blacklistedKeys = ["password", "token", "code"], showFirstAndLastChar = false) => {
8
8
  return Object.entries(data).reduce(
9
9
  (purifiedPayload, [key, value]) => {
10
10
  if (!!value && value.constructor === Object) {
@@ -33,7 +33,7 @@ export const getCheckoutToken = defineRpcHandler(async (jwtPayload = {}, context
33
33
  carrier,
34
34
  basketId: context.basketKey,
35
35
  campaignKey
36
- }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"8.38.4"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
36
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"8.39.1"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
37
37
  return {
38
38
  accessToken: refreshedAccessToken,
39
39
  checkoutJwt
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scayle/storefront-core",
3
- "version": "8.38.4",
3
+ "version": "8.39.1",
4
4
  "description": "Collection of essential utilities to work with the Storefront API",
5
5
  "author": "SCAYLE Commerce Engine",
6
6
  "license": "MIT",
@@ -61,7 +61,7 @@
61
61
  },
62
62
  "devDependencies": {
63
63
  "@types/crypto-js": "4.2.2",
64
- "@types/node": "22.16.5",
64
+ "@types/node": "22.17.0",
65
65
  "@types/webpack-env": "1.18.8",
66
66
  "@vitest/coverage-v8": "3.2.4",
67
67
  "dprint": "0.50.1",
@@ -70,14 +70,15 @@
70
70
  "fishery": "2.3.1",
71
71
  "publint": "0.3.12",
72
72
  "rimraf": "6.0.1",
73
- "typescript": "5.8.3",
73
+ "typescript": "5.9.2",
74
74
  "unbuild": "3.6.0",
75
75
  "unstorage": "1.16.1",
76
76
  "vitest": "3.2.4",
77
- "@scayle/eslint-config-storefront": "4.7.2"
77
+ "@scayle/eslint-config-storefront": "4.7.3",
78
+ "@scayle/vitest-config-storefront": "1.0.0"
78
79
  },
79
80
  "volta": {
80
- "node": "22.17.1"
81
+ "node": "22.18.0"
81
82
  },
82
83
  "scripts": {
83
84
  "clean": "rimraf ./dist",