@usethrottle/catalog 1.2.0 → 1.4.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.
Files changed (45) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +111 -15
  3. package/dist/admin.cjs +16 -16
  4. package/dist/admin.d.cts +15 -2
  5. package/dist/admin.d.ts +15 -2
  6. package/dist/admin.js +1 -1
  7. package/dist/{catalog-error-yTBMAdCv.d.cts → catalog-error-BKN5hNWP.d.cts} +11 -1
  8. package/dist/{catalog-error-7DCsTyB2.d.ts → catalog-error-BnabMMEy.d.ts} +11 -1
  9. package/dist/{chunk-JNBKKAMP.js → chunk-3FX2HISB.js} +97 -2
  10. package/dist/{chunk-B2DYAHNR.cjs → chunk-J2GHGQY6.cjs} +334 -43
  11. package/dist/{chunk-TDMDOHD3.cjs → chunk-OKWXS3FD.cjs} +110 -15
  12. package/dist/chunk-PZ3SFYH4.cjs +192 -0
  13. package/dist/chunk-SN6STYPW.js +192 -0
  14. package/dist/{chunk-55G4ZTD5.js → chunk-VJHA7J7B.js} +315 -24
  15. package/dist/{client-Dm6I4nAZ.d.ts → client-B6CsU_v9.d.ts} +1 -1
  16. package/dist/{client-BrHJCyBP.d.cts → client-terkEl6u.d.cts} +1 -1
  17. package/dist/{contract-types-BPSzY_Co.d.cts → contract-types-D2-SSPM9.d.cts} +241 -11
  18. package/dist/{contract-types-BPSzY_Co.d.ts → contract-types-D2-SSPM9.d.ts} +241 -11
  19. package/dist/index.cjs +34 -2
  20. package/dist/index.d.cts +56 -7
  21. package/dist/index.d.ts +56 -7
  22. package/dist/index.js +35 -3
  23. package/dist/next.cjs +180 -0
  24. package/dist/next.d.cts +60 -0
  25. package/dist/next.d.ts +60 -0
  26. package/dist/next.js +180 -0
  27. package/dist/react-extras.cjs +27 -9
  28. package/dist/react-extras.d.cts +7 -4
  29. package/dist/react-extras.d.ts +7 -4
  30. package/dist/react-extras.js +20 -2
  31. package/dist/react.cjs +130 -54
  32. package/dist/react.d.cts +52 -11
  33. package/dist/react.d.ts +52 -11
  34. package/dist/react.js +112 -36
  35. package/dist/server.cjs +58 -66
  36. package/dist/server.d.cts +58 -10
  37. package/dist/server.d.ts +58 -10
  38. package/dist/server.js +52 -60
  39. package/dist/{types-BlYCKzB8.d.ts → types-jNpOwEUw.d.cts} +81 -8
  40. package/dist/{types-BTrqSprj.d.cts → types-z57bkjjB.d.ts} +81 -8
  41. package/dist/url.d.cts +2 -1
  42. package/dist/url.d.ts +2 -1
  43. package/dist/{use-query-QOEBuYlp.d.ts → use-query-COqRZJnC.d.ts} +1 -1
  44. package/dist/{use-query-BZgjxGPO.d.cts → use-query-H1xgL3_e.d.cts} +1 -1
  45. package/package.json +17 -2
package/dist/react.js CHANGED
@@ -10,19 +10,22 @@ import {
10
10
  useConfig,
11
11
  useCustomerKey,
12
12
  useFilterValues,
13
+ useGenerationWatch,
13
14
  useProduct,
14
15
  useProducts,
15
16
  useRelated,
16
17
  useReviews,
18
+ useStorefrontSettings,
17
19
  useSuggest
18
- } from "./chunk-JNBKKAMP.js";
20
+ } from "./chunk-3FX2HISB.js";
19
21
  import {
20
22
  CatalogError,
21
23
  RateLimitedError,
22
24
  SDK_VERSION,
23
25
  THROTTLE_CHECKOUT_URL,
26
+ formatMoney,
24
27
  isCatalogError
25
- } from "./chunk-55G4ZTD5.js";
28
+ } from "./chunk-VJHA7J7B.js";
26
29
  import "./chunk-PKBMQBKP.js";
27
30
 
28
31
  // src/react/use-cart.ts
@@ -99,7 +102,8 @@ var EMPTY = {
99
102
  cartUrl: null,
100
103
  status: "idle",
101
104
  error: void 0,
102
- pending: false
105
+ pending: false,
106
+ warnings: []
103
107
  };
