@sixtyninecommerce/client 0.29.0 → 0.30.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 +8 -2
- package/dist/commerce/products.d.ts.map +1 -1
- package/dist/commerce/products.js +5 -0
- package/dist/commerce/products.js.map +1 -1
- package/dist/commerce/queries.d.ts +15 -9
- package/dist/commerce/queries.d.ts.map +1 -1
- package/dist/commerce/queries.js +16 -0
- package/dist/commerce/queries.js.map +1 -1
- package/dist/commerce/saved-lists.d.ts +7 -7
- package/dist/commerce/saved-lists.d.ts.map +1 -1
- package/dist/commerce/saved-lists.js +1 -0
- package/dist/commerce/saved-lists.js.map +1 -1
- package/dist/commerce/search.d.ts.map +1 -1
- package/dist/commerce/search.js +8 -0
- package/dist/commerce/search.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pricing/index.d.ts +1 -1
- package/dist/pricing/index.d.ts.map +1 -1
- package/dist/pricing/index.js +5 -2
- package/dist/pricing/index.js.map +1 -1
- package/dist/pricing/validation.d.ts +89 -1
- package/dist/pricing/validation.d.ts.map +1 -1
- package/dist/pricing/validation.js +107 -1
- package/dist/pricing/validation.js.map +1 -1
- package/dist/seo/availability.d.ts +95 -0
- package/dist/seo/availability.d.ts.map +1 -0
- package/dist/seo/availability.js +89 -0
- package/dist/seo/availability.js.map +1 -0
- package/dist/seo/index.d.ts +2 -0
- package/dist/seo/index.d.ts.map +1 -1
- package/dist/seo/index.js +3 -0
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/json-ld.d.ts.map +1 -1
- package/dist/seo/json-ld.js +34 -1
- package/dist/seo/json-ld.js.map +1 -1
- package/dist/seo/meta-tags.d.ts +40 -1
- package/dist/seo/meta-tags.d.ts.map +1 -1
- package/dist/seo/meta-tags.js +8 -1
- package/dist/seo/meta-tags.js.map +1 -1
- package/dist/seo/types.d.ts +11 -0
- package/dist/seo/types.d.ts.map +1 -1
- package/dist/types.d.ts +177 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/pricing/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { formatPrice, formatPriceRange } from './format.js';
|
|
2
2
|
import { ACTIVE_TAX_DISPLAY_MODE, identityStamp, parseTaxDisplayPolicy, resolveTaxDisplayMode, taxDisplayModeFromEnum, } from './tax-display.js';
|
|
3
3
|
import { computeTierTable, getTierForQuantity } from './tiers.js';
|
|
4
|
-
import { backorderedQuantityForCart, isBackorderOnly, maxOrderableQuantity, validateOrderMinimums, } from './validation.js';
|
|
4
|
+
import { backorderedQuantityForCart, canAddToCart, isBackorderOnly, isComingSoon, isPreorderOnly, maxOrderableQuantity, validateOrderMinimums, } from './validation.js';
|
|
5
5
|
export { formatPrice, formatPriceRange } from './format.js';
|
|
6
6
|
export { ACTIVE_TAX_DISPLAY_MODE, DEFAULT_TAX_DISPLAY_POLICY, identityStamp, parseTaxDisplayPolicy, parseTaxExclusiveCountries, resolveTaxDisplayMode, taxDisplayModeFromEnum, } from './tax-display.js';
|
|
7
7
|
export { computeTierTable, getTierForQuantity } from './tiers.js';
|
|
8
|
-
export { backorderedQuantityForCart, isBackorderOnly, maxOrderableQuantity, validateOrderMinimums, } from './validation.js';
|
|
8
|
+
export { backorderedQuantityForCart, canAddToCart, isBackorderOnly, isComingSoon, isPreorderOnly, maxOrderableQuantity, validateOrderMinimums, } from './validation.js';
|
|
9
9
|
/**
|
|
10
10
|
* @param http Optional Shop API client. Without it the module is fully offline
|
|
11
11
|
* (formatting, tier maths, the pure policy helpers) and
|
|
@@ -100,6 +100,9 @@ export function createPricingModule(ctx, http) {
|
|
|
100
100
|
validateOrderMinimums,
|
|
101
101
|
maxOrderableQuantity,
|
|
102
102
|
isBackorderOnly,
|
|
103
|
+
isComingSoon,
|
|
104
|
+
isPreorderOnly,
|
|
105
|
+
canAddToCart,
|
|
103
106
|
backorderedQuantityForCart,
|
|
104
107
|
};
|
|
105
108
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pricing/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EACL,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,aAAa,EACb,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EACL,0BAA0B,EAC1B,eAAe,EACf,oBAAoB,EAEpB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAiB,EAAE,IAAiB;IACtE,8EAA8E;IAC9E,MAAM,WAAW,GAAG,GAAmB,EAAE,CAAC,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAEnF,0EAA0E;IAC1E,MAAM,UAAU,GAAG,GAA0B,EAAE;QAC7C,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC;QAC9B,OAAO,MAAM,IAAI,MAAM,CAAC,KAAK,KAAK,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,CAAC,CAAC;IAEF,OAAO;QACL,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;QAEtC,KAAK,CAAC,iBAAiB,CAAC,OAA+B;YACrD,IAAI,OAAO,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;gBAC9B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;gBAC5B,IAAI,MAAM,KAAK,IAAI;oBAAE,OAAO,MAAM,CAAC;YACrC,CAAC;YACD,IAAI,CAAC,IAAI;gBAAE,OAAO,WAAW,EAAE,CAAC;YAEhC,IAAI,IAAI,GAA0B,IAAI,CAAC;YACvC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAC7B,uBAAuB,CACxB,CAAC;gBACF,IAAI,GAAG,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;YAC5D,CAAC;YAAC,MAAM,CAAC;gBACP,kEAAkE;gBAClE,qDAAqD;gBACrD,IAAI,GAAG,IAAI,CAAC;YACd,CAAC;YACD,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAO,WAAW,EAAE,CAAC;YAExC,wEAAwE;YACxE,gEAAgE;YAChE,GAAG,CAAC,UAAU,GAAG,EAAE,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,qBAAqB;YACnB,OAAO,UAAU,EAAE,IAAI,WAAW,EAAE,CAAC;QACvC,CAAC;QAED,qBAAqB;QACrB,qBAAqB;QAErB,WAAW,CAAC,MAAM,EAAE,YAAa,EAAE,MAAO;YACxC,OAAO,WAAW,CAAC,MAAM,EAAE,YAAY,IAAI,GAAG,CAAC,YAAY,EAAE,MAAM,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;QAC3F,CAAC;QAED,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,YAAa,EAAE,MAAO;YAC/C,OAAO,gBAAgB,CACrB,GAAG,EACH,GAAG,EACH,YAAY,IAAI,GAAG,CAAC,YAAY,EAChC,MAAM,IAAI,GAAG,CAAC,YAAY,CAC3B,CAAC;QACJ,CAAC;QAED,kBAAkB;QAClB,gBAAgB;QAEhB,kBAAkB,CAAC,OAAyB,EAAE,IAAqB;YACjE,MAAM,OAAO,GAAG,CAAC,IAAI,IAAI,UAAU,EAAE,IAAI,WAAW,EAAE,CAAC,KAAK,OAAO,CAAC;YACpE,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;YAC9D,MAAM,YAAY,GAAG,OAAO;gBAC1B,CAAC,CAAC,CAAC,OAAO,CAAC,kBAAkB,IAAI,IAAI,CAAC;gBACtC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC;YAClC,OAAO;gBACL,MAAM;gBACN,YAAY;gBACZ,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,OAAO;gBACP,WAAW,EAAE,YAAY,IAAI,IAAI,IAAI,YAAY,GAAG,MAAM;aAC3D,CAAC;QACJ,CAAC;QAED,eAAe,CAAC,OAAyB;YACvC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC;YAEvF,IAAI,kBAAkB,GAAkB,IAAI,CAAC;YAC7C,IAAI,WAAW,IAAI,OAAO,CAAC,WAAW,IAAI,IAAI,IAAI,OAAO,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;gBAC1E,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAC7B,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,GAAG,CACpE,CAAC;YACJ,CAAC;YAED,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,EAAE,MAAM;gBAC3C,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;gBAC3C,CAAC,CAAC,IAAI,CAAC;YAET,OAAO;gBACL,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI;gBACxC,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,IAAI,IAAI;gBACtD,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,IAAI;gBAC5C,OAAO,EAAE,OAAO,CAAC,cAAc,EAAE,KAAK,IAAI,IAAI;gBAC9C,WAAW;gBACX,kBAAkB;gBAClB,UAAU;aACX,CAAC;QACJ,CAAC;QAED,qBAAqB;QACrB,oBAAoB;QACpB,eAAe;QACf,0BAA0B;KAC3B,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pricing/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,12 +43,22 @@ export declare function validateOrderMinimums(order: {
|
|
|
43
43
|
export type { OrderableStockInput };
|
|
44
44
|
/**
|
|
45
45
|
* How many units of a variant the current shopper may put in the cart:
|
|
46
|
-
* `max(0, saleable) + backorderAllowance
|
|
46
|
+
* `max(0, saleable) + backorderAllowance` — or `0` when the merchant is not
|
|
47
|
+
* accepting orders for it at all (`availability.orderable === false`, i.e.
|
|
48
|
+
* "coming soon").
|
|
47
49
|
*
|
|
48
50
|
* Returns `null` when the channel does not expose stock (`saleable == null`) —
|
|
49
51
|
* the storefront cannot know a ceiling then and should let the server decide,
|
|
50
52
|
* exactly as before backorders existed. A `null` allowance counts as 0, so a
|
|
51
53
|
* shopper the policy does not admit gets plain `saleable`.
|
|
54
|
+
*
|
|
55
|
+
* The coming-soon clamp comes FIRST and ignores stock: a coming-soon variant
|
|
56
|
+
* with units on hand is still refused by the server (`InsufficientStockError`,
|
|
57
|
+
* `quantityAvailable: 0`), so a stepper that let the shopper reach that number
|
|
58
|
+
* would be offering something no add-to-cart can deliver. `0` is returned
|
|
59
|
+
* rather than `null` even on a channel that hides stock, because `orderable:
|
|
60
|
+
* false` is a merchant decision the storefront CAN read — there is nothing to
|
|
61
|
+
* defer to the server about.
|
|
52
62
|
*/
|
|
53
63
|
export declare function maxOrderableQuantity(variant: OrderableStockInput): number | null;
|
|
54
64
|
/**
|
|
@@ -56,6 +66,84 @@ export declare function maxOrderableQuantity(variant: OrderableStockInput): numb
|
|
|
56
66
|
* allowance. The signal to label "Backorder" instead of "Out of stock".
|
|
57
67
|
*/
|
|
58
68
|
export declare function isBackorderOnly(variant: OrderableStockInput): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Whether the merchant is showing this variant as "coming soon": visible, but
|
|
71
|
+
* not orderable by anyone — not from stock on hand, and not on backorder.
|
|
72
|
+
*
|
|
73
|
+
* The signal to render a "Coming soon" badge (with `availability.availableFrom`
|
|
74
|
+
* as the date when it is set) and to disable add-to-cart. Stock never ends the
|
|
75
|
+
* state: a coming-soon variant with units on hand is still refused.
|
|
76
|
+
*
|
|
77
|
+
* Deliberately a `===` comparison and not a `switch`: a state this SDK release
|
|
78
|
+
* has never heard of must read as "not coming soon", never as `undefined`.
|
|
79
|
+
*/
|
|
80
|
+
export declare function isComingSoon(variant: OrderableStockInput): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Does the storefront KNOW there is nothing to buy outright?
|
|
83
|
+
*
|
|
84
|
+
* Three answers, and the third is the point: `true` known empty, `false` known
|
|
85
|
+
* to have stock, `null` when no signal is readable and nothing may be asserted
|
|
86
|
+
* either way.
|
|
87
|
+
*
|
|
88
|
+
* The signals, most precise first — and which one a shape carries depends on
|
|
89
|
+
* the document it came from:
|
|
90
|
+
*
|
|
91
|
+
* - `saleable`, the precise number. It is `null` whenever the channel does not
|
|
92
|
+
* expose stock numbers — which is the DEFAULT
|
|
93
|
+
* (`Channel.customFields.exposeStockToStorefront` is off until a merchant
|
|
94
|
+
* turns it on), so on an ordinary retail tenant every shopper sees `null`.
|
|
95
|
+
* - `inStock`, the only stock signal a SEARCH row has: `SEARCH_PRODUCTS`
|
|
96
|
+
* selects neither `saleable` nor `stockLevel`, so without this a search grid
|
|
97
|
+
* could never tell a 0-stock pre-order from one with stock.
|
|
98
|
+
* - `stockLevel`, the coarse display string every VARIANT document selects.
|
|
99
|
+
* Any value other than `'OUT_OF_STOCK'` means there is something to sell (a
|
|
100
|
+
* custom `StockDisplayStrategy` may emit `'LOW_STOCK'` and the like).
|
|
101
|
+
*/
|
|
102
|
+
export declare function knownNothingSaleable(variant: OrderableStockInput): boolean | null;
|
|
103
|
+
/**
|
|
104
|
+
* Whether this variant can be had ONLY as a pre-order: the merchant has it on
|
|
105
|
+
* pre-order AND the storefront can see there is nothing to buy outright.
|
|
106
|
+
*
|
|
107
|
+
* The label is "Pre-order", not "Out of stock". How MANY units this shopper may
|
|
108
|
+
* pre-order is `backorderAllowance` — pre-orders borrow the backorder cap, so
|
|
109
|
+
* an anonymous visitor sees `state: 'preorder'` with a `null` allowance and
|
|
110
|
+
* cannot in fact order beyond stock. Use `canAddToCart` for the button.
|
|
111
|
+
*
|
|
112
|
+
* **A `null` `saleable` is the DEFAULT, not an edge case, and it is not read as
|
|
113
|
+
* zero here.** `exposeStockToStorefront` is off until a merchant turns it on,
|
|
114
|
+
* so on an ordinary retail tenant `saleable` is `null` for everybody. Stock
|
|
115
|
+
* never ends a pre-order state either (the merchant may keep selling from the
|
|
116
|
+
* warehouse while the state stands), so reading `null` as "nothing saleable"
|
|
117
|
+
* badged a SKU with forty units on hand "Pre-order, ships 12 March" while the
|
|
118
|
+
* add succeeded from stock and the parcel shipped that afternoon. It now falls
|
|
119
|
+
* back to a search row's `inStock`, then to `stockLevel`, and answers `false`
|
|
120
|
+
* when no signal is knowable — "I cannot prove this is pre-order-only" rather
|
|
121
|
+
* than a wrong promise.
|
|
122
|
+
*
|
|
123
|
+
* **It does NOT match `isBackorderOnly`, despite the shape.** That one reads
|
|
124
|
+
* `saleable ?? 0` and cannot be wrong for the same reason: its
|
|
125
|
+
* `backorderAllowance > 0` clause is never true on a stock-hiding channel,
|
|
126
|
+
* since the allowance is `null` under exactly the same gate. The availability
|
|
127
|
+
* state has no such gate — it is public — so this helper needs the stock
|
|
128
|
+
* question answered properly.
|
|
129
|
+
*/
|
|
130
|
+
export declare function isPreorderOnly(variant: OrderableStockInput): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Whether the buy button should be enabled for this shopper, right now.
|
|
133
|
+
*
|
|
134
|
+
* `true` unless the storefront can prove otherwise: the ceiling is `0` (coming
|
|
135
|
+
* soon, or out of stock with no allowance). A `null` ceiling — the channel
|
|
136
|
+
* hides stock — stays `true` and lets the server decide, exactly as before
|
|
137
|
+
* backorders and pre-orders existed.
|
|
138
|
+
*
|
|
139
|
+
* This is the ONE rule a storefront needs. In particular it is NOT
|
|
140
|
+
* `availability.orderable`: an anonymous shopper sees `orderable: true` on a
|
|
141
|
+
* pre-order they cannot order beyond stock, because the units come from
|
|
142
|
+
* `backorderAllowance`, which is `null` for them. The server refuses either way
|
|
143
|
+
* (`InsufficientStockError` on add, `INSUFFICIENT_STOCK` at placement) — this
|
|
144
|
+
* just stops the storefront offering it.
|
|
145
|
+
*/
|
|
146
|
+
export declare function canAddToCart(variant: OrderableStockInput): boolean;
|
|
59
147
|
/**
|
|
60
148
|
* Units of a cart line physical stock will not cover — the "N on backorder"
|
|
61
149
|
* hint BEFORE placement, when `backorderedQuantity` is still 0 — computed the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/pricing/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAwB,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAGpG;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE;IACL,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,EACD,WAAW,EAAE;IACX,6FAA6F;IAC7F,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,kGAAkG;IAClG,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,GACA,qBAAqB,CAgDvB;AAED,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/pricing/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAwB,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAGpG;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE;IACL,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,EACD,WAAW,EAAE;IACX,6FAA6F;IAC7F,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,kGAAkG;IAClG,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,GACA,qBAAqB,CAgDvB;AAED,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAIhF;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAErE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAElE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,GAAG,IAAI,CAMjF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAEpE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAElE;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAC9C,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAIf"}
|
|
@@ -61,14 +61,26 @@ export function validateOrderMinimums(order, constraints) {
|
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
63
|
* How many units of a variant the current shopper may put in the cart:
|
|
64
|
-
* `max(0, saleable) + backorderAllowance
|
|
64
|
+
* `max(0, saleable) + backorderAllowance` — or `0` when the merchant is not
|
|
65
|
+
* accepting orders for it at all (`availability.orderable === false`, i.e.
|
|
66
|
+
* "coming soon").
|
|
65
67
|
*
|
|
66
68
|
* Returns `null` when the channel does not expose stock (`saleable == null`) —
|
|
67
69
|
* the storefront cannot know a ceiling then and should let the server decide,
|
|
68
70
|
* exactly as before backorders existed. A `null` allowance counts as 0, so a
|
|
69
71
|
* shopper the policy does not admit gets plain `saleable`.
|
|
72
|
+
*
|
|
73
|
+
* The coming-soon clamp comes FIRST and ignores stock: a coming-soon variant
|
|
74
|
+
* with units on hand is still refused by the server (`InsufficientStockError`,
|
|
75
|
+
* `quantityAvailable: 0`), so a stepper that let the shopper reach that number
|
|
76
|
+
* would be offering something no add-to-cart can deliver. `0` is returned
|
|
77
|
+
* rather than `null` even on a channel that hides stock, because `orderable:
|
|
78
|
+
* false` is a merchant decision the storefront CAN read — there is nothing to
|
|
79
|
+
* defer to the server about.
|
|
70
80
|
*/
|
|
71
81
|
export function maxOrderableQuantity(variant) {
|
|
82
|
+
if (variant.availability?.orderable === false)
|
|
83
|
+
return 0;
|
|
72
84
|
if (variant.saleable == null)
|
|
73
85
|
return null;
|
|
74
86
|
return Math.max(0, variant.saleable) + Math.max(0, variant.backorderAllowance ?? 0);
|
|
@@ -80,6 +92,100 @@ export function maxOrderableQuantity(variant) {
|
|
|
80
92
|
export function isBackorderOnly(variant) {
|
|
81
93
|
return (variant.saleable ?? 0) <= 0 && (variant.backorderAllowance ?? 0) > 0;
|
|
82
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Whether the merchant is showing this variant as "coming soon": visible, but
|
|
97
|
+
* not orderable by anyone — not from stock on hand, and not on backorder.
|
|
98
|
+
*
|
|
99
|
+
* The signal to render a "Coming soon" badge (with `availability.availableFrom`
|
|
100
|
+
* as the date when it is set) and to disable add-to-cart. Stock never ends the
|
|
101
|
+
* state: a coming-soon variant with units on hand is still refused.
|
|
102
|
+
*
|
|
103
|
+
* Deliberately a `===` comparison and not a `switch`: a state this SDK release
|
|
104
|
+
* has never heard of must read as "not coming soon", never as `undefined`.
|
|
105
|
+
*/
|
|
106
|
+
export function isComingSoon(variant) {
|
|
107
|
+
return variant.availability?.state === 'comingSoon';
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Does the storefront KNOW there is nothing to buy outright?
|
|
111
|
+
*
|
|
112
|
+
* Three answers, and the third is the point: `true` known empty, `false` known
|
|
113
|
+
* to have stock, `null` when no signal is readable and nothing may be asserted
|
|
114
|
+
* either way.
|
|
115
|
+
*
|
|
116
|
+
* The signals, most precise first — and which one a shape carries depends on
|
|
117
|
+
* the document it came from:
|
|
118
|
+
*
|
|
119
|
+
* - `saleable`, the precise number. It is `null` whenever the channel does not
|
|
120
|
+
* expose stock numbers — which is the DEFAULT
|
|
121
|
+
* (`Channel.customFields.exposeStockToStorefront` is off until a merchant
|
|
122
|
+
* turns it on), so on an ordinary retail tenant every shopper sees `null`.
|
|
123
|
+
* - `inStock`, the only stock signal a SEARCH row has: `SEARCH_PRODUCTS`
|
|
124
|
+
* selects neither `saleable` nor `stockLevel`, so without this a search grid
|
|
125
|
+
* could never tell a 0-stock pre-order from one with stock.
|
|
126
|
+
* - `stockLevel`, the coarse display string every VARIANT document selects.
|
|
127
|
+
* Any value other than `'OUT_OF_STOCK'` means there is something to sell (a
|
|
128
|
+
* custom `StockDisplayStrategy` may emit `'LOW_STOCK'` and the like).
|
|
129
|
+
*/
|
|
130
|
+
export function knownNothingSaleable(variant) {
|
|
131
|
+
if (typeof variant.saleable === 'number')
|
|
132
|
+
return variant.saleable <= 0;
|
|
133
|
+
if (typeof variant.inStock === 'boolean')
|
|
134
|
+
return !variant.inStock;
|
|
135
|
+
if (variant.stockLevel === 'OUT_OF_STOCK')
|
|
136
|
+
return true;
|
|
137
|
+
if (typeof variant.stockLevel === 'string' && variant.stockLevel !== '')
|
|
138
|
+
return false;
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Whether this variant can be had ONLY as a pre-order: the merchant has it on
|
|
143
|
+
* pre-order AND the storefront can see there is nothing to buy outright.
|
|
144
|
+
*
|
|
145
|
+
* The label is "Pre-order", not "Out of stock". How MANY units this shopper may
|
|
146
|
+
* pre-order is `backorderAllowance` — pre-orders borrow the backorder cap, so
|
|
147
|
+
* an anonymous visitor sees `state: 'preorder'` with a `null` allowance and
|
|
148
|
+
* cannot in fact order beyond stock. Use `canAddToCart` for the button.
|
|
149
|
+
*
|
|
150
|
+
* **A `null` `saleable` is the DEFAULT, not an edge case, and it is not read as
|
|
151
|
+
* zero here.** `exposeStockToStorefront` is off until a merchant turns it on,
|
|
152
|
+
* so on an ordinary retail tenant `saleable` is `null` for everybody. Stock
|
|
153
|
+
* never ends a pre-order state either (the merchant may keep selling from the
|
|
154
|
+
* warehouse while the state stands), so reading `null` as "nothing saleable"
|
|
155
|
+
* badged a SKU with forty units on hand "Pre-order, ships 12 March" while the
|
|
156
|
+
* add succeeded from stock and the parcel shipped that afternoon. It now falls
|
|
157
|
+
* back to a search row's `inStock`, then to `stockLevel`, and answers `false`
|
|
158
|
+
* when no signal is knowable — "I cannot prove this is pre-order-only" rather
|
|
159
|
+
* than a wrong promise.
|
|
160
|
+
*
|
|
161
|
+
* **It does NOT match `isBackorderOnly`, despite the shape.** That one reads
|
|
162
|
+
* `saleable ?? 0` and cannot be wrong for the same reason: its
|
|
163
|
+
* `backorderAllowance > 0` clause is never true on a stock-hiding channel,
|
|
164
|
+
* since the allowance is `null` under exactly the same gate. The availability
|
|
165
|
+
* state has no such gate — it is public — so this helper needs the stock
|
|
166
|
+
* question answered properly.
|
|
167
|
+
*/
|
|
168
|
+
export function isPreorderOnly(variant) {
|
|
169
|
+
return variant.availability?.state === 'preorder' && knownNothingSaleable(variant) === true;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Whether the buy button should be enabled for this shopper, right now.
|
|
173
|
+
*
|
|
174
|
+
* `true` unless the storefront can prove otherwise: the ceiling is `0` (coming
|
|
175
|
+
* soon, or out of stock with no allowance). A `null` ceiling — the channel
|
|
176
|
+
* hides stock — stays `true` and lets the server decide, exactly as before
|
|
177
|
+
* backorders and pre-orders existed.
|
|
178
|
+
*
|
|
179
|
+
* This is the ONE rule a storefront needs. In particular it is NOT
|
|
180
|
+
* `availability.orderable`: an anonymous shopper sees `orderable: true` on a
|
|
181
|
+
* pre-order they cannot order beyond stock, because the units come from
|
|
182
|
+
* `backorderAllowance`, which is `null` for them. The server refuses either way
|
|
183
|
+
* (`InsufficientStockError` on add, `INSUFFICIENT_STOCK` at placement) — this
|
|
184
|
+
* just stops the storefront offering it.
|
|
185
|
+
*/
|
|
186
|
+
export function canAddToCart(variant) {
|
|
187
|
+
return maxOrderableQuantity(variant) !== 0;
|
|
188
|
+
}
|
|
83
189
|
/**
|
|
84
190
|
* Units of a cart line physical stock will not cover — the "N on backorder"
|
|
85
191
|
* hint BEFORE placement, when `backorderedQuantity` is still 0 — computed the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/pricing/validation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAWC,EACD,WAYC;IAED,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,MAAM,SAAS,GAAG,WAAW,CAAC,mBAAmB,IAAI,WAAW,CAAC,cAAc,CAAC;IAChF,IAAI,SAAS,IAAI,IAAI,IAAI,SAAS,GAAG,CAAC,IAAI,KAAK,CAAC,YAAY,GAAG,SAAS,EAAE,CAAC;QACzE,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,2BAA2B,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,YAAY,CAAC,EAAE;YAChF,QAAQ,EAAE,SAAS;YACnB,MAAM,EAAE,KAAK,CAAC,YAAY;SAC3B,CAAC,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,2EAA2E;IAC3E,wDAAwD;IACxD,MAAM,YAAY,GAAG,WAAW,CAAC,iBAAiB,CAAC;IACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC;IAC/C,IAAI,YAAY,IAAI,IAAI,IAAI,YAAY,GAAG,CAAC,IAAI,QAAQ,IAAI,IAAI,IAAI,QAAQ,GAAG,YAAY,EAAE,CAAC;QAC5F,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,YAAY;YAClB,yEAAyE;YACzE,mDAAmD;YACnD,OAAO,EAAE,2BAA2B,WAAW,CAAC,YAAY,EAAE,KAAK,CAAC,YAAY,CAAC,YAAY;YAC7F,QAAQ,EAAE,YAAY;YACtB,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,WAAW,GAAG,WAAW,CAAC,gBAAgB,CAAC;IACjD,8EAA8E;IAC9E,wEAAwE;IACxE,wDAAwD;IACxD,IACE,WAAW,IAAI,IAAI;QACnB,WAAW,GAAG,CAAC;QACf,KAAK,CAAC,aAAa,IAAI,IAAI;QAC3B,KAAK,CAAC,aAAa,GAAG,WAAW,EACjC,CAAC;QACD,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,6BAA6B,WAAW,QAAQ;YACzD,QAAQ,EAAE,WAAW;YACrB,MAAM,EAAE,KAAK,CAAC,aAAa;SAC5B,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;AAChD,CAAC;AAID
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/pricing/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Availability for structured data: one variant's stock + merchant publication
|
|
3
|
+
* state, expressed as the schema.org `ItemAvailability` URL that
|
|
4
|
+
* `Offer.availability` wants and the OpenGraph token `product:availability`
|
|
5
|
+
* wants.
|
|
6
|
+
*
|
|
7
|
+
* These are separate vocabularies for the same fact, and `ProductSeoExtras`
|
|
8
|
+
* carries ONE `availability` string that feeds both tags. So the schema.org URL
|
|
9
|
+
* is the value a storefront passes, and `openGraphAvailability` translates it
|
|
10
|
+
* back for the OpenGraph tag. Anything the SDK does not recognise is passed
|
|
11
|
+
* through untouched, which is what every caller that predates this file gets.
|
|
12
|
+
*/
|
|
13
|
+
import type { ProductAvailability } from '../types.js';
|
|
14
|
+
/** The three `ItemAvailability` members this SDK emits. */
|
|
15
|
+
export type SchemaOrgAvailability = 'https://schema.org/InStock' | 'https://schema.org/OutOfStock' | 'https://schema.org/PreOrder';
|
|
16
|
+
/**
|
|
17
|
+
* What `schemaOrgAvailability` reads; satisfied by every SDK variant shape AND
|
|
18
|
+
* by a search row. The stock signals are the ones `isPreorderOnly` reads, read
|
|
19
|
+
* the same way (`knownNothingSaleable`), so the feed and the badge cannot
|
|
20
|
+
* disagree about whether a pre-order is buyable today.
|
|
21
|
+
*/
|
|
22
|
+
export interface AvailabilityForSeo {
|
|
23
|
+
/**
|
|
24
|
+
* The merchant publication state in force. Absent or `null` (a search row
|
|
25
|
+
* that predates the attribute, an older engine) is read as "nothing in
|
|
26
|
+
* force" — the pre-order-free behaviour.
|
|
27
|
+
*/
|
|
28
|
+
availability?: ProductAvailability | null;
|
|
29
|
+
/** Available-to-promise units — the precise signal, preferred when present. */
|
|
30
|
+
saleable?: number | null;
|
|
31
|
+
/** A search row's stock flag, the only stock signal `SEARCH_PRODUCTS` selects. */
|
|
32
|
+
inStock?: boolean | null;
|
|
33
|
+
/** Vendure's display string — `'IN_STOCK'` / `'OUT_OF_STOCK'`. */
|
|
34
|
+
stockLevel?: string | null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The schema.org `ItemAvailability` URL for a variant. Pass the result as
|
|
38
|
+
* `extras.availability` to `metaTagsFor` — JSON-LD emits it verbatim as
|
|
39
|
+
* `Offer.availability`, and the OpenGraph `product:availability` tag gets the
|
|
40
|
+
* matching Facebook token automatically.
|
|
41
|
+
*
|
|
42
|
+
* ```ts
|
|
43
|
+
* const extras = {
|
|
44
|
+
* availability: schemaOrgAvailability(variant),
|
|
45
|
+
* availabilityStarts: variant.availability?.availableFrom,
|
|
46
|
+
* ...
|
|
47
|
+
* };
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* | state | stock the storefront can SEE | result |
|
|
51
|
+
* |---|---|---|
|
|
52
|
+
* | `comingSoon` | anything | `OutOfStock` |
|
|
53
|
+
* | `preorder` | known nothing to buy | `PreOrder` |
|
|
54
|
+
* | `preorder` | known stock, or no signal | `InStock` |
|
|
55
|
+
* | anything else | known nothing to buy | `OutOfStock` |
|
|
56
|
+
* | anything else | known stock, or no signal | `InStock` |
|
|
57
|
+
*
|
|
58
|
+
* **Coming soon is `OutOfStock`, whatever the stock.** schema.org defines
|
|
59
|
+
* `PreOrder` as "Indicates that the item is available for pre-order" — an
|
|
60
|
+
* assertion that it can be ORDERED now for later delivery, which is the one
|
|
61
|
+
* thing this SDK guarantees a coming-soon item is not (`orderable: false`,
|
|
62
|
+
* `canAddToCart` false, and the engine refuses every add with
|
|
63
|
+
* `quantityAvailable: 0`, stock on hand or not). Emitting it would advertise a
|
|
64
|
+
* purchasable offer behind a disabled buy button — a Merchant Center
|
|
65
|
+
* availability-versus-landing-page mismatch. `OutOfStock` is the honest
|
|
66
|
+
* member for "not currently purchasable". (`SoldOut` is wrong the other way:
|
|
67
|
+
* it says the item HAD stock and it went, not that it has not launched.)
|
|
68
|
+
*
|
|
69
|
+
* **A pre-order is `PreOrder` only while there is nothing to buy outright** —
|
|
70
|
+
* exactly when `isPreorderOnly(variant)` is true, through the same
|
|
71
|
+
* `knownNothingSaleable` predicate. Stock never ENDS a pre-order state (the
|
|
72
|
+
* merchant may keep selling from the warehouse while it stands), but a variant
|
|
73
|
+
* with stock on hand ships today: the page shows the ordinary in-stock UI, and
|
|
74
|
+
* a feed saying "Pre-order, available 12 March" for it is the same mismatch in
|
|
75
|
+
* the other direction. So it is `InStock`, and the JSON-LD composer drops
|
|
76
|
+
* `availabilityStarts` for an `InStock` offer. When no stock signal is
|
|
77
|
+
* readable it is not claimed as a pre-order either, matching the label.
|
|
78
|
+
*
|
|
79
|
+
* Everything else is today's rule, read through the same predicate:
|
|
80
|
+
* `saleable` when the channel exposes it, then a search row's `inStock`, then
|
|
81
|
+
* the `stockLevel` string, and `InStock` when nothing says otherwise. An
|
|
82
|
+
* unknown state — one a later engine added — falls through to the stock rule
|
|
83
|
+
* rather than throwing, which is why this is a chain of comparisons and not a
|
|
84
|
+
* `switch`.
|
|
85
|
+
*/
|
|
86
|
+
export declare function schemaOrgAvailability(variant: AvailabilityForSeo): SchemaOrgAvailability;
|
|
87
|
+
/**
|
|
88
|
+
* The OpenGraph `product:availability` token for an availability value.
|
|
89
|
+
*
|
|
90
|
+
* Translates the three schema.org URLs into Facebook's vocabulary and passes
|
|
91
|
+
* anything else through verbatim — so a storefront that has always passed
|
|
92
|
+
* `'in stock'` keeps emitting `'in stock'`, byte for byte.
|
|
93
|
+
*/
|
|
94
|
+
export declare function openGraphAvailability(availability: string): string;
|
|
95
|
+
//# sourceMappingURL=availability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"availability.d.ts","sourceRoot":"","sources":["../../src/seo/availability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,2DAA2D;AAC3D,MAAM,MAAM,qBAAqB,GAC7B,4BAA4B,GAC5B,+BAA+B,GAC/B,6BAA6B,CAAC;AAElC;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,YAAY,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC1C,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,kBAAkB,GAAG,qBAAqB,CAMxF;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAKlE"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Availability for structured data: one variant's stock + merchant publication
|
|
3
|
+
* state, expressed as the schema.org `ItemAvailability` URL that
|
|
4
|
+
* `Offer.availability` wants and the OpenGraph token `product:availability`
|
|
5
|
+
* wants.
|
|
6
|
+
*
|
|
7
|
+
* These are separate vocabularies for the same fact, and `ProductSeoExtras`
|
|
8
|
+
* carries ONE `availability` string that feeds both tags. So the schema.org URL
|
|
9
|
+
* is the value a storefront passes, and `openGraphAvailability` translates it
|
|
10
|
+
* back for the OpenGraph tag. Anything the SDK does not recognise is passed
|
|
11
|
+
* through untouched, which is what every caller that predates this file gets.
|
|
12
|
+
*/
|
|
13
|
+
import { knownNothingSaleable } from '../pricing/validation.js';
|
|
14
|
+
/**
|
|
15
|
+
* The schema.org `ItemAvailability` URL for a variant. Pass the result as
|
|
16
|
+
* `extras.availability` to `metaTagsFor` — JSON-LD emits it verbatim as
|
|
17
|
+
* `Offer.availability`, and the OpenGraph `product:availability` tag gets the
|
|
18
|
+
* matching Facebook token automatically.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* const extras = {
|
|
22
|
+
* availability: schemaOrgAvailability(variant),
|
|
23
|
+
* availabilityStarts: variant.availability?.availableFrom,
|
|
24
|
+
* ...
|
|
25
|
+
* };
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* | state | stock the storefront can SEE | result |
|
|
29
|
+
* |---|---|---|
|
|
30
|
+
* | `comingSoon` | anything | `OutOfStock` |
|
|
31
|
+
* | `preorder` | known nothing to buy | `PreOrder` |
|
|
32
|
+
* | `preorder` | known stock, or no signal | `InStock` |
|
|
33
|
+
* | anything else | known nothing to buy | `OutOfStock` |
|
|
34
|
+
* | anything else | known stock, or no signal | `InStock` |
|
|
35
|
+
*
|
|
36
|
+
* **Coming soon is `OutOfStock`, whatever the stock.** schema.org defines
|
|
37
|
+
* `PreOrder` as "Indicates that the item is available for pre-order" — an
|
|
38
|
+
* assertion that it can be ORDERED now for later delivery, which is the one
|
|
39
|
+
* thing this SDK guarantees a coming-soon item is not (`orderable: false`,
|
|
40
|
+
* `canAddToCart` false, and the engine refuses every add with
|
|
41
|
+
* `quantityAvailable: 0`, stock on hand or not). Emitting it would advertise a
|
|
42
|
+
* purchasable offer behind a disabled buy button — a Merchant Center
|
|
43
|
+
* availability-versus-landing-page mismatch. `OutOfStock` is the honest
|
|
44
|
+
* member for "not currently purchasable". (`SoldOut` is wrong the other way:
|
|
45
|
+
* it says the item HAD stock and it went, not that it has not launched.)
|
|
46
|
+
*
|
|
47
|
+
* **A pre-order is `PreOrder` only while there is nothing to buy outright** —
|
|
48
|
+
* exactly when `isPreorderOnly(variant)` is true, through the same
|
|
49
|
+
* `knownNothingSaleable` predicate. Stock never ENDS a pre-order state (the
|
|
50
|
+
* merchant may keep selling from the warehouse while it stands), but a variant
|
|
51
|
+
* with stock on hand ships today: the page shows the ordinary in-stock UI, and
|
|
52
|
+
* a feed saying "Pre-order, available 12 March" for it is the same mismatch in
|
|
53
|
+
* the other direction. So it is `InStock`, and the JSON-LD composer drops
|
|
54
|
+
* `availabilityStarts` for an `InStock` offer. When no stock signal is
|
|
55
|
+
* readable it is not claimed as a pre-order either, matching the label.
|
|
56
|
+
*
|
|
57
|
+
* Everything else is today's rule, read through the same predicate:
|
|
58
|
+
* `saleable` when the channel exposes it, then a search row's `inStock`, then
|
|
59
|
+
* the `stockLevel` string, and `InStock` when nothing says otherwise. An
|
|
60
|
+
* unknown state — one a later engine added — falls through to the stock rule
|
|
61
|
+
* rather than throwing, which is why this is a chain of comparisons and not a
|
|
62
|
+
* `switch`.
|
|
63
|
+
*/
|
|
64
|
+
export function schemaOrgAvailability(variant) {
|
|
65
|
+
const state = variant.availability?.state;
|
|
66
|
+
if (state === 'comingSoon')
|
|
67
|
+
return 'https://schema.org/OutOfStock';
|
|
68
|
+
const nothingSaleable = knownNothingSaleable(variant) === true;
|
|
69
|
+
if (state === 'preorder' && nothingSaleable)
|
|
70
|
+
return 'https://schema.org/PreOrder';
|
|
71
|
+
return nothingSaleable ? 'https://schema.org/OutOfStock' : 'https://schema.org/InStock';
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The OpenGraph `product:availability` token for an availability value.
|
|
75
|
+
*
|
|
76
|
+
* Translates the three schema.org URLs into Facebook's vocabulary and passes
|
|
77
|
+
* anything else through verbatim — so a storefront that has always passed
|
|
78
|
+
* `'in stock'` keeps emitting `'in stock'`, byte for byte.
|
|
79
|
+
*/
|
|
80
|
+
export function openGraphAvailability(availability) {
|
|
81
|
+
if (availability === 'https://schema.org/InStock')
|
|
82
|
+
return 'in stock';
|
|
83
|
+
if (availability === 'https://schema.org/OutOfStock')
|
|
84
|
+
return 'out of stock';
|
|
85
|
+
if (availability === 'https://schema.org/PreOrder')
|
|
86
|
+
return 'preorder';
|
|
87
|
+
return availability;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=availability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"availability.js","sourceRoot":"","sources":["../../src/seo/availability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AA8BhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAA2B;IAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC;IAC1C,IAAI,KAAK,KAAK,YAAY;QAAE,OAAO,+BAA+B,CAAC;IACnE,MAAM,eAAe,GAAG,oBAAoB,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC;IAC/D,IAAI,KAAK,KAAK,UAAU,IAAI,eAAe;QAAE,OAAO,6BAA6B,CAAC;IAClF,OAAO,eAAe,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,4BAA4B,CAAC;AAC1F,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,YAAoB;IACxD,IAAI,YAAY,KAAK,4BAA4B;QAAE,OAAO,UAAU,CAAC;IACrE,IAAI,YAAY,KAAK,+BAA+B;QAAE,OAAO,cAAc,CAAC;IAC5E,IAAI,YAAY,KAAK,6BAA6B;QAAE,OAAO,UAAU,CAAC;IACtE,OAAO,YAAY,CAAC;AACtB,CAAC"}
|
package/dist/seo/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { StoreContext } from '../types.js';
|
|
|
2
2
|
import type { SeoModule } from './types.js';
|
|
3
3
|
export declare function createSeoModule(ctx: StoreContext): SeoModule;
|
|
4
4
|
export type { AiSummaryInput, LlmsTxtEntryInput, } from './ai.js';
|
|
5
|
+
export type { AvailabilityForSeo, SchemaOrgAvailability } from './availability.js';
|
|
6
|
+
export { openGraphAvailability, schemaOrgAvailability } from './availability.js';
|
|
5
7
|
export type { CmsMetaTagsInput, CmsSeoExtras, CollectionMetaTagsInput, CollectionSeoExtras, HreflangLinkTag, MetaTagsEntityInput, MetaTagsResult, OpenGraphTag, ProductMetaTagsInput, ProductSeoExtras, TwitterTag, } from './meta-tags.js';
|
|
6
8
|
export type { RawCmsSeo, RawCollectionSeo, RawProductMetadata } from './metadata-parser.js';
|
|
7
9
|
export { parseCmsItemMetadata, parseCollectionMetadata, parseProductMetadata, robotsFromFlags, } from './metadata-parser.js';
|
package/dist/seo/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/seo/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/seo/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQhD,OAAO,KAAK,EAAkB,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5D,wBAAgB,eAAe,CAAC,GAAG,EAAE,YAAY,GAAG,SAAS,CA0E5D;AAED,YAAY,EACV,cAAc,EACd,iBAAiB,GAClB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACjF,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,oBAAoB,EACpB,gBAAgB,EAChB,UAAU,GACX,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC5F,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,YAAY,EACZ,uBAAuB,EACvB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EACV,yBAAyB,EACzB,wBAAwB,EACxB,yBAAyB,EACzB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,MAAM,EACN,YAAY,EACZ,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,4BAA4B,EAC5B,gBAAgB,EAChB,2BAA2B,EAC3B,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,OAAO,EACP,SAAS,EACT,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/seo/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createContextAssetUrlResolver } from '../media/urls.js';
|
|
|
2
2
|
import { aiSummaryFor, llmsTxtEntryFor } from './ai.js';
|
|
3
3
|
import { alternatesFor } from './alternates.js';
|
|
4
4
|
import { createArtifactUrls, reportNotFound } from './artifacts.js';
|
|
5
|
+
import { schemaOrgAvailability } from './availability.js';
|
|
5
6
|
import { canonicalFor } from './canonical.js';
|
|
6
7
|
import { metaTagsFor } from './meta-tags.js';
|
|
7
8
|
import { composePerBotDirectives } from './robots.js';
|
|
@@ -72,6 +73,7 @@ export function createSeoModule(ctx) {
|
|
|
72
73
|
xRobotsHeaders: [],
|
|
73
74
|
};
|
|
74
75
|
},
|
|
76
|
+
schemaOrgAvailability,
|
|
75
77
|
aiSummaryFor(entity) {
|
|
76
78
|
return aiSummaryFor(entity);
|
|
77
79
|
},
|
|
@@ -80,6 +82,7 @@ export function createSeoModule(ctx) {
|
|
|
80
82
|
},
|
|
81
83
|
};
|
|
82
84
|
}
|
|
85
|
+
export { openGraphAvailability, schemaOrgAvailability } from './availability.js';
|
|
83
86
|
export { parseCmsItemMetadata, parseCollectionMetadata, parseProductMetadata, robotsFromFlags, } from './metadata-parser.js';
|
|
84
87
|
export { DEFAULT_PRODUCT_PATH_SEGMENT, isUserFacingRoot, normalizeProductPathSegment, pickCanonicalRootIndex, } from './product-path.js';
|
|
85
88
|
export { buildUrl, readUrlStrategy } from './url-builder.js';
|
package/dist/seo/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/seo/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/seo/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-ld.d.ts","sourceRoot":"","sources":["../../src/seo/json-ld.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC5F,OAAO,KAAK,EAAoB,aAAa,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAuB1D,MAAM,WAAW,kBAAkB;IACjC,gFAAgF;IAChF,eAAe,EAAE,gBAAgB,CAAC;IAClC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACrC,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC9D;
|
|
1
|
+
{"version":3,"file":"json-ld.d.ts","sourceRoot":"","sources":["../../src/seo/json-ld.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC5F,OAAO,KAAK,EAAoB,aAAa,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAuB1D,MAAM,WAAW,kBAAkB;IACjC,gFAAgF;IAChF,eAAe,EAAE,gBAAgB,CAAC;IAClC,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACrC,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC9D;AAYD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiFvF;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,iBAAiB,CAAC;IACvB,OAAO,EAAE,aAAa,CAAC;IACvB,QAAQ,EAAE,aAAa,CAAC,uBAAuB,CAAC,CAAC;CAClD;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkB7F;AAqCD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,gFAAgF;IAChF,eAAe,EAAE,gBAAgB,CAAC;CACnC;AAQD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWvF;AAED,4DAA4D;AAC5D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWhF;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUtF"}
|
package/dist/seo/json-ld.js
CHANGED
|
@@ -24,6 +24,15 @@ function pickImageUrls(resolveAssetUrl, ...assets) {
|
|
|
24
24
|
}
|
|
25
25
|
return urls;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* The two `ItemAvailability` values `schemaOrgAvailability` returns for an
|
|
29
|
+
* offer that cannot be bought outright today — the only ones a future
|
|
30
|
+
* `availabilityStarts` is consistent with. `InStock` is deliberately absent.
|
|
31
|
+
*/
|
|
32
|
+
const NOT_PURCHASABLE_NOW = new Set([
|
|
33
|
+
'https://schema.org/PreOrder',
|
|
34
|
+
'https://schema.org/OutOfStock',
|
|
35
|
+
]);
|
|
27
36
|
export function composeProductJsonLd(input) {
|
|
28
37
|
const { product, metadata, canonical, title, description, extras, reviews } = input;
|
|
29
38
|
const out = {
|
|
@@ -50,9 +59,33 @@ export function composeProductJsonLd(input) {
|
|
|
50
59
|
};
|
|
51
60
|
if (extras.availability) {
|
|
52
61
|
// schema.org expects an ItemAvailability URL, but text is also widely
|
|
53
|
-
// accepted by validators. Pass-through whatever the storefront provides
|
|
62
|
+
// accepted by validators. Pass-through whatever the storefront provides —
|
|
63
|
+
// `schemaOrgAvailability(variant)` (`./availability.js`) is what produces
|
|
64
|
+
// the URL, and it is the only way `PreOrder` ever gets emitted: a
|
|
65
|
+
// pre-order with nothing on hand reads 0 stock, so anything derived from
|
|
66
|
+
// `stockLevel` alone would say `OutOfStock` and hide a product the
|
|
67
|
+
// merchant is actively taking orders for.
|
|
54
68
|
offer.availability = extras.availability;
|
|
55
69
|
}
|
|
70
|
+
if (extras.availabilityStarts && NOT_PURCHASABLE_NOW.has(extras.availability ?? '')) {
|
|
71
|
+
// `https://schema.org/availabilityStarts` — "The beginning of the
|
|
72
|
+
// availability of the product or service included in the offer", a
|
|
73
|
+
// property of `Offer` (verified against schema.org). It is the date half
|
|
74
|
+
// of the two merchant states: a `PreOrder` with no availability date is
|
|
75
|
+
// an item-level feed error, and a coming-soon item (mapped to
|
|
76
|
+
// `OutOfStock`, which says nothing about WHEN) has no other way to say
|
|
77
|
+
// it is arriving.
|
|
78
|
+
//
|
|
79
|
+
// Only beside an offer that is NOT purchasable now. A pre-order with stock
|
|
80
|
+
// on hand is `InStock` — it ships today — and "in stock, available from
|
|
81
|
+
// 12 March" contradicts itself; a storefront passing
|
|
82
|
+
// `variant.availability?.availableFrom` unconditionally must not produce
|
|
83
|
+
// that. A hand-written availability string is not recognised either: the
|
|
84
|
+
// SDK cannot tell whether that offer is purchasable now. Nothing is
|
|
85
|
+
// emitted without a date, so an offer from a storefront that predates this
|
|
86
|
+
// field is byte-identical.
|
|
87
|
+
offer.availabilityStarts = extras.availabilityStarts;
|
|
88
|
+
}
|
|
56
89
|
if (extras.condition) {
|
|
57
90
|
offer.itemCondition = `https://schema.org/${extras.condition === 'new'
|
|
58
91
|
? 'NewCondition'
|