@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.
- package/__mocks__/get-product-by-id.ts +0 -1
- package/__mocks__/query-client.ts +1 -1
- package/package.json +3 -3
- package/src/api-manager/datasources/d365/d365-address.datasource.ts +2 -2
- package/src/api-manager/datasources/d365/d365-cart.datasource.ts +4 -5
- package/src/api-manager/datasources/d365/d365-categories.datasource.ts +1 -1
- package/src/api-manager/datasources/d365/d365-product.datasource.ts +21 -7
- package/src/api-manager/datasources/d365/d365-session.datasource.ts +5 -7
- package/src/api-manager/datasources/d365/d365-user.datasource.ts +12 -23
- package/src/api-manager/datasources/d365/d365.datasource.ts +0 -2
- package/src/api-manager/datasources/d365/index.ts +2 -4
- package/src/api-manager/datasources/d365/utils/decode-jwt.ts +1 -2
- package/src/api-manager/datasources/d365/utils/parse-object.ts +1 -1
- package/src/api-manager/datasources/e4/address/e4-address.remaps.ts +2 -2
- package/src/api-manager/datasources/e4/address/e4-address.translator.ts +1 -1
- package/src/api-manager/datasources/e4/cart/e4-cart.datasource.ts +28 -27
- package/src/api-manager/datasources/e4/cart/e4-cart.remaps.ts +1 -1
- package/src/api-manager/datasources/e4/cart/e4-cart.translator.ts +1 -1
- package/src/api-manager/datasources/e4/categories/e4-categories.translator.ts +20 -20
- package/src/api-manager/datasources/e4/graphqlRequestSdk.ts +471 -7
- package/src/api-manager/datasources/e4/order/e4-order.remaps.ts +2 -2
- package/src/api-manager/datasources/e4/organization/e4-organization.datasource.ts +2 -8
- package/src/api-manager/datasources/e4/product/e4-product.remaps.ts +3 -3
- package/src/api-manager/datasources/e4/product/e4-product.translator.ts +13 -29
- package/src/api-manager/datasources/e4/session/e4-session.datasource.ts +1 -3
- package/src/api-manager/datasources/e4/user/e4-user.remaps.ts +2 -4
- package/src/api-manager/datasources/e4/utils/unwrap-e4-variants.ts +4 -4
- package/src/api-manager/index.ts +1 -1
- package/src/api-manager/lib/category-helpers.ts +3 -2
- package/src/api-manager/lib/get-graphql-client.ts +1 -2
- package/src/api-manager/services/cart/mutations/add-discount-code.ts +2 -2
- package/src/api-manager/services/cart/mutations/add-to-cart.ts +2 -2
- package/src/api-manager/services/product/server/product.server.ts +1 -1
- package/src/api-manager/types/Datasource.ts +4 -9
- package/src/auth/auth-options.test.ts +2 -58
- package/src/auth/auth-options.ts +1 -2
- package/src/auth/next-auth-cookie-manager.ts +0 -2
- package/src/auth/refresh-token.ts +3 -8
- package/src/auth/signout.ts +1 -1
- package/src/cms/blocks/block-manager.tsx +3 -3
- package/src/cms/blocks/components/category-card.tsx +1 -1
- package/src/cms/blocks/components/category-carousel/index.tsx +3 -1
- package/src/cms/blocks/components/footer/index.tsx +2 -2
- package/src/cms/blocks/components/footer/sections/footer-links.tsx +2 -2
- package/src/cms/blocks/components/footer/sections/footer-logo.tsx +1 -1
- package/src/cms/blocks/components/footer/sections/footer-social-links.tsx +10 -2
- package/src/cms/blocks/components/hero-carousel/index.tsx +29 -25
- package/src/cms/blocks/components/media-card.tsx +1 -1
- package/src/cms/blocks/components/product-carousel/index.tsx +1 -1
- package/src/cms/blocks/components/product-section-fullwidth/index.tsx +2 -2
- package/src/cms/blocks/components/seo/index.tsx +5 -1
- package/src/cms/blocks/components/services/index.tsx +1 -1
- package/src/cms/blocks/components/services/service-card.tsx +1 -1
- package/src/cms/blocks/components/shared/featured-product-card.tsx +4 -1
- package/src/cms/blocks/components/shared/product-category-item.tsx +1 -1
- package/src/cms/blocks/components/shared/product-grid.tsx +4 -1
- package/src/cms/blocks/components/shared/top-categories-card.tsx +5 -1
- package/src/cms/blocks/components/shared/top-rating-product-card.tsx +1 -1
- package/src/components-v2/BazaarImage.tsx +1 -1
- package/src/components-v2/BazaarMenu.tsx +2 -2
- package/src/components-v2/BazaarTextField.tsx +3 -3
- package/src/components-v2/BorderShadowCard.stories.tsx +1 -1
- package/src/components-v2/DropZone.tsx +1 -2
- package/src/components-v2/Typography.tsx +12 -12
- package/src/components-v2/accordion/accordion-header.tsx +1 -1
- package/src/components-v2/categories/category-list/styles.ts +0 -7
- package/src/components-v2/categories/category-list-item/category-menu-item.tsx +1 -1
- package/src/components-v2/categories/category-menu.tsx +16 -13
- package/src/components-v2/categories/mega-menu/mega-menu-1.tsx +1 -1
- package/src/components-v2/categories/mega-menu/mega-menu-2.tsx +2 -2
- package/src/components-v2/header/components/user.tsx +5 -5
- package/src/components-v2/mini-cart/__tests__/cart-item.test.tsx +13 -13
- package/src/components-v2/mini-cart/components/bottom-actions.tsx +1 -1
- package/src/components-v2/mini-cart/components/cart-item.tsx +3 -3
- package/src/components-v2/mini-cart/components/top-header.tsx +2 -2
- package/src/components-v2/mobile-navigation/mobile-navigation-bar.tsx +1 -1
- package/src/components-v2/nav-link/nav-link-2.tsx +1 -1
- package/src/components-v2/nav-link/nav-link-3.tsx +1 -1
- package/src/components-v2/nav-link/nav-link.tsx +1 -1
- package/src/components-v2/navbar/categories.tsx +3 -1
- package/src/components-v2/navbar/category-based-menu/category-based-menu.tsx +2 -2
- package/src/components-v2/navbar/mobile-menu/mobile-menu.tsx +11 -3
- package/src/components-v2/navbar/nav-list/nav-item-child.tsx +1 -1
- package/src/components-v2/navbar/nav-list/nav-list.tsx +118 -80
- package/src/components-v2/navbar/navbar.tsx +1 -1
- package/src/components-v2/no-records.tsx +1 -1
- package/src/components-v2/product-cards/favorite-button.tsx +1 -1
- package/src/components-v2/product-cards/product-card/product-card.tsx +5 -7
- package/src/components-v2/product-cards/product-card-plp/product-card.tsx +7 -6
- package/src/components-v2/product-cards/product-card-plp-list/components/tags.tsx +1 -1
- package/src/components-v2/product-cards/product-card-plp-list/product-card.tsx +7 -4
- package/src/components-v2/product-cards/product-card-search/product-card.tsx +4 -2
- package/src/components-v2/product-cards/product-price.tsx +1 -1
- package/src/components-v2/product-cards/product-rating.tsx +1 -1
- package/src/components-v2/product-cards/product-title.tsx +1 -1
- package/src/components-v2/product-cards/quantity-buttons.tsx +1 -1
- package/src/components-v2/product-dialog/compound/product-dialog.tsx +2 -2
- package/src/components-v2/product-dialog/index.tsx +1 -1
- package/src/components-v2/product-dimensions/compound/dimensions-group-list.tsx +6 -1
- package/src/components-v2/product-dimensions/index.tsx +3 -3
- package/src/components-v2/product-quantity-buttons/compound/quantity-buttons-root.tsx +1 -1
- package/src/components-v2/product-quantity-variants/index.tsx +1 -2
- package/src/components-v2/products-view/ProductsList.stories.tsx +0 -2
- package/src/components-v2/products-view/compound/products-grid-view.tsx +2 -2
- package/src/components-v2/products-view/compound/products-list-view.tsx +3 -3
- package/src/components-v2/products-view/index.tsx +2 -2
- package/src/components-v2/progress/progress.tsx +1 -1
- package/src/components-v2/scrollbar/scrollbar.tsx +1 -1
- package/src/components-v2/search-bar/compound/results-suspense.tsx +1 -2
- package/src/components-v2/search-bar/compound/results.tsx +6 -3
- package/src/components-v2/search-bar/compound/search-bar-root.tsx +4 -2
- package/src/components-v2/search-bar/compound/textfield-adornment-category.tsx +25 -27
- package/src/components-v2/search-bar/compound/textfield.tsx +0 -1
- package/src/components-v2/search-bar/hooks/use-search.ts +1 -1
- package/src/components-v2/section/Section.stories.tsx +1 -1
- package/src/components-v2/side-nav/side-nav.tsx +1 -1
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-dialog.tsx +1 -1
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-list.tsx +2 -2
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/hooks/use-add-to-wishlist.ts +2 -0
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/index.tsx +11 -13
- package/src/components-v2/wishlist-dialogs/create-wishlist/compound/create-wishlist-dialog.tsx +2 -1
- package/src/hooks/use-variants.ts +25 -27
- package/src/lib/build-detail-url.ts +1 -1
- package/src/lib/category-helpers.ts +3 -3
- package/src/lib/get-palette-color.ts +35 -15
- package/src/lib/hexToLuma.ts +2 -2
- package/src/lib/store-hours-helper.ts +5 -5
- package/src/pages-v2/account/addresses/address-form.tsx +10 -8
- package/src/pages-v2/account/addresses/address-item.tsx +1 -1
- package/src/pages-v2/account/orders/order-progress.tsx +1 -1
- package/src/pages-v2/account/orders/ordered-products.tsx +1 -1
- package/src/pages-v2/account/profile/user-info.tsx +1 -2
- package/src/pages-v2/account/wishlist/create-new-list.tsx +1 -0
- package/src/pages-v2/account/wishlist/wishlist-item.tsx +2 -1
- package/src/pages-v2/blog/blog-card.tsx +1 -1
- package/src/pages-v2/cart/__tests__/cart-item.test.tsx +0 -1
- package/src/pages-v2/cart/__tests__/checkout-form.test.tsx +0 -8
- package/src/pages-v2/cart/cart-item.tsx +86 -77
- package/src/pages-v2/cart/checkout-form.tsx +4 -4
- package/src/pages-v2/cart/coupon-entry.tsx +3 -3
- package/src/pages-v2/cart/estimate-shipping.tsx +6 -6
- package/src/pages-v2/checkout/checkout-alt-form/checkout-form.tsx +2 -2
- package/src/pages-v2/checkout/checkout-alt-form/checkout-step.tsx +2 -2
- package/src/pages-v2/checkout/checkout-alt-form/step-heading.tsx +1 -1
- package/src/pages-v2/checkout/checkout-alt-form/steps/address/delivery-address.tsx +12 -10
- package/src/pages-v2/checkout/checkout-alt-form/steps/address/new-address-form.tsx +5 -6
- package/src/pages-v2/checkout/checkout-alt-form/steps/customer-info/customer-information.tsx +8 -9
- package/src/pages-v2/checkout/checkout-alt-form/steps/payment/payment-details.tsx +17 -20
- package/src/pages-v2/checkout/checkout-alt-form/steps/shipping/delivery-date.tsx +1 -1
- package/src/pages-v2/checkout/checkout-alt-form/steps/shipping/delivery-options.tsx +14 -15
- package/src/pages-v2/confirmation/confirmation-summary.tsx +8 -7
- package/src/pages-v2/confirmation/ordered-products.tsx +3 -3
- package/src/pages-v2/product-details/bopis/pickup-option-select.tsx +1 -1
- package/src/pages-v2/product-details/bopis/store-card/shop-card.tsx +1 -1
- package/src/pages-v2/product-details/checkbox-label.tsx +1 -1
- package/src/pages-v2/product-details/frequently-bought.tsx +1 -1
- package/src/pages-v2/product-details/frequently-product-card.tsx +1 -1
- package/src/pages-v2/product-details/product-comment.tsx +1 -1
- package/src/pages-v2/product-details/product-description.tsx +2 -2
- package/src/pages-v2/product-details/product-filter-card.tsx +4 -1
- package/src/pages-v2/product-details/product-intro/compound/product-intro-images.tsx +36 -31
- package/src/pages-v2/product-details/product-intro/compound/product-intro.tsx +1 -1
- package/src/pages-v2/product-details/product-intro/compound/thumbnail-with-skeleton.tsx +1 -1
- package/src/pages-v2/product-details/product-intro/utils.ts +2 -4
- package/src/pages-v2/product-details/product-review.tsx +1 -1
- package/src/pages-v2/product-details/product-tabs.tsx +5 -2
- package/src/pages-v2/product-details/related-products.tsx +7 -4
- package/src/pages-v2/product-list/breadcrumbs.tsx +1 -1
- package/src/pages-v2/product-list/checkbox-label.tsx +1 -1
- package/src/pages-v2/product-list/facet-group.tsx +1 -1
- package/src/pages-v2/product-list/list-filter.tsx +2 -2
- package/src/pages-v2/product-list/product-list-context.tsx +5 -1
- package/src/pages-v2/product-list/product-list-view.tsx +4 -1
- package/src/pages-v2/product-list/product-rating.tsx +4 -1
- package/src/pages-v2/product-list/quick-view-dialog-content.tsx +2 -4
- package/src/pages-v2/product-list/quick-view-dialog.tsx +5 -1
- package/src/pages-v2/product-list/range-filter.tsx +0 -1
- package/src/pages-v2/product-list/scrollbar.tsx +1 -1
- package/src/pages-v2/product-list/side-nav.tsx +1 -1
- package/src/pages-v2/product-list/swatch.tsx +12 -7
- package/src/pages-v2/product-list/utils/getCategoryFilterFromSlug.ts +33 -68
- package/src/pages-v2/product-list/utils/product-list-helper.ts +1 -1
- package/src/pages-v2/product-list/utils/search-for-category.ts +2 -2
- package/src/pages-v2/quickorder/order-upload.tsx +90 -76
- package/src/pages-v2/quickorder/provider.tsx +6 -4
- package/src/pages-v2/quickorder/quick-order-row.tsx +1 -1
- package/src/pages-v2/quickorder/quick-order.tsx +28 -21
- package/src/providers/notifications/notification-context.tsx +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evenicanpm/storefront-core",
|
|
3
|
-
"version": "1.
|
|
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.
|
|
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": "
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
|
|
@@ -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 =
|
|
158
|
-
const
|
|
159
|
-
|
|
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
|
-
|
|
165
|
-
|
|
177
|
+
productSearchResult,
|
|
178
|
+
refinersPromise,
|
|
166
179
|
]);
|
|
167
|
-
|
|
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 =
|
|
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
|
|
10
|
+
return {} as Session;
|
|
14
11
|
}
|
|
12
|
+
|
|
15
13
|
async sessionLogout(): Promise<boolean> {
|
|
16
14
|
return true;
|
|
17
15
|
}
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
|
|
17
|
+
async getSession(): Promise<Session> {
|
|
20
18
|
console.warn("getSession not implemented on d365");
|
|
21
|
-
return
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
186
|
+
productList,
|
|
185
187
|
);
|
|
186
188
|
return wishlist;
|
|
187
189
|
} catch (error) {
|
|
188
|
-
throw new 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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
271
|
+
throw new Error(`Error copying cart to wishlist: ${error}`);
|
|
283
272
|
}
|
|
284
273
|
}
|
|
285
274
|
}
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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 =
|
|
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
|
}
|
|
@@ -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
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
208
|
-
throw new Error("Error getCardAcceptPoint");
|
|
209
|
-
}
|
|
206
|
+
throw new Error("Error getCardAcceptPoint");
|
|
210
207
|
},
|
|
211
208
|
|
|
212
209
|
async retrieveCardPaymentAcceptResult(): Promise<CardPaymentAcceptResult> {
|
|
213
|
-
|
|
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[
|
|
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> => {
|
|
@@ -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 (!
|
|
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 (
|
|
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
|
|