@scayle/storefront-core 7.38.1 → 7.39.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,19 @@
1
1
  # @scayle/storefront-core
2
2
 
3
+ ## 7.39.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Persist accessToken to user.authentication
8
+
9
+ ## 7.39.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Add `sortable` option to `groupFilterableValuesByKey` filter helper
14
+ - Add `sortable` option to `getGroupedFilterableValues` to provide the ability for custom sorting implementation for specific filtersGroups
15
+ - Authentication RPC methods include status codes in error cases
16
+
3
17
  ## 7.38.1
4
18
 
5
19
  ### Patch Changes
@@ -164,8 +178,8 @@
164
178
 
165
179
  ### Minor Changes
166
180
 
167
- - - Add `promotion` RPC methods and types
168
- - - Add promotion data within the basket payloads
181
+ - Add `promotion` RPC methods and types
182
+ - Add promotion data within the basket payloads
169
183
 
170
184
  ### Patch Changes
171
185
 
@@ -373,9 +387,9 @@
373
387
 
374
388
  ### Minor Changes
375
389
 
376
- - - Replaced `enums` with the companion object pattern approach.
377
- - - Replaced `HttpStatusMessage` number values with the actual message
378
- - - Exposed `HashAlgorithm` constant with its type and move it to the core
390
+ - Replaced `enums` with the companion object pattern approach.
391
+ - Replaced `HttpStatusMessage` number values with the actual message
392
+ - Exposed `HashAlgorithm` constant with its type and move it to the core
379
393
  - **Breaking:** If you are importing `HashAlgorithm` from `@scayle/storefront-nuxt2` change to importing it from `@scayle/storefront-core`
380
394
 
381
395
  ## 7.1.0
