@scayle/storefront-core 7.65.5 → 7.65.7

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,17 @@
1
1
  # @scayle/storefront-core
2
2
 
3
+ ## 7.65.7
4
+
5
+ ### Patch Changes
6
+
7
+ - Delete `refreshToken` if it fails to refresh the access token
8
+
9
+ ## 7.65.6
10
+
11
+ ### Patch Changes
12
+
13
+ - Resolved an issue where the `cache` value from parameters was being unintentionally overwritten by the default value for `getProductsByCategory` rpc.
14
+
3
15
  ## 7.65.5
4
16
 
5
17
  ### Patch Changes
@@ -337,8 +349,8 @@
337
349
 
338
350
  ```ts
339
351
  const { data: externalIDPRedirects } = await useIDP({
340
- queryParams: { redirectTo: '/account' },
341
- })
352
+ queryParams: { redirectTo: "/account" },
353
+ });
342
354
  ```
343
355
 
344
356
  Please note that `code` and `state` are not supported as these are used by the SCAYLE Authentication API.
@@ -955,7 +967,7 @@
955
967
 
956
968
  ```js
957
969
  env: {
958
- SFC_OMIT_MD5: true
970
+ SFC_OMIT_MD5: true;
959
971
  }
960
972
  ```
961
973
 
@@ -963,7 +975,7 @@
963
975
 
964
976
  ```js
965
977
  env: {
966
- SFC_OMIT_MD5: process.env.SFC_OMIT_MD5
978
+ SFC_OMIT_MD5: process.env.SFC_OMIT_MD5;
967
979
  }
968
980
  ```
969
981
 
@@ -1001,7 +1013,7 @@
1001
1013
 
1002
1014
  ```js
1003
1015
  env: {
1004
- SFC_OMIT_MD5: true
1016
+ SFC_OMIT_MD5: true;
1005
1017
  }
1006
1018
  ```
1007
1019
 
@@ -1009,7 +1021,7 @@
1009
1021
 
1010
1022
  ```js
1011
1023
  env: {
1012
- SFC_OMIT_MD5: process.env.SFC_OMIT_MD5
1024
+ SFC_OMIT_MD5: process.env.SFC_OMIT_MD5;
1013
1025
  }
1014
1026
  ```
1015
1027
 
@@ -34,18 +34,29 @@ class CustomerAPIClient {
34
34
  if ((response.status === _httpStatus.HttpStatusCode.UNAUTHORIZED && response.headers.get("WWW-Authenticate")?.includes("invalid_token") || response.status === _httpStatus.HttpStatusCode.FORBIDDEN) && this.context.accessToken && this.context.refreshToken) {
35
35
  if (retry) {
36
36
  const client = (0, _oauth.getOAuthClient)(this.context);
37
- const tokens = await client.refreshToken({
38
- grant_type: "refresh_token",
39
- refresh_token: this.context.refreshToken
40
- });
41
- this.context.updateTokens({
42
- accessToken: tokens?.access_token,
43
- refreshToken: tokens?.refresh_token
44
- });
37
+ try {
38
+ const tokens = await client.refreshToken({
39
+ grant_type: "refresh_token",
40
+ refresh_token: this.context.refreshToken
41
+ });
42
+ this.context.updateTokens({
43
+ accessToken: tokens?.access_token,
44
+ refreshToken: tokens?.refresh_token
45
+ });
46
+ } catch (e) {
47
+ if (e instanceof _fetch.FetchError && e.response.status === _httpStatus.HttpStatusCode.UNAUTHORIZED) {
48
+ this.context.log.debug("Failed to refresh Checkout Token due to invalid refresh token. Deleting session");
49
+ await this.context.destroySession();
50
+ } else {
51
+ this.context.log.debug("Failed to refresh Checkout Token for unknown reason.");
52
+ }
53
+ throw new _fetch.FetchError(response);
54
+ }
45
55
  return await this.sendRequest(request, false);
56
+ } else {
57
+ this.context.log.debug("Invalid Checkout Token. Deleting session");
58
+ await this.context.destroySession();
46
59
  }
47
- this.context.log.debug("Invalid Checkout Token. Deleting session");
48
- await this.context.destroySession();
49
60
  }
50
61
  throw new _fetch.FetchError(response);
51
62
  }
