@scayle/storefront-core 7.64.4 → 7.65.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 +22 -0
- package/dist/api/customer.cjs +1 -5
- package/dist/api/customer.mjs +1 -3
- package/dist/cache/cached.cjs +1 -1
- package/dist/cache/cached.mjs +1 -1
- package/dist/rpc/methods/cbd.cjs +23 -25
- package/dist/rpc/methods/cbd.d.ts +2 -1
- package/dist/rpc/methods/cbd.mjs +48 -28
- package/dist/rpc/methods/checkout/checkout.cjs +5 -1
- package/dist/rpc/methods/checkout/checkout.mjs +9 -1
- package/dist/rpc/methods/products.cjs +74 -64
- package/dist/rpc/methods/products.d.ts +22 -4
- package/dist/rpc/methods/products.mjs +74 -58
- package/dist/types/bapi/filter.d.ts +8 -3
- package/dist/types/bapi/product.d.ts +16 -7
- package/dist/utils/hash.cjs +5 -4
- package/dist/utils/hash.d.ts +1 -1
- package/dist/utils/hash.mjs +3 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @scayle/storefront-core
|
|
2
2
|
|
|
3
|
+
## 7.65.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fix regresion in product RPC methods where the categoryId may not be resolved from the category path
|
|
8
|
+
|
|
9
|
+
## 7.65.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- Improves the handling of `getOrderDataByCbd` RPC to return descriptive errors in case the validation of the token fails.
|
|
14
|
+
|
|
15
|
+
In case the token can't be validated using the Checkout Secret, this is now returned and a warning on the server is logged.
|
|
16
|
+
|
|
17
|
+
If the token has expired, this is now also returned and logged on the server.
|
|
18
|
+
|
|
19
|
+
- Support passing `categoryId` as an alternative to the category path in `getProductsByCategory` and `getFilters`
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Fixed cached fallback ttl to be used only if passed `option.ttl` is undefined
|
|
24
|
+
|
|
3
25
|
## 7.64.4
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
package/dist/api/customer.cjs
CHANGED
|
@@ -15,14 +15,10 @@ class CustomerAPIClient {
|
|
|
15
15
|
this.context = context;
|
|
16
16
|
}
|
|
17
17
|
get headers() {
|
|
18
|
-
const accessHeader = this.context.checkout.accessHeader;
|
|
19
18
|
return {
|
|
20
19
|
Authorization: `Bearer ${this.context.accessToken}`,
|
|
21
20
|
Accept: "application/json",
|
|
22
|
-
"Content-Type": "application/json"
|
|
23
|
-
...(accessHeader ? {
|
|
24
|
-
"X-Access-Header": accessHeader
|
|
25
|
-
} : {})
|
|
21
|
+
"Content-Type": "application/json"
|
|
26
22
|
};
|
|
27
23
|
}
|
|
28
24
|
async sendRequest(request, retry = true) {
|
package/dist/api/customer.mjs
CHANGED
|
@@ -9,12 +9,10 @@ export class CustomerAPIClient {
|
|
|
9
9
|
this.context = context;
|
|
10
10
|
}
|
|
11
11
|
get headers() {
|
|
12
|
-
const accessHeader = this.context.checkout.accessHeader;
|
|
13
12
|
return {
|
|
14
13
|
Authorization: `Bearer ${this.context.accessToken}`,
|
|
15
14
|
Accept: "application/json",
|
|
16
|
-
"Content-Type": "application/json"
|
|
17
|
-
...accessHeader ? { "X-Access-Header": accessHeader } : {}
|
|
15
|
+
"Content-Type": "application/json"
|
|
18
16
|
};
|
|
19
17
|
}
|
|
20
18
|
async sendRequest(request, retry = true) {
|
package/dist/cache/cached.cjs
CHANGED
|
@@ -71,7 +71,7 @@ class Cached {
|
|
|
71
71
|
if (!this.isCacheEnabled) {
|
|
72
72
|
return;
|
|
73
73
|
}
|
|
74
|
-
const ttl = options?.ttl
|
|
74
|
+
const ttl = options?.ttl ?? 60 * MINUTE;
|
|
75
75
|
if (ttl) {
|
|
76
76
|
await (0, _utils.timeout)(_constants.CACHE_TIMEOUT, this.cache.set(cacheKey, value, ttl));
|
|
77
77
|
}
|
package/dist/cache/cached.mjs
CHANGED
package/dist/rpc/methods/cbd.cjs
CHANGED
|
@@ -4,37 +4,35 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getOrderDataByCbd = void 0;
|
|
7
|
+
var _constants = require("../../constants/index.cjs");
|
|
8
|
+
var _errors = require("../../errors/index.cjs");
|
|
7
9
|
var _hash = require("../../utils/hash.cjs");
|
|
8
10
|
const getOrderDataByCbd = exports.getOrderDataByCbd = async function getOrderDataByCbd2({
|
|
9
11
|
cbdToken
|
|
10
12
|
}, context) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
const payload = await (0, _hash.verifyOrderSuccessToken)(cbdToken, context.checkout.secret);
|
|
14
|
+
if (!payload) {
|
|
15
|
+
context.log.warn("Unable to verify CBD token. Please check that you configured the correct Checkout Secret");
|
|
16
|
+
return new _errors.ErrorResponse(_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusMessage.BAD_REQUEST, "Unable to verify CBD token.");
|
|
13
17
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
context.
|
|
25
|
-
return;
|
|
18
|
+
if (context.checkout.cbdExpiration && Math.floor(Date.now() / 1e3) - payload.issued_at > context.checkout.cbdExpiration) {
|
|
19
|
+
context.log.warn("Attempting to use expired CBD token");
|
|
20
|
+
return new _errors.ErrorResponse(_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusMessage.BAD_REQUEST, "The CBD token has expired.");
|
|
21
|
+
}
|
|
22
|
+
const checkoutUrl = context.checkout.url;
|
|
23
|
+
const basicAuth = (0, _hash.encodeBase64)(`${context.checkout.user}:${context.checkout.token}`);
|
|
24
|
+
const response = await fetch(`${checkoutUrl}/api/v1/orders/${payload.order_id}`, {
|
|
25
|
+
headers: {
|
|
26
|
+
Accept: "application/json",
|
|
27
|
+
Authorization: `Basic ${basicAuth}`,
|
|
28
|
+
"X-Shop-Id": context.shopId.toString()
|
|
26
29
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
headers: {
|
|
30
|
-
Accept: "application/json",
|
|
31
|
-
Authorization: `Basic ${accessToken}`,
|
|
32
|
-
"x-shop-id": shopId.toString(),
|
|
33
|
-
...(accessHeader ? {
|
|
34
|
-
"X-Access-Header": accessHeader
|
|
35
|
-
} : {})
|
|
36
|
-
}
|
|
37
|
-
});
|
|
30
|
+
});
|
|
31
|
+
if (response.ok) {
|
|
38
32
|
return await response.json();
|
|
39
33
|
}
|
|
34
|
+
context.log.error(`Unexpected status code when fetching order from Checkout API: ${response.status}`);
|
|
35
|
+
return new _errors.ErrorResponse(_constants.HttpStatusCode.INTERNAL_SERVER_ERROR, _constants.HttpStatusMessage.INTERNAL_SERVER_ERROR, "Unknown error", {
|
|
36
|
+
detail: `Fetching order failed with status code ${response.status}`
|
|
37
|
+
});
|
|
40
38
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
+
import { ErrorResponse } from '../../errors';
|
|
1
2
|
import type { Order, RpcContext } from '../../types';
|
|
2
3
|
export declare const getOrderDataByCbd: ({ cbdToken }: {
|
|
3
4
|
cbdToken: string;
|
|
4
|
-
}, context: RpcContext) => Promise<Order |
|
|
5
|
+
}, context: RpcContext) => Promise<Order | ErrorResponse>;
|
package/dist/rpc/methods/cbd.mjs
CHANGED
|
@@ -1,35 +1,55 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HttpStatusCode, HttpStatusMessage } from "../../constants/index.mjs";
|
|
2
|
+
import { ErrorResponse } from "../../errors/index.mjs";
|
|
3
|
+
import { encodeBase64, verifyOrderSuccessToken } from "../../utils/hash.mjs";
|
|
2
4
|
export const getOrderDataByCbd = async function getOrderDataByCbd2({ cbdToken }, context) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
const payload = await verifyOrderSuccessToken(
|
|
6
|
+
cbdToken,
|
|
7
|
+
context.checkout.secret
|
|
8
|
+
);
|
|
9
|
+
if (!payload) {
|
|
10
|
+
context.log.warn(
|
|
11
|
+
"Unable to verify CBD token. Please check that you configured the correct Checkout Secret"
|
|
12
|
+
);
|
|
13
|
+
return new ErrorResponse(
|
|
14
|
+
HttpStatusCode.BAD_REQUEST,
|
|
15
|
+
HttpStatusMessage.BAD_REQUEST,
|
|
16
|
+
"Unable to verify CBD token."
|
|
17
|
+
);
|
|
5
18
|
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const checkoutUsername = context.checkout.user;
|
|
13
|
-
const checkoutToken = context.checkout.token;
|
|
14
|
-
const checkoutUrl = context.checkout.url;
|
|
15
|
-
if (context.checkout.cbdExpiration && Math.floor(Date.now() / 1e3) - payload.issued_at > context.checkout.cbdExpiration) {
|
|
16
|
-
context.log.debug("Attempting to use expired CBD token");
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
const accessToken = encodeBase64(
|
|
20
|
-
`${checkoutUsername}:${unescape(checkoutToken)}`
|
|
19
|
+
if (context.checkout.cbdExpiration && Math.floor(Date.now() / 1e3) - payload.issued_at > context.checkout.cbdExpiration) {
|
|
20
|
+
context.log.warn("Attempting to use expired CBD token");
|
|
21
|
+
return new ErrorResponse(
|
|
22
|
+
HttpStatusCode.BAD_REQUEST,
|
|
23
|
+
HttpStatusMessage.BAD_REQUEST,
|
|
24
|
+
"The CBD token has expired."
|
|
21
25
|
);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
}
|
|
27
|
+
const checkoutUrl = context.checkout.url;
|
|
28
|
+
const basicAuth = encodeBase64(
|
|
29
|
+
`${context.checkout.user}:${context.checkout.token}`
|
|
30
|
+
);
|
|
31
|
+
const response = await fetch(
|
|
32
|
+
`${checkoutUrl}/api/v1/orders/${payload.order_id}`,
|
|
33
|
+
{
|
|
34
|
+
headers: {
|
|
35
|
+
Accept: "application/json",
|
|
36
|
+
Authorization: `Basic ${basicAuth}`,
|
|
37
|
+
"X-Shop-Id": context.shopId.toString()
|
|
31
38
|
}
|
|
32
|
-
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
if (response.ok) {
|
|
33
42
|
return await response.json();
|
|
34
43
|
}
|
|
44
|
+
context.log.error(
|
|
45
|
+
`Unexpected status code when fetching order from Checkout API: ${response.status}`
|
|
46
|
+
);
|
|
47
|
+
return new ErrorResponse(
|
|
48
|
+
HttpStatusCode.INTERNAL_SERVER_ERROR,
|
|
49
|
+
HttpStatusMessage.INTERNAL_SERVER_ERROR,
|
|
50
|
+
"Unknown error",
|
|
51
|
+
{
|
|
52
|
+
detail: `Fetching order failed with status code ${response.status}`
|
|
53
|
+
}
|
|
54
|
+
);
|
|
35
55
|
};
|
|
@@ -5,10 +5,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.getCheckoutToken = void 0;
|
|
7
7
|
var _jose = require("jose");
|
|
8
|
+
var _types = require("../../../types/index.cjs");
|
|
8
9
|
var _errors = require("../../../errors/index.cjs");
|
|
9
10
|
var _constants = require("../../../constants/index.cjs");
|
|
10
11
|
var _user = require("../user.cjs");
|
|
11
12
|
const getCheckoutToken = exports.getCheckoutToken = async function getCheckoutToken2(jwtPayload = {}, context) {
|
|
13
|
+
if (!(0, _types.hasSession)(context)) {
|
|
14
|
+
return new _errors.ErrorResponse(_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusMessage.BAD_REQUEST, "No Session found");
|
|
15
|
+
}
|
|
12
16
|
if (!context.accessToken) {
|
|
13
17
|
return new _errors.ErrorResponse(_constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusMessage.UNAUTHORIZED, "No access token present");
|
|
14
18
|
}
|
|
@@ -33,7 +37,7 @@ const getCheckoutToken = exports.getCheckoutToken = async function getCheckoutTo
|
|
|
33
37
|
carrier,
|
|
34
38
|
basketId: context.basketKey,
|
|
35
39
|
campaignKey: context.campaignKey
|
|
36
|
-
}).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.
|
|
40
|
+
}).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.1"}`).setProtectedHeader({
|
|
37
41
|
alg: "HS256",
|
|
38
42
|
typ: "JWT"
|
|
39
43
|
}).sign(secret);
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { SignJWT } from "jose";
|
|
2
|
+
import { hasSession } from "../../../types/index.mjs";
|
|
2
3
|
import { ErrorResponse } from "../../../errors/index.mjs";
|
|
3
4
|
import { HttpStatusCode, HttpStatusMessage } from "../../../constants/index.mjs";
|
|
4
5
|
import { getAccessToken } from "../user.mjs";
|
|
5
6
|
export const getCheckoutToken = async function getCheckoutToken2(jwtPayload = {}, context) {
|
|
7
|
+
if (!hasSession(context)) {
|
|
8
|
+
return new ErrorResponse(
|
|
9
|
+
HttpStatusCode.BAD_REQUEST,
|
|
10
|
+
HttpStatusMessage.BAD_REQUEST,
|
|
11
|
+
"No Session found"
|
|
12
|
+
);
|
|
13
|
+
}
|
|
6
14
|
if (!context.accessToken) {
|
|
7
15
|
return new ErrorResponse(
|
|
8
16
|
HttpStatusCode.UNAUTHORIZED,
|
|
@@ -27,7 +35,7 @@ export const getCheckoutToken = async function getCheckoutToken2(jwtPayload = {}
|
|
|
27
35
|
carrier,
|
|
28
36
|
basketId: context.basketKey,
|
|
29
37
|
campaignKey: context.campaignKey
|
|
30
|
-
}).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.
|
|
38
|
+
}).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.65.1"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
|
|
31
39
|
return {
|
|
32
40
|
accessToken: refreshedAccessToken,
|
|
33
41
|
checkoutJwt
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getProductsCount = exports.getProductsByReferenceKeys = exports.getProductsByIds = exports.getProductsByCategory = exports.getProductById = exports.getFilters = exports.fetchAllFiltersForCategory = void 0;
|
|
7
|
+
exports.resolveCategoryIdFromParams = resolveCategoryIdFromParams;
|
|
7
8
|
var _helpers = require("../../helpers/index.cjs");
|
|
8
9
|
var _constants = require("../../constants/index.cjs");
|
|
9
10
|
var _cache = require("../../cache/index.cjs");
|
|
@@ -22,6 +23,25 @@ const sanitizeAttributesForBAPI = ({
|
|
|
22
23
|
const mapFiltersToSlugs = (filters = []) => filters.map(({
|
|
23
24
|
slug
|
|
24
25
|
}) => slug.toLowerCase());
|
|
26
|
+
async function resolveCategoryIdFromParams(context, params) {
|
|
27
|
+
let category;
|
|
28
|
+
let categoryId;
|
|
29
|
+
if ("categoryId" in params) {
|
|
30
|
+
categoryId = params.categoryId;
|
|
31
|
+
} else if (params.category && params.category !== "/") {
|
|
32
|
+
category = params.category;
|
|
33
|
+
const result = await context.cached(context.bapiClient.categories.getByPath, {
|
|
34
|
+
cacheKeyPrefix: `getByPath-categories-${category}`
|
|
35
|
+
})((0, _helpers.splitAndRemoveEmpty)(category));
|
|
36
|
+
categoryId = result.id;
|
|
37
|
+
} else {
|
|
38
|
+
category = "/";
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
category,
|
|
42
|
+
categoryId
|
|
43
|
+
};
|
|
44
|
+
}
|
|
25
45
|
const getProductById = exports.getProductById = async function getProductById2(options, {
|
|
26
46
|
bapiClient,
|
|
27
47
|
cached,
|
|
@@ -68,31 +88,27 @@ const getProductsByReferenceKeys = exports.getProductsByReferenceKeys = async fu
|
|
|
68
88
|
pricePromotionKey: options.pricePromotionKey
|
|
69
89
|
});
|
|
70
90
|
};
|
|
71
|
-
const getProductsCount = exports.getProductsCount = async function getProductsCount2({
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
result = await cached(bapiClient.categories.getByPath, {
|
|
87
|
-
cacheKeyPrefix: `getByPath-categories-${sanitizedPath}`
|
|
88
|
-
})(sanitizedPath);
|
|
89
|
-
}
|
|
91
|
+
const getProductsCount = exports.getProductsCount = async function getProductsCount2(params, context) {
|
|
92
|
+
const {
|
|
93
|
+
where = void 0,
|
|
94
|
+
includeSoldOut = false,
|
|
95
|
+
includeSellableForFree = false,
|
|
96
|
+
orFiltersOperator = void 0
|
|
97
|
+
} = params;
|
|
98
|
+
const {
|
|
99
|
+
cached,
|
|
100
|
+
bapiClient,
|
|
101
|
+
campaignKey
|
|
102
|
+
} = context;
|
|
103
|
+
const {
|
|
104
|
+
categoryId
|
|
105
|
+
} = await resolveCategoryIdFromParams(context, params);
|
|
90
106
|
const productCount = await cached(bapiClient.products.query, {
|
|
91
107
|
ttl: 15 * _cache.MINUTE,
|
|
92
108
|
cacheKeyPrefix: "products-query"
|
|
93
109
|
})({
|
|
94
110
|
where: {
|
|
95
|
-
categoryId
|
|
111
|
+
categoryId,
|
|
96
112
|
minPrice: where?.minPrice,
|
|
97
113
|
maxPrice: where?.maxPrice,
|
|
98
114
|
attributes: where?.attributes,
|
|
@@ -131,32 +147,29 @@ const fetchAllFiltersForCategory = exports.fetchAllFiltersForCategory = async fu
|
|
|
131
147
|
return await cached(fetchAndMapFiltersToSlugs, {
|
|
132
148
|
ttl: 4 * 60 * 60,
|
|
133
149
|
// cached for 4 hours
|
|
134
|
-
cacheKey: `filters-for-category-${category.
|
|
150
|
+
cacheKey: `filters-for-category-${category.id}`
|
|
135
151
|
})();
|
|
136
152
|
};
|
|
137
|
-
const getFilters = exports.getFilters = async function getFilters2({
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
let result;
|
|
153
|
+
const getFilters = exports.getFilters = async function getFilters2(params, context) {
|
|
154
|
+
const {
|
|
155
|
+
includedFilters,
|
|
156
|
+
where = void 0,
|
|
157
|
+
includeSoldOut = false,
|
|
158
|
+
includeSellableForFree = false,
|
|
159
|
+
orFiltersOperator
|
|
160
|
+
} = params;
|
|
146
161
|
const {
|
|
147
162
|
cached,
|
|
148
163
|
bapiClient,
|
|
149
164
|
campaignKey
|
|
150
165
|
} = context;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
166
|
+
const {
|
|
167
|
+
category,
|
|
168
|
+
categoryId
|
|
169
|
+
} = await resolveCategoryIdFromParams(context, params);
|
|
156
170
|
const response = await fetchAllFiltersForCategory({
|
|
157
171
|
category: {
|
|
158
|
-
id:
|
|
159
|
-
slug: category
|
|
172
|
+
id: categoryId
|
|
160
173
|
},
|
|
161
174
|
includedFilters
|
|
162
175
|
}, context);
|
|
@@ -170,10 +183,10 @@ const getFilters = exports.getFilters = async function getFilters2({
|
|
|
170
183
|
includedFilters
|
|
171
184
|
});
|
|
172
185
|
const [filters, productCount] = await Promise.all([cached(bapiClient.filters.get, {
|
|
173
|
-
cacheKeyPrefix: `get-filters-${
|
|
186
|
+
cacheKeyPrefix: `get-filters-${categoryId}`
|
|
174
187
|
})({
|
|
175
188
|
where: {
|
|
176
|
-
categoryId
|
|
189
|
+
categoryId,
|
|
177
190
|
minPrice: where?.minPrice,
|
|
178
191
|
maxPrice: where?.maxPrice,
|
|
179
192
|
term: where?.term,
|
|
@@ -186,10 +199,10 @@ const getFilters = exports.getFilters = async function getFilters2({
|
|
|
186
199
|
orFiltersOperator
|
|
187
200
|
}), cached(bapiClient.products.query, {
|
|
188
201
|
ttl: 15 * _cache.MINUTE,
|
|
189
|
-
cacheKeyPrefix: `products-query-category-${category === "/" ? "root" :
|
|
202
|
+
cacheKeyPrefix: `products-query-category-${category === "/" ? "root" : categoryId}`
|
|
190
203
|
})({
|
|
191
204
|
where: {
|
|
192
|
-
categoryId
|
|
205
|
+
categoryId,
|
|
193
206
|
minPrice: where?.minPrice,
|
|
194
207
|
maxPrice: where?.maxPrice,
|
|
195
208
|
term: where?.term,
|
|
@@ -207,34 +220,31 @@ const getFilters = exports.getFilters = async function getFilters2({
|
|
|
207
220
|
unfilteredCount: productCount?.pagination.total
|
|
208
221
|
};
|
|
209
222
|
};
|
|
210
|
-
const getProductsByCategory = exports.getProductsByCategory = async function getProductsByCategory2({
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
let result;
|
|
223
|
+
const getProductsByCategory = exports.getProductsByCategory = async function getProductsByCategory2(params, context) {
|
|
224
|
+
const {
|
|
225
|
+
cache,
|
|
226
|
+
with: _with,
|
|
227
|
+
perPage = 20,
|
|
228
|
+
page = 1,
|
|
229
|
+
where = void 0,
|
|
230
|
+
sort = void 0,
|
|
231
|
+
pricePromotionKey = "",
|
|
232
|
+
includeSellableForFree = void 0,
|
|
233
|
+
includeSoldOut = void 0,
|
|
234
|
+
orFiltersOperator = void 0
|
|
235
|
+
} = params;
|
|
224
236
|
const {
|
|
225
237
|
cached,
|
|
226
238
|
bapiClient,
|
|
227
239
|
campaignKey
|
|
228
240
|
} = context;
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
241
|
+
const {
|
|
242
|
+
category,
|
|
243
|
+
categoryId
|
|
244
|
+
} = await resolveCategoryIdFromParams(context, params);
|
|
234
245
|
const response = await fetchAllFiltersForCategory({
|
|
235
246
|
category: {
|
|
236
|
-
id:
|
|
237
|
-
slug: category
|
|
247
|
+
id: categoryId
|
|
238
248
|
}
|
|
239
249
|
}, context);
|
|
240
250
|
if (response instanceof _errors.ErrorResponse) {
|
|
@@ -251,11 +261,11 @@ const getProductsByCategory = exports.getProductsByCategory = async function get
|
|
|
251
261
|
} = await cached(bapiClient.products.query, {
|
|
252
262
|
...cache,
|
|
253
263
|
ttl: 15 * _cache.MINUTE,
|
|
254
|
-
cacheKeyPrefix: `products-query-category-${category === "/" ? "root" :
|
|
264
|
+
cacheKeyPrefix: `products-query-category-${category === "/" ? "root" : categoryId}`
|
|
255
265
|
})({
|
|
256
266
|
where: {
|
|
257
267
|
term: where?.term,
|
|
258
|
-
categoryId
|
|
268
|
+
categoryId,
|
|
259
269
|
minPrice: where?.minPrice,
|
|
260
270
|
maxPrice: where?.maxPrice,
|
|
261
271
|
attributes: [...sanitizedAttributes, ...(where?.whitelistAttributes || [])],
|
|
@@ -1,24 +1,42 @@
|
|
|
1
1
|
import type { FiltersEndpointResponseData } from '@scayle/storefront-api';
|
|
2
2
|
import type { FetchFiltersParams, FetchProductParams, FetchProductsByCategoryParams, FetchProductsByIdsParams, FetchProductsByReferenceKeysParams, FetchProductsCountParams, Product, RpcContext } from '../../types';
|
|
3
3
|
import { ErrorResponse } from '../../errors';
|
|
4
|
+
/**
|
|
5
|
+
* For functions which accept either a category path or category ID,
|
|
6
|
+
* this function can resolve the ID which is necessary for the calling
|
|
7
|
+
* the Storefront APIs.
|
|
8
|
+
* @param context
|
|
9
|
+
* @param params
|
|
10
|
+
* @returns A object with `category` and `categoryId` properties.
|
|
11
|
+
* If no `category` was provided in the params, it will be undefined or '/'
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveCategoryIdFromParams(context: RpcContext, params: {
|
|
14
|
+
category?: string;
|
|
15
|
+
categoryId?: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
categoryId: number;
|
|
18
|
+
category?: undefined;
|
|
19
|
+
}): Promise<{
|
|
20
|
+
category: string | undefined;
|
|
21
|
+
categoryId: number | undefined;
|
|
22
|
+
}>;
|
|
4
23
|
export declare const getProductById: (options: FetchProductParams, { bapiClient, cached, campaignKey, withParams }: RpcContext) => Promise<Product>;
|
|
5
24
|
export declare const getProductsByIds: (options: FetchProductsByIdsParams, { bapiClient, cached, campaignKey, withParams }: RpcContext) => Promise<Product[]>;
|
|
6
25
|
export declare const getProductsByReferenceKeys: (options: FetchProductsByReferenceKeysParams, { bapiClient, cached, campaignKey, withParams }: RpcContext) => Promise<Product[]>;
|
|
7
|
-
export declare const getProductsCount: (
|
|
26
|
+
export declare const getProductsCount: (params: FetchProductsCountParams, context: RpcContext) => Promise<{
|
|
8
27
|
count: number;
|
|
9
28
|
}>;
|
|
10
29
|
export declare const fetchAllFiltersForCategory: ({ includedFilters, category }: {
|
|
11
30
|
includedFilters?: string[];
|
|
12
31
|
category: {
|
|
13
|
-
slug: string;
|
|
14
32
|
id?: number;
|
|
15
33
|
};
|
|
16
34
|
}, { cached, bapiClient, campaignKey }: RpcContext) => Promise<string[]>;
|
|
17
|
-
export declare const getFilters: (
|
|
35
|
+
export declare const getFilters: (params: FetchFiltersParams, context: RpcContext) => Promise<(string[] & ErrorResponse) | {
|
|
18
36
|
filters: FiltersEndpointResponseData;
|
|
19
37
|
unfilteredCount: number;
|
|
20
38
|
}>;
|
|
21
|
-
export declare const getProductsByCategory: (
|
|
39
|
+
export declare const getProductsByCategory: (params: FetchProductsByCategoryParams, context: RpcContext) => Promise<(string[] & ErrorResponse) | {
|
|
22
40
|
products: Product[];
|
|
23
41
|
pagination: {
|
|
24
42
|
current: number;
|
|
@@ -14,6 +14,25 @@ const sanitizeAttributesForBAPI = ({
|
|
|
14
14
|
);
|
|
15
15
|
};
|
|
16
16
|
const mapFiltersToSlugs = (filters = []) => filters.map(({ slug }) => slug.toLowerCase());
|
|
17
|
+
export async function resolveCategoryIdFromParams(context, params) {
|
|
18
|
+
let category;
|
|
19
|
+
let categoryId;
|
|
20
|
+
if ("categoryId" in params) {
|
|
21
|
+
categoryId = params.categoryId;
|
|
22
|
+
} else if (params.category && params.category !== "/") {
|
|
23
|
+
category = params.category;
|
|
24
|
+
const result = await context.cached(
|
|
25
|
+
context.bapiClient.categories.getByPath,
|
|
26
|
+
{
|
|
27
|
+
cacheKeyPrefix: `getByPath-categories-${category}`
|
|
28
|
+
}
|
|
29
|
+
)(splitAndRemoveEmpty(category));
|
|
30
|
+
categoryId = result.id;
|
|
31
|
+
} else {
|
|
32
|
+
category = "/";
|
|
33
|
+
}
|
|
34
|
+
return { category, categoryId };
|
|
35
|
+
}
|
|
17
36
|
export const getProductById = async function getProductById2(options, { bapiClient, cached, campaignKey, withParams }) {
|
|
18
37
|
return await cached(bapiClient.products.getById, {
|
|
19
38
|
cacheKeyPrefix: `getById-product-${options.id}`,
|
|
@@ -45,27 +64,21 @@ export const getProductsByReferenceKeys = async function getProductsByReferenceK
|
|
|
45
64
|
pricePromotionKey: options.pricePromotionKey
|
|
46
65
|
});
|
|
47
66
|
};
|
|
48
|
-
export const getProductsCount = async function getProductsCount2({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (category !== "/") {
|
|
58
|
-
const sanitizedPath = splitAndRemoveEmpty(category);
|
|
59
|
-
result = await cached(bapiClient.categories.getByPath, {
|
|
60
|
-
cacheKeyPrefix: `getByPath-categories-${sanitizedPath}`
|
|
61
|
-
})(sanitizedPath);
|
|
62
|
-
}
|
|
67
|
+
export const getProductsCount = async function getProductsCount2(params, context) {
|
|
68
|
+
const {
|
|
69
|
+
where = void 0,
|
|
70
|
+
includeSoldOut = false,
|
|
71
|
+
includeSellableForFree = false,
|
|
72
|
+
orFiltersOperator = void 0
|
|
73
|
+
} = params;
|
|
74
|
+
const { cached, bapiClient, campaignKey } = context;
|
|
75
|
+
const { categoryId } = await resolveCategoryIdFromParams(context, params);
|
|
63
76
|
const productCount = await cached(bapiClient.products.query, {
|
|
64
77
|
ttl: 15 * MINUTE,
|
|
65
78
|
cacheKeyPrefix: "products-query"
|
|
66
79
|
})({
|
|
67
80
|
where: {
|
|
68
|
-
categoryId
|
|
81
|
+
categoryId,
|
|
69
82
|
minPrice: where?.minPrice,
|
|
70
83
|
maxPrice: where?.maxPrice,
|
|
71
84
|
attributes: where?.attributes,
|
|
@@ -95,26 +108,27 @@ export const fetchAllFiltersForCategory = async function fetchAllFiltersForCateg
|
|
|
95
108
|
return await cached(fetchAndMapFiltersToSlugs, {
|
|
96
109
|
ttl: 4 * 60 * 60,
|
|
97
110
|
// cached for 4 hours
|
|
98
|
-
cacheKey: `filters-for-category-${category.
|
|
111
|
+
cacheKey: `filters-for-category-${category.id}`
|
|
99
112
|
})();
|
|
100
113
|
};
|
|
101
|
-
export const getFilters = async function getFilters2({
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
let result;
|
|
114
|
+
export const getFilters = async function getFilters2(params, context) {
|
|
115
|
+
const {
|
|
116
|
+
includedFilters,
|
|
117
|
+
where = void 0,
|
|
118
|
+
includeSoldOut = false,
|
|
119
|
+
includeSellableForFree = false,
|
|
120
|
+
orFiltersOperator
|
|
121
|
+
} = params;
|
|
110
122
|
const { cached, bapiClient, campaignKey } = context;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
123
|
+
const { category, categoryId } = await resolveCategoryIdFromParams(
|
|
124
|
+
context,
|
|
125
|
+
params
|
|
126
|
+
);
|
|
116
127
|
const response = await fetchAllFiltersForCategory(
|
|
117
|
-
{
|
|
128
|
+
{
|
|
129
|
+
category: { id: categoryId },
|
|
130
|
+
includedFilters
|
|
131
|
+
},
|
|
118
132
|
context
|
|
119
133
|
);
|
|
120
134
|
if (response instanceof ErrorResponse) {
|
|
@@ -128,10 +142,10 @@ export const getFilters = async function getFilters2({
|
|
|
128
142
|
});
|
|
129
143
|
const [filters, productCount] = await Promise.all([
|
|
130
144
|
cached(bapiClient.filters.get, {
|
|
131
|
-
cacheKeyPrefix: `get-filters-${
|
|
145
|
+
cacheKeyPrefix: `get-filters-${categoryId}`
|
|
132
146
|
})({
|
|
133
147
|
where: {
|
|
134
|
-
categoryId
|
|
148
|
+
categoryId,
|
|
135
149
|
minPrice: where?.minPrice,
|
|
136
150
|
maxPrice: where?.maxPrice,
|
|
137
151
|
term: where?.term,
|
|
@@ -148,10 +162,10 @@ export const getFilters = async function getFilters2({
|
|
|
148
162
|
}),
|
|
149
163
|
cached(bapiClient.products.query, {
|
|
150
164
|
ttl: 15 * MINUTE,
|
|
151
|
-
cacheKeyPrefix: `products-query-category-${category === "/" ? "root" :
|
|
165
|
+
cacheKeyPrefix: `products-query-category-${category === "/" ? "root" : categoryId}`
|
|
152
166
|
})({
|
|
153
167
|
where: {
|
|
154
|
-
categoryId
|
|
168
|
+
categoryId,
|
|
155
169
|
minPrice: where?.minPrice,
|
|
156
170
|
maxPrice: where?.maxPrice,
|
|
157
171
|
term: where?.term,
|
|
@@ -173,28 +187,30 @@ export const getFilters = async function getFilters2({
|
|
|
173
187
|
unfilteredCount: productCount?.pagination.total
|
|
174
188
|
};
|
|
175
189
|
};
|
|
176
|
-
export const getProductsByCategory = async function getProductsByCategory2({
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
let result;
|
|
190
|
+
export const getProductsByCategory = async function getProductsByCategory2(params, context) {
|
|
191
|
+
const {
|
|
192
|
+
cache,
|
|
193
|
+
with: _with,
|
|
194
|
+
perPage = 20,
|
|
195
|
+
page = 1,
|
|
196
|
+
where = void 0,
|
|
197
|
+
sort = void 0,
|
|
198
|
+
pricePromotionKey = "",
|
|
199
|
+
includeSellableForFree = void 0,
|
|
200
|
+
includeSoldOut = void 0,
|
|
201
|
+
orFiltersOperator = void 0
|
|
202
|
+
} = params;
|
|
190
203
|
const { cached, bapiClient, campaignKey } = context;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
204
|
+
const { category, categoryId } = await resolveCategoryIdFromParams(
|
|
205
|
+
context,
|
|
206
|
+
params
|
|
207
|
+
);
|
|
196
208
|
const response = await fetchAllFiltersForCategory(
|
|
197
|
-
{
|
|
209
|
+
{
|
|
210
|
+
category: {
|
|
211
|
+
id: categoryId
|
|
212
|
+
}
|
|
213
|
+
},
|
|
198
214
|
context
|
|
199
215
|
);
|
|
200
216
|
if (response instanceof ErrorResponse) {
|
|
@@ -210,12 +226,12 @@ export const getProductsByCategory = async function getProductsByCategory2({
|
|
|
210
226
|
{
|
|
211
227
|
...cache,
|
|
212
228
|
ttl: 15 * MINUTE,
|
|
213
|
-
cacheKeyPrefix: `products-query-category-${category === "/" ? "root" :
|
|
229
|
+
cacheKeyPrefix: `products-query-category-${category === "/" ? "root" : categoryId}`
|
|
214
230
|
}
|
|
215
231
|
)({
|
|
216
232
|
where: {
|
|
217
233
|
term: where?.term,
|
|
218
|
-
categoryId
|
|
234
|
+
categoryId,
|
|
219
235
|
minPrice: where?.minPrice,
|
|
220
236
|
maxPrice: where?.maxPrice,
|
|
221
237
|
attributes: [
|
|
@@ -15,8 +15,7 @@ export interface FilterParams {
|
|
|
15
15
|
sort?: ProductSortConfig;
|
|
16
16
|
orFiltersOperator?: ProductsSearchEndpointParameters['orFiltersOperator'];
|
|
17
17
|
}
|
|
18
|
-
export
|
|
19
|
-
category: string;
|
|
18
|
+
export type FetchFiltersParams = {
|
|
20
19
|
includedFilters?: Array<string>;
|
|
21
20
|
where?: {
|
|
22
21
|
term?: ProductSearchQuery['term'];
|
|
@@ -28,7 +27,13 @@ export interface FetchFiltersParams {
|
|
|
28
27
|
includeSoldOut?: boolean;
|
|
29
28
|
includeSellableForFree?: boolean;
|
|
30
29
|
orFiltersOperator?: ProductsSearchEndpointParameters['orFiltersOperator'];
|
|
31
|
-
}
|
|
30
|
+
} & ({
|
|
31
|
+
category?: string;
|
|
32
|
+
categoryId?: undefined;
|
|
33
|
+
} | {
|
|
34
|
+
categoryId: number;
|
|
35
|
+
category?: undefined;
|
|
36
|
+
});
|
|
32
37
|
export interface FetchFiltersResponse {
|
|
33
38
|
filters: FiltersEndpointResponseData;
|
|
34
39
|
unfilteredCount: number;
|
|
@@ -43,8 +43,7 @@ export interface FetchProductsByReferenceKeysParams {
|
|
|
43
43
|
with?: ProductWith;
|
|
44
44
|
pricePromotionKey?: string;
|
|
45
45
|
}
|
|
46
|
-
export
|
|
47
|
-
category: string;
|
|
46
|
+
export type FetchProductsByCategoryParams = {
|
|
48
47
|
with?: ProductWith;
|
|
49
48
|
cache?: CacheOptions;
|
|
50
49
|
includedFilters?: Array<string>;
|
|
@@ -63,14 +62,18 @@ export interface FetchProductsByCategoryParams {
|
|
|
63
62
|
includeSellableForFree?: boolean;
|
|
64
63
|
includeSoldOut?: boolean;
|
|
65
64
|
orFiltersOperator?: ProductsSearchEndpointParameters['orFiltersOperator'];
|
|
66
|
-
}
|
|
65
|
+
} & ({
|
|
66
|
+
category?: string;
|
|
67
|
+
categoryId?: undefined;
|
|
68
|
+
} | {
|
|
69
|
+
categoryId: number;
|
|
70
|
+
category?: undefined;
|
|
71
|
+
});
|
|
67
72
|
export interface FetchProductsByCategoryResponse {
|
|
68
73
|
products: Product[];
|
|
69
74
|
pagination: ProductsByIdsEndpointResponseData['pagination'];
|
|
70
75
|
}
|
|
71
|
-
export
|
|
72
|
-
category?: string;
|
|
73
|
-
categoryId?: number;
|
|
76
|
+
export type FetchProductsCountParams = {
|
|
74
77
|
where?: {
|
|
75
78
|
term?: ProductSearchQuery['term'];
|
|
76
79
|
minPrice?: ProductSearchQuery['minPrice'];
|
|
@@ -80,7 +83,13 @@ export interface FetchProductsCountParams {
|
|
|
80
83
|
includeSoldOut?: boolean;
|
|
81
84
|
includeSellableForFree?: boolean;
|
|
82
85
|
orFiltersOperator?: ProductsSearchEndpointParameters['orFiltersOperator'];
|
|
83
|
-
}
|
|
86
|
+
} & ({
|
|
87
|
+
category?: string;
|
|
88
|
+
categoryId?: undefined;
|
|
89
|
+
} | {
|
|
90
|
+
categoryId: number;
|
|
91
|
+
category?: undefined;
|
|
92
|
+
});
|
|
84
93
|
export interface FetchProductsCountResponse {
|
|
85
94
|
count: number;
|
|
86
95
|
}
|
package/dist/utils/hash.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.verifyOrderSuccessToken = exports.sha256 = exports.md5 = exports.hmac = exports.encodeBase64 = exports.decodeBase64 = exports.buildSignature = exports.buildHashPayload = void 0;
|
|
7
7
|
var _uncrypto = require("uncrypto");
|
|
8
8
|
const md5 = async value => {
|
|
9
9
|
if (!process.env.SFC_OMIT_MD5) {
|
|
@@ -54,14 +54,15 @@ const decodeBase64 = string => {
|
|
|
54
54
|
return new TextDecoder().decode(base64ToBytes(string));
|
|
55
55
|
};
|
|
56
56
|
exports.decodeBase64 = decodeBase64;
|
|
57
|
-
const
|
|
57
|
+
const verifyOrderSuccessToken = async (token, secret) => {
|
|
58
58
|
const [encodedPayload, signature] = token.split(".", 2);
|
|
59
59
|
const expectedSignature = encodeBase64(await hmac(encodedPayload, secret));
|
|
60
60
|
if (expectedSignature === signature) {
|
|
61
|
-
return decodeBase64(encodedPayload);
|
|
61
|
+
return JSON.parse(decodeBase64(encodedPayload));
|
|
62
62
|
}
|
|
63
|
+
return void 0;
|
|
63
64
|
};
|
|
64
|
-
exports.
|
|
65
|
+
exports.verifyOrderSuccessToken = verifyOrderSuccessToken;
|
|
65
66
|
const buildHashPayload = payload => encodeBase64(JSON.stringify(payload));
|
|
66
67
|
exports.buildHashPayload = buildHashPayload;
|
|
67
68
|
const buildSignature = async (payloadHash, secret) => encodeBase64(await hmac(payloadHash, secret));
|
package/dist/utils/hash.d.ts
CHANGED
|
@@ -3,6 +3,6 @@ export declare const sha256: (value: string) => Promise<string>;
|
|
|
3
3
|
export declare const hmac: (value: string, secret: string, algorithm?: string) => Promise<string>;
|
|
4
4
|
export declare const encodeBase64: (string: string) => string;
|
|
5
5
|
export declare const decodeBase64: (string: string) => string;
|
|
6
|
-
export declare const
|
|
6
|
+
export declare const verifyOrderSuccessToken: <T = unknown>(token: string, secret: string) => Promise<T | undefined>;
|
|
7
7
|
export declare const buildHashPayload: (payload: unknown) => string;
|
|
8
8
|
export declare const buildSignature: (payloadHash: string, secret: string) => Promise<string>;
|
package/dist/utils/hash.mjs
CHANGED
|
@@ -50,12 +50,13 @@ export const decodeBase64 = (string) => {
|
|
|
50
50
|
}
|
|
51
51
|
return new TextDecoder().decode(base64ToBytes(string));
|
|
52
52
|
};
|
|
53
|
-
export const
|
|
53
|
+
export const verifyOrderSuccessToken = async (token, secret) => {
|
|
54
54
|
const [encodedPayload, signature] = token.split(".", 2);
|
|
55
55
|
const expectedSignature = encodeBase64(await hmac(encodedPayload, secret));
|
|
56
56
|
if (expectedSignature === signature) {
|
|
57
|
-
return decodeBase64(encodedPayload);
|
|
57
|
+
return JSON.parse(decodeBase64(encodedPayload));
|
|
58
58
|
}
|
|
59
|
+
return void 0;
|
|
59
60
|
};
|
|
60
61
|
export const buildHashPayload = (payload) => encodeBase64(JSON.stringify(payload));
|
|
61
62
|
export const buildSignature = async (payloadHash, secret) => encodeBase64(await hmac(payloadHash, secret));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scayle/storefront-core",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.65.1",
|
|
4
4
|
"description": "Collection of essential utilities to work with the Storefront API",
|
|
5
5
|
"author": "SCAYLE Commerce Engine",
|
|
6
6
|
"license": "MIT",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"@types/crypto-js": "4.2.2",
|
|
74
74
|
"@types/node": "20.16.5",
|
|
75
75
|
"@types/webpack-env": "1.18.5",
|
|
76
|
-
"@vitest/coverage-v8": "2.
|
|
76
|
+
"@vitest/coverage-v8": "2.1.1",
|
|
77
77
|
"dprint": "0.47.2",
|
|
78
78
|
"eslint": "9.10.0",
|
|
79
79
|
"eslint-formatter-gitlab": "5.1.0",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"typescript": "5.6.2",
|
|
84
84
|
"unbuild": "2.0.0",
|
|
85
85
|
"unstorage": "1.12.0",
|
|
86
|
-
"vitest": "2.
|
|
86
|
+
"vitest": "2.1.1"
|
|
87
87
|
},
|
|
88
88
|
"optionalDependencies": {
|
|
89
89
|
"redis": "4"
|