@01.software/sdk 0.39.0 → 0.40.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 +52 -20
- package/dist/client.cjs +43 -68
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +6 -6
- package/dist/client.d.ts +6 -6
- package/dist/client.js +43 -68
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-CaMgs5KE.d.ts → collection-client-CKFa99C6.d.ts} +3 -3
- package/dist/{collection-client-DVfB0Em1.d.cts → collection-client-VYwYi6u6.d.cts} +3 -3
- package/dist/const-4BUtUdGU.d.cts +32 -0
- package/dist/const-ymprfiPf.d.ts +32 -0
- package/dist/{index-BOLQxveo.d.cts → index-Dquv4xTL.d.cts} +3 -3
- package/dist/{index-CSwR2HSg.d.ts → index-w36lpSkU.d.ts} +3 -3
- package/dist/index.cjs +101 -131
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +101 -131
- package/dist/index.js.map +1 -1
- package/dist/{payload-types-m3jjhxk9.d.cts → payload-types-DC0xzR9i.d.cts} +470 -265
- package/dist/{payload-types-m3jjhxk9.d.ts → payload-types-DC0xzR9i.d.ts} +470 -265
- package/dist/query.d.cts +5 -5
- package/dist/query.d.ts +5 -5
- package/dist/realtime.d.cts +2 -2
- package/dist/realtime.d.ts +2 -2
- package/dist/server.cjs +36 -68
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +7 -7
- package/dist/server.d.ts +7 -7
- package/dist/server.js +36 -68
- package/dist/server.js.map +1 -1
- package/dist/{types-Cmrd1ezc.d.ts → types-Bh2p-EMc.d.ts} +5 -1
- package/dist/{types-D0ubzQw0.d.cts → types-BvpjooU-.d.cts} +5 -1
- package/dist/{types-CVf8sCZ-.d.ts → types-D5uHrPLr.d.cts} +99 -77
- package/dist/{types-BQo7UdI9.d.cts → types-Umd-YTjM.d.ts} +99 -77
- 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.d.cts +4 -4
- package/dist/webhook.d.ts +4 -4
- package/package.json +1 -1
- package/dist/const-6XHz_jej.d.ts +0 -32
- package/dist/const-B5KT72c7.d.cts +0 -32
package/README.md
CHANGED
|
@@ -126,7 +126,7 @@ const client = createClient({
|
|
|
126
126
|
// Query data (returns Payload native response)
|
|
127
127
|
const { docs } = await client.collections.from('products').find({
|
|
128
128
|
limit: 10,
|
|
129
|
-
|
|
129
|
+
select: { title: true, slug: true },
|
|
130
130
|
})
|
|
131
131
|
```
|
|
132
132
|
|
|
@@ -264,7 +264,8 @@ if (!result.found) {
|
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
const { product } = result
|
|
267
|
-
// product: { product, variants, options, brand, categories, tags, images, videos,
|
|
267
|
+
// product: { product, variants, options, brand, categories, tags, images, videos,
|
|
268
|
+
// featuredImage, priceRange, compareAtPriceRange, availableForSale, selectedOrFirstAvailableVariant }
|
|
268
269
|
```
|
|
269
270
|
|
|
270
271
|
`detail()` returns `ProductDetailResult`, a discriminated union:
|
|
@@ -276,6 +277,15 @@ mismatches, still throw
|
|
|
276
277
|
typed `SDKError` subclasses and preserve request IDs through the existing
|
|
277
278
|
`lastRequestId` / `onRequestId` path.
|
|
278
279
|
|
|
280
|
+
Public product visibility has two axes. Lifecycle `status` must still be
|
|
281
|
+
`published` and `publishedAt` must be current or empty. Then
|
|
282
|
+
`storefrontVisibility` decides storefront exposure: `listed` products appear in
|
|
283
|
+
listing helpers and direct detail, `unlisted` products are omitted from listing
|
|
284
|
+
helpers but can be fetched by direct detail slug/id, and `hidden` products return
|
|
285
|
+
`{ found: false, reason: 'not_published' }` from detail and are omitted from
|
|
286
|
+
listings. Legacy products without `storefrontVisibility` are treated as
|
|
287
|
+
`listed`.
|
|
288
|
+
|
|
279
289
|
The successful product payload exposes inventory rollups without sentinel
|
|
280
290
|
values: `product.totalInventory` is the tracked stock sum across non-unlimited
|
|
281
291
|
variants, `null` when no variants are tracked, and
|
|
@@ -362,9 +372,28 @@ const server = createServerClient({
|
|
|
362
372
|
secretKey: process.env.SOFTWARE_SECRET_KEY!,
|
|
363
373
|
})
|
|
364
374
|
|
|
375
|
+
const now = new Date().toISOString()
|
|
365
376
|
const { docs } = await server.collections.from('products').find({
|
|
366
377
|
...PRODUCT_PLP_FIND_OPTIONS,
|
|
367
|
-
where: {
|
|
378
|
+
where: {
|
|
379
|
+
and: [
|
|
380
|
+
{ status: { equals: 'published' } },
|
|
381
|
+
{
|
|
382
|
+
or: [
|
|
383
|
+
{ publishedAt: { less_than_equal: now } },
|
|
384
|
+
{ publishedAt: { exists: false } },
|
|
385
|
+
{ publishedAt: { equals: null } },
|
|
386
|
+
],
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
or: [
|
|
390
|
+
{ storefrontVisibility: { equals: 'listed' } },
|
|
391
|
+
{ storefrontVisibility: { exists: false } },
|
|
392
|
+
{ storefrontVisibility: { equals: null } },
|
|
393
|
+
],
|
|
394
|
+
},
|
|
395
|
+
],
|
|
396
|
+
},
|
|
368
397
|
limit: 24,
|
|
369
398
|
})
|
|
370
399
|
```
|
|
@@ -465,11 +494,11 @@ const selectionQuery = codec.stringify(normalizedSelection)
|
|
|
465
494
|
#### Empty vs partial selection
|
|
466
495
|
|
|
467
496
|
When selection input is omitted, `resolveProductSelection()` applies
|
|
468
|
-
`
|
|
497
|
+
`selectedOrFirstAvailableVariant` so PDP defaults match listing cards. That is
|
|
469
498
|
separate from `fillDefaults` and is not gated by a flag.
|
|
470
499
|
|
|
471
500
|
```typescript
|
|
472
|
-
// PDP default (uses
|
|
501
|
+
// PDP default (uses selectedOrFirstAvailableVariant when selection is omitted)
|
|
473
502
|
resolveProductSelection(product)
|
|
474
503
|
|
|
475
504
|
// Catalog: keep price range / no concrete variant
|
|
@@ -489,7 +518,7 @@ const resolution = resolveProductSelection(
|
|
|
489
518
|
},
|
|
490
519
|
)
|
|
491
520
|
// resolution.selectedVariant is concrete; unselected options are filled
|
|
492
|
-
// using the same available-by-order
|
|
521
|
+
// using the same available-by-order rule that derives selectedOrFirstAvailableVariant.
|
|
493
522
|
```
|
|
494
523
|
|
|
495
524
|
For option-click handlers, use `selectNext()` to apply a slug transition,
|
|
@@ -548,16 +577,19 @@ inspect grouped variant fields without a follow-up fetch. The by-ids response
|
|
|
548
577
|
also returns `missing: string[]` for requested product IDs that were not found,
|
|
549
578
|
not published, or not accessible; `docs` preserve the input `productIds` order
|
|
550
579
|
for returned products. The helper populates optional `representativeVariant`, a
|
|
551
|
-
PDP-seeded `href`, representative media
|
|
552
|
-
`product.
|
|
553
|
-
|
|
554
|
-
groups when there is more than one. Single-group
|
|
555
|
-
storefronts that disagree can read `item.groups`
|
|
580
|
+
PDP-seeded `href`, representative media from Shopify-shaped
|
|
581
|
+
`product.featuredImage` with product gallery fallback, Product-level
|
|
582
|
+
`priceRange` / `compareAtPriceRange`, Product-level `availableForSale`, and a
|
|
583
|
+
`swatches[]` array derived from groups when there is more than one. Single-group
|
|
584
|
+
products emit `swatches: []`; storefronts that disagree can read `item.groups`
|
|
585
|
+
directly.
|
|
556
586
|
|
|
557
587
|
`buildProductListingCard()` derives card swatches from listing-group
|
|
558
588
|
`optionValueSwatch`. Image swatches use `swatch.mediaItemId`; color swatches use
|
|
559
589
|
`swatch.color`. Option-value thumbnail/gallery fields are no longer part of the
|
|
560
|
-
public listing-group or product-detail contract.
|
|
590
|
+
public listing-group or product-detail contract. New PLP filters and sorts
|
|
591
|
+
should use Product-shaped names such as `priceRange.minVariantPrice.amount`,
|
|
592
|
+
`priceRange.maxVariantPrice.amount`, and `availableForSale`.
|
|
561
593
|
|
|
562
594
|
```ts
|
|
563
595
|
import {
|
|
@@ -669,7 +701,7 @@ Dotted-path filters (`where: { 'product.slug': { equals } }`) are Payload-native
|
|
|
669
701
|
|
|
670
702
|
Checklist when `find()` returns `docs: []` unexpectedly, in order of likelihood:
|
|
671
703
|
|
|
672
|
-
1. **Access control filtered the document.** Many collections enforce status
|
|
704
|
+
1. **Access control filtered the document.** Many collections enforce public read filters. Products require `status: 'published'`, a current or unset `publishedAt`, and listable storefront visibility (`listed`, legacy missing, or `null`) for publishable-key raw listing reads. Draft, future, `unlisted`, `hidden`, or malformed products silently disappear from raw listing results even when their slug or ID matches. Use the shaped product detail helper for direct-link `unlisted` products. Correlate with backend logs via `client.lastRequestId` (or catch `SDKError.requestId`).
|
|
673
705
|
2. **Build-time publishable key / API URL differs from runtime.** SSG `generateStaticParams` / `generateMetadata` / the page render must all see the same tenant context. A wrong or missing key at build time produces a baked-in empty response.
|
|
674
706
|
3. **Next.js SSG fetch cache served a stale empty response.** Use `cache: 'no-store'` or `export const revalidate = 0` on server components that should reflect live data.
|
|
675
707
|
4. **`where: { slug: 'x' }` string shorthand.** Always use `{ slug: { equals: 'x' } }` — bare strings silently match nothing.
|
|
@@ -749,7 +781,6 @@ const { docs, totalDocs, hasNextPage } = await client.collections
|
|
|
749
781
|
limit: 20,
|
|
750
782
|
page: 1,
|
|
751
783
|
sort: '-createdAt',
|
|
752
|
-
where: { status: { equals: 'published' } },
|
|
753
784
|
depth: 0,
|
|
754
785
|
select: { title: true, slug: true },
|
|
755
786
|
})
|
|
@@ -981,7 +1012,7 @@ client.customer.auth.logout()
|
|
|
981
1012
|
const orders = await client.commerce.orders.listMine({
|
|
982
1013
|
page: 1,
|
|
983
1014
|
limit: 10,
|
|
984
|
-
|
|
1015
|
+
displayFinancialStatus: 'paid',
|
|
985
1016
|
})
|
|
986
1017
|
|
|
987
1018
|
// Password
|
|
@@ -992,7 +1023,7 @@ await client.customer.auth.changePassword(currentPassword, newPassword)
|
|
|
992
1023
|
|
|
993
1024
|
### Commerce Orders (ServerClient-only writes)
|
|
994
1025
|
|
|
995
|
-
Available on ServerClient via `server.commerce.orders.*`. `checkout` and `listMine` are also on Client and return sanitized customer-facing order DTOs. Use `server.collections.from('orders')` for raw operational order documents.
|
|
1026
|
+
Available on ServerClient via `server.commerce.orders.*`. `checkout` and `listMine` are also on Client and return sanitized customer-facing order DTOs. Customer order DTOs expose the independent status axes (`displayFinancialStatus`, `displayFulfillmentStatus`, `returnStatus`, `primaryDisplayStatus`, `returnDisplayStatus`); `status` and `displayStatus` are read-only compatibility aliases for older clients. Use `server.collections.from('orders')` for raw operational order documents.
|
|
996
1027
|
|
|
997
1028
|
```typescript
|
|
998
1029
|
// Orders
|
|
@@ -1307,7 +1338,7 @@ join-order surface and does not emit a semantic order-change webhook.
|
|
|
1307
1338
|
|
|
1308
1339
|
## Supported Collections
|
|
1309
1340
|
|
|
1310
|
-
Source of truth: `packages/sdk/src/core/collection/const.ts` (`COLLECTIONS`:
|
|
1341
|
+
Source of truth: `packages/sdk/src/core/collection/const.ts` (`COLLECTIONS`: 51).
|
|
1311
1342
|
|
|
1312
1343
|
| Category | Browser-public generic collections |
|
|
1313
1344
|
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
@@ -1318,7 +1349,7 @@ Source of truth: `packages/sdk/src/core/collection/const.ts` (`COLLECTIONS`: 53)
|
|
|
1318
1349
|
| Content | `documents`, `document-categories`, `document-types`, `articles`, `article-authors`, `article-categories`, `article-tags`, `links`, `link-categories`, `link-tags` |
|
|
1319
1350
|
| Playlists / Tracks | `playlists`, `playlist-categories`, `playlist-tags`, `tracks`, `track-categories`, `track-tags` |
|
|
1320
1351
|
| Galleries | `galleries`, `gallery-categories`, `gallery-tags`, `gallery-items` |
|
|
1321
|
-
| Canvas | `canvases`, `canvas-node-types`, `canvas-edge-types`, `canvas-categories`, `canvas-tags
|
|
1352
|
+
| Canvas | `canvases`, `canvas-node-types`, `canvas-edge-types`, `canvas-categories`, `canvas-tags` |
|
|
1322
1353
|
| Videos | `video-categories`, `video-tags` |
|
|
1323
1354
|
| Forms | `forms` |
|
|
1324
1355
|
| Community | `reaction-types`, `post-categories`, `post-tags`, `customer-profile-lists` |
|
|
@@ -1327,7 +1358,8 @@ Source of truth: `packages/sdk/src/core/collection/const.ts` (`COLLECTIONS`: 53)
|
|
|
1327
1358
|
Server-only collections include raw media/logo records, customer and order
|
|
1328
1359
|
operational records, raw cart/cart-item records, form submissions, raw community documents
|
|
1329
1360
|
(`posts`, `comments`, `reactions`, `bookmarks`), live stream provider records,
|
|
1330
|
-
|
|
1361
|
+
Canvas graph shell rows (`canvas-nodes`, `canvas-edges`), segmentation records,
|
|
1362
|
+
and moderation records. They remain available from
|
|
1331
1363
|
`createServerClient().collections` with secret/PAT credentials. Shaped
|
|
1332
1364
|
browser/customer helpers such as `commerce.cart.*`,
|
|
1333
1365
|
`commerce.orders.listMine()`, and `commerce.orders.checkout()` remain available
|
|
@@ -1477,7 +1509,7 @@ Migration steps:
|
|
|
1477
1509
|
|
|
1478
1510
|
1. Replace color-only values with `swatch: { type: 'color', color: '#111111' }`.
|
|
1479
1511
|
2. Replace thumbnail/gallery values with `swatch: { type: 'media', mediaItemId: '<product-pool-image-id>' }`.
|
|
1480
|
-
3. Ensure media swatches reference an image already attached to the parent product (`products.images`
|
|
1512
|
+
3. Ensure media swatches reference an image already attached to the parent product (`products.images`).
|
|
1481
1513
|
4. Remove reads of pre-ADR-0025 response fields; consume `optionValueSwatch` / `optionValue.swatch` instead.
|
|
1482
1514
|
|
|
1483
1515
|
## Migration Guide
|
package/dist/client.cjs
CHANGED
|
@@ -1479,6 +1479,19 @@ var CustomerAuth = class {
|
|
|
1479
1479
|
const params = new URLSearchParams();
|
|
1480
1480
|
if (options?.page) params.set("page", String(options.page));
|
|
1481
1481
|
if (options?.limit) params.set("limit", String(options.limit));
|
|
1482
|
+
if (options?.displayFinancialStatus) {
|
|
1483
|
+
params.set("displayFinancialStatus", options.displayFinancialStatus);
|
|
1484
|
+
}
|
|
1485
|
+
if (options?.displayFulfillmentStatus) {
|
|
1486
|
+
params.set("displayFulfillmentStatus", options.displayFulfillmentStatus);
|
|
1487
|
+
}
|
|
1488
|
+
if (options?.returnStatus) params.set("returnStatus", options.returnStatus);
|
|
1489
|
+
if (options?.primaryDisplayStatus) {
|
|
1490
|
+
params.set("primaryDisplayStatus", options.primaryDisplayStatus);
|
|
1491
|
+
}
|
|
1492
|
+
if (options?.returnDisplayStatus) {
|
|
1493
|
+
params.set("returnDisplayStatus", options.returnDisplayStatus);
|
|
1494
|
+
}
|
|
1482
1495
|
if (options?.status) params.set("status", options.status);
|
|
1483
1496
|
const qs = params.toString();
|
|
1484
1497
|
return this.requestJson(`/api/customers/me/orders${qs ? `?${qs}` : ""}`, {
|
|
@@ -1593,9 +1606,6 @@ function getMediaId(value) {
|
|
|
1593
1606
|
}
|
|
1594
1607
|
return null;
|
|
1595
1608
|
}
|
|
1596
|
-
function toPointerId(value) {
|
|
1597
|
-
return getMediaId(value);
|
|
1598
|
-
}
|
|
1599
1609
|
function mediaArray(value) {
|
|
1600
1610
|
if (!Array.isArray(value)) return [];
|
|
1601
1611
|
return value.filter((entry) => entry != null);
|
|
@@ -1712,22 +1722,16 @@ function resolveProductSelectionMedia(input) {
|
|
|
1712
1722
|
source: "none"
|
|
1713
1723
|
};
|
|
1714
1724
|
}
|
|
1715
|
-
function
|
|
1725
|
+
function resolveFeaturedImagePointer(input) {
|
|
1716
1726
|
const pool = mediaArray(input.productMediaPool);
|
|
1717
1727
|
const resolvedPointer = getMediaId(input.resolvedPrimary);
|
|
1718
1728
|
if (resolvedPointer && input.resolvedSource !== "product_pool" && input.resolvedSource !== "none") {
|
|
1719
1729
|
return resolvedPointer;
|
|
1720
1730
|
}
|
|
1721
1731
|
const poolById = buildPoolById(pool);
|
|
1722
|
-
const
|
|
1723
|
-
if (
|
|
1724
|
-
return
|
|
1725
|
-
}
|
|
1726
|
-
const primaryPointer = toPointerId(input.productPrimaryMediaItemId);
|
|
1727
|
-
if (primaryPointer && poolById.has(primaryPointer)) return primaryPointer;
|
|
1728
|
-
const thumbnailPointer = getMediaId(input.productThumbnail);
|
|
1729
|
-
if (thumbnailPointer && poolById.has(thumbnailPointer)) {
|
|
1730
|
-
return thumbnailPointer;
|
|
1732
|
+
const featuredImagePointer = getMediaId(input.featuredImage);
|
|
1733
|
+
if (featuredImagePointer && poolById.has(featuredImagePointer)) {
|
|
1734
|
+
return featuredImagePointer;
|
|
1731
1735
|
}
|
|
1732
1736
|
if (pool.length > 0) {
|
|
1733
1737
|
const firstPoolId = getMediaId(pool[0]);
|
|
@@ -1782,13 +1786,9 @@ function extractEntityId(value) {
|
|
|
1782
1786
|
return null;
|
|
1783
1787
|
}
|
|
1784
1788
|
function resolveGenericListingPrimaryImage(product, resolvedPrimary, resolvedSource) {
|
|
1785
|
-
return
|
|
1789
|
+
return resolveFeaturedImagePointer({
|
|
1786
1790
|
productMediaPool: product?.images ?? [],
|
|
1787
|
-
|
|
1788
|
-
product?.primaryMediaItemId ?? null
|
|
1789
|
-
),
|
|
1790
|
-
productThumbnail: product?.thumbnail ?? null,
|
|
1791
|
-
listingPrimaryImage: product?.listing?.primaryImage ?? null,
|
|
1791
|
+
featuredImage: product?.featuredImage ?? null,
|
|
1792
1792
|
resolvedPrimary,
|
|
1793
1793
|
resolvedSource
|
|
1794
1794
|
});
|
|
@@ -2427,7 +2427,7 @@ function getMinMax(values) {
|
|
|
2427
2427
|
max: Math.max(...numbers)
|
|
2428
2428
|
};
|
|
2429
2429
|
}
|
|
2430
|
-
function
|
|
2430
|
+
function buildProductListingGroupProjection(product, variants) {
|
|
2431
2431
|
const orderedVariants = [...variants].sort(compareVariantOrder);
|
|
2432
2432
|
const activeVariants = orderedVariants.filter(
|
|
2433
2433
|
(variant) => variant.isActive !== false
|
|
@@ -2448,7 +2448,6 @@ function buildProductListingProjection(product, variants) {
|
|
|
2448
2448
|
const mediaSelectionVariants = sortVariantsForMediaSelection(variants);
|
|
2449
2449
|
const resolvedProductMedia = resolveProductSelectionMedia({
|
|
2450
2450
|
productMediaPool,
|
|
2451
|
-
productPrimaryMediaItemId: getRelationID(product?.primaryMediaItemId),
|
|
2452
2451
|
selectedVariant: selectionHintVariant && selectionHintHasPoolMedia ? {
|
|
2453
2452
|
id: selectionHintVariant.id,
|
|
2454
2453
|
images: selectionHintVariant.images
|
|
@@ -2474,47 +2473,22 @@ function buildProductListingCard(item, options = {}) {
|
|
|
2474
2473
|
const product = item.product;
|
|
2475
2474
|
const groups = item.groups;
|
|
2476
2475
|
const variants = getProductListingCardVariants(item);
|
|
2477
|
-
const projectedListing =
|
|
2478
|
-
const selectionHintVariant = getRelationID(
|
|
2479
|
-
product.listing && "selectionHintVariant" in product.listing ? product.listing.selectionHintVariant : null
|
|
2480
|
-
) ?? projectedListing.selectionHintVariant;
|
|
2476
|
+
const projectedListing = buildProductListingGroupProjection(product, variants);
|
|
2477
|
+
const selectionHintVariant = getRelationID(product.selectedOrFirstAvailableVariant) ?? projectedListing.selectionHintVariant;
|
|
2481
2478
|
const representativeVariant = findListingCardRepresentativeVariant(
|
|
2482
2479
|
variants,
|
|
2483
2480
|
selectionHintVariant
|
|
2484
2481
|
);
|
|
2485
2482
|
const productMediaPool = mediaArray2(product.images);
|
|
2486
|
-
const
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
(poolItem) => getRelationID(poolItem) === getRelationID(image)
|
|
2490
|
-
)
|
|
2491
|
-
)
|
|
2492
|
-
);
|
|
2493
|
-
const resolvedPrimaryMedia = resolveProductSelectionMedia(
|
|
2494
|
-
{
|
|
2495
|
-
productMediaPool,
|
|
2496
|
-
productPrimaryMediaItemId: getRelationID(product.primaryMediaItemId),
|
|
2497
|
-
selectedVariant: representativeHasPoolMedia ? representativeVariant : null,
|
|
2498
|
-
matchingVariants: representativeHasPoolMedia ? [] : variants
|
|
2499
|
-
}
|
|
2500
|
-
);
|
|
2501
|
-
const listingPrimaryPointer = resolveListingPrimaryImagePointer({
|
|
2502
|
-
productMediaPool,
|
|
2503
|
-
productPrimaryMediaItemId: getRelationID(product.primaryMediaItemId),
|
|
2504
|
-
productThumbnail: product.thumbnail ?? null,
|
|
2505
|
-
listingPrimaryImage: product.listing?.primaryImage ?? null,
|
|
2506
|
-
resolvedPrimary: resolvedPrimaryMedia.primaryImage,
|
|
2507
|
-
resolvedSource: resolvedPrimaryMedia.source
|
|
2508
|
-
});
|
|
2509
|
-
const listingPrimaryMedia = listingPrimaryPointer ? productMediaPool.find(
|
|
2510
|
-
(item2) => getRelationID(item2) === listingPrimaryPointer
|
|
2511
|
-
) ?? resolvedPrimaryMedia.primaryImage ?? null : null;
|
|
2483
|
+
const featuredImageId = getRelationID(product.featuredImage);
|
|
2484
|
+
const featuredImageFromPool = featuredImageId ? productMediaPool.find((item2) => getRelationID(item2) === featuredImageId) : void 0;
|
|
2485
|
+
const listingPrimaryMedia = featuredImageFromPool ?? product.featuredImage ?? productMediaPool[0] ?? null;
|
|
2512
2486
|
const priceRange = resolveListingCardPriceRange(
|
|
2513
2487
|
product,
|
|
2514
2488
|
projectedListing,
|
|
2515
2489
|
groups
|
|
2516
2490
|
);
|
|
2517
|
-
const availableForSale = product.
|
|
2491
|
+
const availableForSale = product.availableForSale != null ? product.availableForSale : groups.length > 0 ? groups.some((group) => group.listing.availableForSale) : projectedListing.availableForSale;
|
|
2518
2492
|
const swatches = groups.length > 1 ? groups.map((group) => buildListingSwatch(product, group, options)) : [];
|
|
2519
2493
|
return {
|
|
2520
2494
|
id: String(product.id),
|
|
@@ -2554,23 +2528,20 @@ function findListingCardRepresentativeVariant(variants, representativeVariantId)
|
|
|
2554
2528
|
(variant) => getRelationID(variant.id) === representativeVariantId
|
|
2555
2529
|
) ?? null;
|
|
2556
2530
|
}
|
|
2557
|
-
function
|
|
2558
|
-
return
|
|
2559
|
-
}
|
|
2560
|
-
function listingDefinesCompareAtProjection(listing) {
|
|
2561
|
-
return "minCompareAtPrice" in listing || "maxCompareAtPrice" in listing;
|
|
2531
|
+
function hasCompleteProductPriceRange(priceRange) {
|
|
2532
|
+
return priceRange?.minVariantPrice?.amount != null && priceRange?.maxVariantPrice?.amount != null;
|
|
2562
2533
|
}
|
|
2563
2534
|
function resolveListingCardPriceRange(product, projectedListing, groups) {
|
|
2564
|
-
|
|
2565
|
-
if (hasCompleteListingPriceProjection(listing)) {
|
|
2535
|
+
if (hasCompleteProductPriceRange(product.priceRange)) {
|
|
2566
2536
|
const groupRange = groups.length > 0 ? aggregateListingPriceRange(groups) : null;
|
|
2567
|
-
const
|
|
2537
|
+
const minCompareAtPrice = product.compareAtPriceRange?.minVariantPrice?.amount ?? groupRange?.minCompareAtPrice ?? null;
|
|
2538
|
+
const maxCompareAtPrice = product.compareAtPriceRange?.maxVariantPrice?.amount ?? groupRange?.maxCompareAtPrice ?? null;
|
|
2568
2539
|
return {
|
|
2569
|
-
minPrice:
|
|
2570
|
-
maxPrice:
|
|
2571
|
-
minCompareAtPrice
|
|
2572
|
-
maxCompareAtPrice
|
|
2573
|
-
isPriceRange:
|
|
2540
|
+
minPrice: product.priceRange.minVariantPrice.amount,
|
|
2541
|
+
maxPrice: product.priceRange.maxVariantPrice.amount,
|
|
2542
|
+
minCompareAtPrice,
|
|
2543
|
+
maxCompareAtPrice,
|
|
2544
|
+
isPriceRange: product.priceRange.isPriceRange ?? product.priceRange.minVariantPrice.amount !== product.priceRange.maxVariantPrice.amount
|
|
2574
2545
|
};
|
|
2575
2546
|
}
|
|
2576
2547
|
if (groups.length > 0) {
|
|
@@ -2682,15 +2653,19 @@ function buildProductListingPageWhere(params) {
|
|
|
2682
2653
|
if (tagIds) clauses.push({ tags: { in: tagIds } });
|
|
2683
2654
|
const minPrice = filters?.price?.min;
|
|
2684
2655
|
if (minPrice != null) {
|
|
2685
|
-
clauses.push({
|
|
2656
|
+
clauses.push({
|
|
2657
|
+
"priceRange.maxVariantPrice.amount": { greater_than_equal: minPrice }
|
|
2658
|
+
});
|
|
2686
2659
|
}
|
|
2687
2660
|
const maxPrice = filters?.price?.max;
|
|
2688
2661
|
if (maxPrice != null) {
|
|
2689
|
-
clauses.push({
|
|
2662
|
+
clauses.push({
|
|
2663
|
+
"priceRange.minVariantPrice.amount": { less_than_equal: maxPrice }
|
|
2664
|
+
});
|
|
2690
2665
|
}
|
|
2691
2666
|
if (filters?.availableForSale != null) {
|
|
2692
2667
|
clauses.push({
|
|
2693
|
-
|
|
2668
|
+
availableForSale: { equals: filters.availableForSale }
|
|
2694
2669
|
});
|
|
2695
2670
|
}
|
|
2696
2671
|
if (clauses.length === 0) return void 0;
|