@@ -37,7 +37,7 @@ interface PasswordUpdate {
37
37
  export declare class CustomerAPIClient {
38
38
  baseURL: string;
39
39
  context: RpcContext;
40
- private additionalHeaders;
40
+ additionalHeaders: HeadersInit | undefined;
41
41
  constructor(context: RpcContext);
42
42
  get headers(): HeadersInit;
43
43
  sendRequest<BodyType>(request: () => Promise<Response>, retry?: boolean): Promise<BodyType>;
@@ -28,18 +28,33 @@ export class CustomerAPIClient {
28
28
  ) || response.status === HttpStatusCode.FORBIDDEN) && this.context.accessToken && this.context.refreshToken) {
29
29
  if (retry) {
30
30
  const client = getOAuthClient(this.context);
31
- const tokens = await client.refreshToken({
32
- grant_type: "refresh_token",
33
- refresh_token: this.context.refreshToken
34
- });
35
- this.context.updateTokens({
36
- accessToken: tokens?.access_token,
37
- refreshToken: tokens?.refresh_token
38
- });
31
+ try {
32
+ const tokens = await client.refreshToken({
33
+ grant_type: "refresh_token",
34
+ refresh_token: this.context.refreshToken
35
+ });
36
+ this.context.updateTokens({
37
+ accessToken: tokens?.access_token,
38
+ refreshToken: tokens?.refresh_token
39
+ });
40
+ } catch (e) {
41
+ if (e instanceof FetchError && e.response.status === HttpStatusCode.UNAUTHORIZED) {
42
+ this.context.log.debug(
43
+ "Failed to refresh Checkout Token due to invalid refresh token. Deleting session"
44
+ );
45
+ await this.context.destroySession();
46
+ } else {
47
+ this.context.log.debug(
48
+ "Failed to refresh Checkout Token for unknown reason."
49
+ );
50
+ }
51
+ throw new FetchError(response);
52
+ }
39
53
  return await this.sendRequest(request, false);
54
+ } else {
55
+ this.context.log.debug("Invalid Checkout Token. Deleting session");
56
+ await this.context.destroySession();
40
57
  }
41
- this.context.log.debug("Invalid Checkout Token. Deleting session");
42
- await this.context.destroySession();
43
58
  }
44
59
  throw new FetchError(response);
45
60
  }
@@ -109,7 +109,9 @@ exports.getActiveFilters = getActiveFilters;
109
109
  const groupFiltersByKey = filters => {
110
110
  const groupedFilters = filters.reduce((acc, item) => {
111
111
  const groupId = item.key;
112
- if (!acc[groupId]) acc[groupId] = [];
112
+ if (!acc[groupId]) {
113
+ acc[groupId] = [];
114
+ }
113
115
  acc[groupId].push(item);
114
116
  return acc;
115
117
  }, {});
@@ -97,7 +97,9 @@ export const getActiveFilters = (filters, activeFilters) => {
97
97
  export const groupFiltersByKey = (filters) => {
98
98
  const groupedFilters = filters.reduce((acc, item) => {
99
99
  const groupId = item.key;
100
- if (!acc[groupId]) acc[groupId] = [];
100
+ if (!acc[groupId]) {
101
+ acc[groupId] = [];
102
+ }
101
103
  acc[groupId].push(item);
102
104
  return acc;
103
105
  }, {});
@@ -37,7 +37,7 @@ const getCheckoutToken = exports.getCheckoutToken = async function getCheckoutTo
37
37
  carrier,
38
38
  basketId: context.basketKey,
39
39
  campaignKey: context.campaignKey
40
- }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.5"}`).setProtectedHeader({
40
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.7"}`).setProtectedHeader({
41
41
  alg: "HS256",
42
42
  typ: "JWT"
43
43
  }).sign(secret);
