@scayle/storefront-core 8.35.0 → 8.37.0

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,29 @@
1
1
  # @scayle/storefront-core
2
2
 
3
+ ## 8.37.0
4
+
5
+ ### Minor Changes
6
+
7
+ - The `where` parameter for the `getProductsByCategory` and `getProductsCount` RPCs was extended to include the previously missing options `sellableAt`, `hasCampaignReduction`, and `containsSearch`.
8
+
9
+ ### Patch Changes
10
+
11
+ - Added missing export of the RPC `getCampaign`
12
+
13
+ ## 8.36.0
14
+
15
+ ### Minor Changes
16
+
17
+ - Created a new RPC method `getCampaign` to retrieve the first active campaign.
18
+
19
+ More details can be found in the official SCAYLE Resource Center under [API Guides / Storefront API / Campaigns / List Campaigns](https://scayle.dev/en/api-guides/storefront-api/resources/campaigns/list-campaigns).
20
+
21
+ ### Patch Changes
22
+
23
+ **Dependencies**
24
+
25
+ - Updated dependency to @scayle/storefront-api@18.11.0
26
+
3
27
  ## 8.35.0
4
28
 
5
29
  ### Minor Changes
@@ -1,4 +1,15 @@
1
+ import type { Campaign } from '@scayle/storefront-api';
1
2
  import type { RpcHandler } from '../../types';
3
+ /**
4
+ * Retrieves the active campaign.
5
+ *
6
+ * This RPC method retrieves the active campaign.
7
+ * It then returns the first active campaign.
8
+ *
9
+ * @param context The RPC Context
10
+ * @returns The current active campaign.
11
+ */
12
+ export declare const getCampaign: RpcHandler<Campaign | undefined>;
2
13
  /**
3
14
  * Retrieves the active campaign key.
4
15
  *
@@ -6,11 +17,6 @@ import type { RpcHandler } from '../../types';
6
17
  * for an existing `campaignKey`. If not present, it fetches active campaigns from the SAPI
7
18
  * `list-campaigns` endpoint using the `sapiClient`, caching the result for 5 minutes.
8
19
  *
9
- * @see https://scayle.dev/en/api-guides/storefront-api/resources/campaigns/list-campaigns
10
- *
11
- * This function uses the Storefront cache (`cached()`) with a `get-campaignKey` key prefix to improve performance.
12
- * Cached entries are returned if found; otherwise, data is fetched and cached.
13
- *
14
20
  * @param context The RPC Context
15
21
  * @returns The current active campaign key.
16
22
  */
@@ -4,10 +4,7 @@ import {
4
4
  isCampaignActive
5
5
  } from "../../utils/campaign.mjs";
6
6
  import { defineRpcHandler } from "../../utils/index.mjs";
7
- export const getCampaignKey = defineRpcHandler(async (context) => {
8
- if (context.campaignKey) {
9
- return context.campaignKey;
10
- }
7
+ const getCampaigns = async (context) => {
11
8
  const { cached, sapiClient } = context;
12
9
  const { campaigns } = await cached(async () => {
13
10
  const { entities } = await sapiClient.campaigns.get();
@@ -17,8 +14,20 @@ export const getCampaignKey = defineRpcHandler(async (context) => {
17
14
  }).sort(sortCampaignsByDateAscending)
18
15
  };
19
16
  }, {
20
- cacheKeyPrefix: "get-campaignKey",
17
+ cacheKeyPrefix: "get-campaigns",
21
18
  ttl: 5 * 60
22
19
  })();
23
- return campaigns.find(isCampaignActive)?.key;
20
+ return campaigns;
21
+ };
22
+ export const getCampaign = defineRpcHandler(async (context) => {
23
+ const campaigns = await getCampaigns(context);
24
+ return campaigns.find(isCampaignActive);
25
+ });
26
+ export const getCampaignKey = defineRpcHandler(async (context) => {
27
+ if (context.campaignKey) {
28
+ return context.campaignKey;
29
+ }
30
+ const campaigns = await getCampaigns(context);
31
+ const campaign = campaigns.find(isCampaignActive);
32
+ return campaign?.key;
24
33
  });
@@ -37,7 +37,7 @@ export const getCheckoutToken = defineRpcHandler(async (jwtPayload = {}, context
37
37
  carrier,
38
38
  basketId: context.basketKey,
39
39
  campaignKey
40
- }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"8.35.0"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
40
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"8.37.0"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
41
41
  return {
42
42
  accessToken: refreshedAccessToken,
43
43
  checkoutJwt
@@ -1,7 +1,7 @@
1
1
  export * from './basket/basket';
2
2
  export * from './brands';
3
3
  export * from './categories';
4
- export { getCampaignKey } from './campaign';
4
+ export * from './campaign';
5
5
  export * from './cbd';
6
6
  export { getProductById, getProductsByIds, getProductsByReferenceKeys, getProductsCount, fetchAllFiltersForCategory, getFilters, getProductsByCategory, } from './products';
7
7
  export * from './search';
@@ -1,7 +1,7 @@
1
1
  export * from "./basket/basket.mjs";
2
2
  export * from "./brands.mjs";
3
3
  export * from "./categories.mjs";
4
- export { getCampaignKey } from "./campaign.mjs";
4
+ export * from "./campaign.mjs";
5
5
  export * from "./cbd.mjs";
6
6
  export {
7
7
  getProductById,
@@ -89,10 +89,11 @@ export const getProductsCount = async function getProductsCount2(params, context
89
89
  const { cached, sapiClient } = context;
90
90
  const campaignKey = await context.callRpc?.("getCampaignKey");
91
91
  const { categoryId } = await resolveCategoryIdFromParams(context, params);
92
+ const { attributes, whitelistAttributes, ...filter } = where || {};
92
93
  const response = await getSanitizedAttributes(
93
94
  context,
94
95
  categoryId,
95
- where?.attributes || [],
96
+ attributes || [],
96
97
  includedFilters
97
98
  );
98
99
  if (response instanceof ErrorResponse) {
@@ -104,17 +105,12 @@ export const getProductsCount = async function getProductsCount2(params, context
104
105
  cacheKeyPrefix: "products-query"
105
106
  })({
106
107
  where: {
108
+ ...filter,
107
109
  categoryId,
108
- minPrice: where?.minPrice,
109
- maxPrice: where?.maxPrice,
110
- minReduction: where?.minReduction,
111
- maxReduction: where?.maxReduction,
112
- term: where?.term,
113
110
  attributes: [
114
111
  ...sanitizedAttributes,
115
- ...where?.whitelistAttributes || []
116
- ],
117
- disableFuzziness: where?.disableFuzziness
112
+ ...whitelistAttributes || []
113
+ ]
118
114
  },
119
115
  pagination: {
120
116
  perPage: 1
@@ -177,10 +173,11 @@ export const getFilters = async function getFilters2(params, context) {
177
173
  context,
178
174
  params
179
175
  );
176
+ const { attributes, whitelistAttributes, ...filter } = where || {};
180
177
  const response = await getSanitizedAttributes(
181
178
  context,
182
179
  categoryId,
183
- where?.attributes || [],
180
+ attributes || [],
184
181
  includedFilters
185
182
  );
186
183
  if (response instanceof ErrorResponse) {
@@ -192,15 +189,11 @@ export const getFilters = async function getFilters2(params, context) {
192
189
  cacheKeyPrefix: `get-filters-${categoryId}`
193
190
  })({
194
191
  where: {
192
+ ...filter,
195
193
  categoryId,
196
- minPrice: where?.minPrice,
197
- maxPrice: where?.maxPrice,
198
- minReduction: where?.minReduction,
199
- maxReduction: where?.maxReduction,
200
- term: where?.term,
201
194
  attributes: [
202
195
  ...sanitizedAttributes,
203
- ...where?.whitelistAttributes || []
196
+ ...whitelistAttributes || []
204
197
  ]
205
198
  },
206
199
  includeSoldOut,
@@ -214,17 +207,12 @@ export const getFilters = async function getFilters2(params, context) {
214
207
  cacheKeyPrefix: `products-query-category-${category === "/" ? "root" : categoryId}`
215
208
  })({
216
209
  where: {
210
+ ...filter,
217
211
  categoryId,
218
- minPrice: where?.minPrice,
219
- maxPrice: where?.maxPrice,
220
- minReduction: where?.minReduction,
221
- maxReduction: where?.maxReduction,
222
- term: where?.term,
223
212
  attributes: [
224
213
  ...sanitizedAttributes,
225
- ...where?.whitelistAttributes || []
226
- ],
227
- disableFuzziness: where?.disableFuzziness
214
+ ...whitelistAttributes || []
215
+ ]
228
216
  },
229
217
  pagination: {
230
218
  perPage: 1
@@ -261,10 +249,11 @@ export const getProductsByCategory = async function getProductsByCategory2(param
261
249
  context,
262
250
  params
263
251
  );
252
+ const { attributes, whitelistAttributes, ...filter } = where || {};
264
253
  const response = await getSanitizedAttributes(
265
254
  context,
266
255
  categoryId,
267
- where?.attributes || [],
256
+ attributes || [],
268
257
  includedFilters
269
258
  );
270
259
  if (response instanceof ErrorResponse) {
@@ -280,17 +269,12 @@ export const getProductsByCategory = async function getProductsByCategory2(param
280
269
  }
281
270
  )({
282
271
  where: {
272
+ ...filter,
283
273
  categoryId,
284
- minPrice: where?.minPrice,
285
- maxPrice: where?.maxPrice,
286
- minReduction: where?.minReduction,
287
- maxReduction: where?.maxReduction,
288
- term: where?.term,
289
274
  attributes: [
290
275
  ...sanitizedAttributes,
291
- ...where?.whitelistAttributes || []
292
- ],
293
- disableFuzziness: where?.disableFuzziness
276
+ ...whitelistAttributes || []
277
+ ]
294
278
  },
295
279
  pagination: {
296
280
  perPage: Math.min(perPage, MAX_PER_PAGE),
@@ -90,6 +90,9 @@ export interface FetchProductsByReferenceKeysParams {
90
90
  with?: ProductWith;
91
91
  pricePromotionKey?: string;
92
92
  }
93
+ export type ProductWhere = Partial<Omit<ProductSearchQuery, 'categoryId'> & {
94
+ whitelistAttributes?: ProductSearchQuery['attributes'];
95
+ }>;
93
96
  /**
94
97
  * Parameters for fetching products by category.
95
98
  */
@@ -101,16 +104,7 @@ export type FetchProductsByCategoryParams = {
101
104
  perPage?: number;
102
105
  page?: number;
103
106
  /** Search query parameters. */
104
- where?: {
105
- term?: ProductSearchQuery['term'];
106
- minPrice?: ProductSearchQuery['minPrice'];
107
- maxPrice?: ProductSearchQuery['maxPrice'];
108
- minReduction?: ProductSearchQuery['minReduction'];
109
- maxReduction?: ProductSearchQuery['maxReduction'];
110
- attributes?: ProductSearchQuery['attributes'];
111
- disableFuzziness?: ProductSearchQuery['disableFuzziness'];
112
- whitelistAttributes?: ProductSearchQuery['attributes'];
113
- };
107
+ where?: ProductWhere;
114
108
  /** Sort parameters. */
115
109
  sort?: FilterParams['sort'];
116
110
  pricePromotionKey?: string;
@@ -145,16 +139,7 @@ export interface FetchProductsByCategoryResponse {
145
139
  */
146
140
  export type FetchProductsCountParams = {
147
141
  /** Search query parameters. */
148
- where?: {
149
- term?: ProductSearchQuery['term'];
150
- minPrice?: ProductSearchQuery['minPrice'];
151
- maxPrice?: ProductSearchQuery['maxPrice'];
152
- minReduction?: ProductSearchQuery['minReduction'];
153
- maxReduction?: ProductSearchQuery['maxReduction'];
154
- attributes?: ProductSearchQuery['attributes'];
155
- disableFuzziness?: ProductSearchQuery['disableFuzziness'];
156
- whitelistAttributes?: ProductSearchQuery['attributes'];
157
- };
142
+ where?: ProductWhere;
158
143
  includedFilters?: Array<string>;
159
144
  includeSoldOut?: boolean;
160
145
  includeSellableForFree?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scayle/storefront-core",
3
- "version": "8.35.0",
3
+ "version": "8.37.0",
4
4
  "description": "Collection of essential utilities to work with the Storefront API",
5
5
  "author": "SCAYLE Commerce Engine",
6
6
  "license": "MIT",
@@ -56,12 +56,12 @@
56
56
  "ufo": "^1.5.3",
57
57
  "uncrypto": "^0.1.3",
58
58
  "utility-types": "^3.11.0",
59
- "@scayle/storefront-api": "18.10.0",
59
+ "@scayle/storefront-api": "18.11.0",
60
60
  "@scayle/unstorage-scayle-kv-driver": "1.0.2"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@types/crypto-js": "4.2.2",
64
- "@types/node": "22.16.4",
64
+ "@types/node": "22.16.5",
65
65
  "@types/webpack-env": "1.18.8",
66
66
  "@vitest/coverage-v8": "3.2.4",
67
67
  "dprint": "0.50.1",
@@ -77,7 +77,7 @@
77
77
  "@scayle/eslint-config-storefront": "4.6.1"
78
78
  },
79
79
  "volta": {
80
- "node": "22.17.0"
80
+ "node": "22.17.1"
81
81
  },
82
82
  "scripts": {
83
83
  "clean": "rimraf ./dist",