@scayle/storefront-core 8.61.1 → 8.61.2
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-V7.md +1 -11
- package/CHANGELOG.md +96 -103
- package/dist/api/customer.mjs +1 -3
- package/dist/api/oauth.mjs +9 -6
- package/dist/cache/providers/unstorage.mjs +1 -3
- package/dist/constants/withParameters.mjs +2 -16
- package/dist/helpers/attributeHelpers.mjs +3 -1
- package/dist/helpers/filterHelper.mjs +11 -8
- package/dist/helpers/productHelpers.mjs +1 -3
- package/dist/helpers/sanitizationHelpers.mjs +1 -4
- package/dist/helpers/sortingHelper.mjs +1 -3
- package/dist/rpc/methods/basket/basket.d.ts +2 -2
- package/dist/rpc/methods/basket/basket.mjs +334 -321
- package/dist/rpc/methods/brands.mjs +26 -20
- package/dist/rpc/methods/campaign.mjs +32 -23
- package/dist/rpc/methods/categories.mjs +156 -135
- package/dist/rpc/methods/cbd.mjs +52 -49
- package/dist/rpc/methods/checkout/checkout.mjs +42 -39
- package/dist/rpc/methods/checkout/order.mjs +46 -40
- package/dist/rpc/methods/checkout/shopUser.mjs +112 -106
- package/dist/rpc/methods/navigationTrees.mjs +50 -32
- package/dist/rpc/methods/oauth/idp.mjs +64 -55
- package/dist/rpc/methods/products.mjs +224 -212
- package/dist/rpc/methods/promotion.mjs +46 -31
- package/dist/rpc/methods/search.mjs +26 -20
- package/dist/rpc/methods/session.mjs +289 -260
- package/dist/rpc/methods/shopConfiguration.mjs +12 -9
- package/dist/rpc/methods/user.mjs +87 -78
- package/dist/rpc/methods/variants.mjs +17 -14
- package/dist/rpc/methods/wishlist.mjs +71 -62
- package/dist/utils/hash.mjs +2 -7
- package/dist/utils/sapi.mjs +10 -7
- package/package.json +1 -1
|
@@ -21,93 +21,102 @@ const getUser = defineRpcHandler(
|
|
|
21
21
|
// We use POST here to prevent user data to be leaking into caches.
|
|
22
22
|
{ method: "POST" }
|
|
23
23
|
);
|
|
24
|
-
const fetchUser = defineRpcHandler(
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
user.authentication
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return user;
|
|
40
|
-
}, { method: "POST" });
|
|
41
|
-
const refreshUser = defineRpcHandler(async (context) => {
|
|
42
|
-
if (!hasSession(context)) {
|
|
43
|
-
return new ErrorResponse(
|
|
44
|
-
HttpStatusCode.BAD_REQUEST,
|
|
45
|
-
HttpStatusMessage.BAD_REQUEST,
|
|
46
|
-
"No Session found"
|
|
24
|
+
const fetchUser = defineRpcHandler(
|
|
25
|
+
async ({ accessToken }, context) => {
|
|
26
|
+
const { shopId } = context;
|
|
27
|
+
const client = new CustomerAPIClient(context);
|
|
28
|
+
const user = await client.getMe(shopId, accessToken);
|
|
29
|
+
if (!user.authentication) {
|
|
30
|
+
user.authentication = {
|
|
31
|
+
type: "idp"
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (user.email) {
|
|
35
|
+
user.emailHash = await sha256(user.email);
|
|
36
|
+
}
|
|
37
|
+
user.orderSummary = user.orderSummary?.filter(
|
|
38
|
+
({ shopId: shopId2 }) => shopId2 === context.shopId
|
|
47
39
|
);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
40
|
+
return user;
|
|
41
|
+
},
|
|
42
|
+
{ method: "POST" }
|
|
43
|
+
);
|
|
44
|
+
const refreshUser = defineRpcHandler(
|
|
45
|
+
async (context) => {
|
|
46
|
+
if (!hasSession(context)) {
|
|
47
|
+
return new ErrorResponse(
|
|
48
|
+
HttpStatusCode.BAD_REQUEST,
|
|
49
|
+
HttpStatusMessage.BAD_REQUEST,
|
|
50
|
+
"No Session found"
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
const { accessToken } = context;
|
|
54
|
+
if (!accessToken) {
|
|
56
55
|
return { user: void 0 };
|
|
57
56
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (!context.
|
|
57
|
+
try {
|
|
58
|
+
const user = await context.callRpc?.("fetchUser", { accessToken });
|
|
59
|
+
if (!user) {
|
|
60
|
+
return { user: void 0 };
|
|
61
|
+
}
|
|
62
|
+
context.updateUser(user);
|
|
63
|
+
return { user };
|
|
64
|
+
} catch {
|
|
65
|
+
await context.destroySession();
|
|
66
|
+
return { user: void 0 };
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{ method: "POST" }
|
|
70
|
+
);
|
|
71
|
+
const getAccessToken = defineRpcHandler(
|
|
72
|
+
async ({ forceTokenRefresh = false } = { forceTokenRefresh: false }, context) => {
|
|
73
|
+
if (!hasSession(context)) {
|
|
74
|
+
return new ErrorResponse(
|
|
75
|
+
HttpStatusCode.BAD_REQUEST,
|
|
76
|
+
HttpStatusMessage.BAD_REQUEST,
|
|
77
|
+
"No Session found"
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
if (!context.accessToken) {
|
|
82
81
|
return new ErrorResponse(
|
|
83
82
|
HttpStatusCode.UNAUTHORIZED,
|
|
84
83
|
HttpStatusMessage.UNAUTHORIZED,
|
|
85
|
-
"No
|
|
84
|
+
"No access token present"
|
|
86
85
|
);
|
|
87
86
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
context.updateTokens({
|
|
95
|
-
accessToken: tokens.access_token,
|
|
96
|
-
refreshToken: tokens.refresh_token
|
|
97
|
-
});
|
|
98
|
-
} catch (e) {
|
|
99
|
-
if (e instanceof FetchError && e.response.status === HttpStatusCode.UNAUTHORIZED) {
|
|
100
|
-
context.log.debug(
|
|
101
|
-
"Failed to refresh Checkout Token due to invalid refresh token. Deleting session"
|
|
102
|
-
);
|
|
103
|
-
await context.destroySession();
|
|
104
|
-
} else {
|
|
105
|
-
context.log.debug(
|
|
106
|
-
"Failed to refresh Checkout Token for unknown reason."
|
|
87
|
+
if (forceTokenRefresh) {
|
|
88
|
+
if (!context.refreshToken) {
|
|
89
|
+
return new ErrorResponse(
|
|
90
|
+
HttpStatusCode.UNAUTHORIZED,
|
|
91
|
+
HttpStatusMessage.UNAUTHORIZED,
|
|
92
|
+
"No refresh token present"
|
|
107
93
|
);
|
|
108
94
|
}
|
|
95
|
+
const client = getOAuthClient(context);
|
|
96
|
+
try {
|
|
97
|
+
const tokens = await client.refreshToken({
|
|
98
|
+
grant_type: "refresh_token",
|
|
99
|
+
refresh_token: context.refreshToken
|
|
100
|
+
});
|
|
101
|
+
context.updateTokens({
|
|
102
|
+
accessToken: tokens.access_token,
|
|
103
|
+
refreshToken: tokens.refresh_token
|
|
104
|
+
});
|
|
105
|
+
} catch (e) {
|
|
106
|
+
if (e instanceof FetchError && e.response.status === HttpStatusCode.UNAUTHORIZED) {
|
|
107
|
+
context.log.debug(
|
|
108
|
+
"Failed to refresh Checkout Token due to invalid refresh token. Deleting session"
|
|
109
|
+
);
|
|
110
|
+
await context.destroySession();
|
|
111
|
+
} else {
|
|
112
|
+
context.log.debug(
|
|
113
|
+
"Failed to refresh Checkout Token for unknown reason."
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
109
117
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
118
|
+
return context.accessToken;
|
|
119
|
+
},
|
|
120
|
+
{ method: "POST" }
|
|
121
|
+
);
|
|
113
122
|
export { getUser, fetchUser, refreshUser, getAccessToken };
|
|
@@ -3,17 +3,20 @@ import { defineRpcHandler } from "../../utils/rpc.mjs";
|
|
|
3
3
|
const defaultWith = {
|
|
4
4
|
attributes: "all"
|
|
5
5
|
};
|
|
6
|
-
export const getVariantById = defineRpcHandler(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
6
|
+
export const getVariantById = defineRpcHandler(
|
|
7
|
+
async ({ ids, include = defaultWith, pricePromotionKey = "default" }, context) => {
|
|
8
|
+
const { sapiClient, cached, withParams } = context;
|
|
9
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
10
|
+
const resolvedWith = include ?? withParams?.variant ?? defaultWith;
|
|
11
|
+
return await cached(
|
|
12
|
+
mapSAPIFetchErrorToResponse(sapiClient.variants.getByIds),
|
|
13
|
+
{
|
|
14
|
+
cacheKeyPrefix: "getByIds-variants"
|
|
15
|
+
}
|
|
16
|
+
)(
|
|
17
|
+
ids,
|
|
18
|
+
include ? { with: resolvedWith, campaignKey, pricePromotionKey } : void 0
|
|
19
|
+
);
|
|
20
|
+
},
|
|
21
|
+
{ method: "GET" }
|
|
22
|
+
);
|
|
@@ -22,9 +22,12 @@ export const getWishlist = defineRpcHandler(
|
|
|
22
22
|
}
|
|
23
23
|
const { sapiClient, wishlistKey } = context;
|
|
24
24
|
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
25
|
-
const { pricePromotionKey, ...resolvedWith } = getWithParams(
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
const { pricePromotionKey, ...resolvedWith } = getWithParams(
|
|
26
|
+
{
|
|
27
|
+
with: options
|
|
28
|
+
},
|
|
29
|
+
context
|
|
30
|
+
);
|
|
28
31
|
return await mapSAPIFetchErrorToResponse(sapiClient.wishlist.get)(
|
|
29
32
|
wishlistKey,
|
|
30
33
|
{
|
|
@@ -36,69 +39,75 @@ export const getWishlist = defineRpcHandler(
|
|
|
36
39
|
},
|
|
37
40
|
{ method: "POST" }
|
|
38
41
|
);
|
|
39
|
-
export const addItemToWishlist = defineRpcHandler(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (!productId && !variantId) {
|
|
55
|
-
return new ErrorResponse(
|
|
56
|
-
HttpStatusCode.BAD_REQUEST,
|
|
57
|
-
HttpStatusMessage.BAD_REQUEST,
|
|
58
|
-
"No productId or variantId given"
|
|
42
|
+
export const addItemToWishlist = defineRpcHandler(
|
|
43
|
+
async (options, context) => {
|
|
44
|
+
if (!hasSession(context)) {
|
|
45
|
+
return new ErrorResponse(
|
|
46
|
+
HttpStatusCode.BAD_REQUEST,
|
|
47
|
+
HttpStatusMessage.BAD_REQUEST,
|
|
48
|
+
"No Session found"
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
const { sapiClient, wishlistKey } = context;
|
|
52
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
53
|
+
const { productId, variantId } = options;
|
|
54
|
+
const { pricePromotionKey, ...resolvedWith } = getWithParams(
|
|
55
|
+
options,
|
|
56
|
+
context
|
|
59
57
|
);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
campaignKey,
|
|
67
|
-
pricePromotionKey: pricePromotionKey ?? ""
|
|
58
|
+
if (!productId && !variantId) {
|
|
59
|
+
return new ErrorResponse(
|
|
60
|
+
HttpStatusCode.BAD_REQUEST,
|
|
61
|
+
HttpStatusMessage.BAD_REQUEST,
|
|
62
|
+
"No productId or variantId given"
|
|
63
|
+
);
|
|
68
64
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}, { method: "PUT" });
|
|
78
|
-
export const removeItemFromWishlist = defineRpcHandler(async (options, context) => {
|
|
79
|
-
if (!hasSession(context)) {
|
|
80
|
-
return new ErrorResponse(
|
|
81
|
-
HttpStatusCode.BAD_REQUEST,
|
|
82
|
-
HttpStatusMessage.BAD_REQUEST,
|
|
83
|
-
"No Session found"
|
|
65
|
+
const result = await sapiClient.wishlist.addItem(
|
|
66
|
+
wishlistKey,
|
|
67
|
+
variantId ? { variantId } : { productId },
|
|
68
|
+
{
|
|
69
|
+
with: resolvedWith,
|
|
70
|
+
campaignKey,
|
|
71
|
+
pricePromotionKey: pricePromotionKey ?? ""
|
|
72
|
+
}
|
|
84
73
|
);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
);
|
|
92
|
-
return await mapSAPIFetchErrorToResponse(sapiClient.wishlist.deleteItem)(
|
|
93
|
-
wishlistKey,
|
|
94
|
-
options.itemKey,
|
|
95
|
-
{
|
|
96
|
-
with: resolvedWith,
|
|
97
|
-
campaignKey,
|
|
98
|
-
pricePromotionKey: pricePromotionKey ?? ""
|
|
74
|
+
if (result.type === "success") {
|
|
75
|
+
return result.wishlist;
|
|
76
|
+
} else {
|
|
77
|
+
const { statusCode: code, kind, type } = result;
|
|
78
|
+
context.log.error("Adding to wishlist failed", result.wishlist);
|
|
79
|
+
return new Response(JSON.stringify({ kind, type }), { status: code });
|
|
99
80
|
}
|
|
100
|
-
|
|
101
|
-
|
|
81
|
+
},
|
|
82
|
+
{ method: "PUT" }
|
|
83
|
+
);
|
|
84
|
+
export const removeItemFromWishlist = defineRpcHandler(
|
|
85
|
+
async (options, context) => {
|
|
86
|
+
if (!hasSession(context)) {
|
|
87
|
+
return new ErrorResponse(
|
|
88
|
+
HttpStatusCode.BAD_REQUEST,
|
|
89
|
+
HttpStatusMessage.BAD_REQUEST,
|
|
90
|
+
"No Session found"
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
const { sapiClient, wishlistKey } = context;
|
|
94
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
95
|
+
const { pricePromotionKey, ...resolvedWith } = getWithParams(
|
|
96
|
+
options,
|
|
97
|
+
context
|
|
98
|
+
);
|
|
99
|
+
return await mapSAPIFetchErrorToResponse(sapiClient.wishlist.deleteItem)(
|
|
100
|
+
wishlistKey,
|
|
101
|
+
options.itemKey,
|
|
102
|
+
{
|
|
103
|
+
with: resolvedWith,
|
|
104
|
+
campaignKey,
|
|
105
|
+
pricePromotionKey: pricePromotionKey ?? ""
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
},
|
|
109
|
+
{ method: "DELETE" }
|
|
110
|
+
);
|
|
102
111
|
export const clearWishlist = defineRpcHandler(
|
|
103
112
|
async (context) => {
|
|
104
113
|
const wishlistResponse = await getWishlist({}, context);
|
package/dist/utils/hash.mjs
CHANGED
|
@@ -35,15 +35,10 @@ export const hmac = async (value, secret, algorithm = "SHA-256") => {
|
|
|
35
35
|
};
|
|
36
36
|
function base64ToBytes(base64) {
|
|
37
37
|
const binString = atob(base64);
|
|
38
|
-
return Uint8Array.from(
|
|
39
|
-
binString,
|
|
40
|
-
(m) => m.codePointAt(0)
|
|
41
|
-
);
|
|
38
|
+
return Uint8Array.from(binString, (m) => m.codePointAt(0));
|
|
42
39
|
}
|
|
43
40
|
function bytesToBase64(bytes) {
|
|
44
|
-
const binString = Array.from(bytes, (x) => String.fromCodePoint(x)).join(
|
|
45
|
-
""
|
|
46
|
-
);
|
|
41
|
+
const binString = Array.from(bytes, (x) => String.fromCodePoint(x)).join("");
|
|
47
42
|
return btoa(binString);
|
|
48
43
|
}
|
|
49
44
|
export const encodeBase64 = (string) => {
|
package/dist/utils/sapi.mjs
CHANGED
|
@@ -6,13 +6,16 @@ export function mapSAPIFetchErrorToResponse(func) {
|
|
|
6
6
|
} catch (e) {
|
|
7
7
|
if (e instanceof FetchError) {
|
|
8
8
|
const response = e.response;
|
|
9
|
-
return Response.json(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
return Response.json(
|
|
10
|
+
{
|
|
11
|
+
statusCode: response.status,
|
|
12
|
+
statusMessage: response.statusText
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
status: response.status,
|
|
16
|
+
statusText: response.statusText
|
|
17
|
+
}
|
|
18
|
+
);
|
|
16
19
|
}
|
|
17
20
|
throw e;
|
|
18
21
|
}
|