@usethrottle/catalog 1.3.0 → 1.4.1
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 +22 -0
- package/README.md +105 -9
- package/dist/admin.cjs +16 -16
- package/dist/admin.d.cts +14 -2
- package/dist/admin.d.ts +14 -2
- package/dist/admin.js +1 -1
- package/dist/{catalog-error-BOaSKgY3.d.cts → catalog-error-bG1XHquN.d.cts} +1 -1
- package/dist/{catalog-error-CSoPS0-d.d.ts → catalog-error-c3BVgU6k.d.ts} +1 -1
- package/dist/{chunk-2YQNMBDI.cjs → chunk-2ODFFMZ4.cjs} +274 -38
- package/dist/chunk-5AJS3CX5.cjs +192 -0
- package/dist/{chunk-CADIHOIR.js → chunk-6K7H7HBD.js} +89 -2
- package/dist/chunk-P3ABGAF5.js +192 -0
- package/dist/{chunk-3DLH56OX.js → chunk-STNQNHNZ.js} +258 -22
- package/dist/{chunk-GU63WFXI.cjs → chunk-VOOX3WJY.cjs} +102 -15
- package/dist/{client-6j1Iz-iJ.d.cts → client-CGGlbacq.d.cts} +1 -1
- package/dist/{client-B3mL2-xJ.d.ts → client-CNsVr2lR.d.ts} +1 -1
- package/dist/{contract-types-BRyonOYH.d.cts → contract-types-BJMeJSTz.d.cts} +269 -2
- package/dist/{contract-types-BRyonOYH.d.ts → contract-types-BJMeJSTz.d.ts} +269 -2
- package/dist/index.cjs +12 -2
- package/dist/index.d.cts +53 -7
- package/dist/index.d.ts +53 -7
- package/dist/index.js +11 -1
- package/dist/next.cjs +180 -0
- package/dist/next.d.cts +60 -0
- package/dist/next.d.ts +60 -0
- package/dist/next.js +180 -0
- package/dist/react-extras.cjs +27 -9
- package/dist/react-extras.d.cts +6 -4
- package/dist/react-extras.d.ts +6 -4
- package/dist/react-extras.js +20 -2
- package/dist/react.cjs +18 -14
- package/dist/react.d.cts +22 -5
- package/dist/react.d.ts +22 -5
- package/dist/react.js +6 -2
- package/dist/server.cjs +58 -66
- package/dist/server.d.cts +57 -10
- package/dist/server.d.ts +57 -10
- package/dist/server.js +52 -60
- package/dist/{types-D0PywKnN.d.cts → types-BtBxMbM5.d.cts} +40 -3
- package/dist/{types-BfveENg1.d.ts → types-dKvIfrVH.d.ts} +40 -3
- package/dist/url.d.cts +1 -1
- package/dist/url.d.ts +1 -1
- package/dist/{use-query-UWf6Pi5g.d.cts → use-query-C2rfTJd4.d.cts} +1 -1
- package/dist/{use-query-CR7r5tam.d.ts → use-query-DeCj1hXt.d.ts} +1 -1
- package/package.json +16 -2
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _chunk2ODFFMZ4cjs = require('./chunk-2ODFFMZ4.cjs');
|
|
6
|
+
|
|
7
|
+
// src/server/cache-policy.ts
|
|
8
|
+
var UNTIL_CHANGED_REVALIDATE_S = 3600;
|
|
9
|
+
var DEFAULT_CACHE_POLICY = {
|
|
10
|
+
settings: "until-changed",
|
|
11
|
+
navigation: "until-changed",
|
|
12
|
+
pages: "until-changed",
|
|
13
|
+
product: "until-changed",
|
|
14
|
+
listings: "60s",
|
|
15
|
+
facets: "60s",
|
|
16
|
+
related: "60s",
|
|
17
|
+
reviews: "60s",
|
|
18
|
+
search: "60s"
|
|
19
|
+
};
|
|
20
|
+
function decode(segment) {
|
|
21
|
+
try {
|
|
22
|
+
return decodeURIComponent(segment);
|
|
23
|
+
} catch (e) {
|
|
24
|
+
return segment;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function storefrontRoute(path) {
|
|
28
|
+
const bare = _nullishCoalesce(path.split(/[?#]/u, 1)[0], () => ( ""));
|
|
29
|
+
const at = bare.indexOf("/v1/storefront/");
|
|
30
|
+
const parts = (at < 0 ? bare : bare.slice(at + 15)).replace(/^\//u, "");
|
|
31
|
+
const [first, segment, sub, extra] = parts.split("/");
|
|
32
|
+
if (extra !== void 0) return null;
|
|
33
|
+
if (segment === void 0) {
|
|
34
|
+
switch (first) {
|
|
35
|
+
case "config":
|
|
36
|
+
case "products":
|
|
37
|
+
case "pages":
|
|
38
|
+
case "categories":
|
|
39
|
+
case "tags":
|
|
40
|
+
case "collections":
|
|
41
|
+
case "suggest":
|
|
42
|
+
return { route: 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" ? { route: "filters" } : null;
|
|
52
|
+
case "products":
|
|
53
|
+
if (sub === "related" || sub === "reviews") return { route: sub, handle };
|
|
54
|
+
return sub === void 0 ? { route: "product", handle } : null;
|
|
55
|
+
case "pages":
|
|
56
|
+
return sub === void 0 ? { route: "page", handle } : null;
|
|
57
|
+
case "categories":
|
|
58
|
+
return sub === void 0 ? { route: "category", handle } : null;
|
|
59
|
+
case "collections":
|
|
60
|
+
return sub === void 0 ? { route: "collection", handle } : null;
|
|
61
|
+
default:
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
var KIND_OF_ROUTE = {
|
|
66
|
+
config: "settings",
|
|
67
|
+
pages: "pages",
|
|
68
|
+
page: "pages",
|
|
69
|
+
products: "listings",
|
|
70
|
+
product: "product",
|
|
71
|
+
related: "related",
|
|
72
|
+
reviews: "reviews",
|
|
73
|
+
filters: "facets",
|
|
74
|
+
suggest: "search",
|
|
75
|
+
categories: "listings",
|
|
76
|
+
category: "listings",
|
|
77
|
+
collections: "listings",
|
|
78
|
+
collection: "listings",
|
|
79
|
+
tags: "listings"
|
|
80
|
+
};
|
|
81
|
+
function cacheKindForPath(path) {
|
|
82
|
+
const found = storefrontRoute(path);
|
|
83
|
+
return found === null ? null : _nullishCoalesce(KIND_OF_ROUTE[found.route], () => ( null));
|
|
84
|
+
}
|
|
85
|
+
var DURATION = /^(\d+)([sm])$/u;
|
|
86
|
+
function policyToNext(policy) {
|
|
87
|
+
if (policy === "no-store") return "no-store";
|
|
88
|
+
if (policy === "until-changed")
|
|
89
|
+
return { revalidate: UNTIL_CHANGED_REVALIDATE_S };
|
|
90
|
+
const match = typeof policy === "string" ? DURATION.exec(policy) : null;
|
|
91
|
+
if (match === null) {
|
|
92
|
+
throw new (0, _chunk2ODFFMZ4cjs.CatalogError)({
|
|
93
|
+
code: "INVALID_REQUEST",
|
|
94
|
+
message: "A cache policy is 'until-changed', 'no-store' or a duration such as '90s' or '5m'.",
|
|
95
|
+
statusCode: 0,
|
|
96
|
+
source: "client",
|
|
97
|
+
retryable: false
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const seconds = Number(match[1]) * (match[2] === "m" ? 60 : 1);
|
|
101
|
+
return seconds === 0 ? "no-store" : { revalidate: seconds };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/server/min-generation.ts
|
|
105
|
+
var EVERY_STORE = Symbol("every-store");
|
|
106
|
+
var floors = /* @__PURE__ */ new Map();
|
|
107
|
+
function noteMinGeneration(generation, floorKey) {
|
|
108
|
+
if (!Number.isSafeInteger(generation) || generation < 0) return;
|
|
109
|
+
const key = _nullishCoalesce(floorKey, () => ( EVERY_STORE));
|
|
110
|
+
const known = floors.get(key);
|
|
111
|
+
if (known === void 0 || generation > known) floors.set(key, generation);
|
|
112
|
+
}
|
|
113
|
+
function pendingMinGeneration(floorKey) {
|
|
114
|
+
const own = floors.get(floorKey);
|
|
115
|
+
const every = floors.get(EVERY_STORE);
|
|
116
|
+
return own === void 0 || every !== void 0 && every > own ? every : own;
|
|
117
|
+
}
|
|
118
|
+
function observeGeneration(generation, floorKey) {
|
|
119
|
+
if (typeof generation !== "number") return;
|
|
120
|
+
for (const key of [floorKey, EVERY_STORE]) {
|
|
121
|
+
const floor = floors.get(key);
|
|
122
|
+
if (floor !== void 0 && generation >= floor) floors.delete(key);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/server/tags.ts
|
|
127
|
+
function familyOf(route) {
|
|
128
|
+
if (route === "config") return "config";
|
|
129
|
+
return route === "pages" || route === "page" ? "pages" : "data";
|
|
130
|
+
}
|
|
131
|
+
function catalogTags(route, handle) {
|
|
132
|
+
const tags = [_chunk2ODFFMZ4cjs.CACHE_TAG, `${_chunk2ODFFMZ4cjs.CACHE_TAG}:${familyOf(route)}`];
|
|
133
|
+
if (route !== familyOf(route)) tags.push(`${_chunk2ODFFMZ4cjs.CACHE_TAG}:${route}`);
|
|
134
|
+
if (handle !== void 0) tags.push(`${_chunk2ODFFMZ4cjs.CACHE_TAG}:${route}:${handle}`);
|
|
135
|
+
return tags.filter((tag) => tag.length <= _chunk2ODFFMZ4cjs.TAG_MAX_CHARS);
|
|
136
|
+
}
|
|
137
|
+
function tagsForUrl(url, storefront) {
|
|
138
|
+
const path = _nullishCoalesce(url.split(/[?#]/u, 1)[0], () => ( ""));
|
|
139
|
+
if (!path.startsWith(storefront)) return null;
|
|
140
|
+
const found = storefrontRoute(path.slice(storefront.length));
|
|
141
|
+
return found === null ? null : catalogTags(found.route, found.handle);
|
|
142
|
+
}
|
|
143
|
+
var family = (name) => `${_chunk2ODFFMZ4cjs.CACHE_TAG}:${name}`;
|
|
144
|
+
function tagsForScope(scope) {
|
|
145
|
+
const colon = scope.indexOf(":");
|
|
146
|
+
const name = colon < 0 ? scope : scope.slice(0, colon);
|
|
147
|
+
const handle = colon < 0 ? "" : scope.slice(colon + 1);
|
|
148
|
+
switch (scope) {
|
|
149
|
+
case "settings":
|
|
150
|
+
case "navigation":
|
|
151
|
+
return [family("config")];
|
|
152
|
+
case "filters":
|
|
153
|
+
return [family("config"), family("data")];
|
|
154
|
+
case "pages":
|
|
155
|
+
return [family("pages")];
|
|
156
|
+
case "taxonomy":
|
|
157
|
+
case "catalog":
|
|
158
|
+
return [family("data")];
|
|
159
|
+
}
|
|
160
|
+
if (handle !== "") {
|
|
161
|
+
if (name === "product" || name === "collection" || name === "category")
|
|
162
|
+
return [`${family(name)}:${handle}`, family("data")];
|
|
163
|
+
if (name === "reviews")
|
|
164
|
+
return [
|
|
165
|
+
`${family("reviews")}:${handle}`,
|
|
166
|
+
`${family("product")}:${handle}`
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
return [family("data")];
|
|
170
|
+
}
|
|
171
|
+
function scopesToTags(scopes) {
|
|
172
|
+
const out = /* @__PURE__ */ new Set();
|
|
173
|
+
for (const scope of scopes) {
|
|
174
|
+
for (const tag of tagsForScope(scope)) {
|
|
175
|
+
if (tag.length <= _chunk2ODFFMZ4cjs.TAG_MAX_CHARS) out.add(tag);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return [...out];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
exports.DEFAULT_CACHE_POLICY = DEFAULT_CACHE_POLICY; exports.storefrontRoute = storefrontRoute; exports.cacheKindForPath = cacheKindForPath; exports.policyToNext = policyToNext; exports.noteMinGeneration = noteMinGeneration; exports.pendingMinGeneration = pendingMinGeneration; exports.observeGeneration = observeGeneration; exports.catalogTags = catalogTags; exports.tagsForUrl = tagsForUrl; exports.scopesToTags = scopesToTags;
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
STALE_MS,
|
|
7
7
|
SUGGEST_DEBOUNCE_MS,
|
|
8
8
|
SUGGEST_MIN_CHARS
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-STNQNHNZ.js";
|
|
10
10
|
|
|
11
11
|
// src/react/provider.tsx
|
|
12
12
|
import {
|
|
@@ -183,6 +183,21 @@ function createStore(client, options = {}) {
|
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
|
+
function invalidate() {
|
|
187
|
+
for (const [key, entry] of [...entries]) {
|
|
188
|
+
clearTimeout(entry.timer);
|
|
189
|
+
clearTimeout(entry.retry);
|
|
190
|
+
entry.flight?.abort();
|
|
191
|
+
if (entry.subs.size === 0) {
|
|
192
|
+
entries.delete(key);
|
|
193
|
+
} else {
|
|
194
|
+
entry.etag = entry.flight = entry.promise = void 0;
|
|
195
|
+
entry.indexing = false;
|
|
196
|
+
entry.retries = 0;
|
|
197
|
+
if (entry.run) void fetchKey(key, entry.run, { force: true });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
186
201
|
return {
|
|
187
202
|
subscribe(key, listener) {
|
|
188
203
|
const entry = touch(key);
|
|
@@ -202,6 +217,7 @@ function createStore(client, options = {}) {
|
|
|
202
217
|
},
|
|
203
218
|
fetch: fetchKey,
|
|
204
219
|
clear,
|
|
220
|
+
invalidate,
|
|
205
221
|
pause,
|
|
206
222
|
pausedUntil: () => until > now() ? until : 0,
|
|
207
223
|
dispose() {
|
|
@@ -360,7 +376,7 @@ function useQuery(route, params, run, options = {}) {
|
|
|
360
376
|
}
|
|
361
377
|
|
|
362
378
|
// src/react/hooks.ts
|
|
363
|
-
import { useEffect as useEffect3, useMemo as useMemo2, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
379
|
+
import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
364
380
|
function defined(options) {
|
|
365
381
|
const out = {};
|
|
366
382
|
for (const name in options) {
|
|
@@ -466,6 +482,75 @@ function useConfig(options) {
|
|
|
466
482
|
options
|
|
467
483
|
);
|
|
468
484
|
}
|
|
485
|
+
function useStorefrontSettings(options) {
|
|
486
|
+
return useQuery(
|
|
487
|
+
"settings",
|
|
488
|
+
null,
|
|
489
|
+
(client, call) => client.settings(call),
|
|
490
|
+
options
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
var watches = /* @__PURE__ */ new WeakMap();
|
|
494
|
+
var watchRun = (client, call) => client.config(call);
|
|
495
|
+
var pageDocument = () => Reflect.get(globalThis, "document");
|
|
496
|
+
function watch(store, intervalMs, listener) {
|
|
497
|
+
let w = watches.get(store);
|
|
498
|
+
if (w === void 0) {
|
|
499
|
+
const key = `\0${catalogQueryKey("generation", null)}`;
|
|
500
|
+
const visible = () => pageDocument().visibilityState === "visible";
|
|
501
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
502
|
+
let known;
|
|
503
|
+
let hiddenAt = visible() ? 0 : Date.now();
|
|
504
|
+
const check = async () => {
|
|
505
|
+
if (!visible()) return;
|
|
506
|
+
await store.fetch(key, watchRun, { force: true });
|
|
507
|
+
const data = store.get(key).data;
|
|
508
|
+
if (watches.get(store) !== w || data?.generation === void 0) return;
|
|
509
|
+
const changed = known !== void 0 && data.generation !== known;
|
|
510
|
+
known = data.generation;
|
|
511
|
+
if (changed) {
|
|
512
|
+
store.invalidate();
|
|
513
|
+
for (const { current } of [...listeners]) current?.(known);
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
const onVisibility = () => {
|
|
517
|
+
if (!visible()) hiddenAt = Date.now();
|
|
518
|
+
else {
|
|
519
|
+
if (known === void 0 || Date.now() - hiddenAt >= intervalMs)
|
|
520
|
+
void check();
|
|
521
|
+
hiddenAt = 0;
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
void check();
|
|
525
|
+
const timer = setInterval(() => void check(), intervalMs);
|
|
526
|
+
const doc = pageDocument();
|
|
527
|
+
doc.addEventListener("visibilitychange", onVisibility);
|
|
528
|
+
w = {
|
|
529
|
+
listeners,
|
|
530
|
+
stop() {
|
|
531
|
+
clearInterval(timer);
|
|
532
|
+
doc.removeEventListener("visibilitychange", onVisibility);
|
|
533
|
+
watches.delete(store);
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
watches.set(store, w);
|
|
537
|
+
}
|
|
538
|
+
const mine = w;
|
|
539
|
+
mine.listeners.add(listener);
|
|
540
|
+
return () => {
|
|
541
|
+
mine.listeners.delete(listener);
|
|
542
|
+
if (mine.listeners.size === 0) mine.stop();
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
function useGenerationWatch({
|
|
546
|
+
intervalMs = 6e4,
|
|
547
|
+
onChange
|
|
548
|
+
} = {}) {
|
|
549
|
+
const { store } = useCatalogContext();
|
|
550
|
+
const latest = useRef3(onChange);
|
|
551
|
+
latest.current = onChange;
|
|
552
|
+
useEffect3(() => watch(store, intervalMs, latest), [store, intervalMs]);
|
|
553
|
+
}
|
|
469
554
|
function useFilterValues(key, query = {}, options) {
|
|
470
555
|
return useQuery(
|
|
471
556
|
"filterValues",
|
|
@@ -492,5 +577,7 @@ export {
|
|
|
492
577
|
useCollection,
|
|
493
578
|
useReviews,
|
|
494
579
|
useConfig,
|
|
580
|
+
useStorefrontSettings,
|
|
581
|
+
useGenerationWatch,
|
|
495
582
|
useFilterValues
|
|
496
583
|
};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CACHE_TAG,
|
|
3
|
+
CatalogError,
|
|
4
|
+
TAG_MAX_CHARS
|
|
5
|
+
} from "./chunk-STNQNHNZ.js";
|
|
6
|
+
|
|
7
|
+
// src/server/cache-policy.ts
|
|
8
|
+
var UNTIL_CHANGED_REVALIDATE_S = 3600;
|
|
9
|
+
var DEFAULT_CACHE_POLICY = {
|
|
10
|
+
settings: "until-changed",
|
|
11
|
+
navigation: "until-changed",
|
|
12
|
+
pages: "until-changed",
|
|
13
|
+
product: "until-changed",
|
|
14
|
+
listings: "60s",
|
|
15
|
+
facets: "60s",
|
|
16
|
+
related: "60s",
|
|
17
|
+
reviews: "60s",
|
|
18
|
+
search: "60s"
|
|
19
|
+
};
|
|
20
|
+
function decode(segment) {
|
|
21
|
+
try {
|
|
22
|
+
return decodeURIComponent(segment);
|
|
23
|
+
} catch {
|
|
24
|
+
return segment;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function storefrontRoute(path) {
|
|
28
|
+
const bare = path.split(/[?#]/u, 1)[0] ?? "";
|
|
29
|
+
const at = bare.indexOf("/v1/storefront/");
|
|
30
|
+
const parts = (at < 0 ? bare : bare.slice(at + 15)).replace(/^\//u, "");
|
|
31
|
+
const [first, segment, sub, extra] = parts.split("/");
|
|
32
|
+
if (extra !== void 0) return null;
|
|
33
|
+
if (segment === void 0) {
|
|
34
|
+
switch (first) {
|
|
35
|
+
case "config":
|
|
36
|
+
case "products":
|
|
37
|
+
case "pages":
|
|
38
|
+
case "categories":
|
|
39
|
+
case "tags":
|
|
40
|
+
case "collections":
|
|
41
|
+
case "suggest":
|
|
42
|
+
return { route: 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" ? { route: "filters" } : null;
|
|
52
|
+
case "products":
|
|
53
|
+
if (sub === "related" || sub === "reviews") return { route: sub, handle };
|
|
54
|
+
return sub === void 0 ? { route: "product", handle } : null;
|
|
55
|
+
case "pages":
|
|
56
|
+
return sub === void 0 ? { route: "page", handle } : null;
|
|
57
|
+
case "categories":
|
|
58
|
+
return sub === void 0 ? { route: "category", handle } : null;
|
|
59
|
+
case "collections":
|
|
60
|
+
return sub === void 0 ? { route: "collection", handle } : null;
|
|
61
|
+
default:
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
var KIND_OF_ROUTE = {
|
|
66
|
+
config: "settings",
|
|
67
|
+
pages: "pages",
|
|
68
|
+
page: "pages",
|
|
69
|
+
products: "listings",
|
|
70
|
+
product: "product",
|
|
71
|
+
related: "related",
|
|
72
|
+
reviews: "reviews",
|
|
73
|
+
filters: "facets",
|
|
74
|
+
suggest: "search",
|
|
75
|
+
categories: "listings",
|
|
76
|
+
category: "listings",
|
|
77
|
+
collections: "listings",
|
|
78
|
+
collection: "listings",
|
|
79
|
+
tags: "listings"
|
|
80
|
+
};
|
|
81
|
+
function cacheKindForPath(path) {
|
|
82
|
+
const found = storefrontRoute(path);
|
|
83
|
+
return found === null ? null : KIND_OF_ROUTE[found.route] ?? null;
|
|
84
|
+
}
|
|
85
|
+
var DURATION = /^(\d+)([sm])$/u;
|
|
86
|
+
function policyToNext(policy) {
|
|
87
|
+
if (policy === "no-store") return "no-store";
|
|
88
|
+
if (policy === "until-changed")
|
|
89
|
+
return { revalidate: UNTIL_CHANGED_REVALIDATE_S };
|
|
90
|
+
const match = typeof policy === "string" ? DURATION.exec(policy) : null;
|
|
91
|
+
if (match === null) {
|
|
92
|
+
throw new CatalogError({
|
|
93
|
+
code: "INVALID_REQUEST",
|
|
94
|
+
message: "A cache policy is 'until-changed', 'no-store' or a duration such as '90s' or '5m'.",
|
|
95
|
+
statusCode: 0,
|
|
96
|
+
source: "client",
|
|
97
|
+
retryable: false
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
const seconds = Number(match[1]) * (match[2] === "m" ? 60 : 1);
|
|
101
|
+
return seconds === 0 ? "no-store" : { revalidate: seconds };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/server/min-generation.ts
|
|
105
|
+
var EVERY_STORE = Symbol("every-store");
|
|
106
|
+
var floors = /* @__PURE__ */ new Map();
|
|
107
|
+
function noteMinGeneration(generation, floorKey) {
|
|
108
|
+
if (!Number.isSafeInteger(generation) || generation < 0) return;
|
|
109
|
+
const key = floorKey ?? EVERY_STORE;
|
|
110
|
+
const known = floors.get(key);
|
|
111
|
+
if (known === void 0 || generation > known) floors.set(key, generation);
|
|
112
|
+
}
|
|
113
|
+
function pendingMinGeneration(floorKey) {
|
|
114
|
+
const own = floors.get(floorKey);
|
|
115
|
+
const every = floors.get(EVERY_STORE);
|
|
116
|
+
return own === void 0 || every !== void 0 && every > own ? every : own;
|
|
117
|
+
}
|
|
118
|
+
function observeGeneration(generation, floorKey) {
|
|
119
|
+
if (typeof generation !== "number") return;
|
|
120
|
+
for (const key of [floorKey, EVERY_STORE]) {
|
|
121
|
+
const floor = floors.get(key);
|
|
122
|
+
if (floor !== void 0 && generation >= floor) floors.delete(key);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/server/tags.ts
|
|
127
|
+
function familyOf(route) {
|
|
128
|
+
if (route === "config") return "config";
|
|
129
|
+
return route === "pages" || route === "page" ? "pages" : "data";
|
|
130
|
+
}
|
|
131
|
+
function catalogTags(route, handle) {
|
|
132
|
+
const tags = [CACHE_TAG, `${CACHE_TAG}:${familyOf(route)}`];
|
|
133
|
+
if (route !== familyOf(route)) tags.push(`${CACHE_TAG}:${route}`);
|
|
134
|
+
if (handle !== void 0) tags.push(`${CACHE_TAG}:${route}:${handle}`);
|
|
135
|
+
return tags.filter((tag) => tag.length <= TAG_MAX_CHARS);
|
|
136
|
+
}
|
|
137
|
+
function tagsForUrl(url, storefront) {
|
|
138
|
+
const path = url.split(/[?#]/u, 1)[0] ?? "";
|
|
139
|
+
if (!path.startsWith(storefront)) return null;
|
|
140
|
+
const found = storefrontRoute(path.slice(storefront.length));
|
|
141
|
+
return found === null ? null : catalogTags(found.route, found.handle);
|
|
142
|
+
}
|
|
143
|
+
var family = (name) => `${CACHE_TAG}:${name}`;
|
|
144
|
+
function tagsForScope(scope) {
|
|
145
|
+
const colon = scope.indexOf(":");
|
|
146
|
+
const name = colon < 0 ? scope : scope.slice(0, colon);
|
|
147
|
+
const handle = colon < 0 ? "" : scope.slice(colon + 1);
|
|
148
|
+
switch (scope) {
|
|
149
|
+
case "settings":
|
|
150
|
+
case "navigation":
|
|
151
|
+
return [family("config")];
|
|
152
|
+
case "filters":
|
|
153
|
+
return [family("config"), family("data")];
|
|
154
|
+
case "pages":
|
|
155
|
+
return [family("pages")];
|
|
156
|
+
case "taxonomy":
|
|
157
|
+
case "catalog":
|
|
158
|
+
return [family("data")];
|
|
159
|
+
}
|
|
160
|
+
if (handle !== "") {
|
|
161
|
+
if (name === "product" || name === "collection" || name === "category")
|
|
162
|
+
return [`${family(name)}:${handle}`, family("data")];
|
|
163
|
+
if (name === "reviews")
|
|
164
|
+
return [
|
|
165
|
+
`${family("reviews")}:${handle}`,
|
|
166
|
+
`${family("product")}:${handle}`
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
return [family("data")];
|
|
170
|
+
}
|
|
171
|
+
function scopesToTags(scopes) {
|
|
172
|
+
const out = /* @__PURE__ */ new Set();
|
|
173
|
+
for (const scope of scopes) {
|
|
174
|
+
for (const tag of tagsForScope(scope)) {
|
|
175
|
+
if (tag.length <= TAG_MAX_CHARS) out.add(tag);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return [...out];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export {
|
|
182
|
+
DEFAULT_CACHE_POLICY,
|
|
183
|
+
storefrontRoute,
|
|
184
|
+
cacheKindForPath,
|
|
185
|
+
policyToNext,
|
|
186
|
+
noteMinGeneration,
|
|
187
|
+
pendingMinGeneration,
|
|
188
|
+
observeGeneration,
|
|
189
|
+
catalogTags,
|
|
190
|
+
tagsForUrl,
|
|
191
|
+
scopesToTags
|
|
192
|
+
};
|