package/README.md CHANGED
@@ -1,10 +1,24 @@
1
- # Storefront Core
2
-
3
- [![npm version][npm-version-src]][npm-version-href]
4
- [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
- [![License][license-src]][license-href]
6
-
7
- This is a shared package for framework-independent components of the Storefront Core.
1
+ <div align="center">
2
+ <img src="https://cdn-prod.scayle.com/public/media/general/SCAYLE-Commerce-Engine-header.png" />
3
+ </div>
4
+
5
+ <div align="center">
6
+ <h1>SCAYLE Storefront Core</h1>
7
+ </div>
8
+
9
+ <div align="center">
10
+ <h4><a href="https://scayle.dev">Documentation</a> | <a href="https://www.scayle.com/">Website</a></h4>
11
+ </div>
12
+
13
+ <div align="center">
14
+ The SCAYLE <strong>Storefront Core SDK</strong> package contains framework-independent components of the Storefront Boilerplate.
15
+ </div>
16
+ <br/>
17
+ <div align="center">
18
+ <a href="https://www.npmjs.com/package/@scayle/storefront-core"><img src="https://img.shields.io/npm/v/@scayle/storefront-core/latest.svg?style=flat&colorB=007ec6" /></a>
19
+ <a href="https://www.npmjs.com/package/@scayle/storefront-core"><img src="https://img.shields.io/npm/dm/@scayle/storefront-core.svg?style=flat&colorB=007ec6" /></a>
20
+ <a href="https://www.npmjs.com/package/@scayle/storefront-core"><img src="https://img.shields.io/badge/license-MIT-blue.svg" /></a>
21
+ </div>
8
22
 
9
23
  ## Installation
10
24
 
@@ -19,11 +33,23 @@ yarn add @scayle/storefront-core
19
33
  npm install @scayle/storefront-core
20
34
  ```
21
35
 
22
- <!-- Badges -->
36
+ ## Getting Started
37
+
38
+ Visit the [Quickstart Guide](https://scayle.dev/en/dev/storefront-core/getting-started-sfb) to get started with Storefront Core.
39
+
40
+ Visit the [Docs](https://scayle.dev) to learn more about our system requirements.
41
+
42
+ ## What is SCAYLE?
43
+
44
+ [SCAYLE](https://scayle.com) is a full-featured e-commerce software solution that comes with flexible APIs. Within SCAYLE, you can manage all aspects of your shop, such as products, stocks, customers, and transactions.
45
+
46
+ Learn more about [Scayle’s architecture](https://scayle.dev/en/dev/getting-started/introduction) and [commerce modules](https://scayle.dev/en/dev/getting-started/introduction) in the Docs.
47
+
48
+ ## Other channels
49
+
50
+ - [LinkedIn](https://www.linkedin.com/company/scaylecommerce/)
51
+ - [Jobs](https://careers.smartrecruiters.com/ABOUTYOUGmbH/scayle)
52
+
53
+ ## License
23
54
 
24
- [npm-version-src]: https://img.shields.io/npm/v/@scayle/storefront-core/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
25
- [npm-version-href]: https://npmjs.com/package/@scayle/storefront-core
26
- [npm-downloads-src]: https://img.shields.io/npm/dm/@scayle/storefront-core.svg?style=flat&colorA=18181B&colorB=28CF8D
27
- [npm-downloads-href]: https://npmjs.com/package/@scayle/storefront-core
28
- [license-src]: https://img.shields.io/npm/l/@scayle/storefront-core.svg?style=flat&colorA=18181B&colorB=28CF8D
29
- [license-href]: https://npmjs.com/package/@scayle/storefront-core
55
+ Licensed under the [MIT](https://opensource.org/license/mit/)
@@ -34,19 +34,24 @@ const transformToWhereCondition = conditions => {
34
34
  return where;
35
35
  };
36
36
  exports.transformToWhereCondition = transformToWhereCondition;
37
- const groupFilterableValuesByKey = (filters, filterableKeys) => {
37
+ const groupFilterableValuesByKey = (filters, filterableKeys, {
38
+ sortable
39
+ } = {
40
+ sortable: true
41
+ }) => {
38
42
  const enabledFilters = filterableKeys ? filters.filter(filter => filterableKeys.includes(filter.slug)) : filters;
39
- const availableFilters = [];
40
- enabledFilters.forEach(filter => {
41
- ;
43
+ const transformedAvailableFilters = enabledFilters.reduce((availableFilters, filter) => {
42
44
  filter.values.forEach(value => {
43
- if (filter.type === "boolean" && value.name === false) {
45
+ const isBoolean = filter.type === _backbone.FilterTypes.BOOLEAN;
46
+ const hasNameInValue = ("name" in value);
47
+ if (isBoolean && hasNameInValue && value.name === false) {
44
48
  return;
45
49
  }
46
50
  const filterValue = _getFilterValueByType(value, filter.type);
51
+ const nameValue = hasNameInValue ? String(value.name) : "";
47
52
  availableFilters.push({
48
53
  key: filter.slug,
49
- displayName: filter.type === "boolean" ? filter.name : value.name,
54
+ displayName: isBoolean ? filter.name : nameValue,
50
55
  count: value.productCount,
51
56
  value: filterValue,
52
57
  whereCondition: {
@@ -54,8 +59,9 @@ const groupFilterableValuesByKey = (filters, filterableKeys) => {
54
59
  }
55
60
  });
56
61
  });
57
- });
58
- return availableFilters.sort((a, b) => a.displayName < b.displayName ? -1 : 1);
62
+ return availableFilters;
63
+ }, []);
64
+ return sortable ? transformedAvailableFilters.sort((a, b) => a.displayName.localeCompare(b.displayName)) : transformedAvailableFilters;
59
65
  };
60
66
  exports.groupFilterableValuesByKey = groupFilterableValuesByKey;
61
67
  const transformStateToFilters = state => {
@@ -99,10 +105,16 @@ const transformSortToFilter = sort => {
99
105
  return (0, _sortingHelper.getSortByValue)(sort);
100
106
  };
101
107
  exports.transformSortToFilter = transformSortToFilter;
102
- const getGroupedFilterableValues = (keys, filterableValues) => {
103
- return keys.reduce((acc, key) => {
104
- acc[key] = groupFilterableValuesByKey(filterableValues, [key]);
105
- return acc;
108
+ const getGroupedFilterableValues = (keys, filterableValues, {
109
+ sortable
110
+ } = {
111
+ sortable: true
112
+ }) => {
113
+ return keys.reduce((filtersGroup, key) => {
114
+ filtersGroup[key] = groupFilterableValuesByKey(filterableValues, [key], {
115
+ sortable
116
+ });
117
+ return filtersGroup;
106
118
  }, {});
107
119
  };
108
120
  exports.getGroupedFilterableValues = getGroupedFilterableValues;
@@ -25,7 +25,9 @@ export declare const transformToWhereCondition: (conditions: Record<string, any>
25
25
  * @param filters
26
26
  * @param filterableKeys
27
27
  */
28
- export declare const groupFilterableValuesByKey: (filters: ProductFilter[], filterableKeys?: Array<string>) => Array<TransformedFilter>;
28
+ export declare const groupFilterableValuesByKey: (filters: ProductFilter[], filterableKeys?: string[], { sortable }?: {
29
+ sortable: boolean;
30
+ }) => TransformedFilter[];
29
31
  export declare const transformStateToFilters: (state: {
30
32
  [key: string]: TransformedFilter[];
31
33
  }) => any;
@@ -63,7 +65,9 @@ export declare const transformSortToFilter: (sort: string) => {
63
65
  name: "reduction_asc";
64
66
  query: "reduction-asc";
65
67
  };
66
- export declare const getGroupedFilterableValues: (keys: Array<string>, filterableValues: ProductFilter[]) => Record<string, any>;
68
+ export declare const getGroupedFilterableValues: (keys: Array<string>, filterableValues: ProductFilter[], { sortable }?: {
69
+ sortable: boolean;
70
+ }) => Record<string, TransformedFilter[]>;
67
71
  export declare const isFilterActive: (filters: Record<string, any>, filterToCheck: TransformedFilter) => any;
68
72
  export declare const getFilterablePriceValue: (filterableValues: Record<string, any>, key?: 'min' | 'max') => any;
69
73
  export type SerializedFilter = Record<string, string>;
@@ -25,19 +25,20 @@ export const transformToWhereCondition = (conditions) => {
25
25
  });
26
26
  return where;
27
27
  };
28
- export const groupFilterableValuesByKey = (filters, filterableKeys) => {
28
+ export const groupFilterableValuesByKey = (filters, filterableKeys, { sortable } = { sortable: true }) => {
29
29
  const enabledFilters = filterableKeys ? filters.filter((filter) => filterableKeys.includes(filter.slug)) : filters;
30
- const availableFilters = [];
31
- enabledFilters.forEach((filter) => {
32
- ;
30
+ const transformedAvailableFilters = enabledFilters.reduce((availableFilters, filter) => {
33
31
  filter.values.forEach((value) => {
34
- if (filter.type === "boolean" && value.name === false) {
32
+ const isBoolean = filter.type === FilterTypes.BOOLEAN;
33
+ const hasNameInValue = "name" in value;
34
+ if (isBoolean && hasNameInValue && value.name === false) {
35
35
  return;
36
36
  }
37
37
  const filterValue = _getFilterValueByType(value, filter.type);
38
+ const nameValue = hasNameInValue ? String(value.name) : "";
38
39
  availableFilters.push({
39
40
  key: filter.slug,
40
- displayName: filter.type === "boolean" ? filter.name : value.name,
41
+ displayName: isBoolean ? filter.name : nameValue,
41
42
  count: value.productCount,
42
43
  value: filterValue,
43
44
  whereCondition: {
@@ -45,10 +46,11 @@ export const groupFilterableValuesByKey = (filters, filterableKeys) => {
45
46
  }
46
47
  });
47
48
  });
48
- });
49
- return availableFilters.sort(
50
- (a, b) => a.displayName < b.displayName ? -1 : 1
51
- );
49
+ return availableFilters;
50
+ }, []);
51
+ return sortable ? transformedAvailableFilters.sort(
52
+ (a, b) => a.displayName.localeCompare(b.displayName)
53
+ ) : transformedAvailableFilters;
52
54
  };
53
55
  export const transformStateToFilters = (state) => {
54
56
  return Object.values(state).reduce(
@@ -92,11 +94,16 @@ export const transformMinAndMaxPriceToFilter = (prices) => {
92
94
  export const transformSortToFilter = (sort) => {
93
95
  return getSortByValue(sort);
94
96
  };
95
- export const getGroupedFilterableValues = (keys, filterableValues) => {
96
- return keys.reduce((acc, key) => {
97
- acc[key] = groupFilterableValuesByKey(filterableValues, [key]);
98
- return acc;
99
- }, {});
97
+ export const getGroupedFilterableValues = (keys, filterableValues, { sortable } = { sortable: true }) => {
98
+ return keys.reduce(
99
+ (filtersGroup, key) => {
100
+ filtersGroup[key] = groupFilterableValuesByKey(filterableValues, [key], {
101
+ sortable
102
+ });
103
+ return filtersGroup;
104
+ },
105
+ {}
106
+ );
100
107
  };
101
108
  export const isFilterActive = (filters, filterToCheck) => {
102
109
  const key = filterToCheck.key;
@@ -8,6 +8,7 @@ var _errors = require("../../../errors/index.cjs");
8
8
  var _types = require("../../../types/index.cjs");
9
9
  var _constants = require("../../../constants/index.cjs");
10
10
  var _user = require("../../../utils/user.cjs");
11
+ var _response = require("../../../utils/response.cjs");
11
12
  const BAPI_ERROR_NAME = "BAPI ERROR";
12
13
  function getWithParams(params, context) {
13
14
  return params.with ?? context.withParams?.basket ?? _constants.MIN_WITH_PARAMS_BASKET;
@@ -145,7 +146,7 @@ const removeItemFromBasket = exports.removeItemFromBasket = async function remov
145
146
  });
146
147
  };
147
148
  const clearBasket = exports.clearBasket = async function clearBasket2(context) {
148
- const basket = await getBasket({}, context);
149
+ const basket = await (0, _response.unwrap)(getBasket({}, context));
149
150
  await Promise.all(basket.items.map(async item => {
150
151
  await removeItemFromBasket({
151
152
  itemKey: item.key
@@ -7,6 +7,7 @@ import {
7
7
  MIN_WITH_PARAMS_BASKET
8
8
  } from "../../../constants/index.mjs";
9
9
  import { mergeBaskets as mergeBasketFunction } from "../../../utils/user.mjs";
10
+ import { unwrap } from "../../../utils/response.mjs";
10
11
  const BAPI_ERROR_NAME = "BAPI ERROR";
11
12
  function getWithParams(params, context) {
12
13
  return params.with ?? context.withParams?.basket ?? MIN_WITH_PARAMS_BASKET;
@@ -147,7 +148,7 @@ export const removeItemFromBasket = async function removeItemFromBasket2(options
147
148
  });
148
149
  };
149
150
  export const clearBasket = async function clearBasket2(context) {
150
- const basket = await getBasket({}, context);
151
+ const basket = await unwrap(getBasket({}, context));
151
152
  await Promise.all(
152
153
  basket.items.map(async (item) => {
153
154
  await removeItemFromBasket({ itemKey: item.key }, context);
@@ -7,6 +7,7 @@ exports.getProductsCount = exports.getProductsByIds = exports.getProductsByCateg
7
7
  var _helpers = require("../../helpers/index.cjs");
8
8
  var _constants = require("../../constants/index.cjs");
9
9
  var _cache = require("../../cache/index.cjs");
10
+ var _response = require("../../utils/response.cjs");
10
11
  const MAX_PER_PAGE = 100;
11
12
  const getProductById = exports.getProductById = async function getProductById2(options, {
12
13
  bapiClient,
@@ -66,12 +67,12 @@ const getProductsByCategory = exports.getProductsByCategory = async function get
66
67
  }
67
68
  const {
68
69
  filters
69
- } = await getFilters({
70
+ } = await (0, _response.unwrap)(getFilters({
70
71
  category,
71
72
  includeSoldOut,
72
73
  where,
73
74
  includeSellableForFree
74
- }, context);
75
+ }, context));
75
76
  const {
76
77
  entities: products,
77
78
  pagination
@@ -127,13 +128,13 @@ const getFilters = exports.getFilters = async function getFilters2({
127
128
  result = await cached(bapiClient.categories.getByPath, {
128
129
  cacheKeyPrefix: `getByPath-categories-${category}`
129
130
  })((0, _helpers.splitAndRemoveEmpty)(category));
130
- allFiltersForCategory = await fetchAllFiltersForCategory({
131
+ allFiltersForCategory = await (0, _response.unwrap)(fetchAllFiltersForCategory({
131
132
  category: {
132
133
  id: result.id,
133
134
  slug: category
134
135
  },
135
136
  includedFilters
136
- }, context);
137
+ }, context));
137
138
  }
138
139
  const sanitizedAttributes = sanitizeAttributesForBAPI({
139
140
  attributes: where?.attributes || [],
@@ -1,6 +1,7 @@
1
1
  import { splitAndRemoveEmpty } from "../../helpers/index.mjs";
2
2
  import { MIN_WITH_PARAMS_PRODUCT } from "../../constants/index.mjs";
3
3
  import { MINUTE } from "../../cache/index.mjs";
4
+ import { unwrap } from "../../utils/response.mjs";
4
5
  const MAX_PER_PAGE = 100;
5
6
  export const getProductById = async function getProductById2(options, { bapiClient, cached, campaignKey, withParams }) {
6
7
  return await cached(bapiClient.products.getById, {
@@ -44,9 +45,11 @@ export const getProductsByCategory = async function getProductsByCategory2({
44
45
  cacheKeyPrefix: `getByPath-categories-${category}`
45
46
  })(splitAndRemoveEmpty(category));
46
47
  }
47
- const { filters } = await getFilters(
48
- { category, includeSoldOut, where, includeSellableForFree },
49
- context
48
+ const { filters } = await unwrap(
49
+ getFilters(
50
+ { category, includeSoldOut, where, includeSellableForFree },
51
+ context
52
+ )
50
53
  );
51
54
  const { entities: products, pagination } = await cached(
52
55
  bapiClient.products.query,
@@ -102,9 +105,11 @@ export const getFilters = async function getFilters2({
102
105
  result = await cached(bapiClient.categories.getByPath, {
103
106
  cacheKeyPrefix: `getByPath-categories-${category}`
104
107
  })(splitAndRemoveEmpty(category));
105
- allFiltersForCategory = await fetchAllFiltersForCategory(
106
- { category: { id: result.id, slug: category }, includedFilters },
107
- context
108
+ allFiltersForCategory = await unwrap(
109
+ fetchAllFiltersForCategory(
110
+ { category: { id: result.id, slug: category }, includedFilters },
111
+ context
112
+ )
108
113
  );
109
114
  }
110
115
  const sanitizedAttributes = sanitizeAttributesForBAPI({
@@ -10,18 +10,21 @@ var _constants = require("../../constants/index.cjs");
10
10
  var _fetch = require("../../utils/fetch.cjs");
11
11
  var _user = require("../../utils/user.cjs");
12
12
  var _user2 = require("../../rpc/methods/user.cjs");
13
+ var _response = require("../../utils/response.cjs");
13
14
  var _oauth = require("../../api/oauth.cjs");
14
15
  const convertErrorForRpcCall = (error, httpStatuses) => {
15
16
  if (error instanceof _fetch.FetchError && httpStatuses.includes(error.response.status)) {
16
- return error;
17
+ return new Response(null, {
18
+ status: error.response.status
19
+ });
17
20
  }
18
21
  };
19
22
  exports.convertErrorForRpcCall = convertErrorForRpcCall;
20
23
  async function postLogin(context, tokens) {
21
- const user = await (0, _user2.fetchUser)({
24
+ const user = await (0, _response.unwrap)((0, _user2.fetchUser)({
22
25
  accessToken: tokens.access_token,
23
26
  callback: ""
24
- }, context);
27
+ }, context));
25
28
  context.updateTokens({
26
29
  accessToken: tokens.access_token,
27
30
  refreshToken: tokens.refresh_token
@@ -47,11 +50,15 @@ const oauthLogin = async (login, context) => {
47
50
  });
48
51
  await postLogin(context, tokens);
49
52
  } catch (error) {
50
- const err = convertErrorForRpcCall(error, [_constants.HttpStatusCode.INTERNAL_SERVER_ERROR, _constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.NOT_FOUND, _constants.HttpStatusCode.FORBIDDEN]);
51
- if (err) {
52
- throw err;
53
+ const res = convertErrorForRpcCall(error, [_constants.HttpStatusCode.INTERNAL_SERVER_ERROR, _constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.NOT_FOUND, _constants.HttpStatusCode.FORBIDDEN]);
54
+ if (res) {
55
+ return res;
53
56
  }
57
+ throw error;
54
58
  }
59
+ return new Response(null, {
60
+ status: _constants.HttpStatusCode.NO_CONTENT
61
+ });
55
62
  };
56
63
  exports.oauthLogin = oauthLogin;
57
64
  const oauthRegister = async (register, context) => {
@@ -65,11 +72,15 @@ const oauthRegister = async (register, context) => {
65
72
  });
66
73
  await postLogin(context, tokens);
67
74
  } catch (error) {
68
- const err = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.CONFLICT, _constants.HttpStatusCode.FORBIDDEN]);
69
- if (err) {
70
- throw err;
75
+ const res = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.CONFLICT, _constants.HttpStatusCode.FORBIDDEN]);
76
+ if (res) {
77
+ return res;
71
78
  }
79
+ throw error;
72
80
  }
81
+ return new Response(null, {
82
+ status: _constants.HttpStatusCode.NO_CONTENT
83
+ });
73
84
  };
74
85
  exports.oauthRegister = oauthRegister;
75
86
  const oauthGuestLogin = async (guest, context) => {
@@ -83,11 +94,15 @@ const oauthGuestLogin = async (guest, context) => {
83
94
  });
84
95
  await postLogin(context, tokens);
85
96
  } catch (error) {
86
- const err = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.CONFLICT, _constants.HttpStatusCode.FORBIDDEN]);
87
- if (err) {
88
- throw err;
97
+ const res = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.CONFLICT, _constants.HttpStatusCode.FORBIDDEN]);
98
+ if (res) {
99
+ return res;
89
100
  }
101
+ throw error;
90
102
  }
103
+ return new Response(null, {
104
+ status: _constants.HttpStatusCode.NO_CONTENT
105
+ });
91
106
  };
92
107
  exports.oauthGuestLogin = oauthGuestLogin;
93
108
  const refreshAccessToken = async context => {
@@ -110,9 +125,9 @@ const refreshAccessToken = async context => {
110
125
  success: !!tokens
111
126
  };
112
127
  } catch (error) {
113
- const err = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED]);
114
- if (err) {
115
- throw err;
128
+ const res = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED]);
129
+ if (res) {
130
+ return res;
116
131
  }
117
132
  return {
118
133
  success: false
@@ -134,9 +149,9 @@ const oauthRevokeToken = async context => {
134
149
  result: true
135
150
  };
136
151
  } catch (error) {
137
- const err = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.NOT_FOUND]);
138
- if (err) {
139
- throw err;
152
+ const res = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.NOT_FOUND]);
153
+ if (res) {
154
+ return res;
140
155
  }
141
156
  return {
142
157
  result: false
@@ -169,9 +184,9 @@ const oauthForgetPassword = async ({
169
184
  success: true
170
185
  };
171
186
  } catch (error) {
172
- const err = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.NOT_FOUND, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.FORBIDDEN]);
173
- if (err) {
174
- throw err;
187
+ const res = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.NOT_FOUND, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.FORBIDDEN]);
188
+ if (res) {
189
+ return res;
175
190
  }
176
191
  return {
177
192
  success: false
@@ -194,10 +209,14 @@ const updatePasswordByHash = async (passwordHash, context) => {
194
209
  });
195
210
  await context.createUserBoundSession();
196
211
  } catch (error) {
197
- const err = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.NOT_ACCEPTABLE]);
198
- if (err) {
199
- throw err;
212
+ const res = convertErrorForRpcCall(error, [_constants.HttpStatusCode.BAD_REQUEST, _constants.HttpStatusCode.UNAUTHORIZED, _constants.HttpStatusCode.NOT_ACCEPTABLE]);
213
+ if (res) {
214
+ return res;
200
215
  }
216
+ throw error;
201
217
  }
218
+ return new Response(null, {
219
+ status: _constants.HttpStatusCode.NO_CONTENT
220
+ });
202
221
  };
203
222
  exports.updatePasswordByHash = updatePasswordByHash;
@@ -3,7 +3,7 @@ import type { GuestRequest, LoginRequest, ParamRpcHandler, RegisterRequest, RpcH
3
3
  /**
4
4
  * Ensure error is a fetch error with one of the status codes
5
5
  */
6
- export declare const convertErrorForRpcCall: (error: any, httpStatuses: Array<number>) => Error | undefined;
6
+ export declare const convertErrorForRpcCall: (error: any, httpStatuses: Array<number>) => Response | undefined;
7
7
  export declare const oauthLogin: ParamRpcHandler<Optional<LoginRequest, 'shop_id'>, undefined>;
8
8
  export declare const oauthRegister: ParamRpcHandler<Optional<RegisterRequest, 'shop_id'>, undefined>;
9
9
  export declare const oauthGuestLogin: ParamRpcHandler<Optional<GuestRequest, 'shop_id'>, undefined>;
@@ -4,16 +4,16 @@ import { DEFAULT_WITH_LISTING, HttpStatusCode } from "../../constants/index.mjs"
4
4
  import { FetchError } from "../../utils/fetch.mjs";
5
5
  import { mergeBaskets, mergeWishlists } from "../../utils/user.mjs";
6
6
  import { fetchUser } from "../../rpc/methods/user.mjs";
7
+ import { unwrap } from "../../utils/response.mjs";
7
8
  import { getOAuthClient } from "../../api/oauth.mjs";
8
9
  export const convertErrorForRpcCall = (error, httpStatuses) => {
9
10
  if (error instanceof FetchError && httpStatuses.includes(error.response.status)) {
10
- return error;
11
+ return new Response(null, { status: error.response.status });
11
12
  }
12
13
  };
13
14
  async function postLogin(context, tokens) {
14
- const user = await fetchUser(
15
- { accessToken: tokens.access_token, callback: "" },
16
- context
15
+ const user = await unwrap(
16
+ fetchUser({ accessToken: tokens.access_token, callback: "" }, context)
17
17
  );
18
18
  context.updateTokens({
19
19
  accessToken: tokens.access_token,
@@ -50,17 +50,19 @@ export const oauthLogin = async (login, context) => {
50
50
  const tokens = await client.login({ ...login, shop_id: shopId });
51
51
  await postLogin(context, tokens);
52
52
  } catch (error) {
53
- const err = convertErrorForRpcCall(error, [
53
+ const res = convertErrorForRpcCall(error, [
54
54
  HttpStatusCode.INTERNAL_SERVER_ERROR,
55
55
  HttpStatusCode.BAD_REQUEST,
56
56
  HttpStatusCode.UNAUTHORIZED,
57
57
  HttpStatusCode.NOT_FOUND,
58
58
  HttpStatusCode.FORBIDDEN
59
59
  ]);
60
- if (err) {
61
- throw err;
60
+ if (res) {
61
+ return res;
62
62
  }
63
+ throw error;
63
64
  }
65
+ return new Response(null, { status: HttpStatusCode.NO_CONTENT });
64
66
  };
65
67
  export const oauthRegister = async (register, context) => {
66
68
  assertSession(context);
@@ -73,16 +75,18 @@ export const oauthRegister = async (register, context) => {
73
75
  });
74
76
  await postLogin(context, tokens);
75
77
  } catch (error) {
76
- const err = convertErrorForRpcCall(error, [
78
+ const res = convertErrorForRpcCall(error, [
77
79
  HttpStatusCode.BAD_REQUEST,
78
80
  HttpStatusCode.UNAUTHORIZED,
79
81
  HttpStatusCode.CONFLICT,
80
82
  HttpStatusCode.FORBIDDEN
81
83
  ]);
82
- if (err) {
83
- throw err;
84
+ if (res) {
85
+ return res;
84
86
  }
87
+ throw error;
85
88
  }
89
+ return new Response(null, { status: HttpStatusCode.NO_CONTENT });
86
90
  };
87
91
  export const oauthGuestLogin = async (guest, context) => {
88
92
  assertSession(context);
@@ -95,16 +99,18 @@ export const oauthGuestLogin = async (guest, context) => {
95
99
  });
96
100
  await postLogin(context, tokens);
97
101
  } catch (error) {
98
- const err = convertErrorForRpcCall(error, [
102
+ const res = convertErrorForRpcCall(error, [
99
103
  HttpStatusCode.BAD_REQUEST,
100
104
  HttpStatusCode.UNAUTHORIZED,
101
105
  HttpStatusCode.CONFLICT,
102
106
  HttpStatusCode.FORBIDDEN
103
107
  ]);
104
- if (err) {
105
- throw err;
108
+ if (res) {
109
+ return res;
106
110
  }
111
+ throw error;
107
112
  }
113
+ return new Response(null, { status: HttpStatusCode.NO_CONTENT });
108
114
  };
109
115
  export const refreshAccessToken = async (context) => {
110
116
  assertSession(context);
@@ -124,12 +130,12 @@ export const refreshAccessToken = async (context) => {
124
130
  });
125
131
  return { success: !!tokens };
126
132
  } catch (error) {
127
- const err = convertErrorForRpcCall(error, [
133
+ const res = convertErrorForRpcCall(error, [
128
134
  HttpStatusCode.BAD_REQUEST,
129
135
  HttpStatusCode.UNAUTHORIZED
130
136
  ]);
131
- if (err) {
132
- throw err;
137
+ if (res) {
138
+ return res;
133
139
  }
134
140
  return { success: false };
135
141
  }
@@ -146,13 +152,13 @@ export const oauthRevokeToken = async (context) => {
146
152
  await client.revokeToken(accessToken);
147
153
  return { result: true };
148
154
  } catch (error) {
149
- const err = convertErrorForRpcCall(error, [
155
+ const res = convertErrorForRpcCall(error, [
150
156
  HttpStatusCode.BAD_REQUEST,
151
157
  HttpStatusCode.UNAUTHORIZED,
152
158
  HttpStatusCode.NOT_FOUND
153
159
  ]);
154
- if (err) {
155
- throw err;
160
+ if (res) {
161
+ return res;
156
162
  }
157
163
  return { result: false };
158
164
  }
@@ -178,14 +184,14 @@ export const oauthForgetPassword = async ({ email }, context) => {
178
184
  });
179
185
  return { success: true };
180
186
  } catch (error) {
181
- const err = convertErrorForRpcCall(error, [
187
+ const res = convertErrorForRpcCall(error, [
182
188
  HttpStatusCode.BAD_REQUEST,
183
189
  HttpStatusCode.NOT_FOUND,
184
190
  HttpStatusCode.UNAUTHORIZED,
185
191
  HttpStatusCode.FORBIDDEN
186
192
  ]);
187
- if (err) {
188
- throw err;
193
+ if (res) {
194
+ return res;
189
195
  }
190
196
  return { success: false };
191
197
  }
@@ -205,13 +211,15 @@ export const updatePasswordByHash = async (passwordHash, context) => {
205
211
  });
206
212
  await context.createUserBoundSession();
207
213
  } catch (error) {
208
- const err = convertErrorForRpcCall(error, [
214
+ const res = convertErrorForRpcCall(error, [
209
215
  HttpStatusCode.BAD_REQUEST,
210
216
  HttpStatusCode.UNAUTHORIZED,
211
217
  HttpStatusCode.NOT_ACCEPTABLE
212
218
  ]);
213
- if (err) {
214
- throw err;
219
+ if (res) {
220
+ return res;
215
221
  }
222
+ throw error;
216
223
  }
224
+ return new Response(null, { status: HttpStatusCode.NO_CONTENT });
217
225
  };
@@ -20,9 +20,12 @@ const fetchUser = exports.fetchUser = async function fetchUser2(payload, context
20
20
  } = context;
21
21
  const client = new _customer.CustomerAPIClient(context);
22
22
  const user = await client.getMe(shopId, accessToken);
23
- if (user.authentication) {
24
- user.authentication.storefrontAccessToken = accessToken;
23
+ if (!user.authentication) {
24
+ user.authentication = {
25
+ type: "idp"
26
+ };
25
27
  }
28
+ user.authentication.storefrontAccessToken = accessToken;
26
29
  user.loginShopId = shopId;
27
30
  return user;
28
31
  };
@@ -41,9 +44,7 @@ const refreshUser = exports.refreshUser = async function refreshUser2(context) {
41
44
  ...user.authentication,
42
45
  storefrontAccessToken: accessToken
43
46
  } : void 0,
44
- ...{
45
- loginShopId: shopId
46
- }
47
+ loginShopId: shopId
47
48
  });
48
49
  return {
49
50
  user
@@ -10,9 +10,12 @@ const fetchUser = async function fetchUser2(payload, context) {
10
10
  const { shopId } = context;
11
11
  const client = new CustomerAPIClient(context);
12
12
  const user = await client.getMe(shopId, accessToken);
13
- if (user.authentication) {
14
- user.authentication.storefrontAccessToken = accessToken;
13
+ if (!user.authentication) {
14
+ user.authentication = {
15
+ type: "idp"
16
+ };
15
17
  }
18
+ user.authentication.storefrontAccessToken = accessToken;
16
19
  user.loginShopId = shopId;
17
20
  return user;
18
21
  };
@@ -28,7 +31,7 @@ const refreshUser = async function refreshUser2(context) {
28
31
  ...user.authentication,
29
32
  storefrontAccessToken: accessToken
30
33
  } : void 0,
31
- ...{ loginShopId: shopId }
34
+ loginShopId: shopId
32
35
  });
33
36
  return { user };
34
37
  } catch {
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.removeItemFromWishlist = exports.getWishlist = exports.clearWishlist = exports.addItemToWishlist = void 0;
7
7
  var _types = require("../../types/index.cjs");
8
8
  var _constants = require("../../constants/index.cjs");
9
+ var _response = require("../../utils/response.cjs");
9
10
  function getWithParams(params, context) {
10
11
  return params.with ?? context.withParams?.basket ?? _constants.MIN_WITH_PARAMS_WISHLIST;
11
12
  }
@@ -79,7 +80,7 @@ const removeItemFromWishlist = exports.removeItemFromWishlist = async function r
79
80
  });
80
81
  };
81
82
  const clearWishlist = exports.clearWishlist = async function clearWishlist2(context) {
82
- const wishlist = await getWishlist({}, context);
83
+ const wishlist = await (0, _response.unwrap)(getWishlist({}, context));
83
84
  await Promise.all(wishlist.items.map(async item => {
84
85
  await removeItemFromWishlist({
85
86
  itemKey: item.key
@@ -1,5 +1,6 @@
1
1
  import { assertSession } from "../../types/index.mjs";
2
2
  import { MIN_WITH_PARAMS_WISHLIST } from "../../constants/index.mjs";
3
+ import { unwrap } from "../../utils/response.mjs";
3
4
  function getWithParams(params, context) {
4
5
  return params.with ?? context.withParams?.basket ?? MIN_WITH_PARAMS_WISHLIST;
5
6
  }
@@ -49,7 +50,7 @@ export const removeItemFromWishlist = async function removeItemFromWishlist2(opt
49
50
  });
50
51
  };
51
52
  export const clearWishlist = async function clearWishlist2(context) {
52
- const wishlist = await getWishlist({}, context);
53
+ const wishlist = await unwrap(getWishlist({}, context));
53
54
  await Promise.all(
54
55
  wishlist.items.map(async (item) => {
55
56
  await removeItemFromWishlist({ itemKey: item.key }, context);
@@ -1,4 +1,4 @@
1
1
  import { RpcContext } from './context';
2
- export type ParamRpcHandler<Params extends Record<string, any>, ResponseType> = (params: Params, context: RpcContext) => Promise<ResponseType> | ResponseType;
3
- export type NoParamRpcHandler<ResponseType> = (context: RpcContext) => Promise<ResponseType> | ResponseType;
2
+ export type ParamRpcHandler<Params extends Record<string, any>, ResponseType> = (params: Params, context: RpcContext) => Promise<(ResponseType extends undefined ? void : ResponseType) | Response> | ResponseType | Response;
3
+ export type NoParamRpcHandler<ResponseType> = (context: RpcContext) => Promise<ResponseType | Response> | ResponseType | Response;
4
4
  export type RpcHandler<A, B = void> = B extends void ? NoParamRpcHandler<A> : ParamRpcHandler<A, B>;
@@ -14,7 +14,7 @@ interface MemberRole {
14
14
  memberPriority: number;
15
15
  memberRoleSap: string;
16
16
  }
17
- type AuthenticationType = 'facebook' | 'password' | 'apple';
17
+ type AuthenticationType = 'password' | string;
18
18
  interface UserAuthentication {
19
19
  data?: {
20
20
  accessToken?: string;
@@ -4,9 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.unwrap = unwrap;
7
- async function unwrap(response) {
7
+ async function unwrap(res) {
8
+ const response = await res;
8
9
  if (response instanceof Response) {
9
- console.log("unwrapping for ", response.url);
10
10
  return await response.json();
11
11
  }
12
12
  return response;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Unwrap a possible response into its body
3
- * @param x
3
+ * @param res
4
4
  * @returns
5
5
  */
6
- export declare function unwrap<T>(response: Response | T): Promise<T>;
6
+ export declare function unwrap<T>(res: Promise<Response | T> | Response | T): Promise<T>;
@@ -1,6 +1,6 @@
1
- export async function unwrap(response) {
1
+ export async function unwrap(res) {
2
+ const response = await res;
2
3
  if (response instanceof Response) {
3
- console.log("unwrapping for ", response.url);
4
4
  return await response.json();
5
5
  }
6
6
  return response;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scayle/storefront-core",
3
- "version": "7.38.1",
3
+ "version": "7.39.1",
4
4
  "description": "Collection of essential utilities to work with the Storefront API",
5
5
  "author": "SCAYLE Commerce Engine",
6
6
  "license": "MIT",
@@ -49,8 +49,8 @@
49
49
  "build:legacy": "tsc -p tsconfig.legacy.json",
50
50
  "build": "unbuild",
51
51
  "typecheck": "tsc --noEmit -p tsconfig.json",
52
- "format": "prettier --ignore-unknown --log-level warn --check .",
53
- "format:fix": "prettier --ignore-unknown --log-level warn --write .",
52
+ "format": "dprint check",
53
+ "format:fix": "dprint fmt",
54
54
  "lint": "eslint . --format gitlab",
55
55
  "lint:fix": "eslint . --fix",
56
56
  "package:lint": "publint",
@@ -59,32 +59,31 @@
59
59
  "test:ci": "vitest --run --passWithNoTests --coverage --reporter=default --reporter=junit"
60
60
  },
61
61
  "dependencies": {
62
- "@aboutyou/backbone": "16.1.0",
62
+ "@aboutyou/backbone": "16.1.1",
63
63
  "crypto-js": "4.2.0",
64
- "jose": "5.2.0",
64
+ "jose": "5.2.1",
65
65
  "radash": "11.0.0",
66
66
  "slugify": "1.6.6",
67
- "ufo": "1.3.2",
67
+ "ufo": "1.4.0",
68
68
  "uncrypto": "0.1.3",
69
69
  "utility-types": "3.11.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@scayle/eslint-config-storefront": "3.2.6",
73
- "@scayle/prettier-config-storefront": "2.0.2",
74
73
  "@types/crypto-js": "4.2.2",
75
- "@types/node": "20.11.5",
74
+ "@types/node": "20.11.17",
76
75
  "@types/webpack-env": "1.18.4",
77
- "@vitest/coverage-v8": "1.2.1",
76
+ "@vitest/coverage-v8": "1.2.2",
77
+ "dprint": "0.45.0",
78
78
  "eslint": "8.56.0",
79
79
  "eslint-formatter-gitlab": "5.1.0",
80
- "prettier": "3.0.0",
81
80
  "publint": "0.2.7",
82
81
  "rimraf": "5.0.5",
83
82
  "ts-node": "10.9.2",
84
83
  "typescript": "5.3.3",
85
84
  "unbuild": "2.0.0",
86
85
  "unstorage": "1.10.1",
87
- "vitest": "1.2.1"
86
+ "vitest": "1.2.2"
88
87
  },
89
88
  "optionalDependencies": {
90
89
  "redis": "4"