@brytdesigns/shopify-ajax-cart 1.1.8 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/main/actions.d.ts +378 -0
  2. package/dist/main/actions.js +80 -0
  3. package/dist/main/actions.js.map +1 -0
  4. package/dist/main/api.js +56 -6
  5. package/dist/main/api.js.map +1 -1
  6. package/dist/main/client.js +88 -22
  7. package/dist/main/client.js.map +1 -1
  8. package/dist/main/const.js +5 -6
  9. package/dist/main/const.js.map +1 -1
  10. package/dist/main/index.d.ts +6062 -4779
  11. package/dist/main/index.js +105 -109
  12. package/dist/main/index.js.map +1 -1
  13. package/dist/main/mutations/addItems.js +18 -23
  14. package/dist/main/mutations/addItems.js.map +1 -1
  15. package/dist/main/mutations/clearCart.js +28 -33
  16. package/dist/main/mutations/clearCart.js.map +1 -1
  17. package/dist/main/mutations/index.js +8 -18
  18. package/dist/main/mutations/removeItems.js +44 -41
  19. package/dist/main/mutations/removeItems.js.map +1 -1
  20. package/dist/main/mutations/replaceItem.js +33 -57
  21. package/dist/main/mutations/replaceItem.js.map +1 -1
  22. package/dist/main/mutations/updateAttributes.js +34 -42
  23. package/dist/main/mutations/updateAttributes.js.map +1 -1
  24. package/dist/main/mutations/updateDiscounts.js +18 -28
  25. package/dist/main/mutations/updateDiscounts.js.map +1 -1
  26. package/dist/main/mutations/updateItem.js +47 -62
  27. package/dist/main/mutations/updateItem.js.map +1 -1
  28. package/dist/main/mutations/updateNote.js +31 -39
  29. package/dist/main/mutations/updateNote.js.map +1 -1
  30. package/dist/main/query/cart.js +28 -31
  31. package/dist/main/query/cart.js.map +1 -1
  32. package/dist/main/query/index.js +1 -4
  33. package/dist/main/reactive-root.js +32 -0
  34. package/dist/main/reactive-root.js.map +1 -0
  35. package/dist/main/utils.js +28 -25
  36. package/dist/main/utils.js.map +1 -1
  37. package/package.json +15 -9
  38. package/dist/esm/index.js +0 -518
  39. package/dist/esm/index.js.map +0 -1
  40. package/dist/jsdelivr/api.js +0 -8
  41. package/dist/jsdelivr/api.js.map +0 -1
  42. package/dist/jsdelivr/client.js +0 -20
  43. package/dist/jsdelivr/client.js.map +0 -1
  44. package/dist/jsdelivr/index.js +0 -94
  45. package/dist/jsdelivr/index.js.map +0 -1
  46. package/dist/jsdelivr/mutations/addItems.js +0 -24
  47. package/dist/jsdelivr/mutations/addItems.js.map +0 -1
  48. package/dist/jsdelivr/mutations/clearCart.js +0 -39
  49. package/dist/jsdelivr/mutations/clearCart.js.map +0 -1
  50. package/dist/jsdelivr/mutations/index.js +0 -18
  51. package/dist/jsdelivr/mutations/index.js.map +0 -1
  52. package/dist/jsdelivr/mutations/removeItems.js +0 -44
  53. package/dist/jsdelivr/mutations/removeItems.js.map +0 -1
  54. package/dist/jsdelivr/mutations/replaceItem.js +0 -49
  55. package/dist/jsdelivr/mutations/replaceItem.js.map +0 -1
  56. package/dist/jsdelivr/mutations/updateAttributes.js +0 -43
  57. package/dist/jsdelivr/mutations/updateAttributes.js.map +0 -1
  58. package/dist/jsdelivr/mutations/updateDiscounts.js +0 -28
  59. package/dist/jsdelivr/mutations/updateDiscounts.js.map +0 -1
  60. package/dist/jsdelivr/mutations/updateItem.js +0 -69
  61. package/dist/jsdelivr/mutations/updateItem.js.map +0 -1
  62. package/dist/jsdelivr/mutations/updateNote.js +0 -40
  63. package/dist/jsdelivr/mutations/updateNote.js.map +0 -1
  64. package/dist/jsdelivr/query/cart.js +0 -30
  65. package/dist/jsdelivr/query/cart.js.map +0 -1
  66. package/dist/jsdelivr/query/index.js +0 -4
  67. package/dist/jsdelivr/query/index.js.map +0 -1
  68. package/dist/jsdelivr/types.js +0 -3
  69. package/dist/jsdelivr/types.js.map +0 -1
  70. package/dist/jsdelivr/utils.js +0 -33
  71. package/dist/jsdelivr/utils.js.map +0 -1
  72. package/dist/main/mutations/index.js.map +0 -1
  73. package/dist/main/query/index.js.map +0 -1
  74. package/dist/main/types.js +0 -3
  75. package/dist/main/types.js.map +0 -1
