@mframework/layer-commerce 0.0.3 → 0.0.4
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/app/normalizers/Cart.query.ts +8 -0
- package/app/normalizers/Category.query.ts +7 -0
- package/app/normalizers/Category.type.ts +28 -0
- package/app/normalizers/Checkout.query.ts +22 -0
- package/app/normalizers/CmsPage.type.ts +14 -0
- package/app/normalizers/Menu.query.ts +9 -1
- package/app/normalizers/Menu.type.ts +18 -0
- package/app/normalizers/Order.query.ts +14 -0
- package/app/normalizers/ProductList.query.ts +9 -0
- package/app/normalizers/Review.query.ts +7 -0
- package/app/normalizers/UrlRewrites.query.ts +7 -0
- package/app/normalizers/UrlRewrites.type.ts +15 -0
- package/app/normalizers/Wishlist.query.ts +26 -0
- package/app/stores/Product/Product.dispatcher.ts +13 -1
- package/app/stores/ProductList/ProductList.dispatcher.ts +12 -5
- package/app/stores/orders.ts +3 -2
- package/app/utils/DynamicReducer/index.tsx +2 -2
- package/app/utils/Preload/index.ts +3 -6
- package/app/utils/client.ts +95 -1
- package/package.json +1 -1
- package/app/stores/Product/Product.reducer.ts +0 -12
- package/app/stores/ProductList/ProductList.reducer.ts +0 -13
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
SelectedShippingMethod,
|
|
50
50
|
UserErrors,
|
|
51
51
|
} from './Cart.type';
|
|
52
|
+
import { normalizeCart } from './Cart.type';
|
|
52
53
|
|
|
53
54
|
/** @namespace ../../normalizers/Cart/Query */
|
|
54
55
|
export class CartQuery {
|
|
@@ -727,3 +728,10 @@ export class CartQuery {
|
|
|
727
728
|
}
|
|
728
729
|
|
|
729
730
|
export default new CartQuery();
|
|
731
|
+
|
|
732
|
+
export function normalizeCartResponse(raw: any) {
|
|
733
|
+
if (!raw) return null;
|
|
734
|
+
if (raw.cartData) return normalizeCart(raw.cartData as any);
|
|
735
|
+
if (raw.cart) return normalizeCart(raw.cart as any);
|
|
736
|
+
return normalizeCart(raw as any);
|
|
737
|
+
}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
CategoryQueryOptions,
|
|
18
18
|
CategoryTree,
|
|
19
19
|
CmsBlock,
|
|
20
|
+
normalizeCategory,
|
|
20
21
|
} from './Category.type';
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -144,3 +145,9 @@ export class CategoryQuery {
|
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
export default new CategoryQuery();
|
|
148
|
+
|
|
149
|
+
export function normalizeCategoryResponse(raw: any): Category | null {
|
|
150
|
+
if (!raw) return null;
|
|
151
|
+
if (raw.category) return normalizeCategory(raw.category as any);
|
|
152
|
+
return normalizeCategory(raw as any);
|
|
153
|
+
}
|
|
@@ -53,3 +53,31 @@ export interface CategoryQueryOptions {
|
|
|
53
53
|
categoryIds: number;
|
|
54
54
|
isSearchPage?: boolean;
|
|
55
55
|
}
|
|
56
|
+
|
|
57
|
+
// Lightweight normalizer for category objects. Adapters can provide
|
|
58
|
+
// richer implementations; this helper maps common fields into a stable
|
|
59
|
+
// Category shape used by the commerce layer.
|
|
60
|
+
export function normalizeCategory(raw: any): Category {
|
|
61
|
+
if (!raw) return raw;
|
|
62
|
+
return {
|
|
63
|
+
id: raw?.id ?? raw?.category_id ?? raw?.uid ?? '',
|
|
64
|
+
url: raw?.url ?? raw?.url_key ?? raw?.url_path ?? '',
|
|
65
|
+
name: raw?.name ?? raw?.label ?? raw?.category_name ?? '',
|
|
66
|
+
image: raw?.image ?? raw?.thumbnail ?? '',
|
|
67
|
+
url_key: raw?.url_key ?? raw?.url ?? '',
|
|
68
|
+
url_path: raw?.url_path ?? raw?.url_key ?? '',
|
|
69
|
+
is_active: raw?.is_active ?? raw?.active ?? true,
|
|
70
|
+
meta_title: raw?.meta_title ?? raw?.title ?? '',
|
|
71
|
+
description: raw?.description ?? raw?.meta_description ?? '',
|
|
72
|
+
canonical_url: raw?.canonical_url ?? raw?.canonical ?? '',
|
|
73
|
+
product_count: raw?.product_count ?? raw?.products_count ?? 0,
|
|
74
|
+
meta_keywords: raw?.meta_keywords ?? raw?.keywords ?? '',
|
|
75
|
+
default_sort_by: raw?.default_sort_by ?? raw?.defaultSortBy ?? '',
|
|
76
|
+
meta_description: raw?.meta_description ?? raw?.description ?? '',
|
|
77
|
+
landing_page: raw?.landing_page ?? raw?.page ?? 0,
|
|
78
|
+
display_mode: raw?.display_mode ?? raw?.mode ?? '',
|
|
79
|
+
is_anchor: raw?.is_anchor ?? raw?.anchor ?? false,
|
|
80
|
+
cms_block: raw?.cms_block ?? raw?.cms ?? null,
|
|
81
|
+
breadcrumbs: Array.isArray(raw?.breadcrumbs) ? raw.breadcrumbs : (raw?.breadcrumb ? [raw.breadcrumb] : []),
|
|
82
|
+
} as Category;
|
|
83
|
+
}
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
TotalsItem,
|
|
28
28
|
TotalsObject,
|
|
29
29
|
} from './Checkout.type';
|
|
30
|
+
import { normalizeOrder } from './Order.type';
|
|
30
31
|
|
|
31
32
|
/** @namespace ../../normalizers/Checkout/Query */
|
|
32
33
|
export class CheckoutQuery {
|
|
@@ -251,3 +252,24 @@ export class CheckoutQuery {
|
|
|
251
252
|
}
|
|
252
253
|
|
|
253
254
|
export default new CheckoutQuery();
|
|
255
|
+
|
|
256
|
+
export function normalizePaymentMethodsResponse(raw: any): PaymentMethod[] {
|
|
257
|
+
if (!raw) return [];
|
|
258
|
+
const payload = raw.paymentMethods ?? raw.payment_methods ?? raw;
|
|
259
|
+
return Array.isArray(payload) ? payload : (Array.isArray(payload?.payment_methods) ? payload.payment_methods : []);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function normalizeTotalsResponse(raw: any): TotalsObject | null {
|
|
263
|
+
if (!raw) return null;
|
|
264
|
+
const payload = raw.totals ?? raw.Totals ?? raw;
|
|
265
|
+
return payload || null;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export function normalizePlaceOrderResponse(raw: any) {
|
|
269
|
+
if (!raw) return null;
|
|
270
|
+
// placeOrder typically returns { order: { order_id } }
|
|
271
|
+
const payload = raw.placeOrder ?? raw.order ?? raw;
|
|
272
|
+
if (payload?.order) return normalizeOrder(payload.order as any);
|
|
273
|
+
if (payload?.order_id) return { id: String(payload.order_id), raw: payload };
|
|
274
|
+
return payload;
|
|
275
|
+
}
|
|
@@ -24,3 +24,17 @@ export interface CmsPageQueryOptions {
|
|
|
24
24
|
url_key: string;
|
|
25
25
|
identifier: string;
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
export function normalizeCmsPage(raw: any): CmsPageFields | null {
|
|
29
|
+
if (!raw) return null;
|
|
30
|
+
const fields: CmsPageFields = {
|
|
31
|
+
title: raw?.title ?? raw?.page_title ?? '',
|
|
32
|
+
content: raw?.content ?? raw?.content_html ?? raw?.body ?? '',
|
|
33
|
+
page_width: raw?.page_width ?? raw?.width ?? 'full',
|
|
34
|
+
content_heading: raw?.content_heading ?? raw?.heading ?? '',
|
|
35
|
+
meta_title: raw?.meta_title ?? raw?.title ?? '',
|
|
36
|
+
meta_description: raw?.meta_description ?? raw?.description ?? '',
|
|
37
|
+
meta_keywords: raw?.meta_keywords ?? raw?.keywords ?? '',
|
|
38
|
+
};
|
|
39
|
+
return fields;
|
|
40
|
+
}
|
|
@@ -13,7 +13,7 @@ import { Field, Query } from '@tilework/opus';
|
|
|
13
13
|
|
|
14
14
|
import { CategoryDisplayMode } from '../routes/CategoryPage/CategoryPage.config';
|
|
15
15
|
|
|
16
|
-
import { MenuItem } from './Menu.type';
|
|
16
|
+
import { MenuItem, normalizeMenuItems } from './Menu.type';
|
|
17
17
|
/**
|
|
18
18
|
* Menu Query
|
|
19
19
|
* @class MenuQuery
|
|
@@ -52,3 +52,11 @@ export class MenuQuery {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
export default new MenuQuery();
|
|
55
|
+
|
|
56
|
+
export function normalizeMenuResponse(raw: any): MenuItem[] {
|
|
57
|
+
if (!raw) return [];
|
|
58
|
+
if (raw.menu) return normalizeMenuItems(raw.menu);
|
|
59
|
+
if (Array.isArray(raw)) return normalizeMenuItems(raw);
|
|
60
|
+
if (Array.isArray(raw?.menuItems)) return normalizeMenuItems(raw.menuItems);
|
|
61
|
+
return normalizeMenuItems(raw);
|
|
62
|
+
}
|
|
@@ -20,3 +20,21 @@ export interface MenuItem {
|
|
|
20
20
|
category_id: number;
|
|
21
21
|
display_mode: CategoryDisplayMode;
|
|
22
22
|
}
|
|
23
|
+
|
|
24
|
+
export function normalizeMenuItems(raw: any): MenuItem[] {
|
|
25
|
+
if (!raw) return [];
|
|
26
|
+
if (Array.isArray(raw)) {
|
|
27
|
+
return raw.map((it: any) => ({
|
|
28
|
+
url: it?.url ?? it?.link ?? '',
|
|
29
|
+
title: it?.title ?? it?.label ?? it?.name ?? '',
|
|
30
|
+
item_id: String(it?.item_id ?? it?.id ?? ''),
|
|
31
|
+
position: Number(it?.position ?? 0),
|
|
32
|
+
parent_id: Number(it?.parent_id ?? it?.parent ?? 0),
|
|
33
|
+
category_id: Number(it?.category_id ?? it?.cat_id ?? 0),
|
|
34
|
+
display_mode: it?.display_mode ?? it?.mode ?? 'PRODUCTS',
|
|
35
|
+
} as MenuItem));
|
|
36
|
+
}
|
|
37
|
+
// If the payload contains an items key, map that
|
|
38
|
+
if (Array.isArray(raw?.items)) return normalizeMenuItems(raw.items);
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
ShippingHandling,
|
|
42
42
|
TaxItem,
|
|
43
43
|
} from './Order.type';
|
|
44
|
+
import { normalizeOrder } from './Order.type';
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
47
|
* Order Query
|
|
@@ -739,3 +740,16 @@ export class OrderQuery {
|
|
|
739
740
|
}
|
|
740
741
|
|
|
741
742
|
export default new OrderQuery();
|
|
743
|
+
|
|
744
|
+
export function normalizeOrderResponse(raw: any) {
|
|
745
|
+
if (!raw) return null;
|
|
746
|
+
if (raw.order) return normalizeOrder(raw.order as any);
|
|
747
|
+
if (raw.orderData) return normalizeOrder(raw.orderData as any);
|
|
748
|
+
return normalizeOrder(raw as any);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
export function normalizeOrdersResponse(raw: any) {
|
|
752
|
+
if (!raw) return [];
|
|
753
|
+
const list = Array.isArray(raw.items) ? raw.items : (Array.isArray(raw) ? raw : (raw.orders ?? raw.items ?? []));
|
|
754
|
+
return Array.isArray(list) ? list.map((o: any) => normalizeOrder(o)) : [];
|
|
755
|
+
}
|
|
@@ -83,6 +83,8 @@ import {
|
|
|
83
83
|
SwatchData,
|
|
84
84
|
TierPrice,
|
|
85
85
|
UrlRewrite,
|
|
86
|
+
NormalizedProductsQueryOutput,
|
|
87
|
+
normalizeProductsQueryOutput,
|
|
86
88
|
VariantItem,
|
|
87
89
|
} from './ProductList.type';
|
|
88
90
|
|
|
@@ -1618,3 +1620,10 @@ export class ProductListQuery {
|
|
|
1618
1620
|
}
|
|
1619
1621
|
|
|
1620
1622
|
export default new ProductListQuery();
|
|
1623
|
+
|
|
1624
|
+
// Normalize a products GraphQL response into the canonical NormalizedProductsQueryOutput
|
|
1625
|
+
export function normalizeProductsResponse(raw: any): NormalizedProductsQueryOutput {
|
|
1626
|
+
if (!raw) return normalizeProductsQueryOutput({ items: [], sort_fields: { options: [] }, filters: [], total_count: 0, page_info: { current_page: 1, total_pages: 1 } });
|
|
1627
|
+
if (raw.products) return normalizeProductsQueryOutput(raw.products);
|
|
1628
|
+
return normalizeProductsQueryOutput(raw);
|
|
1629
|
+
}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
ReviewRatingItem,
|
|
19
19
|
ReviewRatingValue,
|
|
20
20
|
} from './Review.type';
|
|
21
|
+
import { normalizeReview } from './Review.type';
|
|
21
22
|
|
|
22
23
|
/** @namespace ../../normalizers/Review/Query */
|
|
23
24
|
export class ReviewQuery {
|
|
@@ -79,3 +80,9 @@ export class ReviewQuery {
|
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
export default new ReviewQuery();
|
|
83
|
+
|
|
84
|
+
export function normalizeReviewResponse(raw: any) {
|
|
85
|
+
if (!raw) return null;
|
|
86
|
+
if (raw.review) return normalizeReview(raw.review as any);
|
|
87
|
+
return normalizeReview(raw as any);
|
|
88
|
+
}
|
|
@@ -16,6 +16,7 @@ import { GQLUrlRewriteEntityTypeEnum } from '../types/Graphql.type';
|
|
|
16
16
|
import {
|
|
17
17
|
UrlRewritesOutput,
|
|
18
18
|
UrlRewritesQueryOptions,
|
|
19
|
+
normalizeUrlRewriteResponse,
|
|
19
20
|
} from './UrlRewrites.type';
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -53,3 +54,9 @@ export class UrlRewritesQuery {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
export default new UrlRewritesQuery();
|
|
57
|
+
|
|
58
|
+
export function normalizeUrlRewrite(raw: any): UrlRewritesOutput | null {
|
|
59
|
+
if (!raw) return null;
|
|
60
|
+
if (raw.urlResolver) return normalizeUrlRewriteResponse(raw.urlResolver as any);
|
|
61
|
+
return normalizeUrlRewriteResponse(raw as any);
|
|
62
|
+
}
|
|
@@ -23,3 +23,18 @@ export interface UrlRewritesOutput {
|
|
|
23
23
|
export interface UrlRewritesQueryOptions {
|
|
24
24
|
urlParam: string;
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
export function normalizeUrlRewriteResponse(raw: any): UrlRewritesOutput | null {
|
|
28
|
+
if (!raw) return null;
|
|
29
|
+
// GraphQL urlResolver may return the object directly or wrap it under
|
|
30
|
+
// urlResolver property depending on response shape.
|
|
31
|
+
const payload = raw?.urlResolver ?? raw;
|
|
32
|
+
if (!payload) return null;
|
|
33
|
+
return {
|
|
34
|
+
sku: payload?.sku ?? payload?.product_sku ?? '',
|
|
35
|
+
type: payload?.type ?? payload?.entity_type ?? (payload?.is_category ? 'CATEGORY' : 'PRODUCT'),
|
|
36
|
+
id: Number(payload?.id ?? payload?.entity_id ?? 0),
|
|
37
|
+
display_mode: payload?.display_mode ?? payload?.mode ?? 'PRODUCTS',
|
|
38
|
+
sort_by: payload?.sort_by ?? payload?.sort ?? '',
|
|
39
|
+
} as UrlRewritesOutput;
|
|
40
|
+
}
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
WishlistItem,
|
|
29
29
|
WishListUserInputError,
|
|
30
30
|
} from './Wishlist.type';
|
|
31
|
+
import { normalizeProduct } from './ProductList.type';
|
|
31
32
|
|
|
32
33
|
/** @namespace ../../normalizers/Wishlist/Query */
|
|
33
34
|
export class WishlistQuery {
|
|
@@ -200,3 +201,28 @@ export class WishlistQuery {
|
|
|
200
201
|
}
|
|
201
202
|
|
|
202
203
|
export default new WishlistQuery();
|
|
204
|
+
|
|
205
|
+
export function normalizeWishlistResponse(raw: any): Wishlist | null {
|
|
206
|
+
if (!raw) return null;
|
|
207
|
+
const payload = raw.wishlist ?? raw;
|
|
208
|
+
const items = Array.isArray(payload.items) ? payload.items.map((it: any) => ({
|
|
209
|
+
id: String(it?.id ?? it?.uid ?? ''),
|
|
210
|
+
sku: it?.sku ?? it?.product?.sku ?? '',
|
|
211
|
+
qty: Number(it?.qty ?? it?.quantity ?? 0),
|
|
212
|
+
description: it?.description ?? it?.product?.description ?? '',
|
|
213
|
+
price: it?.price ?? it?.product?.price ?? 0,
|
|
214
|
+
price_without_tax: it?.price_without_tax ?? 0,
|
|
215
|
+
buy_request: it?.buy_request ?? '',
|
|
216
|
+
options: it?.options ?? [],
|
|
217
|
+
product: it?.product ? normalizeProduct(it.product) : (it?.product as any),
|
|
218
|
+
raw: it,
|
|
219
|
+
} as WishlistItem)) : [];
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
id: Number(payload.id ?? 0),
|
|
223
|
+
updated_at: payload.updated_at ?? payload.updatedAt ?? '',
|
|
224
|
+
items_count: Number(payload.items_count ?? items.length),
|
|
225
|
+
creators_name: payload.creators_name ?? '',
|
|
226
|
+
items,
|
|
227
|
+
} as Wishlist;
|
|
228
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getCommerceClient } from '../../utils/client'
|
|
2
|
+
import { useProductStore } from '../product'
|
|
2
3
|
|
|
3
4
|
// Product dispatcher that uses the normalized commerce client when available.
|
|
4
5
|
export async function fetchProductById(id: string): Promise<any | null> {
|
|
@@ -35,7 +36,18 @@ export async function handleData(dispatch: any, options: any) {
|
|
|
35
36
|
try {
|
|
36
37
|
if (typeof dispatch === 'function' && options && options.id) {
|
|
37
38
|
const product = await fetchProductById(options.id)
|
|
38
|
-
|
|
39
|
+
// Update Pinia store when available
|
|
40
|
+
try {
|
|
41
|
+
const store = useProductStore()
|
|
42
|
+
if (store && typeof store.selectProduct === 'function') {
|
|
43
|
+
store.selectProduct(product)
|
|
44
|
+
} else if (store) {
|
|
45
|
+
;(store as any).selectedProduct = product
|
|
46
|
+
}
|
|
47
|
+
} catch (e) {
|
|
48
|
+
// ignore Pinia errors
|
|
49
|
+
}
|
|
50
|
+
|
|
39
51
|
return product
|
|
40
52
|
}
|
|
41
53
|
} catch (e) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getCommerceClient } from '../../utils/client'
|
|
2
|
+
import { useProductListStore } from '../productList'
|
|
2
3
|
|
|
3
4
|
// ProductList dispatcher that prefers the normalized commerce client when
|
|
4
5
|
// available. Returns an array of normalized products or an empty array.
|
|
@@ -21,13 +22,19 @@ export async function fetchProductList(params: any = {}): Promise<any[]> {
|
|
|
21
22
|
|
|
22
23
|
export async function handleData(dispatch: any, options: any) {
|
|
23
24
|
const data = await fetchProductList(options)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
//
|
|
25
|
+
// Update Pinia store when available
|
|
26
|
+
try {
|
|
27
|
+
const store = useProductListStore()
|
|
28
|
+
if (store && typeof store.fetch === 'function') {
|
|
29
|
+
// let the store perform its fetch to populate items/state consistently
|
|
30
|
+
await store.fetch(options)
|
|
31
|
+
} else if (store) {
|
|
32
|
+
;(store as any).items = Array.isArray(data) ? data : []
|
|
29
33
|
}
|
|
34
|
+
} catch (e) {
|
|
35
|
+
// ignore Pinia errors
|
|
30
36
|
}
|
|
37
|
+
|
|
31
38
|
return data
|
|
32
39
|
}
|
|
33
40
|
|
package/app/stores/orders.ts
CHANGED
|
@@ -125,7 +125,8 @@ export const useOrdersStore = defineStore('orders', () => {
|
|
|
125
125
|
// Computed properties
|
|
126
126
|
const ordersByStatus = computed(() => {
|
|
127
127
|
return orders.value.reduce((acc: Record<string, number>, order: Order) => {
|
|
128
|
-
|
|
128
|
+
const status = order?.status ?? 'unknown'
|
|
129
|
+
acc[status] = (acc[status] || 0) + 1
|
|
129
130
|
return acc
|
|
130
131
|
}, {} as Record<string, number>)
|
|
131
132
|
})
|
|
@@ -139,7 +140,7 @@ export const useOrdersStore = defineStore('orders', () => {
|
|
|
139
140
|
|
|
140
141
|
const averageOrderValue = computed(() => {
|
|
141
142
|
const validOrders = orders.value.filter((order: Order) =>
|
|
142
|
-
!['cancelled', 'refunded'].includes(order
|
|
143
|
+
!['cancelled', 'refunded'].includes(order?.status ?? '')
|
|
143
144
|
)
|
|
144
145
|
return validOrders.length > 0 ? totalRevenue.value / validOrders.length : 0
|
|
145
146
|
})
|
|
@@ -23,8 +23,8 @@ export const withReducers = (reducers: Record<string, Reducer>) => (
|
|
|
23
23
|
WrappedComponent: ElementType,
|
|
24
24
|
): WithReducersResult => {
|
|
25
25
|
const injectAndExecute = (props: Props) => {
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
// Reducer injection is deprecated — we no longer inject Redux reducers.
|
|
27
|
+
// Keep this wrapper for API compatibility but avoid mutating the legacy store.
|
|
28
28
|
// eslint-disable-next-line @mframework/mframework-guidelines/jsx-no-props-destruction
|
|
29
29
|
return <WrappedComponent { ...props } />;
|
|
30
30
|
};
|
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { UrlRewritePageType } from '../../routes/UrlRewrites/UrlRewrites.config';
|
|
13
|
-
|
|
14
|
-
import ProductListReducer from '../../stores/ProductList/ProductList.reducer';
|
|
13
|
+
// Reducers removed — migration to Pinia stores; keep Preload minimal
|
|
15
14
|
import BrowserDatabase from '../../utils/BrowserDatabase';
|
|
16
15
|
import { isMobile } from '../../utils/Mobile';
|
|
17
16
|
import getStore, { injectReducers } from '../../utils/Store';
|
|
@@ -19,10 +18,8 @@ import getStore, { injectReducers } from '../../utils/Store';
|
|
|
19
18
|
import CategoryPreload from './CategoryPreload';
|
|
20
19
|
import ProductPreload from './ProductPreload';
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
ProductListReducer,
|
|
25
|
-
});
|
|
21
|
+
// Previously reducers were injected here for legacy Redux-style consumers.
|
|
22
|
+
// Reducers have been migrated into Pinia stores; no injection needed.
|
|
26
23
|
|
|
27
24
|
const { actionName: { type = '' } = {} } = window;
|
|
28
25
|
|
package/app/utils/client.ts
CHANGED
|
@@ -2,6 +2,14 @@ import * as CommercePkg from '~/types';
|
|
|
2
2
|
import { sdk } from '@mframework/sdk';
|
|
3
3
|
import imports from '../types';
|
|
4
4
|
import { normalizeProductsQueryOutput, normalizeProduct } from '../normalizers/ProductList.type';
|
|
5
|
+
import { normalizeProductsResponse } from '../normalizers/ProductList.query';
|
|
6
|
+
import { normalizeMenuResponse } from '../normalizers/Menu.query';
|
|
7
|
+
import { normalizeCategoryResponse } from '../normalizers/Category.query';
|
|
8
|
+
import { normalizeCompareResponse } from '../normalizers/ProductCompare.query';
|
|
9
|
+
import { normalizeStoresResponse } from '../normalizers/StoreInPickUp.query';
|
|
10
|
+
import { normalizeCmsPage } from '../normalizers/CmsPage.type';
|
|
11
|
+
import { normalizeUrlRewrite } from '../normalizers/UrlRewrites.query';
|
|
12
|
+
import { normalizeWishlistResponse } from '../normalizers/Wishlist.query';
|
|
5
13
|
import { normalizeCart } from '../normalizers/Cart.type';
|
|
6
14
|
import { normalizeOrder } from '../normalizers/Order.type';
|
|
7
15
|
import { normalizeReview } from '../normalizers/Review.type';
|
|
@@ -48,13 +56,99 @@ function createNormalizedClient(client: any) {
|
|
|
48
56
|
wrapped.listProducts = async (...args: any[]) => {
|
|
49
57
|
const res = await client.listProducts(...args);
|
|
50
58
|
try {
|
|
51
|
-
|
|
59
|
+
// prefer the type-level normalizer but also accept query-level responses
|
|
60
|
+
return normalizeProductsQueryOutput(res) || normalizeProductsResponse(res);
|
|
52
61
|
} catch (e) {
|
|
53
62
|
return res;
|
|
54
63
|
}
|
|
55
64
|
};
|
|
56
65
|
}
|
|
57
66
|
|
|
67
|
+
// Menu endpoints
|
|
68
|
+
const menuMethods = ['getMenu', 'getMenus', 'listMenus', 'listMenu', 'getMenuItems', 'listMenuItems'];
|
|
69
|
+
for (const m of menuMethods) {
|
|
70
|
+
if (typeof client[m] === 'function') {
|
|
71
|
+
wrapped[m] = async (...args: any[]) => {
|
|
72
|
+
const res = await client[m](...args);
|
|
73
|
+
try {
|
|
74
|
+
return normalizeMenuResponse(res);
|
|
75
|
+
} catch (e) {
|
|
76
|
+
return res;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Category endpoints
|
|
83
|
+
const categoryMethods = ['getCategory', 'getCategoryBySlug', 'getCategories', 'listCategories', 'getCategoryTree'];
|
|
84
|
+
for (const m of categoryMethods) {
|
|
85
|
+
if (typeof client[m] === 'function') {
|
|
86
|
+
wrapped[m] = async (...args: any[]) => {
|
|
87
|
+
const res = await client[m](...args);
|
|
88
|
+
try {
|
|
89
|
+
return normalizeCategoryResponse(res);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
return res;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// CMS / pages
|
|
98
|
+
const cmsMethods = ['getPage', 'getCmsPage', 'getPageBySlug', 'listPages', 'getPages'];
|
|
99
|
+
for (const m of cmsMethods) {
|
|
100
|
+
if (typeof client[m] === 'function') {
|
|
101
|
+
wrapped[m] = async (...args: any[]) => {
|
|
102
|
+
const res = await client[m](...args);
|
|
103
|
+
try { return normalizeCmsPage(res); } catch (e) { return res; }
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// URL rewrites / resolver
|
|
109
|
+
const urlMethods = ['resolveUrl', 'getUrlRewrite', 'urlResolver', 'findUrl'];
|
|
110
|
+
for (const m of urlMethods) {
|
|
111
|
+
if (typeof client[m] === 'function') {
|
|
112
|
+
wrapped[m] = async (...args: any[]) => {
|
|
113
|
+
const res = await client[m](...args);
|
|
114
|
+
try { return normalizeUrlRewrite(res); } catch (e) { return res; }
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Wishlist
|
|
120
|
+
const wishlistMethods = ['getWishlist', 'listWishlist', 'getWishlistById', 'getWishlistItems'];
|
|
121
|
+
for (const m of wishlistMethods) {
|
|
122
|
+
if (typeof client[m] === 'function') {
|
|
123
|
+
wrapped[m] = async (...args: any[]) => {
|
|
124
|
+
const res = await client[m](...args);
|
|
125
|
+
try { return normalizeWishlistResponse(res); } catch (e) { return res; }
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Compare / product compare
|
|
131
|
+
const compareMethods = ['getCompare', 'listCompare', 'compareProducts', 'getCompareList'];
|
|
132
|
+
for (const m of compareMethods) {
|
|
133
|
+
if (typeof client[m] === 'function') {
|
|
134
|
+
wrapped[m] = async (...args: any[]) => {
|
|
135
|
+
const res = await client[m](...args);
|
|
136
|
+
try { return normalizeCompareResponse(res); } catch (e) { return res; }
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Stores / pickup
|
|
142
|
+
const storeMethods = ['listStores', 'getStores', 'getStore', 'listPickUpStores', 'getStoresInPickUp'];
|
|
143
|
+
for (const m of storeMethods) {
|
|
144
|
+
if (typeof client[m] === 'function') {
|
|
145
|
+
wrapped[m] = async (...args: any[]) => {
|
|
146
|
+
const res = await client[m](...args);
|
|
147
|
+
try { return normalizeStoresResponse(res); } catch (e) { return res; }
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
58
152
|
if (typeof client.getProductById === 'function') {
|
|
59
153
|
wrapped.getProductById = async (...args: any[]) => {
|
|
60
154
|
const res = await client.getProductById(...args);
|
package/package.json
CHANGED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// Minimal Product reducer compatibility layer. Responds to `PRODUCT_LOADED`.
|
|
2
|
-
export default function ProductReducer(state = { product: null }, action: any) {
|
|
3
|
-
if (!action) return state
|
|
4
|
-
try {
|
|
5
|
-
if (action.type === 'PRODUCT_LOADED') {
|
|
6
|
-
return { ...state, product: action.payload }
|
|
7
|
-
}
|
|
8
|
-
} catch (e) {
|
|
9
|
-
// ignore and return current state
|
|
10
|
-
}
|
|
11
|
-
return state
|
|
12
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Minimal ProductList reducer compatibility layer. Accepts an action with
|
|
2
|
-
// `type: 'PRODUCT_LIST_LOADED'` and `payload` to populate `items`.
|
|
3
|
-
export default function ProductListReducer(state = { items: [] }, action: any) {
|
|
4
|
-
if (!action) return state
|
|
5
|
-
try {
|
|
6
|
-
if (action.type === 'PRODUCT_LIST_LOADED') {
|
|
7
|
-
return { ...state, items: Array.isArray(action.payload) ? action.payload : state.items }
|
|
8
|
-
}
|
|
9
|
-
} catch (e) {
|
|
10
|
-
// ignore and return current state
|
|
11
|
-
}
|
|
12
|
-
return state
|
|
13
|
-
}
|