@@ -35,7 +35,7 @@ export const getCheckoutToken = async function getCheckoutToken2(jwtPayload = {}
35
35
  carrier,
36
36
  basketId: context.basketKey,
37
37
  campaignKey: context.campaignKey
38
- }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.5"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
38
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.7"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
39
39
  return {
40
40
  accessToken: refreshedAccessToken,
41
41
  checkoutJwt
@@ -269,8 +269,8 @@ const getProductsByCategory = exports.getProductsByCategory = async function get
269
269
  pagination
270
270
  } = await cached(bapiClient.products.query, {
271
271
  ...cache,
272
- ttl: 15 * _cache.MINUTE,
273
- cacheKeyPrefix: `products-query-category-${category === "/" ? "root" : categoryId}`
272
+ ttl: cache?.ttl ?? 15 * _cache.MINUTE,
273
+ cacheKeyPrefix: cache?.cacheKeyPrefix || `products-query-category-${category === "/" ? "root" : categoryId}`
274
274
  })({
275
275
  where: {
276
276
  categoryId,
@@ -249,8 +249,8 @@ export const getProductsByCategory = async function getProductsByCategory2(param
249
249
  bapiClient.products.query,
250
250
  {
251
251
  ...cache,
252
- ttl: 15 * MINUTE,
253
- cacheKeyPrefix: `products-query-category-${category === "/" ? "root" : categoryId}`
252
+ ttl: cache?.ttl ?? 15 * MINUTE,
253
+ cacheKeyPrefix: cache?.cacheKeyPrefix || `products-query-category-${category === "/" ? "root" : categoryId}`
254
254
  }
255
255
  )({
256
256
  where: {
@@ -143,6 +143,12 @@ const refreshAccessToken = async context => {
143
143
  };
144
144
  } catch (error) {
145
145
  const res = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED]);
146
+ if (res && res.status === _constants.HttpStatusCode.UNAUTHORIZED) {
147
+ context.log.debug("Failed to refresh Checkout Token due to invalid refresh token. Deleting session");
148
+ await context.destroySession();
149
+ } else {
150
+ context.log.debug("Failed to refresh Checkout Token for unknown reason.");
151
+ }
146
152
  if (res) {
147
153
  return res;
148
154
  }
@@ -190,6 +190,16 @@ export const refreshAccessToken = async (context) => {
190
190
  HttpStatusCode.BAD_REQUEST,
191
191
  HttpStatusCode.UNAUTHORIZED
192
192
  ]);
193
+ if (res && res.status === HttpStatusCode.UNAUTHORIZED) {
194
+ context.log.debug(
195
+ "Failed to refresh Checkout Token due to invalid refresh token. Deleting session"
196
+ );
197
+ await context.destroySession();
198
+ } else {
199
+ context.log.debug(
200
+ "Failed to refresh Checkout Token for unknown reason."
201
+ );
202
+ }
193
203
  if (res) {
194
204
  return res;
195
205
  }
@@ -9,6 +9,7 @@ var _customer = require("../../api/customer.cjs");
9
9
  var _oauth = require("../../api/oauth.cjs");
10
10
  var _constants = require("../../constants/index.cjs");
11
11
  var _errors = require("../../errors/index.cjs");
12
+ var _fetch = require("../../utils/fetch.cjs");
12
13
  const getUser = exports.getUser = function getUser2(context) {
13
14
  const {
14
15
  user,
@@ -84,18 +85,31 @@ const getAccessToken = exports.getAccessToken = async function getAccessToken2({
84
85
  return new _errors.ErrorResponse(_constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusMessage.UNAUTHORIZED, "No refresh token present");
85
86
  }
86
87
  const client = (0, _oauth.getOAuthClient)(context);
87
- const tokens = await client.refreshToken({
88
- grant_type: "refresh_token",
89
- refresh_token: context.refreshToken
90
- });
91
- context.updateTokens({
92
- accessToken: tokens.access_token,
93
- refreshToken: tokens.refresh_token
94
- });
95
- const user = await fetchUser({
96
- accessToken: tokens.access_token
97
- }, context);
98
- context.updateUser(user);
88
+ try {
89
+ const tokens = await client.refreshToken({
90
+ grant_type: "refresh_token",
91
+ refresh_token: context.refreshToken
92
+ });
93
+ context.updateTokens({
94
+ accessToken: tokens.access_token,
95
+ refreshToken: tokens.refresh_token
96
+ });
97
+ try {
98
+ const user = await fetchUser({
99
+ accessToken: tokens.access_token
100
+ }, context);
101
+ context.updateUser(user);
102
+ } catch {
103
+ context.log.debug("Failed to update user");
104
+ }
105
+ } catch (e) {
106
+ if (e instanceof _fetch.FetchError && e.response.status === _constants.HttpStatusCode.UNAUTHORIZED) {
107
+ context.log.debug("Failed to refresh Checkout Token due to invalid refresh token. Deleting session");
108
+ await context.destroySession();
109
+ } else {
110
+ context.log.debug("Failed to refresh Checkout Token for unknown reason.");
111
+ }
112
+ }
99
113
  }
100
114
  return context.accessToken;
101
115
  };
@@ -3,6 +3,7 @@ import { CustomerAPIClient } from "../../api/customer.mjs";
3
3
  import { getOAuthClient } from "../../api/oauth.mjs";
4
4
  import { HttpStatusCode, HttpStatusMessage } from "../../constants/index.mjs";
5
5
  import { ErrorResponse } from "../../errors/index.mjs";
6
+ import { FetchError } from "../../utils/fetch.mjs";
6
7
  const getUser = function getUser2(context) {
7
8
  const { user, accessToken, shopId } = context;
8
9
  if (user) {
@@ -74,19 +75,36 @@ const getAccessToken = async function getAccessToken2({ forceTokenRefresh = fals
74
75
  );
75
76
  }
76
77
  const client = getOAuthClient(context);
77
- const tokens = await client.refreshToken({
78
- grant_type: "refresh_token",
79
- refresh_token: context.refreshToken
80
- });
81
- context.updateTokens({
82
- accessToken: tokens.access_token,
83
- refreshToken: tokens.refresh_token
84
- });
85
- const user = await fetchUser(
86
- { accessToken: tokens.access_token },
87
- context
88
- );
89
- context.updateUser(user);
78
+ try {
79
+ const tokens = await client.refreshToken({
80
+ grant_type: "refresh_token",
81
+ refresh_token: context.refreshToken
82
+ });
83
+ context.updateTokens({
84
+ accessToken: tokens.access_token,
85
+ refreshToken: tokens.refresh_token
86
+ });
87
+ try {
88
+ const user = await fetchUser(
89
+ { accessToken: tokens.access_token },
90
+ context
91
+ );
92
+ context.updateUser(user);
93
+ } catch {
94
+ context.log.debug("Failed to update user");
95
+ }
96
+ } catch (e) {
97
+ if (e instanceof FetchError && e.response.status === HttpStatusCode.UNAUTHORIZED) {
98
+ context.log.debug(
99
+ "Failed to refresh Checkout Token due to invalid refresh token. Deleting session"
100
+ );
101
+ await context.destroySession();
102
+ } else {
103
+ context.log.debug(
104
+ "Failed to refresh Checkout Token for unknown reason."
105
+ );
106
+ }
107
+ }
90
108
  }
91
109
  return context.accessToken;
92
110
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scayle/storefront-core",
3
- "version": "7.65.5",
3
+ "version": "7.65.7",
4
4
  "description": "Collection of essential utilities to work with the Storefront API",
5
5
  "author": "SCAYLE Commerce Engine",
6
6
  "license": "MIT",
@@ -56,7 +56,7 @@
56
56
  "package:lint": "publint",
57
57
  "test:watch": "vitest --passWithNoTests",
58
58
  "test": "vitest --run --passWithNoTests",
59
- "test:ci": "vitest --run --passWithNoTests --coverage --reporter=default --reporter=junit"
59
+ "test:ci": "vitest --run --passWithNoTests --coverage --reporter=default --reporter=junit --outputFile=./junit.xml"
60
60
  },
61
61
  "dependencies": {
62
62
  "@scayle/storefront-api": "17.8.0",
@@ -69,21 +69,21 @@
69
69
  "utility-types": "^3.11.0"
70
70
  },
71
71
  "devDependencies": {
72
- "@scayle/eslint-config-storefront": "4.3.0",
72
+ "@scayle/eslint-config-storefront": "4.3.2",
73
73
  "@types/crypto-js": "4.2.2",
74
- "@types/node": "20.16.10",
74
+ "@types/node": "20.16.12",
75
75
  "@types/webpack-env": "1.18.5",
76
- "@vitest/coverage-v8": "2.1.1",
76
+ "@vitest/coverage-v8": "2.1.3",
77
77
  "dprint": "0.47.2",
78
- "eslint": "9.11.1",
78
+ "eslint": "9.12.0",
79
79
  "eslint-formatter-gitlab": "5.1.0",
80
80
  "publint": "0.2.11",
81
81
  "rimraf": "6.0.1",
82
82
  "ts-node": "10.9.2",
83
- "typescript": "5.6.2",
83
+ "typescript": "5.6.3",
84
84
  "unbuild": "2.0.0",
85
85
  "unstorage": "1.12.0",
86
- "vitest": "2.1.1"
86
+ "vitest": "2.1.3"
87
87
  },
88
88
  "optionalDependencies": {
89
89
  "redis": "4"