@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
package/dist/next.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import {
|
|
2
|
+
noteMinGeneration,
|
|
3
|
+
scopesToTags
|
|
4
|
+
} from "./chunk-P3ABGAF5.js";
|
|
5
|
+
import {
|
|
6
|
+
SDK_VERSION,
|
|
7
|
+
TAG_MAX_CHARS
|
|
8
|
+
} from "./chunk-STNQNHNZ.js";
|
|
9
|
+
import "./chunk-PKBMQBKP.js";
|
|
10
|
+
|
|
11
|
+
// src/next/verify.ts
|
|
12
|
+
var HEX_SHA256 = /^[0-9a-fA-F]{64}$/u;
|
|
13
|
+
var TOLERANCE_SECONDS = 300;
|
|
14
|
+
var MAX_V1 = 8;
|
|
15
|
+
var MAX_HEADER_BYTES = 1024;
|
|
16
|
+
var encoder = new TextEncoder();
|
|
17
|
+
async function hmac(secret, payload) {
|
|
18
|
+
const key = await crypto.subtle.importKey(
|
|
19
|
+
"raw",
|
|
20
|
+
encoder.encode(secret),
|
|
21
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
22
|
+
false,
|
|
23
|
+
["sign"]
|
|
24
|
+
);
|
|
25
|
+
return new Uint8Array(
|
|
26
|
+
await crypto.subtle.sign("HMAC", key, encoder.encode(payload))
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
function fromHex(hex) {
|
|
30
|
+
return Uint8Array.from(
|
|
31
|
+
{ length: hex.length / 2 },
|
|
32
|
+
(_, i) => Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16)
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
function constantTimeEqual(left, right) {
|
|
36
|
+
const length = Math.max(left.length, right.length);
|
|
37
|
+
let difference = left.length ^ right.length;
|
|
38
|
+
for (let i = 0; i < length; i += 1)
|
|
39
|
+
difference |= (left[i] ?? 0) ^ (right[i] ?? 0);
|
|
40
|
+
return difference === 0;
|
|
41
|
+
}
|
|
42
|
+
async function verifyCatalogWebhook(input) {
|
|
43
|
+
try {
|
|
44
|
+
const { secret, rawBody, signature } = input;
|
|
45
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
46
|
+
if (secret.length === 0 || rawBody.length === 0 || signature.length === 0 || encoder.encode(signature).byteLength > MAX_HEADER_BYTES)
|
|
47
|
+
return false;
|
|
48
|
+
const parts = signature.split(",").map((part) => part.split("="));
|
|
49
|
+
if (parts.some((part) => part.length !== 2)) return false;
|
|
50
|
+
const timestamps = parts.filter(([k]) => k === "t").map(([, v]) => v ?? "");
|
|
51
|
+
const digests = parts.filter(([k]) => k === "v1").map(([, v]) => v ?? "");
|
|
52
|
+
if (parts.some(([k]) => k !== "t" && k !== "v1") || timestamps.length !== 1 || digests.length === 0 || digests.length > MAX_V1 || digests.some((d) => !HEX_SHA256.test(d)))
|
|
53
|
+
return false;
|
|
54
|
+
const timestampText = timestamps[0] ?? "";
|
|
55
|
+
if (!/^(?:0|[1-9][0-9]*)$/u.test(timestampText)) return false;
|
|
56
|
+
const timestamp = Number(timestampText);
|
|
57
|
+
if (!Number.isSafeInteger(timestamp) || Math.abs(now - timestamp) > TOLERANCE_SECONDS)
|
|
58
|
+
return false;
|
|
59
|
+
const expected = await hmac(secret, `${timestampText}.${rawBody}`);
|
|
60
|
+
let matched = false;
|
|
61
|
+
for (const digest of digests)
|
|
62
|
+
matched = constantTimeEqual(expected, fromHex(digest)) || matched;
|
|
63
|
+
return matched;
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/next/revalidate.ts
|
|
70
|
+
var SIGNATURE_HEADER = "x-catalog-signature";
|
|
71
|
+
var MAX_BODY_BYTES = 64 * 1024;
|
|
72
|
+
async function readCapped(req) {
|
|
73
|
+
const declared = Number(req.headers.get("content-length"));
|
|
74
|
+
if (Number.isFinite(declared) && declared > MAX_BODY_BYTES) return null;
|
|
75
|
+
if (req.body === null) return "";
|
|
76
|
+
const reader = req.body.getReader();
|
|
77
|
+
const decoder = new TextDecoder();
|
|
78
|
+
let text = "";
|
|
79
|
+
let size = 0;
|
|
80
|
+
for (; ; ) {
|
|
81
|
+
const { done, value } = await reader.read();
|
|
82
|
+
if (done) return text + decoder.decode();
|
|
83
|
+
size += value.byteLength;
|
|
84
|
+
if (size > MAX_BODY_BYTES) {
|
|
85
|
+
await reader.cancel();
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
text += decoder.decode(value, { stream: true });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
var json = (status, body) => new Response(JSON.stringify(body), {
|
|
92
|
+
status,
|
|
93
|
+
headers: {
|
|
94
|
+
"content-type": "application/json",
|
|
95
|
+
"cache-control": "no-store"
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
function parseNotice(rawBody) {
|
|
99
|
+
let value;
|
|
100
|
+
try {
|
|
101
|
+
value = JSON.parse(rawBody);
|
|
102
|
+
} catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
if (typeof value !== "object" || value === null) return null;
|
|
106
|
+
const event = value;
|
|
107
|
+
const { generation, scopes } = event;
|
|
108
|
+
if (event.type !== "storefront.changed" || typeof generation !== "number" || !Number.isSafeInteger(generation) || generation < 0 || !Array.isArray(scopes) || scopes.length === 0 || !scopes.every(
|
|
109
|
+
(scope) => typeof scope === "string" && scope.length > 0 && scope.length <= TAG_MAX_CHARS
|
|
110
|
+
) || event.test !== void 0 && typeof event.test !== "boolean")
|
|
111
|
+
return null;
|
|
112
|
+
return {
|
|
113
|
+
generation,
|
|
114
|
+
scopes,
|
|
115
|
+
test: event.test === true
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
async function defaultRevalidateTag() {
|
|
119
|
+
const { revalidateTag } = await import("next/cache");
|
|
120
|
+
return (tag) => revalidateTag(tag, { expire: 0 });
|
|
121
|
+
}
|
|
122
|
+
function createRevalidateHandler(options) {
|
|
123
|
+
return async (req) => {
|
|
124
|
+
const list = typeof options.secret === "string" || options.secret === void 0 ? [options.secret] : options.secret;
|
|
125
|
+
const secrets = list.filter(
|
|
126
|
+
(secret) => typeof secret === "string" && secret !== ""
|
|
127
|
+
);
|
|
128
|
+
if (secrets.length === 0)
|
|
129
|
+
return json(500, {
|
|
130
|
+
error: "createRevalidateHandler has no signing secret: set the webhook secret (for example THROTTLE_WEBHOOK_SECRET) in this environment."
|
|
131
|
+
});
|
|
132
|
+
const rawBody = await readCapped(req);
|
|
133
|
+
if (rawBody === null) return json(413, { error: "body too large" });
|
|
134
|
+
const signature = req.headers.get(SIGNATURE_HEADER) ?? "";
|
|
135
|
+
let verified = false;
|
|
136
|
+
for (const secret of secrets)
|
|
137
|
+
verified = await verifyCatalogWebhook({ rawBody, signature, secret }) || verified;
|
|
138
|
+
if (!verified) return json(401, { error: "invalid signature" });
|
|
139
|
+
const notice = parseNotice(rawBody);
|
|
140
|
+
if (notice === null) return json(400, { error: "invalid body" });
|
|
141
|
+
if (notice.test) return json(200, { revalidated: [] });
|
|
142
|
+
const tags = scopesToTags(notice.scopes);
|
|
143
|
+
const revalidate = options.revalidateTag ?? await defaultRevalidateTag();
|
|
144
|
+
for (const tag of tags) revalidate(tag);
|
|
145
|
+
noteMinGeneration(notice.generation, options.floorKey);
|
|
146
|
+
return json(200, { revalidated: tags });
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/next/preview.ts
|
|
151
|
+
var PREVIEW_COOKIE = "throttle_preview";
|
|
152
|
+
var PREVIEW_PARAM = "throttle_preview";
|
|
153
|
+
var PREVIEW_MAX_AGE_S = 3600;
|
|
154
|
+
function previewMiddleware(req) {
|
|
155
|
+
const url = new URL(req.url);
|
|
156
|
+
const token = url.searchParams.get(PREVIEW_PARAM);
|
|
157
|
+
if (token === null || token === "") return null;
|
|
158
|
+
url.searchParams.delete(PREVIEW_PARAM);
|
|
159
|
+
return new Response(null, {
|
|
160
|
+
status: 307,
|
|
161
|
+
headers: {
|
|
162
|
+
location: url.toString(),
|
|
163
|
+
"set-cookie": `${PREVIEW_COOKIE}=${encodeURIComponent(token)}; Max-Age=${PREVIEW_MAX_AGE_S}; Path=/; HttpOnly; Secure; SameSite=None`,
|
|
164
|
+
"cache-control": "no-store"
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
async function getPreviewToken() {
|
|
169
|
+
const { cookies } = await import("next/headers");
|
|
170
|
+
const store = await cookies();
|
|
171
|
+
const value = store.get(PREVIEW_COOKIE)?.value;
|
|
172
|
+
return value === void 0 || value === "" ? void 0 : value;
|
|
173
|
+
}
|
|
174
|
+
export {
|
|
175
|
+
SDK_VERSION,
|
|
176
|
+
createRevalidateHandler,
|
|
177
|
+
getPreviewToken,
|
|
178
|
+
noteMinGeneration,
|
|
179
|
+
previewMiddleware
|
|
180
|
+
};
|
package/dist/react-extras.cjs
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var
|
|
7
|
-
require('./chunk-
|
|
6
|
+
var _chunkVOOX3WJYcjs = require('./chunk-VOOX3WJY.cjs');
|
|
7
|
+
require('./chunk-2ODFFMZ4.cjs');
|
|
8
8
|
require('./chunk-ETV4XYOV.cjs');
|
|
9
9
|
|
|
10
10
|
// src/react/extras/index.ts
|
|
11
11
|
function useTags(options = {}) {
|
|
12
|
-
const extra =
|
|
13
|
-
return
|
|
12
|
+
const extra = _chunkVOOX3WJYcjs.defined.call(void 0, { q: options.q, limit: options.limit });
|
|
13
|
+
return _chunkVOOX3WJYcjs.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 =
|
|
22
|
-
return
|
|
21
|
+
const extra = _chunkVOOX3WJYcjs.defined.call(void 0, { limit: options.limit, cursor: options.cursor });
|
|
22
|
+
return _chunkVOOX3WJYcjs.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 =
|
|
31
|
-
return
|
|
30
|
+
const customerKey = _chunkVOOX3WJYcjs.useCustomerKey.call(void 0, );
|
|
31
|
+
return _chunkVOOX3WJYcjs.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 _chunkVOOX3WJYcjs.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 _chunkVOOX3WJYcjs.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;
|
package/dist/react-extras.d.cts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { CatalogClient } from './index.cjs';
|
|
2
2
|
import { QueryOptions, QueryResult } from './react.cjs';
|
|
3
|
-
import './types-
|
|
3
|
+
import './types-BtBxMbM5.cjs';
|
|
4
4
|
import '@usethrottle/money';
|
|
5
|
-
import './contract-types-
|
|
6
|
-
import './catalog-error-
|
|
5
|
+
import './contract-types-BJMeJSTz.cjs';
|
|
6
|
+
import './catalog-error-bG1XHquN.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 };
|
package/dist/react-extras.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { CatalogClient } from './index.js';
|
|
2
2
|
import { QueryOptions, QueryResult } from './react.js';
|
|
3
|
-
import './types-
|
|
3
|
+
import './types-dKvIfrVH.js';
|
|
4
4
|
import '@usethrottle/money';
|
|
5
|
-
import './contract-types-
|
|
6
|
-
import './catalog-error-
|
|
5
|
+
import './contract-types-BJMeJSTz.js';
|
|
6
|
+
import './catalog-error-c3BVgU6k.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 };
|
package/dist/react-extras.js
CHANGED
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
defined,
|
|
4
4
|
useCustomerKey,
|
|
5
5
|
useQuery
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-6K7H7HBD.js";
|
|
7
|
+
import "./chunk-STNQNHNZ.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 _chunkVOOX3WJYcjs = require('./chunk-VOOX3WJY.cjs');
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
var _chunk2ODFFMZ4cjs = require('./chunk-2ODFFMZ4.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,
|
|
45
|
+
return new (0, _chunk2ODFFMZ4cjs.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) =>
|
|
58
|
+
var wrap = (error) => _chunk2ODFFMZ4cjs.isCatalogError.call(void 0, error) ? error : new (0, _chunk2ODFFMZ4cjs.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,
|
|
69
|
+
throw new (0, _chunk2ODFFMZ4cjs.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
|
|
79
|
+
if (error instanceof _chunk2ODFFMZ4cjs.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) =>
|
|
114
|
+
var ended = (error) => _chunk2ODFFMZ4cjs.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, () => (
|
|
158
|
+
const fallbackUrl = (id) => `${(_nullishCoalesce(ctx().throttleCheckoutUrl, () => ( _chunk2ODFFMZ4cjs.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 =
|
|
620
|
+
const context = _chunkVOOX3WJYcjs.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 =
|
|
694
|
+
const repriced = _chunk2ODFFMZ4cjs.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,
|
|
714
|
+
throw new (0, _chunk2ODFFMZ4cjs.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) =>
|
|
732
|
+
const format = (minor) => _chunk2ODFFMZ4cjs.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 } =
|
|
744
|
+
const { client, store, customerKey } = _chunkVOOX3WJYcjs.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
|
-
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
exports.CatalogProvider = _chunkVOOX3WJYcjs.CatalogProvider; exports.SDK_VERSION = _chunk2ODFFMZ4cjs.SDK_VERSION; exports.catalogQueryKey = _chunkVOOX3WJYcjs.catalogQueryKey; exports.createMemoryCartStorage = _chunkVOOX3WJYcjs.createMemoryCartStorage; exports.useCart = useCart; exports.useCatalog = _chunkVOOX3WJYcjs.useCatalog; exports.useCategories = _chunkVOOX3WJYcjs.useCategories; exports.useCollection = _chunkVOOX3WJYcjs.useCollection; exports.useConfig = _chunkVOOX3WJYcjs.useConfig; exports.useCustomerKey = _chunkVOOX3WJYcjs.useCustomerKey; exports.useFilterValues = _chunkVOOX3WJYcjs.useFilterValues; exports.useGenerationWatch = _chunkVOOX3WJYcjs.useGenerationWatch; exports.useProduct = _chunkVOOX3WJYcjs.useProduct; exports.useProducts = _chunkVOOX3WJYcjs.useProducts; exports.useRelated = _chunkVOOX3WJYcjs.useRelated; exports.useReviews = _chunkVOOX3WJYcjs.useReviews; exports.useStorefrontSettings = _chunkVOOX3WJYcjs.useStorefrontSettings; exports.useSubmitReview = useSubmitReview; exports.useSuggest = _chunkVOOX3WJYcjs.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-
|
|
4
|
+
import { C as CustomerCartSource } from './types-BtBxMbM5.cjs';
|
|
5
5
|
import { CategoryTreeDepth, ProductsQuery, ThrottleCart, CartWarning } from './index.cjs';
|
|
6
|
-
export { O as OpenCartRef } from './types-
|
|
7
|
-
import { Q as QueryOptions, a as QueryResult } from './use-query-
|
|
8
|
-
export { c as catalogQueryKey } from './use-query-
|
|
6
|
+
export { O as OpenCartRef } from './types-BtBxMbM5.cjs';
|
|
7
|
+
import { Q as QueryOptions, a as QueryResult } from './use-query-C2rfTJd4.cjs';
|
|
8
|
+
export { c as catalogQueryKey } from './use-query-C2rfTJd4.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-
|
|
4
|
+
import { C as CustomerCartSource } from './types-dKvIfrVH.js';
|
|
5
5
|
import { CategoryTreeDepth, ProductsQuery, ThrottleCart, CartWarning } from './index.js';
|
|
6
|
-
export { O as OpenCartRef } from './types-
|
|
7
|
-
import { Q as QueryOptions, a as QueryResult } from './use-query-
|
|
8
|
-
export { c as catalogQueryKey } from './use-query-
|
|
6
|
+
export { O as OpenCartRef } from './types-dKvIfrVH.js';
|
|
7
|
+
import { Q as QueryOptions, a as QueryResult } from './use-query-DeCj1hXt.js';
|
|
8
|
+
export { c as catalogQueryKey } from './use-query-DeCj1hXt.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-
|
|
20
|
+
} from "./chunk-6K7H7HBD.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-
|
|
28
|
+
} from "./chunk-STNQNHNZ.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
|
};
|