@usethrottle/catalog 1.1.0 → 1.3.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/CHANGELOG.md +28 -0
- package/README.md +135 -24
- package/dist/admin.cjs +16 -16
- package/dist/admin.d.cts +6 -2
- package/dist/admin.d.ts +6 -2
- package/dist/admin.js +1 -1
- package/dist/{catalog-error-s1BINNkt.d.cts → catalog-error-BOaSKgY3.d.cts} +12 -2
- package/dist/{catalog-error-C_zLOtYA.d.ts → catalog-error-CSoPS0-d.d.ts} +12 -2
- package/dist/{chunk-4ORXUW2U.cjs → chunk-2YQNMBDI.cjs} +119 -33
- package/dist/{chunk-JK2UY4CD.js → chunk-3DLH56OX.js} +99 -13
- package/dist/chunk-CADIHOIR.js +496 -0
- package/dist/chunk-GU63WFXI.cjs +496 -0
- package/dist/{client-c2F-eCaL.d.ts → client-6j1Iz-iJ.d.cts} +2 -9
- package/dist/{client-BAoq6jmM.d.cts → client-B3mL2-xJ.d.ts} +2 -9
- package/dist/{contract-types-DhiThMEr.d.cts → contract-types-BRyonOYH.d.cts} +23 -21
- package/dist/{contract-types-DhiThMEr.d.ts → contract-types-BRyonOYH.d.ts} +23 -21
- package/dist/index.cjs +24 -2
- package/dist/index.d.cts +13 -7
- package/dist/index.d.ts +13 -7
- package/dist/index.js +25 -3
- package/dist/react-extras.cjs +42 -0
- package/dist/react-extras.d.cts +23 -0
- package/dist/react-extras.d.ts +23 -0
- package/dist/react-extras.js +42 -0
- package/dist/react.cjs +286 -491
- package/dist/react.d.cts +44 -38
- package/dist/react.d.ts +44 -38
- package/dist/react.js +289 -494
- package/dist/server.cjs +19 -14
- package/dist/server.d.cts +4 -3
- package/dist/server.d.ts +4 -3
- package/dist/server.js +7 -2
- package/dist/{types-DsjoG8ce.d.cts → types-BfveENg1.d.ts} +76 -3
- package/dist/{types-xQLID-4j.d.ts → types-D0PywKnN.d.cts} +76 -3
- package/dist/url.d.cts +2 -1
- package/dist/url.d.ts +2 -1
- package/dist/use-query-CR7r5tam.d.ts +40 -0
- package/dist/use-query-UWf6Pi5g.d.cts +40 -0
- package/dist/version-ev3p03v2.d.cts +8 -0
- package/dist/version-ev3p03v2.d.ts +8 -0
- package/package.json +13 -2
package/dist/server.cjs
CHANGED
|
@@ -9,14 +9,14 @@
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
var
|
|
12
|
+
var _chunk2YQNMBDIcjs = require('./chunk-2YQNMBDI.cjs');
|
|
13
13
|
require('./chunk-ETV4XYOV.cjs');
|
|
14
14
|
|
|
15
15
|
// src/server/tags.ts
|
|
16
16
|
function catalogTags(route, handle) {
|
|
17
|
-
const tags = [
|
|
18
|
-
if (handle !== void 0) tags.push(`${
|
|
19
|
-
return tags.filter((tag) => tag.length <=
|
|
17
|
+
const tags = [_chunk2YQNMBDIcjs.CACHE_TAG, `${_chunk2YQNMBDIcjs.CACHE_TAG}:${route}`];
|
|
18
|
+
if (handle !== void 0) tags.push(`${_chunk2YQNMBDIcjs.CACHE_TAG}:${route}:${handle}`);
|
|
19
|
+
return tags.filter((tag) => tag.length <= _chunk2YQNMBDIcjs.TAG_MAX_CHARS);
|
|
20
20
|
}
|
|
21
21
|
function decode(segment) {
|
|
22
22
|
try {
|
|
@@ -72,10 +72,15 @@ function serverInit(url, init, storefront, revalidate, extraTags) {
|
|
|
72
72
|
return { ...rest, next: { revalidate, tags: [...tags, ...extraTags] } };
|
|
73
73
|
}
|
|
74
74
|
function createServerCatalogClient(options) {
|
|
75
|
-
const {
|
|
76
|
-
|
|
75
|
+
const {
|
|
76
|
+
next,
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- dropped on purpose (P8-R21)
|
|
78
|
+
keyInQuery: _ignored,
|
|
79
|
+
...rest
|
|
80
|
+
} = options;
|
|
81
|
+
const revalidate = _nullishCoalesce(_optionalChain([next, 'optionalAccess', _ => _.revalidate]), () => ( _chunk2YQNMBDIcjs.DEFAULT_REVALIDATE_S));
|
|
77
82
|
const extraTags = _nullishCoalesce(_optionalChain([next, 'optionalAccess', _2 => _2.tags]), () => ( []));
|
|
78
|
-
const storefront = `${(_nullishCoalesce(rest.baseUrl, () => (
|
|
83
|
+
const storefront = `${(_nullishCoalesce(rest.baseUrl, () => ( _chunk2YQNMBDIcjs.DEFAULT_BASE_URL))).replace(/\/+$/u, "")}/v1/storefront/`;
|
|
79
84
|
const base = rest.fetch;
|
|
80
85
|
const serverFetch = (input, init = {}) => {
|
|
81
86
|
const out = serverInit(
|
|
@@ -87,7 +92,7 @@ function createServerCatalogClient(options) {
|
|
|
87
92
|
);
|
|
88
93
|
return base !== void 0 ? base(input, out) : globalThis.fetch(input, out);
|
|
89
94
|
};
|
|
90
|
-
return
|
|
95
|
+
return _chunk2YQNMBDIcjs.createCatalogClient.call(void 0, {
|
|
91
96
|
...rest,
|
|
92
97
|
fetch: serverFetch
|
|
93
98
|
});
|
|
@@ -107,16 +112,16 @@ async function syncCatalogGeneration(input) {
|
|
|
107
112
|
|
|
108
113
|
// src/server/paging.ts
|
|
109
114
|
function bounds(opts) {
|
|
110
|
-
const pageSize = _nullishCoalesce(opts.pageSize, () => (
|
|
111
|
-
const max = _nullishCoalesce(opts.max, () => (
|
|
112
|
-
if (!Number.isInteger(pageSize) || pageSize < 1 || pageSize >
|
|
115
|
+
const pageSize = _nullishCoalesce(opts.pageSize, () => ( _chunk2YQNMBDIcjs.LIST_PAGE_SIZE));
|
|
116
|
+
const max = _nullishCoalesce(opts.max, () => ( _chunk2YQNMBDIcjs.LIST_MAX_HANDLES));
|
|
117
|
+
if (!Number.isInteger(pageSize) || pageSize < 1 || pageSize > _chunk2YQNMBDIcjs.LIST_PAGE_SIZE)
|
|
113
118
|
throw invalid("pageSize must be a whole number from 1 to 100.");
|
|
114
119
|
if (!Number.isInteger(max) || max < 0)
|
|
115
120
|
throw invalid("max must be a whole number of 0 or more.");
|
|
116
121
|
return { pageSize, max };
|
|
117
122
|
}
|
|
118
123
|
function invalid(message) {
|
|
119
|
-
return new (0,
|
|
124
|
+
return new (0, _chunk2YQNMBDIcjs.CatalogError)({
|
|
120
125
|
code: "INVALID_REQUEST",
|
|
121
126
|
message,
|
|
122
127
|
statusCode: 0,
|
|
@@ -186,7 +191,7 @@ function listAllCollectionHandles(client, opts = {}) {
|
|
|
186
191
|
}
|
|
187
192
|
async function listAllCategoryHandles(client, opts = {}) {
|
|
188
193
|
const { categories } = await client.categories.tree({
|
|
189
|
-
depth:
|
|
194
|
+
depth: _chunk2YQNMBDIcjs.CATEGORY_TREE_MAX_DEPTH,
|
|
190
195
|
...call(opts.signal)
|
|
191
196
|
});
|
|
192
197
|
const out = [];
|
|
@@ -208,4 +213,4 @@ async function listAllCategoryHandles(client, opts = {}) {
|
|
|
208
213
|
|
|
209
214
|
|
|
210
215
|
|
|
211
|
-
exports.SDK_VERSION =
|
|
216
|
+
exports.SDK_VERSION = _chunk2YQNMBDIcjs.SDK_VERSION; exports.catalogTags = catalogTags; exports.createServerCatalogClient = createServerCatalogClient; exports.listAllCategoryHandles = listAllCategoryHandles; exports.listAllCollectionHandles = listAllCollectionHandles; exports.listAllProductHandles = listAllProductHandles; exports.staticProductParams = staticProductParams; exports.syncCatalogGeneration = syncCatalogGeneration;
|
package/dist/server.d.cts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
export { S as SDK_VERSION } from './version-ev3p03v2.cjs';
|
|
1
2
|
import { CatalogClient } from './index.cjs';
|
|
2
|
-
export { S as SDK_VERSION } from './client-BAoq6jmM.cjs';
|
|
3
3
|
import { CatalogClientOptions, NextFetchOptions } from './index.cjs';
|
|
4
|
-
import '
|
|
4
|
+
import '@usethrottle/money';
|
|
5
|
+
import './contract-types-BRyonOYH.cjs';
|
|
5
6
|
|
|
6
|
-
type ServerCatalogClientOptions = CatalogClientOptions & {
|
|
7
|
+
type ServerCatalogClientOptions = Omit<CatalogClientOptions, 'keyInQuery'> & {
|
|
7
8
|
/** `revalidate` defaults to 60 seconds; `tags` are appended to the route's own. */
|
|
8
9
|
next?: NextFetchOptions;
|
|
9
10
|
};
|
package/dist/server.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
export { S as SDK_VERSION } from './version-ev3p03v2.js';
|
|
1
2
|
import { CatalogClient } from './index.js';
|
|
2
|
-
export { S as SDK_VERSION } from './client-c2F-eCaL.js';
|
|
3
3
|
import { CatalogClientOptions, NextFetchOptions } from './index.js';
|
|
4
|
-
import '
|
|
4
|
+
import '@usethrottle/money';
|
|
5
|
+
import './contract-types-BRyonOYH.js';
|
|
5
6
|
|
|
6
|
-
type ServerCatalogClientOptions = CatalogClientOptions & {
|
|
7
|
+
type ServerCatalogClientOptions = Omit<CatalogClientOptions, 'keyInQuery'> & {
|
|
7
8
|
/** `revalidate` defaults to 60 seconds; `tags` are appended to the route's own. */
|
|
8
9
|
next?: NextFetchOptions;
|
|
9
10
|
};
|
package/dist/server.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
SDK_VERSION,
|
|
10
10
|
TAG_MAX_CHARS,
|
|
11
11
|
createCatalogClient
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-3DLH56OX.js";
|
|
13
13
|
import "./chunk-PKBMQBKP.js";
|
|
14
14
|
|
|
15
15
|
// src/server/tags.ts
|
|
@@ -72,7 +72,12 @@ function serverInit(url, init, storefront, revalidate, extraTags) {
|
|
|
72
72
|
return { ...rest, next: { revalidate, tags: [...tags, ...extraTags] } };
|
|
73
73
|
}
|
|
74
74
|
function createServerCatalogClient(options) {
|
|
75
|
-
const {
|
|
75
|
+
const {
|
|
76
|
+
next,
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- dropped on purpose (P8-R21)
|
|
78
|
+
keyInQuery: _ignored,
|
|
79
|
+
...rest
|
|
80
|
+
} = options;
|
|
76
81
|
const revalidate = next?.revalidate ?? DEFAULT_REVALIDATE_S;
|
|
77
82
|
const extraTags = next?.tags ?? [];
|
|
78
83
|
const storefront = `${(rest.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/u, "")}/v1/storefront/`;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CurrencyCode } from '@usethrottle/money';
|
|
2
|
+
import { C as CartCheckAnswer, h as CartCreateRequest, g as CartCreateAnswer, b as StorefrontListAnswer, e as StorefrontProductAnswer, p as StorefrontRelatedAnswer, o as StorefrontFilterValuesAnswer, j as StorefrontCategoriesAnswer, k as StorefrontCategoryAnswer, s as StorefrontTagsAnswer, m as StorefrontCollectionsAnswer, l as StorefrontCollectionAnswer, r as StorefrontSuggestAnswer, n as StorefrontConfigAnswer, q as StorefrontReviewsAnswer, d as ReviewEligibilityAnswer, a as ReviewSubmitInput, R as ReviewSubmitAnswer } from './contract-types-BRyonOYH.js';
|
|
2
3
|
|
|
3
4
|
type QueryPairs = [string, string][];
|
|
4
5
|
|
|
@@ -28,6 +29,13 @@ type CatalogClientOptions = {
|
|
|
28
29
|
maxWaitSeconds: number;
|
|
29
30
|
};
|
|
30
31
|
headers?: Record<string, string>;
|
|
32
|
+
/**
|
|
33
|
+
* Send the publishable key as `?key=` on a GET instead of the
|
|
34
|
+
* `x-catalog-key` header, so a browser read needs no CORS preflight
|
|
35
|
+
* (P8-R21). Default `false`: the header is always sent. A POST always sends
|
|
36
|
+
* the header.
|
|
37
|
+
*/
|
|
38
|
+
keyInQuery?: boolean;
|
|
31
39
|
};
|
|
32
40
|
/** Next.js's `fetch` cache options; the SDK never imports Next. */
|
|
33
41
|
type NextFetchOptions = {
|
|
@@ -64,6 +72,13 @@ type RequestSpec = {
|
|
|
64
72
|
/** `false` turns off the one indexing retry for this request (P6-R10). */
|
|
65
73
|
indexingRetry?: boolean;
|
|
66
74
|
ifNoneMatch?: string;
|
|
75
|
+
/**
|
|
76
|
+
* The answer is the same for every shopper (P8-R22): this implies
|
|
77
|
+
* `customerToken: 'none'` (no token is read or sent), the cache entry is
|
|
78
|
+
* the guest partition, and with `keyInQuery` on the request sends no
|
|
79
|
+
* `If-None-Match`, so its only header is `accept`.
|
|
80
|
+
*/
|
|
81
|
+
tokenFree?: boolean;
|
|
67
82
|
/**
|
|
68
83
|
* Query context the transport appends to a GET: `'priced'` adds `currency`
|
|
69
84
|
* and `locale`, `'locale'` adds `locale` only (call options over client
|
|
@@ -127,7 +142,7 @@ type ThrottleLine = {
|
|
|
127
142
|
/** Throttle's cart as a cart session answers it; other keys pass through. */
|
|
128
143
|
type ThrottleCart = {
|
|
129
144
|
cartId: string;
|
|
130
|
-
currency:
|
|
145
|
+
currency: CurrencyCode;
|
|
131
146
|
subtotal: number;
|
|
132
147
|
total: number;
|
|
133
148
|
unitCount: number;
|
|
@@ -184,6 +199,32 @@ type CartCheckout = {
|
|
|
184
199
|
};
|
|
185
200
|
/** Per-call options of a cart-session call. */
|
|
186
201
|
type SessionCallOptions = Pick<CallOptions, 'signal' | 'timeoutMs'>;
|
|
202
|
+
/**
|
|
203
|
+
* What an absorb reports besides the cart (MC2-R39): lines of the other cart
|
|
204
|
+
* that could not move (no price in this cart's currency, or a custom line in
|
|
205
|
+
* another currency), a discount code this cart's currency refuses, and lines
|
|
206
|
+
* whose prices are unconfirmed until the next refresh or checkout.
|
|
207
|
+
*/
|
|
208
|
+
type CartWarning = {
|
|
209
|
+
code: 'lines_removed';
|
|
210
|
+
lines: {
|
|
211
|
+
referenceId: string | null;
|
|
212
|
+
code: string;
|
|
213
|
+
}[];
|
|
214
|
+
message: string;
|
|
215
|
+
} | {
|
|
216
|
+
code: 'discount_dropped';
|
|
217
|
+
discountCode: string;
|
|
218
|
+
message: string;
|
|
219
|
+
} | {
|
|
220
|
+
code: 'lines_stale';
|
|
221
|
+
message: string;
|
|
222
|
+
};
|
|
223
|
+
/** `CartSession.absorb()`'s answer: this session's cart after the move. */
|
|
224
|
+
type CartAbsorb = {
|
|
225
|
+
cart: ThrottleCart;
|
|
226
|
+
warnings: CartWarning[];
|
|
227
|
+
};
|
|
187
228
|
/** One Throttle cart session, addressed by its opaque id. */
|
|
188
229
|
type CartSession = {
|
|
189
230
|
readonly id: string;
|
|
@@ -198,6 +239,15 @@ type CartSession = {
|
|
|
198
239
|
refresh(call?: SessionCallOptions): Promise<CartSessionSnapshot>;
|
|
199
240
|
/** Refuses non-http(s) URLs before a request, and never returns a non-http(s) `checkoutUrl`. */
|
|
200
241
|
checkout(input: CartCheckoutInput, call?: SessionCallOptions): Promise<CartCheckout>;
|
|
242
|
+
/**
|
|
243
|
+
* Moves the cart of session `fromSessionId` into this session's cart, in
|
|
244
|
+
* this cart's currency, and closes the other one (`abandoned`, reason
|
|
245
|
+
* `merged`; a merged cart refuses writes with `409 cart_not_open`).
|
|
246
|
+
* Throttle never creates a cart or changes a currency or an owner here: a
|
|
247
|
+
* customer's cart only moves into that customer's cart (`403
|
|
248
|
+
* cart_owner_mismatch`).
|
|
249
|
+
*/
|
|
250
|
+
absorb(fromSessionId: string, call?: SessionCallOptions): Promise<CartAbsorb>;
|
|
201
251
|
};
|
|
202
252
|
type ProductsNamespace = {
|
|
203
253
|
list(query?: ProductsQuery, call?: CallOptions): Promise<StorefrontListAnswer>;
|
|
@@ -272,5 +322,28 @@ type CatalogNamespaces = {
|
|
|
272
322
|
readonly reviews: ReviewsNamespace;
|
|
273
323
|
readonly carts: CartsNamespace;
|
|
274
324
|
};
|
|
325
|
+
/** The customer's open cart as Throttle answers it (P8-R14). */
|
|
326
|
+
type OpenCartRef = {
|
|
327
|
+
sessionId: string;
|
|
328
|
+
cartId: string;
|
|
329
|
+
currency: CurrencyCode;
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* Where a signed-in customer's cart is found (P8-R14). Structural: the SDK
|
|
333
|
+
* never holds the Throttle `pk_` and never imports `@usethrottle/auth`.
|
|
334
|
+
* `getOpenCart` answers the customer's most recently updated open cart in
|
|
335
|
+
* `currency`, or `null`; `whenClaimSettled` resolves once the sign-in's
|
|
336
|
+
* guest-cart claim is done, so the merged lines can be read.
|
|
337
|
+
* Resuming needs a currency: the hook's `currency` option or the client's;
|
|
338
|
+
* without one `useCart` makes no lookup. A write to a cart another device
|
|
339
|
+
* merged is refused (`409 cart_not_open`, never reopened), and `useCart`
|
|
340
|
+
* then looks the customer's cart up.
|
|
341
|
+
*/
|
|
342
|
+
type CustomerCartSource = {
|
|
343
|
+
getOpenCart(input: {
|
|
344
|
+
currency: string;
|
|
345
|
+
}): Promise<OpenCartRef | null>;
|
|
346
|
+
whenClaimSettled(): Promise<void>;
|
|
347
|
+
};
|
|
275
348
|
|
|
276
|
-
export type {
|
|
349
|
+
export type { CustomerCartSource as C, FieldsOption as F, NextFetchOptions as N, OpenCartRef as O, ProductsQuery as P, Redirect as R, SessionCallOptions as S, ThrottleCart as T, CategoryTreeDepth as a, CartWarning as b, CallOptions as c, CartAbsorb as d, CartCheckout as e, CartCheckoutInput as f, CartSession as g, CartSessionBranding as h, CartSessionDetail as i, CartSessionSnapshot as j, CartsNamespace as k, CatalogClientOptions as l, CatalogHttpCache as m, CatalogHttpCacheEntry as n, CatalogNamespaces as o, CategoriesNamespace as p, CollectionsNamespace as q, CustomerTokenSource as r, FiltersNamespace as s, ProductsNamespace as t, ReviewsNamespace as u, StorefrontSort as v, TagsNamespace as w, ThrottleLine as x, RequestSpec as y };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CurrencyCode } from '@usethrottle/money';
|
|
2
|
+
import { C as CartCheckAnswer, h as CartCreateRequest, g as CartCreateAnswer, b as StorefrontListAnswer, e as StorefrontProductAnswer, p as StorefrontRelatedAnswer, o as StorefrontFilterValuesAnswer, j as StorefrontCategoriesAnswer, k as StorefrontCategoryAnswer, s as StorefrontTagsAnswer, m as StorefrontCollectionsAnswer, l as StorefrontCollectionAnswer, r as StorefrontSuggestAnswer, n as StorefrontConfigAnswer, q as StorefrontReviewsAnswer, d as ReviewEligibilityAnswer, a as ReviewSubmitInput, R as ReviewSubmitAnswer } from './contract-types-BRyonOYH.cjs';
|
|
2
3
|
|
|
3
4
|
type QueryPairs = [string, string][];
|
|
4
5
|
|
|
@@ -28,6 +29,13 @@ type CatalogClientOptions = {
|
|
|
28
29
|
maxWaitSeconds: number;
|
|
29
30
|
};
|
|
30
31
|
headers?: Record<string, string>;
|
|
32
|
+
/**
|
|
33
|
+
* Send the publishable key as `?key=` on a GET instead of the
|
|
34
|
+
* `x-catalog-key` header, so a browser read needs no CORS preflight
|
|
35
|
+
* (P8-R21). Default `false`: the header is always sent. A POST always sends
|
|
36
|
+
* the header.
|
|
37
|
+
*/
|
|
38
|
+
keyInQuery?: boolean;
|
|
31
39
|
};
|
|
32
40
|
/** Next.js's `fetch` cache options; the SDK never imports Next. */
|
|
33
41
|
type NextFetchOptions = {
|
|
@@ -64,6 +72,13 @@ type RequestSpec = {
|
|
|
64
72
|
/** `false` turns off the one indexing retry for this request (P6-R10). */
|
|
65
73
|
indexingRetry?: boolean;
|
|
66
74
|
ifNoneMatch?: string;
|
|
75
|
+
/**
|
|
76
|
+
* The answer is the same for every shopper (P8-R22): this implies
|
|
77
|
+
* `customerToken: 'none'` (no token is read or sent), the cache entry is
|
|
78
|
+
* the guest partition, and with `keyInQuery` on the request sends no
|
|
79
|
+
* `If-None-Match`, so its only header is `accept`.
|
|
80
|
+
*/
|
|
81
|
+
tokenFree?: boolean;
|
|
67
82
|
/**
|
|
68
83
|
* Query context the transport appends to a GET: `'priced'` adds `currency`
|
|
69
84
|
* and `locale`, `'locale'` adds `locale` only (call options over client
|
|
@@ -127,7 +142,7 @@ type ThrottleLine = {
|
|
|
127
142
|
/** Throttle's cart as a cart session answers it; other keys pass through. */
|
|
128
143
|
type ThrottleCart = {
|
|
129
144
|
cartId: string;
|
|
130
|
-
currency:
|
|
145
|
+
currency: CurrencyCode;
|
|
131
146
|
subtotal: number;
|
|
132
147
|
total: number;
|
|
133
148
|
unitCount: number;
|
|
@@ -184,6 +199,32 @@ type CartCheckout = {
|
|
|
184
199
|
};
|
|
185
200
|
/** Per-call options of a cart-session call. */
|
|
186
201
|
type SessionCallOptions = Pick<CallOptions, 'signal' | 'timeoutMs'>;
|
|
202
|
+
/**
|
|
203
|
+
* What an absorb reports besides the cart (MC2-R39): lines of the other cart
|
|
204
|
+
* that could not move (no price in this cart's currency, or a custom line in
|
|
205
|
+
* another currency), a discount code this cart's currency refuses, and lines
|
|
206
|
+
* whose prices are unconfirmed until the next refresh or checkout.
|
|
207
|
+
*/
|
|
208
|
+
type CartWarning = {
|
|
209
|
+
code: 'lines_removed';
|
|
210
|
+
lines: {
|
|
211
|
+
referenceId: string | null;
|
|
212
|
+
code: string;
|
|
213
|
+
}[];
|
|
214
|
+
message: string;
|
|
215
|
+
} | {
|
|
216
|
+
code: 'discount_dropped';
|
|
217
|
+
discountCode: string;
|
|
218
|
+
message: string;
|
|
219
|
+
} | {
|
|
220
|
+
code: 'lines_stale';
|
|
221
|
+
message: string;
|
|
222
|
+
};
|
|
223
|
+
/** `CartSession.absorb()`'s answer: this session's cart after the move. */
|
|
224
|
+
type CartAbsorb = {
|
|
225
|
+
cart: ThrottleCart;
|
|
226
|
+
warnings: CartWarning[];
|
|
227
|
+
};
|
|
187
228
|
/** One Throttle cart session, addressed by its opaque id. */
|
|
188
229
|
type CartSession = {
|
|
189
230
|
readonly id: string;
|
|
@@ -198,6 +239,15 @@ type CartSession = {
|
|
|
198
239
|
refresh(call?: SessionCallOptions): Promise<CartSessionSnapshot>;
|
|
199
240
|
/** Refuses non-http(s) URLs before a request, and never returns a non-http(s) `checkoutUrl`. */
|
|
200
241
|
checkout(input: CartCheckoutInput, call?: SessionCallOptions): Promise<CartCheckout>;
|
|
242
|
+
/**
|
|
243
|
+
* Moves the cart of session `fromSessionId` into this session's cart, in
|
|
244
|
+
* this cart's currency, and closes the other one (`abandoned`, reason
|
|
245
|
+
* `merged`; a merged cart refuses writes with `409 cart_not_open`).
|
|
246
|
+
* Throttle never creates a cart or changes a currency or an owner here: a
|
|
247
|
+
* customer's cart only moves into that customer's cart (`403
|
|
248
|
+
* cart_owner_mismatch`).
|
|
249
|
+
*/
|
|
250
|
+
absorb(fromSessionId: string, call?: SessionCallOptions): Promise<CartAbsorb>;
|
|
201
251
|
};
|
|
202
252
|
type ProductsNamespace = {
|
|
203
253
|
list(query?: ProductsQuery, call?: CallOptions): Promise<StorefrontListAnswer>;
|
|
@@ -272,5 +322,28 @@ type CatalogNamespaces = {
|
|
|
272
322
|
readonly reviews: ReviewsNamespace;
|
|
273
323
|
readonly carts: CartsNamespace;
|
|
274
324
|
};
|
|
325
|
+
/** The customer's open cart as Throttle answers it (P8-R14). */
|
|
326
|
+
type OpenCartRef = {
|
|
327
|
+
sessionId: string;
|
|
328
|
+
cartId: string;
|
|
329
|
+
currency: CurrencyCode;
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* Where a signed-in customer's cart is found (P8-R14). Structural: the SDK
|
|
333
|
+
* never holds the Throttle `pk_` and never imports `@usethrottle/auth`.
|
|
334
|
+
* `getOpenCart` answers the customer's most recently updated open cart in
|
|
335
|
+
* `currency`, or `null`; `whenClaimSettled` resolves once the sign-in's
|
|
336
|
+
* guest-cart claim is done, so the merged lines can be read.
|
|
337
|
+
* Resuming needs a currency: the hook's `currency` option or the client's;
|
|
338
|
+
* without one `useCart` makes no lookup. A write to a cart another device
|
|
339
|
+
* merged is refused (`409 cart_not_open`, never reopened), and `useCart`
|
|
340
|
+
* then looks the customer's cart up.
|
|
341
|
+
*/
|
|
342
|
+
type CustomerCartSource = {
|
|
343
|
+
getOpenCart(input: {
|
|
344
|
+
currency: string;
|
|
345
|
+
}): Promise<OpenCartRef | null>;
|
|
346
|
+
whenClaimSettled(): Promise<void>;
|
|
347
|
+
};
|
|
275
348
|
|
|
276
|
-
export type {
|
|
349
|
+
export type { CustomerCartSource as C, FieldsOption as F, NextFetchOptions as N, OpenCartRef as O, ProductsQuery as P, Redirect as R, SessionCallOptions as S, ThrottleCart as T, CategoryTreeDepth as a, CartWarning as b, CallOptions as c, CartAbsorb as d, CartCheckout as e, CartCheckoutInput as f, CartSession as g, CartSessionBranding as h, CartSessionDetail as i, CartSessionSnapshot as j, CartsNamespace as k, CatalogClientOptions as l, CatalogHttpCache as m, CatalogHttpCacheEntry as n, CatalogNamespaces as o, CategoriesNamespace as p, CollectionsNamespace as q, CustomerTokenSource as r, FiltersNamespace as s, ProductsNamespace as t, ReviewsNamespace as u, StorefrontSort as v, TagsNamespace as w, ThrottleLine as x, RequestSpec as y };
|
package/dist/url.d.cts
CHANGED
package/dist/url.d.ts
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { b as CatalogError } from './catalog-error-CSoPS0-d.js';
|
|
2
|
+
|
|
3
|
+
type QueryResult<T> = {
|
|
4
|
+
data: T | undefined;
|
|
5
|
+
error: CatalogError | undefined;
|
|
6
|
+
/** No data and no error yet, and the hook is enabled. */
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
/** A request for this key is in flight (first load or revalidation). */
|
|
9
|
+
isValidating: boolean;
|
|
10
|
+
/** The params object `data` answers (the one the key was built from); the params asked for while `data` is undefined. */
|
|
11
|
+
dataFor: unknown;
|
|
12
|
+
/** `data` is the last answer of an earlier key, shown while this one loads (`keepPreviousData`). */
|
|
13
|
+
isPreviousData: boolean;
|
|
14
|
+
/** `data` was not confirmed by the latest attempt: a revalidation failed, or a seed is still being revalidated. */
|
|
15
|
+
isStale: boolean;
|
|
16
|
+
/** Fetches again now (unless a rate-limit pause holds every read). Never rejects. */
|
|
17
|
+
refetch(): Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
type QueryOptions<T> = {
|
|
20
|
+
/** `false` makes no request; `data` stays `undefined`. */
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Shown at once (SSR hand-off). Treated as fetched at mount when the
|
|
24
|
+
* provider has no `customerKey`; under a signed-in customer it is
|
|
25
|
+
* revalidated at once, since a server render is usually anonymous (P6-R51).
|
|
26
|
+
*/
|
|
27
|
+
initialData?: T;
|
|
28
|
+
/** Cached data younger than this is not fetched again; default `STALE_MS`. */
|
|
29
|
+
staleTimeMs?: number;
|
|
30
|
+
/** Shows the last settled answer while another key loads or fails; never across a `customerKey` change. */
|
|
31
|
+
keepPreviousData?: boolean;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The cache key of a read: the route name and its canonical parameters.
|
|
35
|
+
* Hooks prefix it with the provider's `customerKey` (P6-R14).
|
|
36
|
+
*/
|
|
37
|
+
declare function catalogQueryKey(route: string, params: unknown): string;
|
|
38
|
+
|
|
39
|
+
export { catalogQueryKey as c };
|
|
40
|
+
export type { QueryOptions as Q, QueryResult as a };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { b as CatalogError } from './catalog-error-BOaSKgY3.cjs';
|
|
2
|
+
|
|
3
|
+
type QueryResult<T> = {
|
|
4
|
+
data: T | undefined;
|
|
5
|
+
error: CatalogError | undefined;
|
|
6
|
+
/** No data and no error yet, and the hook is enabled. */
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
/** A request for this key is in flight (first load or revalidation). */
|
|
9
|
+
isValidating: boolean;
|
|
10
|
+
/** The params object `data` answers (the one the key was built from); the params asked for while `data` is undefined. */
|
|
11
|
+
dataFor: unknown;
|
|
12
|
+
/** `data` is the last answer of an earlier key, shown while this one loads (`keepPreviousData`). */
|
|
13
|
+
isPreviousData: boolean;
|
|
14
|
+
/** `data` was not confirmed by the latest attempt: a revalidation failed, or a seed is still being revalidated. */
|
|
15
|
+
isStale: boolean;
|
|
16
|
+
/** Fetches again now (unless a rate-limit pause holds every read). Never rejects. */
|
|
17
|
+
refetch(): Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
type QueryOptions<T> = {
|
|
20
|
+
/** `false` makes no request; `data` stays `undefined`. */
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Shown at once (SSR hand-off). Treated as fetched at mount when the
|
|
24
|
+
* provider has no `customerKey`; under a signed-in customer it is
|
|
25
|
+
* revalidated at once, since a server render is usually anonymous (P6-R51).
|
|
26
|
+
*/
|
|
27
|
+
initialData?: T;
|
|
28
|
+
/** Cached data younger than this is not fetched again; default `STALE_MS`. */
|
|
29
|
+
staleTimeMs?: number;
|
|
30
|
+
/** Shows the last settled answer while another key loads or fails; never across a `customerKey` change. */
|
|
31
|
+
keepPreviousData?: boolean;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The cache key of a read: the route name and its canonical parameters.
|
|
35
|
+
* Hooks prefix it with the provider's `customerKey` (P6-R14).
|
|
36
|
+
*/
|
|
37
|
+
declare function catalogQueryKey(route: string, params: unknown): string;
|
|
38
|
+
|
|
39
|
+
export { catalogQueryKey as c };
|
|
40
|
+
export type { QueryOptions as Q, QueryResult as a };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The package version, baked in at build time (tsup `define`). Under the
|
|
3
|
+
* package's vitest it is `'0.0.0-test'`; elsewhere (root vitest, `tsc`) the
|
|
4
|
+
* global is absent and it reads `'0.0.0-dev'`. No JSON import ships.
|
|
5
|
+
*/
|
|
6
|
+
declare const SDK_VERSION: string;
|
|
7
|
+
|
|
8
|
+
export { SDK_VERSION as S };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The package version, baked in at build time (tsup `define`). Under the
|
|
3
|
+
* package's vitest it is `'0.0.0-test'`; elsewhere (root vitest, `tsc`) the
|
|
4
|
+
* global is absent and it reads `'0.0.0-dev'`. No JSON import ships.
|
|
5
|
+
*/
|
|
6
|
+
declare const SDK_VERSION: string;
|
|
7
|
+
|
|
8
|
+
export { SDK_VERSION as S };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usethrottle/catalog",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Storefront SDK for the Throttle Product Catalog: a typed client, React hooks, server helpers and URL helpers.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -36,6 +36,16 @@
|
|
|
36
36
|
"default": "./dist/react.cjs"
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
|
+
"./react/extras": {
|
|
40
|
+
"import": {
|
|
41
|
+
"types": "./dist/react-extras.d.ts",
|
|
42
|
+
"default": "./dist/react-extras.js"
|
|
43
|
+
},
|
|
44
|
+
"require": {
|
|
45
|
+
"types": "./dist/react-extras.d.cts",
|
|
46
|
+
"default": "./dist/react-extras.cjs"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
39
49
|
"./server": {
|
|
40
50
|
"import": {
|
|
41
51
|
"types": "./dist/server.d.ts",
|
|
@@ -78,7 +88,8 @@
|
|
|
78
88
|
"access": "public"
|
|
79
89
|
},
|
|
80
90
|
"dependencies": {
|
|
81
|
-
"@usethrottle/errors": "^1.1.0"
|
|
91
|
+
"@usethrottle/errors": "^1.1.0",
|
|
92
|
+
"@usethrottle/money": "^1.0.0"
|
|
82
93
|
},
|
|
83
94
|
"peerDependencies": {
|
|
84
95
|
"react": "^18.2.0 || ^19.0.0"
|