@scayle/storefront-core 8.40.0 → 8.41.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,25 @@
1
1
  # @scayle/storefront-core
2
2
 
3
+ ## 8.41.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Improved logging around cache errors to provide more details.
8
+
9
+ ## 8.41.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Introduce a new `updatePromotions` RPC method to wrap the Storefront API "Bulk update promotions" endpoint.
14
+ This allows to update all promotions applied to basket's items in a single API call.
15
+ For more details, see the [Storefront API documentation](https://scayle.dev/en/api-guides/storefront-api/resources/baskets/bulk-update-promotions).
16
+
17
+ ### Patch Changes
18
+
19
+ **Dependencies**
20
+
21
+ - Updated dependency to @scayle/storefront-api@18.13.0
22
+
3
23
  ## 8.40.0
4
24
 
5
25
  ### Patch Changes
@@ -106,6 +106,7 @@ export declare class Cached {
106
106
  * Handles errors during cache operations.
107
107
  *
108
108
  * @param error The error that occurred.
109
+ * @param operation The operation which caused the error
109
110
  *
110
111
  * @private
111
112
  */
@@ -24,7 +24,7 @@ export class Cached {
24
24
  throw new Error(CACHE_NOT_INITIALIZED_MSG);
25
25
  }
26
26
  this.cache = cache;
27
- this.log = log.space("cached.init");
27
+ this.log = log.space("cached");
28
28
  this.prefix = prefix;
29
29
  this.enabled = enabled;
30
30
  }
@@ -57,7 +57,7 @@ export class Cached {
57
57
  }
58
58
  } catch (e) {
59
59
  if (e instanceof Error) {
60
- this.handleError(e);
60
+ this.handleError(e, "getting");
61
61
  }
62
62
  }
63
63
  const response = await fn(...args);
@@ -71,7 +71,7 @@ export class Cached {
71
71
  await this.setCacheValue(cacheKey, response, options);
72
72
  } catch (e) {
73
73
  if (e instanceof Error) {
74
- this.handleError(e);
74
+ this.handleError(e, "setting");
75
75
  }
76
76
  }
77
77
  return response;
