@evenicanpm/storefront-core 1.3.0 → 1.4.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.
Files changed (188) hide show
  1. package/__mocks__/get-product-by-id.ts +0 -1
  2. package/__mocks__/query-client.ts +1 -1
  3. package/package.json +3 -3
  4. package/src/api-manager/datasources/d365/d365-address.datasource.ts +2 -2
  5. package/src/api-manager/datasources/d365/d365-cart.datasource.ts +4 -5
  6. package/src/api-manager/datasources/d365/d365-categories.datasource.ts +1 -1
  7. package/src/api-manager/datasources/d365/d365-product.datasource.ts +21 -7
  8. package/src/api-manager/datasources/d365/d365-session.datasource.ts +5 -7
  9. package/src/api-manager/datasources/d365/d365-user.datasource.ts +12 -23
  10. package/src/api-manager/datasources/d365/d365.datasource.ts +0 -2
  11. package/src/api-manager/datasources/d365/index.ts +2 -4
  12. package/src/api-manager/datasources/d365/utils/decode-jwt.ts +1 -2
  13. package/src/api-manager/datasources/d365/utils/parse-object.ts +1 -1
  14. package/src/api-manager/datasources/e4/address/e4-address.remaps.ts +2 -2
  15. package/src/api-manager/datasources/e4/address/e4-address.translator.ts +1 -1
  16. package/src/api-manager/datasources/e4/cart/e4-cart.datasource.ts +28 -27
  17. package/src/api-manager/datasources/e4/cart/e4-cart.remaps.ts +1 -1
  18. package/src/api-manager/datasources/e4/cart/e4-cart.translator.ts +1 -1
  19. package/src/api-manager/datasources/e4/categories/e4-categories.translator.ts +20 -20
  20. package/src/api-manager/datasources/e4/graphqlRequestSdk.ts +471 -7
  21. package/src/api-manager/datasources/e4/order/e4-order.remaps.ts +2 -2
  22. package/src/api-manager/datasources/e4/organization/e4-organization.datasource.ts +2 -8
  23. package/src/api-manager/datasources/e4/product/e4-product.remaps.ts +3 -3
  24. package/src/api-manager/datasources/e4/product/e4-product.translator.ts +13 -29
  25. package/src/api-manager/datasources/e4/session/e4-session.datasource.ts +1 -3
  26. package/src/api-manager/datasources/e4/user/e4-user.remaps.ts +2 -4
  27. package/src/api-manager/datasources/e4/utils/unwrap-e4-variants.ts +4 -4
  28. package/src/api-manager/index.ts +1 -1
  29. package/src/api-manager/lib/category-helpers.ts +3 -2
  30. package/src/api-manager/lib/get-graphql-client.ts +1 -2
  31. package/src/api-manager/services/cart/mutations/add-discount-code.ts +2 -2
  32. package/src/api-manager/services/cart/mutations/add-to-cart.ts +2 -2
  33. package/src/api-manager/services/product/server/product.server.ts +1 -1
  34. package/src/api-manager/types/Datasource.ts +4 -9
  35. package/src/auth/auth-options.test.ts +2 -58
  36. package/src/auth/auth-options.ts +1 -2
  37. package/src/auth/next-auth-cookie-manager.ts +0 -2
  38. package/src/auth/refresh-token.ts +3 -8
  39. package/src/auth/signout.ts +1 -1
  40. package/src/cms/blocks/block-manager.tsx +3 -3
  41. package/src/cms/blocks/components/category-card.tsx +1 -1
  42. package/src/cms/blocks/components/category-carousel/index.tsx +3 -1
  43. package/src/cms/blocks/components/footer/index.tsx +2 -2
  44. package/src/cms/blocks/components/footer/sections/footer-links.tsx +2 -2
  45. package/src/cms/blocks/components/footer/sections/footer-logo.tsx +1 -1
  46. package/src/cms/blocks/components/footer/sections/footer-social-links.tsx +10 -2
  47. package/src/cms/blocks/components/hero-carousel/index.tsx +29 -25
  48. package/src/cms/blocks/components/media-card.tsx +1 -1
  49. package/src/cms/blocks/components/product-carousel/index.tsx +1 -1
  50. package/src/cms/blocks/components/product-section-fullwidth/index.tsx +2 -2
  51. package/src/cms/blocks/components/seo/index.tsx +5 -1
  52. package/src/cms/blocks/components/services/index.tsx +1 -1
  53. package/src/cms/blocks/components/services/service-card.tsx +1 -1
  54. package/src/cms/blocks/components/shared/featured-product-card.tsx +4 -1
  55. package/src/cms/blocks/components/shared/product-category-item.tsx +1 -1
  56. package/src/cms/blocks/components/shared/product-grid.tsx +4 -1
  57. package/src/cms/blocks/components/shared/top-categories-card.tsx +5 -1
  58. package/src/cms/blocks/components/shared/top-rating-product-card.tsx +1 -1
  59. package/src/components-v2/BazaarImage.tsx +1 -1
  60. package/src/components-v2/BazaarMenu.tsx +2 -2
  61. package/src/components-v2/BazaarTextField.tsx +3 -3
  62. package/src/components-v2/BorderShadowCard.stories.tsx +1 -1
  63. package/src/components-v2/DropZone.tsx +1 -2
  64. package/src/components-v2/Typography.tsx +12 -12
  65. package/src/components-v2/accordion/accordion-header.tsx +1 -1
  66. package/src/components-v2/categories/category-list/styles.ts +0 -7
  67. package/src/components-v2/categories/category-list-item/category-menu-item.tsx +1 -1
  68. package/src/components-v2/categories/category-menu.tsx +16 -13
  69. package/src/components-v2/categories/mega-menu/mega-menu-1.tsx +1 -1
  70. package/src/components-v2/categories/mega-menu/mega-menu-2.tsx +2 -2
  71. package/src/components-v2/header/components/user.tsx +5 -5
  72. package/src/components-v2/mini-cart/__tests__/cart-item.test.tsx +13 -13
  73. package/src/components-v2/mini-cart/components/bottom-actions.tsx +1 -1
  74. package/src/components-v2/mini-cart/components/cart-item.tsx +3 -3
  75. package/src/components-v2/mini-cart/components/top-header.tsx +2 -2
  76. package/src/components-v2/mobile-navigation/mobile-navigation-bar.tsx +1 -1
  77. package/src/components-v2/nav-link/nav-link-2.tsx +1 -1
  78. package/src/components-v2/nav-link/nav-link-3.tsx +1 -1
  79. package/src/components-v2/nav-link/nav-link.tsx +1 -1
  80. package/src/components-v2/navbar/categories.tsx +3 -1
  81. package/src/components-v2/navbar/category-based-menu/category-based-menu.tsx +2 -2
  82. package/src/components-v2/navbar/mobile-menu/mobile-menu.tsx +11 -3
  83. package/src/components-v2/navbar/nav-list/nav-item-child.tsx +1 -1
  84. package/src/components-v2/navbar/nav-list/nav-list.tsx +118 -80
  85. package/src/components-v2/navbar/navbar.tsx +1 -1
  86. package/src/components-v2/no-records.tsx +1 -1
  87. package/src/components-v2/product-cards/favorite-button.tsx +1 -1
  88. package/src/components-v2/product-cards/product-card/product-card.tsx +5 -7
  89. package/src/components-v2/product-cards/product-card-plp/product-card.tsx +7 -6
  90. package/src/components-v2/product-cards/product-card-plp-list/components/tags.tsx +1 -1
  91. package/src/components-v2/product-cards/product-card-plp-list/product-card.tsx +7 -4
  92. package/src/components-v2/product-cards/product-card-search/product-card.tsx +4 -2
  93. package/src/components-v2/product-cards/product-price.tsx +1 -1
  94. package/src/components-v2/product-cards/product-rating.tsx +1 -1
  95. package/src/components-v2/product-cards/product-title.tsx +1 -1
  96. package/src/components-v2/product-cards/quantity-buttons.tsx +1 -1
  97. package/src/components-v2/product-dialog/compound/product-dialog.tsx +2 -2
  98. package/src/components-v2/product-dialog/index.tsx +1 -1
  99. package/src/components-v2/product-dimensions/compound/dimensions-group-list.tsx +6 -1
  100. package/src/components-v2/product-dimensions/index.tsx +3 -3
  101. package/src/components-v2/product-quantity-buttons/compound/quantity-buttons-root.tsx +1 -1
  102. package/src/components-v2/product-quantity-variants/index.tsx +1 -2
  103. package/src/components-v2/products-view/ProductsList.stories.tsx +0 -2
  104. package/src/components-v2/products-view/compound/products-grid-view.tsx +2 -2
  105. package/src/components-v2/products-view/compound/products-list-view.tsx +3 -3
  106. package/src/components-v2/products-view/index.tsx +2 -2
  107. package/src/components-v2/progress/progress.tsx +1 -1
  108. package/src/components-v2/scrollbar/scrollbar.tsx +1 -1
  109. package/src/components-v2/search-bar/compound/results-suspense.tsx +1 -2
  110. package/src/components-v2/search-bar/compound/results.tsx +6 -3
  111. package/src/components-v2/search-bar/compound/search-bar-root.tsx +4 -2
  112. package/src/components-v2/search-bar/compound/textfield-adornment-category.tsx +25 -27
  113. package/src/components-v2/search-bar/compound/textfield.tsx +0 -1
  114. package/src/components-v2/search-bar/hooks/use-search.ts +1 -1
  115. package/src/components-v2/section/Section.stories.tsx +1 -1
  116. package/src/components-v2/side-nav/side-nav.tsx +1 -1
  117. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-dialog.tsx +1 -1
  118. package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-list.tsx +2 -2
  119. package/src/components-v2/wishlist-dialogs/add-to-wishlist/hooks/use-add-to-wishlist.ts +2 -0
  120. package/src/components-v2/wishlist-dialogs/add-to-wishlist/index.tsx +11 -13
  121. package/src/components-v2/wishlist-dialogs/create-wishlist/compound/create-wishlist-dialog.tsx +2 -1
  122. package/src/hooks/use-variants.ts +25 -27
  123. package/src/lib/build-detail-url.ts +1 -1
  124. package/src/lib/category-helpers.ts +3 -3
  125. package/src/lib/get-palette-color.ts +35 -15
  126. package/src/lib/hexToLuma.ts +2 -2
  127. package/src/lib/store-hours-helper.ts +5 -5
  128. package/src/pages-v2/account/addresses/address-form.tsx +10 -8
  129. package/src/pages-v2/account/addresses/address-item.tsx +1 -1
  130. package/src/pages-v2/account/orders/order-progress.tsx +1 -1
  131. package/src/pages-v2/account/orders/ordered-products.tsx +1 -1
  132. package/src/pages-v2/account/profile/user-info.tsx +1 -2
  133. package/src/pages-v2/account/wishlist/create-new-list.tsx +1 -0
  134. package/src/pages-v2/account/wishlist/wishlist-item.tsx +2 -1
  135. package/src/pages-v2/blog/blog-card.tsx +1 -1
  136. package/src/pages-v2/cart/__tests__/cart-item.test.tsx +0 -1
  137. package/src/pages-v2/cart/__tests__/checkout-form.test.tsx +0 -8
  138. package/src/pages-v2/cart/cart-item.tsx +86 -77
  139. package/src/pages-v2/cart/checkout-form.tsx +4 -4
  140. package/src/pages-v2/cart/coupon-entry.tsx +3 -3
  141. package/src/pages-v2/cart/estimate-shipping.tsx +6 -6
  142. package/src/pages-v2/checkout/checkout-alt-form/checkout-form.tsx +2 -2
  143. package/src/pages-v2/checkout/checkout-alt-form/checkout-step.tsx +2 -2
  144. package/src/pages-v2/checkout/checkout-alt-form/step-heading.tsx +1 -1
  145. package/src/pages-v2/checkout/checkout-alt-form/steps/address/delivery-address.tsx +12 -10
  146. package/src/pages-v2/checkout/checkout-alt-form/steps/address/new-address-form.tsx +5 -6
  147. package/src/pages-v2/checkout/checkout-alt-form/steps/customer-info/customer-information.tsx +8 -9
  148. package/src/pages-v2/checkout/checkout-alt-form/steps/payment/payment-details.tsx +17 -20
  149. package/src/pages-v2/checkout/checkout-alt-form/steps/shipping/delivery-date.tsx +1 -1
  150. package/src/pages-v2/checkout/checkout-alt-form/steps/shipping/delivery-options.tsx +14 -15
  151. package/src/pages-v2/confirmation/confirmation-summary.tsx +8 -7
  152. package/src/pages-v2/confirmation/ordered-products.tsx +3 -3
  153. package/src/pages-v2/product-details/bopis/pickup-option-select.tsx +1 -1
  154. package/src/pages-v2/product-details/bopis/store-card/shop-card.tsx +1 -1
  155. package/src/pages-v2/product-details/checkbox-label.tsx +1 -1
  156. package/src/pages-v2/product-details/frequently-bought.tsx +1 -1
  157. package/src/pages-v2/product-details/frequently-product-card.tsx +1 -1
  158. package/src/pages-v2/product-details/product-comment.tsx +1 -1
  159. package/src/pages-v2/product-details/product-description.tsx +2 -2
  160. package/src/pages-v2/product-details/product-filter-card.tsx +4 -1
  161. package/src/pages-v2/product-details/product-intro/compound/product-intro-images.tsx +36 -31
  162. package/src/pages-v2/product-details/product-intro/compound/product-intro.tsx +1 -1
  163. package/src/pages-v2/product-details/product-intro/compound/thumbnail-with-skeleton.tsx +1 -1
  164. package/src/pages-v2/product-details/product-intro/utils.ts +2 -4
  165. package/src/pages-v2/product-details/product-review.tsx +1 -1
  166. package/src/pages-v2/product-details/product-tabs.tsx +5 -2
  167. package/src/pages-v2/product-details/related-products.tsx +7 -4
  168. package/src/pages-v2/product-list/breadcrumbs.tsx +1 -1
  169. package/src/pages-v2/product-list/checkbox-label.tsx +1 -1
  170. package/src/pages-v2/product-list/facet-group.tsx +1 -1
  171. package/src/pages-v2/product-list/list-filter.tsx +2 -2
  172. package/src/pages-v2/product-list/product-list-context.tsx +5 -1
  173. package/src/pages-v2/product-list/product-list-view.tsx +4 -1
  174. package/src/pages-v2/product-list/product-rating.tsx +4 -1
  175. package/src/pages-v2/product-list/quick-view-dialog-content.tsx +2 -4
  176. package/src/pages-v2/product-list/quick-view-dialog.tsx +5 -1
  177. package/src/pages-v2/product-list/range-filter.tsx +0 -1
  178. package/src/pages-v2/product-list/scrollbar.tsx +1 -1
  179. package/src/pages-v2/product-list/side-nav.tsx +1 -1
  180. package/src/pages-v2/product-list/swatch.tsx +12 -7
  181. package/src/pages-v2/product-list/utils/getCategoryFilterFromSlug.ts +33 -68
  182. package/src/pages-v2/product-list/utils/product-list-helper.ts +1 -1
  183. package/src/pages-v2/product-list/utils/search-for-category.ts +2 -2
  184. package/src/pages-v2/quickorder/order-upload.tsx +90 -76
  185. package/src/pages-v2/quickorder/provider.tsx +6 -4
  186. package/src/pages-v2/quickorder/quick-order-row.tsx +1 -1
  187. package/src/pages-v2/quickorder/quick-order.tsx +28 -21
  188. package/src/providers/notifications/notification-context.tsx +0 -1
