@01.software/sdk 0.10.0 → 0.11.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/README.md +1 -1
- package/dist/{const-Dmgge6oQ.d.ts → const-CWbOFesW.d.ts} +2 -2
- package/dist/{const-k0fqIBda.d.cts → const-DBZBjsZH.d.cts} +2 -2
- package/dist/index.cjs +362 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +165 -7
- package/dist/index.d.ts +165 -7
- package/dist/index.js +367 -2
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-D0zFPijW.d.cts → payload-types-BX9al1wy.d.cts} +45 -88
- package/dist/{payload-types-D0zFPijW.d.ts → payload-types-BX9al1wy.d.ts} +45 -88
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/realtime.js.map +1 -1
- package/dist/ui/canvas/server.cjs.map +1 -1
- package/dist/ui/canvas/server.js.map +1 -1
- package/dist/ui/canvas.cjs.map +1 -1
- package/dist/ui/canvas.js.map +1 -1
- package/dist/ui/form.d.cts +1 -1
- package/dist/ui/form.d.ts +1 -1
- package/dist/ui/video.d.cts +1 -1
- package/dist/ui/video.d.ts +1 -1
- package/dist/{webhook-DXr8B9E6.d.cts → webhook-Bqek9sBP.d.cts} +2 -2
- package/dist/{webhook-caDRhnd7.d.ts → webhook-I-iZO5-K.d.ts} +2 -2
- package/dist/webhook.d.cts +3 -3
- package/dist/webhook.d.ts +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -429,7 +429,7 @@ const handler = createTypedWebhookHandler('orders', async (event) => {
|
|
|
429
429
|
| Carts | `carts`, `cart-items` |
|
|
430
430
|
| Commerce | `discounts`, `shipping-policies` |
|
|
431
431
|
| Content | `posts`, `post-authors`, `post-categories`, `post-tags`, `documents`, `document-categories`, `document-types` |
|
|
432
|
-
| Playlists | `playlists`, `playlist-categories`, `playlist-tags`, `tracks`, `
|
|
432
|
+
| Playlists | `playlists`, `playlist-categories`, `playlist-tags`, `tracks`, `track-categories`, `track-tags` |
|
|
433
433
|
| Galleries | `galleries`, `gallery-items`, `gallery-categories`, `gallery-tags` |
|
|
434
434
|
| Canvas | `canvases`, `canvas-node-types`, `canvas-edge-types`, `canvas-categories`, `canvas-tags` |
|
|
435
435
|
| Videos | `videos`, `video-categories`, `video-tags` |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as Config } from './payload-types-
|
|
1
|
+
import { C as Config } from './payload-types-BX9al1wy.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Collection type derived from Payload Config.
|
|
@@ -9,7 +9,7 @@ type Collection = keyof Config['collections'];
|
|
|
9
9
|
* Array of all public collection names for runtime use (e.g., Zod enum validation).
|
|
10
10
|
* This is the single source of truth for which collections are publicly accessible via SDK.
|
|
11
11
|
*/
|
|
12
|
-
declare const COLLECTIONS: readonly ["tenants", "tenant-metadata", "tenant-logos", "products", "product-variants", "product-options", "product-option-values", "product-categories", "product-tags", "product-collections", "brands", "brand-logos", "orders", "order-items", "returns", "return-items", "fulfillments", "fulfillment-items", "transactions", "customers", "customer-addresses", "customer-groups", "carts", "cart-items", "discounts", "shipping-policies", "documents", "document-categories", "document-types", "posts", "post-authors", "post-categories", "post-tags", "playlists", "playlist-categories", "playlist-tags", "tracks", "
|
|
12
|
+
declare const COLLECTIONS: readonly ["tenants", "tenant-metadata", "tenant-logos", "products", "product-variants", "product-options", "product-option-values", "product-categories", "product-tags", "product-collections", "brands", "brand-logos", "orders", "order-items", "returns", "return-items", "fulfillments", "fulfillment-items", "transactions", "customers", "customer-addresses", "customer-groups", "carts", "cart-items", "discounts", "shipping-policies", "documents", "document-categories", "document-types", "posts", "post-authors", "post-categories", "post-tags", "playlists", "playlist-categories", "playlist-tags", "tracks", "track-categories", "track-tags", "galleries", "gallery-categories", "gallery-tags", "gallery-items", "links", "link-categories", "link-tags", "canvases", "canvas-node-types", "canvas-edge-types", "canvas-categories", "canvas-tags", "videos", "video-categories", "video-tags", "live-streams", "images", "forms", "form-submissions", "threads", "comments", "reactions", "reaction-types", "bookmarks", "thread-categories", "reports", "community-bans"];
|
|
13
13
|
/**
|
|
14
14
|
* Public collections available for SDK access.
|
|
15
15
|
* Derived from the COLLECTIONS array (single source of truth).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as Config } from './payload-types-
|
|
1
|
+
import { C as Config } from './payload-types-BX9al1wy.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Collection type derived from Payload Config.
|
|
@@ -9,7 +9,7 @@ type Collection = keyof Config['collections'];
|
|
|
9
9
|
* Array of all public collection names for runtime use (e.g., Zod enum validation).
|
|
10
10
|
* This is the single source of truth for which collections are publicly accessible via SDK.
|
|
11
11
|
*/
|
|
12
|
-
declare const COLLECTIONS: readonly ["tenants", "tenant-metadata", "tenant-logos", "products", "product-variants", "product-options", "product-option-values", "product-categories", "product-tags", "product-collections", "brands", "brand-logos", "orders", "order-items", "returns", "return-items", "fulfillments", "fulfillment-items", "transactions", "customers", "customer-addresses", "customer-groups", "carts", "cart-items", "discounts", "shipping-policies", "documents", "document-categories", "document-types", "posts", "post-authors", "post-categories", "post-tags", "playlists", "playlist-categories", "playlist-tags", "tracks", "
|
|
12
|
+
declare const COLLECTIONS: readonly ["tenants", "tenant-metadata", "tenant-logos", "products", "product-variants", "product-options", "product-option-values", "product-categories", "product-tags", "product-collections", "brands", "brand-logos", "orders", "order-items", "returns", "return-items", "fulfillments", "fulfillment-items", "transactions", "customers", "customer-addresses", "customer-groups", "carts", "cart-items", "discounts", "shipping-policies", "documents", "document-categories", "document-types", "posts", "post-authors", "post-categories", "post-tags", "playlists", "playlist-categories", "playlist-tags", "tracks", "track-categories", "track-tags", "galleries", "gallery-categories", "gallery-tags", "gallery-items", "links", "link-categories", "link-tags", "canvases", "canvas-node-types", "canvas-edge-types", "canvas-categories", "canvas-tags", "videos", "video-categories", "video-tags", "live-streams", "images", "forms", "form-submissions", "threads", "comments", "reactions", "reaction-types", "bookmarks", "thread-categories", "reports", "community-bans"];
|
|
13
13
|
/**
|
|
14
14
|
* Public collections available for SDK access.
|
|
15
15
|
* Derived from the COLLECTIONS array (single source of truth).
|
package/dist/index.cjs
CHANGED
|
@@ -45,6 +45,9 @@ __export(src_exports, {
|
|
|
45
45
|
TimeoutError: () => TimeoutError,
|
|
46
46
|
UsageLimitError: () => UsageLimitError,
|
|
47
47
|
ValidationError: () => ValidationError,
|
|
48
|
+
buildProductListingGroupsByOption: () => buildProductListingGroupsByOption,
|
|
49
|
+
buildProductListingProjection: () => buildProductListingProjection,
|
|
50
|
+
buildProductOptionMatrix: () => buildProductOptionMatrix,
|
|
48
51
|
collectionKeys: () => collectionKeys,
|
|
49
52
|
createClient: () => createClient,
|
|
50
53
|
createServerClient: () => createServerClient,
|
|
@@ -52,12 +55,14 @@ __export(src_exports, {
|
|
|
52
55
|
customerKeys: () => customerKeys,
|
|
53
56
|
formatOrderName: () => formatOrderName,
|
|
54
57
|
generateOrderNumber: () => generateOrderNumber,
|
|
58
|
+
getAvailableOptionValues: () => getAvailableOptionValues,
|
|
55
59
|
getImageLqip: () => getImageLqip,
|
|
56
60
|
getImagePalette: () => getImagePalette,
|
|
57
61
|
getImagePlaceholderStyle: () => getImagePlaceholderStyle,
|
|
58
62
|
getImageSrcSet: () => getImageSrcSet,
|
|
59
63
|
getImageUrl: () => getImageUrl,
|
|
60
64
|
getQueryClient: () => getQueryClient,
|
|
65
|
+
getSelectedValueByOptionId: () => getSelectedValueByOptionId,
|
|
61
66
|
getVideoGif: () => getVideoGif,
|
|
62
67
|
getVideoMp4Url: () => getVideoMp4Url,
|
|
63
68
|
getVideoStoryboard: () => getVideoStoryboard,
|
|
@@ -74,7 +79,10 @@ __export(src_exports, {
|
|
|
74
79
|
isUsageLimitError: () => isUsageLimitError,
|
|
75
80
|
isValidWebhookEvent: () => isValidWebhookEvent,
|
|
76
81
|
isValidationError: () => isValidationError,
|
|
77
|
-
|
|
82
|
+
normalizeSelectedValueIds: () => normalizeSelectedValueIds,
|
|
83
|
+
productKeys: () => productKeys,
|
|
84
|
+
resolveRelation: () => resolveRelation,
|
|
85
|
+
resolveVariantForSelection: () => resolveVariantForSelection
|
|
78
86
|
});
|
|
79
87
|
module.exports = __toCommonJS(src_exports);
|
|
80
88
|
|
|
@@ -644,6 +652,12 @@ var ProductApi = class extends BaseApi {
|
|
|
644
652
|
stockCheck(params) {
|
|
645
653
|
return this.request("/api/products/stock-check", params);
|
|
646
654
|
}
|
|
655
|
+
listingGroups(params) {
|
|
656
|
+
return this.request(
|
|
657
|
+
"/api/products/listing-groups",
|
|
658
|
+
params
|
|
659
|
+
);
|
|
660
|
+
}
|
|
647
661
|
};
|
|
648
662
|
|
|
649
663
|
// src/utils/types.ts
|
|
@@ -988,6 +1002,18 @@ var CollectionClient = class extends HttpClient {
|
|
|
988
1002
|
});
|
|
989
1003
|
return this.parseFindResponse(response);
|
|
990
1004
|
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Find-like response from a custom endpoint
|
|
1007
|
+
* POST /api/...custom-endpoint
|
|
1008
|
+
*/
|
|
1009
|
+
async requestFindEndpoint(endpoint, data) {
|
|
1010
|
+
const response = await httpFetch(endpoint, {
|
|
1011
|
+
...this.defaultOptions,
|
|
1012
|
+
method: "POST",
|
|
1013
|
+
body: data ? JSON.stringify(data) : void 0
|
|
1014
|
+
});
|
|
1015
|
+
return this.parseFindResponse(response);
|
|
1016
|
+
}
|
|
991
1017
|
/**
|
|
992
1018
|
* Find document by ID
|
|
993
1019
|
* GET /api/{collection}/{id}
|
|
@@ -1136,7 +1162,6 @@ var COLLECTIONS = [
|
|
|
1136
1162
|
"playlist-categories",
|
|
1137
1163
|
"playlist-tags",
|
|
1138
1164
|
"tracks",
|
|
1139
|
-
"playlist-tracks",
|
|
1140
1165
|
"track-categories",
|
|
1141
1166
|
"track-tags",
|
|
1142
1167
|
"galleries",
|
|
@@ -1631,6 +1656,9 @@ function getQueryClient() {
|
|
|
1631
1656
|
return browserQueryClient;
|
|
1632
1657
|
}
|
|
1633
1658
|
|
|
1659
|
+
// src/core/query/query-hooks.ts
|
|
1660
|
+
var import_react_query4 = require("@tanstack/react-query");
|
|
1661
|
+
|
|
1634
1662
|
// src/core/query/collection-hooks.ts
|
|
1635
1663
|
var import_react_query2 = require("@tanstack/react-query");
|
|
1636
1664
|
|
|
@@ -1650,6 +1678,10 @@ var customerKeys = {
|
|
|
1650
1678
|
all: ["customer"],
|
|
1651
1679
|
me: () => ["customer", "me"]
|
|
1652
1680
|
};
|
|
1681
|
+
var productKeys = {
|
|
1682
|
+
listingGroups: (options) => ["products", "listing-groups", "list", options],
|
|
1683
|
+
listingGroupsInfinite: (options) => ["products", "listing-groups", "infinite", options]
|
|
1684
|
+
};
|
|
1653
1685
|
|
|
1654
1686
|
// src/core/query/collection-hooks.ts
|
|
1655
1687
|
var DEFAULT_PAGE_SIZE = 20;
|
|
@@ -2024,6 +2056,98 @@ var QueryHooks = class extends CollectionHooks {
|
|
|
2024
2056
|
this.setCustomerData = (data) => this._customer.setCustomerData(data);
|
|
2025
2057
|
this._customer = new CustomerHooks(queryClient, customerAuth);
|
|
2026
2058
|
}
|
|
2059
|
+
useProductListingGroupsQuery(params, options) {
|
|
2060
|
+
const queryOptions = params.options;
|
|
2061
|
+
const { placeholderData, ...restOptions } = options ?? {};
|
|
2062
|
+
return (0, import_react_query4.useQuery)({
|
|
2063
|
+
queryKey: productKeys.listingGroups(queryOptions),
|
|
2064
|
+
queryFn: async () => this.collectionClient.requestFindEndpoint(
|
|
2065
|
+
"/api/products/listing-groups/query",
|
|
2066
|
+
{ options: queryOptions }
|
|
2067
|
+
),
|
|
2068
|
+
...restOptions,
|
|
2069
|
+
...placeholderData !== void 0 && {
|
|
2070
|
+
placeholderData
|
|
2071
|
+
}
|
|
2072
|
+
});
|
|
2073
|
+
}
|
|
2074
|
+
useSuspenseProductListingGroupsQuery(params, options) {
|
|
2075
|
+
const queryOptions = params.options;
|
|
2076
|
+
return (0, import_react_query4.useSuspenseQuery)({
|
|
2077
|
+
queryKey: productKeys.listingGroups(queryOptions),
|
|
2078
|
+
queryFn: async () => this.collectionClient.requestFindEndpoint(
|
|
2079
|
+
"/api/products/listing-groups/query",
|
|
2080
|
+
{ options: queryOptions }
|
|
2081
|
+
),
|
|
2082
|
+
...options
|
|
2083
|
+
});
|
|
2084
|
+
}
|
|
2085
|
+
useInfiniteProductListingGroupsQuery(params, options) {
|
|
2086
|
+
const {
|
|
2087
|
+
options: queryOptions,
|
|
2088
|
+
pageSize = 20
|
|
2089
|
+
} = params;
|
|
2090
|
+
return (0, import_react_query4.useInfiniteQuery)({
|
|
2091
|
+
queryKey: productKeys.listingGroupsInfinite(queryOptions),
|
|
2092
|
+
queryFn: async ({ pageParam }) => this.collectionClient.requestFindEndpoint(
|
|
2093
|
+
"/api/products/listing-groups/query",
|
|
2094
|
+
{
|
|
2095
|
+
options: { ...queryOptions, page: pageParam, limit: pageSize }
|
|
2096
|
+
}
|
|
2097
|
+
),
|
|
2098
|
+
initialPageParam: 1,
|
|
2099
|
+
getNextPageParam: (lastPage) => lastPage.hasNextPage ? lastPage.nextPage : void 0,
|
|
2100
|
+
...options
|
|
2101
|
+
});
|
|
2102
|
+
}
|
|
2103
|
+
useSuspenseInfiniteProductListingGroupsQuery(params, options) {
|
|
2104
|
+
const {
|
|
2105
|
+
options: queryOptions,
|
|
2106
|
+
pageSize = 20
|
|
2107
|
+
} = params;
|
|
2108
|
+
return (0, import_react_query4.useSuspenseInfiniteQuery)({
|
|
2109
|
+
queryKey: productKeys.listingGroupsInfinite(queryOptions),
|
|
2110
|
+
queryFn: async ({ pageParam }) => this.collectionClient.requestFindEndpoint(
|
|
2111
|
+
"/api/products/listing-groups/query",
|
|
2112
|
+
{
|
|
2113
|
+
options: { ...queryOptions, page: pageParam, limit: pageSize }
|
|
2114
|
+
}
|
|
2115
|
+
),
|
|
2116
|
+
initialPageParam: 1,
|
|
2117
|
+
getNextPageParam: (lastPage) => lastPage.hasNextPage ? lastPage.nextPage : void 0,
|
|
2118
|
+
...options
|
|
2119
|
+
});
|
|
2120
|
+
}
|
|
2121
|
+
async prefetchProductListingGroupsQuery(params, options) {
|
|
2122
|
+
const queryOptions = params.options;
|
|
2123
|
+
return this.queryClient.prefetchQuery({
|
|
2124
|
+
queryKey: productKeys.listingGroups(queryOptions),
|
|
2125
|
+
queryFn: async () => this.collectionClient.requestFindEndpoint(
|
|
2126
|
+
"/api/products/listing-groups/query",
|
|
2127
|
+
{ options: queryOptions }
|
|
2128
|
+
),
|
|
2129
|
+
...options
|
|
2130
|
+
});
|
|
2131
|
+
}
|
|
2132
|
+
async prefetchInfiniteProductListingGroupsQuery(params, options) {
|
|
2133
|
+
const {
|
|
2134
|
+
options: queryOptions,
|
|
2135
|
+
pageSize = 20
|
|
2136
|
+
} = params;
|
|
2137
|
+
return this.queryClient.prefetchInfiniteQuery({
|
|
2138
|
+
queryKey: productKeys.listingGroupsInfinite(queryOptions),
|
|
2139
|
+
queryFn: async ({ pageParam }) => this.collectionClient.requestFindEndpoint(
|
|
2140
|
+
"/api/products/listing-groups/query",
|
|
2141
|
+
{
|
|
2142
|
+
options: { ...queryOptions, page: pageParam, limit: pageSize }
|
|
2143
|
+
}
|
|
2144
|
+
),
|
|
2145
|
+
initialPageParam: 1,
|
|
2146
|
+
getNextPageParam: (lastPage) => lastPage.hasNextPage ? lastPage.nextPage : void 0,
|
|
2147
|
+
pages: options?.pages ?? 1,
|
|
2148
|
+
staleTime: options?.staleTime
|
|
2149
|
+
});
|
|
2150
|
+
}
|
|
2027
2151
|
};
|
|
2028
2152
|
|
|
2029
2153
|
// src/core/client/client.ts
|
|
@@ -2364,6 +2488,242 @@ function createTypedWebhookHandler(collection, handler) {
|
|
|
2364
2488
|
};
|
|
2365
2489
|
}
|
|
2366
2490
|
|
|
2491
|
+
// src/utils/ecommerce.ts
|
|
2492
|
+
function getRelationID(value) {
|
|
2493
|
+
if (typeof value === "string") return value;
|
|
2494
|
+
if (typeof value === "number") return String(value);
|
|
2495
|
+
if (value && typeof value === "object" && "id" in value) {
|
|
2496
|
+
const id = value.id;
|
|
2497
|
+
if (typeof id === "string") return id;
|
|
2498
|
+
if (typeof id === "number") return String(id);
|
|
2499
|
+
}
|
|
2500
|
+
return void 0;
|
|
2501
|
+
}
|
|
2502
|
+
function compareOrder(left, right) {
|
|
2503
|
+
return (left ?? "").localeCompare(right ?? "");
|
|
2504
|
+
}
|
|
2505
|
+
function isProductOptionValueDoc(value) {
|
|
2506
|
+
return typeof value === "object" && value !== null && "id" in value && ("value" in value || "slug" in value);
|
|
2507
|
+
}
|
|
2508
|
+
function extractEntityId(value) {
|
|
2509
|
+
if (typeof value === "string") return value;
|
|
2510
|
+
if (typeof value === "number") return String(value);
|
|
2511
|
+
if (value && typeof value === "object" && "id" in value) {
|
|
2512
|
+
if (typeof value.id === "string") return value.id;
|
|
2513
|
+
if (typeof value.id === "number") return String(value.id);
|
|
2514
|
+
}
|
|
2515
|
+
return null;
|
|
2516
|
+
}
|
|
2517
|
+
function getFirstMediaId(values) {
|
|
2518
|
+
if (!Array.isArray(values)) return null;
|
|
2519
|
+
for (const value of values) {
|
|
2520
|
+
const id = extractEntityId(value);
|
|
2521
|
+
if (id != null) return id;
|
|
2522
|
+
}
|
|
2523
|
+
return null;
|
|
2524
|
+
}
|
|
2525
|
+
function getVariantPrimaryImage(variant) {
|
|
2526
|
+
if (!variant) return null;
|
|
2527
|
+
return extractEntityId(variant.thumbnail) ?? getFirstMediaId(variant.images);
|
|
2528
|
+
}
|
|
2529
|
+
function normalizeOptionValue(value, fallbackOptionId) {
|
|
2530
|
+
return {
|
|
2531
|
+
id: String(value.id),
|
|
2532
|
+
optionId: getRelationID(value.option) ?? fallbackOptionId,
|
|
2533
|
+
label: value.value || value.slug || String(value.id),
|
|
2534
|
+
slug: value.slug ?? null,
|
|
2535
|
+
order: value._order ?? value["_product-option-values_values_order"] ?? ""
|
|
2536
|
+
};
|
|
2537
|
+
}
|
|
2538
|
+
function normalizeVariantOptionValues(variant, valueToOptionId, optionIds) {
|
|
2539
|
+
const optionValueByOptionId = /* @__PURE__ */ new Map();
|
|
2540
|
+
for (const rawValue of Array.isArray(variant.optionValues) ? variant.optionValues : []) {
|
|
2541
|
+
const valueId = getRelationID(rawValue);
|
|
2542
|
+
if (!valueId) continue;
|
|
2543
|
+
const optionId = valueToOptionId.get(valueId) ?? (isProductOptionValueDoc(rawValue) ? getRelationID(rawValue.option) : void 0);
|
|
2544
|
+
if (!optionId || optionValueByOptionId.has(optionId)) continue;
|
|
2545
|
+
optionValueByOptionId.set(optionId, valueId);
|
|
2546
|
+
}
|
|
2547
|
+
const optionValueIds = optionIds.map((optionId) => optionValueByOptionId.get(optionId)).filter((valueId) => Boolean(valueId));
|
|
2548
|
+
return {
|
|
2549
|
+
id: String(variant.id),
|
|
2550
|
+
optionValueIds,
|
|
2551
|
+
optionValueByOptionId,
|
|
2552
|
+
source: variant
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2555
|
+
function buildProductOptionMatrix({
|
|
2556
|
+
options,
|
|
2557
|
+
variants = []
|
|
2558
|
+
}) {
|
|
2559
|
+
const normalizedOptions = options.map((option) => {
|
|
2560
|
+
const valuesById = /* @__PURE__ */ new Map();
|
|
2561
|
+
for (const rawValue of option.values?.docs ?? []) {
|
|
2562
|
+
if (!isProductOptionValueDoc(rawValue)) continue;
|
|
2563
|
+
const normalizedValue = normalizeOptionValue(rawValue, String(option.id));
|
|
2564
|
+
valuesById.set(normalizedValue.id, normalizedValue);
|
|
2565
|
+
}
|
|
2566
|
+
return {
|
|
2567
|
+
id: String(option.id),
|
|
2568
|
+
title: option.title ?? String(option.id),
|
|
2569
|
+
order: option._order ?? option["_product-options_options_order"] ?? "",
|
|
2570
|
+
values: Array.from(valuesById.values()).sort(
|
|
2571
|
+
(left, right) => compareOrder(left.order, right.order)
|
|
2572
|
+
)
|
|
2573
|
+
};
|
|
2574
|
+
}).sort((left, right) => compareOrder(left.order, right.order));
|
|
2575
|
+
const optionById = new Map(normalizedOptions.map((option) => [option.id, option]));
|
|
2576
|
+
const valueById = /* @__PURE__ */ new Map();
|
|
2577
|
+
const valueToOptionId = /* @__PURE__ */ new Map();
|
|
2578
|
+
for (const option of normalizedOptions) {
|
|
2579
|
+
for (const value of option.values) {
|
|
2580
|
+
valueById.set(value.id, value);
|
|
2581
|
+
valueToOptionId.set(value.id, option.id);
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
const optionIds = normalizedOptions.map((option) => option.id);
|
|
2585
|
+
const normalizedVariants = variants.map(
|
|
2586
|
+
(variant) => normalizeVariantOptionValues(variant, valueToOptionId, optionIds)
|
|
2587
|
+
);
|
|
2588
|
+
return {
|
|
2589
|
+
options: normalizedOptions,
|
|
2590
|
+
optionIds,
|
|
2591
|
+
optionById,
|
|
2592
|
+
valueById,
|
|
2593
|
+
valueToOptionId,
|
|
2594
|
+
variants: normalizedVariants
|
|
2595
|
+
};
|
|
2596
|
+
}
|
|
2597
|
+
function getSelectedValueByOptionId(matrix, selectedValueIds) {
|
|
2598
|
+
const selectedByOption = /* @__PURE__ */ new Map();
|
|
2599
|
+
for (const rawValue of selectedValueIds) {
|
|
2600
|
+
const valueId = getRelationID(rawValue);
|
|
2601
|
+
if (!valueId) continue;
|
|
2602
|
+
const optionId = matrix.valueToOptionId.get(valueId);
|
|
2603
|
+
if (!optionId || selectedByOption.has(optionId)) continue;
|
|
2604
|
+
selectedByOption.set(optionId, valueId);
|
|
2605
|
+
}
|
|
2606
|
+
return selectedByOption;
|
|
2607
|
+
}
|
|
2608
|
+
function normalizeSelectedValueIds(matrix, selectedValueIds) {
|
|
2609
|
+
const selectedByOption = getSelectedValueByOptionId(matrix, selectedValueIds);
|
|
2610
|
+
return matrix.optionIds.map((optionId) => selectedByOption.get(optionId)).filter((valueId) => Boolean(valueId));
|
|
2611
|
+
}
|
|
2612
|
+
function getAvailableOptionValues(matrix, optionId, selectedValueIds) {
|
|
2613
|
+
const option = matrix.optionById.get(optionId);
|
|
2614
|
+
if (!option) return [];
|
|
2615
|
+
if (matrix.variants.length === 0) {
|
|
2616
|
+
return option.values;
|
|
2617
|
+
}
|
|
2618
|
+
const selectedByOption = getSelectedValueByOptionId(matrix, selectedValueIds);
|
|
2619
|
+
selectedByOption.delete(optionId);
|
|
2620
|
+
const matchingVariants = matrix.variants.filter(
|
|
2621
|
+
(variant) => Array.from(selectedByOption.entries()).every(
|
|
2622
|
+
([selectedOptionId, selectedValueId]) => variant.optionValueByOptionId.get(selectedOptionId) === selectedValueId
|
|
2623
|
+
)
|
|
2624
|
+
);
|
|
2625
|
+
const availableValueIds = new Set(
|
|
2626
|
+
matchingVariants.map((variant) => variant.optionValueByOptionId.get(optionId)).filter((valueId) => Boolean(valueId))
|
|
2627
|
+
);
|
|
2628
|
+
return option.values.filter((value) => availableValueIds.has(value.id));
|
|
2629
|
+
}
|
|
2630
|
+
function resolveVariantForSelection(matrix, selectedValueIds) {
|
|
2631
|
+
const selectedByOption = getSelectedValueByOptionId(matrix, selectedValueIds);
|
|
2632
|
+
if (selectedByOption.size !== matrix.optionIds.length) {
|
|
2633
|
+
return void 0;
|
|
2634
|
+
}
|
|
2635
|
+
return matrix.variants.find(
|
|
2636
|
+
(variant) => matrix.optionIds.every(
|
|
2637
|
+
(optionId) => variant.optionValueByOptionId.get(optionId) === selectedByOption.get(optionId)
|
|
2638
|
+
)
|
|
2639
|
+
);
|
|
2640
|
+
}
|
|
2641
|
+
function compareVariantOrder(a, b) {
|
|
2642
|
+
const aOrder = Number(a._order ?? Number.MAX_SAFE_INTEGER);
|
|
2643
|
+
const bOrder = Number(b._order ?? Number.MAX_SAFE_INTEGER);
|
|
2644
|
+
if (Number.isFinite(aOrder) && Number.isFinite(bOrder) && aOrder !== bOrder) {
|
|
2645
|
+
return aOrder - bOrder;
|
|
2646
|
+
}
|
|
2647
|
+
const aId = String(getRelationID(a.id) ?? "");
|
|
2648
|
+
const bId = String(getRelationID(b.id) ?? "");
|
|
2649
|
+
return aId.localeCompare(bId);
|
|
2650
|
+
}
|
|
2651
|
+
function isVariantAvailableForSale(variant) {
|
|
2652
|
+
if (variant.isActive === false) return false;
|
|
2653
|
+
if (variant.isUnlimited) return true;
|
|
2654
|
+
return (variant.stock ?? 0) > 0;
|
|
2655
|
+
}
|
|
2656
|
+
function getMinMax(values) {
|
|
2657
|
+
const numbers = values.filter((value) => typeof value === "number");
|
|
2658
|
+
if (numbers.length === 0) {
|
|
2659
|
+
return { min: null, max: null };
|
|
2660
|
+
}
|
|
2661
|
+
return {
|
|
2662
|
+
min: Math.min(...numbers),
|
|
2663
|
+
max: Math.max(...numbers)
|
|
2664
|
+
};
|
|
2665
|
+
}
|
|
2666
|
+
function buildProductListingProjection(product, variants) {
|
|
2667
|
+
const orderedVariants = [...variants].sort(compareVariantOrder);
|
|
2668
|
+
const activeVariants = orderedVariants.filter((variant) => variant.isActive !== false);
|
|
2669
|
+
const availableVariants = activeVariants.filter(isVariantAvailableForSale);
|
|
2670
|
+
const selectionHintVariant = availableVariants[0] ?? activeVariants[0] ?? null;
|
|
2671
|
+
const { min: minPrice, max: maxPrice } = getMinMax(
|
|
2672
|
+
activeVariants.map((variant) => variant.price)
|
|
2673
|
+
);
|
|
2674
|
+
const { min: minCompareAtPrice, max: maxCompareAtPrice } = getMinMax(
|
|
2675
|
+
activeVariants.map((variant) => variant.compareAtPrice)
|
|
2676
|
+
);
|
|
2677
|
+
const productPrimaryImage = extractEntityId(product?.thumbnail) ?? getFirstMediaId(product?.images);
|
|
2678
|
+
const variantPrimaryImage = getVariantPrimaryImage(selectionHintVariant) ?? getVariantPrimaryImage(activeVariants[0]) ?? getVariantPrimaryImage(orderedVariants[0]);
|
|
2679
|
+
return {
|
|
2680
|
+
selectionHintVariant: getRelationID(selectionHintVariant?.id) ?? null,
|
|
2681
|
+
primaryImage: productPrimaryImage ?? variantPrimaryImage,
|
|
2682
|
+
minPrice,
|
|
2683
|
+
maxPrice,
|
|
2684
|
+
minCompareAtPrice,
|
|
2685
|
+
maxCompareAtPrice,
|
|
2686
|
+
isPriceRange: minPrice !== null && maxPrice !== null ? minPrice !== maxPrice : false,
|
|
2687
|
+
availableForSale: availableVariants.length > 0
|
|
2688
|
+
};
|
|
2689
|
+
}
|
|
2690
|
+
function buildProductListingGroupsByOption(args) {
|
|
2691
|
+
const primaryOptionId = args.primaryOptionId ?? void 0;
|
|
2692
|
+
if (!primaryOptionId) return [];
|
|
2693
|
+
const matrix = buildProductOptionMatrix({
|
|
2694
|
+
options: args.options,
|
|
2695
|
+
variants: args.variants
|
|
2696
|
+
});
|
|
2697
|
+
const primaryOption = matrix.optionById.get(primaryOptionId);
|
|
2698
|
+
if (!primaryOption) return [];
|
|
2699
|
+
return primaryOption.values.flatMap((value) => {
|
|
2700
|
+
const variants = matrix.variants.filter(
|
|
2701
|
+
(variant) => variant.optionValueByOptionId.get(primaryOption.id) === value.id
|
|
2702
|
+
).map((variant) => variant.source);
|
|
2703
|
+
if (variants.length === 0) {
|
|
2704
|
+
return [];
|
|
2705
|
+
}
|
|
2706
|
+
const listingBase = buildProductListingProjection(void 0, variants);
|
|
2707
|
+
const productFallbackImage = extractEntityId(args.product?.thumbnail) ?? getFirstMediaId(args.product?.images);
|
|
2708
|
+
return [
|
|
2709
|
+
{
|
|
2710
|
+
optionId: primaryOption.id,
|
|
2711
|
+
optionTitle: primaryOption.title,
|
|
2712
|
+
optionValueId: value.id,
|
|
2713
|
+
optionValueLabel: value.label,
|
|
2714
|
+
optionValueSlug: value.slug,
|
|
2715
|
+
variantIds: variants.map((variant) => String(variant.id)),
|
|
2716
|
+
variantCount: variants.length,
|
|
2717
|
+
variants,
|
|
2718
|
+
listing: {
|
|
2719
|
+
...listingBase,
|
|
2720
|
+
primaryImage: listingBase.primaryImage ?? productFallbackImage
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
];
|
|
2724
|
+
});
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2367
2727
|
// src/utils/image.ts
|
|
2368
2728
|
var IMAGE_SIZES = [384, 768, 1536];
|
|
2369
2729
|
function getImageUrl(image, displayWidth, dpr = 1) {
|