@@ -0,0 +1,378 @@
1
+ // Generated by dts-bundle-generator v9.5.1
2
+
3
+ import * as Cause from 'effect/Cause';
4
+ import * as Context from 'effect/Context';
5
+ import * as Effect from 'effect/Effect';
6
+ import * as Layer from 'effect/Layer';
7
+ import * as LogLevel from 'effect/LogLevel';
8
+ import * as Scope from 'effect/Scope';
9
+
10
+ declare const toAsyncCallback: <Args extends ReadonlyArray<unknown>, A, E, R>(services: Context.Context<R>, f: (...args: Args) => Effect.Effect<A, E, R>) => (...args: Args) => Promise<A>;
11
+ declare const toSyncCallback: <Args extends ReadonlyArray<unknown>, A, R>(services: Context.Context<R>, f: (...args: Args) => Effect.Effect<A, never, R>, onAbnormal: (cause: Cause.Cause<never>) => A) => (...args: Args) => A;
12
+ declare const fromPromiseThunk: <A, E>(thunk: () => Promise<A>, onReject: (cause: unknown) => E) => Effect.Effect<A, E>;
13
+ /** Every action exposed on `window.Shopify.actions`. */
14
+ export type ActionName = "getCart" | "updateCart" | "openCart";
15
+ /**
16
+ * Only `updateCart` and `openCart` are `ActionFunction`s — `getCart` is a bare
17
+ * callable with no `configure()` / `isDefault()`.
18
+ */
19
+ export type ConfigurableActionName = Exclude<ActionName, "getCart">;
20
+ declare const ActionsUnavailableError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{
21
+ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P];
22
+ }>) => import("effect/Cause").YieldableError & {
23
+ readonly _tag: "@brytdesigns/shopify-utils/ActionsUnavailableError";
24
+ } & Readonly<A>;
25
+ declare class ActionsUnavailableError extends ActionsUnavailableError_base<{
26
+ readonly action: ActionName;
27
+ readonly message: string;
28
+ }> {
29
+ constructor(options: {
30
+ readonly action: ActionName;
31
+ });
32
+ }
33
+ declare const ActionConfigurationRejectedError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{
34
+ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P];
35
+ }>) => import("effect/Cause").YieldableError & {
36
+ readonly _tag: "@brytdesigns/shopify-utils/ActionConfigurationRejectedError";
37
+ } & Readonly<A>;
38
+ declare class ActionConfigurationRejectedError extends ActionConfigurationRejectedError_base<{
39
+ readonly action: ConfigurableActionName;
40
+ readonly message: string;
41
+ }> {
42
+ constructor(options: {
43
+ readonly action: ConfigurableActionName;
44
+ });
45
+ }
46
+ declare const ActionInvocationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{
47
+ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P];
48
+ }>) => import("effect/Cause").YieldableError & {
49
+ readonly _tag: "@brytdesigns/shopify-utils/ActionInvocationError";
50
+ } & Readonly<A>;
51
+ declare class ActionInvocationError extends ActionInvocationError_base<{
52
+ readonly action: ActionName;
53
+ readonly cause: unknown;
54
+ readonly message: string;
55
+ }> {
56
+ constructor(options: {
57
+ readonly action: ActionName;
58
+ readonly cause: unknown;
59
+ });
60
+ }
61
+ // -----------------------------------------------------------------------------
62
+ // VENDORED FILE — DO NOT EDIT BY HAND.
63
+ //
64
+ // Source: https://cdn.shopify.com/storefront/standard-actions.d.ts
65
+ // Vendored: 2026-08-13
66
+ // Upstream version (see `// version:` line below): 977e4f914dd2b3eca85ad01dee81c2c96eb1b2e5
67
+ // sha256 (upstream body only, i.e. everything below this header):
68
+ // 2f0fc044f35999cd09550b8b68620077601d1409817edae16745e600417788e7
69
+ //
70
+ // Everything below this header is the upstream file byte-for-byte. To diff
71
+ // against a future revision:
72
+ //
73
+ // curl -sSL https://cdn.shopify.com/storefront/standard-actions.d.ts \
74
+ // | diff - <(tail -n +25 shopify/utils/src/types/standard-actions.d.ts)
75
+ //
76
+ // There is NO npm package for this. Shopify injects the runtime on every Liquid
77
+ // storefront as `window.Shopify.actions`; a module build for import maps lives
78
+ // at https://cdn.shopify.com/storefront/standard-actions.js. Do not add a
79
+ // dependency — import types via the `@theme/standard-actions` alias
80
+ // (see tsconfig.json `paths`), which is marked `external` in tsup.config.ts.
81
+ //
82
+ // This file is excluded from Biome in the root biome.json so formatting/lint
83
+ // never rewrites upstream content and pollutes the diff.
84
+ // -----------------------------------------------------------------------------
85
+ // version: 977e4f914dd2b3eca85ad01dee81c2c96eb1b2e5
86
+ export interface Price {
87
+ amount: string;
88
+ currencyCode: string;
89
+ }
90
+ export interface CartDiscountCode {
91
+ applicable: boolean;
92
+ code: string;
93
+ }
94
+ export interface CartCost {
95
+ totalAmount: Price;
96
+ }
97
+ export interface CartLine {
98
+ id: string;
99
+ quantity: number;
100
+ cost: CartCost;
101
+ }
102
+ export interface CartMutationUserError {
103
+ code?: string;
104
+ field?: string[];
105
+ message: string;
106
+ }
107
+ export interface CartMutationWarning {
108
+ code?: string;
109
+ message: string;
110
+ target?: string;
111
+ }
112
+ declare const CART_UPDATE_CONTEXTS: readonly [
113
+ "product",
114
+ "cart",
115
+ "dialog",
116
+ "standard-action"
117
+ ];
118
+ export type CartUpdateContext = (typeof CART_UPDATE_CONTEXTS)[number];
119
+ declare const CART_UPDATE_ACTIONS: readonly [
120
+ "add",
121
+ "remove",
122
+ "update"
123
+ ];
124
+ export type CartUpdateAction = (typeof CART_UPDATE_ACTIONS)[number];
125
+ export type ActionArgs<P, O = void> = [
126
+ P
127
+ ] extends [
128
+ void
129
+ ] ? [
130
+ options?: O
131
+ ] : [
132
+ Extract<P, void>
133
+ ] extends [
134
+ never
135
+ ] ? [
136
+ payload: P,
137
+ options?: O
138
+ ] : [
139
+ payload?: Exclude<P, void>,
140
+ options?: O
141
+ ];
142
+ export type UpdateCartUserError = CartMutationUserError;
143
+ export type UpdateCartWarning = CartMutationWarning;
144
+ export interface CartAttributeInput {
145
+ key: string;
146
+ value: string;
147
+ }
148
+ export interface StorefrontCartLinesConnection {
149
+ nodes: CartLine[];
150
+ }
151
+ export interface StorefrontCartSummary {
152
+ id: string;
153
+ totalQuantity: number;
154
+ cost: CartCost;
155
+ lines: StorefrontCartLinesConnection;
156
+ discountCodes: CartDiscountCode[];
157
+ }
158
+ export type UpdateCartEventTargetMeta = {
159
+ type: "shopify:cart:lines-update";
160
+ action: CartUpdateAction;
161
+ } | {
162
+ type: "shopify:cart:note-update" | "shopify:cart:attributes-update" | "shopify:cart:discount-update" | "shopify:cart:error";
163
+ };
164
+ export interface CartLineInput {
165
+ /**
166
+ * Existing-line id from SFAPI or the AJAX cart API.
167
+ * CartLine GIDs keep or receive a `?cart=` suffix automatically when the cart id is known.
168
+ * Present = update/remove; absent = add.
169
+ */
170
+ id?: string;
171
+ /** ProductVariant GID or raw variant id. Required for add. */
172
+ merchandiseId?: string;
173
+ /** Set to 0 to remove. */
174
+ quantity: number;
175
+ /** Line item-level custom attributes */
176
+ attributes?: CartAttributeInput[];
177
+ /** Selling plan GID or raw selling plan id. */
178
+ sellingPlanId?: string;
179
+ }
180
+ export interface UpdateCartPayload {
181
+ /** Cart GID or raw cart token. If omitted, discovered from the cart cookie. */
182
+ cartId?: string;
183
+ lines?: CartLineInput[];
184
+ note?: string;
185
+ discountCodes?: string[];
186
+ /** Cart-level custom attributes */
187
+ attributes?: CartAttributeInput[];
188
+ }
189
+ export interface UpdateCartResult {
190
+ cart: StorefrontCartSummary;
191
+ userErrors?: UpdateCartUserError[];
192
+ warnings?: UpdateCartWarning[];
193
+ detail?: Record<string, any>;
194
+ }
195
+ export interface UpdateCartOptions {
196
+ signal?: AbortSignal;
197
+ event?: {
198
+ detail?: Record<string, any>;
199
+ context?: CartUpdateContext;
200
+ };
201
+ }
202
+ export interface GetCartPayload {
203
+ /** Cart GID or raw cart token. If omitted, discovered from the browser cookie. */
204
+ cartId?: string;
205
+ }
206
+ export interface GetCartResult {
207
+ cart: StorefrontCartSummary | null;
208
+ detail?: Record<string, any>;
209
+ }
210
+ export interface GetCartOptions {
211
+ signal?: AbortSignal;
212
+ }
213
+ /**
214
+ * The default handler, lifted into Effect-land.
215
+ *
216
+ * Handlers receive this rather than a pre-computed result so they keep the full
217
+ * range of the upstream contract: run the default, wrap it, retry it, race it,
218
+ * or skip it entirely and synthesise a result.
219
+ */
220
+ export type DefaultHandler<A> = Effect.Effect<A, ActionInvocationError>;
221
+ /**
222
+ * An action handler written in Effect.
223
+ *
224
+ * The returned Effect's success value is what the action resolves with, and its
225
+ * failure becomes a rejected promise for Shopify.
226
+ *
227
+ * Note that `E` is checked but never surfaces to the fiber that called
228
+ * `configure` — the handler runs long afterwards, when a shopper triggers the
229
+ * action, so its failure has nowhere to go but the promise Shopify awaits. If
230
+ * you want handler failures observed, observe them inside the handler.
231
+ */
232
+ export type Handler<P, A, O, E, R> = (defaultHandler: DefaultHandler<A>, ...args: ActionArgs<P, O>) => Effect.Effect<A, E, R>;
233
+ /**
234
+ * Resolves the element that `shopify:cart:*` events are dispatched from.
235
+ *
236
+ * The error channel is `never` on purpose. Shopify calls this synchronously and
237
+ * uses the return value immediately, so there is nowhere for a failure to go —
238
+ * handle errors inside the Effect and fall back to an element or `null`.
239
+ *
240
+ * For the same reason this Effect must complete synchronously. Anything that
241
+ * suspends (`Effect.sleep`, an HTTP call, an async service) cannot produce a
242
+ * value in time and is reported as `null` with a logged defect, which makes
243
+ * Shopify dispatch on `document`. If you need async work, resolve it ahead of
244
+ * time into a `Ref` and read the `Ref` here.
245
+ */
246
+ export type EventTargetResolver<R> = (meta: UpdateCartEventTargetMeta) => Effect.Effect<EventTarget | null, never, R>;
247
+ export interface UpdateCartConfiguration<E, R> {
248
+ readonly eventTarget: EventTargetResolver<R>;
249
+ /** Optional: routing events without changing cart behaviour is valid. */
250
+ readonly handler?: Handler<UpdateCartPayload, UpdateCartResult, UpdateCartOptions, E, R>;
251
+ }
252
+ export interface OpenCartConfiguration<E, R> {
253
+ /**
254
+ * Required, unlike `updateCart`'s. `openCart` has no event target, so a
255
+ * configuration without a handler would claim the one-shot upstream slot
256
+ * while contributing nothing — locking everyone else out for the life of
257
+ * the page in exchange for default behaviour.
258
+ */
259
+ readonly handler: Handler<void, void, void, E, R>;
260
+ }
261
+ export interface ShopifyStorefrontActionsImpl {
262
+ /**
263
+ * Read the current cart. `getCart` is a bare callable upstream — it has no
264
+ * `configure()`, so there is no `configureGetCart`.
265
+ */
266
+ readonly getCart: (payload?: GetCartPayload, options?: GetCartOptions) => Effect.Effect<GetCartResult, ActionsUnavailableError | ActionInvocationError>;
267
+ readonly updateCart: (payload: UpdateCartPayload, options?: UpdateCartOptions) => Effect.Effect<UpdateCartResult, ActionsUnavailableError | ActionInvocationError>;
268
+ readonly openCart: Effect.Effect<void, ActionsUnavailableError | ActionInvocationError>;
269
+ /**
270
+ * Install an Effect-based `updateCart` configuration for the lifetime of the
271
+ * enclosing `Scope`.
272
+ *
273
+ * The `R` of the supplied Effects flows out into the returned Effect's
274
+ * requirements, so the services your handler needs stay explicit and must be
275
+ * provided before this runs — they are captured, not smuggled.
276
+ *
277
+ * Calling this more than once rebinds rather than failing: we claim the
278
+ * upstream slot once and swap our own configuration behind it. A
279
+ * `ActionConfigurationRejectedError` therefore means one specific thing —
280
+ * something outside this library claimed the action first.
281
+ *
282
+ * For page-lifetime registration, build it into a layer with
283
+ * `Layer.effectDiscard(Actions.configureUpdateCart({ ... }))` so the
284
+ * registration lives exactly as long as the runtime does.
285
+ */
286
+ readonly configureUpdateCart: <E, R>(config: UpdateCartConfiguration<E, R>) => Effect.Effect<void, ActionsUnavailableError | ActionConfigurationRejectedError, R | Scope.Scope>;
287
+ readonly configureOpenCart: <E, R>(config: OpenCartConfiguration<E, R>) => Effect.Effect<void, ActionsUnavailableError | ActionConfigurationRejectedError, R | Scope.Scope>;
288
+ /**
289
+ * Upstream's own notion: `true` until the action's slot is claimed.
290
+ *
291
+ * Because the slot can never be released, this stays `false` once we have
292
+ * claimed it, even after every configuration has been deactivated.
293
+ */
294
+ readonly isDefault: (action: ConfigurableActionName) => Effect.Effect<boolean, ActionsUnavailableError>;
295
+ }
296
+ declare const ShopifyStorefrontActions_base: Context.ServiceClass<ShopifyStorefrontActions, "@brytdesigns/shopify-utils/ShopifyStorefrontActions", ShopifyStorefrontActionsImpl>;
297
+ declare class ShopifyStorefrontActions extends ShopifyStorefrontActions_base {
298
+ }
299
+ declare const layer: Layer.Layer<ShopifyStorefrontActions, never, never>;
300
+ declare const getCart: (payload?: GetCartPayload, options?: GetCartOptions) => Effect.Effect<GetCartResult, ActionsUnavailableError | ActionInvocationError, ShopifyStorefrontActions>;
301
+ declare const updateCart: (payload: UpdateCartPayload, options?: UpdateCartOptions) => Effect.Effect<UpdateCartResult, ActionsUnavailableError | ActionInvocationError, ShopifyStorefrontActions>;
302
+ declare const openCart: Effect.Effect<void, ActionsUnavailableError | ActionInvocationError, ShopifyStorefrontActions>;
303
+ declare const configureUpdateCart: <E, R>(config: UpdateCartConfiguration<E, R>) => Effect.Effect<void, ActionsUnavailableError | ActionConfigurationRejectedError, Scope.Scope | ShopifyStorefrontActions | R>;
304
+ declare const configureOpenCart: <E, R>(config: OpenCartConfiguration<E, R>) => Effect.Effect<void, ActionsUnavailableError | ActionConfigurationRejectedError, Scope.Scope | ShopifyStorefrontActions | R>;
305
+ declare const isDefault: (action: ConfigurableActionName) => Effect.Effect<boolean, ActionsUnavailableError, ShopifyStorefrontActions>;
306
+ declare namespace Bridge {
307
+ export { fromPromiseThunk, toAsyncCallback, toSyncCallback };
308
+ }
309
+ declare namespace Actions {
310
+ export { ActionConfigurationRejectedError, ActionInvocationError, ActionName, ActionsUnavailableError, Bridge, CartAttributeInput, CartCost, CartDiscountCode, CartLine, CartLineInput, CartMutationUserError, CartMutationWarning, CartUpdateAction, CartUpdateContext, ConfigurableActionName, DefaultHandler, EventTargetResolver, GetCartOptions, GetCartPayload, GetCartResult, Handler, OpenCartConfiguration, Price, ShopifyStorefrontActions, ShopifyStorefrontActionsImpl, StorefrontCartLinesConnection, StorefrontCartSummary, UpdateCartConfiguration, UpdateCartEventTargetMeta, UpdateCartOptions, UpdateCartPayload, UpdateCartResult, UpdateCartUserError, UpdateCartWarning, configureOpenCart, configureUpdateCart, getCart, isDefault, layer, openCart, updateCart };
311
+ }
312
+ export declare namespace syncWithStorefrontActions {
313
+ type Options = {
314
+ /**
315
+ * Opens the cart. Supply this and `openCart` is configured; omit it and the
316
+ * action is left alone entirely.
317
+ *
318
+ * Shopify's default looks for `<cart-drawer-component>` or `<cart-drawer>`
319
+ * with an `.open()` method and, finding neither, sets
320
+ * `window.location.href = "/cart"`. Bryt themes have neither, so without a
321
+ * callback here every `Shopify.actions.openCart()` navigates the shopper
322
+ * off the page.
323
+ *
324
+ * @example
325
+ * ```ts
326
+ * openCart: () => {
327
+ * const drawer = document.querySelector("drawer-context#cart");
328
+ * if (drawer) drawer.isOpen = true;
329
+ * }
330
+ * ```
331
+ */
332
+ openCart?: () => void;
333
+ /**
334
+ * Chooses the element `shopify:cart:*` events are dispatched from.
335
+ *
336
+ * Returning `null` - the default - dispatches on `document`, which is what
337
+ * Shopify does when nothing is configured. Because these events are
338
+ * `bubbles: true`, returning an element is purely additive: listeners on
339
+ * `document` still fire.
340
+ *
341
+ * Must be synchronous. Shopify uses the return value immediately.
342
+ */
343
+ eventTarget?: (meta: Actions.UpdateCartEventTargetMeta) => EventTarget | null;
344
+ };
345
+ /** Deactivates the configuration installed by this call. */
346
+ type Dispose = () => Promise<void>;
347
+ }
348
+ /**
349
+ * Route Shopify's storefront cart actions through AjaxCart.
350
+ *
351
+ * Two regressions on a Bryt theme are fixed by configuring at all, before any
352
+ * resync happens. While `updateCart` is unconfigured, Shopify probes for Dawn's
353
+ * `<cart-icon>` / `<cart-items-component>` and for `cart-drawer`-family
354
+ * elements, and finding none falls back to `window.location.reload()`. And
355
+ * `openCart` falls back to navigating to `/cart`.
356
+ *
357
+ * Opt-in by design: this claims page-global, one-shot configuration slots, so
358
+ * it is the theme's call to make, not something that happens on import.
359
+ *
360
+ * Retries while the actions runtime is absent. Shopify installs
361
+ * `window.Shopify.actions` from a synchronous IIFE and announces nothing, so
362
+ * there is no readiness signal to wait on and script order is not ours to
363
+ * control.
364
+ *
365
+ * @example
366
+ * ```ts
367
+ * const dispose = await syncWithStorefrontActions({
368
+ * openCart: () => { drawer.isOpen = true; },
369
+ * });
370
+ * ```
371
+ */
372
+ export declare const syncWithStorefrontActions: (options?: syncWithStorefrontActions.Options) => Promise<syncWithStorefrontActions.Dispose>;
373
+
374
+ export {
375
+ syncWithStorefrontActions as default,
376
+ };
377
+
378
+ export {};
@@ -0,0 +1,80 @@
1
+ import { cancel, invalidate } from "./query/cart.js";
2
+ import "./query/index.js";
3
+ import { Actions } from "@brytdesigns/shopify-utils/effect";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Exit from "effect/Exit";
6
+ import * as Schedule from "effect/Schedule";
7
+ import * as Scope from "effect/Scope";
8
+ //#region src/actions.ts
9
+ /**
10
+ * Refetch `/cart.js`.
11
+ *
12
+ * This has to be a refetch rather than a cache write: the handler is handed a
13
+ * `StorefrontCartSummary` (`id`, `totalQuantity`, `cost`, `lines.nodes`,
14
+ * `discountCodes`) while `CartData` is the classic AJAX shape, with line
15
+ * titles, images and discount allocations that the summary simply does not
16
+ * carry.
17
+ *
18
+ * Cancel-then-invalidate mirrors what the `window.fetch` patch in `index.ts`
19
+ * already does for `/cart/*` mutations.
20
+ *
21
+ * Failure is swallowed on purpose. Shopify rethrows whatever the handler
22
+ * rejects with, so letting a transient `/cart.js` error escape would report an
23
+ * add-to-cart that already succeeded - and whose cart cookie is already
24
+ * written - to the shopper as a failure.
25
+ */
26
+ var resync = Effect.promise(async () => {
27
+ await cancel();
28
+ await invalidate();
29
+ }).pipe(Effect.catchCause((cause) => Effect.logWarning("AjaxCart resync failed after a storefront cart action", cause)));
30
+ var configure = (options) => Effect.gen(function* () {
31
+ yield* Actions.configureUpdateCart({
32
+ eventTarget: (meta) => Effect.sync(() => options.eventTarget?.(meta) ?? null),
33
+ handler: (defaultAction, payload) => defaultAction.pipe(Effect.tap(() => payload.cartId === void 0 ? resync : Effect.logDebug("updateCart was given an explicit cartId; the cart cookie is not synced, so AjaxCart was left alone")))
34
+ });
35
+ const openCart = options.openCart;
36
+ if (openCart === void 0) return;
37
+ yield* Actions.configureOpenCart({ handler: () => Effect.try(() => openCart()).pipe(Effect.catchCause((cause) => Effect.logError("openCart callback threw; cart was not opened", cause))) });
38
+ });
39
+ /**
40
+ * Route Shopify's storefront cart actions through AjaxCart.
41
+ *
42
+ * Two regressions on a Bryt theme are fixed by configuring at all, before any
43
+ * resync happens. While `updateCart` is unconfigured, Shopify probes for Dawn's
44
+ * `<cart-icon>` / `<cart-items-component>` and for `cart-drawer`-family
45
+ * elements, and finding none falls back to `window.location.reload()`. And
46
+ * `openCart` falls back to navigating to `/cart`.
47
+ *
48
+ * Opt-in by design: this claims page-global, one-shot configuration slots, so
49
+ * it is the theme's call to make, not something that happens on import.
50
+ *
51
+ * Retries while the actions runtime is absent. Shopify installs
52
+ * `window.Shopify.actions` from a synchronous IIFE and announces nothing, so
53
+ * there is no readiness signal to wait on and script order is not ours to
54
+ * control.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * const dispose = await syncWithStorefrontActions({
59
+ * openCart: () => { drawer.isOpen = true; },
60
+ * });
61
+ * ```
62
+ */
63
+ var syncWithStorefrontActions = async (options = {}) => {
64
+ const scope = Effect.runSync(Scope.make());
65
+ const dispose = () => Effect.runPromise(Scope.close(scope, Exit.void));
66
+ try {
67
+ await Effect.runPromise(configure(options).pipe(Effect.retry({
68
+ schedule: Schedule.exponential("50 millis").pipe(Schedule.upTo({ duration: "3 seconds" })),
69
+ while: (error) => error instanceof Actions.ActionsUnavailableError
70
+ }), Scope.provide(scope), Effect.provide(Actions.layer)));
71
+ } catch (error) {
72
+ await dispose();
73
+ throw error;
74
+ }
75
+ return dispose;
76
+ };
77
+ //#endregion
78
+ export { syncWithStorefrontActions as default, syncWithStorefrontActions };
79
+
80
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","names":[],"sources":["../../src/actions.ts"],"sourcesContent":["// The package's ./effect entry exposes namespaces (`export * as Actions`), so\n// the wrapper is reached through the Actions namespace rather than directly.\nimport { Actions } from \"@brytdesigns/shopify-utils/effect\";\nimport * as Effect from \"effect/Effect\";\nimport * as Exit from \"effect/Exit\";\nimport * as Schedule from \"effect/Schedule\";\nimport * as Scope from \"effect/Scope\";\n\nimport { Cart } from \"./query/index.js\";\n\nexport namespace syncWithStorefrontActions {\n\texport type Options = {\n\t\t/**\n\t\t * Opens the cart. Supply this and `openCart` is configured; omit it and the\n\t\t * action is left alone entirely.\n\t\t *\n\t\t * Shopify's default looks for `<cart-drawer-component>` or `<cart-drawer>`\n\t\t * with an `.open()` method and, finding neither, sets\n\t\t * `window.location.href = \"/cart\"`. Bryt themes have neither, so without a\n\t\t * callback here every `Shopify.actions.openCart()` navigates the shopper\n\t\t * off the page.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * openCart: () => {\n\t\t * const drawer = document.querySelector(\"drawer-context#cart\");\n\t\t * if (drawer) drawer.isOpen = true;\n\t\t * }\n\t\t * ```\n\t\t */\n\t\topenCart?: () => void;\n\n\t\t/**\n\t\t * Chooses the element `shopify:cart:*` events are dispatched from.\n\t\t *\n\t\t * Returning `null` - the default - dispatches on `document`, which is what\n\t\t * Shopify does when nothing is configured. Because these events are\n\t\t * `bubbles: true`, returning an element is purely additive: listeners on\n\t\t * `document` still fire.\n\t\t *\n\t\t * Must be synchronous. Shopify uses the return value immediately.\n\t\t */\n\t\teventTarget?: (\n\t\t\tmeta: Actions.UpdateCartEventTargetMeta,\n\t\t) => EventTarget | null;\n\t};\n\n\t/** Deactivates the configuration installed by this call. */\n\texport type Dispose = () => Promise<void>;\n}\n\n/**\n * Refetch `/cart.js`.\n *\n * This has to be a refetch rather than a cache write: the handler is handed a\n * `StorefrontCartSummary` (`id`, `totalQuantity`, `cost`, `lines.nodes`,\n * `discountCodes`) while `CartData` is the classic AJAX shape, with line\n * titles, images and discount allocations that the summary simply does not\n * carry.\n *\n * Cancel-then-invalidate mirrors what the `window.fetch` patch in `index.ts`\n * already does for `/cart/*` mutations.\n *\n * Failure is swallowed on purpose. Shopify rethrows whatever the handler\n * rejects with, so letting a transient `/cart.js` error escape would report an\n * add-to-cart that already succeeded - and whose cart cookie is already\n * written - to the shopper as a failure.\n */\nconst resync = Effect.promise(async () => {\n\tawait Cart.cancel();\n\tawait Cart.invalidate();\n}).pipe(\n\tEffect.catchCause((cause) =>\n\t\tEffect.logWarning(\n\t\t\t\"AjaxCart resync failed after a storefront cart action\",\n\t\t\tcause,\n\t\t),\n\t),\n);\n\nconst configure = (options: syncWithStorefrontActions.Options) =>\n\tEffect.gen(function* () {\n\t\tyield* Actions.configureUpdateCart({\n\t\t\t// Wrapping a plain function in Effect.sync makes the wrapper's\n\t\t\t// synchronous-only contract unrepresentable to break here.\n\t\t\teventTarget: (meta) =>\n\t\t\t\tEffect.sync(() => options.eventTarget?.(meta) ?? null),\n\n\t\t\thandler: (defaultAction, payload) =>\n\t\t\t\tdefaultAction.pipe(\n\t\t\t\t\tEffect.tap(() =>\n\t\t\t\t\t\t// With an explicit cartId, Shopify sets syncCartCookie: false and\n\t\t\t\t\t\t// never writes the cart cookie, so /cart.js still resolves a\n\t\t\t\t\t\t// different cart. Refetching could not reflect this mutation.\n\t\t\t\t\t\tpayload.cartId === undefined\n\t\t\t\t\t\t\t? resync\n\t\t\t\t\t\t\t: Effect.logDebug(\n\t\t\t\t\t\t\t\t\t\"updateCart was given an explicit cartId; the cart cookie is not synced, so AjaxCart was left alone\",\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t});\n\n\t\tconst openCart = options.openCart;\n\n\t\tif (openCart === undefined) return;\n\n\t\tyield* Actions.configureOpenCart({\n\t\t\thandler: () =>\n\t\t\t\tEffect.try(() => openCart()).pipe(\n\t\t\t\t\tEffect.catchCause((cause) =>\n\t\t\t\t\t\t// Deliberately not falling through to Shopify's default, which\n\t\t\t\t\t\t// would navigate to /cart - the behaviour this exists to prevent.\n\t\t\t\t\t\tEffect.logError(\n\t\t\t\t\t\t\t\"openCart callback threw; cart was not opened\",\n\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t});\n\t});\n\n/**\n * Route Shopify's storefront cart actions through AjaxCart.\n *\n * Two regressions on a Bryt theme are fixed by configuring at all, before any\n * resync happens. While `updateCart` is unconfigured, Shopify probes for Dawn's\n * `<cart-icon>` / `<cart-items-component>` and for `cart-drawer`-family\n * elements, and finding none falls back to `window.location.reload()`. And\n * `openCart` falls back to navigating to `/cart`.\n *\n * Opt-in by design: this claims page-global, one-shot configuration slots, so\n * it is the theme's call to make, not something that happens on import.\n *\n * Retries while the actions runtime is absent. Shopify installs\n * `window.Shopify.actions` from a synchronous IIFE and announces nothing, so\n * there is no readiness signal to wait on and script order is not ours to\n * control.\n *\n * @example\n * ```ts\n * const dispose = await syncWithStorefrontActions({\n * openCart: () => { drawer.isOpen = true; },\n * });\n * ```\n */\nexport const syncWithStorefrontActions = async (\n\toptions: syncWithStorefrontActions.Options = {},\n): Promise<syncWithStorefrontActions.Dispose> => {\n\tconst scope = Effect.runSync(Scope.make());\n\n\tconst dispose = () => Effect.runPromise(Scope.close(scope, Exit.void));\n\n\ttry {\n\t\tawait Effect.runPromise(\n\t\t\tconfigure(options).pipe(\n\t\t\t\tEffect.retry({\n\t\t\t\t\tschedule: Schedule.exponential(\"50 millis\").pipe(\n\t\t\t\t\t\tSchedule.upTo({ duration: \"3 seconds\" }),\n\t\t\t\t\t),\n\t\t\t\t\t// A rejected configuration means another script owns the slot; that\n\t\t\t\t\t// will never come good, so only wait on the runtime being absent.\n\t\t\t\t\twhile: (error) => error instanceof Actions.ActionsUnavailableError,\n\t\t\t\t}),\n\t\t\t\tScope.provide(scope),\n\t\t\t\tEffect.provide(Actions.layer),\n\t\t\t),\n\t\t);\n\t} catch (error) {\n\t\tawait dispose();\n\t\tthrow error;\n\t}\n\n\treturn dispose;\n};\n\nexport default syncWithStorefrontActions;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAoEA,IAAM,SAAS,OAAO,QAAQ,YAAY;CACzC,MAAM,OAAY;CAClB,MAAM,WAAgB;AACvB,CAAC,CAAC,CAAC,KACF,OAAO,YAAY,UAClB,OAAO,WACN,yDACA,KACD,CACD,CACD;AAEA,IAAM,aAAa,YAClB,OAAO,IAAI,aAAa;CACvB,OAAO,QAAQ,oBAAoB;EAGlC,cAAc,SACb,OAAO,WAAW,QAAQ,cAAc,IAAI,KAAK,IAAI;EAEtD,UAAU,eAAe,YACxB,cAAc,KACb,OAAO,UAIN,QAAQ,WAAW,KAAA,IAChB,SACA,OAAO,SACP,oGACD,CACH,CACD;CACF,CAAC;CAED,MAAM,WAAW,QAAQ;CAEzB,IAAI,aAAa,KAAA,GAAW;CAE5B,OAAO,QAAQ,kBAAkB,EAChC,eACC,OAAO,UAAU,SAAS,CAAC,CAAC,CAAC,KAC5B,OAAO,YAAY,UAGlB,OAAO,SACN,gDACA,KACD,CACD,CACD,EACF,CAAC;AACF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AA0BF,IAAa,4BAA4B,OACxC,UAA6C,CAAC,MACE;CAChD,MAAM,QAAQ,OAAO,QAAQ,MAAM,KAAK,CAAC;CAEzC,MAAM,gBAAgB,OAAO,WAAW,MAAM,MAAM,OAAO,KAAK,IAAI,CAAC;CAErE,IAAI;EACH,MAAM,OAAO,WACZ,UAAU,OAAO,CAAC,CAAC,KAClB,OAAO,MAAM;GACZ,UAAU,SAAS,YAAY,WAAW,CAAC,CAAC,KAC3C,SAAS,KAAK,EAAE,UAAU,YAAY,CAAC,CACxC;GAGA,QAAQ,UAAU,iBAAiB,QAAQ;EAC5C,CAAC,GACD,MAAM,QAAQ,KAAK,GACnB,OAAO,QAAQ,QAAQ,KAAK,CAC7B,CACD;CACD,SAAS,OAAO;EACf,MAAM,QAAQ;EACd,MAAM;CACP;CAEA,OAAO;AACR"}
package/dist/main/api.js CHANGED
@@ -1,8 +1,58 @@
1
- import { createAjaxCartApi } from '@brytdesigns/shopify-ajax-cart-api';
1
+ import { createAjaxCartApi } from "@brytdesigns/shopify-ajax-cart-api";
2
+ //#region src/api.ts
3
+ var instance;
4
+ var overrides;
5
+ /**
6
+ * Builds the client on first use rather than on import.
7
+ *
8
+ * `debug` comes from `window.BrytDesigns.debug`, which a theme sets from an
9
+ * inline script. Reading it at module scope made the result depend on whether
10
+ * that script ran before or after this module evaluated - and as an ES module
11
+ * in a Shopify theme, it usually ran after, so `debug: true` was silently
12
+ * ignored. Deferring the read to the first request removes the ordering
13
+ * question entirely.
14
+ */
15
+ var resolve = () => {
16
+ if (instance === void 0) instance = createAjaxCartApi({
17
+ debug: globalThis.window?.BrytDesigns?.debug,
18
+ ...overrides
19
+ });
20
+ return instance;
21
+ };
22
+ /**
23
+ * Replaces the options the client is built with.
24
+ *
25
+ * Must be called before the first request; after that the client exists and
26
+ * this is ignored unless {@link reset} is called first. Intended for tests and
27
+ * for a theme that wants to supply its own transport - a storefront that just
28
+ * wants logging should set `window.BrytDesigns.debug`.
29
+ */
30
+ var configure = (options) => {
31
+ overrides = options;
32
+ instance = void 0;
33
+ };
34
+ /** Drops the built client so the next call rebuilds it. For tests. */
35
+ var reset = () => {
36
+ instance = void 0;
37
+ overrides = void 0;
38
+ };
39
+ /**
40
+ * The cart client, as a stable object whose methods resolve lazily.
41
+ *
42
+ * A getter-backed facade rather than the client itself: callers import this at
43
+ * module scope, so handing them the real object would force construction at
44
+ * import time, which is the thing being avoided.
45
+ *
46
+ * @internal
47
+ */
48
+ var API = {
49
+ add: ((input, options) => resolve().add(input, options)),
50
+ change: ((input, options) => resolve().change(input, options)),
51
+ clear: ((input, options) => resolve().clear(input, options)),
52
+ get: ((input, options) => resolve().get(input, options)),
53
+ update: ((input, options) => resolve().update(input, options))
54
+ };
55
+ //#endregion
56
+ export { configure, API as default, reset };
2
57
 