@@ -1,4 +1,3 @@
1
- import { fn } from "storybook/test";
2
1
  import { product } from "./product-dimensions";
3
2
 
4
3
  export default {
@@ -1,3 +1,3 @@
1
- import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
1
+ import { QueryClient } from "@tanstack/react-query";
2
2
 
3
3
  export const queryClient = new QueryClient();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evenicanpm/storefront-core",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Core module for D365/e4 Headless Storefront",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -16,7 +16,7 @@
16
16
  "author": "Evenica",
17
17
  "license": "ISC",
18
18
  "dependencies": {
19
- "@evenicanpm/ui": "^1.3.0"
19
+ "@evenicanpm/ui": "^1.4.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@storybook/addon-docs": "^9.1.6",
@@ -49,5 +49,5 @@
49
49
  "esbuild": "0.19.11"
50
50
  }
51
51
  },
52
- "gitHead": "074f33378006dfc21ceb49456806a18dbb6e91ad"
52
+ "gitHead": "0614726ec6b7ce9564706514a6b756b390a13e96"
53
53
  }
@@ -42,7 +42,7 @@ class D365AddressDatasource extends D365DatasourceBase implements AddressApi {
42
42
  const added = updatedCustomer.Addresses?.find((a) =>
43
43
  prevAddresses.every((old) => old.RecordId !== a.RecordId),
44
44
  );
45
- if (!added || added.RecordId == null) {
45
+ if (added?.RecordId == null) {
46
46
  throw new Error("Failed to create new address");
47
47
  }
48
48
 
@@ -73,7 +73,7 @@ class D365AddressDatasource extends D365DatasourceBase implements AddressApi {
73
73
 
74
74
  const updatedCustomer = await updateAsync(context as any, customer);
75
75
  const rec = updatedCustomer?.Addresses?.[idx];
76
- if (!rec || rec.RecordId == null) {
76
+ if (rec?.RecordId == null) {
77
77
  throw new Error(
78
78
  `Failed to update address Id=${address.Id}. Updated address record with a matching id not found.`,
79
79
  );
@@ -105,8 +105,7 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
105
105
  const context = this.context;
106
106
  const { totalAmount, hideBillingAddress, origin } = input;
107
107
  const paymentAcceptSettings: CardPaymentAcceptSettings = {
108
- AdaptorPath:
109
- (typeof window !== "undefined" && `${origin}/Connectors`) || undefined,
108
+ AdaptorPath: globalThis?.window ? `${origin}/Connectors` : undefined,
110
109
  CardPaymentEnabled: true,
111
110
  CardTokenizationEnabled: true,
112
111
  HideBillingAddress: hideBillingAddress || false,
@@ -259,14 +258,14 @@ export class D365CartDatasource extends D365DatasourceBase implements CartApi {
259
258
  const id = input?.cartId ?? (await getCartCookie());
260
259
  let cart: DynCart;
261
260
 
262
- if (!id) {
263
- return this.createCart(context);
264
- } else {
261
+ if (id) {
265
262
  cart = (await readAsync(context as any, id)) as DynCart;
266
263
  if (!cart) {
267
264
  return this.createCart(context);
268
265
  }
269
266
  return await mergeCartWithProducts(cart, this.context);
267
+ } else {
268
+ return this.createCart(context);
270
269
  }
271
270
  }
272
271
 
@@ -32,7 +32,7 @@ class D365CategoriesDatasource
32
32
  "Error fetching categories:",
33
33
  JSON.stringify(error, null, 2),
34
34
  );
35
- throw error;
35
+ return [];
36
36
  }
37
37
  }
38
38
  }
@@ -26,8 +26,10 @@ import {
26
26
  type ProductSearchCriteria,
27
27
  type ProductSearchResult,
28
28
  type SimpleProduct,
29
+ executeAction,
29
30
  } from "@msdyn365-commerce/retail-proxy";
30
31
  import {
32
+ createSearchByCriteriaInput,
31
33
  getActivePricesAsync,
32
34
  getAttributeValuesAsync,
33
35
  getByIdAsync,
@@ -147,6 +149,10 @@ class D365ProductDatasource extends D365DatasourceBase implements ProductApi {
147
149
  }
148
150
 
149
151
  const refinerSearchSettings = { ...searchCriteria };
152
+ const queryResultSettingsWithCount: IQueryResultSettings = {
153
+ ...(queryResultSettings ?? {}),
154
+ count: true,
155
+ };
150
156
 
151
157
  //Remove the price refiner from the refinement to stop the price adjustment
152
158
  refinerSearchSettings.Refinement = refinerSearchSettings.Refinement?.filter(
@@ -154,17 +160,25 @@ class D365ProductDatasource extends D365DatasourceBase implements ProductApi {
154
160
  );
155
161
 
156
162
  const ctx = { ...context } as any;
157
- ctx.queryResultSettings = queryResultSettings;
158
- const productSearchPromise = searchByCriteriaAsync(ctx, searchCriteria);
159
- const refinersPRomise = getProductSearchRefinersAsync(
163
+ ctx.queryResultSettings = queryResultSettingsWithCount;
164
+ const searchRequest = createSearchByCriteriaInput(
165
+ queryResultSettingsWithCount,
166
+ searchCriteria,
167
+ );
168
+ const productSearchResult = executeAction<ProductSearchResult[]>(
169
+ searchRequest,
170
+ ctx,
171
+ );
172
+ const refinersPromise = getProductSearchRefinersAsync(
160
173
  ctx,
161
174
  refinerSearchSettings,
162
175
  );
163
176
  const [productResults, refinerResults] = await Promise.all([
164
- productSearchPromise,
165
- refinersPRomise,
177
+ productSearchResult,
178
+ refinersPromise,
166
179
  ]);
167
- const count = productSearchPromise.metadata?.count || 500; //Set to high number for pagination
180
+
181
+ const count = (searchRequest as any)?._totalCount ?? productResults.length;
168
182
  const promises = [];
169
183
  for (const product of productResults) {
170
184
  promises.push(
@@ -219,7 +233,7 @@ class D365ProductDatasource extends D365DatasourceBase implements ProductApi {
219
233
  );
220
234
  }
221
235
  await Promise.all(promises);
222
- const parsed = JSON.parse(JSON.stringify(results));
236
+ const parsed = globalThis.structuredClone(results);
223
237
  return parsed;
224
238
  }
225
239
 
@@ -1,24 +1,22 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
 
3
- //import { getContextFromCookie } from "./utils/get-context-cookie";
4
3
  import { D365DatasourceBase } from "@evenicanpm/storefront-core/src/api-manager/datasources/d365/d365-base.datasource";
5
- //import { Customer, ICallerContext } from "@msdyn365-commerce/retail-proxy";
6
- //import { readAsync } from "@msdyn365-commerce/retail-proxy/dist/DataActions/CustomersDataActions.g";
7
4
  import type { Session } from "@evenicanpm/storefront-core/src/api-manager/schemas/session.schema";
8
5
  import type { SessionApi } from "@evenicanpm/storefront-core/src/api-manager/types/Datasource";
9
6
 
10
7
  class D365SessionDatasource extends D365DatasourceBase implements SessionApi {
11
8
  async sessionInit(): Promise<Session> {
12
9
  console.warn("sessionInit not implemented");
13
- return Promise.resolve({} as Session);
10
+ return {} as Session;
14
11
  }
12
+
15
13
  async sessionLogout(): Promise<boolean> {
16
14
  return true;
17
15
  }
18
- getSession(): Promise<Session> {
19
- //throw new Error("Method not implemented");
16
+
17
+ async getSession(): Promise<Session> {
20
18
  console.warn("getSession not implemented on d365");
21
- return Promise.resolve({} as Session);
19
+ return {} as Session;
22
20
  }
23
21
  }
24
22
 
@@ -124,7 +124,7 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
124
124
  );
125
125
  return wishlistProductData;
126
126
  } catch (error) {
127
- throw new Error("Error getting wishlists: " + error);
127
+ throw new Error(`Error getting wishlists: ${error}`);
128
128
  }
129
129
  }
130
130
 
@@ -136,7 +136,9 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
136
136
  try {
137
137
  wishlist = await wishlistReadAsync(context as any, input.Id);
138
138
  } catch (error) {
139
- throw new Error("Error getting wishlist details" + JSON.stringify(error));
139
+ throw new Error(
140
+ `Error getting wishlist details: ${JSON.stringify(error)}`,
141
+ );
140
142
  }
141
143
 
142
144
  const extendedWishlist = { ...wishlist } as ExtendedWishlist;
@@ -154,7 +156,7 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
154
156
  id: uniq(productIds),
155
157
  });
156
158
  } catch (error) {
157
- throw new Error("Error getting wishlist products: " + error);
159
+ throw new Error(`Error getting wishlist products: ${error}`);
158
160
  }
159
161
 
160
162
  if (products) {
@@ -181,11 +183,11 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
181
183
  try {
182
184
  const wishlist = await createProductListAsync(
183
185
  context as any,
184
- productList as ProductList,
186
+ productList,
185
187
  );
186
188
  return wishlist;
187
189
  } catch (error) {
188
- throw new Error("Error creating wishlist: " + JSON.stringify(error));
190
+ throw new Error(`Error creating wishlist: ${JSON.stringify(error)}`);
189
191
  }
190
192
  }
191
193
 
@@ -197,22 +199,10 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
197
199
  try {
198
200
  await deleteAsync(context as any, { Id: input.Id });
199
201
  } catch (error) {
200
- throw new Error("Error deleting wishlist: " + error);
202
+ throw new Error(`Error deleting wishlist: ${error}`);
201
203
  }
202
204
  }
