@usethrottle/catalog 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +135 -24
- package/dist/admin.cjs +16 -16
- package/dist/admin.d.cts +6 -2
- package/dist/admin.d.ts +6 -2
- package/dist/admin.js +1 -1
- package/dist/{catalog-error-s1BINNkt.d.cts → catalog-error-BOaSKgY3.d.cts} +12 -2
- package/dist/{catalog-error-C_zLOtYA.d.ts → catalog-error-CSoPS0-d.d.ts} +12 -2
- package/dist/{chunk-4ORXUW2U.cjs → chunk-2YQNMBDI.cjs} +119 -33
- package/dist/{chunk-JK2UY4CD.js → chunk-3DLH56OX.js} +99 -13
- package/dist/chunk-CADIHOIR.js +496 -0
- package/dist/chunk-GU63WFXI.cjs +496 -0
- package/dist/{client-c2F-eCaL.d.ts → client-6j1Iz-iJ.d.cts} +2 -9
- package/dist/{client-BAoq6jmM.d.cts → client-B3mL2-xJ.d.ts} +2 -9
- package/dist/{contract-types-DhiThMEr.d.cts → contract-types-BRyonOYH.d.cts} +23 -21
- package/dist/{contract-types-DhiThMEr.d.ts → contract-types-BRyonOYH.d.ts} +23 -21
- package/dist/index.cjs +24 -2
- package/dist/index.d.cts +13 -7
- package/dist/index.d.ts +13 -7
- package/dist/index.js +25 -3
- package/dist/react-extras.cjs +42 -0
- package/dist/react-extras.d.cts +23 -0
- package/dist/react-extras.d.ts +23 -0
- package/dist/react-extras.js +42 -0
- package/dist/react.cjs +286 -491
- package/dist/react.d.cts +44 -38
- package/dist/react.d.ts +44 -38
- package/dist/react.js +289 -494
- package/dist/server.cjs +19 -14
- package/dist/server.d.cts +4 -3
- package/dist/server.d.ts +4 -3
- package/dist/server.js +7 -2
- package/dist/{types-DsjoG8ce.d.cts → types-BfveENg1.d.ts} +76 -3
- package/dist/{types-xQLID-4j.d.ts → types-D0PywKnN.d.cts} +76 -3
- package/dist/url.d.cts +2 -1
- package/dist/url.d.ts +2 -1
- package/dist/use-query-CR7r5tam.d.ts +40 -0
- package/dist/use-query-UWf6Pi5g.d.cts +40 -0
- package/dist/version-ev3p03v2.d.cts +8 -0
- package/dist/version-ev3p03v2.d.ts +8 -0
- package/package.json +13 -2
package/dist/react.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
@@ -11,449 +11,28 @@
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
var _chunk4ORXUW2Ucjs = require('./chunk-4ORXUW2U.cjs');
|
|
15
|
-
require('./chunk-ETV4XYOV.cjs');
|
|
16
14
|
|
|
17
|
-
// src/react/provider.tsx
|
|
18
15
|
|
|
19
16
|
|
|
20
17
|
|
|
18
|
+
var _chunkGU63WFXIcjs = require('./chunk-GU63WFXI.cjs');
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
|
|
24
|
-
var _react = require('react');
|
|
25
22
|
|
|
26
|
-
// src/react/store.ts
|
|
27
|
-
var HOOK_CALL = Symbol.for("@usethrottle/catalog.hookCall");
|
|
28
|
-
var EMPTY = {
|
|
29
|
-
data: void 0,
|
|
30
|
-
error: void 0,
|
|
31
|
-
isValidating: false,
|
|
32
|
-
fetchedAt: void 0
|
|
33
|
-
};
|
|
34
|
-
var done = Promise.resolve();
|
|
35
|
-
function createStore(client, options = {}) {
|
|
36
|
-
const now = _nullishCoalesce(options.now, () => ( Date.now));
|
|
37
|
-
const entries = /* @__PURE__ */ new Map();
|
|
38
|
-
let until = 0;
|
|
39
|
-
let cause;
|
|
40
|
-
let pauseTimer;
|
|
41
|
-
const pausedError = () => new (0, _chunk4ORXUW2Ucjs.RateLimitedError)({
|
|
42
|
-
code: _nullishCoalesce(_optionalChain([cause, 'optionalAccess', _ => _.code]), () => ( "RATE_LIMITED")),
|
|
43
|
-
message: _nullishCoalesce(_optionalChain([cause, 'optionalAccess', _2 => _2.message]), () => ( "Too many requests.")),
|
|
44
|
-
statusCode: 429,
|
|
45
|
-
source: _nullishCoalesce(_optionalChain([cause, 'optionalAccess', _3 => _3.source]), () => ( "catalog")),
|
|
46
|
-
retryAfterSeconds: Math.ceil((until - now()) / 1e3)
|
|
47
|
-
});
|
|
48
|
-
const update = (entry, patch) => {
|
|
49
|
-
entry.snap = { ...entry.snap, ...patch };
|
|
50
|
-
for (const listener of [...entry.subs]) listener();
|
|
51
|
-
};
|
|
52
|
-
const touch = (key, initial, stale = false) => {
|
|
53
|
-
let entry = entries.get(key);
|
|
54
|
-
if (entry !== void 0) {
|
|
55
|
-
entries.delete(key);
|
|
56
|
-
} else {
|
|
57
|
-
entry = {
|
|
58
|
-
snap: initial === void 0 ? EMPTY : { ...EMPTY, data: initial, fetchedAt: stale ? void 0 : now() },
|
|
59
|
-
subs: /* @__PURE__ */ new Set()
|
|
60
|
-
};
|
|
61
|
-
for (const [oldKey, old] of entries) {
|
|
62
|
-
if (entries.size < _chunk4ORXUW2Ucjs.CACHE_MAX_ENTRIES) break;
|
|
63
|
-
if (old.subs.size === 0 && old.flight === void 0) {
|
|
64
|
-
clearTimeout(old.timer);
|
|
65
|
-
entries.delete(oldKey);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
entries.set(key, entry);
|
|
70
|
-
return entry;
|
|
71
|
-
};
|
|
72
|
-
const later = (key, entry, ms) => {
|
|
73
|
-
entry.indexing = true;
|
|
74
|
-
clearTimeout(entry.timer);
|
|
75
|
-
entry.timer = setTimeout(() => {
|
|
76
|
-
if (entries.get(key) === entry && entry.subs.size > 0 && entry.run)
|
|
77
|
-
void fetchKey(key, entry.run, { force: true });
|
|
78
|
-
else entry.indexing = false;
|
|
79
|
-
}, ms);
|
|
80
|
-
};
|
|
81
|
-
function fetchKey(key, run, { force = false, staleMs = _chunk4ORXUW2Ucjs.STALE_MS } = {}) {
|
|
82
|
-
const entry = touch(key);
|
|
83
|
-
entry.run = run;
|
|
84
|
-
if (entry.promise !== void 0 && !_optionalChain([entry, 'access', _4 => _4.flight, 'optionalAccess', _5 => _5.signal, 'access', _6 => _6.aborted]))
|
|
85
|
-
return entry.promise;
|
|
86
|
-
if (now() < until) {
|
|
87
|
-
if (entry.snap.data === void 0 && entry.snap.error === void 0)
|
|
88
|
-
update(entry, { error: pausedError() });
|
|
89
|
-
return done;
|
|
90
|
-
}
|
|
91
|
-
const at = entry.snap.fetchedAt;
|
|
92
|
-
if (!force && at !== void 0 && now() - at < staleMs) return done;
|
|
93
|
-
const controller = new AbortController();
|
|
94
|
-
const box = entry.etag === void 0 ? {} : { etag: entry.etag };
|
|
95
|
-
const current = () => {
|
|
96
|
-
if (entry.flight !== controller) return false;
|
|
97
|
-
entry.flight = entry.promise = void 0;
|
|
98
|
-
if (!controller.signal.aborted) return true;
|
|
99
|
-
update(entry, { isValidating: false });
|
|
100
|
-
return false;
|
|
101
|
-
};
|
|
102
|
-
entry.flight = controller;
|
|
103
|
-
update(entry, { isValidating: true });
|
|
104
|
-
let pending;
|
|
105
|
-
try {
|
|
106
|
-
pending = run(client, {
|
|
107
|
-
signal: controller.signal,
|
|
108
|
-
[HOOK_CALL]: box
|
|
109
|
-
});
|
|
110
|
-
} catch (error) {
|
|
111
|
-
pending = Promise.reject(error);
|
|
112
|
-
}
|
|
113
|
-
const promise = pending.then(
|
|
114
|
-
(value) => {
|
|
115
|
-
if (!current()) return;
|
|
116
|
-
const result = _nullishCoalesce(box.result, () => ( {
|
|
117
|
-
notModified: false,
|
|
118
|
-
data: value,
|
|
119
|
-
etag: null
|
|
120
|
-
}));
|
|
121
|
-
entry.etag = _nullishCoalesce(result.etag, () => ( void 0));
|
|
122
|
-
if (result.notModified) {
|
|
123
|
-
update(entry, {
|
|
124
|
-
error: void 0,
|
|
125
|
-
isValidating: false,
|
|
126
|
-
fetchedAt: now()
|
|
127
|
-
});
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
if (_optionalChain([result, 'access', _7 => _7.data, 'optionalAccess', _8 => _8.indexing]) === true) {
|
|
131
|
-
if (!entry.indexing) later(key, entry, _chunk4ORXUW2Ucjs.INDEXING_REVALIDATE_MS);
|
|
132
|
-
} else {
|
|
133
|
-
entry.indexing = false;
|
|
134
|
-
}
|
|
135
|
-
update(entry, {
|
|
136
|
-
data: result.data,
|
|
137
|
-
error: void 0,
|
|
138
|
-
isValidating: false,
|
|
139
|
-
fetchedAt: now()
|
|
140
|
-
});
|
|
141
|
-
},
|
|
142
|
-
(error) => {
|
|
143
|
-
if (!current()) return;
|
|
144
|
-
const retryMs = (_nullishCoalesce(error.retryAfterSeconds, () => ( _chunk4ORXUW2Ucjs.RATE_LIMIT_DEFAULT_RETRY_S))) * 1e3;
|
|
145
|
-
if (error.statusCode === 429 && error.code === "RATE_LIMITED")
|
|
146
|
-
pause(now() + retryMs, error);
|
|
147
|
-
else if (error.code === "STOREFRONT_INDEXING" && !entry.indexing)
|
|
148
|
-
later(key, entry, retryMs);
|
|
149
|
-
update(entry, { error, isValidating: false });
|
|
150
|
-
}
|
|
151
|
-
);
|
|
152
|
-
entry.promise = promise;
|
|
153
|
-
return promise;
|
|
154
|
-
}
|
|
155
|
-
function pause(untilMs, error) {
|
|
156
|
-
if (untilMs <= Math.max(until, now())) return;
|
|
157
|
-
until = untilMs;
|
|
158
|
-
cause = error;
|
|
159
|
-
clearTimeout(pauseTimer);
|
|
160
|
-
pauseTimer = setTimeout(() => {
|
|
161
|
-
until = 0;
|
|
162
|
-
for (const [key, entry] of [...entries]) {
|
|
163
|
-
if (entry.subs.size > 0 && entry.run)
|
|
164
|
-
void fetchKey(key, entry.run, { force: true });
|
|
165
|
-
}
|
|
166
|
-
}, untilMs - now());
|
|
167
|
-
}
|
|
168
|
-
function clear() {
|
|
169
|
-
for (const [key, entry] of [...entries]) {
|
|
170
|
-
clearTimeout(entry.timer);
|
|
171
|
-
_optionalChain([entry, 'access', _9 => _9.flight, 'optionalAccess', _10 => _10.abort, 'call', _11 => _11()]);
|
|
172
|
-
if (entry.subs.size === 0) {
|
|
173
|
-
entries.delete(key);
|
|
174
|
-
} else {
|
|
175
|
-
entry.etag = entry.flight = entry.promise = void 0;
|
|
176
|
-
entry.indexing = false;
|
|
177
|
-
update(entry, EMPTY);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return {
|
|
182
|
-
subscribe(key, listener) {
|
|
183
|
-
const entry = touch(key);
|
|
184
|
-
entry.subs.add(listener);
|
|
185
|
-
return () => {
|
|
186
|
-
entry.subs.delete(listener);
|
|
187
|
-
void done.then(() => {
|
|
188
|
-
if (entry.subs.size === 0) _optionalChain([entry, 'access', _12 => _12.flight, 'optionalAccess', _13 => _13.abort, 'call', _14 => _14()]);
|
|
189
|
-
});
|
|
190
|
-
};
|
|
191
|
-
},
|
|
192
|
-
get: (key, initial, stale) => key === null ? EMPTY : _nullishCoalesce(_optionalChain([(_nullishCoalesce(entries.get(key), () => ( (initial === void 0 ? void 0 : touch(key, initial, stale))))), 'optionalAccess', _15 => _15.snap]), () => ( EMPTY)),
|
|
193
|
-
getServer(key, initial, stale) {
|
|
194
|
-
if (key === null || initial === void 0) return EMPTY;
|
|
195
|
-
const entry = _nullishCoalesce(entries.get(key), () => ( touch(key, initial, stale)));
|
|
196
|
-
return _nullishCoalesce(entry.server, () => ( (entry.server = { ...EMPTY, data: initial })));
|
|
197
|
-
},
|
|
198
|
-
fetch: fetchKey,
|
|
199
|
-
clear,
|
|
200
|
-
pause,
|
|
201
|
-
pausedUntil: () => until > now() ? until : 0,
|
|
202
|
-
dispose() {
|
|
203
|
-
clearTimeout(pauseTimer);
|
|
204
|
-
until = 0;
|
|
205
|
-
clear();
|
|
206
|
-
for (const entry of entries.values()) entry.subs.clear();
|
|
207
|
-
entries.clear();
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
23
|
|
|
212
|
-
// src/react/provider.tsx
|
|
213
|
-
var _jsxruntime = require('react/jsx-runtime');
|
|
214
|
-
function createMemoryCartStorage() {
|
|
215
|
-
let id = null;
|
|
216
|
-
return {
|
|
217
|
-
get: () => id,
|
|
218
|
-
set: (value) => {
|
|
219
|
-
id = value;
|
|
220
|
-
},
|
|
221
|
-
remove: () => {
|
|
222
|
-
id = null;
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
var CatalogContext = _react.createContext.call(void 0, null);
|
|
227
|
-
function useCatalogContext() {
|
|
228
|
-
const value = _react.useContext.call(void 0, CatalogContext);
|
|
229
|
-
if (value === null)
|
|
230
|
-
throw new Error("Catalog hooks must be used inside a <CatalogProvider>.");
|
|
231
|
-
return value;
|
|
232
|
-
}
|
|
233
|
-
function CatalogProvider(props) {
|
|
234
|
-
const { client, children, ...rest } = props;
|
|
235
|
-
const customerKey = _nullishCoalesce(props.customerKey, () => ( null));
|
|
236
|
-
const mounted = _react.useRef.call(void 0, null);
|
|
237
|
-
const store = _react.useMemo.call(void 0, () => {
|
|
238
|
-
const next = createStore(client);
|
|
239
|
-
next.pause(_nullishCoalesce(_optionalChain([mounted, 'access', _16 => _16.current, 'optionalAccess', _17 => _17.pausedUntil, 'call', _18 => _18()]), () => ( 0)));
|
|
240
|
-
return next;
|
|
241
|
-
}, [client, customerKey]);
|
|
242
|
-
_react.useEffect.call(void 0, () => {
|
|
243
|
-
mounted.current = store;
|
|
244
|
-
return () => {
|
|
245
|
-
mounted.current = null;
|
|
246
|
-
void Promise.resolve().then(() => {
|
|
247
|
-
if (mounted.current !== store) store.dispose();
|
|
248
|
-
});
|
|
249
|
-
};
|
|
250
|
-
}, [store]);
|
|
251
|
-
const memory = _react.useMemo.call(void 0, createMemoryCartStorage, []);
|
|
252
|
-
const cartStorage = _nullishCoalesce(rest.cartStorage, () => ( memory));
|
|
253
|
-
const shared = _react.useRef.call(void 0, {}).current;
|
|
254
|
-
const cart = _react.useMemo.call(void 0,
|
|
255
|
-
() => ({ shared }),
|
|
256
|
-
[shared, client, rest.throttleBaseUrl]
|
|
257
|
-
);
|
|
258
|
-
const urls = rest.cartUrls;
|
|
259
|
-
const value = _react.useMemo.call(void 0,
|
|
260
|
-
() => ({ ...rest, client, customerKey, store, cartStorage, cart }),
|
|
261
|
-
// `rest` is spread fresh each render; its fields are the dependencies.
|
|
262
|
-
[
|
|
263
|
-
client,
|
|
264
|
-
customerKey,
|
|
265
|
-
store,
|
|
266
|
-
cartStorage,
|
|
267
|
-
cart,
|
|
268
|
-
rest.throttleBaseUrl,
|
|
269
|
-
rest.throttleCheckoutUrl,
|
|
270
|
-
_optionalChain([urls, 'optionalAccess', _19 => _19.returnUrl]),
|
|
271
|
-
_optionalChain([urls, 'optionalAccess', _20 => _20.cancelUrl]),
|
|
272
|
-
_optionalChain([urls, 'optionalAccess', _21 => _21.storefrontUrl])
|
|
273
|
-
]
|
|
274
|
-
);
|
|
275
|
-
cart.context = value;
|
|
276
|
-
shared.home = cart;
|
|
277
|
-
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CatalogContext.Provider, { value, children });
|
|
278
|
-
}
|
|
279
|
-
function useCatalog() {
|
|
280
|
-
return useCatalogContext().client;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// src/react/use-query.ts
|
|
284
|
-
|
|
285
|
-
function canonical(value) {
|
|
286
|
-
if (Array.isArray(value)) return value.map(canonical);
|
|
287
|
-
if (value === null || typeof value !== "object") return value;
|
|
288
|
-
const out = {};
|
|
289
|
-
for (const name of Object.keys(value).sort()) {
|
|
290
|
-
const item = value[name];
|
|
291
|
-
if (item !== void 0) out[name] = canonical(item);
|
|
292
|
-
}
|
|
293
|
-
return out;
|
|
294
|
-
}
|
|
295
|
-
function catalogQueryKey(route, params) {
|
|
296
|
-
return `${route}:${JSON.stringify(canonical(_nullishCoalesce(params, () => ( null))))}`;
|
|
297
|
-
}
|
|
298
|
-
var noop = () => {
|
|
299
|
-
};
|
|
300
|
-
var unsubscribe = () => noop;
|
|
301
|
-
function useQuery(route, params, run, options = {}) {
|
|
302
|
-
const { store, customerKey } = useCatalogContext();
|
|
303
|
-
const key = run === null || options.enabled === false ? null : `${_nullishCoalesce(customerKey, () => ( ""))}\0${catalogQueryKey(route, params)}`;
|
|
304
|
-
const first = _react.useRef.call(void 0, { store, key });
|
|
305
|
-
const initial = first.current.store === store && first.current.key === key ? options.initialData : void 0;
|
|
306
|
-
const subscribe = _react.useCallback.call(void 0,
|
|
307
|
-
(listener) => key === null ? unsubscribe() : store.subscribe(key, listener),
|
|
308
|
-
[store, key]
|
|
309
|
-
);
|
|
310
|
-
const stale = customerKey !== null;
|
|
311
|
-
const snap = _react.useSyncExternalStore.call(void 0,
|
|
312
|
-
subscribe,
|
|
313
|
-
() => store.get(key, initial, stale),
|
|
314
|
-
() => store.getServer(key, initial, stale)
|
|
315
|
-
);
|
|
316
|
-
const staleMs = options.staleTimeMs;
|
|
317
|
-
_react.useEffect.call(void 0, () => {
|
|
318
|
-
if (key !== null && run !== null)
|
|
319
|
-
void store.fetch(key, run, staleMs === void 0 ? {} : { staleMs });
|
|
320
|
-
}, [store, key, staleMs]);
|
|
321
|
-
const refetch = _react.useCallback.call(void 0,
|
|
322
|
-
() => key === null || run === null ? Promise.resolve() : store.fetch(key, run, { force: true }),
|
|
323
|
-
[store, key]
|
|
324
|
-
);
|
|
325
|
-
return {
|
|
326
|
-
data: snap.data,
|
|
327
|
-
error: snap.error,
|
|
328
|
-
isLoading: key !== null && snap.data === void 0 && snap.error === void 0,
|
|
329
|
-
isValidating: snap.isValidating,
|
|
330
|
-
refetch
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
24
|
|
|
334
|
-
// src/react/hooks.ts
|
|
335
25
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
for (const name in options) {
|
|
339
|
-
if (options[name] !== void 0) out[name] = options[name];
|
|
340
|
-
}
|
|
341
|
-
return out;
|
|
342
|
-
}
|
|
343
|
-
function useProducts(query = {}, options) {
|
|
344
|
-
return useQuery(
|
|
345
|
-
"products",
|
|
346
|
-
query,
|
|
347
|
-
(client, call) => client.products.list(query, call),
|
|
348
|
-
options
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
function useProduct(handle, options = {}) {
|
|
352
|
-
const extra = defined({ include: options.include });
|
|
353
|
-
return useQuery(
|
|
354
|
-
"product",
|
|
355
|
-
{ handle, ...extra },
|
|
356
|
-
handle === null ? null : (client, call) => client.products.get(handle, { ...call, ...extra }),
|
|
357
|
-
options
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
function useRelated(handle, options = {}) {
|
|
361
|
-
const extra = defined({ limit: options.limit });
|
|
362
|
-
return useQuery(
|
|
363
|
-
"related",
|
|
364
|
-
{ handle, ...extra },
|
|
365
|
-
handle === null ? null : (client, call) => client.products.related(handle, { ...call, ...extra }),
|
|
366
|
-
options
|
|
367
|
-
);
|
|
368
|
-
}
|
|
369
|
-
function useDebounced(q, ms) {
|
|
370
|
-
const box = _react.useMemo.call(void 0, () => {
|
|
371
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
372
|
-
let value = q;
|
|
373
|
-
return {
|
|
374
|
-
get: () => value,
|
|
375
|
-
set(next) {
|
|
376
|
-
value = next;
|
|
377
|
-
for (const listener of [...listeners]) listener();
|
|
378
|
-
},
|
|
379
|
-
subscribe(listener) {
|
|
380
|
-
listeners.add(listener);
|
|
381
|
-
return () => listeners.delete(listener);
|
|
382
|
-
}
|
|
383
|
-
};
|
|
384
|
-
}, []);
|
|
385
|
-
_react.useEffect.call(void 0, () => {
|
|
386
|
-
const timer = setTimeout(() => box.set(q), ms);
|
|
387
|
-
return () => clearTimeout(timer);
|
|
388
|
-
}, [box, q, ms]);
|
|
389
|
-
return _react.useSyncExternalStore.call(void 0, box.subscribe, box.get, box.get);
|
|
390
|
-
}
|
|
391
|
-
function useSuggest(q, options = {}) {
|
|
392
|
-
const settled = useDebounced(q, _nullishCoalesce(options.debounceMs, () => ( _chunk4ORXUW2Ucjs.SUGGEST_DEBOUNCE_MS)));
|
|
393
|
-
const extra = defined({ limit: options.limit });
|
|
394
|
-
const long = (value) => value.trim().length >= _chunk4ORXUW2Ucjs.SUGGEST_MIN_CHARS;
|
|
395
|
-
return useQuery(
|
|
396
|
-
"suggest",
|
|
397
|
-
{ q: settled, ...extra },
|
|
398
|
-
long(q) && long(settled) ? (client, call) => client.suggest(settled, { ...call, ...extra }) : null,
|
|
399
|
-
options
|
|
400
|
-
);
|
|
401
|
-
}
|
|
402
|
-
function useCategories(options = {}) {
|
|
403
|
-
const extra = defined({ depth: options.depth });
|
|
404
|
-
return useQuery(
|
|
405
|
-
"categories",
|
|
406
|
-
extra,
|
|
407
|
-
(client, call) => client.categories.tree({ ...call, ...extra }),
|
|
408
|
-
options
|
|
409
|
-
);
|
|
410
|
-
}
|
|
411
|
-
function useCollection(handle, options) {
|
|
412
|
-
return useQuery(
|
|
413
|
-
"collection",
|
|
414
|
-
{ handle },
|
|
415
|
-
handle === null ? null : (client, call) => client.collections.get(handle, call),
|
|
416
|
-
options
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
function useReviews(handle, options = {}) {
|
|
420
|
-
const extra = defined({
|
|
421
|
-
sort: options.sort,
|
|
422
|
-
rating: options.rating,
|
|
423
|
-
limit: options.limit,
|
|
424
|
-
cursor: options.cursor
|
|
425
|
-
});
|
|
426
|
-
return useQuery(
|
|
427
|
-
"reviews",
|
|
428
|
-
{ handle, ...extra },
|
|
429
|
-
handle === null ? null : (client, call) => client.reviews.list(handle, { ...call, ...extra }),
|
|
430
|
-
options
|
|
431
|
-
);
|
|
432
|
-
}
|
|
433
|
-
function useConfig(options) {
|
|
434
|
-
return useQuery(
|
|
435
|
-
"config",
|
|
436
|
-
null,
|
|
437
|
-
(client, call) => client.config(call),
|
|
438
|
-
options
|
|
439
|
-
);
|
|
440
|
-
}
|
|
441
|
-
function useFilterValues(key, query = {}, options) {
|
|
442
|
-
return useQuery(
|
|
443
|
-
"filterValues",
|
|
444
|
-
{ key, query },
|
|
445
|
-
key === null ? null : (client, call) => client.filters.values(key, query, call),
|
|
446
|
-
options
|
|
447
|
-
);
|
|
448
|
-
}
|
|
26
|
+
var _chunk2YQNMBDIcjs = require('./chunk-2YQNMBDI.cjs');
|
|
27
|
+
require('./chunk-ETV4XYOV.cjs');
|
|
449
28
|
|
|
450
29
|
// src/react/use-cart.ts
|
|
451
|
-
|
|
30
|
+
var _react = require('react');
|
|
452
31
|
|
|
453
32
|
// src/react/mutation.ts
|
|
454
33
|
function newKey() {
|
|
455
34
|
const webCrypto = globalThis.crypto;
|
|
456
|
-
if (typeof _optionalChain([webCrypto, 'optionalAccess',
|
|
35
|
+
if (typeof _optionalChain([webCrypto, 'optionalAccess', _ => _.randomUUID]) === "function")
|
|
457
36
|
return webCrypto.randomUUID();
|
|
458
37
|
let out = "";
|
|
459
38
|
for (let i = 0; i < 32; i += 1)
|
|
@@ -461,7 +40,7 @@ function newKey() {
|
|
|
461
40
|
return out;
|
|
462
41
|
}
|
|
463
42
|
function refuse(message, path) {
|
|
464
|
-
return new (0,
|
|
43
|
+
return new (0, _chunk2YQNMBDIcjs.CatalogError)({
|
|
465
44
|
code: "INVALID_REQUEST",
|
|
466
45
|
message,
|
|
467
46
|
statusCode: 0,
|
|
@@ -474,7 +53,7 @@ var UNSAFE = /[\x00-\x20\x7f]/u;
|
|
|
474
53
|
function isHttpUrl(value) {
|
|
475
54
|
return typeof value === "string" && /^https?:\/\/[^/?#\\]/iu.test(value) && !UNSAFE.test(value);
|
|
476
55
|
}
|
|
477
|
-
var wrap = (error) =>
|
|
56
|
+
var wrap = (error) => _chunk2YQNMBDIcjs.isCatalogError.call(void 0, error) ? error : new (0, _chunk2YQNMBDIcjs.CatalogError)({
|
|
478
57
|
code: "CLIENT_ERROR",
|
|
479
58
|
message: "The action failed.",
|
|
480
59
|
statusCode: 0,
|
|
@@ -485,7 +64,7 @@ var wrap = (error) => _chunk4ORXUW2Ucjs.isCatalogError.call(void 0, error) ? err
|
|
|
485
64
|
function checkPause(store) {
|
|
486
65
|
const until = store.pausedUntil();
|
|
487
66
|
if (until > 0) {
|
|
488
|
-
throw new (0,
|
|
67
|
+
throw new (0, _chunk2YQNMBDIcjs.RateLimitedError)({
|
|
489
68
|
code: "RATE_LIMITED",
|
|
490
69
|
message: "Too many requests.",
|
|
491
70
|
statusCode: 429,
|
|
@@ -495,7 +74,7 @@ function checkPause(store) {
|
|
|
495
74
|
}
|
|
496
75
|
}
|
|
497
76
|
function notePause(store, error) {
|
|
498
|
-
if (error instanceof
|
|
77
|
+
if (error instanceof _chunk2YQNMBDIcjs.RateLimitedError && error.source === "catalog" && error.code === "RATE_LIMITED")
|
|
499
78
|
store.pause(Date.now() + error.retryAfterSeconds * 1e3, error);
|
|
500
79
|
}
|
|
501
80
|
function createBox(initial) {
|
|
@@ -515,13 +94,14 @@ function createBox(initial) {
|
|
|
515
94
|
}
|
|
516
95
|
|
|
517
96
|
// src/react/use-cart.ts
|
|
518
|
-
var
|
|
97
|
+
var EMPTY = {
|
|
519
98
|
cart: null,
|
|
520
99
|
sessionId: null,
|
|
521
100
|
cartUrl: null,
|
|
522
101
|
status: "idle",
|
|
523
102
|
error: void 0,
|
|
524
|
-
pending: false
|
|
103
|
+
pending: false,
|
|
104
|
+
warnings: []
|
|
525
105
|
};
|
|
526
106
|
var ENDED = /* @__PURE__ */ new Set([
|
|
527
107
|
"cart_session_expired",
|
|
@@ -529,11 +109,11 @@ var ENDED = /* @__PURE__ */ new Set([
|
|
|
529
109
|
"cart_not_open",
|
|
530
110
|
"cart_not_found"
|
|
531
111
|
]);
|
|
532
|
-
var ended = (error) =>
|
|
533
|
-
var converted = (error) => _optionalChain([error, 'access',
|
|
112
|
+
var ended = (error) => _chunk2YQNMBDIcjs.isCatalogError.call(void 0, error) && ENDED.has(error.code);
|
|
113
|
+
var converted = (error) => _optionalChain([error, 'access', _2 => _2.details, 'optionalAccess', _3 => _3.reason]) === "converted";
|
|
534
114
|
function itemsOf(cart) {
|
|
535
115
|
const items = /* @__PURE__ */ new Map();
|
|
536
|
-
for (const line of _nullishCoalesce(_optionalChain([cart, 'optionalAccess',
|
|
116
|
+
for (const line of _nullishCoalesce(_optionalChain([cart, 'optionalAccess', _4 => _4.lineItems]), () => ( []))) {
|
|
537
117
|
if (line.referenceId !== null)
|
|
538
118
|
items.set(
|
|
539
119
|
line.referenceId,
|
|
@@ -542,7 +122,9 @@ function itemsOf(cart) {
|
|
|
542
122
|
}
|
|
543
123
|
return items;
|
|
544
124
|
}
|
|
545
|
-
var skuOf = (cart, lineId) => _nullishCoalesce(_optionalChain([cart, 'optionalAccess',
|
|
125
|
+
var skuOf = (cart, lineId) => _nullishCoalesce(_optionalChain([cart, 'optionalAccess', _5 => _5.lineItems, 'optionalAccess', _6 => _6.find, 'call', _7 => _7((line) => line.id === lineId), 'optionalAccess', _8 => _8.referenceId]), () => ( null));
|
|
126
|
+
var CART_REREAD_MS = 3e4;
|
|
127
|
+
var TRANSPORT = Symbol.for("@usethrottle/catalog.transport");
|
|
546
128
|
function createController(home) {
|
|
547
129
|
var _a;
|
|
548
130
|
const ctx = () => home.context;
|
|
@@ -551,16 +133,19 @@ function createController(home) {
|
|
|
551
133
|
seen: void 0,
|
|
552
134
|
moving: void 0,
|
|
553
135
|
unremoved: false,
|
|
136
|
+
reads: /* @__PURE__ */ new Map(),
|
|
137
|
+
slots: /* @__PURE__ */ new Set(),
|
|
554
138
|
abort: new AbortController(),
|
|
555
139
|
writing: Promise.resolve(),
|
|
556
140
|
tail: Promise.resolve()
|
|
557
141
|
})));
|
|
558
142
|
const retired = () => home.shared.home !== home;
|
|
559
|
-
const box = createBox(
|
|
143
|
+
const box = createBox(EMPTY);
|
|
560
144
|
let queued = 0;
|
|
561
145
|
let loaded = false;
|
|
562
146
|
let currency;
|
|
563
|
-
|
|
147
|
+
let hinted;
|
|
148
|
+
const reset = () => box.set({ ...EMPTY, pending: queued > 0 });
|
|
564
149
|
const session = (id) => {
|
|
565
150
|
const { client, throttleBaseUrl } = ctx();
|
|
566
151
|
return client.carts.session(
|
|
@@ -568,18 +153,112 @@ function createController(home) {
|
|
|
568
153
|
throttleBaseUrl === void 0 ? void 0 : { throttleBaseUrl }
|
|
569
154
|
);
|
|
570
155
|
};
|
|
571
|
-
const fallbackUrl = (id) => `${(_nullishCoalesce(ctx().throttleCheckoutUrl, () => (
|
|
156
|
+
const fallbackUrl = (id) => `${(_nullishCoalesce(ctx().throttleCheckoutUrl, () => ( _chunk2YQNMBDIcjs.THROTTLE_CHECKOUT_URL))).replace(/\/+$/u, "")}/cart/${encodeURIComponent(id)}`;
|
|
572
157
|
const live = async (signal, value) => {
|
|
573
158
|
const out = await value;
|
|
574
159
|
if (signal.aborted) throw signal.reason;
|
|
575
160
|
return out;
|
|
576
161
|
};
|
|
162
|
+
const resuming = () => ctx().customerCart !== void 0 && ctx().customerKey !== null;
|
|
163
|
+
const wanted = (options) => {
|
|
164
|
+
const transport = ctx().client[TRANSPORT];
|
|
165
|
+
return _optionalChain([(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(currency, () => ( _optionalChain([options, 'optionalAccess', _9 => _9.currency]))), () => ( hinted)), () => ( _optionalChain([transport, 'optionalAccess', _10 => _10.context, 'optionalCall', _11 => _11(), 'access', _12 => _12.currency])))), 'optionalAccess', _13 => _13.toUpperCase, 'call', _14 => _14()]);
|
|
166
|
+
};
|
|
167
|
+
async function soft(signal, step) {
|
|
168
|
+
try {
|
|
169
|
+
await step();
|
|
170
|
+
} catch (error) {
|
|
171
|
+
if (signal.aborted) throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async function find(signal, wantedCurrency, strict = false) {
|
|
175
|
+
const source = ctx().customerCart;
|
|
176
|
+
if (source === void 0 || wantedCurrency === void 0) return null;
|
|
177
|
+
const asked = wantedCurrency.toUpperCase();
|
|
178
|
+
try {
|
|
179
|
+
const found = await live(signal, source.getOpenCart({ currency: asked }));
|
|
180
|
+
return found !== null && found.currency.toUpperCase() === asked ? found : null;
|
|
181
|
+
} catch (error) {
|
|
182
|
+
if (signal.aborted || strict) throw error;
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async function findTarget(signal, code, storage) {
|
|
187
|
+
if (resuming()) {
|
|
188
|
+
const found = await find(signal, code, true);
|
|
189
|
+
return found === null ? null : { id: found.sessionId, cartUrl: fallbackUrl(found.sessionId) };
|
|
190
|
+
}
|
|
191
|
+
if (ctx().customerKey !== null || storage.getFor === void 0) return null;
|
|
192
|
+
const id = await live(signal, storage.getFor(code));
|
|
193
|
+
if (id === null || id === "") return null;
|
|
194
|
+
try {
|
|
195
|
+
const answer = await live(signal, session(id).get({ signal }));
|
|
196
|
+
if (answer.cart.status !== "open" || answer.cart.currency.toUpperCase() !== code)
|
|
197
|
+
return null;
|
|
198
|
+
} catch (error) {
|
|
199
|
+
if (signal.aborted || !ended(error)) throw error;
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
return { id, cartUrl: fallbackUrl(id) };
|
|
203
|
+
}
|
|
204
|
+
async function findOnce(signal, storage) {
|
|
205
|
+
var _a2;
|
|
206
|
+
if (!resuming()) return;
|
|
207
|
+
const looked = _nullishCoalesce((_a2 = home.shared).looked, () => ( (_a2.looked = /* @__PURE__ */ new Set())));
|
|
208
|
+
const asked = wanted();
|
|
209
|
+
if (asked === void 0) return;
|
|
210
|
+
const key = `${ctx().customerKey}\0${asked}`;
|
|
211
|
+
if (looked.has(key)) return;
|
|
212
|
+
looked.add(key);
|
|
213
|
+
let found = null;
|
|
214
|
+
try {
|
|
215
|
+
found = await find(signal, asked);
|
|
216
|
+
} finally {
|
|
217
|
+
if (found === null) looked.delete(key);
|
|
218
|
+
}
|
|
219
|
+
if (found !== null) await soft(signal, () => adopt(signal, found, storage));
|
|
220
|
+
}
|
|
221
|
+
async function forgetSlots(storage, codes) {
|
|
222
|
+
for (const code of codes)
|
|
223
|
+
if (storage.removeFor !== void 0) await storage.removeFor(code);
|
|
224
|
+
else await _optionalChain([storage, 'access', _15 => _15.setFor, 'optionalCall', _16 => _16(code, "")]);
|
|
225
|
+
}
|
|
226
|
+
async function save(signal, storage, id) {
|
|
227
|
+
const write = storage.set(id);
|
|
228
|
+
me.writing = Promise.resolve(write).catch(() => void 0);
|
|
229
|
+
await live(signal, write);
|
|
230
|
+
}
|
|
231
|
+
async function adopt(signal, found, storage) {
|
|
232
|
+
const id = found.sessionId;
|
|
233
|
+
const answer = await live(signal, session(id).get({ signal }));
|
|
234
|
+
me.reads.set(id, Date.now());
|
|
235
|
+
await save(signal, storage, id);
|
|
236
|
+
box.set({
|
|
237
|
+
sessionId: id,
|
|
238
|
+
cartUrl: fallbackUrl(id),
|
|
239
|
+
cart: answer.cart,
|
|
240
|
+
status: "ready",
|
|
241
|
+
error: void 0
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
async function supersede(signal, answer, storage) {
|
|
245
|
+
if (answer.cart.status !== "abandoned" || !resuming()) return;
|
|
246
|
+
const found = await find(signal, answer.cart.currency);
|
|
247
|
+
if (found !== null && found.cartId !== answer.cart.cartId)
|
|
248
|
+
await adopt(signal, found, storage);
|
|
249
|
+
}
|
|
250
|
+
async function read(signal, id) {
|
|
251
|
+
const answer = await live(signal, session(id).get({ signal }));
|
|
252
|
+
me.reads.set(id, Date.now());
|
|
253
|
+
box.set({ cart: answer.cart, status: "ready", error: void 0 });
|
|
254
|
+
return answer;
|
|
255
|
+
}
|
|
577
256
|
async function endSession(signal, error, storage) {
|
|
578
257
|
await live(signal, storage.remove());
|
|
579
258
|
if (converted(error)) reset();
|
|
580
259
|
else box.set({ sessionId: null, cartUrl: null });
|
|
581
260
|
}
|
|
582
|
-
async function
|
|
261
|
+
async function start(signal, options, items) {
|
|
583
262
|
const context = ctx();
|
|
584
263
|
const body = {
|
|
585
264
|
items: [...items].map(([sku, quantity]) => ({ sku, quantity }))
|
|
@@ -588,9 +267,9 @@ function createController(home) {
|
|
|
588
267
|
if (chosen !== void 0) body.currency = chosen;
|
|
589
268
|
if (options.locale !== void 0) body.locale = options.locale;
|
|
590
269
|
const urls = context.cartUrls;
|
|
591
|
-
if (_optionalChain([urls, 'optionalAccess',
|
|
592
|
-
if (_optionalChain([urls, 'optionalAccess',
|
|
593
|
-
if (_optionalChain([urls, 'optionalAccess',
|
|
270
|
+
if (_optionalChain([urls, 'optionalAccess', _17 => _17.returnUrl]) !== void 0) body.returnUrl = urls.returnUrl;
|
|
271
|
+
if (_optionalChain([urls, 'optionalAccess', _18 => _18.cancelUrl]) !== void 0) body.cancelUrl = urls.cancelUrl;
|
|
272
|
+
if (_optionalChain([urls, 'optionalAccess', _19 => _19.storefrontUrl]) !== void 0)
|
|
594
273
|
body.storefrontUrl = urls.storefrontUrl;
|
|
595
274
|
let answer;
|
|
596
275
|
try {
|
|
@@ -603,33 +282,25 @@ function createController(home) {
|
|
|
603
282
|
throw error;
|
|
604
283
|
}
|
|
605
284
|
const id = answer.sessionId;
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
cartUrl,
|
|
615
|
-
cart: snapshot.cart,
|
|
616
|
-
status: "ready",
|
|
617
|
-
error: void 0
|
|
618
|
-
});
|
|
619
|
-
return;
|
|
620
|
-
}
|
|
285
|
+
return {
|
|
286
|
+
id,
|
|
287
|
+
cartUrl: isHttpUrl(answer.cartUrl) ? answer.cartUrl : fallbackUrl(id)
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
async function create(signal, options, items) {
|
|
291
|
+
const storage = ctx().cartStorage;
|
|
292
|
+
const { id, cartUrl } = await start(signal, options, items);
|
|
621
293
|
box.set({ sessionId: id, cartUrl });
|
|
622
294
|
let unsaved;
|
|
623
295
|
try {
|
|
624
|
-
|
|
625
|
-
me.writing = Promise.resolve(write).catch(() => void 0);
|
|
626
|
-
await live(signal, write);
|
|
296
|
+
await save(signal, storage, id);
|
|
627
297
|
} catch (error) {
|
|
628
298
|
if (signal.aborted) throw error;
|
|
629
299
|
unsaved = error;
|
|
630
300
|
}
|
|
631
301
|
try {
|
|
632
302
|
const snapshot = await live(signal, session(id).get({ signal }));
|
|
303
|
+
me.reads.set(id, Date.now());
|
|
633
304
|
box.set({ cart: snapshot.cart, status: "ready", error: void 0 });
|
|
634
305
|
} catch (error) {
|
|
635
306
|
if (!signal.aborted) box.set({ status: "error" });
|
|
@@ -640,18 +311,52 @@ function createController(home) {
|
|
|
640
311
|
async function mutate(signal, options, call, apply) {
|
|
641
312
|
checkPause(ctx().store);
|
|
642
313
|
const storage = ctx().cartStorage;
|
|
643
|
-
const id = box.get().sessionId;
|
|
644
314
|
let met;
|
|
645
|
-
|
|
315
|
+
const attempt = async (id2) => {
|
|
646
316
|
try {
|
|
647
|
-
const answer = await live(signal, call(session(
|
|
317
|
+
const answer = await live(signal, call(session(id2), signal));
|
|
648
318
|
if (answer !== null)
|
|
649
319
|
box.set({ cart: answer.cart, status: "ready", error: void 0 });
|
|
650
|
-
return
|
|
320
|
+
return true;
|
|
651
321
|
} catch (error) {
|
|
652
322
|
if (signal.aborted || !ended(error)) throw error;
|
|
653
323
|
await endSession(signal, error, storage);
|
|
654
324
|
met = error;
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
const stale = box.get().sessionId;
|
|
329
|
+
if (stale !== null && resuming() && Date.now() - (_nullishCoalesce(me.reads.get(stale), () => ( 0))) > CART_REREAD_MS) {
|
|
330
|
+
let answer;
|
|
331
|
+
try {
|
|
332
|
+
answer = await read(signal, stale);
|
|
333
|
+
} catch (error) {
|
|
334
|
+
if (signal.aborted) throw error;
|
|
335
|
+
if (ended(error)) {
|
|
336
|
+
await endSession(signal, error, storage);
|
|
337
|
+
met = error;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (answer !== void 0) {
|
|
341
|
+
const seen = answer;
|
|
342
|
+
await soft(signal, () => supersede(signal, seen, storage));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
const id = box.get().sessionId;
|
|
346
|
+
if (id !== null && await attempt(id)) return void 0;
|
|
347
|
+
if (resuming()) {
|
|
348
|
+
const found = await find(signal, wanted(options));
|
|
349
|
+
if (found !== null) {
|
|
350
|
+
let adopted = true;
|
|
351
|
+
await soft(signal, async () => {
|
|
352
|
+
try {
|
|
353
|
+
await adopt(signal, found, storage);
|
|
354
|
+
} catch (error) {
|
|
355
|
+
adopted = false;
|
|
356
|
+
throw error;
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
if (adopted && await attempt(found.sessionId)) return void 0;
|
|
655
360
|
}
|
|
656
361
|
}
|
|
657
362
|
const cart = box.get().cart;
|
|
@@ -687,13 +392,16 @@ function createController(home) {
|
|
|
687
392
|
me.tail = result.catch(() => void 0);
|
|
688
393
|
return result;
|
|
689
394
|
}
|
|
690
|
-
async function restore(signal, storage = ctx().cartStorage) {
|
|
395
|
+
async function restore(signal, storage = ctx().cartStorage, look = true) {
|
|
691
396
|
const id = await live(signal, storage.get());
|
|
692
|
-
if (id === null || id === "")
|
|
397
|
+
if (id === null || id === "") {
|
|
398
|
+
if (look) await findOnce(signal, storage);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
693
401
|
box.set({ sessionId: id, cartUrl: fallbackUrl(id), status: "loading" });
|
|
402
|
+
let answer;
|
|
694
403
|
try {
|
|
695
|
-
|
|
696
|
-
box.set({ cart: answer.cart, status: "ready", error: void 0 });
|
|
404
|
+
answer = await read(signal, id);
|
|
697
405
|
} catch (error) {
|
|
698
406
|
if (signal.aborted) return;
|
|
699
407
|
if (!ended(error)) {
|
|
@@ -707,7 +415,10 @@ function createController(home) {
|
|
|
707
415
|
return;
|
|
708
416
|
}
|
|
709
417
|
reset();
|
|
418
|
+
if (look) await findOnce(signal, storage);
|
|
419
|
+
return;
|
|
710
420
|
}
|
|
421
|
+
if (look) await soft(signal, () => supersede(signal, answer, storage));
|
|
711
422
|
}
|
|
712
423
|
function load() {
|
|
713
424
|
if (loaded) return;
|
|
@@ -716,6 +427,17 @@ function createController(home) {
|
|
|
716
427
|
const signal = me.abort.signal;
|
|
717
428
|
me.tail = me.tail.then(() => me.unremoved ? void 0 : restore(signal)).catch(() => void 0);
|
|
718
429
|
}
|
|
430
|
+
async function claimSettled(signal) {
|
|
431
|
+
const source = ctx().customerCart;
|
|
432
|
+
if (source === void 0) return false;
|
|
433
|
+
try {
|
|
434
|
+
await live(signal, source.whenClaimSettled());
|
|
435
|
+
return true;
|
|
436
|
+
} catch (error) {
|
|
437
|
+
if (signal.aborted) throw error;
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
719
441
|
function follow(guest, fresh) {
|
|
720
442
|
const signal = me.abort.signal;
|
|
721
443
|
me.moving = guest;
|
|
@@ -727,18 +449,32 @@ function createController(home) {
|
|
|
727
449
|
me.tail = me.tail.then(async () => {
|
|
728
450
|
await me.writing;
|
|
729
451
|
if (signal.aborted) return;
|
|
730
|
-
if (fresh && !me.unremoved) await restore(signal, guest);
|
|
452
|
+
if (fresh && !me.unremoved) await restore(signal, guest, false);
|
|
731
453
|
if (signal.aborted) return;
|
|
454
|
+
const codes = new Set(me.slots);
|
|
455
|
+
const shown = _optionalChain([box, 'access', _20 => _20.get, 'call', _21 => _21(), 'access', _22 => _22.cart, 'optionalAccess', _23 => _23.currency]);
|
|
456
|
+
if (shown !== void 0) codes.add(shown.toUpperCase());
|
|
457
|
+
await live(signal, forgetSlots(guest, codes));
|
|
458
|
+
me.slots.clear();
|
|
732
459
|
const id = box.get().sessionId;
|
|
733
460
|
if (id === null) {
|
|
734
|
-
if (box.get().cart === null && !me.unremoved)
|
|
461
|
+
if (box.get().cart === null && !me.unremoved) {
|
|
462
|
+
await claimSettled(signal);
|
|
463
|
+
return restore(signal);
|
|
464
|
+
}
|
|
735
465
|
return;
|
|
736
466
|
}
|
|
737
467
|
const next = ctx().cartStorage;
|
|
738
468
|
await write(next, id);
|
|
739
|
-
if (guest
|
|
740
|
-
|
|
741
|
-
|
|
469
|
+
if (guest !== next) {
|
|
470
|
+
await live(signal, guest.remove());
|
|
471
|
+
if (await live(signal, next.get()) !== id) await write(next, id);
|
|
472
|
+
}
|
|
473
|
+
if (resuming() && await claimSettled(signal))
|
|
474
|
+
await soft(
|
|
475
|
+
signal,
|
|
476
|
+
async () => supersede(signal, await read(signal, id), next)
|
|
477
|
+
);
|
|
742
478
|
}).catch((error) => {
|
|
743
479
|
if (!signal.aborted) box.set({ error: wrap(error) });
|
|
744
480
|
}).finally(() => {
|
|
@@ -758,6 +494,9 @@ function createController(home) {
|
|
|
758
494
|
if (was === void 0 || was === null || was === key) return;
|
|
759
495
|
me.abort.abort();
|
|
760
496
|
me.abort = new AbortController();
|
|
497
|
+
me.reads.clear();
|
|
498
|
+
for (const key2 of _nullishCoalesce(home.shared.looked, () => ( [])))
|
|
499
|
+
if (key2.startsWith(`${was}\0`)) _optionalChain([home, 'access', _24 => _24.shared, 'access', _25 => _25.looked, 'optionalAccess', _26 => _26.delete, 'call', _27 => _27(key2)]);
|
|
761
500
|
currency = void 0;
|
|
762
501
|
loaded = true;
|
|
763
502
|
reset();
|
|
@@ -765,9 +504,15 @@ function createController(home) {
|
|
|
765
504
|
const outgoing = _nullishCoalesce(prior, () => ( me.seen));
|
|
766
505
|
const left = me.moving;
|
|
767
506
|
me.moving = void 0;
|
|
507
|
+
const slots = [...me.slots];
|
|
508
|
+
me.slots.clear();
|
|
768
509
|
const remove = async () => {
|
|
769
510
|
await outgoing.remove();
|
|
770
|
-
|
|
511
|
+
await forgetSlots(outgoing, slots);
|
|
512
|
+
if (left !== void 0 && left !== outgoing) {
|
|
513
|
+
await left.remove();
|
|
514
|
+
await forgetSlots(left, slots);
|
|
515
|
+
}
|
|
771
516
|
};
|
|
772
517
|
me.tail = me.writing.then(remove).catch(remove).then(
|
|
773
518
|
() => {
|
|
@@ -784,12 +529,16 @@ function createController(home) {
|
|
|
784
529
|
box,
|
|
785
530
|
/** The customer the cart belongs to (`undefined` before the first look). */
|
|
786
531
|
owner: () => me.owner,
|
|
532
|
+
hint: (next) => {
|
|
533
|
+
hinted = next;
|
|
534
|
+
},
|
|
787
535
|
identify,
|
|
788
536
|
load,
|
|
789
537
|
run,
|
|
790
538
|
mutate,
|
|
791
539
|
create,
|
|
792
540
|
session,
|
|
541
|
+
wanted,
|
|
793
542
|
async switchCurrency(signal, options, next) {
|
|
794
543
|
checkPause(ctx().store);
|
|
795
544
|
const storage = ctx().cartStorage;
|
|
@@ -806,28 +555,67 @@ function createController(home) {
|
|
|
806
555
|
}
|
|
807
556
|
const before = currency;
|
|
808
557
|
currency = next;
|
|
809
|
-
const
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
558
|
+
const code = next.toUpperCase();
|
|
559
|
+
const from = box.get().sessionId;
|
|
560
|
+
const cart = box.get().cart;
|
|
561
|
+
const items = itemsOf(cart);
|
|
562
|
+
if (from === null || items.size === 0) {
|
|
563
|
+
if (from !== null) await live(signal, storage.remove());
|
|
564
|
+
if (items.size === 0) reset();
|
|
813
565
|
return;
|
|
814
566
|
}
|
|
567
|
+
if (_optionalChain([cart, 'optionalAccess', _28 => _28.currency, 'access', _29 => _29.toUpperCase, 'call', _30 => _30()]) === code) return;
|
|
568
|
+
let target;
|
|
569
|
+
let moved;
|
|
815
570
|
try {
|
|
816
|
-
await
|
|
571
|
+
target = await _asyncNullishCoalesce(await findTarget(signal, code, storage), async () => ( await start(signal, options, /* @__PURE__ */ new Map())));
|
|
572
|
+
moved = await live(signal, session(target.id).absorb(from, { signal }));
|
|
817
573
|
} catch (error) {
|
|
818
574
|
if (!signal.aborted) currency = before;
|
|
819
575
|
throw error;
|
|
820
576
|
}
|
|
577
|
+
me.reads.set(target.id, Date.now());
|
|
578
|
+
box.set({
|
|
579
|
+
sessionId: target.id,
|
|
580
|
+
cartUrl: target.cartUrl,
|
|
581
|
+
cart: moved.cart,
|
|
582
|
+
status: "ready",
|
|
583
|
+
error: void 0,
|
|
584
|
+
warnings: moved.warnings.filter(
|
|
585
|
+
(warning) => warning.code !== "lines_stale"
|
|
586
|
+
)
|
|
587
|
+
});
|
|
588
|
+
let unsaved;
|
|
589
|
+
try {
|
|
590
|
+
await save(signal, storage, target.id);
|
|
591
|
+
} catch (error) {
|
|
592
|
+
if (signal.aborted) throw error;
|
|
593
|
+
unsaved = error;
|
|
594
|
+
try {
|
|
595
|
+
await live(signal, storage.remove());
|
|
596
|
+
} catch (failure) {
|
|
597
|
+
if (signal.aborted) throw failure;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
if (ctx().customerKey === null && storage.setFor !== void 0) {
|
|
601
|
+
me.slots.add(code);
|
|
602
|
+
await live(signal, storage.setFor(code, target.id));
|
|
603
|
+
}
|
|
604
|
+
if (unsaved !== void 0) throw unsaved;
|
|
821
605
|
},
|
|
822
606
|
async clear(signal) {
|
|
823
|
-
|
|
607
|
+
const storage = ctx().cartStorage;
|
|
608
|
+
const shown = _optionalChain([box, 'access', _31 => _31.get, 'call', _32 => _32(), 'access', _33 => _33.cart, 'optionalAccess', _34 => _34.currency]);
|
|
609
|
+
await live(signal, storage.remove());
|
|
610
|
+
if (shown !== void 0)
|
|
611
|
+
await live(signal, _optionalChain([storage, 'access', _35 => _35.removeFor, 'optionalCall', _36 => _36(shown.toUpperCase())]));
|
|
824
612
|
currency = void 0;
|
|
825
613
|
reset();
|
|
826
614
|
}
|
|
827
615
|
};
|
|
828
616
|
}
|
|
829
617
|
function useCart(options = {}) {
|
|
830
|
-
const context = useCatalogContext();
|
|
618
|
+
const context = _chunkGU63WFXIcjs.useCatalogContext.call(void 0, );
|
|
831
619
|
const home = context.cart;
|
|
832
620
|
const controller = _nullishCoalesce(home.current, () => ( (home.current = createController(home))));
|
|
833
621
|
const state = _react.useSyncExternalStore.call(void 0,
|
|
@@ -836,6 +624,10 @@ function useCart(options = {}) {
|
|
|
836
624
|
controller.box.get
|
|
837
625
|
);
|
|
838
626
|
const { customerKey } = context;
|
|
627
|
+
const hooked = options.currency;
|
|
628
|
+
_react.useEffect.call(void 0, () => {
|
|
629
|
+
controller.hint(hooked);
|
|
630
|
+
}, [controller, hooked]);
|
|
839
631
|
_react.useEffect.call(void 0, () => {
|
|
840
632
|
controller.identify(customerKey);
|
|
841
633
|
controller.load();
|
|
@@ -873,8 +665,8 @@ function useCart(options = {}) {
|
|
|
873
665
|
),
|
|
874
666
|
checkout: (input) => controller.run(async (signal) => {
|
|
875
667
|
const { cartUrls } = home.context;
|
|
876
|
-
const returnUrl = _nullishCoalesce(_optionalChain([input, 'optionalAccess',
|
|
877
|
-
const cancelUrl = _nullishCoalesce(_optionalChain([input, 'optionalAccess',
|
|
668
|
+
const returnUrl = _nullishCoalesce(_optionalChain([input, 'optionalAccess', _37 => _37.returnUrl]), () => ( _optionalChain([cartUrls, 'optionalAccess', _38 => _38.returnUrl])));
|
|
669
|
+
const cancelUrl = _nullishCoalesce(_optionalChain([input, 'optionalAccess', _39 => _39.cancelUrl]), () => ( _optionalChain([cartUrls, 'optionalAccess', _40 => _40.cancelUrl])));
|
|
878
670
|
if (returnUrl === void 0 || cancelUrl === void 0)
|
|
879
671
|
throw refuse(
|
|
880
672
|
"checkout() needs returnUrl and cancelUrl, given or from the provider cartUrls."
|
|
@@ -897,7 +689,7 @@ function useCart(options = {}) {
|
|
|
897
689
|
{ signal: callSignal }
|
|
898
690
|
);
|
|
899
691
|
} catch (error) {
|
|
900
|
-
const repriced =
|
|
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;
|
|
901
693
|
if (!callSignal.aborted && typeof repriced === "object" && repriced !== null)
|
|
902
694
|
controller.box.set({ cart: repriced });
|
|
903
695
|
throw error;
|
|
@@ -917,7 +709,7 @@ function useCart(options = {}) {
|
|
|
917
709
|
if (out === void 0)
|
|
918
710
|
throw _nullishCoalesce(met, () => ( refuse("There is no cart to check out.")));
|
|
919
711
|
if (!isHttpUrl(out.checkoutUrl))
|
|
920
|
-
throw new (0,
|
|
712
|
+
throw new (0, _chunk2YQNMBDIcjs.CatalogError)({
|
|
921
713
|
code: "INVALID_RESPONSE",
|
|
922
714
|
message: "Throttle answered a checkout URL that is not http or https.",
|
|
923
715
|
statusCode: 200,
|
|
@@ -933,8 +725,10 @@ function useCart(options = {}) {
|
|
|
933
725
|
};
|
|
934
726
|
}, [controller, home, currency, locale]);
|
|
935
727
|
const owner = controller.owner();
|
|
936
|
-
const view = owner !== void 0 && owner !== null && owner !== customerKey ? { ...
|
|
937
|
-
|
|
728
|
+
const view = owner !== void 0 && owner !== null && owner !== customerKey ? { ...EMPTY, pending: state.pending } : state;
|
|
729
|
+
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);
|
|
731
|
+
return { ...view, ...actions, format };
|
|
938
732
|
}
|
|
939
733
|
|
|
940
734
|
// src/react/use-submit-review.ts
|
|
@@ -945,7 +739,7 @@ var IDLE = {
|
|
|
945
739
|
result: void 0
|
|
946
740
|
};
|
|
947
741
|
function useSubmitReview(handle) {
|
|
948
|
-
const { client, store, customerKey } = useCatalogContext();
|
|
742
|
+
const { client, store, customerKey } = _chunkGU63WFXIcjs.useCatalogContext.call(void 0, );
|
|
949
743
|
const scope = _react.useMemo.call(void 0,
|
|
950
744
|
() => ({
|
|
951
745
|
box: createBox(IDLE),
|
|
@@ -1015,4 +809,5 @@ function useSubmitReview(handle) {
|
|
|
1015
809
|
|
|
1016
810
|
|
|
1017
811
|
|
|
1018
|
-
|
|
812
|
+
|
|
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;
|