104
108
  var ENDED = /* @__PURE__ */ new Set([
105
109
  "cart_session_expired",
@@ -132,6 +136,7 @@ function createController(home) {
132
136
  moving: void 0,
133
137
  unremoved: false,
134
138
  reads: /* @__PURE__ */ new Map(),
139
+ slots: /* @__PURE__ */ new Set(),
135
140
  abort: new AbortController(),
136
141
  writing: Promise.resolve(),
137
142
  tail: Promise.resolve()
@@ -168,7 +173,7 @@ function createController(home) {
168
173
  if (signal.aborted) throw error;
169
174
  }
170
175
  }
171
- async function find(signal, wantedCurrency) {
176
+ async function find(signal, wantedCurrency, strict = false) {
172
177
  const source = ctx().customerCart;
173
178
  if (source === void 0 || wantedCurrency === void 0) return null;
174
179
  const asked = wantedCurrency.toUpperCase();
@@ -176,9 +181,27 @@ function createController(home) {
176
181
  const found = await live(signal, source.getOpenCart({ currency: asked }));
177
182
  return found !== null && found.currency.toUpperCase() === asked ? found : null;
178
183
  } catch (error) {
179
- if (signal.aborted) throw error;
184
+ if (signal.aborted || strict) throw error;
185
+ return null;
186
+ }
187
+ }
188
+ async function findTarget(signal, code, storage) {
189
+ if (resuming()) {
190
+ const found = await find(signal, code, true);
191
+ return found === null ? null : { id: found.sessionId, cartUrl: fallbackUrl(found.sessionId) };
192
+ }
193
+ if (ctx().customerKey !== null || storage.getFor === void 0) return null;
194
+ const id = await live(signal, storage.getFor(code));
195
+ if (id === null || id === "") return null;
196
+ try {
197
+ const answer = await live(signal, session(id).get({ signal }));
198
+ if (answer.cart.status !== "open" || answer.cart.currency.toUpperCase() !== code)
199
+ return null;
200
+ } catch (error) {
201
+ if (signal.aborted || !ended(error)) throw error;
180
202
  return null;
181
203
  }
204
+ return { id, cartUrl: fallbackUrl(id) };
182
205
  }
183
206
  async function findOnce(signal, storage) {
184
207
  var _a2;
@@ -197,13 +220,21 @@ function createController(home) {
197
220
  }
198
221
  if (found !== null) await soft(signal, () => adopt(signal, found, storage));
199
222
  }
223
+ async function forgetSlots(storage, codes) {
224
+ for (const code of codes)
225
+ if (storage.removeFor !== void 0) await storage.removeFor(code);
226
+ else await storage.setFor?.(code, "");
227
+ }
228
+ async function save(signal, storage, id) {
229
+ const write = storage.set(id);
230
+ me.writing = Promise.resolve(write).catch(() => void 0);
231
+ await live(signal, write);
232
+ }
200
233
  async function adopt(signal, found, storage) {
201
234
  const id = found.sessionId;
202
235
  const answer = await live(signal, session(id).get({ signal }));
203
236
  me.reads.set(id, Date.now());
204
- const write = storage.set(id);
205
- me.writing = Promise.resolve(write).catch(() => void 0);
206
- await live(signal, write);
237
+ await save(signal, storage, id);
207
238
  box.set({
208
239
  sessionId: id,
209
240
  cartUrl: fallbackUrl(id),
@@ -229,7 +260,7 @@ function createController(home) {
229
260
  if (converted(error)) reset();
230
261
  else box.set({ sessionId: null, cartUrl: null });
231
262
  }
232
- async function create(signal, options, items, whole = false) {
263
+ async function start(signal, options, items) {
233
264
  const context = ctx();
234
265
  const body = {
235
266
  items: [...items].map(([sku, quantity]) => ({ sku, quantity }))
@@ -253,28 +284,18 @@ function createController(home) {
253
284
  throw error;
254
285
  }
255
286
  const id = answer.sessionId;
256
- const cartUrl = isHttpUrl(answer.cartUrl) ? answer.cartUrl : fallbackUrl(id);
257
- if (whole) {
258
- const snapshot = await live(signal, session(id).get({ signal }));
259
- me.reads.set(id, Date.now());
260
- const write = context.cartStorage.set(id);
261
- me.writing = Promise.resolve(write).catch(() => void 0);
262
- await live(signal, write);
263
- box.set({
264
- sessionId: id,
265
- cartUrl,
266
- cart: snapshot.cart,
267
- status: "ready",
268
- error: void 0
269
- });
270
- return;
271
- }
287
+ return {
288
+ id,
289
+ cartUrl: isHttpUrl(answer.cartUrl) ? answer.cartUrl : fallbackUrl(id)
290
+ };
291
+ }
292
+ async function create(signal, options, items) {
293
+ const storage = ctx().cartStorage;
294
+ const { id, cartUrl } = await start(signal, options, items);
272
295
  box.set({ sessionId: id, cartUrl });
273
296
  let unsaved;
274
297
  try {
275
- const write = context.cartStorage.set(id);
276
- me.writing = Promise.resolve(write).catch(() => void 0);
277
- await live(signal, write);
298
+ await save(signal, storage, id);
278
299
  } catch (error) {
279
300
  if (signal.aborted) throw error;
280
301
  unsaved = error;
@@ -432,6 +453,11 @@ function createController(home) {
432
453
  if (signal.aborted) return;
433
454
  if (fresh && !me.unremoved) await restore(signal, guest, false);
434
455
  if (signal.aborted) return;
456
+ const codes = new Set(me.slots);
457
+ const shown = box.get().cart?.currency;
458
+ if (shown !== void 0) codes.add(shown.toUpperCase());
459
+ await live(signal, forgetSlots(guest, codes));
460
+ me.slots.clear();
435
461
  const id = box.get().sessionId;
436
462
  if (id === null) {
437
463
  if (box.get().cart === null && !me.unremoved) {
@@ -480,9 +506,15 @@ function createController(home) {
480
506
  const outgoing = prior ?? me.seen;
481
507
  const left = me.moving;
482
508
  me.moving = void 0;
509
+ const slots = [...me.slots];
510
+ me.slots.clear();
483
511
  const remove = async () => {
484
512
  await outgoing.remove();
485
- if (left !== void 0 && left !== outgoing) await left.remove();
513
+ await forgetSlots(outgoing, slots);
514
+ if (left !== void 0 && left !== outgoing) {
515
+ await left.remove();
516
+ await forgetSlots(left, slots);
517
+ }
486
518
  };
487
519
  me.tail = me.writing.then(remove).catch(remove).then(
488
520
  () => {
@@ -508,6 +540,7 @@ function createController(home) {
508
540
  mutate,
509
541
  create,
510
542
  session,
543
+ wanted,
511
544
  async switchCurrency(signal, options, next) {
512
545
  checkPause(ctx().store);
513
546
  const storage = ctx().cartStorage;
@@ -524,21 +557,60 @@ function createController(home) {
524
557
  }
525
558
  const before = currency;
526
559
  currency = next;
527
- const items = itemsOf(box.get().cart);
528
- if (items.size === 0) {
529
- if (box.get().sessionId !== null) await live(signal, storage.remove());
530
- reset();
560
+ const code = next.toUpperCase();
561
+ const from = box.get().sessionId;
562
+ const cart = box.get().cart;
563
+ const items = itemsOf(cart);
564
+ if (from === null || items.size === 0) {
565
+ if (from !== null) await live(signal, storage.remove());
566
+ if (items.size === 0) reset();
531
567
  return;
532
568
  }
569
+ if (cart?.currency.toUpperCase() === code) return;
570
+ let target;
571
+ let moved;
533
572
  try {
534
- await create(signal, options, items, true);
573
+ target = await findTarget(signal, code, storage) ?? await start(signal, options, /* @__PURE__ */ new Map());
574
+ moved = await live(signal, session(target.id).absorb(from, { signal }));
535
575
  } catch (error) {
536
576
  if (!signal.aborted) currency = before;
537
577
  throw error;
538
578
  }
579
+ me.reads.set(target.id, Date.now());
580
+ box.set({
581
+ sessionId: target.id,
582
+ cartUrl: target.cartUrl,
583
+ cart: moved.cart,
584
+ status: "ready",
585
+ error: void 0,
586
+ warnings: moved.warnings.filter(
587
+ (warning) => warning.code !== "lines_stale"
588
+ )
589
+ });
590
+ let unsaved;
591
+ try {
592
+ await save(signal, storage, target.id);
593
+ } catch (error) {
594
+ if (signal.aborted) throw error;
595
+ unsaved = error;
596
+ try {
597
+ await live(signal, storage.remove());
598
+ } catch (failure) {
599
+ if (signal.aborted) throw failure;
600
+ }
601
+ }
602
+ if (ctx().customerKey === null && storage.setFor !== void 0) {
603
+ me.slots.add(code);
604
+ await live(signal, storage.setFor(code, target.id));
605
+ }
606
+ if (unsaved !== void 0) throw unsaved;
539
607
  },
540
608
  async clear(signal) {
541
- await live(signal, ctx().cartStorage.remove());
609
+ const storage = ctx().cartStorage;
610
+ const shown = box.get().cart?.currency;
611
+ await live(signal, storage.remove());
612
+ if (shown !== void 0)
613
+ await live(signal, storage.removeFor?.(shown.toUpperCase()));
542
614
  currency = void 0;
543
615
  reset();
544
616
  }
@@ -656,7 +728,9 @@ function useCart(options = {}) {
656
728
  }, [controller, home, currency, locale]);
657
729
  const owner = controller.owner();
658
730
  const view = owner !== void 0 && owner !== null && owner !== customerKey ? { ...EMPTY, pending: state.pending } : state;
659
- return { ...view, ...actions };
731
+ const shownCurrency = view.cart?.currency ?? controller.wanted(options) ?? "";
732
+ const format = (minor) => formatMoney(minor, shownCurrency);
733
+ return { ...view, ...actions, format };
660
734
  }
661
735
 
662
736
  // src/react/use-submit-review.ts
@@ -732,10 +806,12 @@ export {
732
806
  useConfig,
733
807
  useCustomerKey,
734
808
  useFilterValues,
809
+ useGenerationWatch,
735
810
  useProduct,
736
811
  useProducts,
737
812
  useRelated,
738
813
  useReviews,
814
+ useStorefrontSettings,
739
815
  useSubmitReview,
740
816
  useSuggest
741
817
  };
package/dist/server.cjs CHANGED
@@ -8,91 +8,79 @@
8
8
 
9
9
 
10
10
 
11
+ var _chunkPZ3SFYH4cjs = require('./chunk-PZ3SFYH4.cjs');
12
+
13
+
14
+
11
15
 
12
- var _chunkB2DYAHNRcjs = require('./chunk-B2DYAHNR.cjs');
13
- require('./chunk-ETV4XYOV.cjs');
14
16
 
15
- // src/server/tags.ts
16
- function catalogTags(route, handle) {
17
- const tags = [_chunkB2DYAHNRcjs.CACHE_TAG, `${_chunkB2DYAHNRcjs.CACHE_TAG}:${route}`];
18
- if (handle !== void 0) tags.push(`${_chunkB2DYAHNRcjs.CACHE_TAG}:${route}:${handle}`);
19
- return tags.filter((tag) => tag.length <= _chunkB2DYAHNRcjs.TAG_MAX_CHARS);
20
- }
21
- function decode(segment) {
22
- try {
23
- return decodeURIComponent(segment);
24
- } catch (e) {
25
- return segment;
26
- }
27
- }
28
- function tagsForUrl(url, storefront) {
29
- const path = _nullishCoalesce(url.split(/[?#]/u, 1)[0], () => ( ""));
30
- if (!path.startsWith(storefront)) return null;
31
- const parts = path.slice(storefront.length).split("/");
32
- if (parts.length > 3) return null;
33
- const [first, segment, sub] = parts;
34
- if (segment === void 0) {
35
- switch (first) {
36
- case "config":
37
- case "products":
38
- case "categories":
39
- case "tags":
40
- case "collections":
41
- case "suggest":
42
- return catalogTags(first);
43
- default:
44
- return null;
45
- }
46
- }
47
- const handle = decode(segment);
48
- if (handle === "") return null;
49
- switch (first) {
50
- case "filters":
51
- return sub === "values" ? catalogTags("filters") : null;
52
- case "products":
53
- if (sub === "related" || sub === "reviews")
54
- return catalogTags(sub, handle);
55
- return sub === void 0 ? catalogTags("product", handle) : null;
56
- case "categories":
57
- return sub === void 0 ? catalogTags("category", handle) : null;
58
- case "collections":
59
- return sub === void 0 ? catalogTags("collection", handle) : null;
60
- default:
61
- return null;
62
- }
63
- }
17
+
18
+
19
+
20
+ var _chunkJ2GHGQY6cjs = require('./chunk-J2GHGQY6.cjs');
21
+ require('./chunk-ETV4XYOV.cjs');
64
22
 
65
23
  // src/server/client.ts
66
- function serverInit(url, init, storefront, revalidate, extraTags) {
24
+ function serverInit(url, init, storefront, policies, extraTags) {
67
25
  const { next, ...rest } = init;
68
- const tags = rest.method === "GET" ? tagsForUrl(url, storefront) : null;
26
+ const tags = rest.method === "GET" ? _chunkPZ3SFYH4cjs.tagsForUrl.call(void 0, url, storefront) : null;
69
27
  if (tags === null || rest.cache === "no-store")
70
28
  return { ...rest, cache: "no-store" };
71
29
  if (next !== void 0) return init;
72
- return { ...rest, next: { revalidate, tags: [...tags, ...extraTags] } };
30
+ const kind = _chunkPZ3SFYH4cjs.cacheKindForPath.call(void 0, url.slice(storefront.length));
31
+ const policy = kind === null ? "no-store" : policies(kind);
32
+ if (policy === "no-store") return { ...rest, cache: "no-store" };
33
+ return {
34
+ ...rest,
35
+ next: { revalidate: policy.revalidate, tags: [...tags, ...extraTags] }
36
+ };
73
37
  }
74
38
  function createServerCatalogClient(options) {
75
39
  const {
76
40
  next,
41
+ cachePolicy,
42
+ floorKey: namedFloorKey,
77
43
  // eslint-disable-next-line @typescript-eslint/no-unused-vars -- dropped on purpose (P8-R21)
78
44
  keyInQuery: _ignored,
79
45
  ...rest
80
46
  } = options;
81
- const revalidate = _nullishCoalesce(_optionalChain([next, 'optionalAccess', _ => _.revalidate]), () => ( _chunkB2DYAHNRcjs.DEFAULT_REVALIDATE_S));
47
+ const named = /* @__PURE__ */ new Map();
48
+ for (const [kind, policy] of Object.entries(_nullishCoalesce(cachePolicy, () => ( {}))))
49
+ if (policy !== void 0)
50
+ named.set(kind, _chunkPZ3SFYH4cjs.policyToNext.call(void 0, policy));
51
+ const policies = (kind) => _nullishCoalesce(named.get(kind), () => ( (_optionalChain([next, 'optionalAccess', _ => _.revalidate]) === void 0 ? _chunkPZ3SFYH4cjs.policyToNext.call(void 0, _chunkPZ3SFYH4cjs.DEFAULT_CACHE_POLICY[kind]) : { revalidate: next.revalidate })));
52
+ const floorKey = _nullishCoalesce(namedFloorKey, () => ( rest.publishableKey));
82
53
  const extraTags = _nullishCoalesce(_optionalChain([next, 'optionalAccess', _2 => _2.tags]), () => ( []));
83
- const storefront = `${(_nullishCoalesce(rest.baseUrl, () => ( _chunkB2DYAHNRcjs.DEFAULT_BASE_URL))).replace(/\/+$/u, "")}/v1/storefront/`;
54
+ const storefront = `${(_nullishCoalesce(rest.baseUrl, () => ( _chunkJ2GHGQY6cjs.DEFAULT_BASE_URL))).replace(/\/+$/u, "")}/v1/storefront/`;
84
55
  const base = rest.fetch;
85
56
  const serverFetch = (input, init = {}) => {
57
+ let target = String(input);
58
+ const isConfig = init.method === "GET" && target.startsWith(storefront) && _optionalChain([_chunkPZ3SFYH4cjs.storefrontRoute.call(void 0, target.slice(storefront.length)), 'optionalAccess', _3 => _3.route]) === "config";
59
+ const floor = isConfig ? _chunkPZ3SFYH4cjs.pendingMinGeneration.call(void 0, floorKey) : void 0;
60
+ if (floor !== void 0 && !target.includes("minGeneration="))
61
+ target += `${target.includes("?") ? "&" : "?"}minGeneration=${floor}`;
86
62
  const out = serverInit(
87
- String(input),
63
+ target,
88
64
  init,
89
65
  storefront,
90
- revalidate,
66
+ policies,
91
67
  extraTags
92
68
  );
93
- return base !== void 0 ? base(input, out) : globalThis.fetch(input, out);
69
+ const answer = base !== void 0 ? base(target, out) : globalThis.fetch(target, out);
70
+ if (floor === void 0) return answer;
71
+ return answer.then(async (response) => {
72
+ if (response.ok)
73
+ try {
74
+ _chunkPZ3SFYH4cjs.observeGeneration.call(void 0,
75
+ (await response.clone().json()).generation,
76
+ floorKey
77
+ );
78
+ } catch (e) {
79
+ }
80
+ return response;
81
+ });
94
82
  };
95
- return _chunkB2DYAHNRcjs.createCatalogClient.call(void 0, {
83
+ return _chunkJ2GHGQY6cjs.createCatalogClient.call(void 0, {
96
84
  ...rest,
97
85
  fetch: serverFetch
98
86
  });
@@ -112,16 +100,16 @@ async function syncCatalogGeneration(input) {
112
100
 
113
101
  // src/server/paging.ts
114
102
  function bounds(opts) {
115
- const pageSize = _nullishCoalesce(opts.pageSize, () => ( _chunkB2DYAHNRcjs.LIST_PAGE_SIZE));
116
- const max = _nullishCoalesce(opts.max, () => ( _chunkB2DYAHNRcjs.LIST_MAX_HANDLES));
117
- if (!Number.isInteger(pageSize) || pageSize < 1 || pageSize > _chunkB2DYAHNRcjs.LIST_PAGE_SIZE)
103
+ const pageSize = _nullishCoalesce(opts.pageSize, () => ( _chunkJ2GHGQY6cjs.LIST_PAGE_SIZE));
104
+ const max = _nullishCoalesce(opts.max, () => ( _chunkJ2GHGQY6cjs.LIST_MAX_HANDLES));
105
+ if (!Number.isInteger(pageSize) || pageSize < 1 || pageSize > _chunkJ2GHGQY6cjs.LIST_PAGE_SIZE)
118
106
  throw invalid("pageSize must be a whole number from 1 to 100.");
119
107
  if (!Number.isInteger(max) || max < 0)
120
108
  throw invalid("max must be a whole number of 0 or more.");
121
109
  return { pageSize, max };
122
110
  }
123
111
  function invalid(message) {
124
- return new (0, _chunkB2DYAHNRcjs.CatalogError)({
112
+ return new (0, _chunkJ2GHGQY6cjs.CatalogError)({
125
113
  code: "INVALID_REQUEST",
126
114
  message,
127
115
  statusCode: 0,
@@ -191,7 +179,7 @@ function listAllCollectionHandles(client, opts = {}) {
191
179
  }
192
180
  async function listAllCategoryHandles(client, opts = {}) {
193
181
  const { categories } = await client.categories.tree({
194
- depth: _chunkB2DYAHNRcjs.CATEGORY_TREE_MAX_DEPTH,
182
+ depth: _chunkJ2GHGQY6cjs.CATEGORY_TREE_MAX_DEPTH,
195
183
  ...call(opts.signal)
196
184
  });
197
185
  const out = [];
@@ -213,4 +201,8 @@ async function listAllCategoryHandles(client, opts = {}) {
213
201
 
214
202
 
215
203
 
216
- exports.SDK_VERSION = _chunkB2DYAHNRcjs.SDK_VERSION; exports.catalogTags = catalogTags; exports.createServerCatalogClient = createServerCatalogClient; exports.listAllCategoryHandles = listAllCategoryHandles; exports.listAllCollectionHandles = listAllCollectionHandles; exports.listAllProductHandles = listAllProductHandles; exports.staticProductParams = staticProductParams; exports.syncCatalogGeneration = syncCatalogGeneration;
204
+
205
+
206
+
207
+
208
+ exports.DEFAULT_CACHE_POLICY = _chunkPZ3SFYH4cjs.DEFAULT_CACHE_POLICY; exports.SDK_VERSION = _chunkJ2GHGQY6cjs.SDK_VERSION; exports.cacheKindForPath = _chunkPZ3SFYH4cjs.cacheKindForPath; exports.catalogTags = _chunkPZ3SFYH4cjs.catalogTags; exports.createServerCatalogClient = createServerCatalogClient; exports.listAllCategoryHandles = listAllCategoryHandles; exports.listAllCollectionHandles = listAllCollectionHandles; exports.listAllProductHandles = listAllProductHandles; exports.policyToNext = _chunkPZ3SFYH4cjs.policyToNext; exports.scopesToTags = _chunkPZ3SFYH4cjs.scopesToTags; exports.staticProductParams = staticProductParams; exports.syncCatalogGeneration = syncCatalogGeneration;
package/dist/server.d.cts CHANGED
@@ -1,11 +1,48 @@
1
1
  export { S as SDK_VERSION } from './version-ev3p03v2.cjs';
2
2
  import { CatalogClient } from './index.cjs';
3
3
  import { CatalogClientOptions, NextFetchOptions } from './index.cjs';
4
- import './contract-types-BPSzY_Co.cjs';
4
+ import '@usethrottle/money';
5
+ import './contract-types-D2-SSPM9.cjs';
6
+
7
+ /** A kind of storefront data, each with its own cache policy. */
8
+ type CacheKind = 'settings' | 'navigation' | 'pages' | 'listings' | 'facets' | 'product' | 'related' | 'reviews' | 'search';
9
+ /**
10
+ * How long a read is cached: `'until-changed'` (an hour's safety TTL, cleared
11
+ * sooner by its cache tags), `'no-store'`, or a duration such as `'90s'` or
12
+ * `'5m'`.
13
+ */
14
+ type CachePolicy = 'until-changed' | 'no-store' | `${number}s` | `${number}m`;
15
+ declare const DEFAULT_CACHE_POLICY: Readonly<Record<CacheKind, CachePolicy>>;
16
+ /** The kind of data a storefront path serves, or `null` when it is not a cacheable catalog read. */
17
+ declare function cacheKindForPath(path: string): CacheKind | null;
18
+ /**
19
+ * The `fetch` cache option a policy means: `{ revalidate }` for Next, or
20
+ * `'no-store'` (also for a zero duration). A string that is not a policy is
21
+ * `INVALID_REQUEST`.
22
+ */
23
+ declare function policyToNext(policy: CachePolicy): {
24
+ revalidate: number | false;
25
+ } | 'no-store';
5
26
 
6
27
  type ServerCatalogClientOptions = Omit<CatalogClientOptions, 'keyInQuery'> & {
7
- /** `revalidate` defaults to 60 seconds; `tags` are appended to the route's own. */
28
+ /**
29
+ * `revalidate` replaces the default of every kind of read that
30
+ * `cachePolicy` does not name; `tags` are appended to the route's own.
31
+ */
8
32
  next?: NextFetchOptions;
33
+ /**
34
+ * How long each kind of read is cached, over the defaults (`settings`,
35
+ * `navigation`, `pages` and `product` `'until-changed'`, the rest `'60s'`).
36
+ * Navigation arrives inside `/config`, so its policy follows `settings`.
37
+ * A customer-token, cart or preview request is `no-store` regardless.
38
+ */
39
+ cachePolicy?: Partial<Record<CacheKind, CachePolicy>>;
40
+ /**
41
+ * Names this store's generation floor (see `noteMinGeneration`). Defaults
42
+ * to `publishableKey`: one client per store needs nothing. Pass the same
43
+ * value to `createRevalidateHandler({ floorKey })`.
44
+ */
45
+ floorKey?: string;
9
46
  };
10
47
  /**
11
48
  * `createCatalogClient` for Next.js and other SSR: every catalog storefront
@@ -18,14 +55,25 @@ type ServerCatalogClientOptions = Omit<CatalogClientOptions, 'keyInQuery'> & {
18
55
  declare function createServerCatalogClient(options: ServerCatalogClientOptions): CatalogClient;
19
56
 
20
57
  /**
21
- * The cache tags of one storefront route (P6-R17): always `throttle-catalog`
22
- * and `throttle-catalog:<route>`, plus `throttle-catalog:<route>:<handle>`
23
- * for a handle route. Next refuses a tag over 256 characters, so one is
24
- * dropped. `route` is one of `config`, `products`, `filters`, `product`,
25
- * `related`, `categories`, `category`, `tags`, `collections`, `collection`,
26
- * `suggest`, `reviews`.
58
+ * The cache tags of one storefront route (P6-R17): always `throttle-catalog`,
59
+ * the route's family (`throttle-catalog:config`, `:pages` or `:data`) and
60
+ * `throttle-catalog:<route>`, plus `throttle-catalog:<route>:<handle>` for a
61
+ * handle route. Next refuses a tag over 256 characters, so one is dropped.
62
+ * `route` is one of `config`, `products`, `filters`, `product`, `related`,
63
+ * `categories`, `category`, `tags`, `collections`, `collection`, `suggest`,
64
+ * `reviews`, `pages`, `page`.
27
65
  */
28
66
  declare function catalogTags(route: string, handle?: string): string[];
67
+ /**
68
+ * The cache tags a storefront change notice clears, for the revalidate
69
+ * handler and any custom receiver. `settings` and `navigation` clear
70
+ * `throttle-catalog:config`; `filters` that and `:data`; `pages`
71
+ * `:pages`; `taxonomy` and `catalog` `:data`; `product:<h>`, `collection:<h>`
72
+ * and `category:<h>` their handle tag and `:data`; `reviews:<h>` the
73
+ * reviews and product handle tags. Anything else clears `:data`. In order,
74
+ * without repeats; a tag over 256 characters is dropped, as in `catalogTags`.
75
+ */
76
+ declare function scopesToTags(scopes: readonly string[]): string[];
29
77
 
30
78
  type SyncCatalogGenerationInput = {
31
79
  client: CatalogClient;
@@ -76,5 +124,5 @@ declare function listAllCategoryHandles(client: CatalogClient, opts?: {
76
124
  signal?: AbortSignal;
77
125
  }): Promise<string[]>;
78
126
 
79
- export { catalogTags, createServerCatalogClient, listAllCategoryHandles, listAllCollectionHandles, listAllProductHandles, staticProductParams, syncCatalogGeneration };
80
- export type { ListHandlesOptions, ServerCatalogClientOptions, SyncCatalogGenerationInput };
127
+ export { DEFAULT_CACHE_POLICY, cacheKindForPath, catalogTags, createServerCatalogClient, listAllCategoryHandles, listAllCollectionHandles, listAllProductHandles, policyToNext, scopesToTags, staticProductParams, syncCatalogGeneration };
128
+ export type { CacheKind, CachePolicy, ListHandlesOptions, ServerCatalogClientOptions, SyncCatalogGenerationInput };
package/dist/server.d.ts CHANGED
@@ -1,11 +1,48 @@
1
1
  export { S as SDK_VERSION } from './version-ev3p03v2.js';
2
2
  import { CatalogClient } from './index.js';
3
3
  import { CatalogClientOptions, NextFetchOptions } from './index.js';
4
- import './contract-types-BPSzY_Co.js';
4
+ import '@usethrottle/money';
5
+ import './contract-types-D2-SSPM9.js';
6
+
7
+ /** A kind of storefront data, each with its own cache policy. */
8
+ type CacheKind = 'settings' | 'navigation' | 'pages' | 'listings' | 'facets' | 'product' | 'related' | 'reviews' | 'search';
9
+ /**
10
+ * How long a read is cached: `'until-changed'` (an hour's safety TTL, cleared
11
+ * sooner by its cache tags), `'no-store'`, or a duration such as `'90s'` or
12
+ * `'5m'`.
13
+ */
14
+ type CachePolicy = 'until-changed' | 'no-store' | `${number}s` | `${number}m`;
15
+ declare const DEFAULT_CACHE_POLICY: Readonly<Record<CacheKind, CachePolicy>>;
16
+ /** The kind of data a storefront path serves, or `null` when it is not a cacheable catalog read. */
17
+ declare function cacheKindForPath(path: string): CacheKind | null;
18
+ /**
19
+ * The `fetch` cache option a policy means: `{ revalidate }` for Next, or
20
+ * `'no-store'` (also for a zero duration). A string that is not a policy is
21
+ * `INVALID_REQUEST`.
22
+ */
23
+ declare function policyToNext(policy: CachePolicy): {
24
+ revalidate: number | false;
25
+ } | 'no-store';
5
26
 
6
27
  type ServerCatalogClientOptions = Omit<CatalogClientOptions, 'keyInQuery'> & {
7
- /** `revalidate` defaults to 60 seconds; `tags` are appended to the route's own. */
28
+ /**
29
+ * `revalidate` replaces the default of every kind of read that
30
+ * `cachePolicy` does not name; `tags` are appended to the route's own.
31
+ */
8
32
  next?: NextFetchOptions;
33
+ /**
34
+ * How long each kind of read is cached, over the defaults (`settings`,
35
+ * `navigation`, `pages` and `product` `'until-changed'`, the rest `'60s'`).
36
+ * Navigation arrives inside `/config`, so its policy follows `settings`.
37
+ * A customer-token, cart or preview request is `no-store` regardless.
38
+ */
39
+ cachePolicy?: Partial<Record<CacheKind, CachePolicy>>;
40
+ /**
41
+ * Names this store's generation floor (see `noteMinGeneration`). Defaults
42
+ * to `publishableKey`: one client per store needs nothing. Pass the same
43
+ * value to `createRevalidateHandler({ floorKey })`.
44
+ */
45
+ floorKey?: string;
9
46
  };
10
47
  /**
11
48
  * `createCatalogClient` for Next.js and other SSR: every catalog storefront
@@ -18,14 +55,25 @@ type ServerCatalogClientOptions = Omit<CatalogClientOptions, 'keyInQuery'> & {
18
55
  declare function createServerCatalogClient(options: ServerCatalogClientOptions): CatalogClient;
19
56
 
20
57
  /**
21
- * The cache tags of one storefront route (P6-R17): always `throttle-catalog`
22
- * and `throttle-catalog:<route>`, plus `throttle-catalog:<route>:<handle>`
23
- * for a handle route. Next refuses a tag over 256 characters, so one is
24
- * dropped. `route` is one of `config`, `products`, `filters`, `product`,
25
- * `related`, `categories`, `category`, `tags`, `collections`, `collection`,
26
- * `suggest`, `reviews`.
58
+ * The cache tags of one storefront route (P6-R17): always `throttle-catalog`,
59
+ * the route's family (`throttle-catalog:config`, `:pages` or `:data`) and
60
+ * `throttle-catalog:<route>`, plus `throttle-catalog:<route>:<handle>` for a
61
+ * handle route. Next refuses a tag over 256 characters, so one is dropped.
62
+ * `route` is one of `config`, `products`, `filters`, `product`, `related`,
63
+ * `categories`, `category`, `tags`, `collections`, `collection`, `suggest`,
64
+ * `reviews`, `pages`, `page`.
27
65
  */
28
66
  declare function catalogTags(route: string, handle?: string): string[];
67
+ /**
68
+ * The cache tags a storefront change notice clears, for the revalidate
69
+ * handler and any custom receiver. `settings` and `navigation` clear
70
+ * `throttle-catalog:config`; `filters` that and `:data`; `pages`
71
+ * `:pages`; `taxonomy` and `catalog` `:data`; `product:<h>`, `collection:<h>`
72
+ * and `category:<h>` their handle tag and `:data`; `reviews:<h>` the
73
+ * reviews and product handle tags. Anything else clears `:data`. In order,
74
+ * without repeats; a tag over 256 characters is dropped, as in `catalogTags`.
75
+ */
76
+ declare function scopesToTags(scopes: readonly string[]): string[];
29
77
 
30
78
  type SyncCatalogGenerationInput = {
31
79
  client: CatalogClient;
@@ -76,5 +124,5 @@ declare function listAllCategoryHandles(client: CatalogClient, opts?: {
76
124
  signal?: AbortSignal;
77
125
  }): Promise<string[]>;
78
126
 
79
- export { catalogTags, createServerCatalogClient, listAllCategoryHandles, listAllCollectionHandles, listAllProductHandles, staticProductParams, syncCatalogGeneration };
80
- export type { ListHandlesOptions, ServerCatalogClientOptions, SyncCatalogGenerationInput };
127
+ export { DEFAULT_CACHE_POLICY, cacheKindForPath, catalogTags, createServerCatalogClient, listAllCategoryHandles, listAllCollectionHandles, listAllProductHandles, policyToNext, scopesToTags, staticProductParams, syncCatalogGeneration };
128
+ export type { CacheKind, CachePolicy, ListHandlesOptions, ServerCatalogClientOptions, SyncCatalogGenerationInput };