203
205
 
204
- // async updateWishlist(input: WishlistLinesInput): Promise<Wishlist> {
205
- // const context = await getContextFromCookie();
206
-
207
- // try {
208
- // const wishlist = await updateAsync(context as any, input);
209
- // return wishlist;
210
- // } catch (error) {
211
- // console.log('input', input);
212
- // throw new Error("Error updating wishlist: " + error);
213
- // }
214
- // }
215
-
216
206
  async updateWishlist(input: WishlistLinesInput): Promise<Wishlist> {
217
207
  const context = this.context;
218
208
  const id = input.Id;
@@ -227,7 +217,7 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
227
217
  const wishlist = { Id: id, productListLines: updatedProductListLines };
228
218
  return wishlist;
229
219
  } catch (error) {
230
- throw new Error("Error updating wishlist: " + error);
220
+ throw new Error(`Error updating wishlist: ${error}`);
231
221
  }
232
222
  }
233
223
 
@@ -246,11 +236,10 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
246
236
  const wishlist = { Id: id, productListLines: updatedProductListLines };
247
237
  return wishlist;
248
238
  } catch (error) {
249
- throw new Error("Error adding to wishlist: " + error);
239
+ throw new Error(`Error adding to wishlist: ${error}`);
250
240
  }
251
241
  }