@@ -136,13 +136,17 @@ export class Cached {
136
136
  * Handles errors during cache operations.
137
137
  *
138
138
  * @param error The error that occurred.
139
+ * @param operation The operation which caused the error
139
140
  *
140
141
  * @private
141
142
  */
142
- handleError(error) {
143
+ handleError(error, operation) {
143
144
  if (error.message === "timeout") {
144
- return this.log.error("Cache timeout");
145
+ return this.log.error(
146
+ `Cache timeout while ${operation} cache value`,
147
+ error
148
+ );
145
149
  }
146
- this.log.error(error);
150
+ this.log.error(`Error while ${operation} cache value`, error);
147
151
  }
148
152
  }
@@ -1,5 +1,5 @@
1
1
  import { ExistingItemHandling } from '@scayle/storefront-api';
2
- import type { AddOrUpdateItemError, UpdateBasketItemQuantity, GetApplicablePromotionsByCodeParameters } from '@scayle/storefront-api';
2
+ import type { AddOrUpdateItemError, UpdateBasketItemQuantity, GetApplicablePromotionsByCodeParameters, BulkUpdatePromotionsParameters } from '@scayle/storefront-api';
3
3
  import type { AddOrUpdateItemType, BasketResponseData, BasketWithOptions, Product, RpcHandler, Variant } from '../../../types';
4
4
  import { mergeBaskets as mergeBasketFunction } from '../../../utils/user';
5
5
  /**
@@ -165,3 +165,17 @@ export declare const updateBasketItem: RpcHandler<UpdateBasketItemRequestParamet
165
165
  export declare const getApplicablePromotionsByCode: RpcHandler<Omit<GetApplicablePromotionsByCodeParameters, 'basketKey'>, {
166
166
  basket: BasketResponseData<Product, Variant>;
167
167
  }>;
168
+ /**
169
+ * Updates the promotions for a basket item.
170
+ *
171
+ * @param params The parameters for updating the promotions for a basket item.
172
+ * @param params.itemId The ID of the item to update.
173
+ * @param params.promotions The promotions to update.
174
+ * @param context The RPC context.
175
+ *
176
+ * @returns A promise that resolves with the updated basket.
177
+ * It will return an `ErrorResponse` if no session is found or update operation fails.
178
+ */
179
+ export declare const updatePromotions: RpcHandler<Omit<BulkUpdatePromotionsParameters, 'basketKey'>, {
180
+ basket: BasketResponseData<Product, Variant>;
181
+ }>;
@@ -305,6 +305,43 @@ export const getApplicablePromotionsByCode = defineRpcHandler(async ({ promotion
305
305
  return { basket: result.basket };
306
306
  }
307
307
  });
308
+ export const updatePromotions = defineRpcHandler(async (params, context) => {
309
+ if (!hasSession(context)) {
310
+ return new ErrorResponse(
311
+ HttpStatusCode.BAD_REQUEST,
312
+ HttpStatusMessage.BAD_REQUEST,
313
+ "No Session found"
314
+ );
315
+ }
316
+ const { basketKey, sapiClient } = context;
317
+ const campaignKey = params.campaignKey ?? await context.callRpc?.("getCampaignKey");
318
+ const resolvedWith = getWithParams(
319
+ { with: params.with },
320
+ context
321
+ );
322
+ const result = await mapSAPIFetchErrorToResponse(
323
+ sapiClient.basket.bulkUpdatePromotions
324
+ )(
325
+ basketKey,
326
+ {
327
+ ...params,
328
+ campaignKey,
329
+ with: resolvedWith
330
+ }
331
+ );
332
+ if (result instanceof Response || result.type === "failure") {
333
+ context.log.info("Bulk updating promotions failed", {
334
+ basketKey,
335
+ items: params.items
336
+ });
337
+ return new ErrorResponse(
338
+ HttpStatusCode.BAD_REQUEST,
339
+ SAPI_ERROR_NAME,
340
+ "Bulk updating promotions failed"
341
+ );
342
+ }
343
+ return { basket: result.basket };
344
+ });
308
345
  function parseBasketError(response) {
309
346
  const parsedError = {
310
347
  message: "",
@@ -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.40.0"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
36
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"8.41.1"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
37
37
  return {
38
38
  accessToken: refreshedAccessToken,
39
39
  checkoutJwt
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Wraps a SAPI API function, catching SAPI FetchErrors and converting them to a structured Response.
2
+ * Wraps a Storefront API client function, catching Storefront API FetchErrors and converting them to a structured Response.
3
3
  * This allows handling SAPI errors in a consistent way, returning a JSON response with status information.
4
4
  *
5
- * @template T The type of the SAPI API function.
5
+ * @template T The type of the Storefront API client function.
6
6
  *
7
- * @param func The SAPI API function to wrap.
7
+ * @param func The Storefront API client function to wrap.
8
8
  *
9
9
  * @returns A wrapped function that returns a Promise resolving to either the original function's result or a JSON Response representing the error.
10
10
  *
11
- * @throws Re-throws any error that is not an instance of FetchError.
11
+ * @throws Re-throws any error that is not an instance of StorefrontAPI FetchError.
12
12
  */
13
13
  export declare function mapSAPIFetchErrorToResponse<T extends (...args: any[]) => any>(func: T): (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>> | Response>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scayle/storefront-core",
3
- "version": "8.40.0",
3
+ "version": "8.41.1",
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
  "ufo": "^1.5.3",
57
57
  "uncrypto": "^0.1.3",
58
58
  "utility-types": "^3.11.0",
59
- "@scayle/storefront-api": "18.12.0",
59
+ "@scayle/storefront-api": "18.13.0",
60
60
  "@scayle/unstorage-scayle-kv-driver": "1.0.3"
61
61
  },
62
62
  "devDependencies": {