@scayle/storefront-core 8.7.1 → 8.9.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 +30 -0
- package/dist/index.d.ts +2 -0
- package/dist/rpc/methods/basket/basket.mjs +8 -4
- package/dist/rpc/methods/campaign.d.ts +13 -0
- package/dist/rpc/methods/campaign.mjs +23 -0
- package/dist/rpc/methods/checkout/checkout.d.ts +2 -3
- package/dist/rpc/methods/checkout/checkout.mjs +3 -2
- package/dist/rpc/methods/index.d.ts +1 -0
- package/dist/rpc/methods/index.mjs +1 -0
- package/dist/rpc/methods/products.d.ts +9 -28
- package/dist/rpc/methods/products.mjs +18 -7
- package/dist/rpc/methods/variants.d.ts +2 -2
- package/dist/rpc/methods/variants.mjs +3 -1
- package/dist/rpc/methods/wishlist.d.ts +7 -7
- package/dist/rpc/methods/wishlist.mjs +6 -3
- package/dist/types/api/context.d.ts +23 -0
- package/dist/utils/campaign.d.ts +38 -0
- package/dist/utils/campaign.mjs +17 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.mjs +1 -0
- package/dist/utils/user.mjs +5 -2
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @scayle/storefront-core
|
|
2
2
|
|
|
3
|
+
## 8.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Extend `RpcContext` with an `rpcCall` property. This is a utility function that can be used within RPC methods to invoke another RPC method.
|
|
8
|
+
|
|
9
|
+
## 8.8.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- Deprecate `RpcContext.campaignKey`. The `getCampaignKey` RPC should be used instead.
|
|
14
|
+
|
|
15
|
+
To get the default campaign key, you can call the RPC method:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// Before
|
|
19
|
+
async function rpcMethod(context) {
|
|
20
|
+
const campaignKey = { context }
|
|
21
|
+
// ...
|
|
22
|
+
}
|
|
23
|
+
// After
|
|
24
|
+
async function rpcMethod(context) {
|
|
25
|
+
const campaignKey = await context.callRpc?.('getCampaignKey')
|
|
26
|
+
// ...
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
To override the default campaign key, override the getCampaignKey RPC with your own implementation.
|
|
31
|
+
See [Overriding core RPC Methods](https://scayle.dev/en/storefront-guide/developer-guide/basic-setup/rpc-methods#overriding-core-rpc-methods) for more.
|
|
32
|
+
|
|
3
33
|
## 8.7.1
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as rpcMethods from './rpc/methods';
|
|
2
|
+
import type { RpcContext } from './types';
|
|
2
3
|
export { rpcMethods };
|
|
3
4
|
export * from './errors';
|
|
4
5
|
export * from './utils';
|
|
@@ -65,4 +66,5 @@ export type RpcMethodParameters<N extends RpcMethodName> = Parameters<RpcMethod<
|
|
|
65
66
|
* @template N The name of the RPC method.
|
|
66
67
|
*/
|
|
67
68
|
export type RpcMethodReturnType<N extends RpcMethodName> = ReturnType<RpcMethod<N>>;
|
|
69
|
+
export type RpcMethodCall = <N extends RpcMethodName, P extends RpcMethodParameters<N>, TResult extends Exclude<Awaited<RpcMethodReturnType<N>>, Response>>(...args: P extends RpcContext ? [N] : [N, P]) => TResult;
|
|
68
70
|
export { ExistingItemHandling, AddToBasketFailureKind, UpdateBasketItemFailureKind, AddToWishlistFailureKind, PromotionEffectType, FilterTypes, APISortOption, APISortOrder, type ProductSortConfig, } from '@scayle/storefront-api';
|
|
@@ -31,7 +31,8 @@ export const addItemToBasket = async function addItemToBasket2({
|
|
|
31
31
|
"No Session found"
|
|
32
32
|
);
|
|
33
33
|
}
|
|
34
|
-
const {
|
|
34
|
+
const { sapiClient, basketKey } = context;
|
|
35
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
35
36
|
const resolvedWith = getWithParams(
|
|
36
37
|
{ with: _with },
|
|
37
38
|
context
|
|
@@ -91,7 +92,8 @@ export const addItemsToBasket = async function addItemsToBasket2(params, context
|
|
|
91
92
|
"No Session found"
|
|
92
93
|
);
|
|
93
94
|
}
|
|
94
|
-
const {
|
|
95
|
+
const { sapiClient, basketKey } = context;
|
|
96
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
95
97
|
const resolvedWith = getWithParams(params, context);
|
|
96
98
|
const itemsToBeAddedOrUpdated = params.items.map((item) => ({
|
|
97
99
|
variantId: item.variantId,
|
|
@@ -151,7 +153,8 @@ export const getBasket = async function getBasket2(options, context) {
|
|
|
151
153
|
"No Session found"
|
|
152
154
|
);
|
|
153
155
|
}
|
|
154
|
-
const { sapiClient,
|
|
156
|
+
const { sapiClient, basketKey } = context;
|
|
157
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
155
158
|
const resolvedWith = getWithParams(
|
|
156
159
|
{ with: options },
|
|
157
160
|
context
|
|
@@ -183,7 +186,8 @@ export const removeItemFromBasket = async function removeItemFromBasket2(options
|
|
|
183
186
|
"No Session found"
|
|
184
187
|
);
|
|
185
188
|
}
|
|
186
|
-
const { sapiClient,
|
|
189
|
+
const { sapiClient, basketKey } = context;
|
|
190
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
187
191
|
const resolvedWith = getWithParams(options, context);
|
|
188
192
|
const basket = await sapiClient.basket.deleteItem(
|
|
189
193
|
basketKey,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RpcContext } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* RPC method to retrieve the current campaign key.
|
|
4
|
+
* Used by other RPC methods which depend on a campaign key.
|
|
5
|
+
* Will return the key for the earliest active campaign.
|
|
6
|
+
*
|
|
7
|
+
* Uses SAPI's list-campaigns endpoint
|
|
8
|
+
* @see https://scayle.dev/en/api-guides/storefront-api/resources/campaigns/list-campaigns
|
|
9
|
+
*
|
|
10
|
+
* @param context The RPC Context
|
|
11
|
+
* @returns The current active campaign key.
|
|
12
|
+
*/
|
|
13
|
+
export declare const getCampaignKey: (context: RpcContext) => Promise<string | undefined>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
campaignHasNotEnded,
|
|
3
|
+
sortCampaignsByDateAscending,
|
|
4
|
+
isCampaignActive
|
|
5
|
+
} from "../../utils/campaign.mjs";
|
|
6
|
+
export const getCampaignKey = async (context) => {
|
|
7
|
+
if (context.campaignKey) {
|
|
8
|
+
return context.campaignKey;
|
|
9
|
+
}
|
|
10
|
+
const { cached, sapiClient } = context;
|
|
11
|
+
const { campaigns } = await cached(async () => {
|
|
12
|
+
const { entities } = await sapiClient.campaigns.get();
|
|
13
|
+
return {
|
|
14
|
+
campaigns: entities.filter((campaign) => {
|
|
15
|
+
return campaignHasNotEnded(campaign);
|
|
16
|
+
}).sort(sortCampaignsByDateAscending)
|
|
17
|
+
};
|
|
18
|
+
}, {
|
|
19
|
+
cacheKeyPrefix: "get-campaignKey",
|
|
20
|
+
ttl: 5 * 60
|
|
21
|
+
})();
|
|
22
|
+
return campaigns.find(isCampaignActive)?.key;
|
|
23
|
+
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { RpcContext } from '../../../types';
|
|
1
|
+
import type { RpcHandler } from '../../../types';
|
|
3
2
|
interface CheckoutJwtPayload {
|
|
4
3
|
voucher?: string;
|
|
5
4
|
customData?: Record<string, unknown>;
|
|
@@ -9,7 +8,7 @@ interface CheckoutJwtPayload {
|
|
|
9
8
|
};
|
|
10
9
|
carrier?: string;
|
|
11
10
|
}
|
|
12
|
-
export declare const getCheckoutToken:
|
|
11
|
+
export declare const getCheckoutToken: RpcHandler<CheckoutJwtPayload | undefined, {
|
|
13
12
|
accessToken: string;
|
|
14
13
|
checkoutJwt: string;
|
|
15
14
|
}>;
|
|
@@ -28,14 +28,15 @@ export const getCheckoutToken = async function getCheckoutToken2(jwtPayload = {}
|
|
|
28
28
|
const secret = new TextEncoder().encode(context.checkout.secret);
|
|
29
29
|
const now = /* @__PURE__ */ new Date();
|
|
30
30
|
const { voucher, customData, preferredCollectionPoint, carrier } = jwtPayload;
|
|
31
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
31
32
|
const checkoutJwt = await new SignJWT({
|
|
32
33
|
voucher,
|
|
33
34
|
customData,
|
|
34
35
|
preferredCollectionPoint,
|
|
35
36
|
carrier,
|
|
36
37
|
basketId: context.basketKey,
|
|
37
|
-
campaignKey
|
|
38
|
-
}).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"8.
|
|
38
|
+
campaignKey
|
|
39
|
+
}).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"8.9.0"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
|
|
39
40
|
return {
|
|
40
41
|
accessToken: refreshedAccessToken,
|
|
41
42
|
checkoutJwt
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './basket/basket';
|
|
2
2
|
export * from './brands';
|
|
3
3
|
export * from './categories';
|
|
4
|
+
export { getCampaignKey } from './campaign';
|
|
4
5
|
export * from './cbd';
|
|
5
6
|
export { getProductById, getProductsByIds, getProductsByReferenceKeys, getProductsCount, fetchAllFiltersForCategory, getFilters, getProductsByCategory, } from './products';
|
|
6
7
|
export * from './search';
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { FetchFiltersParams, FetchProductParams, FetchProductsByCategoryParams, FetchProductsByIdsParams, FetchProductsByReferenceKeysParams, FetchProductsCountParams, Product, RpcContext } from '../../types';
|
|
3
|
-
import { ErrorResponse } from '../../errors';
|
|
1
|
+
import type { FetchFiltersParams, FetchFiltersResponse, FetchProductParams, FetchProductsByCategoryParams, FetchProductsByCategoryResponse, FetchProductsByIdsParams, FetchProductsByReferenceKeysParams, FetchProductsCountParams, FetchProductsCountResponse, Product, RpcContext, RpcHandler } from '../../types';
|
|
4
2
|
/**
|
|
5
3
|
* For functions which accept either a category path or category ID,
|
|
6
4
|
* this function can resolve the ID which is necessary for the calling
|
|
@@ -20,32 +18,15 @@ export declare function resolveCategoryIdFromParams(context: RpcContext, params:
|
|
|
20
18
|
category: string | undefined;
|
|
21
19
|
categoryId: number | undefined;
|
|
22
20
|
}>;
|
|
23
|
-
export declare const getProductById:
|
|
24
|
-
export declare const getProductsByIds:
|
|
25
|
-
export declare const getProductsByReferenceKeys:
|
|
26
|
-
export declare const getProductsCount:
|
|
27
|
-
|
|
28
|
-
}>;
|
|
29
|
-
export declare const fetchAllFiltersForCategory: ({ includedFilters, category }: {
|
|
21
|
+
export declare const getProductById: RpcHandler<FetchProductParams, Product>;
|
|
22
|
+
export declare const getProductsByIds: RpcHandler<FetchProductsByIdsParams, Product[]>;
|
|
23
|
+
export declare const getProductsByReferenceKeys: RpcHandler<FetchProductsByReferenceKeysParams, Product[]>;
|
|
24
|
+
export declare const getProductsCount: RpcHandler<FetchProductsCountParams, FetchProductsCountResponse>;
|
|
25
|
+
export declare const fetchAllFiltersForCategory: RpcHandler<{
|
|
30
26
|
includedFilters?: string[];
|
|
31
27
|
category: {
|
|
32
28
|
id?: number;
|
|
33
29
|
};
|
|
34
|
-
},
|
|
35
|
-
export declare const getFilters:
|
|
36
|
-
|
|
37
|
-
unfilteredCount: number;
|
|
38
|
-
}>;
|
|
39
|
-
export declare const getProductsByCategory: (params: FetchProductsByCategoryParams, context: RpcContext) => Promise<(string[] & ErrorResponse) | {
|
|
40
|
-
products: Product[];
|
|
41
|
-
pagination: {
|
|
42
|
-
current: number;
|
|
43
|
-
total: number;
|
|
44
|
-
perPage: number;
|
|
45
|
-
page: number;
|
|
46
|
-
first: number;
|
|
47
|
-
prev: number;
|
|
48
|
-
next: number;
|
|
49
|
-
last: number;
|
|
50
|
-
};
|
|
51
|
-
}>;
|
|
30
|
+
}, string[]>;
|
|
31
|
+
export declare const getFilters: RpcHandler<FetchFiltersParams, FetchFiltersResponse>;
|
|
32
|
+
export declare const getProductsByCategory: RpcHandler<FetchProductsByCategoryParams, FetchProductsByCategoryResponse>;
|
|
@@ -34,7 +34,9 @@ export async function resolveCategoryIdFromParams(context, params) {
|
|
|
34
34
|
}
|
|
35
35
|
return { category, categoryId };
|
|
36
36
|
}
|
|
37
|
-
export const getProductById = async function getProductById2(options,
|
|
37
|
+
export const getProductById = async function getProductById2(options, context) {
|
|
38
|
+
const { sapiClient, cached, withParams } = context;
|
|
39
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
38
40
|
return await cached(
|
|
39
41
|
mapSAPIFetchErrorToResponse(sapiClient.products.getById),
|
|
40
42
|
{
|
|
@@ -48,7 +50,9 @@ export const getProductById = async function getProductById2(options, { sapiClie
|
|
|
48
50
|
includeSellableForFree: options.includeSellableForFree
|
|
49
51
|
});
|
|
50
52
|
};
|
|
51
|
-
export const getProductsByIds = async function getProductsByIds2(options,
|
|
53
|
+
export const getProductsByIds = async function getProductsByIds2(options, context) {
|
|
54
|
+
const { sapiClient, cached, withParams } = context;
|
|
55
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
52
56
|
return await cached(
|
|
53
57
|
mapSAPIFetchErrorToResponse(sapiClient.products.getByIds),
|
|
54
58
|
{
|
|
@@ -61,7 +65,9 @@ export const getProductsByIds = async function getProductsByIds2(options, { sapi
|
|
|
61
65
|
pricePromotionKey: options.pricePromotionKey
|
|
62
66
|
});
|
|
63
67
|
};
|
|
64
|
-
export const getProductsByReferenceKeys = async function getProductsByReferenceKeys2(options,
|
|
68
|
+
export const getProductsByReferenceKeys = async function getProductsByReferenceKeys2(options, context) {
|
|
69
|
+
const { sapiClient, cached, withParams } = context;
|
|
70
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
65
71
|
return await cached(
|
|
66
72
|
mapSAPIFetchErrorToResponse(sapiClient.products.getByReferenceKeys),
|
|
67
73
|
{
|
|
@@ -82,7 +88,8 @@ export const getProductsCount = async function getProductsCount2(params, context
|
|
|
82
88
|
includeSellableForFree = false,
|
|
83
89
|
orFiltersOperator = void 0
|
|
84
90
|
} = params;
|
|
85
|
-
const { cached, sapiClient
|
|
91
|
+
const { cached, sapiClient } = context;
|
|
92
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
86
93
|
const { categoryId } = await resolveCategoryIdFromParams(context, params);
|
|
87
94
|
const response = await getSanitizedAttributes(
|
|
88
95
|
context,
|
|
@@ -121,7 +128,9 @@ export const getProductsCount = async function getProductsCount2(params, context
|
|
|
121
128
|
count: productCount?.pagination.total
|
|
122
129
|
};
|
|
123
130
|
};
|
|
124
|
-
export const fetchAllFiltersForCategory = async function fetchAllFiltersForCategory2({ includedFilters = [], category },
|
|
131
|
+
export const fetchAllFiltersForCategory = async function fetchAllFiltersForCategory2({ includedFilters = [], category }, context) {
|
|
132
|
+
const { cached, sapiClient } = context;
|
|
133
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
125
134
|
const fetchAndMapFiltersToSlugs = async () => {
|
|
126
135
|
const filtersFromSAPI = await cached(sapiClient.filters.get)({
|
|
127
136
|
where: { categoryId: category.id },
|
|
@@ -162,7 +171,8 @@ export const getFilters = async function getFilters2(params, context) {
|
|
|
162
171
|
includeSellableForFree = false,
|
|
163
172
|
orFiltersOperator
|
|
164
173
|
} = params;
|
|
165
|
-
const { cached, sapiClient
|
|
174
|
+
const { cached, sapiClient } = context;
|
|
175
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
166
176
|
const { category, categoryId } = await resolveCategoryIdFromParams(
|
|
167
177
|
context,
|
|
168
178
|
params
|
|
@@ -241,7 +251,8 @@ export const getProductsByCategory = async function getProductsByCategory2(param
|
|
|
241
251
|
orFiltersOperator = void 0,
|
|
242
252
|
trackSearchAnalyticsEvent = void 0
|
|
243
253
|
} = params;
|
|
244
|
-
const { cached, sapiClient
|
|
254
|
+
const { cached, sapiClient } = context;
|
|
255
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
245
256
|
const { category, categoryId } = await resolveCategoryIdFromParams(
|
|
246
257
|
context,
|
|
247
258
|
params
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ProductWith, VariantDetail } from '@scayle/storefront-api';
|
|
2
|
-
import type {
|
|
2
|
+
import type { RpcHandler } from '../../types';
|
|
3
3
|
export interface FetchVariantsParams {
|
|
4
4
|
ids: number[];
|
|
5
5
|
include?: ProductWith;
|
|
6
6
|
pricePromotionKey?: string;
|
|
7
7
|
}
|
|
8
|
-
export declare const getVariantById:
|
|
8
|
+
export declare const getVariantById: RpcHandler<FetchVariantsParams, VariantDetail[]>;
|
|
@@ -2,7 +2,9 @@ import { mapSAPIFetchErrorToResponse } from "../../utils/sapi.mjs";
|
|
|
2
2
|
const defaultWith = {
|
|
3
3
|
attributes: "all"
|
|
4
4
|
};
|
|
5
|
-
export const getVariantById = async function getVariantById2({ ids, include = defaultWith, pricePromotionKey = "default" },
|
|
5
|
+
export const getVariantById = async function getVariantById2({ ids, include = defaultWith, pricePromotionKey = "default" }, context) {
|
|
6
|
+
const { sapiClient, cached, withParams } = context;
|
|
7
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
6
8
|
const resolvedWith = include ?? withParams?.variant ?? defaultWith;
|
|
7
9
|
return await cached(
|
|
8
10
|
mapSAPIFetchErrorToResponse(sapiClient.variants.getByIds),
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Wishlist } from '@scayle/storefront-api';
|
|
2
|
-
import type {
|
|
3
|
-
export declare const getWishlist:
|
|
4
|
-
export declare const addItemToWishlist:
|
|
2
|
+
import type { ParamRpcHandler, RpcHandler, WishlistWithOptions } from '../../types';
|
|
3
|
+
export declare const getWishlist: RpcHandler<WishlistWithOptions | undefined, Wishlist>;
|
|
4
|
+
export declare const addItemToWishlist: ParamRpcHandler<{
|
|
5
5
|
variantId?: number;
|
|
6
6
|
productId?: number;
|
|
7
7
|
with?: WishlistWithOptions;
|
|
8
|
-
},
|
|
9
|
-
export declare const removeItemFromWishlist:
|
|
8
|
+
}, Wishlist | Response>;
|
|
9
|
+
export declare const removeItemFromWishlist: RpcHandler<{
|
|
10
10
|
itemKey: string;
|
|
11
11
|
with?: WishlistWithOptions;
|
|
12
|
-
},
|
|
13
|
-
export declare const clearWishlist:
|
|
12
|
+
}, Wishlist>;
|
|
13
|
+
export declare const clearWishlist: RpcHandler<Wishlist>;
|
|
@@ -18,7 +18,8 @@ export const getWishlist = async function getWishlist2(options, context) {
|
|
|
18
18
|
"No Session found"
|
|
19
19
|
);
|
|
20
20
|
}
|
|
21
|
-
const { sapiClient,
|
|
21
|
+
const { sapiClient, wishlistKey } = context;
|
|
22
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
22
23
|
const resolvedWith = getWithParams({ with: options }, context);
|
|
23
24
|
return await mapSAPIFetchErrorToResponse(sapiClient.wishlist.get)(
|
|
24
25
|
wishlistKey,
|
|
@@ -37,7 +38,8 @@ export const addItemToWishlist = async function addItemToWishlist2(options, cont
|
|
|
37
38
|
"No Session found"
|
|
38
39
|
);
|
|
39
40
|
}
|
|
40
|
-
const { sapiClient,
|
|
41
|
+
const { sapiClient, wishlistKey } = context;
|
|
42
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
41
43
|
const { productId, variantId } = options;
|
|
42
44
|
const resolvedWith = getWithParams(options, context);
|
|
43
45
|
const pricePromotionKey = resolvedWith?.pricePromotionKey ?? "";
|
|
@@ -73,7 +75,8 @@ export const removeItemFromWishlist = async function removeItemFromWishlist2(opt
|
|
|
73
75
|
"No Session found"
|
|
74
76
|
);
|
|
75
77
|
}
|
|
76
|
-
const { sapiClient,
|
|
78
|
+
const { sapiClient, wishlistKey } = context;
|
|
79
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
77
80
|
const resolvedWith = getWithParams(options, context);
|
|
78
81
|
return await mapSAPIFetchErrorToResponse(sapiClient.wishlist.deleteItem)(
|
|
79
82
|
wishlistKey,
|
|
@@ -5,6 +5,7 @@ import type { CachedType } from '../../cache/cached';
|
|
|
5
5
|
import type { AuthenticationType, ShopUser } from '../user';
|
|
6
6
|
import type { BasketWithOptions, CategoryWith, ProductCategoryWith, ProductWith, SearchV2With, SearchWith, VariantWith, WishlistWithOptions } from '../';
|
|
7
7
|
import type { IDPConfig, OAuthTokens } from './auth';
|
|
8
|
+
import type { RpcMethodCall } from '../..';
|
|
8
9
|
export type WithParams = Partial<{
|
|
9
10
|
basket: BasketWithOptions;
|
|
10
11
|
wishlist: WishlistWithOptions;
|
|
@@ -77,6 +78,27 @@ export type RpcContext = {
|
|
|
77
78
|
shopId: number;
|
|
78
79
|
domain?: string;
|
|
79
80
|
withParams?: WithParams;
|
|
81
|
+
/**
|
|
82
|
+
* @deprecated The `getCampaignKey` RPC method should be used instead to retrieve the default campaign key.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
*
|
|
86
|
+
* ```typescript
|
|
87
|
+
* // Before
|
|
88
|
+
* async function rpcMethod(context) {
|
|
89
|
+
* const campaignKey = { context }
|
|
90
|
+
* // ...
|
|
91
|
+
* }
|
|
92
|
+
* // After
|
|
93
|
+
* async function rpcMethod(context) {
|
|
94
|
+
* const campaignKey = await context.callRpc?.('getCampaignKey')
|
|
95
|
+
* // ...
|
|
96
|
+
* }
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* To override the default campaign key, override the getCampaignKey RPC with your own implementation
|
|
100
|
+
* @see https://scayle.dev/en/storefront-guide/developer-guide/basic-setup/rpc-methods#overriding-core-rpc-methods
|
|
101
|
+
*/
|
|
80
102
|
campaignKey?: string;
|
|
81
103
|
destroySessionsForUserId: (userId: number, sessionsToKeep?: string[]) => Promise<void>;
|
|
82
104
|
generateBasketKeyForUserId: (userId: string) => Promise<string>;
|
|
@@ -99,6 +121,7 @@ export type RpcContext = {
|
|
|
99
121
|
callHook?: Hookable<StorefrontHooks>['callHook'];
|
|
100
122
|
callHookParallel?: Hookable<StorefrontHooks>['callHookParallel'];
|
|
101
123
|
callHookWith?: Hookable<StorefrontHooks>['callHookWith'];
|
|
124
|
+
callRpc?: RpcMethodCall;
|
|
102
125
|
} & AdditionalRpcContext & (ContextWithoutSession | ContextWithSession);
|
|
103
126
|
export type RpcContextWithSession = RpcContext & ContextWithSession;
|
|
104
127
|
export declare function assertSession(context: RpcContext): asserts context is RpcContextWithSession;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Campaign } from '@scayle/storefront-api';
|
|
2
|
+
/**
|
|
3
|
+
* Checks if a given campaign is currently active.
|
|
4
|
+
*
|
|
5
|
+
* Determines if the current time falls within the campaign's start and end dates.
|
|
6
|
+
*
|
|
7
|
+
* @see https://scayle.dev/en/user-guide/shops/promotions/discounts-and-offers/price-campaigns
|
|
8
|
+
*
|
|
9
|
+
* @param campaign The campaign to check.
|
|
10
|
+
*
|
|
11
|
+
* @returns True if the campaign is active, false otherwise.
|
|
12
|
+
*/
|
|
13
|
+
export declare const isCampaignActive: (campaign?: Campaign) => boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Checks if a given campaign has not yet ended.
|
|
16
|
+
*
|
|
17
|
+
* Compares the campaign's end date with the current time.
|
|
18
|
+
*
|
|
19
|
+
* @see https://scayle.dev/en/user-guide/shops/promotions/discounts-and-offers/price-campaigns
|
|
20
|
+
*
|
|
21
|
+
* @param campaign The campaign to check.
|
|
22
|
+
*
|
|
23
|
+
* @returns True if the campaign has not ended, false otherwise.
|
|
24
|
+
*/
|
|
25
|
+
export declare const campaignHasNotEnded: (campaign: Campaign) => boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Sorts campaigns by their start date in ascending order.
|
|
28
|
+
*
|
|
29
|
+
* Uses the difference between start times to determine order.
|
|
30
|
+
*
|
|
31
|
+
* @see https://scayle.dev/en/user-guide/shops/promotions/discounts-and-offers/price-campaigns
|
|
32
|
+
*
|
|
33
|
+
* @param a The first campaign to compare.
|
|
34
|
+
* @param b The second campaign to compare.
|
|
35
|
+
*
|
|
36
|
+
* @returns A negative number if `a` starts before `b`, a positive number if `a` starts after `b`, and 0 if they start at the same time.
|
|
37
|
+
*/
|
|
38
|
+
export declare const sortCampaignsByDateAscending: (a: Campaign, b: Campaign) => number;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const isCampaignActive = (campaign) => {
|
|
2
|
+
if (!campaign) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
const timeNow = Date.now();
|
|
6
|
+
const campaignStart = new Date(campaign.start_at).getTime();
|
|
7
|
+
const hasStarted = timeNow >= campaignStart;
|
|
8
|
+
const campaignEnd = new Date(campaign.end_at).getTime();
|
|
9
|
+
const hasEnded = timeNow >= campaignEnd;
|
|
10
|
+
return hasStarted && !hasEnded;
|
|
11
|
+
};
|
|
12
|
+
export const campaignHasNotEnded = (campaign) => {
|
|
13
|
+
return new Date(campaign.end_at).getTime() > Date.now();
|
|
14
|
+
};
|
|
15
|
+
export const sortCampaignsByDateAscending = (a, b) => {
|
|
16
|
+
return new Date(a.start_at).getTime() - new Date(b.start_at).getTime();
|
|
17
|
+
};
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.mjs
CHANGED
package/dist/utils/user.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ExistingItemHandling } from "@scayle/storefront-api";
|
|
2
|
+
import { getCampaignKey } from "../rpc/methods/index.mjs";
|
|
2
3
|
export const mergeBaskets = async (fromBasketKey, toBasketKey, withOptions, context) => {
|
|
3
|
-
const { sapiClient
|
|
4
|
+
const { sapiClient } = context;
|
|
5
|
+
const campaignKey = await getCampaignKey(context);
|
|
4
6
|
const fromOriginBasket = await sapiClient.basket.get(fromBasketKey, {
|
|
5
7
|
with: withOptions,
|
|
6
8
|
campaignKey,
|
|
@@ -43,7 +45,8 @@ export const mergeBaskets = async (fromBasketKey, toBasketKey, withOptions, cont
|
|
|
43
45
|
}
|
|
44
46
|
};
|
|
45
47
|
export const mergeWishlists = async (fromWishlistKey, toWishlistKey, withOptions, context) => {
|
|
46
|
-
const { sapiClient
|
|
48
|
+
const { sapiClient } = context;
|
|
49
|
+
const campaignKey = await getCampaignKey(context);
|
|
47
50
|
const oldWishlist = await sapiClient.wishlist.get(fromWishlistKey, {
|
|
48
51
|
with: withOptions,
|
|
49
52
|
campaignKey
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scayle/storefront-core",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.9.0",
|
|
4
4
|
"description": "Collection of essential utilities to work with the Storefront API",
|
|
5
5
|
"author": "SCAYLE Commerce Engine",
|
|
6
6
|
"license": "MIT",
|
|
@@ -68,17 +68,17 @@
|
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@scayle/eslint-config-storefront": "4.4.1",
|
|
70
70
|
"@types/crypto-js": "4.2.2",
|
|
71
|
-
"@types/node": "22.13.
|
|
71
|
+
"@types/node": "22.13.5",
|
|
72
72
|
"@types/webpack-env": "1.18.8",
|
|
73
73
|
"@vitest/coverage-v8": "2.1.9",
|
|
74
74
|
"dprint": "0.49.0",
|
|
75
|
-
"eslint": "9.
|
|
75
|
+
"eslint": "9.21.0",
|
|
76
76
|
"eslint-formatter-gitlab": "5.1.0",
|
|
77
77
|
"publint": "0.2.12",
|
|
78
78
|
"rimraf": "6.0.1",
|
|
79
79
|
"typescript": "5.7.3",
|
|
80
80
|
"unbuild": "3.3.1",
|
|
81
|
-
"unstorage": "1.
|
|
81
|
+
"unstorage": "1.15.0",
|
|
82
82
|
"vitest": "2.1.9"
|
|
83
83
|
}
|
|
84
84
|
}
|