252
242
 
253
- // TODO: void return
254
243
  async removeProductsFromWishlist(input: WishlistLinesInput): Promise<void> {
255
244
  const context = this.context;
256
245
  const id = input.Id;
@@ -258,7 +247,7 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
258
247
  try {
259
248
  await removeProductListLinesAsync(context as any, id, productListLines);
260
249
  } catch (error) {
261
- throw new Error("Error removing from wishlist: " + error);
250
+ throw new Error(`Error removing from wishlist: ${error}`);
262
251
  }
263
252
  }
264
253
 
@@ -279,7 +268,7 @@ class D365UserDatasource extends D365DatasourceBase implements UserApi {
279
268
  );
280
269
  return wishlist;
281
270
  } catch (error) {
282
- throw new Error("Error copying cart to wishlist: " + error);
271
+ throw new Error(`Error copying cart to wishlist: ${error}`);
283
272
  }
284
273
  }
285
274
  }
@@ -41,5 +41,3 @@ export class D365Datasource extends Datasource implements PrimaryDatasource {
41
41
  }
42
42
  // Datasources
43
43
  }
44
-
45
- // export default d365Datasource;
@@ -1,4 +1,2 @@
1
- import { D365Datasource } from "@evenicanpm/storefront-core/src/api-manager/datasources/d365/d365.datasource";
2
- import { D365ProductDatasource } from "@evenicanpm/storefront-core/src/api-manager/datasources/d365/d365-product.datasource";
3
-
4
- export { D365ProductDatasource, D365Datasource };
1
+ export { D365Datasource } from "@evenicanpm/storefront-core/src/api-manager/datasources/d365/d365.datasource";
2
+ export { D365ProductDatasource } from "@evenicanpm/storefront-core/src/api-manager/datasources/d365/d365-product.datasource";
@@ -1,9 +1,8 @@
1
1
  "use server";