3
- const API = createAjaxCartApi({ debug: window?.BrytDesigns?.debug });
4
- var api_default = API;
5
-
6
- export { api_default as default };
7
- //# sourceMappingURL=api.js.map
8
58
  //# sourceMappingURL=api.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/api.ts"],"names":[],"mappings":";;AAKA,MAAM,MAAM,iBAAkB,CAAA,EAAE,OAAO,MAAQ,EAAA,WAAA,EAAa,OAAO,CAAA;AAEnE,IAAO,WAAQ,GAAA","file":"api.js","sourcesContent":["import { createAjaxCartApi } from \"@brytdesigns/shopify-ajax-cart-api\";\n\n/**\n * @internal\n */\nconst API = createAjaxCartApi({ debug: window?.BrytDesigns?.debug });\n\nexport default API;\n"]}
1
+ {"version":3,"file":"api.js","names":[],"sources":["../../src/api.ts"],"sourcesContent":["import { createAjaxCartApi } from \"@brytdesigns/shopify-ajax-cart-api\";\n\ntype Api = ReturnType<typeof createAjaxCartApi>;\ntype Options = Parameters<typeof createAjaxCartApi>[0];\n\nlet instance: Api | undefined;\nlet overrides: Options;\n\n/**\n * Builds the client on first use rather than on import.\n *\n * `debug` comes from `window.BrytDesigns.debug`, which a theme sets from an\n * inline script. Reading it at module scope made the result depend on whether\n * that script ran before or after this module evaluated - and as an ES module\n * in a Shopify theme, it usually ran after, so `debug: true` was silently\n * ignored. Deferring the read to the first request removes the ordering\n * question entirely.\n */\nconst resolve = (): Api => {\n\tif (instance === undefined) {\n\t\tinstance = createAjaxCartApi({\n\t\t\tdebug: globalThis.window?.BrytDesigns?.debug,\n\t\t\t...overrides,\n\t\t});\n\t}\n\treturn instance;\n};\n\n/**\n * Replaces the options the client is built with.\n *\n * Must be called before the first request; after that the client exists and\n * this is ignored unless {@link reset} is called first. Intended for tests and\n * for a theme that wants to supply its own transport - a storefront that just\n * wants logging should set `window.BrytDesigns.debug`.\n */\nexport const configure = (options: Options): void => {\n\toverrides = options;\n\tinstance = undefined;\n};\n\n/** Drops the built client so the next call rebuilds it. For tests. */\nexport const reset = (): void => {\n\tinstance = undefined;\n\toverrides = undefined;\n};\n\n/**\n * The cart client, as a stable object whose methods resolve lazily.\n *\n * A getter-backed facade rather than the client itself: callers import this at\n * module scope, so handing them the real object would force construction at\n * import time, which is the thing being avoided.\n *\n * @internal\n */\nconst API = {\n\tadd: ((input, options) => resolve().add(input, options)) as Api[\"add\"],\n\tchange: ((input, options) =>\n\t\tresolve().change(input, options)) as Api[\"change\"],\n\tclear: ((input, options) => resolve().clear(input, options)) as Api[\"clear\"],\n\tget: ((input, options) => resolve().get(input, options)) as Api[\"get\"],\n\tupdate: ((input, options) =>\n\t\tresolve().update(input, options)) as Api[\"update\"],\n};\n\nexport default API;\n"],"mappings":";;AAKA,IAAI;AACJ,IAAI;;;;;;;;;;;AAYJ,IAAM,gBAAqB;CAC1B,IAAI,aAAa,KAAA,GAChB,WAAW,kBAAkB;EAC5B,OAAO,WAAW,QAAQ,aAAa;EACvC,GAAG;CACJ,CAAC;CAEF,OAAO;AACR;;;;;;;;;AAUA,IAAa,aAAa,YAA2B;CACpD,YAAY;CACZ,WAAW,KAAA;AACZ;;AAGA,IAAa,cAAoB;CAChC,WAAW,KAAA;CACX,YAAY,KAAA;AACb;;;;;;;;;;AAWA,IAAM,MAAM;CACX,OAAO,OAAO,YAAY,QAAQ,CAAC,CAAC,IAAI,OAAO,OAAO;CACtD,UAAU,OAAO,YAChB,QAAQ,CAAC,CAAC,OAAO,OAAO,OAAO;CAChC,SAAS,OAAO,YAAY,QAAQ,CAAC,CAAC,MAAM,OAAO,OAAO;CAC1D,OAAO,OAAO,YAAY,QAAQ,CAAC,CAAC,IAAI,OAAO,OAAO;CACtD,UAAU,OAAO,YAChB,QAAQ,CAAC,CAAC,OAAO,OAAO,OAAO;AACjC"}
@@ -1,24 +1,90 @@
1
- import { QueryClient } from '@tanstack/solid-query';
2
- import { experimental_createQueryPersister } from '@tanstack/query-persist-client-core';
3
- import lz from 'lz-string';
1
+ import { QueryClient } from "@tanstack/solid-query";
2
+ import { experimental_createQueryPersister } from "@tanstack/query-persist-client-core";
3
+ import lz from "lz-string";
4
+ //#region src/client.ts
5
+ /**
6
+ * Fields removed before the cart is written to disk.
7
+ *
8
+ * `token` identifies the cart to Shopify's Ajax endpoints; `note` and
9
+ * `attributes` are free text the shopper typed. lz-string is compression, not
10
+ * encryption, so all three sat in `localStorage` in readable form for twelve
11
+ * hours — long enough that the next person on a shared or kiosk browser could
12
+ * read the previous shopper's cart, and long enough to outlive the shopper
13
+ * clearing their cart.
14
+ *
15
+ * Line-item `properties` are in the list for the same reason: gift messages
16
+ * and engraving text are the most personal thing a cart holds, and they are
17
+ * exactly what someone reading a shared browser's storage would find
18
+ * interesting. The trade is that a cart restored from the cache paints its
19
+ * line items without their properties for the one frame before `/cart.js`
20
+ * resolves — incomplete briefly, rather than readable for twelve hours.
21
+ *
22
+ * This is a *cache*. Everything dropped here is re-fetched on the next
23
+ * `/cart.js`, so nothing is lost; only the first paint from a restored entry
24
+ * is thinner.
25
+ */
26
+ var REDACTED_CART_FIELDS = [
27
+ "token",
28
+ "note",
29
+ "attributes",
30
+ "properties"
31
+ ];
32
+ /**
33
+ * Strips {@link REDACTED_CART_FIELDS} wherever they appear in the persisted
34
+ * payload.
35
+ *
36
+ * Walks the whole structure rather than reaching for a known path: the
37
+ * persister writes its own envelope around the query state, and a shape
38
+ * assumption here would fail silently — leaving the fields on disk — the next
39
+ * time TanStack changes it.
40
+ */
41
+ var redact = (value) => {
42
+ if (Array.isArray(value)) return value.map(redact);
43
+ if (value === null || typeof value !== "object") return value;
44
+ const out = {};
45
+ for (const [key, nested] of Object.entries(value)) {
46
+ if (REDACTED_CART_FIELDS.includes(key)) continue;
47
+ out[key] = redact(nested);
48
+ }
49
+ return out;
50
+ };
51
+ var makeClient = () => {
52
+ const persister = experimental_createQueryPersister({
53
+ serialize: (data) => lz.compressToUTF16(JSON.stringify(redact(data))),
54
+ deserialize: (data) => JSON.parse(lz.decompressFromUTF16(data)),
55
+ storage: window.localStorage,
56
+ maxAge: 432e5,
57
+ prefix: "@brytdesigns/shopify-ajax-cart"
58
+ });
59
+ return new QueryClient({ defaultOptions: { queries: {
60
+ gcTime: 3e5,
61
+ persister: persister.persisterFn
62
+ } } });
63
+ };
64
+ /**
65
+ * Memoised on `window` rather than on the module.
66
+ *
67
+ * Within one copy of this package a module-level constant would be enough.
68
+ * The hazard is two copies on one page - a theme and an app block resolving
69
+ * different versions, or a bundler emitting duplicate instances - where each
70
+ * would otherwise hold its own QueryClient and an `invalidate()` from one
71
+ * would leave the other's cache untouched. Anchoring to `window` means every
72
+ * copy converges on one client, and observers sharing the `cart` key share a
73
+ * single cache entry.
74
+ *
75
+ * **This one is deliberately not injectable, and should stay that way.** The
76
+ * other `window` reads in this package were lifted out - the route table and
77
+ * origin became `Context.Reference`s, and the API client is built on first use
78
+ * rather than at import. This is the exception: the whole point is to converge
79
+ * copies that cannot see each other, and a copy holding an injected client is
80
+ * exactly the divergence the global was introduced to prevent. Making it a
81
+ * parameter would reintroduce the bug it was written to fix.
82
+ */
83
+ if (window.BrytDesigns === void 0) window.BrytDesigns = {};
84
+ var globals = window.BrytDesigns;
85
+ if (globals.queryClient === void 0) globals.queryClient = makeClient();
86
+ var client = globals.queryClient;
87
+ //#endregion
88
+ export { client as default, redact };
4
89
 
5
- const persister = experimental_createQueryPersister({
6
- serialize: (data) => lz.compressToUTF16(JSON.stringify(data)),
7
- deserialize: (data) => JSON.parse(lz.decompressFromUTF16(data)),
8
- storage: window.localStorage,
9
- maxAge: 1e3 * 60 * 60 * 12,
10
- prefix: "@brytdesigns/shopify-ajax-cart"
11
- });
12
- const client = new QueryClient({
13
- defaultOptions: {
14
- queries: {
15
- gcTime: 1e3 * 60 * 5,
16
- persister: persister.persisterFn
17
- }
18
- }
19
- });
20
- var client_default = client;
21
-
22
- export { client_default as default };
23
- //# sourceMappingURL=client.js.map
24
90
  //# sourceMappingURL=client.js.map