@usethrottle/catalog 1.3.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 +15 -0
  2. package/README.md +105 -9
  3. package/dist/admin.cjs +16 -16
  4. package/dist/admin.d.cts +14 -2
  5. package/dist/admin.d.ts +14 -2
  6. package/dist/admin.js +1 -1
  7. package/dist/{catalog-error-BOaSKgY3.d.cts → catalog-error-BKN5hNWP.d.cts} +1 -1
  8. package/dist/{catalog-error-CSoPS0-d.d.ts → catalog-error-BnabMMEy.d.ts} +1 -1
  9. package/dist/{chunk-CADIHOIR.js → chunk-3FX2HISB.js} +89 -2
  10. package/dist/{chunk-2YQNMBDI.cjs → chunk-J2GHGQY6.cjs} +274 -38
  11. package/dist/{chunk-GU63WFXI.cjs → chunk-OKWXS3FD.cjs} +102 -15
  12. package/dist/chunk-PZ3SFYH4.cjs +192 -0
  13. package/dist/chunk-SN6STYPW.js +192 -0
  14. package/dist/{chunk-3DLH56OX.js → chunk-VJHA7J7B.js} +258 -22
  15. package/dist/{client-B3mL2-xJ.d.ts → client-B6CsU_v9.d.ts} +1 -1
  16. package/dist/{client-6j1Iz-iJ.d.cts → client-terkEl6u.d.cts} +1 -1
  17. package/dist/{contract-types-BRyonOYH.d.cts → contract-types-D2-SSPM9.d.cts} +230 -2
  18. package/dist/{contract-types-BRyonOYH.d.ts → contract-types-D2-SSPM9.d.ts} +230 -2
  19. package/dist/index.cjs +12 -2
  20. package/dist/index.d.cts +53 -7
  21. package/dist/index.d.ts +53 -7
  22. package/dist/index.js +11 -1
  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 +6 -4
  29. package/dist/react-extras.d.ts +6 -4
  30. package/dist/react-extras.js +20 -2
  31. package/dist/react.cjs +18 -14
  32. package/dist/react.d.cts +22 -5
  33. package/dist/react.d.ts +22 -5
  34. package/dist/react.js +6 -2
  35. package/dist/server.cjs +58 -66
  36. package/dist/server.d.cts +57 -10
  37. package/dist/server.d.ts +57 -10
  38. package/dist/server.js +52 -60
  39. package/dist/{types-D0PywKnN.d.cts → types-jNpOwEUw.d.cts} +40 -3
  40. package/dist/{types-BfveENg1.d.ts → types-z57bkjjB.d.ts} +40 -3
  41. package/dist/url.d.cts +1 -1
  42. package/dist/url.d.ts +1 -1
  43. package/dist/{use-query-CR7r5tam.d.ts → use-query-COqRZJnC.d.ts} +1 -1
  44. package/dist/{use-query-UWf6Pi5g.d.cts → use-query-H1xgL3_e.d.cts} +1 -1
  45. package/package.json +15 -1
@@ -3,14 +3,14 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkGU63WFXIcjs = require('./chunk-GU63WFXI.cjs');
7
- require('./chunk-2YQNMBDI.cjs');
6
+ var _chunkOKWXS3FDcjs = require('./chunk-OKWXS3FD.cjs');
7
+ require('./chunk-J2GHGQY6.cjs');
8
8
  require('./chunk-ETV4XYOV.cjs');
9
9
 
10
10
  // src/react/extras/index.ts