2
- import { getSecret } from "@evenicanpm/common-core/src/lib/keyvault";
3
2
  import { decode } from "next-auth/jwt";
4
3
 
5
4
  export async function decodeToken(token: string) {
6
- const secret = getSecret("NEXTAUTH_SECRET");
5
+ const secret = process.env.NEXTAUTH_SECRET; //this shouldn't be from key vault.
7
6
  if (!secret) {
8
7
  throw new Error("Environment variable NEXTAUTH_SECRET is not set.");
9
8
  }
@@ -1,6 +1,6 @@
1
1
  const parseObject = async <TClass>(data: TClass): Promise<TClass> => {
2
2
  try {
3
- return JSON.parse(JSON.stringify(await data)) as TClass;
3
+ return globalThis.structuredClone(await data) as TClass;
4
4
  } catch {
5
5
  return {} as TClass;
6
6
  }
@@ -16,7 +16,7 @@ export const addressMap = {
16
16
  {
17
17
  key: "[].RecordId",
18
18
  transform: (id: string) => {
19
- if (id !== null) return parseInt(id);
19
+ if (id !== null) return Number.parseInt(id);
20
20
  },
21
21
  },
22
22
  ],
@@ -25,7 +25,7 @@ export const addressMap = {
25
25
  "[].addressType.id": {
26
26
  key: "[].AddressTypeValue",
27
27
  transform: (id: string) => {
28
- if (id !== null) return parseInt(id);
28
+ if (id !== null) return Number.parseInt(id);
29
29
  },
30
30
  },
31
31
  "[].address1": "[].Street",
@@ -88,7 +88,7 @@ export const countriesTransformValidate = (countries: Country[]) => {
88
88
  };
89
89
 
90
90
  export const countryTransformValidate = (country: Country) => {
91
- if (country?.state && country?.state.length) {
91
+ if (country?.state?.length) {
92
92
  return merge(country, countryMap);
93
93
  }
94
94
  return [];
@@ -3,7 +3,6 @@ import * as cartTranslator from "@evenicanpm/storefront-core/src/api-manager/dat
3
3
  import type { Cart as E4Cart } from "@evenicanpm/storefront-core/src/api-manager/datasources/e4/graphqlRequestSdk";
4
4
  import getGraphqlClient from "@evenicanpm/storefront-core/src/api-manager/lib/get-graphql-client";
5
5
  import type * as cartSchema from "@evenicanpm/storefront-core/src/api-manager/schemas/cart.schema";
6
- import type { Cart } from "@evenicanpm/storefront-core/src/api-manager/schemas/cart.schema";
7
6
  import type { SalesOrder } from "@evenicanpm/storefront-core/src/api-manager/schemas/order.schema";
8
7
  import type { CartApi } from "@evenicanpm/storefront-core/src/api-manager/types/Datasource";
9
8
  import type {
@@ -15,7 +14,7 @@ import type {
15
14
 
16
15
  const cart: CartApi = {
17
16
  //For this data source, initCart does the same thing as getCart
18
- async initCart(): Promise<Cart> {
17
+ async initCart(): Promise<cartSchema.Cart> {
19
18
  const e4Api = await getGraphqlClient();
20
19
 
21
20
  const { data, errors } = await e4Api.e4CartReadMD();
@@ -30,7 +29,7 @@ const cart: CartApi = {
30
29
  return transformedData;
31
30
  },
32
31
 
33
- async addToCart(input: cartSchema.AddToCartInput): Promise<Cart> {
32
+ async addToCart(input: cartSchema.AddToCartInput): Promise<cartSchema.Cart> {
34
33
  const e4Api = await getGraphqlClient();
35
34
 
36
35
  const { cartLine } = input;
@@ -53,7 +52,9 @@ const cart: CartApi = {
53
52
  return transformedData;
54
53
  },
55
54
 
56
- async updateCart(input: cartSchema.UpdateCartInput): Promise<Cart> {
55
+ async updateCart(
56
+ input: cartSchema.UpdateCartInput,
57
+ ): Promise<cartSchema.Cart> {
57
58
  const e4Api = await getGraphqlClient();
58
59
 
59
60
  const { cart } = input;
@@ -95,7 +96,9 @@ const cart: CartApi = {
95
96
  return transformedData;
96
97
  },
97
98
 
98
- async updateCartLines(input: cartSchema.UpdateCartLineInput): Promise<Cart> {
99
+ async updateCartLines(
100
+ input: cartSchema.UpdateCartLineInput,
101
+ ): Promise<cartSchema.Cart> {
99
102
  const e4Api = await getGraphqlClient();
100
103
 
101
104
  const { cartLine } = input;
@@ -124,7 +127,9 @@ const cart: CartApi = {
124
127
  return transformedData;
125
128
  },
126
129
 
127
- async deleteCartLine(input: cartSchema.DeleteCartLineInput): Promise<Cart> {
130
+ async deleteCartLine(
131
+ input: cartSchema.DeleteCartLineInput,
132
+ ): Promise<cartSchema.Cart> {
128
133
  const e4Api = await getGraphqlClient();
129
134
 
130
135
  const { cartLine } = input;
@@ -148,7 +153,7 @@ const cart: CartApi = {
148
153
  return transformedData;
149
154
  },
150
155
 
151
- async getCart(): Promise<Cart> {
156
+ async getCart(): Promise<cartSchema.Cart> {
152
157
  const e4Api = await getGraphqlClient();
153
158
 
154
159
  const { data, errors } = await e4Api.e4CartReadMD();
@@ -163,21 +168,17 @@ const cart: CartApi = {
163
168
  return transformedData;
164
169
  },
165
170
 
166
- async addDiscountCode(): Promise<Cart> {
167
- if (true) {
168
- throw new Error("Error adding discount code");
169
- }
171
+ async addDiscountCode(): Promise<cartSchema.Cart> {
172
+ throw new Error("Error adding discount code");
170
173
  },
171
174
 
172
- async removeDiscountcode(): Promise<Cart> {
173
- if (true) {
174
- throw new Error("Error removing discount code");
175
- }
175
+ async removeDiscountcode(): Promise<cartSchema.Cart> {
176
+ throw new Error("Error removing discount code");
176
177
  },
177
178
 
178
179
  async updateLineDeliveryMode(
179
180
  input: cartSchema.UpdateCartLineDeliveryModeInput,
180
- ): Promise<Cart> {
181
+ ): Promise<cartSchema.Cart> {
181
182
  const e4Api = await getGraphqlClient();
182
183
 
183
184
  const { data, errors } = await e4Api.e4ShippingMethodUpdateMD({
@@ -197,22 +198,16 @@ const cart: CartApi = {
197
198
  );
198
199
  },
199
200
 
200
- async removeLineDeliveryMode(): Promise<Cart> {
201
- if (true) {
202
- throw new Error("Error updating cart line delivery mode");
203
- }
201
+ async removeLineDeliveryMode(): Promise<cartSchema.Cart> {
202
+ throw new Error("Error updating cart line delivery mode");
204
203
  },
205
204
 
206
205
  async getCardAcceptPoint(): Promise<CardPaymentAcceptPoint> {
207
- if (true) {
208
- throw new Error("Error getCardAcceptPoint");
209
- }
206
+ throw new Error("Error getCardAcceptPoint");
210
207
  },
211
208
 
212
209
  async retrieveCardPaymentAcceptResult(): Promise<CardPaymentAcceptResult> {
213
- if (true) {
214
- throw new Error("Error retrieveCardPaymentAcceptResult");
215
- }
210
+ throw new Error("Error retrieveCardPaymentAcceptResult");
216
211
  },
217
212
 
218
213
  async checkout(): Promise<SalesOrder> {
@@ -223,9 +218,14 @@ const cart: CartApi = {
223
218
  const chars =
224
219
  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
225
220
  let token = "";
221
+
222
+ const randomValues = new Uint32Array(length);
223
+ crypto.getRandomValues(randomValues);
224
+
226
225
  for (let i = 0; i < length; i++) {
227
- token += chars[Math.floor(Math.random() * chars.length)];
226
+ token += chars[randomValues[i] % chars.length];
228
227
  }
228
+
229
229
  return token;
230
230
  };
231
231
 
@@ -244,6 +244,7 @@ const cart: CartApi = {
244
244
  SalesLines: [],
245
245
  };
246
246
  },
247
+
247
248
  getCartLinesInventory: (
248
249
  _input: cartSchema.InventorySearchCartLinesCriteriaInput,
249
250
  ): Promise<ProductWarehouseInventoryInformation> => {
@@ -42,7 +42,7 @@ export const cartLineMap = {
42
42
  "[].product.id": {
43
43
  key: "[].ProductId",
44
44
  transform: (id: string) => {
45
- if (id !== null) return parseInt(id);
45
+ if (id !== null) return Number.parseInt(id);
46
46
  },
47
47
  },
48
48
  "[].product.code": "[].ItemId",
@@ -14,7 +14,7 @@ import { merge } from "object-mapper";
14
14
  * @returns the transformed cart object
15
15
  */
16
16
  export const cartTransformValidate = (cart: E4Cart): Cart => {
17
- if (!(cart && cart?.id)) throw new Error("Not a valid cart");
17
+ if (!cart?.id) throw new Error("Not a valid cart");
18
18
  const transformedData = merge(cart, cartMap);
19
19
  try {
20
20
  extendedCartSchema.parse(transformedData);
@@ -11,31 +11,31 @@ interface TransformedCategoryNode extends Category {
11
11
  ParentCategory?: number;
12
12
  }
13
13
 
14
+ function generateSlug(name: string): string {
15
+ if (!name) return "";
16
+ return name
17
+ .toLowerCase()
18
+ .replaceAll(/\s+/g, "-")
19
+ .replaceAll(/[^\w-]+/g, "")
20
+ .replaceAll(/--+/g, "-")
21
+ .replace(/^-+/, "")
22
+ .replace(/-+$/, "");
23
+ }
24
+
14
25
  export const categoryTransformValidate = (
15
26
  rawCategories: E4Category[],
16
27
  rootParentId = 1,
17
28
  urlPrefix = "e4",
18
29
  ): CategoryHierarchy[] => {
19
- function generateSlug(name: string): string {
20
- if (!name) return "";
21
- return name
22
- .toLowerCase()
23
- .replace(/\s+/g, "-")
24
- .replace(/[^\w-]+/g, "")
25
- .replace(/--+/g, "-")
26
- .replace(/^-+/, "")
27
- .replace(/-+$/, "");
28
- }
29
-
30
30
  function createTransformedNode(
31
31
  rawCategory: E4Category,
32
32
  ): TransformedCategoryNode | null {
33
33
  let recordIdNum: number;
34
34
  try {
35
- recordIdNum = parseInt(String(rawCategory.id), 10);
36
- if (isNaN(recordIdNum)) throw new Error("Invalid RecordId");
35
+ recordIdNum = Number.parseInt(String(rawCategory.id), 10);
36
+ if (Number.isNaN(recordIdNum)) throw new Error("Invalid RecordId");
37
37
  } catch (e) {
38
- console.warn(`Skipping category due to invalid id:`, rawCategory);
38
+ console.warn(`Skipping category due to invalid id:`, rawCategory, e);
39
39
  return null;
40
40
  }
41
41
 
@@ -43,13 +43,13 @@ export const categoryTransformValidate = (
43
43
  const slug = generateSlug(categoryName);
44
44
  let parentIdNum: number | undefined;
45
45
  if (rawCategory.parentId != null) {
46
- const parsedParentId = parseInt(String(rawCategory.parentId), 10);
47
- if (!isNaN(parsedParentId)) parentIdNum = parsedParentId;
48
- else
46
+ const parsedParentId = Number.parseInt(String(rawCategory.parentId), 10);
47
+ if (Number.isNaN(parsedParentId))
49
48
  console.warn(
50
49
  `Invalid parentId format for id ${recordIdNum}:`,
51
50
  rawCategory.parentId,
52
51
  );
52
+ else parentIdNum = parsedParentId;
53
53
  }
54
54
 
55
55
  const node: TransformedCategoryNode = {
@@ -94,9 +94,9 @@ export const categoryTransformValidate = (
94
94
  categoryNode.Url = `${currentPath}/${categoryNode.RecordId}`;
95
95
  // Check if Children exists before iterating
96
96
  if (categoryNode?.Children && categoryNode?.Children?.length > 0) {
97
- categoryNode.Children.forEach((child: TransformedCategoryNode) =>
98
- calculateUrls(child, currentPath, prefix),
99
- );
97
+ categoryNode.Children.forEach((child: TransformedCategoryNode) => {
98
+ calculateUrls(child, currentPath, prefix);
99
+ });
100
100
  }
101
101
  }
102
102