@scayle/storefront-core 7.65.4 → 7.65.6

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,21 @@
1
1
  # @scayle/storefront-core
2
2
 
3
+ ## 7.65.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Resolved an issue where the `cache` value from parameters was being unintentionally overwritten by the default value for `getProductsByCategory` rpc.
8
+
9
+ ## 7.65.5
10
+
11
+ ### Patch Changes
12
+
13
+ - Support passing an internal access header
14
+ - Make `getProductsCount`, `getFilters` and `getProductsByCategory` RPC methods handle their parameters consistently
15
+ **Dependencies**
16
+
17
+ - Updated dependency to @scayle/storefront-api@17.8.0
18
+
3
19
  ## 7.65.4
4
20
 
5
21
  ### Patch Changes
@@ -10,15 +10,20 @@ var _oauth = require("./oauth.cjs");
10
10
  class CustomerAPIClient {
11
11
  baseURL;
12
12
  context;
13
+ additionalHeaders;
13
14
  constructor(context) {
14
15
  this.baseURL = context.checkout.url;
15
16
  this.context = context;
17
+ this.additionalHeaders = context.internalAccessHeader ? {
18
+ "x-internal-access": context.internalAccessHeader
19
+ } : {};
16
20
  }
17
21
  get headers() {
18
22
  return {
19
23
  Authorization: `Bearer ${this.context.accessToken}`,
20
24
  Accept: "application/json",
21
- "Content-Type": "application/json"
25
+ "Content-Type": "application/json",
26
+ ...this.additionalHeaders
22
27
  };
23
28
  }
24
29
  async sendRequest(request, retry = true) {
@@ -37,6 +37,7 @@ interface PasswordUpdate {
37
37
  export declare class CustomerAPIClient {
38
38
  baseURL: string;
39
39
  context: RpcContext;
40
+ private additionalHeaders;
40
41
  constructor(context: RpcContext);
41
42
  get headers(): HeadersInit;
42
43
  sendRequest<BodyType>(request: () => Promise<Response>, retry?: boolean): Promise<BodyType>;
@@ -4,15 +4,18 @@ import { getOAuthClient } from "./oauth.mjs";
4
4
  export class CustomerAPIClient {
5
5
  baseURL;
6
6
  context;
7
+ additionalHeaders;
7
8
  constructor(context) {
8
9
  this.baseURL = context.checkout.url;
9
10
  this.context = context;
11
+ this.additionalHeaders = context.internalAccessHeader ? { "x-internal-access": context.internalAccessHeader } : {};
10
12
  }
11
13
  get headers() {
12
14
  return {
13
15
  Authorization: `Bearer ${this.context.accessToken}`,
14
16
  Accept: "application/json",
15
- "Content-Type": "application/json"
17
+ "Content-Type": "application/json",
18
+ ...this.additionalHeaders
16
19
  };
17
20
  }
18
21
  async sendRequest(request, retry = true) {
@@ -33,10 +33,14 @@ function getOAuthClient(context) {
33
33
  const clientId = context.oauth.clientId;
34
34
  const clientSecret = context.oauth.clientSecret;
35
35
  const apiHost = context.oauth.apiHost;
36
+ const accessHeader = context.internalAccessHeader;
36
37
  return new OAuthClient({
37
38
  clientId,
38
39
  clientSecret,
39
- apiHost
40
+ apiHost,
41
+ additionalHeaders: accessHeader ? {
42
+ "x-internal-access": accessHeader
43
+ } : {}
40
44
  }, context.log);
41
45
  }
42
46
  class OAuthClient {
@@ -48,7 +52,8 @@ class OAuthClient {
48
52
  const {
49
53
  clientId,
50
54
  clientSecret,
51
- apiHost
55
+ apiHost,
56
+ additionalHeaders
52
57
  } = options;
53
58
  if (!clientId || !clientSecret) {
54
59
  throw new MissingCredentialsError();
@@ -60,7 +65,8 @@ class OAuthClient {
60
65
  this.headers = {
61
66
  Authorization: `Basic ${basicAuthHash}`,
62
67
  Accept: "application/json",
63
- "Content-Type": "application/json"
68
+ "Content-Type": "application/json",
69
+ ...additionalHeaders
64
70
  };
65
71
  }
66
72
  /**
@@ -5,6 +5,7 @@ export interface OAuthOptions {
5
5
  clientId: string;
6
6
  clientSecret: string;
7
7
  apiHost: string;
8
+ additionalHeaders?: HeadersInit;
8
9
  }
9
10
  export declare function getOAuthClient(context: RpcContext): OAuthClient;
10
11
  /**
@@ -26,7 +26,13 @@ export function getOAuthClient(context) {
26
26
  const clientId = context.oauth.clientId;
27
27
  const clientSecret = context.oauth.clientSecret;
28
28
  const apiHost = context.oauth.apiHost;
29
- return new OAuthClient({ clientId, clientSecret, apiHost }, context.log);
29
+ const accessHeader = context.internalAccessHeader;
30
+ return new OAuthClient({
31
+ clientId,
32
+ clientSecret,
33
+ apiHost,
34
+ additionalHeaders: accessHeader ? { "x-internal-access": accessHeader } : {}
35
+ }, context.log);
30
36
  }
31
37
  export class OAuthClient {
32
38
  headers;
@@ -34,7 +40,7 @@ export class OAuthClient {
34
40
  logger;
35
41
  clientId;
36
42
  constructor(options, logger) {
37
- const { clientId, clientSecret, apiHost } = options;
43
+ const { clientId, clientSecret, apiHost, additionalHeaders } = options;
38
44
  if (!clientId || !clientSecret) {
39
45
  throw new MissingCredentialsError();
40
46
  }
@@ -45,7 +51,8 @@ export class OAuthClient {
45
51
  this.headers = {
46
52
  Authorization: `Basic ${basicAuthHash}`,
47
53
  Accept: "application/json",
48
- "Content-Type": "application/json"
54
+ "Content-Type": "application/json",
55
+ ...additionalHeaders
49
56
  };
50
57
  }
51
58
  /**
@@ -12,7 +12,8 @@ const init = config => {
12
12
  auth: {
13
13
  type: config.authentication,
14
14
  token: config.token
15
- }
15
+ },
16
+ additionalHeaders: config.additionalHeaders
16
17
  });
17
18
  };
18
19
  exports.init = init;
@@ -4,6 +4,7 @@ interface StorefrontAPIConfig {
4
4
  shopId: number;
5
5
  authentication: 'token';
6
6
  token: string;
7
+ additionalHeaders: HeadersInit;
7
8
  }
8
9
  /**
9
10
  * Create a new Storefront API Client.
@@ -6,6 +6,7 @@ export const init = (config) => {
6
6
  auth: {
7
7
  type: config.authentication,
8
8
  token: config.token
9
- }
9
+ },
10
+ additionalHeaders: config.additionalHeaders
10
11
  });
11
12
  };
@@ -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.4"}`).setProtectedHeader({
40
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.6"}`).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.4"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
38
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.6"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
39
39
  return {
40
40
  accessToken: refreshedAccessToken,
41
41
  checkoutJwt
@@ -3,9 +3,61 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ var _exportNames = {
7
+ getProductById: true,
8
+ getProductsByIds: true,
9
+ getProductsByReferenceKeys: true,
10
+ getProductsCount: true,
11
+ fetchAllFiltersForCategory: true,
12
+ getFilters: true,
13
+ getProductsByCategory: true
14
+ };
15
+ Object.defineProperty(exports, "fetchAllFiltersForCategory", {
16
+ enumerable: true,
17
+ get: function () {
18
+ return _products.fetchAllFiltersForCategory;
19
+ }
20
+ });
21
+ Object.defineProperty(exports, "getFilters", {
22
+ enumerable: true,
23
+ get: function () {
24
+ return _products.getFilters;
25
+ }
26
+ });
27
+ Object.defineProperty(exports, "getProductById", {
28
+ enumerable: true,
29
+ get: function () {
30
+ return _products.getProductById;
31
+ }
32
+ });
33
+ Object.defineProperty(exports, "getProductsByCategory", {
34
+ enumerable: true,
35
+ get: function () {
36
+ return _products.getProductsByCategory;
37
+ }
38
+ });
39
+ Object.defineProperty(exports, "getProductsByIds", {
40
+ enumerable: true,
41
+ get: function () {
42
+ return _products.getProductsByIds;
43
+ }
44
+ });
45
+ Object.defineProperty(exports, "getProductsByReferenceKeys", {
46
+ enumerable: true,
47
+ get: function () {
48
+ return _products.getProductsByReferenceKeys;
49
+ }
50
+ });
51
+ Object.defineProperty(exports, "getProductsCount", {
52
+ enumerable: true,
53
+ get: function () {
54
+ return _products.getProductsCount;
55
+ }
56
+ });
6
57
  var _basket = require("./basket/basket.cjs");
7
58
  Object.keys(_basket).forEach(function (key) {
8
59
  if (key === "default" || key === "__esModule") return;
60
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
9
61
  if (key in exports && exports[key] === _basket[key]) return;
10
62
  Object.defineProperty(exports, key, {
11
63
  enumerable: true,
@@ -17,6 +69,7 @@ Object.keys(_basket).forEach(function (key) {
17
69
  var _brands = require("./brands.cjs");
18
70
  Object.keys(_brands).forEach(function (key) {
19
71
  if (key === "default" || key === "__esModule") return;
72
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
20
73
  if (key in exports && exports[key] === _brands[key]) return;
21
74
  Object.defineProperty(exports, key, {
22
75
  enumerable: true,
@@ -28,6 +81,7 @@ Object.keys(_brands).forEach(function (key) {
28
81
  var _categories = require("./categories.cjs");
29
82
  Object.keys(_categories).forEach(function (key) {
30
83
  if (key === "default" || key === "__esModule") return;
84
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
31
85
  if (key in exports && exports[key] === _categories[key]) return;
32
86
  Object.defineProperty(exports, key, {
33
87
  enumerable: true,
@@ -39,6 +93,7 @@ Object.keys(_categories).forEach(function (key) {
39
93
  var _cbd = require("./cbd.cjs");
40
94
  Object.keys(_cbd).forEach(function (key) {
41
95
  if (key === "default" || key === "__esModule") return;
96
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
42
97
  if (key in exports && exports[key] === _cbd[key]) return;
43
98
  Object.defineProperty(exports, key, {
44
99
  enumerable: true,
@@ -48,19 +103,10 @@ Object.keys(_cbd).forEach(function (key) {
48
103
  });
49
104
  });
50
105
  var _products = require("./products.cjs");
51
- Object.keys(_products).forEach(function (key) {
52
- if (key === "default" || key === "__esModule") return;
53
- if (key in exports && exports[key] === _products[key]) return;
54
- Object.defineProperty(exports, key, {
55
- enumerable: true,
56
- get: function () {
57
- return _products[key];
58
- }
59
- });
60
- });
61
106
  var _search = require("./search.cjs");
62
107
  Object.keys(_search).forEach(function (key) {
63
108
  if (key === "default" || key === "__esModule") return;
109
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
64
110
  if (key in exports && exports[key] === _search[key]) return;
65
111
  Object.defineProperty(exports, key, {
66
112
  enumerable: true,
@@ -72,6 +118,7 @@ Object.keys(_search).forEach(function (key) {
72
118
  var _shopConfiguration = require("./shopConfiguration.cjs");
73
119
  Object.keys(_shopConfiguration).forEach(function (key) {
74
120
  if (key === "default" || key === "__esModule") return;
121
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
75
122
  if (key in exports && exports[key] === _shopConfiguration[key]) return;
76
123
  Object.defineProperty(exports, key, {
77
124
  enumerable: true,
@@ -83,6 +130,7 @@ Object.keys(_shopConfiguration).forEach(function (key) {
83
130
  var _user = require("./user.cjs");
84
131
  Object.keys(_user).forEach(function (key) {
85
132
  if (key === "default" || key === "__esModule") return;
133
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
86
134
  if (key in exports && exports[key] === _user[key]) return;
87
135
  Object.defineProperty(exports, key, {
88
136
  enumerable: true,
@@ -94,6 +142,7 @@ Object.keys(_user).forEach(function (key) {
94
142
  var _wishlist = require("./wishlist.cjs");
95
143
  Object.keys(_wishlist).forEach(function (key) {
96
144
  if (key === "default" || key === "__esModule") return;
145
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
97
146
  if (key in exports && exports[key] === _wishlist[key]) return;
98
147
  Object.defineProperty(exports, key, {
99
148
  enumerable: true,
@@ -105,6 +154,7 @@ Object.keys(_wishlist).forEach(function (key) {
105
154
  var _checkout = require("./checkout/index.cjs");
106
155
  Object.keys(_checkout).forEach(function (key) {
107
156
  if (key === "default" || key === "__esModule") return;
157
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
108
158
  if (key in exports && exports[key] === _checkout[key]) return;
109
159
  Object.defineProperty(exports, key, {
110
160
  enumerable: true,
@@ -116,6 +166,7 @@ Object.keys(_checkout).forEach(function (key) {
116
166
  var _variants = require("./variants.cjs");
117
167
  Object.keys(_variants).forEach(function (key) {
118
168
  if (key === "default" || key === "__esModule") return;
169
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
119
170
  if (key in exports && exports[key] === _variants[key]) return;
120
171
  Object.defineProperty(exports, key, {
121
172
  enumerable: true,
@@ -127,6 +178,7 @@ Object.keys(_variants).forEach(function (key) {
127
178
  var _navigationTrees = require("./navigationTrees.cjs");
128
179
  Object.keys(_navigationTrees).forEach(function (key) {
129
180
  if (key === "default" || key === "__esModule") return;
181
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
130
182
  if (key in exports && exports[key] === _navigationTrees[key]) return;
131
183
  Object.defineProperty(exports, key, {
132
184
  enumerable: true,
@@ -138,6 +190,7 @@ Object.keys(_navigationTrees).forEach(function (key) {
138
190
  var _session = require("./session.cjs");
139
191
  Object.keys(_session).forEach(function (key) {
140
192
  if (key === "default" || key === "__esModule") return;
193
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
141
194
  if (key in exports && exports[key] === _session[key]) return;
142
195
  Object.defineProperty(exports, key, {
143
196
  enumerable: true,
@@ -149,6 +202,7 @@ Object.keys(_session).forEach(function (key) {
149
202
  var _promotion = require("./promotion.cjs");
150
203
  Object.keys(_promotion).forEach(function (key) {
151
204
  if (key === "default" || key === "__esModule") return;
205
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
152
206
  if (key in exports && exports[key] === _promotion[key]) return;
153
207
  Object.defineProperty(exports, key, {
154
208
  enumerable: true,
@@ -160,6 +214,7 @@ Object.keys(_promotion).forEach(function (key) {
160
214
  var _idp = require("./oauth/idp.cjs");
161
215
  Object.keys(_idp).forEach(function (key) {
162
216
  if (key === "default" || key === "__esModule") return;
217
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
163
218
  if (key in exports && exports[key] === _idp[key]) return;
164
219
  Object.defineProperty(exports, key, {
165
220
  enumerable: true,
@@ -2,7 +2,7 @@ export * from './basket/basket';
2
2
  export * from './brands';
3
3
  export * from './categories';
4
4
  export * from './cbd';
5
- export * from './products';
5
+ export { getProductById, getProductsByIds, getProductsByReferenceKeys, getProductsCount, fetchAllFiltersForCategory, getFilters, getProductsByCategory, } from './products';
6
6
  export * from './search';
7
7
  export * from './shopConfiguration';
8
8
  export * from './user';
@@ -2,7 +2,15 @@ export * from "./basket/basket.mjs";
2
2
  export * from "./brands.mjs";
3
3
  export * from "./categories.mjs";
4
4
  export * from "./cbd.mjs";
5
- export * from "./products.mjs";
5
+ export {
6
+ getProductById,
7
+ getProductsByIds,
8
+ getProductsByReferenceKeys,
9
+ getProductsCount,
10
+ fetchAllFiltersForCategory,
11
+ getFilters,
12
+ getProductsByCategory
13
+ } from "./products.mjs";
6
14
  export * from "./search.mjs";
7
15
  export * from "./shopConfiguration.mjs";
8
16
  export * from "./user.mjs";
@@ -90,6 +90,7 @@ const getProductsByReferenceKeys = exports.getProductsByReferenceKeys = async fu
90
90
  };
91
91
  const getProductsCount = exports.getProductsCount = async function getProductsCount2(params, context) {
92
92
  const {
93
+ includedFilters,
93
94
  where = void 0,
94
95
  includeSoldOut = false,
95
96
  includeSellableForFree = false,
@@ -103,6 +104,11 @@ const getProductsCount = exports.getProductsCount = async function getProductsCo
103
104
  const {
104
105
  categoryId
105
106
  } = await resolveCategoryIdFromParams(context, params);
107
+ const response = await getSanitizedAttributes(context, categoryId, where?.attributes || [], includedFilters);
108
+ if (response instanceof _errors.ErrorResponse) {
109
+ return response;
110
+ }
111
+ const sanitizedAttributes = response;
106
112
  const productCount = await cached(bapiClient.products.query, {
107
113
  ttl: 15 * _cache.MINUTE,
108
114
  cacheKeyPrefix: "products-query"
@@ -111,15 +117,16 @@ const getProductsCount = exports.getProductsCount = async function getProductsCo
111
117
  categoryId,
112
118
  minPrice: where?.minPrice,
113
119
  maxPrice: where?.maxPrice,
114
- attributes: where?.attributes,
115
- term: where?.term
120
+ term: where?.term,
121
+ attributes: [...sanitizedAttributes, ...(where?.whitelistAttributes || [])],
122
+ disableFuzziness: where?.disableFuzziness
116
123
  },
117
- includeSoldOut,
118
- includeSellableForFree,
119
- campaignKey,
120
124
  pagination: {
121
125
  perPage: 1
122
126
  },
127
+ campaignKey,
128
+ includeSellableForFree,
129
+ includeSoldOut,
123
130
  orFiltersOperator
124
131
  });
125
132
  return {
@@ -150,6 +157,23 @@ const fetchAllFiltersForCategory = exports.fetchAllFiltersForCategory = async fu
150
157
  cacheKey: `filters-for-category-${category.id}`
151
158
  })();
152
159
  };
160
+ async function getSanitizedAttributes(context, categoryId, attributes, includedFilters) {
161
+ const response = await fetchAllFiltersForCategory({
162
+ category: {
163
+ id: categoryId
164
+ },
165
+ includedFilters
166
+ }, context);
167
+ if (response instanceof _errors.ErrorResponse) {
168
+ return response;
169
+ }
170
+ const allFiltersForCategory = await (0, _response.unwrap)(response);
171
+ return sanitizeAttributesForBAPI({
172
+ attributes: attributes || [],
173
+ filterKeys: allFiltersForCategory,
174
+ includedFilters
175
+ });
176
+ }
153
177
  const getFilters = exports.getFilters = async function getFilters2(params, context) {
154
178
  const {
155
179
  includedFilters,
@@ -167,21 +191,11 @@ const getFilters = exports.getFilters = async function getFilters2(params, conte
167
191
  category,
168
192
  categoryId
169
193
  } = await resolveCategoryIdFromParams(context, params);
170
- const response = await fetchAllFiltersForCategory({
171
- category: {
172
- id: categoryId
173
- },
174
- includedFilters
175
- }, context);
194
+ const response = await getSanitizedAttributes(context, categoryId, where?.attributes || [], includedFilters);
176
195
  if (response instanceof _errors.ErrorResponse) {
177
196
  return response;
178
197
  }
179
- const allFiltersForCategory = await (0, _response.unwrap)(response);
180
- const sanitizedAttributes = sanitizeAttributesForBAPI({
181
- attributes: where?.attributes || [],
182
- filterKeys: allFiltersForCategory,
183
- includedFilters
184
- });
198
+ const sanitizedAttributes = response;
185
199
  const [filters, productCount] = await Promise.all([cached(bapiClient.filters.get, {
186
200
  cacheKeyPrefix: `get-filters-${categoryId}`
187
201
  })({
@@ -206,14 +220,15 @@ const getFilters = exports.getFilters = async function getFilters2(params, conte
206
220
  minPrice: where?.minPrice,
207
221
  maxPrice: where?.maxPrice,
208
222
  term: where?.term,
209
- attributes: [...sanitizedAttributes, ...(where?.whitelistAttributes || [])]
223
+ attributes: [...sanitizedAttributes, ...(where?.whitelistAttributes || [])],
224
+ disableFuzziness: where?.disableFuzziness
210
225
  },
211
- includeSoldOut,
212
- includeSellableForFree,
213
- campaignKey,
214
226
  pagination: {
215
227
  perPage: 1
216
228
  },
229
+ campaignKey,
230
+ includeSellableForFree,
231
+ includeSoldOut,
217
232
  orFiltersOperator
218
233
  })]);
219
234
  return {
@@ -223,6 +238,7 @@ const getFilters = exports.getFilters = async function getFilters2(params, conte
223
238
  };
224
239
  const getProductsByCategory = exports.getProductsByCategory = async function getProductsByCategory2(params, context) {
225
240
  const {
241
+ includedFilters,
226
242
  cache,
227
243
  with: _with,
228
244
  perPage = 20,
@@ -243,32 +259,24 @@ const getProductsByCategory = exports.getProductsByCategory = async function get
243
259
  category,
244
260
  categoryId
245
261
  } = await resolveCategoryIdFromParams(context, params);
246
- const response = await fetchAllFiltersForCategory({
247
- category: {
248
- id: categoryId
249
- }
250
- }, context);
262
+ const response = await getSanitizedAttributes(context, categoryId, where?.attributes || [], includedFilters);
251
263
  if (response instanceof _errors.ErrorResponse) {
252
264
  return response;
253
265
  }
254
- const allFiltersForCategory = await (0, _response.unwrap)(response);
255
- const sanitizedAttributes = sanitizeAttributesForBAPI({
256
- attributes: where?.attributes || [],
257
- filterKeys: allFiltersForCategory
258
- });
266
+ const sanitizedAttributes = response;
259
267
  const {
260
268
  entities: products,
261
269
  pagination
262
270
  } = await cached(bapiClient.products.query, {
263
271
  ...cache,
264
- ttl: 15 * _cache.MINUTE,
265
- cacheKeyPrefix: `products-query-category-${category === "/" ? "root" : categoryId}`
272
+ ttl: cache?.ttl ?? 15 * _cache.MINUTE,
273
+ cacheKeyPrefix: cache?.cacheKeyPrefix || `products-query-category-${category === "/" ? "root" : categoryId}`
266
274
  })({
267
275
  where: {
268
- term: where?.term,
269
276
  categoryId,
270
277
  minPrice: where?.minPrice,
271
278
  maxPrice: where?.maxPrice,
279
+ term: where?.term,
272
280
  attributes: [...sanitizedAttributes, ...(where?.whitelistAttributes || [])],
273
281
  disableFuzziness: where?.disableFuzziness
274
282
  },
@@ -277,12 +285,12 @@ const getProductsByCategory = exports.getProductsByCategory = async function get
277
285
  page
278
286
  },
279
287
  campaignKey,
280
- pricePromotionKey,
281
288
  includeSellableForFree,
282
289
  includeSoldOut,
290
+ orFiltersOperator,
291
+ pricePromotionKey,
283
292
  with: _with ?? context.withParams?.product ?? _constants.MIN_WITH_PARAMS_PRODUCT,
284
- sort,
285
- orFiltersOperator
293
+ sort
286
294
  });
287
295
  return {
288
296
  products,
@@ -23,7 +23,7 @@ export declare function resolveCategoryIdFromParams(context: RpcContext, params:
23
23
  export declare const getProductById: (options: FetchProductParams, { bapiClient, cached, campaignKey, withParams }: RpcContext) => Promise<Product>;
24
24
  export declare const getProductsByIds: (options: FetchProductsByIdsParams, { bapiClient, cached, campaignKey, withParams }: RpcContext) => Promise<Product[]>;
25
25
  export declare const getProductsByReferenceKeys: (options: FetchProductsByReferenceKeysParams, { bapiClient, cached, campaignKey, withParams }: RpcContext) => Promise<Product[]>;
26
- export declare const getProductsCount: (params: FetchProductsCountParams, context: RpcContext) => Promise<{
26
+ export declare const getProductsCount: (params: FetchProductsCountParams, context: RpcContext) => Promise<(string[] & ErrorResponse) | {
27
27
  count: number;
28
28
  }>;
29
29
  export declare const fetchAllFiltersForCategory: ({ includedFilters, category }: {
@@ -66,6 +66,7 @@ export const getProductsByReferenceKeys = async function getProductsByReferenceK
66
66
  };
67
67
  export const getProductsCount = async function getProductsCount2(params, context) {
68
68
  const {
69
+ includedFilters,
69
70
  where = void 0,
70
71
  includeSoldOut = false,
71
72
  includeSellableForFree = false,
@@ -73,6 +74,16 @@ export const getProductsCount = async function getProductsCount2(params, context
73
74
  } = params;
74
75
  const { cached, bapiClient, campaignKey } = context;
75
76
  const { categoryId } = await resolveCategoryIdFromParams(context, params);
77
+ const response = await getSanitizedAttributes(
78
+ context,
79
+ categoryId,
80
+ where?.attributes || [],
81
+ includedFilters
82
+ );
83
+ if (response instanceof ErrorResponse) {
84
+ return response;
85
+ }
86
+ const sanitizedAttributes = response;
76
87
  const productCount = await cached(bapiClient.products.query, {
77
88
  ttl: 15 * MINUTE,
78
89
  cacheKeyPrefix: "products-query"
@@ -81,15 +92,19 @@ export const getProductsCount = async function getProductsCount2(params, context
81
92
  categoryId,
82
93
  minPrice: where?.minPrice,
83
94
  maxPrice: where?.maxPrice,
84
- attributes: where?.attributes,
85
- term: where?.term
95
+ term: where?.term,
96
+ attributes: [
97
+ ...sanitizedAttributes,
98
+ ...where?.whitelistAttributes || []
99
+ ],
100
+ disableFuzziness: where?.disableFuzziness
86
101
  },
87
- includeSoldOut,
88
- includeSellableForFree,
89
- campaignKey,
90
102
  pagination: {
91
103
  perPage: 1
92
104
  },
105
+ campaignKey,
106
+ includeSellableForFree,
107
+ includeSoldOut,
93
108
  orFiltersOperator
94
109
  });
95
110
  return {
@@ -111,6 +126,24 @@ export const fetchAllFiltersForCategory = async function fetchAllFiltersForCateg
111
126
  cacheKey: `filters-for-category-${category.id}`
112
127
  })();
113
128
  };
129
+ async function getSanitizedAttributes(context, categoryId, attributes, includedFilters) {
130
+ const response = await fetchAllFiltersForCategory(
131
+ {
132
+ category: { id: categoryId },
133
+ includedFilters
134
+ },
135
+ context
136
+ );
137
+ if (response instanceof ErrorResponse) {
138
+ return response;
139
+ }
140
+ const allFiltersForCategory = await unwrap(response);
141
+ return sanitizeAttributesForBAPI({
142
+ attributes: attributes || [],
143
+ filterKeys: allFiltersForCategory,
144
+ includedFilters
145
+ });
146
+ }
114
147
  export const getFilters = async function getFilters2(params, context) {
115
148
  const {
116
149
  includedFilters,
@@ -124,22 +157,16 @@ export const getFilters = async function getFilters2(params, context) {
124
157
  context,
125
158
  params
126
159
  );
127
- const response = await fetchAllFiltersForCategory(
128
- {
129
- category: { id: categoryId },
130
- includedFilters
131
- },
132
- context
160
+ const response = await getSanitizedAttributes(
161
+ context,
162
+ categoryId,
163
+ where?.attributes || [],
164
+ includedFilters
133
165
  );
134
166
  if (response instanceof ErrorResponse) {
135
167
  return response;
136
168
  }
137
- const allFiltersForCategory = await unwrap(response);
138
- const sanitizedAttributes = sanitizeAttributesForBAPI({
139
- attributes: where?.attributes || [],
140
- filterKeys: allFiltersForCategory,
141
- includedFilters
142
- });
169
+ const sanitizedAttributes = response;
143
170
  const [filters, productCount] = await Promise.all([
144
171
  cached(bapiClient.filters.get, {
145
172
  cacheKeyPrefix: `get-filters-${categoryId}`
@@ -172,14 +199,15 @@ export const getFilters = async function getFilters2(params, context) {
172
199
  attributes: [
173
200
  ...sanitizedAttributes,
174
201
  ...where?.whitelistAttributes || []
175
- ]
202
+ ],
203
+ disableFuzziness: where?.disableFuzziness
176
204
  },
177
- includeSoldOut,
178
- includeSellableForFree,
179
- campaignKey,
180
205
  pagination: {
181
206
  perPage: 1
182
207
  },
208
+ campaignKey,
209
+ includeSellableForFree,
210
+ includeSoldOut,
183
211
  orFiltersOperator
184
212
  })
185
213
  ]);
@@ -190,6 +218,7 @@ export const getFilters = async function getFilters2(params, context) {
190
218
  };
191
219
  export const getProductsByCategory = async function getProductsByCategory2(params, context) {
192
220
  const {
221
+ includedFilters,
193
222
  cache,
194
223
  with: _with,
195
224
  perPage = 20,
@@ -206,35 +235,29 @@ export const getProductsByCategory = async function getProductsByCategory2(param
206
235
  context,
207
236
  params
208
237
  );
209
- const response = await fetchAllFiltersForCategory(
210
- {
211
- category: {
212
- id: categoryId
213
- }
214
- },
215
- context
238
+ const response = await getSanitizedAttributes(
239
+ context,
240
+ categoryId,
241
+ where?.attributes || [],
242
+ includedFilters
216
243
  );
217
244
  if (response instanceof ErrorResponse) {
218
245
  return response;
219
246
  }
220
- const allFiltersForCategory = await unwrap(response);
221
- const sanitizedAttributes = sanitizeAttributesForBAPI({
222
- attributes: where?.attributes || [],
223
- filterKeys: allFiltersForCategory
224
- });
247
+ const sanitizedAttributes = response;
225
248
  const { entities: products, pagination } = await cached(
226
249
  bapiClient.products.query,
227
250
  {
228
251
  ...cache,
229
- ttl: 15 * MINUTE,
230
- cacheKeyPrefix: `products-query-category-${category === "/" ? "root" : categoryId}`
252
+ ttl: cache?.ttl ?? 15 * MINUTE,
253
+ cacheKeyPrefix: cache?.cacheKeyPrefix || `products-query-category-${category === "/" ? "root" : categoryId}`
231
254
  }
232
255
  )({
233
256
  where: {
234
- term: where?.term,
235
257
  categoryId,
236
258
  minPrice: where?.minPrice,
237
259
  maxPrice: where?.maxPrice,
260
+ term: where?.term,
238
261
  attributes: [
239
262
  ...sanitizedAttributes,
240
263
  ...where?.whitelistAttributes || []
@@ -246,12 +269,12 @@ export const getProductsByCategory = async function getProductsByCategory2(param
246
269
  page
247
270
  },
248
271
  campaignKey,
249
- pricePromotionKey,
250
272
  includeSellableForFree,
251
273
  includeSoldOut,
274
+ orFiltersOperator,
275
+ pricePromotionKey,
252
276
  with: _with ?? context.withParams?.product ?? MIN_WITH_PARAMS_PRODUCT,
253
- sort,
254
- orFiltersOperator
277
+ sort
255
278
  });
256
279
  return {
257
280
  products,
@@ -107,6 +107,7 @@ export type RpcContext = {
107
107
  runtimeConfiguration: RuntimeConfiguration;
108
108
  idp?: IDPConfig;
109
109
  headers: Headers;
110
+ internalAccessHeader?: string;
110
111
  callHook?: Hookable<StorefrontHooks>['callHook'];
111
112
  callHookParallel?: Hookable<StorefrontHooks>['callHookParallel'];
112
113
  callHookWith?: Hookable<StorefrontHooks>['callHookWith'];
@@ -22,6 +22,7 @@ export type FetchFiltersParams = {
22
22
  minPrice?: ProductSearchQuery['minPrice'];
23
23
  maxPrice?: ProductSearchQuery['maxPrice'];
24
24
  attributes?: ProductSearchQuery['attributes'];
25
+ disableFuzziness?: ProductSearchQuery['disableFuzziness'];
25
26
  whitelistAttributes?: ProductSearchQuery['attributes'];
26
27
  };
27
28
  includeSoldOut?: boolean;
@@ -79,7 +79,10 @@ export type FetchProductsCountParams = {
79
79
  minPrice?: ProductSearchQuery['minPrice'];
80
80
  maxPrice?: ProductSearchQuery['maxPrice'];
81
81
  attributes?: ProductSearchQuery['attributes'];
82
+ disableFuzziness?: ProductSearchQuery['disableFuzziness'];
83
+ whitelistAttributes?: ProductSearchQuery['attributes'];
82
84
  };
85
+ includedFilters?: Array<string>;
83
86
  includeSoldOut?: boolean;
84
87
  includeSellableForFree?: boolean;
85
88
  orFiltersOperator?: ProductsSearchEndpointParameters['orFiltersOperator'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scayle/storefront-core",
3
- "version": "7.65.4",
3
+ "version": "7.65.6",
4
4
  "description": "Collection of essential utilities to work with the Storefront API",
5
5
  "author": "SCAYLE Commerce Engine",
6
6
  "license": "MIT",
@@ -56,10 +56,10 @@
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
- "@scayle/storefront-api": "17.7.0",
62
+ "@scayle/storefront-api": "17.8.0",
63
63
  "crypto-js": "^4.2.0",
64
64
  "hookable": "^5.5.3",
65
65
  "jose": "^5.6.3",
@@ -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.6",
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"