11
11
  function useTags(options = {}) {
12
- const extra = _chunkGU63WFXIcjs.defined.call(void 0, { q: options.q, limit: options.limit });
13
- return _chunkGU63WFXIcjs.useQuery.call(void 0,
12
+ const extra = _chunkOKWXS3FDcjs.defined.call(void 0, { q: options.q, limit: options.limit });
13
+ return _chunkOKWXS3FDcjs.useQuery.call(void 0,
14
14
  "tags",
15
15
  extra,
16
16
  (client, call) => client.tags.list({ ...call, ...extra }),
@@ -18,8 +18,8 @@ function useTags(options = {}) {
18
18
  );
19
19
  }
20
20
  function useCollections(options = {}) {
21
- const extra = _chunkGU63WFXIcjs.defined.call(void 0, { limit: options.limit, cursor: options.cursor });
22
- return _chunkGU63WFXIcjs.useQuery.call(void 0,
21
+ const extra = _chunkOKWXS3FDcjs.defined.call(void 0, { limit: options.limit, cursor: options.cursor });
22
+ return _chunkOKWXS3FDcjs.useQuery.call(void 0,
23
23
  "collections",
24
24
  extra,
25
25
  (client, call) => client.collections.list({ ...call, ...extra }),
@@ -27,16 +27,34 @@ function useCollections(options = {}) {
27
27
  );
28
28
  }
29
29
  function useReviewEligibility(handle, options = {}) {
30
- const customerKey = _chunkGU63WFXIcjs.useCustomerKey.call(void 0, );
31
- return _chunkGU63WFXIcjs.useQuery.call(void 0,
30
+ const customerKey = _chunkOKWXS3FDcjs.useCustomerKey.call(void 0, );
31
+ return _chunkOKWXS3FDcjs.useQuery.call(void 0,
32
32
  "review-eligibility",
33
33
  { handle },
34
34
  handle === null || customerKey === null ? null : (client, call) => client.reviews.eligibility(handle, call),
35
35
  { ...options, staleTimeMs: _nullishCoalesce(options.staleTimeMs, () => ( 0)) }
36
36
  );
37
37
  }
38
+ function usePages(options) {
39
+ return _chunkOKWXS3FDcjs.useQuery.call(void 0,
40
+ "pages",
41
+ null,
42
+ (client, call) => client.pages.list(call),
43
+ options
44
+ );
45
+ }
46
+ function usePage(handle, options) {
47
+ return _chunkOKWXS3FDcjs.useQuery.call(void 0,
48
+ "page",
49
+ { handle },
50
+ handle === null ? null : (client, call) => client.pages.get(handle, call),
51
+ options
52
+ );
53
+ }
54
+
55
+
38
56
 
39
57
 
40
58
 
41
59
 
42
- exports.useCollections = useCollections; exports.useReviewEligibility = useReviewEligibility; exports.useTags = useTags;
60
+ exports.useCollections = useCollections; exports.usePage = usePage; exports.usePages = usePages; exports.useReviewEligibility = useReviewEligibility; exports.useTags = useTags;
@@ -1,9 +1,9 @@
1
1
  import { CatalogClient } from './index.cjs';
2
2
  import { QueryOptions, QueryResult } from './react.cjs';
3
- import './types-D0PywKnN.cjs';
3
+ import './types-jNpOwEUw.cjs';
4
4
  import '@usethrottle/money';
5
- import './contract-types-BRyonOYH.cjs';
6
- import './catalog-error-BOaSKgY3.cjs';
5
+ import './contract-types-D2-SSPM9.cjs';
6
+ import './catalog-error-BKN5hNWP.cjs';
7
7
 
8
8
  type Answer<F extends (...args: never[]) => unknown> = Awaited<ReturnType<F>>;
9
9
  declare function useTags(options?: QueryOptions<Answer<CatalogClient['tags']['list']>> & {
@@ -19,5 +19,7 @@ declare function useCollections(options?: QueryOptions<Answer<CatalogClient['col
19
19
  * signed out; asks on every mount (`staleTimeMs` 0).
20
20
  */
21
21
  declare function useReviewEligibility(handle: string | null, options?: QueryOptions<Answer<CatalogClient['reviews']['eligibility']>>): QueryResult<Answer<CatalogClient['reviews']['eligibility']>>;
22
+ declare function usePages(options?: QueryOptions<Answer<CatalogClient['pages']['list']>>): QueryResult<Answer<CatalogClient['pages']['list']>>;
23
+ declare function usePage(handle: string | null, options?: QueryOptions<Answer<CatalogClient['pages']['get']>>): QueryResult<Answer<CatalogClient['pages']['get']>>;
22
24
 
23
- export { useCollections, useReviewEligibility, useTags };
25
+ export { useCollections, usePage, usePages, useReviewEligibility, useTags };
@@ -1,9 +1,9 @@
1
1
  import { CatalogClient } from './index.js';
2
2
  import { QueryOptions, QueryResult } from './react.js';
3
- import './types-BfveENg1.js';
3
+ import './types-z57bkjjB.js';
4
4
  import '@usethrottle/money';
5
- import './contract-types-BRyonOYH.js';
6
- import './catalog-error-CSoPS0-d.js';
5
+ import './contract-types-D2-SSPM9.js';
6
+ import './catalog-error-BnabMMEy.js';
7
7
 
8
8
  type Answer<F extends (...args: never[]) => unknown> = Awaited<ReturnType<F>>;
9
9
  declare function useTags(options?: QueryOptions<Answer<CatalogClient['tags']['list']>> & {
@@ -19,5 +19,7 @@ declare function useCollections(options?: QueryOptions<Answer<CatalogClient['col
19
19
  * signed out; asks on every mount (`staleTimeMs` 0).
20
20
  */
21
21
  declare function useReviewEligibility(handle: string | null, options?: QueryOptions<Answer<CatalogClient['reviews']['eligibility']>>): QueryResult<Answer<CatalogClient['reviews']['eligibility']>>;
22
+ declare function usePages(options?: QueryOptions<Answer<CatalogClient['pages']['list']>>): QueryResult<Answer<CatalogClient['pages']['list']>>;
23
+ declare function usePage(handle: string | null, options?: QueryOptions<Answer<CatalogClient['pages']['get']>>): QueryResult<Answer<CatalogClient['pages']['get']>>;
22
24
 
23
- export { useCollections, useReviewEligibility, useTags };
25
+ export { useCollections, usePage, usePages, useReviewEligibility, useTags };
@@ -3,8 +3,8 @@ import {
3
3
  defined,
4
4
  useCustomerKey,
5
5
  useQuery
6
- } from "./chunk-CADIHOIR.js";
7
- import "./chunk-3DLH56OX.js";
6
+ } from "./chunk-3FX2HISB.js";
7
+ import "./chunk-VJHA7J7B.js";
8
8
  import "./chunk-PKBMQBKP.js";
9
9
 
10
10
  // src/react/extras/index.ts
@@ -35,8 +35,26 @@ function useReviewEligibility(handle, options = {}) {
35
35
  { ...options, staleTimeMs: options.staleTimeMs ?? 0 }
36
36
  );
37
37
  }
38
+ function usePages(options) {
39
+ return useQuery(
40
+ "pages",
41
+ null,
42
+ (client, call) => client.pages.list(call),
43
+ options
44
+ );
45
+ }
46
+ function usePage(handle, options) {
47
+ return useQuery(
48
+ "page",
49
+ { handle },
50
+ handle === null ? null : (client, call) => client.pages.get(handle, call),
51
+ options
52
+ );
53
+ }
38
54
  export {
39
55
  useCollections,
56
+ usePage,
57
+ usePages,
40
58
  useReviewEligibility,
41
59
  useTags
42
60
  };
package/dist/react.cjs CHANGED
@@ -15,15 +15,17 @@
15
15
 
16
16
 
17
17
 
18
- var _chunkGU63WFXIcjs = require('./chunk-GU63WFXI.cjs');
19
18
 
20
19
 
20
+ var _chunkOKWXS3FDcjs = require('./chunk-OKWXS3FD.cjs');
21
21
 
22
22
 
23
23
 
24
24
 
25
25
 
26
- var _chunk2YQNMBDIcjs = require('./chunk-2YQNMBDI.cjs');
26
+
27
+
28
+ var _chunkJ2GHGQY6cjs = require('./chunk-J2GHGQY6.cjs');
27
29
  require('./chunk-ETV4XYOV.cjs');
28
30
 
29
31
  // src/react/use-cart.ts
@@ -40,7 +42,7 @@ function newKey() {
40
42
  return out;
41
43
  }
42
44
  function refuse(message, path) {
43
- return new (0, _chunk2YQNMBDIcjs.CatalogError)({
45
+ return new (0, _chunkJ2GHGQY6cjs.CatalogError)({
44
46
  code: "INVALID_REQUEST",
45
47
  message,
46
48
  statusCode: 0,
@@ -53,7 +55,7 @@ var UNSAFE = /[\x00-\x20\x7f]/u;
53
55
  function isHttpUrl(value) {
54
56
  return typeof value === "string" && /^https?:\/\/[^/?#\\]/iu.test(value) && !UNSAFE.test(value);
55
57
  }
56
- var wrap = (error) => _chunk2YQNMBDIcjs.isCatalogError.call(void 0, error) ? error : new (0, _chunk2YQNMBDIcjs.CatalogError)({
58
+ var wrap = (error) => _chunkJ2GHGQY6cjs.isCatalogError.call(void 0, error) ? error : new (0, _chunkJ2GHGQY6cjs.CatalogError)({
57
59
  code: "CLIENT_ERROR",
58
60
  message: "The action failed.",
59
61
  statusCode: 0,
@@ -64,7 +66,7 @@ var wrap = (error) => _chunk2YQNMBDIcjs.isCatalogError.call(void 0, error) ? err
64
66
  function checkPause(store) {
65
67
  const until = store.pausedUntil();
66
68
  if (until > 0) {
67
- throw new (0, _chunk2YQNMBDIcjs.RateLimitedError)({
69
+ throw new (0, _chunkJ2GHGQY6cjs.RateLimitedError)({
68
70
  code: "RATE_LIMITED",
69
71
  message: "Too many requests.",
70
72
  statusCode: 429,
@@ -74,7 +76,7 @@ function checkPause(store) {
74
76
  }
75
77
  }
76
78
  function notePause(store, error) {
77
- if (error instanceof _chunk2YQNMBDIcjs.RateLimitedError && error.source === "catalog" && error.code === "RATE_LIMITED")
79
+ if (error instanceof _chunkJ2GHGQY6cjs.RateLimitedError && error.source === "catalog" && error.code === "RATE_LIMITED")
78
80
  store.pause(Date.now() + error.retryAfterSeconds * 1e3, error);
79
81
  }
80
82
  function createBox(initial) {
@@ -109,7 +111,7 @@ var ENDED = /* @__PURE__ */ new Set([
109
111
  "cart_not_open",
110
112
  "cart_not_found"
111
113
  ]);
112
- var ended = (error) => _chunk2YQNMBDIcjs.isCatalogError.call(void 0, error) && ENDED.has(error.code);
114
+ var ended = (error) => _chunkJ2GHGQY6cjs.isCatalogError.call(void 0, error) && ENDED.has(error.code);
113
115
  var converted = (error) => _optionalChain([error, 'access', _2 => _2.details, 'optionalAccess', _3 => _3.reason]) === "converted";
114
116
  function itemsOf(cart) {
115
117
  const items = /* @__PURE__ */ new Map();
@@ -153,7 +155,7 @@ function createController(home) {
153
155
  throttleBaseUrl === void 0 ? void 0 : { throttleBaseUrl }
154
156
  );
155
157
  };
156
- const fallbackUrl = (id) => `${(_nullishCoalesce(ctx().throttleCheckoutUrl, () => ( _chunk2YQNMBDIcjs.THROTTLE_CHECKOUT_URL))).replace(/\/+$/u, "")}/cart/${encodeURIComponent(id)}`;
158
+ const fallbackUrl = (id) => `${(_nullishCoalesce(ctx().throttleCheckoutUrl, () => ( _chunkJ2GHGQY6cjs.THROTTLE_CHECKOUT_URL))).replace(/\/+$/u, "")}/cart/${encodeURIComponent(id)}`;
157
159
  const live = async (signal, value) => {
158
160
  const out = await value;
159
161
  if (signal.aborted) throw signal.reason;
@@ -615,7 +617,7 @@ function createController(home) {
615
617
  };
616
618
  }
617
619
  function useCart(options = {}) {
618
- const context = _chunkGU63WFXIcjs.useCatalogContext.call(void 0, );
620
+ const context = _chunkOKWXS3FDcjs.useCatalogContext.call(void 0, );
619
621
  const home = context.cart;
620
622
  const controller = _nullishCoalesce(home.current, () => ( (home.current = createController(home))));
621
623
  const state = _react.useSyncExternalStore.call(void 0,
@@ -689,7 +691,7 @@ function useCart(options = {}) {
689
691
  { signal: callSignal }
690
692
  );
691
693
  } catch (error) {
692
- const repriced = _chunk2YQNMBDIcjs.isCatalogError.call(void 0, error) && error.code === "cart_prices_changed" ? _optionalChain([error, 'access', _41 => _41.details, 'optionalAccess', _42 => _42.cart]) : void 0;
694
+ const repriced = _chunkJ2GHGQY6cjs.isCatalogError.call(void 0, error) && error.code === "cart_prices_changed" ? _optionalChain([error, 'access', _41 => _41.details, 'optionalAccess', _42 => _42.cart]) : void 0;
693
695
  if (!callSignal.aborted && typeof repriced === "object" && repriced !== null)
694
696
  controller.box.set({ cart: repriced });
695
697
  throw error;
@@ -709,7 +711,7 @@ function useCart(options = {}) {
709
711
  if (out === void 0)
710
712
  throw _nullishCoalesce(met, () => ( refuse("There is no cart to check out.")));
711
713
  if (!isHttpUrl(out.checkoutUrl))
712
- throw new (0, _chunk2YQNMBDIcjs.CatalogError)({
714
+ throw new (0, _chunkJ2GHGQY6cjs.CatalogError)({
713
715
  code: "INVALID_RESPONSE",
714
716
  message: "Throttle answered a checkout URL that is not http or https.",
715
717
  statusCode: 200,
@@ -727,7 +729,7 @@ function useCart(options = {}) {
727
729
  const owner = controller.owner();
728
730
  const view = owner !== void 0 && owner !== null && owner !== customerKey ? { ...EMPTY, pending: state.pending } : state;
729
731
  const shownCurrency = _nullishCoalesce(_nullishCoalesce(_optionalChain([view, 'access', _43 => _43.cart, 'optionalAccess', _44 => _44.currency]), () => ( controller.wanted(options))), () => ( ""));
730
- const format = (minor) => _chunk2YQNMBDIcjs.formatMoney.call(void 0, minor, shownCurrency);
732
+ const format = (minor) => _chunkJ2GHGQY6cjs.formatMoney.call(void 0, minor, shownCurrency);
731
733
  return { ...view, ...actions, format };
732
734
  }
733
735
 
@@ -739,7 +741,7 @@ var IDLE = {
739
741
  result: void 0
740
742
  };
741
743
  function useSubmitReview(handle) {
742
- const { client, store, customerKey } = _chunkGU63WFXIcjs.useCatalogContext.call(void 0, );
744
+ const { client, store, customerKey } = _chunkOKWXS3FDcjs.useCatalogContext.call(void 0, );
743
745
  const scope = _react.useMemo.call(void 0,
744
746
  () => ({
745
747
  box: createBox(IDLE),
@@ -810,4 +812,6 @@ function useSubmitReview(handle) {
810
812
 
811
813
 
812
814
 
813
- exports.CatalogProvider = _chunkGU63WFXIcjs.CatalogProvider; exports.SDK_VERSION = _chunk2YQNMBDIcjs.SDK_VERSION; exports.catalogQueryKey = _chunkGU63WFXIcjs.catalogQueryKey; exports.createMemoryCartStorage = _chunkGU63WFXIcjs.createMemoryCartStorage; exports.useCart = useCart; exports.useCatalog = _chunkGU63WFXIcjs.useCatalog; exports.useCategories = _chunkGU63WFXIcjs.useCategories; exports.useCollection = _chunkGU63WFXIcjs.useCollection; exports.useConfig = _chunkGU63WFXIcjs.useConfig; exports.useCustomerKey = _chunkGU63WFXIcjs.useCustomerKey; exports.useFilterValues = _chunkGU63WFXIcjs.useFilterValues; exports.useProduct = _chunkGU63WFXIcjs.useProduct; exports.useProducts = _chunkGU63WFXIcjs.useProducts; exports.useRelated = _chunkGU63WFXIcjs.useRelated; exports.useReviews = _chunkGU63WFXIcjs.useReviews; exports.useSubmitReview = useSubmitReview; exports.useSuggest = _chunkGU63WFXIcjs.useSuggest;
815
+
816
+
817
+ exports.CatalogProvider = _chunkOKWXS3FDcjs.CatalogProvider; exports.SDK_VERSION = _chunkJ2GHGQY6cjs.SDK_VERSION; exports.catalogQueryKey = _chunkOKWXS3FDcjs.catalogQueryKey; exports.createMemoryCartStorage = _chunkOKWXS3FDcjs.createMemoryCartStorage; exports.useCart = useCart; exports.useCatalog = _chunkOKWXS3FDcjs.useCatalog; exports.useCategories = _chunkOKWXS3FDcjs.useCategories; exports.useCollection = _chunkOKWXS3FDcjs.useCollection; exports.useConfig = _chunkOKWXS3FDcjs.useConfig; exports.useCustomerKey = _chunkOKWXS3FDcjs.useCustomerKey; exports.useFilterValues = _chunkOKWXS3FDcjs.useFilterValues; exports.useGenerationWatch = _chunkOKWXS3FDcjs.useGenerationWatch; exports.useProduct = _chunkOKWXS3FDcjs.useProduct; exports.useProducts = _chunkOKWXS3FDcjs.useProducts; exports.useRelated = _chunkOKWXS3FDcjs.useRelated; exports.useReviews = _chunkOKWXS3FDcjs.useReviews; exports.useStorefrontSettings = _chunkOKWXS3FDcjs.useStorefrontSettings; exports.useSubmitReview = useSubmitReview; exports.useSuggest = _chunkOKWXS3FDcjs.useSuggest;
package/dist/react.d.cts CHANGED
@@ -1,11 +1,11 @@
1
1
  export { ReviewEligibility } from './index.cjs';
2
2
  import { ReactNode } from 'react';
3
3
  import { CatalogClient } from './index.cjs';
4
- import { C as CustomerCartSource } from './types-D0PywKnN.cjs';
4
+ import { C as CustomerCartSource } from './types-jNpOwEUw.cjs';
5
5
  import { CategoryTreeDepth, ProductsQuery, ThrottleCart, CartWarning } from './index.cjs';
6
- export { O as OpenCartRef } from './types-D0PywKnN.cjs';
7
- import { Q as QueryOptions, a as QueryResult } from './use-query-UWf6Pi5g.cjs';
8
- export { c as catalogQueryKey } from './use-query-UWf6Pi5g.cjs';
6
+ export { O as OpenCartRef } from './types-jNpOwEUw.cjs';
7
+ import { Q as QueryOptions, a as QueryResult } from './use-query-H1xgL3_e.cjs';
8
+ export { c as catalogQueryKey } from './use-query-H1xgL3_e.cjs';
9
9
  import { CatalogError } from './admin.cjs';
10
10
  import { ReviewSubmitAnswer, ReviewSubmitInput } from './index.cjs';
11
11
  export { S as SDK_VERSION } from './version-ev3p03v2.cjs';
@@ -99,6 +99,23 @@ declare function useReviews(handle: string | null, options?: QueryOptions<Answer
99
99
  cursor?: string;
100
100
  }): QueryResult<Answer<ReviewsList>>;
101
101
  declare function useConfig(options?: QueryOptions<Answer<CatalogClient['config']>>): QueryResult<Answer<CatalogClient['config']>>;
102
+ /** The storefront settings with what versions them: `{ settings, settingsVersion, generation }`. */
103
+ declare function useStorefrontSettings(options?: QueryOptions<Answer<CatalogClient['settings']>>): QueryResult<Answer<CatalogClient['settings']>>;
104
+ /**
105
+ * Watches the storefront's generation: every `intervalMs` (60 s), while the
106
+ * page is visible, it asks `config` (conditionally, so an unchanged answer is
107
+ * a `304`), and checks at once when the page becomes visible after being
108
+ * hidden for at least the interval (or before a first answer). When the
109
+ * generation changes, the provider's cache is invalidated (hooks on screen
110
+ * keep their data and read again) and every mounted watcher's `onChange` is
111
+ * called once with the new generation. One timer and one request per
112
+ * provider however many watchers are mounted (the first one's `intervalMs`
113
+ * applies). Nothing runs on the server.
114
+ */
115
+ declare function useGenerationWatch({ intervalMs, onChange, }?: {
116
+ intervalMs?: number;
117
+ onChange?: (generation: number) => void;
118
+ }): void;
102
119
  /** The values of one filter for a selection. */
103
120
  declare function useFilterValues(key: string | null, query?: ProductsQuery, options?: QueryOptions<Answer<CatalogClient['filters']['values']>>): QueryResult<Answer<CatalogClient['filters']['values']>>;
104
121
 
@@ -184,5 +201,5 @@ type SubmitReviewResult = SubmitReviewState & {
184
201
  */
185
202
  declare function useSubmitReview(handle: string): SubmitReviewResult;
186
203
 
187
- export { CatalogProvider, CustomerCartSource, QueryOptions, QueryResult, createMemoryCartStorage, useCart, useCatalog, useCategories, useCollection, useConfig, useCustomerKey, useFilterValues, useProduct, useProducts, useRelated, useReviews, useSubmitReview, useSuggest };
204
+ export { CatalogProvider, CustomerCartSource, QueryOptions, QueryResult, createMemoryCartStorage, useCart, useCatalog, useCategories, useCollection, useConfig, useCustomerKey, useFilterValues, useGenerationWatch, useProduct, useProducts, useRelated, useReviews, useStorefrontSettings, useSubmitReview, useSuggest };
188
205
  export type { CartOptions, CartState, CartStorage, CartUrls, CatalogProviderProps, SubmitReviewResult, SubmitReviewState, UseCartResult };
package/dist/react.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  export { ReviewEligibility } from './index.js';
2
2
  import { ReactNode } from 'react';
3
3
  import { CatalogClient } from './index.js';
4
- import { C as CustomerCartSource } from './types-BfveENg1.js';
4
+ import { C as CustomerCartSource } from './types-z57bkjjB.js';
5
5
  import { CategoryTreeDepth, ProductsQuery, ThrottleCart, CartWarning } from './index.js';
6
- export { O as OpenCartRef } from './types-BfveENg1.js';
7
- import { Q as QueryOptions, a as QueryResult } from './use-query-CR7r5tam.js';
8
- export { c as catalogQueryKey } from './use-query-CR7r5tam.js';
6
+ export { O as OpenCartRef } from './types-z57bkjjB.js';
7
+ import { Q as QueryOptions, a as QueryResult } from './use-query-COqRZJnC.js';
8
+ export { c as catalogQueryKey } from './use-query-COqRZJnC.js';
9
9
  import { CatalogError } from './admin.js';
10
10
  import { ReviewSubmitAnswer, ReviewSubmitInput } from './index.js';
11
11
  export { S as SDK_VERSION } from './version-ev3p03v2.js';
@@ -99,6 +99,23 @@ declare function useReviews(handle: string | null, options?: QueryOptions<Answer
99
99
  cursor?: string;
100
100
  }): QueryResult<Answer<ReviewsList>>;
101
101
  declare function useConfig(options?: QueryOptions<Answer<CatalogClient['config']>>): QueryResult<Answer<CatalogClient['config']>>;
102
+ /** The storefront settings with what versions them: `{ settings, settingsVersion, generation }`. */
103
+ declare function useStorefrontSettings(options?: QueryOptions<Answer<CatalogClient['settings']>>): QueryResult<Answer<CatalogClient['settings']>>;
104
+ /**
105
+ * Watches the storefront's generation: every `intervalMs` (60 s), while the
106
+ * page is visible, it asks `config` (conditionally, so an unchanged answer is
107
+ * a `304`), and checks at once when the page becomes visible after being
108
+ * hidden for at least the interval (or before a first answer). When the
109
+ * generation changes, the provider's cache is invalidated (hooks on screen
110
+ * keep their data and read again) and every mounted watcher's `onChange` is
111
+ * called once with the new generation. One timer and one request per
112
+ * provider however many watchers are mounted (the first one's `intervalMs`
113
+ * applies). Nothing runs on the server.
114
+ */
115
+ declare function useGenerationWatch({ intervalMs, onChange, }?: {
116
+ intervalMs?: number;
117
+ onChange?: (generation: number) => void;
118
+ }): void;
102
119
  /** The values of one filter for a selection. */
103
120
  declare function useFilterValues(key: string | null, query?: ProductsQuery, options?: QueryOptions<Answer<CatalogClient['filters']['values']>>): QueryResult<Answer<CatalogClient['filters']['values']>>;
104
121
 
@@ -184,5 +201,5 @@ type SubmitReviewResult = SubmitReviewState & {
184
201
  */
185
202
  declare function useSubmitReview(handle: string): SubmitReviewResult;
186
203
 
187
- export { CatalogProvider, CustomerCartSource, QueryOptions, QueryResult, createMemoryCartStorage, useCart, useCatalog, useCategories, useCollection, useConfig, useCustomerKey, useFilterValues, useProduct, useProducts, useRelated, useReviews, useSubmitReview, useSuggest };
204
+ export { CatalogProvider, CustomerCartSource, QueryOptions, QueryResult, createMemoryCartStorage, useCart, useCatalog, useCategories, useCollection, useConfig, useCustomerKey, useFilterValues, useGenerationWatch, useProduct, useProducts, useRelated, useReviews, useStorefrontSettings, useSubmitReview, useSuggest };
188
205
  export type { CartOptions, CartState, CartStorage, CartUrls, CatalogProviderProps, SubmitReviewResult, SubmitReviewState, UseCartResult };
package/dist/react.js CHANGED
@@ -10,12 +10,14 @@ 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-CADIHOIR.js";
20
+ } from "./chunk-3FX2HISB.js";
19
21
  import {
20
22
  CatalogError,
21
23
  RateLimitedError,
@@ -23,7 +25,7 @@ import {
23
25
  THROTTLE_CHECKOUT_URL,
24
26
  formatMoney,
25
27
  isCatalogError
26
- } from "./chunk-3DLH56OX.js";
28
+ } from "./chunk-VJHA7J7B.js";
27
29
  import "./chunk-PKBMQBKP.js";
28
30
 
29
31
  // src/react/use-cart.ts
@@ -804,10 +806,12 @@ export {
804
806
  useConfig,
805
807
  useCustomerKey,
806
808
  useFilterValues,
809
+ useGenerationWatch,
807
810
  useProduct,
808
811
  useProducts,
809
812
  useRelated,
810
813
  useReviews,
814
+ useStorefrontSettings,
811
815
  useSubmitReview,
812
816
  useSuggest
813
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 _chunk2YQNMBDIcjs = require('./chunk-2YQNMBDI.cjs');
13
- require('./chunk-ETV4XYOV.cjs');
14
16
 
15
- // src/server/tags.ts
16
- function catalogTags(route, handle) {
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
- }
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]), () => ( _chunk2YQNMBDIcjs.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, () => ( _chunk2YQNMBDIcjs.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 _chunk2YQNMBDIcjs.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, () => ( _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)
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, _chunk2YQNMBDIcjs.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: _chunk2YQNMBDIcjs.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 = _chunk2YQNMBDIcjs.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;