@juo/blocks 1.20.0 → 2.0.0-alpha.10

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 (152) hide show
  1. package/dist/{ExtensionRoot-DfpvN94s.js → ExtensionRoot-CG9dH98z.js} +24 -6
  2. package/dist/block-BjJztStr.js +993 -0
  3. package/dist/{block-dVP4Rqgz.js → block-DnhzyZ1H.js} +29 -3
  4. package/dist/block.d.ts +56 -0
  5. package/dist/block.d.ts.map +1 -1
  6. package/dist/{bridge-4Eq-G73Z.js → bridge-Bss7Xq3D.js} +39 -31
  7. package/dist/core.js +1620 -333
  8. package/dist/css-runtime-CjZl0K48.js +755 -0
  9. package/dist/devtools/hook.d.ts +0 -5
  10. package/dist/devtools/hook.d.ts.map +1 -1
  11. package/dist/devtools/index.d.ts +0 -1
  12. package/dist/devtools/index.d.ts.map +1 -1
  13. package/dist/devtools/protocol.d.ts +15 -1
  14. package/dist/devtools/protocol.d.ts.map +1 -1
  15. package/dist/devtools.js +42 -9
  16. package/dist/editor/bridge.d.ts +7 -7
  17. package/dist/editor/bridge.d.ts.map +1 -1
  18. package/dist/editor/components.d.ts.map +1 -1
  19. package/dist/editor/main.d.ts +2 -1
  20. package/dist/editor/main.d.ts.map +1 -1
  21. package/dist/editor/messages.d.ts +13 -2
  22. package/dist/editor/messages.d.ts.map +1 -1
  23. package/dist/editor/overlays.d.ts +14 -0
  24. package/dist/editor/overlays.d.ts.map +1 -0
  25. package/dist/editor/overlays.test.d.ts +2 -0
  26. package/dist/editor/overlays.test.d.ts.map +1 -0
  27. package/dist/editor.js +47 -33
  28. package/dist/{gridstack-adapter-BZWybRw1.js → gridstack-adapter-C1Q8gbsH.js} +2 -2
  29. package/dist/main.d.ts +3 -1
  30. package/dist/main.d.ts.map +1 -1
  31. package/dist/{morph-DHn3ol8M.js → morph-LwttdRML.js} +1 -1
  32. package/dist/overlay-wrapper.d.ts +69 -0
  33. package/dist/overlay-wrapper.d.ts.map +1 -0
  34. package/dist/overlay-wrapper.test.d.ts +2 -0
  35. package/dist/overlay-wrapper.test.d.ts.map +1 -0
  36. package/dist/overlays/OverlayService.d.ts +34 -0
  37. package/dist/overlays/OverlayService.d.ts.map +1 -0
  38. package/dist/overlays/OverlayService.test.d.ts +2 -0
  39. package/dist/overlays/OverlayService.test.d.ts.map +1 -0
  40. package/dist/preact/block.d.ts.map +1 -1
  41. package/dist/preact/context.d.ts.map +1 -1
  42. package/dist/preact/context.test.d.ts +2 -0
  43. package/dist/preact/context.test.d.ts.map +1 -0
  44. package/dist/preact/signals.d.ts +19 -0
  45. package/dist/preact/signals.d.ts.map +1 -1
  46. package/dist/preact/useContextSubscription.test.d.ts +2 -0
  47. package/dist/preact/useContextSubscription.test.d.ts.map +1 -0
  48. package/dist/preact.js +33 -7
  49. package/dist/{project-gridstack-C2cSYRMx.js → project-gridstack-CRZ_7HoT.js} +1 -1
  50. package/dist/react/block.d.ts.map +1 -1
  51. package/dist/react/context.d.ts.map +1 -1
  52. package/dist/react/context.test.d.ts +2 -0
  53. package/dist/react/context.test.d.ts.map +1 -0
  54. package/dist/react/signals.d.ts +19 -0
  55. package/dist/react/signals.d.ts.map +1 -1
  56. package/dist/react/useContextSubscription.test.d.ts +2 -0
  57. package/dist/react/useContextSubscription.test.d.ts.map +1 -0
  58. package/dist/react.js +40 -8
  59. package/dist/services/customer/adapter.d.ts +14 -1
  60. package/dist/services/customer/adapter.d.ts.map +1 -1
  61. package/dist/services/customer/adapter.test.d.ts +2 -0
  62. package/dist/services/customer/adapter.test.d.ts.map +1 -0
  63. package/dist/services/customer/customerService.d.ts.map +1 -1
  64. package/dist/services/customer/customerService.test.d.ts +2 -0
  65. package/dist/services/customer/customerService.test.d.ts.map +1 -0
  66. package/dist/services/customer/index.d.ts +2 -2
  67. package/dist/services/customer/index.d.ts.map +1 -1
  68. package/dist/services/customer/types.d.ts +29 -0
  69. package/dist/services/customer/types.d.ts.map +1 -1
  70. package/dist/services/index.d.ts +1 -1
  71. package/dist/services/index.d.ts.map +1 -1
  72. package/dist/services/login/adapter.d.ts +0 -10
  73. package/dist/services/login/adapter.d.ts.map +1 -1
  74. package/dist/services/login/index.d.ts +3 -3
  75. package/dist/services/login/index.d.ts.map +1 -1
  76. package/dist/services/login/loginService.d.ts +13 -1
  77. package/dist/services/login/loginService.d.ts.map +1 -1
  78. package/dist/services/login/refreshLock.d.ts +28 -0
  79. package/dist/services/login/refreshLock.d.ts.map +1 -0
  80. package/dist/services/login/refreshLock.test.d.ts +2 -0
  81. package/dist/services/login/refreshLock.test.d.ts.map +1 -0
  82. package/dist/services/order/adapter.d.ts +17 -6
  83. package/dist/services/order/adapter.d.ts.map +1 -1
  84. package/dist/services/order/adapter.test.d.ts +2 -0
  85. package/dist/services/order/adapter.test.d.ts.map +1 -0
  86. package/dist/services/order/index.d.ts +3 -4
  87. package/dist/services/order/index.d.ts.map +1 -1
  88. package/dist/services/order/orderService.d.ts +2 -3
  89. package/dist/services/order/orderService.d.ts.map +1 -1
  90. package/dist/services/order/orderService.test.d.ts +2 -0
  91. package/dist/services/order/orderService.test.d.ts.map +1 -0
  92. package/dist/services/order/types.d.ts +103 -14
  93. package/dist/services/order/types.d.ts.map +1 -1
  94. package/dist/services/product/adapter.d.ts +42 -0
  95. package/dist/services/product/adapter.d.ts.map +1 -1
  96. package/dist/services/product/index.d.ts +1 -1
  97. package/dist/services/product/index.d.ts.map +1 -1
  98. package/dist/services/settings/types.d.ts +15 -0
  99. package/dist/services/settings/types.d.ts.map +1 -1
  100. package/dist/services/subscription/adapter.d.ts +48 -7
  101. package/dist/services/subscription/adapter.d.ts.map +1 -1
  102. package/dist/services/subscription/index.d.ts +3 -1
  103. package/dist/services/subscription/index.d.ts.map +1 -1
  104. package/dist/services/subscription/instantOrderErrors.d.ts +11 -0
  105. package/dist/services/subscription/instantOrderErrors.d.ts.map +1 -1
  106. package/dist/services/subscription/lineRemoval.d.ts +56 -0
  107. package/dist/services/subscription/lineRemoval.d.ts.map +1 -0
  108. package/dist/services/subscription/lineRemoval.test.d.ts +2 -0
  109. package/dist/services/subscription/lineRemoval.test.d.ts.map +1 -0
  110. package/dist/services/subscription/paymentInstrument.d.ts +119 -0
  111. package/dist/services/subscription/paymentInstrument.d.ts.map +1 -0
  112. package/dist/services/subscription/paymentInstrument.test.d.ts +2 -0
  113. package/dist/services/subscription/paymentInstrument.test.d.ts.map +1 -0
  114. package/dist/services/subscription/store.d.ts.map +1 -1
  115. package/dist/services/subscription/subscriptionService.d.ts.map +1 -1
  116. package/dist/services/subscription/types.d.ts +265 -34
  117. package/dist/services/subscription/types.d.ts.map +1 -1
  118. package/dist/shared/context.d.ts +10 -3
  119. package/dist/shared/context.d.ts.map +1 -1
  120. package/dist/shared/touchSignals.d.ts +17 -0
  121. package/dist/shared/touchSignals.d.ts.map +1 -0
  122. package/dist/shared/touchSignals.test.d.ts +2 -0
  123. package/dist/shared/touchSignals.test.d.ts.map +1 -0
  124. package/dist/theme-state.d.ts +2 -1
  125. package/dist/theme-state.d.ts.map +1 -1
  126. package/dist/theme-state.params.test.d.ts +2 -0
  127. package/dist/theme-state.params.test.d.ts.map +1 -0
  128. package/dist/theme-state.translations.test.d.ts +2 -0
  129. package/dist/theme-state.translations.test.d.ts.map +1 -0
  130. package/dist/vue/block.d.ts.map +1 -1
  131. package/dist/vue.js +16 -13
  132. package/dist/web-components/ExtensionRoot.d.ts +1 -0
  133. package/dist/web-components/ExtensionRoot.d.ts.map +1 -1
  134. package/dist/web-components-editor.js +6 -5
  135. package/dist/web-components-runtime.js +3 -2
  136. package/package.json +1 -1
  137. package/dist/css-runtime-DTiXcYSs.js +0 -1576
  138. package/dist/devtools/instrumentation.d.ts +0 -47
  139. package/dist/devtools/instrumentation.d.ts.map +0 -1
  140. package/dist/index-JSv6UH_o.js +0 -169
  141. package/dist/services/login/errors.d.ts +0 -21
  142. package/dist/services/login/errors.d.ts.map +0 -1
  143. package/dist/services/orders/adapter.d.ts +0 -10
  144. package/dist/services/orders/adapter.d.ts.map +0 -1
  145. package/dist/services/orders/index.d.ts +0 -4
  146. package/dist/services/orders/index.d.ts.map +0 -1
  147. package/dist/services/orders/ordersService.d.ts +0 -6
  148. package/dist/services/orders/ordersService.d.ts.map +0 -1
  149. package/dist/services/orders/ordersService.test.d.ts +0 -2
  150. package/dist/services/orders/ordersService.test.d.ts.map +0 -1
  151. package/dist/services/orders/types.d.ts +0 -60
  152. package/dist/services/orders/types.d.ts.map +0 -1
package/dist/core.js CHANGED
@@ -1,11 +1,13 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { f as createContext, g as d, h as w, j as registerBlock, E, u, k as getDefinedBlocks, l as createBlockInstance, m as defineBlock, s as subscribeContext, G as GRID_V1_ENGINE_ID, n as clampRect, p as applyFillExpansion, q as compactItems, t as findFreeRect, D as DEFAULT_GRID } from "./css-runtime-DTiXcYSs.js";
5
- import { B, v, x, y, z, L, P, S, c, T, A, d as d2, b, F, H, I, J, K, N, O, Q, R, U, V, W, X, Y, Z, i, _, a, $, a0, o, a1, a2, a3, e, a4, r, a5, a6, a7, w as w2 } from "./css-runtime-DTiXcYSs.js";
4
+ import { e as createContext, f as d, m as w, n as defineBlock, h as createBlockInstance, j as getDefinedBlocks, p as registerBlock, E, u, s as subscribeContext } from "./block-BjJztStr.js";
5
+ import { B, q, t, S, v, _, x, c, y, g, z, A, D, F, G, i, H, b, I, o, J, k, K, l, L, w as w2 } from "./block-BjJztStr.js";
6
+ import { G as GRID_V1_ENGINE_ID, d as clampRect, e as applyFillExpansion, f as compactItems, g as findFreeRect, D as DEFAULT_GRID } from "./css-runtime-CjZl0K48.js";
7
+ import { h, i as i2, L as L2, P, a, T, b as b2, j, k as k2, l as l2, m, n, o as o2, p, q as q2, s, t as t2, u as u2, v as v2, c as c2, w as w3, r } from "./css-runtime-CjZl0K48.js";
6
8
  import { reportBlockWarning, reportBlockError } from "./observability.js";
7
- import { a as createEditorBridge, D as createSelectBlockMessage } from "./bridge-4Eq-G73Z.js";
8
- import { p } from "./project-gridstack-C2cSYRMx.js";
9
+ import { a as createEditorBridge, E as createSelectBlockMessage } from "./bridge-Bss7Xq3D.js";
10
+ import { p as p2 } from "./project-gridstack-CRZ_7HoT.js";
9
11
  import { clearLayoutModeAdapter, getLayoutModeAdapter, registerLayoutModeAdapter } from "./layout-mode-adapter-BBd4JRQd.js";
10
12
  const SUPPORTED_UI_LANGUAGES = [
11
13
  { code: "cs", label: "Czech" },
@@ -96,6 +98,111 @@ function createState() {
96
98
  };
97
99
  }
98
100
  const StateContext = createContext("state");
101
+ const OVERLAY_WRAPPER_SCHEMA = {
102
+ type: "object",
103
+ properties: {
104
+ props: {
105
+ type: "object",
106
+ properties: {
107
+ layout: {
108
+ type: "string",
109
+ enum: ["modal", "sidebar"]
110
+ },
111
+ canAbort: {
112
+ type: "boolean"
113
+ }
114
+ },
115
+ required: ["layout"],
116
+ additionalProperties: false
117
+ },
118
+ slots: {
119
+ type: "object",
120
+ properties: {
121
+ content: {}
122
+ },
123
+ additionalProperties: false
124
+ }
125
+ },
126
+ required: ["props", "slots"],
127
+ additionalProperties: false
128
+ };
129
+ function defineOverlayWrapper(opts) {
130
+ const layout = opts.layout ?? "sidebar";
131
+ const canAbort = opts.canAbort ?? true;
132
+ return defineBlock(opts.name, {
133
+ displayName: opts.title,
134
+ group: "internal",
135
+ schema: OVERLAY_WRAPPER_SCHEMA,
136
+ initialValue: () => ({
137
+ props: { layout, canAbort },
138
+ slots: {
139
+ content: [createBlockInstance(opts.content)]
140
+ }
141
+ }),
142
+ renderer: () => null
143
+ });
144
+ }
145
+ const OVERLAY_PREFIX$1 = "overlay:";
146
+ function callInitialValue(block) {
147
+ if (typeof block.initialValue !== "function") return block.initialValue;
148
+ try {
149
+ return block.initialValue();
150
+ } catch (error) {
151
+ console.warn(
152
+ `[overlays] initialValue() threw for "${block.name}"; its content block will not be hidden from the palette.`,
153
+ error
154
+ );
155
+ return void 0;
156
+ }
157
+ }
158
+ function buildOverlayRegistry(blocks) {
159
+ var _a, _b;
160
+ const registry = {};
161
+ for (const block of blocks) {
162
+ if (!block.name.startsWith(OVERLAY_PREFIX$1)) continue;
163
+ const id = block.name.slice(OVERLAY_PREFIX$1.length);
164
+ const initial = callInitialValue(block);
165
+ const first = (_b = (_a = initial == null ? void 0 : initial.slots) == null ? void 0 : _a.content) == null ? void 0 : _b[0];
166
+ const contentBlock = typeof (first == null ? void 0 : first.type) === "string" ? first.type : "";
167
+ registry[id] = {
168
+ block: block.name,
169
+ title: block.displayName ?? id,
170
+ contentBlock
171
+ };
172
+ }
173
+ return registry;
174
+ }
175
+ const OVERLAY_PREFIX = "overlay:";
176
+ const OverlayServiceContext = createContext("services/overlay");
177
+ function createOverlayService(themeState, options = {}) {
178
+ const getBlocks = options.getBlocks ?? getDefinedBlocks;
179
+ const current = w(() => {
180
+ const root = themeState.overlay.blocks.value[0];
181
+ const type = root == null ? void 0 : root.type;
182
+ if (typeof type !== "string" || !type.startsWith(OVERLAY_PREFIX)) {
183
+ return null;
184
+ }
185
+ const props = root.props ?? {};
186
+ return {
187
+ name: type,
188
+ // Defaults mirror defineOverlayWrapper's seeding in overlay-wrapper.ts — keep in sync.
189
+ layout: props.layout ?? "sidebar",
190
+ canAbort: Boolean(props.canAbort ?? true)
191
+ };
192
+ });
193
+ return {
194
+ getEditableOverlays() {
195
+ return buildOverlayRegistry(getBlocks());
196
+ },
197
+ open(name, params) {
198
+ void themeState.resolve("overlay", name, params);
199
+ },
200
+ close() {
201
+ themeState.overlay.blocks.value = [];
202
+ },
203
+ current
204
+ };
205
+ }
99
206
  function isLocalhostOrigin(origin) {
100
207
  try {
101
208
  const url = new URL(origin);
@@ -187,32 +294,232 @@ function createCustomerService(options) {
187
294
  const result = await options.adapter.getCurrent();
188
295
  if (result._tag === "Success") current.value = result.data;
189
296
  return result;
297
+ },
298
+ createPaymentMethod(params) {
299
+ return options.adapter.createPaymentMethod(params);
300
+ },
301
+ async updateAttributes(attributes) {
302
+ var _a;
303
+ const merged = { ...(_a = current.value) == null ? void 0 : _a.attributes, ...attributes };
304
+ const result = await options.adapter.updateAttributes(merged);
305
+ if (result._tag === "Success") current.value = result.data;
306
+ return result;
190
307
  }
191
308
  };
192
309
  }
193
310
  const CustomerServiceContext = createContext("services/customer");
311
+ const PAYMENT_INSTRUMENT_TYPES = [
312
+ "credit_card",
313
+ "paypal",
314
+ "shop_pay",
315
+ "sepa_direct_debit",
316
+ "blik",
317
+ "mbway",
318
+ "bacs",
319
+ "manual"
320
+ ];
321
+ const INSTRUMENT_TYPE_TO_NAME = {
322
+ credit_card: null,
323
+ paypal: "PayPal",
324
+ blik: "BLIK",
325
+ sepa_direct_debit: "SEPA",
326
+ mbway: "MB WAY",
327
+ shop_pay: "Shop Pay",
328
+ bacs: "Bacs",
329
+ manual: "Shopify Checkout"
330
+ };
331
+ function getPaymentInstrumentName(instrument) {
332
+ const name = INSTRUMENT_TYPE_TO_NAME[instrument.type] ?? null;
333
+ if (name != null) return name;
334
+ return instrument.type === "credit_card" ? instrument.brand || instrument.type : instrument.type;
335
+ }
336
+ function getPaymentInstrumentDigits(instrument) {
337
+ switch (instrument.type) {
338
+ case "credit_card":
339
+ case "shop_pay":
340
+ case "bacs":
341
+ return instrument.maskedNumber.slice(-4) || null;
342
+ case "sepa_direct_debit":
343
+ return instrument.consumerAccount.slice(-4) || null;
344
+ default:
345
+ return null;
346
+ }
347
+ }
348
+ function getPaymentInstrumentDetail(instrument) {
349
+ switch (instrument.type) {
350
+ case "paypal":
351
+ return instrument.paypalAccountEmail ?? null;
352
+ case "sepa_direct_debit":
353
+ return instrument.consumerName ?? null;
354
+ case "blik":
355
+ return instrument.label ?? null;
356
+ case "mbway":
357
+ return instrument.phone ?? null;
358
+ default:
359
+ return null;
360
+ }
361
+ }
362
+ function getPaymentInstrumentExpiry(instrument, now = /* @__PURE__ */ new Date()) {
363
+ if (instrument.type !== "credit_card" && instrument.type !== "shop_pay") {
364
+ return null;
365
+ }
366
+ const { expiryMonth: month, expiryYear: year } = instrument;
367
+ if (month == null || year == null) return null;
368
+ const nowYear = now.getFullYear();
369
+ const nowMonth = now.getMonth() + 1;
370
+ const expiresThisMonth = year === nowYear && month === nowMonth;
371
+ const isExpired = year < nowYear || year === nowYear && month < nowMonth;
372
+ return { month, year, isExpired, expiresThisMonth };
373
+ }
374
+ function serializeV1PaymentInstrument(raw) {
375
+ if (raw == null || typeof raw !== "object") return null;
376
+ const r2 = raw;
377
+ if (typeof r2.type !== "string") return null;
378
+ switch (r2.type) {
379
+ case "credit-card":
380
+ return {
381
+ type: "credit_card",
382
+ brand: r2.brand ?? "",
383
+ maskedNumber: r2.maskedNumber ?? "",
384
+ ...r2.expiryMonth != null ? { expiryMonth: r2.expiryMonth } : {},
385
+ ...r2.expiryYear != null ? { expiryYear: r2.expiryYear } : {},
386
+ ...r2.cardholderName != null ? { cardholderName: r2.cardholderName } : {}
387
+ };
388
+ case "paypal":
389
+ return { type: "paypal", paypalAccountEmail: r2.paypalAccountEmail ?? null };
390
+ case "shop-pay":
391
+ return {
392
+ type: "shop_pay",
393
+ maskedNumber: r2.maskedNumber ?? "",
394
+ ...r2.expiryMonth != null ? { expiryMonth: r2.expiryMonth } : {},
395
+ ...r2.expiryYear != null ? { expiryYear: r2.expiryYear } : {},
396
+ ...r2.cardholderName != null ? { cardholderName: r2.cardholderName } : {}
397
+ };
398
+ case "sepa-direct-debit":
399
+ return {
400
+ type: "sepa_direct_debit",
401
+ consumerName: r2.consumerName ?? "",
402
+ consumerBic: r2.consumerBic ?? null,
403
+ consumerAccount: r2.maskedConsumerAccount ?? ""
404
+ };
405
+ case "blik":
406
+ return { type: "blik" };
407
+ case "mbway":
408
+ return { type: "mbway", ...r2.phone != null ? { phone: r2.phone } : {} };
409
+ case "bacs":
410
+ return { type: "bacs", maskedNumber: r2.maskedNumber ?? "" };
411
+ case "manual":
412
+ return { type: "manual" };
413
+ default:
414
+ return null;
415
+ }
416
+ }
194
417
  function createMockCustomerAdapter() {
195
- const customer = { id: "customer-1", name: "Customer 1" };
418
+ let customer = { id: "customer-1", name: "Customer 1", attributes: {} };
196
419
  return {
197
420
  async getCurrent() {
198
421
  return { _tag: "Success", data: customer };
422
+ },
423
+ async updateAttributes(attributes) {
424
+ await new Promise((resolve) => setTimeout(resolve, 300));
425
+ customer = { ...customer, attributes: { ...attributes } };
426
+ return { _tag: "Success", data: customer };
427
+ },
428
+ async createPaymentMethod(params) {
429
+ await new Promise((resolve) => setTimeout(resolve, 300));
430
+ if (params.provider === "shopify") {
431
+ return {
432
+ _tag: "Success",
433
+ data: {
434
+ kind: "email_sent",
435
+ paymentMethodId: "pm_mock_1",
436
+ instrument: { type: "credit_card", brand: "visa", maskedNumber: "•••• 4242" }
437
+ }
438
+ };
439
+ }
440
+ if (params.provider === "mollie") {
441
+ return {
442
+ _tag: "Success",
443
+ data: { kind: "redirect", redirectUrl: params.returnUrl }
444
+ };
445
+ }
446
+ return { _tag: "Failure", error: new Error(`Payment provider "${params.provider}" is not supported`) };
199
447
  }
200
448
  };
201
449
  }
450
+ function fromV1Customer(body) {
451
+ return {
452
+ id: body.id,
453
+ name: body.displayName,
454
+ email: body.email ?? void 0,
455
+ attributes: Object.fromEntries(
456
+ body.customAttributes.map(({ key, value }) => [key, value])
457
+ )
458
+ };
459
+ }
202
460
  function createApiCustomerAdapter(fetcher) {
203
461
  return {
204
462
  async getCurrent() {
205
463
  try {
206
- const res = await fetcher("/customer/info");
464
+ const res = await fetcher("/customer/v1/customer");
465
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
466
+ return {
467
+ _tag: "Success",
468
+ data: fromV1Customer(await res.json())
469
+ };
470
+ } catch (e) {
471
+ return { _tag: "Failure", error: e };
472
+ }
473
+ },
474
+ async updateAttributes(attributes) {
475
+ try {
476
+ const res = await fetcher("/customer/v1/customer", {
477
+ method: "PATCH",
478
+ headers: { "Content-Type": "application/json" },
479
+ body: JSON.stringify({ customAttributes: attributes })
480
+ });
207
481
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
208
- const data = await res.json();
209
- const name = [data.firstName, data.lastName].filter(Boolean).join(" ") || data.email || "";
210
482
  return {
211
483
  _tag: "Success",
212
- data: { id: data.id, name, email: data.email }
484
+ data: fromV1Customer(await res.json())
213
485
  };
214
- } catch (e2) {
215
- return { _tag: "Failure", error: e2 };
486
+ } catch (e) {
487
+ return { _tag: "Failure", error: e };
488
+ }
489
+ },
490
+ async createPaymentMethod(params) {
491
+ try {
492
+ if (params.provider === "shopify") {
493
+ const res = await fetcher("/customer/v1/payment-methods", {
494
+ method: "POST"
495
+ });
496
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
497
+ const body = await res.json();
498
+ return {
499
+ _tag: "Success",
500
+ data: {
501
+ kind: "email_sent",
502
+ paymentMethodId: body.id,
503
+ instrument: serializeV1PaymentInstrument(body.instrument) ?? void 0
504
+ }
505
+ };
506
+ }
507
+ if (params.provider === "mollie") {
508
+ const res = await fetcher("/customer/payment-methods", {
509
+ method: "POST",
510
+ headers: { "Content-Type": "application/json" },
511
+ body: JSON.stringify({ redirectUrl: params.returnUrl })
512
+ });
513
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
514
+ const body = await res.json();
515
+ return {
516
+ _tag: "Success",
517
+ data: { kind: "redirect", redirectUrl: body.redirectUrl }
518
+ };
519
+ }
520
+ return { _tag: "Failure", error: new Error(`Payment provider "${params.provider}" is not supported`) };
521
+ } catch (e) {
522
+ return { _tag: "Failure", error: e };
216
523
  }
217
524
  }
218
525
  };
@@ -230,47 +537,35 @@ const PARAMS = {
230
537
  function uuid() {
231
538
  return ("10000000-1000-4000-8000" + -1e11).replace(
232
539
  /[018]/g,
233
- (c2) => (c2 ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c2 / 4).toString(16)
540
+ (c3) => (c3 ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c3 / 4).toString(16)
234
541
  );
235
542
  }
236
- var AuthenticationErrorReason = /* @__PURE__ */ ((AuthenticationErrorReason2) => {
237
- AuthenticationErrorReason2["Expired"] = "expired";
238
- AuthenticationErrorReason2["IncorrectCode"] = "wrong-code";
239
- AuthenticationErrorReason2["TooManyTries"] = "too-many-tries";
240
- AuthenticationErrorReason2["NoEmail"] = "no-email";
241
- AuthenticationErrorReason2["Unknown"] = "unknown";
242
- AuthenticationErrorReason2["Missing"] = "missing";
243
- return AuthenticationErrorReason2;
244
- })(AuthenticationErrorReason || {});
245
- class AuthenticationError extends Error {
246
- constructor(reason, data) {
247
- super("Authentication error");
248
- __publicField(this, "reason");
249
- __publicField(this, "data");
250
- this.reason = reason;
251
- this.data = data ?? {};
252
- }
543
+ const REFRESH_LOCK_NAME = "juo:auth:refresh";
544
+ const LOCK_WAIT_TIMEOUT_MS = 1e4;
545
+ let fallbackQueue = Promise.resolve();
546
+ function runQueued(run) {
547
+ const result = fallbackQueue.then(run, run);
548
+ fallbackQueue = result.catch(() => void 0);
549
+ return result;
253
550
  }
254
- const OTP_ERROR_REASONS = {
255
- INCORRECT_CODE: AuthenticationErrorReason.IncorrectCode,
256
- TOO_MANY_TRIES: AuthenticationErrorReason.TooManyTries,
257
- EXPIRED: AuthenticationErrorReason.Expired
258
- };
259
- function authenticationErrorFromBody(data) {
260
- if (data == null || typeof data !== "object") {
261
- return void 0;
262
- }
263
- const { code, connection } = data;
264
- if (typeof code !== "string") {
265
- return void 0;
551
+ function withRefreshLock(run) {
552
+ const locks = typeof navigator === "undefined" ? void 0 : navigator.locks;
553
+ if (locks == null) {
554
+ return runQueued(run);
266
555
  }
267
- if (code === "AUTH_ERROR") {
268
- return new AuthenticationError(AuthenticationErrorReason.NoEmail, {
269
- connection
270
- });
271
- }
272
- const reason = OTP_ERROR_REASONS[code];
273
- return reason == null ? void 0 : new AuthenticationError(reason);
556
+ const controller = new AbortController();
557
+ const timer = setTimeout(() => controller.abort(), LOCK_WAIT_TIMEOUT_MS);
558
+ let granted = false;
559
+ return locks.request(REFRESH_LOCK_NAME, { signal: controller.signal }, () => {
560
+ granted = true;
561
+ clearTimeout(timer);
562
+ return run();
563
+ }).catch((error) => {
564
+ if (!granted && controller.signal.aborted) {
565
+ return run();
566
+ }
567
+ throw error;
568
+ }).finally(() => clearTimeout(timer));
274
569
  }
275
570
  function createMockLoginAdapter(opts = {}) {
276
571
  const appUrl = opts.appUrl ?? "https://admin.juo.io";
@@ -311,9 +606,19 @@ function createApiLoginAdapter(fetcher, opts) {
311
606
  body: JSON.stringify(body)
312
607
  });
313
608
  if (res.status === 403) {
314
- const error = authenticationErrorFromBody(await res.json());
315
- if (error != null) {
316
- throw error;
609
+ const data = await res.json();
610
+ if ("error_description" in data) {
611
+ if (data.error_description === "Wrong email or verification code.") {
612
+ throw new AuthenticationError(AuthenticationErrorReason.IncorrectCode);
613
+ } else if (data.error_description === "You've reached the maximum number of attempts. Please try to login again.") {
614
+ throw new AuthenticationError(AuthenticationErrorReason.TooManyTries);
615
+ } else if (data.error_description === "The verification code has expired. Please try to login again.") {
616
+ throw new AuthenticationError(AuthenticationErrorReason.Expired);
617
+ }
618
+ } else if ("code" in data && data.code === "AUTH_ERROR") {
619
+ throw new AuthenticationError(AuthenticationErrorReason.NoEmail, {
620
+ connection: data.connection
621
+ });
317
622
  }
318
623
  }
319
624
  if (!res.ok) {
@@ -330,8 +635,8 @@ function createApiLoginAdapter(fetcher, opts) {
330
635
  lang
331
636
  );
332
637
  return { _tag: "Success", data: void 0 };
333
- } catch (e2) {
334
- return { _tag: "Failure", error: e2 };
638
+ } catch (e) {
639
+ return { _tag: "Failure", error: e };
335
640
  }
336
641
  },
337
642
  async authenticate(params) {
@@ -346,9 +651,19 @@ function createApiLoginAdapter(fetcher, opts) {
346
651
  body: JSON.stringify(params)
347
652
  });
348
653
  if (res.status === 403) {
349
- const error = authenticationErrorFromBody(await res.json());
350
- if (error != null) {
351
- throw error;
654
+ const data = await res.json();
655
+ if ("error_description" in data) {
656
+ if (data.error_description === "Wrong email or verification code.") {
657
+ throw new AuthenticationError(AuthenticationErrorReason.IncorrectCode);
658
+ } else if (data.error_description === "You've reached the maximum number of attempts. Please try to login again.") {
659
+ throw new AuthenticationError(AuthenticationErrorReason.TooManyTries);
660
+ } else if (data.error_description === "The verification code has expired. Please try to login again.") {
661
+ throw new AuthenticationError(AuthenticationErrorReason.Expired);
662
+ }
663
+ } else if ("code" in data && data.code === "AUTH_ERROR") {
664
+ throw new AuthenticationError(AuthenticationErrorReason.NoEmail, {
665
+ connection: data.connection
666
+ });
352
667
  }
353
668
  }
354
669
  if (res.status === 401) {
@@ -361,8 +676,8 @@ function createApiLoginAdapter(fetcher, opts) {
361
676
  throw new Error(`Unexpected response: ${res.statusText}`);
362
677
  }
363
678
  return { _tag: "Success", data: await res.json() };
364
- } catch (e2) {
365
- return { _tag: "Failure", error: e2 };
679
+ } catch (e) {
680
+ return { _tag: "Failure", error: e };
366
681
  }
367
682
  },
368
683
  getAuthorizeUrl({ connection, state, shop }) {
@@ -375,23 +690,82 @@ function createApiLoginAdapter(fetcher, opts) {
375
690
  };
376
691
  }
377
692
  const __vite_import_meta_env__ = {};
693
+ var AuthenticationErrorReason = /* @__PURE__ */ ((AuthenticationErrorReason2) => {
694
+ AuthenticationErrorReason2["Expired"] = "expired";
695
+ AuthenticationErrorReason2["IncorrectCode"] = "wrong-code";
696
+ AuthenticationErrorReason2["TooManyTries"] = "too-many-tries";
697
+ AuthenticationErrorReason2["NoEmail"] = "no-email";
698
+ AuthenticationErrorReason2["Unknown"] = "unknown";
699
+ AuthenticationErrorReason2["Missing"] = "missing";
700
+ return AuthenticationErrorReason2;
701
+ })(AuthenticationErrorReason || {});
702
+ class AuthenticationError extends Error {
703
+ constructor(reason, data) {
704
+ super("Authentication error");
705
+ __publicField(this, "reason");
706
+ __publicField(this, "data");
707
+ this.reason = reason;
708
+ this.data = data ?? {};
709
+ }
710
+ }
378
711
  const STORAGE_DELEGATED_TOKEN = "delegated-token";
379
712
  const STORAGE_REFRESH_TOKEN_KEY = "refresh-token";
380
713
  const STORAGE_STATE_KEY = "state";
381
- function storage(key, value) {
382
- const storageKey = `auth:${key}`;
714
+ function webStorage(kind) {
383
715
  try {
384
- if (value === null) {
385
- sessionStorage.removeItem(storageKey);
386
- } else if (value !== void 0) {
387
- sessionStorage.setItem(storageKey, value);
388
- } else {
389
- return sessionStorage.getItem("auth:" + key);
716
+ return (kind === "local" ? localStorage : sessionStorage) ?? null;
717
+ } catch (error) {
718
+ console.warn(`Failed to reach ${kind} storage: ${error}`);
719
+ return null;
720
+ }
721
+ }
722
+ function readFrom(store, key) {
723
+ try {
724
+ return (store == null ? void 0 : store.getItem(key)) ?? null;
725
+ } catch (error) {
726
+ console.warn(`Failed to read web storage: ${error}`);
727
+ return null;
728
+ }
729
+ }
730
+ function writeTo(store, key, value) {
731
+ try {
732
+ if (store != null && store.getItem(key) !== value) {
733
+ store.setItem(key, value);
390
734
  }
391
735
  } catch (error) {
392
- console.warn(`Failed to use session storage: ${error}`);
736
+ console.warn(`Failed to write web storage: ${error}`);
737
+ }
738
+ }
739
+ function removeFrom(store, key) {
740
+ try {
741
+ store == null ? void 0 : store.removeItem(key);
742
+ } catch (error) {
743
+ console.warn(`Failed to clear web storage: ${error}`);
393
744
  }
394
- return null;
745
+ }
746
+ function storage(key, value) {
747
+ const storageKey = `auth:${key}`;
748
+ const isRefreshToken = key === STORAGE_REFRESH_TOKEN_KEY;
749
+ const store = webStorage(isRefreshToken ? "local" : "session");
750
+ const legacyStore = isRefreshToken ? webStorage("session") : null;
751
+ if (value === null) {
752
+ removeFrom(store, storageKey);
753
+ removeFrom(legacyStore, storageKey);
754
+ return null;
755
+ }
756
+ if (value !== void 0) {
757
+ writeTo(store, storageKey, value);
758
+ return null;
759
+ }
760
+ const stored = readFrom(store, storageKey);
761
+ if (stored !== null || legacyStore == null) {
762
+ return stored;
763
+ }
764
+ const legacy = readFrom(legacyStore, storageKey);
765
+ if (legacy !== null) {
766
+ writeTo(store, storageKey, legacy);
767
+ }
768
+ return legacy;
395
769
  }
396
770
  function nonce(len = 10) {
397
771
  return uuid().replace(/-/g, "").slice(0, len);
@@ -431,6 +805,22 @@ function createLoginService(init) {
431
805
  E(() => {
432
806
  storage(STORAGE_STATE_KEY, state.value);
433
807
  });
808
+ if (typeof window !== "undefined") {
809
+ window.addEventListener("storage", (event) => {
810
+ if (event.storageArea !== webStorage("local") || event.key !== `auth:${STORAGE_REFRESH_TOKEN_KEY}`) {
811
+ return;
812
+ }
813
+ if (event.newValue == null) {
814
+ accessToken.value = null;
815
+ expires.value = null;
816
+ refreshToken.value = null;
817
+ return;
818
+ }
819
+ if (event.newValue !== refreshToken.value) {
820
+ refreshToken.value = event.newValue;
821
+ }
822
+ });
823
+ }
434
824
  function storeTokens(data) {
435
825
  const { access_token, refresh_token, expires_in } = data;
436
826
  accessToken.value = access_token;
@@ -441,19 +831,49 @@ function createLoginService(init) {
441
831
  const margin = Math.min(60, lifetime / 2);
442
832
  expires.value = new Date(Date.now() + (lifetime - margin) * 1e3);
443
833
  }
834
+ async function rotate(token) {
835
+ const result = await adapter.authenticate({ refreshToken: token });
836
+ if (result._tag === "Failure") {
837
+ throw result.error;
838
+ }
839
+ if (refreshToken.value === token) {
840
+ storeTokens(result.data);
841
+ } else {
842
+ accessToken.value = null;
843
+ expires.value = null;
844
+ }
845
+ return result.data.access_token;
846
+ }
847
+ async function refreshLocked() {
848
+ const stored = storage(STORAGE_REFRESH_TOKEN_KEY);
849
+ if (stored != null && stored !== refreshToken.value) {
850
+ refreshToken.value = stored;
851
+ }
852
+ const current = refreshToken.value;
853
+ if (current == null) {
854
+ throw new AuthenticationError(
855
+ "expired"
856
+ /* Expired */
857
+ );
858
+ }
859
+ try {
860
+ return await rotate(current);
861
+ } catch (error) {
862
+ const latest = storage(STORAGE_REFRESH_TOKEN_KEY);
863
+ if (latest != null && latest !== current) {
864
+ refreshToken.value = latest;
865
+ return await rotate(latest);
866
+ }
867
+ throw error;
868
+ }
869
+ }
444
870
  async function getToken() {
445
871
  if (refreshToken.value == null) return null;
446
872
  if (accessToken.value == null || typeof accessToken.value === "string" && (expires.value == null || expires.value < /* @__PURE__ */ new Date())) {
447
- accessToken.value = new Promise(
448
- (resolve, reject) => adapter.authenticate({ refreshToken: refreshToken.value }).then((result) => {
449
- if (result._tag === "Failure") {
450
- reject(result.error);
451
- return;
452
- }
453
- storeTokens(result.data);
454
- resolve(result.data.access_token);
455
- }).catch(reject)
456
- );
873
+ accessToken.value = withRefreshLock(refreshLocked).catch((error) => {
874
+ accessToken.value = null;
875
+ throw error;
876
+ });
457
877
  }
458
878
  return Promise.resolve(accessToken.value);
459
879
  }
@@ -580,7 +1000,10 @@ function createLoginService(init) {
580
1000
  return {
581
1001
  _tag: "Failure",
582
1002
  error: formatError(
583
- new AuthenticationError(AuthenticationErrorReason.Missing)
1003
+ new AuthenticationError(
1004
+ "missing"
1005
+ /* Missing */
1006
+ )
584
1007
  )
585
1008
  };
586
1009
  }
@@ -604,7 +1027,7 @@ function createLoginService(init) {
604
1027
  return service;
605
1028
  }
606
1029
  const LoginServiceContext = createContext("services/login");
607
- function createMockOrdersAdapter() {
1030
+ function createMockOrderAdapter() {
608
1031
  const mockOrders = [
609
1032
  {
610
1033
  id: "10001",
@@ -613,7 +1036,10 @@ function createMockOrdersAdapter() {
613
1036
  currencyCode: "USD",
614
1037
  totalPrice: 89.97,
615
1038
  financialStatus: "PAID",
1039
+ paymentStatus: "paid",
1040
+ paidAt: "2024-10-15T09:31:00Z",
616
1041
  fulfillmentStatus: "FULFILLED",
1042
+ subscriptionIds: ["subscription_1"],
617
1043
  lines: [
618
1044
  {
619
1045
  id: "line_1",
@@ -638,7 +1064,10 @@ function createMockOrdersAdapter() {
638
1064
  currencyCode: "USD",
639
1065
  totalPrice: 45.99,
640
1066
  financialStatus: "PAID",
1067
+ paymentStatus: "paid",
1068
+ paidAt: "2024-09-20T14:16:00Z",
641
1069
  fulfillmentStatus: "PARTIALLY_FULFILLED",
1070
+ subscriptionIds: [],
642
1071
  lines: [
643
1072
  {
644
1073
  id: "line_2",
@@ -683,21 +1112,39 @@ function mapOrder(order) {
683
1112
  currencyCode: order.currencyCode,
684
1113
  totalPrice: order.totalPrice,
685
1114
  financialStatus: order.financialStatus,
1115
+ // Defaulted rather than required so an older backend (which returns neither
1116
+ // field) degrades to "settled, time unknown" instead of producing an Order
1117
+ // with holes in it. Matches the endpoint's own fallback for an order it
1118
+ // never tracked.
1119
+ paymentStatus: order.paymentStatus ?? "paid",
1120
+ paidAt: order.paidAt ?? null,
686
1121
  fulfillmentStatus: order.fulfillmentStatus,
687
1122
  lines: order.items.map(mapOrderLine),
688
- customAttributes: order.customAttributes
1123
+ customAttributes: order.customAttributes,
1124
+ subscriptionIds: order.subscriptionIds ?? []
689
1125
  };
690
1126
  }
691
- function createApiOrdersAdapter(fetcher) {
1127
+ function quoteSearchValue(value) {
1128
+ return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
1129
+ }
1130
+ function buildOrdersQuery(params) {
1131
+ const callerQuery = (params == null ? void 0 : params.query) != null && params.query.trim() !== "" ? params.query : null;
1132
+ const subscriptionTerm = (params == null ? void 0 : params.subscriptionId) != null ? `subscriptionId:${quoteSearchValue(params.subscriptionId)}` : null;
1133
+ if (callerQuery == null) return subscriptionTerm;
1134
+ if (subscriptionTerm == null) return callerQuery;
1135
+ return `(${callerQuery}) AND ${subscriptionTerm}`;
1136
+ }
1137
+ function createApiOrderAdapter(fetcher) {
692
1138
  return {
693
1139
  async getOrders(params) {
694
1140
  const query = new URLSearchParams();
695
1141
  if ((params == null ? void 0 : params.limit) != null) query.set("limit", String(params.limit));
696
1142
  if ((params == null ? void 0 : params.after) != null) query.set("after", params.after);
697
1143
  if ((params == null ? void 0 : params.before) != null) query.set("before", params.before);
698
- if ((params == null ? void 0 : params.query) != null) query.set("query", params.query);
699
1144
  if ((params == null ? void 0 : params.includeOneTime) != null) query.set("includeOneTime", String(params.includeOneTime));
700
1145
  if ((params == null ? void 0 : params.sort) != null) query.set("sort", params.sort);
1146
+ const searchQuery = buildOrdersQuery(params);
1147
+ if (searchQuery != null) query.set("query", searchQuery);
701
1148
  const qs = query.toString();
702
1149
  const res = await fetcher(`/customer/v1/orders${qs ? `?${qs}` : ""}`);
703
1150
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
@@ -714,7 +1161,7 @@ function createApiOrdersAdapter(fetcher) {
714
1161
  }
715
1162
  };
716
1163
  }
717
- function createOrdersService(adapter) {
1164
+ function createOrderService(adapter) {
718
1165
  return {
719
1166
  async getOrders(params) {
720
1167
  try {
@@ -726,7 +1173,7 @@ function createOrdersService(adapter) {
726
1173
  }
727
1174
  };
728
1175
  }
729
- const OrdersServiceContext = createContext("services/orders");
1176
+ const OrderServiceContext = createContext("services/order");
730
1177
  function createMockProductAdapter() {
731
1178
  const products = [
732
1179
  {
@@ -917,9 +1364,9 @@ function createMockProductAdapter() {
917
1364
  await new Promise((resolve) => setTimeout(resolve, 100));
918
1365
  return products.filter((product) => ids.includes(product.id)).map(toAvailableProduct);
919
1366
  },
920
- async getAvailableProducts({ q }) {
1367
+ async getAvailableProducts({ q: q3 }) {
921
1368
  await new Promise((resolve) => setTimeout(resolve, 100));
922
- const queryLower = q == null ? void 0 : q.toLowerCase();
1369
+ const queryLower = q3 == null ? void 0 : q3.toLowerCase();
923
1370
  return products.filter(
924
1371
  (product) => !queryLower || product.title.toLowerCase().includes(queryLower) || product.variants.some(
925
1372
  (variant) => variant.title.toLowerCase().includes(queryLower)
@@ -986,6 +1433,13 @@ function mapVariant(variant, currencyCode) {
986
1433
  } : {}
987
1434
  };
988
1435
  }
1436
+ const IDENTIFIER = String.raw`[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*`;
1437
+ const VALUE = String.raw`(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|${IDENTIFIER})`;
1438
+ const TERM = String.raw`(?:NOT\s+|-)?${IDENTIFIER}:(?:>=|<=|>|<)?${VALUE}`;
1439
+ const FILTER_QUERY = new RegExp(String.raw`^${TERM}(?:\s+(?:AND|OR)\s+${TERM})*$`);
1440
+ function isFilterQuery(query) {
1441
+ return FILTER_QUERY.test(query);
1442
+ }
989
1443
  function mapProduct(product, currencyCode) {
990
1444
  return {
991
1445
  id: product.id,
@@ -993,7 +1447,7 @@ function mapProduct(product, currencyCode) {
993
1447
  featuredImage: product.image == null ? null : { url: product.image.url, altText: product.image.altText ?? void 0 },
994
1448
  hasOnlyDefaultVariant: product.variants.length <= 1,
995
1449
  variants: {
996
- items: product.variants.map((v2) => mapVariant(v2, currencyCode)),
1450
+ items: product.variants.map((v3) => mapVariant(v3, currencyCode)),
997
1451
  pageInfo: {
998
1452
  hasNextPage: false,
999
1453
  hasPrevPage: false,
@@ -1038,7 +1492,11 @@ function createApiProductAdapter(fetcher, opts = { currencyCode: "USD" }) {
1038
1492
  try {
1039
1493
  const params = new URLSearchParams();
1040
1494
  if (opts2 == null ? void 0 : opts2.query) {
1041
- params.set("query", `"${opts2.query.trim().replace(/"/g, '\\"')}"`);
1495
+ const trimmed = opts2.query.trim();
1496
+ params.set(
1497
+ "query",
1498
+ isFilterQuery(trimmed) ? trimmed : `"${trimmed.replace(/"/g, '\\"')}"`
1499
+ );
1042
1500
  }
1043
1501
  if (opts2 == null ? void 0 : opts2.pagination) {
1044
1502
  if ("after" in opts2.pagination)
@@ -1048,7 +1506,7 @@ function createApiProductAdapter(fetcher, opts = { currencyCode: "USD" }) {
1048
1506
  }
1049
1507
  const body = await fetchProducts(params);
1050
1508
  return {
1051
- items: body.data.map((p2) => mapProduct(p2, currencyCode)),
1509
+ items: body.data.map((p3) => mapProduct(p3, currencyCode)),
1052
1510
  pageInfo: {
1053
1511
  hasNextPage: body.hasNextPage,
1054
1512
  hasPrevPage: body.hasPrevPage,
@@ -1074,10 +1532,10 @@ function createApiProductAdapter(fetcher, opts = { currencyCode: "USD" }) {
1074
1532
  const res = await fetcher(`/customer/products/by-ids?${params.toString()}`);
1075
1533
  if (!res.ok) return [];
1076
1534
  const data = await res.json();
1077
- return (data ?? []).map((p2) => ({
1078
- id: p2.id,
1079
- title: p2.title ?? "",
1080
- featuredImage: p2.featuredImage ? { url: p2.featuredImage.url, altText: p2.featuredImage.altText } : null,
1535
+ return (data ?? []).map((p3) => ({
1536
+ id: p3.id,
1537
+ title: p3.title ?? "",
1538
+ featuredImage: p3.featuredImage ? { url: p3.featuredImage.url, altText: p3.featuredImage.altText } : null,
1081
1539
  hasOnlyDefaultVariant: true,
1082
1540
  collections: []
1083
1541
  }));
@@ -1089,30 +1547,30 @@ function createApiProductAdapter(fetcher, opts = { currencyCode: "USD" }) {
1089
1547
  const res = await fetcher(`/customer/products/variants?${params.toString()}`);
1090
1548
  if (!res.ok) return [];
1091
1549
  const data = await res.json();
1092
- return (data ?? []).map((p2) => {
1550
+ return (data ?? []).map((p3) => {
1093
1551
  var _a;
1094
1552
  return {
1095
- id: p2.id,
1096
- title: p2.title,
1097
- description: p2.description ?? "",
1098
- featuredImage: p2.featuredImage,
1099
- hasOnlyDefaultVariant: p2.hasOnlyDefaultVariant ?? (((_a = p2.variants) == null ? void 0 : _a.length) ?? 0) <= 1,
1100
- variants: (p2.variants ?? []).map((v2) => ({
1101
- id: v2.id,
1102
- availableForSale: v2.availableForSale,
1103
- title: v2.title,
1104
- currentPrice: v2.currentPrice,
1105
- basePrice: v2.basePrice,
1106
- image: v2.image,
1107
- recurring: v2.recurring
1553
+ id: p3.id,
1554
+ title: p3.title,
1555
+ description: p3.description ?? "",
1556
+ featuredImage: p3.featuredImage,
1557
+ hasOnlyDefaultVariant: p3.hasOnlyDefaultVariant ?? (((_a = p3.variants) == null ? void 0 : _a.length) ?? 0) <= 1,
1558
+ variants: (p3.variants ?? []).map((v3) => ({
1559
+ id: v3.id,
1560
+ availableForSale: v3.availableForSale,
1561
+ title: v3.title,
1562
+ currentPrice: v3.currentPrice,
1563
+ basePrice: v3.basePrice,
1564
+ image: v3.image,
1565
+ recurring: v3.recurring
1108
1566
  }))
1109
1567
  };
1110
1568
  });
1111
1569
  },
1112
- async getAvailableProducts({ subscriptionId, lineId, q, mode, action, pagination }) {
1570
+ async getAvailableProducts({ subscriptionId, lineId, q: q3, mode, action, pagination }) {
1113
1571
  const params = new URLSearchParams();
1114
1572
  params.set("action", action);
1115
- if (q) params.set("q", q);
1573
+ if (q3) params.set("q", q3);
1116
1574
  if (mode) params.set("mode", mode);
1117
1575
  if (pagination && "after" in pagination) params.set("after", pagination.after);
1118
1576
  if (pagination && "before" in pagination) params.set("before", pagination.before);
@@ -1121,22 +1579,22 @@ function createApiProductAdapter(fetcher, opts = { currencyCode: "USD" }) {
1121
1579
  );
1122
1580
  if (!res.ok) return [];
1123
1581
  const data = await res.json();
1124
- return (data ?? []).map((p2) => {
1582
+ return (data ?? []).map((p3) => {
1125
1583
  var _a;
1126
1584
  return {
1127
- id: p2.id,
1128
- title: p2.title,
1129
- description: p2.description ?? "",
1130
- featuredImage: p2.featuredImage,
1131
- hasOnlyDefaultVariant: p2.hasOnlyDefaultVariant ?? (((_a = p2.variants) == null ? void 0 : _a.length) ?? 0) <= 1,
1132
- variants: (p2.variants ?? []).map((v2) => ({
1133
- id: v2.id,
1134
- availableForSale: v2.availableForSale,
1135
- title: v2.title,
1136
- currentPrice: v2.currentPrice,
1137
- basePrice: v2.basePrice,
1138
- image: v2.image,
1139
- recurring: v2.recurring
1585
+ id: p3.id,
1586
+ title: p3.title,
1587
+ description: p3.description ?? "",
1588
+ featuredImage: p3.featuredImage,
1589
+ hasOnlyDefaultVariant: p3.hasOnlyDefaultVariant ?? (((_a = p3.variants) == null ? void 0 : _a.length) ?? 0) <= 1,
1590
+ variants: (p3.variants ?? []).map((v3) => ({
1591
+ id: v3.id,
1592
+ availableForSale: v3.availableForSale,
1593
+ title: v3.title,
1594
+ currentPrice: v3.currentPrice,
1595
+ basePrice: v3.basePrice,
1596
+ image: v3.image,
1597
+ recurring: v3.recurring
1140
1598
  }))
1141
1599
  };
1142
1600
  });
@@ -1181,7 +1639,7 @@ function routeNameTableFromPages(pages) {
1181
1639
  function createRouterService(options) {
1182
1640
  const { pages, pushImplementation } = options;
1183
1641
  const routeNameToPagePath = routeNameTableFromPages(pages);
1184
- const pathSet = new Set(pages.map((p2) => p2.path));
1642
+ const pathSet = new Set(pages.map((p3) => p3.path));
1185
1643
  const navigationSubscribers = [];
1186
1644
  function notifySubscribers(logicalPath) {
1187
1645
  for (const cb of navigationSubscribers) cb({ path: logicalPath });
@@ -1232,6 +1690,49 @@ const DISCOUNT_REJECTION_REASONS = [
1232
1690
  function toAttributeArray(next) {
1233
1691
  return Object.entries(next).map(([key, value]) => ({ key, value }));
1234
1692
  }
1693
+ const MOCK_SHIPPING_METHODS = [
1694
+ {
1695
+ handle: "standard-shipping",
1696
+ title: "Standard shipping",
1697
+ price: { amount: "0.00", currencyCode: "EUR" }
1698
+ },
1699
+ {
1700
+ handle: "dhl-express",
1701
+ title: "DHL Express",
1702
+ price: { amount: "9.99", currencyCode: "EUR" }
1703
+ },
1704
+ {
1705
+ handle: "next-day",
1706
+ title: "Next day delivery",
1707
+ price: { amount: "14.99", currencyCode: "EUR" }
1708
+ }
1709
+ ];
1710
+ function toShippingAddressBody(address) {
1711
+ return {
1712
+ firstName: address.firstName,
1713
+ lastName: address.lastName,
1714
+ address1: address.address1,
1715
+ zip: address.zip,
1716
+ city: address.city,
1717
+ ...address.address2 ? { address2: address.address2 } : {},
1718
+ ...address.province ? { province: address.province } : {},
1719
+ ...address.phone ? { phone: address.phone } : {},
1720
+ ...address.company ? { company: address.company } : {}
1721
+ };
1722
+ }
1723
+ function isStaleSubscriptionMessage(message) {
1724
+ return message ? message.toLowerCase().includes("changed since last fetch") : false;
1725
+ }
1726
+ function toNonEmptyAttributeArray(next) {
1727
+ if (next == null) return [];
1728
+ return toAttributeArray(next).filter(
1729
+ ({ key, value }) => key !== "" && value !== ""
1730
+ );
1731
+ }
1732
+ const MOCK_INSTANT_ORDER_MIN_ITEMS = 1;
1733
+ const MOCK_INSTANT_ORDER_MAX_ITEMS = 20;
1734
+ const MOCK_INSTANT_ORDER_MIN_QUANTITY = 1;
1735
+ const MOCK_INSTANT_ORDER_MAX_QUANTITY = 10;
1235
1736
  function createMockSubscriptionAdapter(options = {}) {
1236
1737
  const richBase = (id, itemId, renewalId) => ({
1237
1738
  id,
@@ -1295,7 +1796,24 @@ function createMockSubscriptionAdapter(options = {}) {
1295
1796
  renewal: { id: renewalId, isInActiveProcessState: false },
1296
1797
  lastPaymentStatus: "succeeded",
1297
1798
  pausePeriod: null,
1298
- isEditable: true
1799
+ isEditable: true,
1800
+ // Shaped like the v1 mapping produces it: one option slot filled, no
1801
+ // presentmentTitle (v1 has no such field). Previews would otherwise render
1802
+ // ContractSelect's address / method rows as "-".
1803
+ deliveryMethod: {
1804
+ address: {
1805
+ firstName: "Ada",
1806
+ lastName: "Lovelace",
1807
+ address1: "Wilcza 12/4",
1808
+ zip: "00-538",
1809
+ city: "Warsaw",
1810
+ country: "Poland",
1811
+ countryCode: "PL"
1812
+ },
1813
+ shippingOption: { title: "Standard shipping" },
1814
+ pickupOption: null,
1815
+ localDeliveryOption: null
1816
+ }
1299
1817
  });
1300
1818
  const mockSubscriptions = [
1301
1819
  {
@@ -1364,6 +1882,20 @@ function createMockSubscriptionAdapter(options = {}) {
1364
1882
  lastPaymentStatus: "succeeded",
1365
1883
  pausePeriod: null,
1366
1884
  isEditable: true,
1885
+ deliveryMethod: {
1886
+ address: {
1887
+ firstName: "Ada",
1888
+ lastName: "Lovelace",
1889
+ address1: "Wilcza 12/4",
1890
+ zip: "00-538",
1891
+ city: "Warsaw",
1892
+ country: "Poland",
1893
+ countryCode: "PL"
1894
+ },
1895
+ shippingOption: { title: "DHL Express" },
1896
+ pickupOption: null,
1897
+ localDeliveryOption: null
1898
+ },
1367
1899
  customAttributes: [
1368
1900
  { key: "subscription_tier", value: "premium" },
1369
1901
  { key: "gift_message", value: "Enjoy your skincare routine!" }
@@ -1395,6 +1927,14 @@ function createMockSubscriptionAdapter(options = {}) {
1395
1927
  frequency: "2 WEEK",
1396
1928
  createdAt: "2024-09-15T00:00:00Z",
1397
1929
  updatedAt: "2024-10-10T00:00:00Z",
1930
+ // Pickup, with no address — the other branch of the option coalescing in
1931
+ // ContractSelect's delivery-method label.
1932
+ deliveryMethod: {
1933
+ address: null,
1934
+ shippingOption: null,
1935
+ pickupOption: { title: "Pickup in store" },
1936
+ localDeliveryOption: null
1937
+ },
1398
1938
  customAttributes: []
1399
1939
  },
1400
1940
  // Per-status fixtures: groundwork for the deferred editor preview picker
@@ -1403,18 +1943,55 @@ function createMockSubscriptionAdapter(options = {}) {
1403
1943
  {
1404
1944
  ...richBase("sub_paused", "item_paused", "ren_paused"),
1405
1945
  status: "paused",
1406
- pausePeriod: { start: "2025-11-01T00:00:00Z", end: "2026-01-01T00:00:00Z" }
1946
+ pausePeriod: { start: "2025-11-01T00:00:00Z", end: "2026-01-01T00:00:00Z" },
1947
+ // BLIK with a non-recurring alias — the shape that gates the
1948
+ // re-authorization prompt in RenewalSummary. Only the legacy-sourced
1949
+ // payment method can express this, so previews would otherwise never
1950
+ // exercise the branch.
1951
+ customerPaymentMethod: {
1952
+ id: "pm_blik",
1953
+ instrument: { type: "blik", label: "my-blik-alias" },
1954
+ active: true,
1955
+ isRecurring: false
1956
+ }
1407
1957
  },
1408
1958
  {
1409
1959
  ...richBase("sub_canceled", "item_canceled", "ren_canceled"),
1410
1960
  status: "canceled",
1411
- pausePeriod: null
1961
+ pausePeriod: null,
1962
+ // SEPA — identified by a masked IBAN rather than card digits.
1963
+ customerPaymentMethod: {
1964
+ id: "pm_sepa",
1965
+ instrument: {
1966
+ type: "sepa_direct_debit",
1967
+ consumerName: "Ada Lovelace",
1968
+ consumerBic: "ABCDEFGH",
1969
+ consumerAccount: "DE12****6789"
1970
+ },
1971
+ active: true,
1972
+ isRecurring: true
1973
+ }
1412
1974
  },
1413
1975
  {
1414
1976
  ...richBase("sub_failed", "item_failed", "ren_failed"),
1415
1977
  status: "failed",
1416
1978
  lastPaymentStatus: "failed",
1417
- pausePeriod: null
1979
+ pausePeriod: null,
1980
+ // An expired card — pairs with the failed payment, and exercises
1981
+ // getPaymentInstrumentExpiry's isExpired branch.
1982
+ customerPaymentMethod: {
1983
+ id: "pm_expired_card",
1984
+ instrument: {
1985
+ type: "credit_card",
1986
+ brand: "mastercard",
1987
+ maskedNumber: "************5100",
1988
+ expiryMonth: 1,
1989
+ expiryYear: 2024,
1990
+ cardholderName: "Ada Lovelace"
1991
+ },
1992
+ active: true,
1993
+ isRecurring: true
1994
+ }
1418
1995
  },
1419
1996
  {
1420
1997
  ...richBase("sub_expired", "item_expired", "ren_expired"),
@@ -1440,6 +2017,60 @@ function createMockSubscriptionAdapter(options = {}) {
1440
2017
  description: "Lightweight daily sun protection"
1441
2018
  }
1442
2019
  ];
2020
+ const mockInstantOrderImages = {
2021
+ "io-product-1": "https://images.unsplash.com/photo-1447933601403-0c6688de566e?w=200",
2022
+ "io-product-2": "https://images.unsplash.com/photo-1495474472287-4d71bcdd2085?w=200"
2023
+ };
2024
+ const mockInstantOrderProducts = [
2025
+ {
2026
+ id: "io-product-1",
2027
+ title: "Single-Origin Espresso",
2028
+ hasOnlyDefaultVariant: false,
2029
+ featuredImage: {
2030
+ url: mockInstantOrderImages["io-product-1"],
2031
+ altText: "Single-Origin Espresso"
2032
+ },
2033
+ variants: {
2034
+ items: [
2035
+ {
2036
+ id: "io-variant-1",
2037
+ title: "250 g",
2038
+ image: { url: mockInstantOrderImages["io-product-1"] },
2039
+ price: { amount: "12.00", currencyCode: "USD" },
2040
+ availableForSale: true
2041
+ },
2042
+ {
2043
+ id: "io-variant-2",
2044
+ title: "1 kg",
2045
+ image: { url: mockInstantOrderImages["io-product-1"] },
2046
+ price: { amount: "38.00", currencyCode: "USD" },
2047
+ availableForSale: true
2048
+ }
2049
+ ]
2050
+ }
2051
+ },
2052
+ {
2053
+ id: "io-product-2",
2054
+ title: "Ceramic Pour-Over Dripper",
2055
+ hasOnlyDefaultVariant: true,
2056
+ featuredImage: {
2057
+ url: mockInstantOrderImages["io-product-2"],
2058
+ altText: "Ceramic Pour-Over Dripper"
2059
+ },
2060
+ variants: {
2061
+ items: [
2062
+ {
2063
+ id: "io-variant-3",
2064
+ title: "Default Title",
2065
+ image: { url: mockInstantOrderImages["io-product-2"] },
2066
+ price: { amount: "24.50", currencyCode: "USD" },
2067
+ availableForSale: true
2068
+ }
2069
+ ]
2070
+ }
2071
+ }
2072
+ ];
2073
+ let placedInstantOrders = 0;
1443
2074
  return {
1444
2075
  async getById(id) {
1445
2076
  await new Promise((resolve) => setTimeout(resolve, 300));
@@ -1449,7 +2080,7 @@ function createMockSubscriptionAdapter(options = {}) {
1449
2080
  data: subscription ? {
1450
2081
  ...subscription,
1451
2082
  items: subscription.items.map((item) => ({ ...item })),
1452
- discounts: subscription.discounts.map((d3) => ({ ...d3 }))
2083
+ discounts: subscription.discounts.map((d2) => ({ ...d2 }))
1453
2084
  } : null
1454
2085
  };
1455
2086
  },
@@ -1497,7 +2128,7 @@ function createMockSubscriptionAdapter(options = {}) {
1497
2128
  }
1498
2129
  const currencyCode = ((_a = subscription.items[0]) == null ? void 0 : _a.price.currencyCode) ?? "USD";
1499
2130
  const product = await ((_b = options.productAdapter) == null ? void 0 : _b.getByVariantId(item.variantId)) ?? await ((_c = options.productAdapter) == null ? void 0 : _c.getById(item.variantId)) ?? null;
1500
- const variant = (product == null ? void 0 : product.variants.items.find((v2) => v2.id === item.variantId)) ?? (product == null ? void 0 : product.variants.items[0]);
2131
+ const variant = (product == null ? void 0 : product.variants.items.find((v3) => v3.id === item.variantId)) ?? (product == null ? void 0 : product.variants.items[0]);
1501
2132
  const linePrice = ((_e = (_d = variant == null ? void 0 : variant.purchaseOptions) == null ? void 0 : _d[0]) == null ? void 0 : _e.price) ?? (variant == null ? void 0 : variant.price);
1502
2133
  subscription.items.push({
1503
2134
  id: `item_${Date.now()}_${subscription.items.length}`,
@@ -1510,8 +2141,11 @@ function createMockSubscriptionAdapter(options = {}) {
1510
2141
  ...variant && product && !product.hasOnlyDefaultVariant ? { variantTitle: variant.title } : {},
1511
2142
  ...(variant == null ? void 0 : variant.image) ? { variantImage: variant.image } : {},
1512
2143
  variantAvailableForSale: true,
1513
- billingPolicy: ((_f = subscription.items[0]) == null ? void 0 : _f.billingPolicy) ?? subscription.billingPolicy ?? null,
1514
- deliveryPolicy: ((_g = subscription.items[0]) == null ? void 0 : _g.deliveryPolicy) ?? subscription.deliveryPolicy ?? null
2144
+ // An explicit per-line billingPolicy wins; otherwise inherit the plan's.
2145
+ billingPolicy: item.billingPolicy ?? ((_f = subscription.items[0]) == null ? void 0 : _f.billingPolicy) ?? subscription.billingPolicy ?? null,
2146
+ deliveryPolicy: ((_g = subscription.items[0]) == null ? void 0 : _g.deliveryPolicy) ?? subscription.deliveryPolicy ?? null,
2147
+ ...item.recurringCycleLimit != null ? { recurringCycleLimit: item.recurringCycleLimit } : {},
2148
+ ...item.customAttributes != null ? { customAttributes: toAttributeArray(item.customAttributes) } : {}
1515
2149
  });
1516
2150
  subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1517
2151
  return { _tag: "Success", data: void 0 };
@@ -1522,7 +2156,7 @@ function createMockSubscriptionAdapter(options = {}) {
1522
2156
  if (!subscription) {
1523
2157
  return { _tag: "Failure", error: "Subscription not found" };
1524
2158
  }
1525
- subscription.items = subscription.items.filter((i2) => i2.id !== itemId);
2159
+ subscription.items = subscription.items.filter((i3) => i3.id !== itemId);
1526
2160
  subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1527
2161
  return { _tag: "Success", data: void 0 };
1528
2162
  },
@@ -1532,13 +2166,16 @@ function createMockSubscriptionAdapter(options = {}) {
1532
2166
  if (!subscription) {
1533
2167
  return { _tag: "Failure", error: "Subscription not found" };
1534
2168
  }
1535
- const item = subscription.items.find((i2) => i2.id === lineId);
2169
+ const item = subscription.items.find((i3) => i3.id === lineId);
1536
2170
  if (!item) {
1537
2171
  return { _tag: "Failure", error: "Line item not found" };
1538
2172
  }
1539
2173
  if (update.variantId !== void 0) item.variantId = update.variantId;
1540
2174
  if (update.quantity !== void 0) item.quantity = update.quantity;
1541
2175
  if (update.billingPolicy !== void 0) item.billingPolicy = update.billingPolicy;
2176
+ if (update.customAttributes !== void 0) {
2177
+ item.customAttributes = toAttributeArray(update.customAttributes);
2178
+ }
1542
2179
  subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1543
2180
  return { _tag: "Success", data: void 0 };
1544
2181
  },
@@ -1548,7 +2185,7 @@ function createMockSubscriptionAdapter(options = {}) {
1548
2185
  if (!subscription) {
1549
2186
  return { _tag: "Failure", error: "Subscription not found" };
1550
2187
  }
1551
- const item = subscription.items.find((i2) => i2.id === lineId);
2188
+ const item = subscription.items.find((i3) => i3.id === lineId);
1552
2189
  if (!item) {
1553
2190
  return { _tag: "Failure", error: "Line item not found" };
1554
2191
  }
@@ -1623,7 +2260,93 @@ function createMockSubscriptionAdapter(options = {}) {
1623
2260
  );
1624
2261
  subscription.customAttributes = [...preserved, ...next];
1625
2262
  subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1626
- return { _tag: "Success", data: { ...subscription } };
2263
+ return { _tag: "Success", data: { ...subscription } };
2264
+ },
2265
+ async updateDeliveryAddress({
2266
+ subscriptionId,
2267
+ address
2268
+ }) {
2269
+ var _a;
2270
+ await new Promise((resolve) => setTimeout(resolve, 300));
2271
+ const subscription = mockSubscriptions.find(
2272
+ (sub) => sub.id === subscriptionId
2273
+ );
2274
+ if (!subscription) {
2275
+ return { _tag: "Failure", error: { kind: "SUBSCRIPTION_NOT_FOUND" } };
2276
+ }
2277
+ const previous = (_a = subscription.deliveryMethod) == null ? void 0 : _a.address;
2278
+ subscription.deliveryMethod = {
2279
+ ...subscription.deliveryMethod,
2280
+ address: {
2281
+ firstName: address.firstName,
2282
+ lastName: address.lastName,
2283
+ address1: address.address1,
2284
+ zip: address.zip,
2285
+ city: address.city,
2286
+ ...address.address2 ? { address2: address.address2 } : {},
2287
+ ...address.province ? { province: address.province } : {},
2288
+ ...address.phone ? { phone: address.phone } : {},
2289
+ ...address.company ? { company: address.company } : {},
2290
+ ...(previous == null ? void 0 : previous.country) != null ? { country: previous.country } : {},
2291
+ ...(previous == null ? void 0 : previous.countryCode) != null ? { countryCode: previous.countryCode } : {}
2292
+ }
2293
+ };
2294
+ subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2295
+ return { _tag: "Success", data: void 0 };
2296
+ },
2297
+ async getAvailableShippingMethods({
2298
+ subscriptionId
2299
+ }) {
2300
+ var _a, _b, _c;
2301
+ await new Promise((resolve) => setTimeout(resolve, 300));
2302
+ const subscription = mockSubscriptions.find(
2303
+ (sub) => sub.id === subscriptionId
2304
+ );
2305
+ if (!subscription) {
2306
+ return { _tag: "Failure", error: "Subscription not found" };
2307
+ }
2308
+ const currentTitle = (_b = (_a = subscription.deliveryMethod) == null ? void 0 : _a.shippingOption) == null ? void 0 : _b.title;
2309
+ const currencyCode = ((_c = subscription.items[0]) == null ? void 0 : _c.price.currencyCode) ?? "EUR";
2310
+ return {
2311
+ _tag: "Success",
2312
+ data: MOCK_SHIPPING_METHODS.map((method) => ({
2313
+ ...method,
2314
+ price: { ...method.price, currencyCode },
2315
+ isActive: method.title === currentTitle
2316
+ }))
2317
+ };
2318
+ },
2319
+ async updateDeliveryMethod({
2320
+ subscriptionId,
2321
+ shippingMethodHandle
2322
+ }) {
2323
+ await new Promise((resolve) => setTimeout(resolve, 300));
2324
+ const subscription = mockSubscriptions.find(
2325
+ (sub) => sub.id === subscriptionId
2326
+ );
2327
+ if (!subscription) {
2328
+ return { _tag: "Failure", error: { kind: "SUBSCRIPTION_NOT_FOUND" } };
2329
+ }
2330
+ const method = MOCK_SHIPPING_METHODS.find(
2331
+ (m2) => m2.handle === shippingMethodHandle
2332
+ );
2333
+ if (!method) {
2334
+ return {
2335
+ _tag: "Failure",
2336
+ error: {
2337
+ kind: "UNKNOWN",
2338
+ message: `Provided shipping method handle "${shippingMethodHandle}" is not available`
2339
+ }
2340
+ };
2341
+ }
2342
+ subscription.deliveryMethod = {
2343
+ ...subscription.deliveryMethod,
2344
+ shippingOption: { title: method.title },
2345
+ pickupOption: null,
2346
+ localDeliveryOption: null
2347
+ };
2348
+ subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2349
+ return { _tag: "Success", data: void 0 };
1627
2350
  },
1628
2351
  async resume(params) {
1629
2352
  await new Promise((resolve) => setTimeout(resolve, 300));
@@ -1738,7 +2461,7 @@ function createMockSubscriptionAdapter(options = {}) {
1738
2461
  data: {
1739
2462
  ...subscription,
1740
2463
  items: subscription.items.map((item) => ({ ...item })),
1741
- discounts: subscription.discounts.map((d3) => ({ ...d3 }))
2464
+ discounts: subscription.discounts.map((d2) => ({ ...d2 }))
1742
2465
  }
1743
2466
  };
1744
2467
  },
@@ -1754,27 +2477,165 @@ function createMockSubscriptionAdapter(options = {}) {
1754
2477
  async addUpsellProduct() {
1755
2478
  await new Promise((resolve) => setTimeout(resolve, 400));
1756
2479
  return { _tag: "Success", data: void 0 };
2480
+ },
2481
+ async getInstantOrderProducts({
2482
+ query
2483
+ }) {
2484
+ await new Promise((resolve) => setTimeout(resolve, 300));
2485
+ const term = query == null ? void 0 : query.trim().toLowerCase();
2486
+ const products = term ? mockInstantOrderProducts.filter(
2487
+ (product) => product.title.toLowerCase().includes(term)
2488
+ ) : [...mockInstantOrderProducts];
2489
+ return {
2490
+ _tag: "Success",
2491
+ data: {
2492
+ // Deliberately independent of `query`, mirroring the endpoint: a search
2493
+ // that matches nothing must not read as "the feature is unavailable"
2494
+ // and make a consumer hide its entry point mid-interaction.
2495
+ available: mockInstantOrderProducts.length > 0,
2496
+ requiresCheckout: false,
2497
+ products,
2498
+ hasNextPage: false,
2499
+ endCursor: null
2500
+ }
2501
+ };
2502
+ },
2503
+ async placeInstantOrder({
2504
+ items,
2505
+ shippingMethodTitle
2506
+ }) {
2507
+ var _a;
2508
+ await new Promise((resolve) => setTimeout(resolve, 400));
2509
+ const malformed = items.length < MOCK_INSTANT_ORDER_MIN_ITEMS || items.length > MOCK_INSTANT_ORDER_MAX_ITEMS || items.some(
2510
+ (item) => !Number.isInteger(item.quantity) || item.quantity < MOCK_INSTANT_ORDER_MIN_QUANTITY || item.quantity > MOCK_INSTANT_ORDER_MAX_QUANTITY
2511
+ );
2512
+ if (malformed) {
2513
+ return {
2514
+ _tag: "Failure",
2515
+ error: {
2516
+ kind: "INVALID_REQUEST",
2517
+ message: "Malformed item list"
2518
+ }
2519
+ };
2520
+ }
2521
+ const variants = mockInstantOrderProducts.flatMap(
2522
+ (product) => product.variants.items
2523
+ );
2524
+ const unknown = items.find(
2525
+ (item) => !variants.some((variant) => variant.id === item.variantId)
2526
+ );
2527
+ if (unknown) {
2528
+ return {
2529
+ _tag: "Failure",
2530
+ error: {
2531
+ kind: "INVALID_REQUEST",
2532
+ message: `Unknown variant ${unknown.variantId}`
2533
+ }
2534
+ };
2535
+ }
2536
+ const rate = MOCK_SHIPPING_METHODS.find(
2537
+ (method) => method.title === shippingMethodTitle
2538
+ );
2539
+ if (shippingMethodTitle != null && rate == null) {
2540
+ return {
2541
+ _tag: "Failure",
2542
+ error: {
2543
+ kind: "INVALID_REQUEST",
2544
+ message: `Shipping method "${shippingMethodTitle}" is not available for this order`
2545
+ }
2546
+ };
2547
+ }
2548
+ const total = items.reduce(
2549
+ (sum, item) => {
2550
+ const variant = variants.find((v3) => v3.id === item.variantId);
2551
+ return sum + Number((variant == null ? void 0 : variant.price.amount) ?? 0) * item.quantity;
2552
+ },
2553
+ // Only when a rate was chosen: an instant order left on the
2554
+ // subscription's own delivery method has no separate delivery price the
2555
+ // mock catalog can know.
2556
+ Number((rate == null ? void 0 : rate.price.amount) ?? 0)
2557
+ );
2558
+ placedInstantOrders += 1;
2559
+ return {
2560
+ _tag: "Success",
2561
+ data: {
2562
+ orderId: `io-order-${placedInstantOrders}`,
2563
+ totalPrice: total.toFixed(2),
2564
+ currencyCode: ((_a = variants[0]) == null ? void 0 : _a.price.currencyCode) ?? "USD",
2565
+ status: "paid"
2566
+ }
2567
+ };
1757
2568
  }
1758
2569
  };
1759
2570
  }
1760
- function normalizeInstrumentType(type) {
1761
- return type.replace(/-/g, "_");
2571
+ function mapV1Instrument(raw) {
2572
+ return serializeV1PaymentInstrument(raw);
2573
+ }
2574
+ function mapV1BillingAddress(raw) {
2575
+ if (raw == null || typeof raw !== "object") return null;
2576
+ const address = {
2577
+ firstName: raw.firstName ?? null,
2578
+ lastName: raw.lastName ?? null,
2579
+ address1: raw.address1 ?? null,
2580
+ address2: raw.address2 ?? null,
2581
+ zip: raw.zip ?? null,
2582
+ city: raw.city ?? null,
2583
+ country: raw.country ?? null,
2584
+ countryCode: raw.countryCode ?? null,
2585
+ province: raw.province ?? null,
2586
+ provinceCode: raw.provinceCode ?? null,
2587
+ phone: raw.phone ?? null,
2588
+ company: raw.company ?? null
2589
+ };
2590
+ return Object.values(address).some((v3) => v3 != null) ? address : null;
2591
+ }
2592
+ function mapV1DeliveryAddress(raw) {
2593
+ if (raw == null || typeof raw !== "object") return null;
2594
+ const address = {
2595
+ ...raw.firstName != null ? { firstName: raw.firstName } : {},
2596
+ ...raw.lastName != null ? { lastName: raw.lastName } : {},
2597
+ ...raw.address1 != null ? { address1: raw.address1 } : {},
2598
+ ...raw.address2 != null ? { address2: raw.address2 } : {},
2599
+ ...raw.zip != null ? { zip: raw.zip } : {},
2600
+ ...raw.city != null ? { city: raw.city } : {},
2601
+ ...raw.country != null ? { country: raw.country } : {},
2602
+ ...raw.countryCode != null ? { countryCode: raw.countryCode } : {},
2603
+ ...raw.province != null ? { province: raw.province } : {},
2604
+ ...raw.provinceCode != null ? { provinceCode: raw.provinceCode } : {},
2605
+ ...raw.phone != null ? { phone: raw.phone } : {},
2606
+ ...raw.company != null ? { company: raw.company } : {}
2607
+ };
2608
+ return Object.keys(address).length > 0 ? address : null;
2609
+ }
2610
+ function mapV1DeliveryMethod(raw) {
2611
+ const address = mapV1DeliveryAddress(raw == null ? void 0 : raw.deliveryAddress);
2612
+ const method = raw == null ? void 0 : raw.deliveryMethod;
2613
+ if (address == null && (method == null || typeof method !== "object")) {
2614
+ return null;
2615
+ }
2616
+ const option = method != null && typeof method === "object" ? {
2617
+ ...method.title != null ? { title: method.title } : {},
2618
+ ...method.description != null ? { description: method.description } : {}
2619
+ } : null;
2620
+ return {
2621
+ address,
2622
+ shippingOption: (method == null ? void 0 : method.type) === "shipping" ? option : null,
2623
+ pickupOption: (method == null ? void 0 : method.type) === "pickup" ? option : null,
2624
+ localDeliveryOption: (method == null ? void 0 : method.type) === "local-delivery" ? option : null
2625
+ };
1762
2626
  }
1763
2627
  function mapPaymentMethod(rawPm) {
1764
2628
  if (!rawPm) return null;
1765
2629
  if (typeof rawPm === "string") {
1766
2630
  return { id: rawPm };
1767
2631
  }
2632
+ const instrument = mapV1Instrument(rawPm.instrument);
2633
+ const billingAddress = mapV1BillingAddress(rawPm.billingAddress);
1768
2634
  return {
1769
2635
  id: rawPm.id ?? "",
1770
- ...rawPm.instrument != null ? {
1771
- instrument: {
1772
- ...rawPm.instrument,
1773
- type: normalizeInstrumentType(rawPm.instrument.type)
1774
- }
1775
- } : {},
1776
- ...rawPm.active != null ? { active: rawPm.active } : {},
1777
- ...rawPm.isRecurring != null ? { isRecurring: rawPm.isRecurring } : {}
2636
+ ...instrument != null ? { instrument } : {},
2637
+ // v1 is the ONLY customer-facing source of a billing address.
2638
+ ...billingAddress != null ? { billingAddress } : {}
1778
2639
  };
1779
2640
  }
1780
2641
  function mapSubscription(raw) {
@@ -1810,14 +2671,14 @@ function mapSubscription(raw) {
1810
2671
  ),
1811
2672
  discounts: (raw.discounts ?? []).map(
1812
2673
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1813
- (d3) => {
2674
+ (d2) => {
1814
2675
  var _a2, _b2, _c;
1815
2676
  return {
1816
- id: d3.id,
1817
- type: ((_a2 = d3.value) == null ? void 0 : _a2.type) === "fixed-amount" || d3.type === "fixed_amount" ? "fixed_amount" : "percentage",
1818
- value: ((_b2 = d3.value) == null ? void 0 : _b2.amount) ?? ((_c = d3.value) == null ? void 0 : _c.percentage) ?? d3.value ?? 0,
1819
- code: d3.title ?? d3.code ?? "",
1820
- description: d3.description ?? ""
2677
+ id: d2.id,
2678
+ type: ((_a2 = d2.value) == null ? void 0 : _a2.type) === "fixed-amount" || d2.type === "fixed_amount" ? "fixed_amount" : "percentage",
2679
+ value: ((_b2 = d2.value) == null ? void 0 : _b2.amount) ?? ((_c = d2.value) == null ? void 0 : _c.percentage) ?? d2.value ?? 0,
2680
+ code: d2.title ?? d2.code ?? "",
2681
+ description: d2.description ?? ""
1821
2682
  };
1822
2683
  }
1823
2684
  ),
@@ -1828,6 +2689,8 @@ function mapSubscription(raw) {
1828
2689
  // Map customerPaymentMethod — expanded to an object (id + instrument) via the
1829
2690
  // adapter's ?expand=paymentMethod request; mapPaymentMethod tolerates a bare id too.
1830
2691
  customerPaymentMethod: mapPaymentMethod(raw.paymentMethod),
2692
+ // v1 returns deliveryAddress + deliveryMethod on every read, no expand needed.
2693
+ deliveryMethod: mapV1DeliveryMethod(raw),
1831
2694
  frequency,
1832
2695
  createdAt: raw.createdAt,
1833
2696
  updatedAt: raw.updatedAt,
@@ -1844,6 +2707,51 @@ async function readErrorBody(res) {
1844
2707
  return {};
1845
2708
  }
1846
2709
  }
2710
+ async function readErrorMessage(res) {
2711
+ const body = await readErrorBody(res);
2712
+ return typeof body.message === "string" ? body.message : void 0;
2713
+ }
2714
+ const PLACE_INSTANT_ORDER_ERROR_KINDS = {
2715
+ 400: "INVALID_REQUEST",
2716
+ 403: "REFUSED",
2717
+ 409: "DUPLICATE_REQUEST",
2718
+ 429: "RATE_LIMITED"
2719
+ };
2720
+ function mapInstantOrderProducts(body) {
2721
+ const currencyCode = body.currencyCode;
2722
+ const products = (body.products ?? []).map(
2723
+ (product) => {
2724
+ const image = product.featuredImage ? {
2725
+ url: product.featuredImage.url,
2726
+ ...product.featuredImage.altText != null ? { altText: product.featuredImage.altText } : {}
2727
+ } : null;
2728
+ return {
2729
+ id: product.productId,
2730
+ title: product.title,
2731
+ // Shopify's own flag, not a count of the variants this response happens
2732
+ // to carry — the two differ whenever some are filtered.
2733
+ hasOnlyDefaultVariant: product.hasOnlyDefaultVariant,
2734
+ featuredImage: image,
2735
+ variants: {
2736
+ items: (product.variants ?? []).map((variant) => ({
2737
+ id: variant.id,
2738
+ title: variant.title,
2739
+ image,
2740
+ price: { amount: variant.price, currencyCode },
2741
+ availableForSale: variant.availableForSale
2742
+ }))
2743
+ }
2744
+ };
2745
+ }
2746
+ );
2747
+ return {
2748
+ available: body.available,
2749
+ requiresCheckout: body.requiresCheckout,
2750
+ products,
2751
+ hasNextPage: body.hasNextPage,
2752
+ endCursor: body.endCursor ?? null
2753
+ };
2754
+ }
1847
2755
  function createApiSubscriptionAdapter(fetcher) {
1848
2756
  const adapter = {
1849
2757
  async search(options) {
@@ -1851,8 +2759,8 @@ function createApiSubscriptionAdapter(fetcher) {
1851
2759
  try {
1852
2760
  const params = new URLSearchParams();
1853
2761
  if ((_a = options == null ? void 0 : options.filters) == null ? void 0 : _a.length) {
1854
- const groups = options.filters.filter((f) => Object.keys(f).length > 0).map((f) => Object.entries(f).filter(([, v2]) => Boolean(v2))).filter((entries) => entries.length > 0).map(
1855
- (entries) => "(" + entries.map(([k, v2]) => `${k}:'${v2}'`).join(" AND ") + ")"
2762
+ const groups = options.filters.filter((f) => Object.keys(f).length > 0).map((f) => Object.entries(f).filter(([, v3]) => Boolean(v3))).filter((entries) => entries.length > 0).map(
2763
+ (entries) => "(" + entries.map(([k3, v3]) => `${k3}:'${v3}'`).join(" AND ") + ")"
1856
2764
  );
1857
2765
  if (groups.length) params.set("query", groups.join(" OR "));
1858
2766
  }
@@ -1882,8 +2790,8 @@ function createApiSubscriptionAdapter(fetcher) {
1882
2790
  }
1883
2791
  }
1884
2792
  };
1885
- } catch (e2) {
1886
- return { _tag: "Failure", error: e2 };
2793
+ } catch (e) {
2794
+ return { _tag: "Failure", error: e };
1887
2795
  }
1888
2796
  },
1889
2797
  async getById(id) {
@@ -1895,24 +2803,43 @@ function createApiSubscriptionAdapter(fetcher) {
1895
2803
  const body = await res.json();
1896
2804
  const raw = body.data[0];
1897
2805
  return { _tag: "Success", data: raw ? mapSubscription(raw) : null };
1898
- } catch (e2) {
1899
- return { _tag: "Failure", error: e2 };
2806
+ } catch (e) {
2807
+ return { _tag: "Failure", error: e };
1900
2808
  }
1901
2809
  },
2810
+ // Uses the legacy POST /customer/subscriptions/{id}/lines rather than
2811
+ // POST /customer/v1/subscriptions/{id}/items: only the legacy endpoint
2812
+ // accepts a per-line `billingPolicy`. It answers 204 with no body.
2813
+ // Behavioural differences vs the v1 route, both intentional here:
2814
+ // - it rejects membership subscriptions with 403 (v1 does not),
2815
+ // - it skips the availableForSale check (v1 enforces it), so callers are
2816
+ // responsible for only offering purchasable variants — which the
2817
+ // product picker already does.
1902
2818
  async addItem({ subscriptionId, item }) {
1903
2819
  try {
2820
+ const attributes = toNonEmptyAttributeArray(item.customAttributes);
2821
+ const body = {
2822
+ productVariantId: item.variantId,
2823
+ quantity: item.quantity,
2824
+ // `!= null` on purpose: null means "inherit"/"no limit", and the
2825
+ // endpoint rejects an explicit null on either field.
2826
+ ...item.billingPolicy != null ? { billingPolicy: item.billingPolicy } : {},
2827
+ ...item.recurringCycleLimit != null ? { renewalLimit: item.recurringCycleLimit } : {},
2828
+ ...item.shippingMethodHandle != null ? { shippingMethodHandle: item.shippingMethodHandle } : {},
2829
+ ...attributes.length > 0 ? { customAttributes: attributes } : {}
2830
+ };
1904
2831
  const res = await fetcher(
1905
- `/customer/v1/subscriptions/${subscriptionId}/items`,
2832
+ `/customer/subscriptions/${subscriptionId}/lines`,
1906
2833
  {
1907
2834
  method: "POST",
1908
2835
  headers: { "Content-Type": "application/json" },
1909
- body: JSON.stringify({ variant: item.variantId, quantity: item.quantity })
2836
+ body: JSON.stringify(body)
1910
2837
  }
1911
2838
  );
1912
2839
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1913
2840
  return { _tag: "Success", data: void 0 };
1914
- } catch (e2) {
1915
- return { _tag: "Failure", error: e2 };
2841
+ } catch (e) {
2842
+ return { _tag: "Failure", error: e };
1916
2843
  }
1917
2844
  },
1918
2845
  async removeItem({ subscriptionId, itemId }) {
@@ -1923,8 +2850,8 @@ function createApiSubscriptionAdapter(fetcher) {
1923
2850
  );
1924
2851
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1925
2852
  return { _tag: "Success", data: void 0 };
1926
- } catch (e2) {
1927
- return { _tag: "Failure", error: e2 };
2853
+ } catch (e) {
2854
+ return { _tag: "Failure", error: e };
1928
2855
  }
1929
2856
  },
1930
2857
  async updateItem({ subscriptionId, lineId, update }) {
@@ -1933,7 +2860,11 @@ function createApiSubscriptionAdapter(fetcher) {
1933
2860
  ...update.variantId !== void 0 ? { productVariantId: update.variantId } : {},
1934
2861
  ...update.quantity !== void 0 ? { quantity: update.quantity } : {},
1935
2862
  ...update.billingPolicy !== void 0 ? { billingPolicy: update.billingPolicy } : {},
1936
- ...update.shippingMethodHandle !== void 0 ? { shippingMethodHandle: update.shippingMethodHandle } : {}
2863
+ ...update.shippingMethodHandle !== void 0 ? { shippingMethodHandle: update.shippingMethodHandle } : {},
2864
+ // Record shape (not the array the add-line endpoint takes). Guarded on
2865
+ // `!== undefined` so `{}` — clear every customer-visible attribute —
2866
+ // reaches the endpoint instead of being dropped as falsy.
2867
+ ...update.customAttributes !== void 0 ? { customAttributes: update.customAttributes } : {}
1937
2868
  };
1938
2869
  const res = await fetcher(
1939
2870
  `/customer/subscriptions/${subscriptionId}/lines/${lineId}`,
@@ -1945,8 +2876,8 @@ function createApiSubscriptionAdapter(fetcher) {
1945
2876
  );
1946
2877
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1947
2878
  return { _tag: "Success", data: void 0 };
1948
- } catch (e2) {
1949
- return { _tag: "Failure", error: e2 };
2879
+ } catch (e) {
2880
+ return { _tag: "Failure", error: e };
1950
2881
  }
1951
2882
  },
1952
2883
  async updateItemAttributes({ subscriptionId, lineId, customAttributes }) {
@@ -1961,8 +2892,8 @@ function createApiSubscriptionAdapter(fetcher) {
1961
2892
  );
1962
2893
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1963
2894
  return { _tag: "Success", data: void 0 };
1964
- } catch (e2) {
1965
- return { _tag: "Failure", error: e2 };
2895
+ } catch (e) {
2896
+ return { _tag: "Failure", error: e };
1966
2897
  }
1967
2898
  },
1968
2899
  async updateAttributes({ subscriptionId, customAttributes }) {
@@ -1977,8 +2908,8 @@ function createApiSubscriptionAdapter(fetcher) {
1977
2908
  );
1978
2909
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1979
2910
  return { _tag: "Success", data: void 0 };
1980
- } catch (e2) {
1981
- return { _tag: "Failure", error: e2 };
2911
+ } catch (e) {
2912
+ return { _tag: "Failure", error: e };
1982
2913
  }
1983
2914
  },
1984
2915
  async skipLineItem({ subscriptionId, lineId, nextBillingDate }) {
@@ -1993,8 +2924,8 @@ function createApiSubscriptionAdapter(fetcher) {
1993
2924
  );
1994
2925
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1995
2926
  return { _tag: "Success", data: void 0 };
1996
- } catch (e2) {
1997
- return { _tag: "Failure", error: e2 };
2927
+ } catch (e) {
2928
+ return { _tag: "Failure", error: e };
1998
2929
  }
1999
2930
  },
2000
2931
  async updateBoxItems({ subscriptionId, parentId, items, shippingMethodHandle }) {
@@ -2009,8 +2940,8 @@ function createApiSubscriptionAdapter(fetcher) {
2009
2940
  );
2010
2941
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2011
2942
  return { _tag: "Success", data: void 0 };
2012
- } catch (e2) {
2013
- return { _tag: "Failure", error: e2 };
2943
+ } catch (e) {
2944
+ return { _tag: "Failure", error: e };
2014
2945
  }
2015
2946
  },
2016
2947
  async addDiscount({ subscriptionId, code }) {
@@ -2036,10 +2967,10 @@ function createApiSubscriptionAdapter(fetcher) {
2036
2967
  return { _tag: "Failure", error: { kind: "UNKNOWN", message: `HTTP ${res.status}` } };
2037
2968
  }
2038
2969
  return { _tag: "Success", data: void 0 };
2039
- } catch (e2) {
2970
+ } catch (e) {
2040
2971
  return {
2041
2972
  _tag: "Failure",
2042
- error: { kind: "NETWORK", message: e2 instanceof Error ? e2.message : void 0 }
2973
+ error: { kind: "NETWORK", message: e instanceof Error ? e.message : void 0 }
2043
2974
  };
2044
2975
  }
2045
2976
  },
@@ -2061,10 +2992,10 @@ function createApiSubscriptionAdapter(fetcher) {
2061
2992
  return { _tag: "Failure", error: { kind: "UNKNOWN", message: `HTTP ${res.status}` } };
2062
2993
  }
2063
2994
  return { _tag: "Success", data: void 0 };
2064
- } catch (e2) {
2995
+ } catch (e) {
2065
2996
  return {
2066
2997
  _tag: "Failure",
2067
- error: { kind: "NETWORK", message: e2 instanceof Error ? e2.message : void 0 }
2998
+ error: { kind: "NETWORK", message: e instanceof Error ? e.message : void 0 }
2068
2999
  };
2069
3000
  }
2070
3001
  },
@@ -2082,8 +3013,8 @@ function createApiSubscriptionAdapter(fetcher) {
2082
3013
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2083
3014
  const data = await res.json();
2084
3015
  return { _tag: "Success", data: mapSubscription(data) };
2085
- } catch (e2) {
2086
- return { _tag: "Failure", error: e2 };
3016
+ } catch (e) {
3017
+ return { _tag: "Failure", error: e };
2087
3018
  }
2088
3019
  },
2089
3020
  // PATCH /customer/v1/subscriptions/{id} with the full customer-visible set.
@@ -2100,8 +3031,123 @@ function createApiSubscriptionAdapter(fetcher) {
2100
3031
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2101
3032
  const data = await res.json();
2102
3033
  return { _tag: "Success", data: mapSubscription(data) };
2103
- } catch (e2) {
2104
- return { _tag: "Failure", error: e2 };
3034
+ } catch (e) {
3035
+ return { _tag: "Failure", error: e };
3036
+ }
3037
+ },
3038
+ // Legacy endpoint on purpose — see SubscriptionAdapter.updateDeliveryAddress
3039
+ // for why the documented v1 `deliveryAddress` patch is not used here.
3040
+ async updateDeliveryAddress({ subscriptionId, address }) {
3041
+ try {
3042
+ const res = await fetcher(
3043
+ `/customer/subscriptions/${subscriptionId}/shipping-address`,
3044
+ {
3045
+ method: "PUT",
3046
+ headers: { "Content-Type": "application/json" },
3047
+ body: JSON.stringify(toShippingAddressBody(address))
3048
+ }
3049
+ );
3050
+ if (!res.ok) {
3051
+ if (res.status === 403) {
3052
+ return { _tag: "Failure", error: { kind: "NOT_ALLOWED" } };
3053
+ }
3054
+ if (res.status === 404) {
3055
+ return {
3056
+ _tag: "Failure",
3057
+ error: { kind: "SUBSCRIPTION_NOT_FOUND" }
3058
+ };
3059
+ }
3060
+ if (res.status === 400) {
3061
+ const body = await readErrorBody(res);
3062
+ const message = typeof body.message === "string" ? body.message : void 0;
3063
+ if (isStaleSubscriptionMessage(message)) {
3064
+ return { _tag: "Failure", error: { kind: "STALE" } };
3065
+ }
3066
+ return {
3067
+ _tag: "Failure",
3068
+ error: {
3069
+ kind: "INVALID_ADDRESS",
3070
+ ...message ? { message } : {}
3071
+ }
3072
+ };
3073
+ }
3074
+ return {
3075
+ _tag: "Failure",
3076
+ error: { kind: "UNKNOWN", message: `HTTP ${res.status}` }
3077
+ };
3078
+ }
3079
+ return { _tag: "Success", data: void 0 };
3080
+ } catch (e) {
3081
+ return {
3082
+ _tag: "Failure",
3083
+ error: {
3084
+ kind: "NETWORK",
3085
+ message: e instanceof Error ? e.message : void 0
3086
+ }
3087
+ };
3088
+ }
3089
+ },
3090
+ // Legacy endpoint — no /customer/v1 equivalent exists yet.
3091
+ async getAvailableShippingMethods({ subscriptionId }) {
3092
+ try {
3093
+ const res = await fetcher(
3094
+ `/customer/subscriptions/${subscriptionId}/available-shipping-methods`
3095
+ );
3096
+ if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
3097
+ const data = await res.json();
3098
+ return { _tag: "Success", data };
3099
+ } catch (e) {
3100
+ return { _tag: "Failure", error: e };
3101
+ }
3102
+ },
3103
+ // Legacy endpoint — no /customer/v1 equivalent exists yet. No `extra` is
3104
+ // sent: pickup points are out of scope, and omitting it is what tells the
3105
+ // endpoint to leave any existing parcel-locker attributes alone.
3106
+ async updateDeliveryMethod({ subscriptionId, shippingMethodHandle }) {
3107
+ try {
3108
+ const res = await fetcher(
3109
+ `/customer/subscriptions/${subscriptionId}/shipping-method`,
3110
+ {
3111
+ method: "POST",
3112
+ headers: { "Content-Type": "application/json" },
3113
+ body: JSON.stringify({ shippingMethodHandle })
3114
+ }
3115
+ );
3116
+ if (!res.ok) {
3117
+ if (res.status === 403) {
3118
+ return { _tag: "Failure", error: { kind: "NOT_ALLOWED" } };
3119
+ }
3120
+ if (res.status === 404) {
3121
+ return {
3122
+ _tag: "Failure",
3123
+ error: { kind: "SUBSCRIPTION_NOT_FOUND" }
3124
+ };
3125
+ }
3126
+ if (res.status === 400) {
3127
+ const body = await readErrorBody(res);
3128
+ const message = typeof body.message === "string" ? body.message : void 0;
3129
+ if (isStaleSubscriptionMessage(message)) {
3130
+ return { _tag: "Failure", error: { kind: "STALE" } };
3131
+ }
3132
+ return {
3133
+ _tag: "Failure",
3134
+ error: { kind: "UNKNOWN", ...message ? { message } : {} }
3135
+ };
3136
+ }
3137
+ return {
3138
+ _tag: "Failure",
3139
+ error: { kind: "UNKNOWN", message: `HTTP ${res.status}` }
3140
+ };
3141
+ }
3142
+ return { _tag: "Success", data: void 0 };
3143
+ } catch (e) {
3144
+ return {
3145
+ _tag: "Failure",
3146
+ error: {
3147
+ kind: "NETWORK",
3148
+ message: e instanceof Error ? e.message : void 0
3149
+ }
3150
+ };
2105
3151
  }
2106
3152
  },
2107
3153
  async resume({ subscriptionId }) {
@@ -2113,8 +3159,8 @@ function createApiSubscriptionAdapter(fetcher) {
2113
3159
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2114
3160
  const data = await res.json();
2115
3161
  return { _tag: "Success", data: mapSubscription(data) };
2116
- } catch (e2) {
2117
- return { _tag: "Failure", error: e2 };
3162
+ } catch (e) {
3163
+ return { _tag: "Failure", error: e };
2118
3164
  }
2119
3165
  },
2120
3166
  async pause({ subscriptionId }) {
@@ -2126,8 +3172,8 @@ function createApiSubscriptionAdapter(fetcher) {
2126
3172
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2127
3173
  const data = await res.json();
2128
3174
  return { _tag: "Success", data: mapSubscription(data) };
2129
- } catch (e2) {
2130
- return { _tag: "Failure", error: e2 };
3175
+ } catch (e) {
3176
+ return { _tag: "Failure", error: e };
2131
3177
  }
2132
3178
  },
2133
3179
  async reactivate({ subscriptionId }) {
@@ -2139,8 +3185,8 @@ function createApiSubscriptionAdapter(fetcher) {
2139
3185
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2140
3186
  const data = await res.json();
2141
3187
  return { _tag: "Success", data: mapSubscription(data) };
2142
- } catch (e2) {
2143
- return { _tag: "Failure", error: e2 };
3188
+ } catch (e) {
3189
+ return { _tag: "Failure", error: e };
2144
3190
  }
2145
3191
  },
2146
3192
  async cancel({ subscriptionId, reason }) {
@@ -2156,8 +3202,8 @@ function createApiSubscriptionAdapter(fetcher) {
2156
3202
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2157
3203
  const data = await res.json();
2158
3204
  return { _tag: "Success", data: mapSubscription(data) };
2159
- } catch (e2) {
2160
- return { _tag: "Failure", error: e2 };
3205
+ } catch (e) {
3206
+ return { _tag: "Failure", error: e };
2161
3207
  }
2162
3208
  },
2163
3209
  // Legacy endpoint — no /customer/v1/subscriptions/{id}/plans exists yet.
@@ -2169,8 +3215,8 @@ function createApiSubscriptionAdapter(fetcher) {
2169
3215
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2170
3216
  const data = await res.json();
2171
3217
  return { _tag: "Success", data };
2172
- } catch (e2) {
2173
- return { _tag: "Failure", error: e2 };
3218
+ } catch (e) {
3219
+ return { _tag: "Failure", error: e };
2174
3220
  }
2175
3221
  },
2176
3222
  // Legacy endpoint — no /customer/v1 equivalent exists yet.
@@ -2182,8 +3228,8 @@ function createApiSubscriptionAdapter(fetcher) {
2182
3228
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2183
3229
  const data = await res.json();
2184
3230
  return { _tag: "Success", data: (data == null ? void 0 : data.id) ?? null };
2185
- } catch (e2) {
2186
- return { _tag: "Failure", error: e2 };
3231
+ } catch (e) {
3232
+ return { _tag: "Failure", error: e };
2187
3233
  }
2188
3234
  },
2189
3235
  // Legacy endpoint — no /customer/v1/subscriptions/{id}/upsells exists yet.
@@ -2194,24 +3240,24 @@ function createApiSubscriptionAdapter(fetcher) {
2194
3240
  );
2195
3241
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2196
3242
  const data = await res.json();
2197
- const products = data.map((p2) => {
3243
+ const products = data.map((p3) => {
2198
3244
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2199
3245
  return {
2200
- id: p2.id,
2201
- variantId: ((_b = (_a = p2.variants) == null ? void 0 : _a[0]) == null ? void 0 : _b.id) ?? "",
2202
- title: p2.title ?? "",
2203
- imageUrl: ((_c = p2.featuredImage) == null ? void 0 : _c.url) ?? void 0,
3246
+ id: p3.id,
3247
+ variantId: ((_b = (_a = p3.variants) == null ? void 0 : _a[0]) == null ? void 0 : _b.id) ?? "",
3248
+ title: p3.title ?? "",
3249
+ imageUrl: ((_c = p3.featuredImage) == null ? void 0 : _c.url) ?? void 0,
2204
3250
  price: {
2205
- amount: String(((_f = (_e = (_d = p2.variants) == null ? void 0 : _d[0]) == null ? void 0 : _e.currentPrice) == null ? void 0 : _f.amount) ?? 0),
2206
- currencyCode: ((_i = (_h = (_g = p2.variants) == null ? void 0 : _g[0]) == null ? void 0 : _h.currentPrice) == null ? void 0 : _i.currencyCode) ?? ""
3251
+ amount: String(((_f = (_e = (_d = p3.variants) == null ? void 0 : _d[0]) == null ? void 0 : _e.currentPrice) == null ? void 0 : _f.amount) ?? 0),
3252
+ currencyCode: ((_i = (_h = (_g = p3.variants) == null ? void 0 : _g[0]) == null ? void 0 : _h.currentPrice) == null ? void 0 : _i.currencyCode) ?? ""
2207
3253
  },
2208
3254
  // recurring comes from the upsell rule on variants[0]; present in PreparedProductSchema
2209
- recurring: (_k = (_j = p2.variants) == null ? void 0 : _j[0]) == null ? void 0 : _k.recurring
3255
+ recurring: (_k = (_j = p3.variants) == null ? void 0 : _j[0]) == null ? void 0 : _k.recurring
2210
3256
  };
2211
3257
  });
2212
3258
  return { _tag: "Success", data: products };
2213
- } catch (e2) {
2214
- return { _tag: "Failure", error: e2 };
3259
+ } catch (e) {
3260
+ return { _tag: "Failure", error: e };
2215
3261
  }
2216
3262
  },
2217
3263
  // Legacy endpoint — no /customer/v1/subscriptions/{id}/upsells POST exists yet.
@@ -2231,8 +3277,118 @@ function createApiSubscriptionAdapter(fetcher) {
2231
3277
  );
2232
3278
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2233
3279
  return { _tag: "Success", data: void 0 };
2234
- } catch (e2) {
2235
- return { _tag: "Failure", error: e2 };
3280
+ } catch (e) {
3281
+ return { _tag: "Failure", error: e };
3282
+ }
3283
+ },
3284
+ // Legacy endpoint — no /customer/v1 equivalent exists yet.
3285
+ async getInstantOrderProducts({ subscriptionId, query, after, limit }) {
3286
+ try {
3287
+ const params = new URLSearchParams();
3288
+ if (query) params.set("q", query);
3289
+ if (after != null) params.set("after", after);
3290
+ if (limit != null) params.set("limit", String(limit));
3291
+ const search = params.toString() ? `?${params.toString()}` : "";
3292
+ const res = await fetcher(
3293
+ `/customer/subscriptions/${subscriptionId}/instant-orders/products${search}`
3294
+ );
3295
+ if (!res.ok) {
3296
+ if (res.status === 404) {
3297
+ return { _tag: "Failure", error: { kind: "SUBSCRIPTION_NOT_FOUND" } };
3298
+ }
3299
+ const message = await readErrorMessage(res);
3300
+ return {
3301
+ _tag: "Failure",
3302
+ error: { kind: "UNKNOWN", message: message ?? `HTTP ${res.status}` }
3303
+ };
3304
+ }
3305
+ const body = await res.json().catch(() => null);
3306
+ if (body == null) {
3307
+ return {
3308
+ _tag: "Failure",
3309
+ error: { kind: "UNKNOWN", message: "Malformed response" }
3310
+ };
3311
+ }
3312
+ return { _tag: "Success", data: mapInstantOrderProducts(body) };
3313
+ } catch (e) {
3314
+ return {
3315
+ _tag: "Failure",
3316
+ error: {
3317
+ kind: "NETWORK",
3318
+ message: e instanceof Error ? e.message : void 0
3319
+ }
3320
+ };
3321
+ }
3322
+ },
3323
+ // Legacy endpoint — no /customer/v1 equivalent exists yet.
3324
+ //
3325
+ // No X-Last-Updated-At header: an instant order never mutates the
3326
+ // subscription, so the optimistic-lock preValidation (which only fires when
3327
+ // the header is present) has nothing to guard here.
3328
+ async placeInstantOrder({
3329
+ subscriptionId,
3330
+ requestKey,
3331
+ items,
3332
+ shippingMethodTitle
3333
+ }) {
3334
+ try {
3335
+ const res = await fetcher(
3336
+ `/customer/subscriptions/${subscriptionId}/instant-orders`,
3337
+ {
3338
+ method: "POST",
3339
+ headers: { "Content-Type": "application/json" },
3340
+ body: JSON.stringify({
3341
+ requestKey,
3342
+ // Narrowed to what the endpoint accepts: the rest of
3343
+ // PostableSubscriptionItem describes a subscription line (its
3344
+ // billing policy, its cycle limit), and an instant order is not one.
3345
+ items: items.map(({ variantId, quantity }) => ({
3346
+ variantId,
3347
+ quantity
3348
+ })),
3349
+ // Basket-level, not per-line: the endpoint prices one delivery
3350
+ // rate for the whole instant order.
3351
+ ...shippingMethodTitle != null ? { shippingMethodTitle } : {}
3352
+ })
3353
+ }
3354
+ );
3355
+ if (!res.ok) {
3356
+ if (res.status === 404) {
3357
+ return { _tag: "Failure", error: { kind: "SUBSCRIPTION_NOT_FOUND" } };
3358
+ }
3359
+ const message = await readErrorMessage(res);
3360
+ const kind = PLACE_INSTANT_ORDER_ERROR_KINDS[res.status] ?? "UNKNOWN";
3361
+ return {
3362
+ _tag: "Failure",
3363
+ error: { kind, message: message ?? `HTTP ${res.status}` }
3364
+ };
3365
+ }
3366
+ const body = await res.json().catch(() => null);
3367
+ if (body == null) {
3368
+ return {
3369
+ _tag: "Failure",
3370
+ error: { kind: "UNKNOWN", message: "Malformed response" }
3371
+ };
3372
+ }
3373
+ return {
3374
+ _tag: "Success",
3375
+ data: {
3376
+ orderId: body.orderId,
3377
+ totalPrice: body.totalPrice ?? null,
3378
+ currencyCode: body.currencyCode,
3379
+ status: body.status,
3380
+ ...body.paymentUrl != null ? { paymentUrl: body.paymentUrl } : {},
3381
+ ...body.reason != null ? { reason: body.reason } : {}
3382
+ }
3383
+ };
3384
+ } catch (e) {
3385
+ return {
3386
+ _tag: "Failure",
3387
+ error: {
3388
+ kind: "NETWORK",
3389
+ message: e instanceof Error ? e.message : void 0
3390
+ }
3391
+ };
2236
3392
  }
2237
3393
  },
2238
3394
  // Legacy endpoint — no /customer/v1 equivalent exists yet.
@@ -2248,8 +3404,8 @@ function createApiSubscriptionAdapter(fetcher) {
2248
3404
  _tag: "Success",
2249
3405
  data: { id: data.id, createdAt: data.createdAt }
2250
3406
  };
2251
- } catch (e2) {
2252
- return { _tag: "Failure", error: e2 };
3407
+ } catch (e) {
3408
+ return { _tag: "Failure", error: e };
2253
3409
  }
2254
3410
  },
2255
3411
  // Legacy endpoints, split by stage (see SubscriptionService.renewNow docs):
@@ -2269,8 +3425,8 @@ function createApiSubscriptionAdapter(fetcher) {
2269
3425
  result: (body == null ? void 0 : body.result) ?? "success"
2270
3426
  }
2271
3427
  };
2272
- } catch (e2) {
2273
- return { _tag: "Failure", error: e2 };
3428
+ } catch (e) {
3429
+ return { _tag: "Failure", error: e };
2274
3430
  }
2275
3431
  },
2276
3432
  // Legacy endpoint — POST /plan returns 204; re-fetch to return the updated subscription.
@@ -2292,8 +3448,8 @@ function createApiSubscriptionAdapter(fetcher) {
2292
3448
  _tag: "Failure",
2293
3449
  error: "Subscription not found after frequency change"
2294
3450
  };
2295
- } catch (e2) {
2296
- return { _tag: "Failure", error: e2 };
3451
+ } catch (e) {
3452
+ return { _tag: "Failure", error: e };
2297
3453
  }
2298
3454
  }
2299
3455
  };
@@ -2354,13 +3510,13 @@ function mapScheduleOrder(order) {
2354
3510
  };
2355
3511
  }),
2356
3512
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2357
- discounts: (order.discounts ?? []).map((d3) => {
3513
+ discounts: (order.discounts ?? []).map((d2) => {
2358
3514
  var _a, _b, _c;
2359
3515
  return {
2360
- id: d3.id,
2361
- title: d3.title ?? void 0,
2362
- type: ((_a = d3.value) == null ? void 0 : _a.type) === "fixed-amount" ? "fixed_amount" : "percentage",
2363
- value: ((_b = d3.value) == null ? void 0 : _b.amount) ?? ((_c = d3.value) == null ? void 0 : _c.percentage) ?? 0
3516
+ id: d2.id,
3517
+ title: d2.title ?? void 0,
3518
+ type: ((_a = d2.value) == null ? void 0 : _a.type) === "fixed-amount" ? "fixed_amount" : "percentage",
3519
+ value: ((_b = d2.value) == null ? void 0 : _b.amount) ?? ((_c = d2.value) == null ? void 0 : _c.percentage) ?? 0
2364
3520
  };
2365
3521
  })
2366
3522
  };
@@ -2399,26 +3555,26 @@ function buildSkipItemMatcher(params) {
2399
3555
  const DELIVERY_PRICE = 5;
2400
3556
  const DELIVERY_OFFSET_DAYS = 2;
2401
3557
  function toPrice(amount) {
2402
- const n = Number.parseFloat(amount ?? "0");
2403
- return Number.isFinite(n) ? n : 0;
3558
+ const n2 = Number.parseFloat(amount ?? "0");
3559
+ return Number.isFinite(n2) ? n2 : 0;
2404
3560
  }
2405
3561
  function addInterval(date, interval, units) {
2406
- const d3 = new Date(date);
3562
+ const d2 = new Date(date);
2407
3563
  switch (interval) {
2408
3564
  case "DAY":
2409
- d3.setDate(d3.getDate() + units);
3565
+ d2.setDate(d2.getDate() + units);
2410
3566
  break;
2411
3567
  case "WEEK":
2412
- d3.setDate(d3.getDate() + units * 7);
3568
+ d2.setDate(d2.getDate() + units * 7);
2413
3569
  break;
2414
3570
  case "YEAR":
2415
- d3.setFullYear(d3.getFullYear() + units);
3571
+ d2.setFullYear(d2.getFullYear() + units);
2416
3572
  break;
2417
3573
  default:
2418
- d3.setMonth(d3.getMonth() + units);
3574
+ d2.setMonth(d2.getMonth() + units);
2419
3575
  break;
2420
3576
  }
2421
- return d3;
3577
+ return d2;
2422
3578
  }
2423
3579
  function mapItem(sub, item, cycle) {
2424
3580
  var _a, _b;
@@ -2476,11 +3632,11 @@ function projectUpcomingOrders(sub, count) {
2476
3632
  deliveryDate: deliveryDate.toISOString(),
2477
3633
  status: "scheduled",
2478
3634
  items,
2479
- discounts: sub.discounts.map((d3) => ({
2480
- id: d3.id,
2481
- title: d3.code,
2482
- type: d3.type,
2483
- value: d3.value
3635
+ discounts: sub.discounts.map((d2) => ({
3636
+ id: d2.id,
3637
+ title: d2.code,
3638
+ type: d2.type,
3639
+ value: d2.value
2484
3640
  }))
2485
3641
  });
2486
3642
  }
@@ -2508,7 +3664,7 @@ function applyAdjustments(orders, stored) {
2508
3664
  );
2509
3665
  const subtotal = items.reduce((sum, it) => sum + it.totalPrice, 0);
2510
3666
  next = { ...next, items, subtotal };
2511
- if (items.length > 0 && items.every((i2) => i2.skipped)) {
3667
+ if (items.length > 0 && items.every((i3) => i3.skipped)) {
2512
3668
  next = { ...next, skipped: true, status: "skipped", deliveryPrice: 0 };
2513
3669
  }
2514
3670
  }
@@ -2543,11 +3699,11 @@ function createMockSchedulesAdapter(subscriptions = createMockSubscriptionAdapte
2543
3699
  const iso = toIsoOrNull(opts.date);
2544
3700
  const target = iso == null ? void 0 : iso.split("T")[0];
2545
3701
  const match = target ? orders.find(
2546
- (o2) => o2.deliveryDate.split("T")[0] === target || o2.date.split("T")[0] === target
3702
+ (o3) => o3.deliveryDate.split("T")[0] === target || o3.date.split("T")[0] === target
2547
3703
  ) : void 0;
2548
3704
  return match ? match.cycleIndex : null;
2549
3705
  }
2550
- const firstScheduled = orders.find((o2) => o2.status === "scheduled");
3706
+ const firstScheduled = orders.find((o3) => o3.status === "scheduled");
2551
3707
  return (firstScheduled == null ? void 0 : firstScheduled.cycleIndex) ?? null;
2552
3708
  }
2553
3709
  async function recordAdjustment(subscriptionId, opts, buildAction, matcherOverride) {
@@ -2580,25 +3736,25 @@ function createMockSchedulesAdapter(subscriptions = createMockSubscriptionAdapte
2580
3736
  const subs = await subscriptionsToProject(subscriptionId);
2581
3737
  const skipCount = new Set(
2582
3738
  stored.filter(
2583
- (s) => s.adjustment.action.type === "SKIP_ORDER" || s.adjustment.action.type === "SKIP_ITEM"
2584
- ).map((s) => `${s.subscriptionId}:${s.cycle}`)
3739
+ (s2) => s2.adjustment.action.type === "SKIP_ORDER" || s2.adjustment.action.type === "SKIP_ITEM"
3740
+ ).map((s2) => `${s2.subscriptionId}:${s2.cycle}`)
2585
3741
  ).size;
2586
3742
  const depth = excludeSkipped ? count + skipCount : count;
2587
3743
  const orders = subs.flatMap(
2588
3744
  (sub) => applyAdjustments(projectUpcomingOrders(sub, depth), stored)
2589
- ).filter((o2) => excludeSkipped ? !o2.skipped : true).map(
2590
- (o2) => (
3745
+ ).filter((o3) => excludeSkipped ? !o3.skipped : true).map(
3746
+ (o3) => (
2591
3747
  // Mirror backend removeSkippedItems: the billable view also strips
2592
3748
  // skipped lines from surviving (partially-skipped) orders. No
2593
3749
  // recompute needed — skipped lines already carry totalPrice 0 (R4).
2594
- excludeSkipped && o2.items.some((i2) => i2.skipped) ? { ...o2, items: o2.items.filter((i2) => !i2.skipped) } : o2
3750
+ excludeSkipped && o3.items.some((i3) => i3.skipped) ? { ...o3, items: o3.items.filter((i3) => !i3.skipped) } : o3
2595
3751
  )
2596
- ).sort((a8, b2) => a8.date.localeCompare(b2.date));
3752
+ ).sort((a2, b3) => a2.date.localeCompare(b3.date));
2597
3753
  return { _tag: "Success", data: orders.slice(0, count) };
2598
3754
  },
2599
3755
  async getAdjustments() {
2600
3756
  await new Promise((r2) => setTimeout(r2, 200));
2601
- return { _tag: "Success", data: stored.map((s) => s.adjustment) };
3757
+ return { _tag: "Success", data: stored.map((s2) => s2.adjustment) };
2602
3758
  },
2603
3759
  async skipOrder({ subscriptionId, cycle, date }) {
2604
3760
  await new Promise((r2) => setTimeout(r2, 300));
@@ -2671,7 +3827,7 @@ function createMockSchedulesAdapter(subscriptions = createMockSubscriptionAdapte
2671
3827
  },
2672
3828
  async removeAdjustment({ adjustmentId }) {
2673
3829
  await new Promise((r2) => setTimeout(r2, 200));
2674
- stored = stored.filter((s) => s.adjustment.id !== adjustmentId);
3830
+ stored = stored.filter((s2) => s2.adjustment.id !== adjustmentId);
2675
3831
  return { _tag: "Success", data: void 0 };
2676
3832
  }
2677
3833
  };
@@ -2686,8 +3842,8 @@ function createApiSchedulesAdapter(fetcher) {
2686
3842
  });
2687
3843
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2688
3844
  return { _tag: "Success", data: void 0 };
2689
- } catch (e2) {
2690
- return { _tag: "Failure", error: e2 };
3845
+ } catch (e) {
3846
+ return { _tag: "Failure", error: e };
2691
3847
  }
2692
3848
  }
2693
3849
  return {
@@ -2700,8 +3856,8 @@ function createApiSchedulesAdapter(fetcher) {
2700
3856
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2701
3857
  const data = await res.json();
2702
3858
  return { _tag: "Success", data: (data.orders ?? []).map(mapScheduleOrder) };
2703
- } catch (e2) {
2704
- return { _tag: "Failure", error: e2 };
3859
+ } catch (e) {
3860
+ return { _tag: "Failure", error: e };
2705
3861
  }
2706
3862
  },
2707
3863
  async getAdjustments() {
@@ -2717,10 +3873,10 @@ function createApiSchedulesAdapter(fetcher) {
2717
3873
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2718
3874
  const body = await res.json();
2719
3875
  all.push(
2720
- ...body.data.map((a8) => ({
2721
- id: a8.id,
2722
- matcher: a8.matcher,
2723
- action: a8.action
3876
+ ...body.data.map((a2) => ({
3877
+ id: a2.id,
3878
+ matcher: a2.matcher,
3879
+ action: a2.action
2724
3880
  }))
2725
3881
  );
2726
3882
  if (!body.hasNextPage) return { _tag: "Success", data: all };
@@ -2736,8 +3892,8 @@ function createApiSchedulesAdapter(fetcher) {
2736
3892
  _tag: "Failure",
2737
3893
  error: "Adjustments pagination exceeded 50 pages"
2738
3894
  };
2739
- } catch (e2) {
2740
- return { _tag: "Failure", error: e2 };
3895
+ } catch (e) {
3896
+ return { _tag: "Failure", error: e };
2741
3897
  }
2742
3898
  },
2743
3899
  async skipOrder({ cycle, date }) {
@@ -2813,16 +3969,16 @@ function createApiSchedulesAdapter(fetcher) {
2813
3969
  );
2814
3970
  if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2815
3971
  return { _tag: "Success", data: void 0 };
2816
- } catch (e2) {
2817
- return { _tag: "Failure", error: e2 };
3972
+ } catch (e) {
3973
+ return { _tag: "Failure", error: e };
2818
3974
  }
2819
3975
  }
2820
3976
  };
2821
3977
  }
2822
3978
  const SchedulesServiceContext = createContext("services/schedules");
2823
- function isSameCalendarDay(a8, b2) {
2824
- const da = new Date(a8);
2825
- const db = new Date(b2);
3979
+ function isSameCalendarDay(a2, b3) {
3980
+ const da = new Date(a2);
3981
+ const db = new Date(b3);
2826
3982
  if (Number.isNaN(da.getTime()) || Number.isNaN(db.getTime())) return false;
2827
3983
  return da.toISOString().slice(0, 10) === db.toISOString().slice(0, 10);
2828
3984
  }
@@ -2902,26 +4058,26 @@ function createSchedulesService(adapter, opts) {
2902
4058
  const adjustments = await adapter.getAdjustments();
2903
4059
  if (adjustments._tag === "Failure") return adjustments;
2904
4060
  const covering = adjustments.data.filter(
2905
- (a8) => a8.action.type === "SKIP_ITEM" && a8.action.input.lineIds.includes(lineId) && matcherAffects(a8.matcher, { cycle, date })
4061
+ (a2) => a2.action.type === "SKIP_ITEM" && a2.action.input.lineIds.includes(lineId) && matcherAffects(a2.matcher, { cycle, date })
2906
4062
  );
2907
4063
  if (covering.length === 0) {
2908
4064
  return { _tag: "Failure", error: "No skip found for this item" };
2909
4065
  }
2910
- if (covering.some((a8) => a8.action.input.lineIds.length > 1)) {
4066
+ if (covering.some((a2) => a2.action.input.lineIds.length > 1)) {
2911
4067
  return {
2912
4068
  _tag: "Failure",
2913
4069
  error: "This item was skipped together with other items and can't be unskipped individually"
2914
4070
  };
2915
4071
  }
2916
- if (covering.some((a8) => !matcherExactlyTargets(a8.matcher, { cycle, date }))) {
4072
+ if (covering.some((a2) => !matcherExactlyTargets(a2.matcher, { cycle, date }))) {
2917
4073
  return {
2918
4074
  _tag: "Failure",
2919
4075
  error: "This skip also affects another order and can't be removed from here"
2920
4076
  };
2921
4077
  }
2922
4078
  let deleted = 0;
2923
- for (const a8 of covering) {
2924
- const result = await adapter.removeAdjustment({ adjustmentId: a8.id });
4079
+ for (const a2 of covering) {
4080
+ const result = await adapter.removeAdjustment({ adjustmentId: a2.id });
2925
4081
  if (result._tag === "Failure") {
2926
4082
  if (deleted > 0) await notifyChanged(subscriptionId);
2927
4083
  return result;
@@ -3005,6 +4161,19 @@ function getCurrentSubscriptionId() {
3005
4161
  }
3006
4162
  return null;
3007
4163
  }
4164
+ async function countRatesTitled(adapter, subscriptionId, title) {
4165
+ try {
4166
+ const available = await adapter.getAvailableShippingMethods({
4167
+ subscriptionId
4168
+ });
4169
+ if (available._tag !== "Success") {
4170
+ return 0;
4171
+ }
4172
+ return available.data.filter((option) => option.title === title).length;
4173
+ } catch {
4174
+ return 0;
4175
+ }
4176
+ }
3008
4177
  function createSubscriptionService(adapter) {
3009
4178
  const current = d(null);
3010
4179
  const hasPendingBilling = w(
@@ -3139,6 +4308,27 @@ function createSubscriptionService(adapter) {
3139
4308
  },
3140
4309
  reschedule: (subscriptionId, newDate) => adapter.reschedule({ subscriptionId, newDate }),
3141
4310
  updateCustomAttributes: (subscriptionId, customAttributes) => adapter.updateCustomAttributes({ subscriptionId, customAttributes }),
4311
+ updateDeliveryAddress: async (subscriptionId, address) => {
4312
+ const result = await adapter.updateDeliveryAddress({
4313
+ subscriptionId,
4314
+ address
4315
+ });
4316
+ if (result._tag === "Success") {
4317
+ await reload();
4318
+ }
4319
+ return result;
4320
+ },
4321
+ getAvailableShippingMethods: (subscriptionId) => adapter.getAvailableShippingMethods({ subscriptionId }),
4322
+ updateDeliveryMethod: async (subscriptionId, shippingMethodHandle) => {
4323
+ const result = await adapter.updateDeliveryMethod({
4324
+ subscriptionId,
4325
+ shippingMethodHandle
4326
+ });
4327
+ if (result._tag === "Success") {
4328
+ await reload();
4329
+ }
4330
+ return result;
4331
+ },
3142
4332
  resume: (subscriptionId) => adapter.resume({ subscriptionId }),
3143
4333
  pause: (subscriptionId) => adapter.pause({ subscriptionId }),
3144
4334
  reactivate: (subscriptionId) => adapter.reactivate({ subscriptionId }),
@@ -3155,37 +4345,114 @@ function createSubscriptionService(adapter) {
3155
4345
  data: {
3156
4346
  available: false,
3157
4347
  requiresCheckout: false,
3158
- paymentMethods: [],
3159
4348
  products: [],
3160
4349
  hasNextPage: false,
3161
4350
  endCursor: null
3162
4351
  }
3163
4352
  }),
3164
- placeInstantOrder: (subscriptionId, requestKey, items, paymentMethodId) => adapter.placeInstantOrder ? adapter.placeInstantOrder({
3165
- subscriptionId,
3166
- requestKey,
3167
- items,
3168
- paymentMethodId
3169
- }) : (
3170
- // Distinguishable from every server-side refusal, so a consumer can
3171
- // treat "this host cannot do instant orders" as a missing capability
3172
- // rather than telling the customer their order was declined.
3173
- Promise.resolve({
3174
- _tag: "Failure",
3175
- error: { kind: "UNSUPPORTED" }
3176
- })
3177
- ),
3178
- getInstantOrder: (subscriptionId, orderId) => adapter.getInstantOrder ? adapter.getInstantOrder({ subscriptionId, orderId }) : Promise.resolve({
3179
- _tag: "Failure",
3180
- error: { kind: "UNSUPPORTED" }
3181
- })
4353
+ placeInstantOrder: async (subscriptionId, requestKey, items, options) => {
4354
+ const placeOrder = adapter.placeInstantOrder;
4355
+ if (!placeOrder) {
4356
+ return {
4357
+ _tag: "Failure",
4358
+ error: { kind: "UNSUPPORTED" }
4359
+ };
4360
+ }
4361
+ const chosenTitle = options == null ? void 0 : options.shippingMethodTitle;
4362
+ if (chosenTitle != null) {
4363
+ const matches = await countRatesTitled(
4364
+ adapter,
4365
+ subscriptionId,
4366
+ chosenTitle
4367
+ );
4368
+ if (matches > 1) {
4369
+ return {
4370
+ _tag: "Failure",
4371
+ error: {
4372
+ kind: "AMBIGUOUS_SHIPPING_METHOD",
4373
+ message: `${matches} available shipping methods are titled "${chosenTitle}", so the title cannot say which one was chosen.`
4374
+ }
4375
+ };
4376
+ }
4377
+ }
4378
+ return placeOrder({ subscriptionId, requestKey, items, ...options });
4379
+ }
3182
4380
  };
3183
4381
  return service;
3184
4382
  }
4383
+ function isOneTimeLine(line) {
4384
+ return line.isOneTime === true || line.recurringCycleLimit === 1;
4385
+ }
4386
+ function hasValue(value) {
4387
+ return typeof value === "string" && value.length > 0;
4388
+ }
4389
+ function hasIdentity(line) {
4390
+ return hasValue(line.subscriptionId) && hasValue(line.subscriptionLineId);
4391
+ }
4392
+ function isSameLine(a2, b3) {
4393
+ return hasValue(a2.subscriptionLineId) && a2.subscriptionLineId === b3.subscriptionLineId;
4394
+ }
4395
+ function belongsToSameSubscription(a2, b3) {
4396
+ return hasValue(a2.subscriptionId) && a2.subscriptionId === b3.subscriptionId;
4397
+ }
4398
+ function parentLineFor(child, lines) {
4399
+ if (!hasValue(child.parentLineId)) {
4400
+ return void 0;
4401
+ }
4402
+ return lines.find(
4403
+ (candidate) => belongsToSameSubscription(candidate, child) && (candidate.subscriptionLineId === child.parentLineId || candidate.id === child.parentLineId)
4404
+ );
4405
+ }
4406
+ function productKey(line, lines) {
4407
+ if (hasValue(line.parentProductId)) {
4408
+ return `product:${line.parentProductId}`;
4409
+ }
4410
+ if (hasValue(line.parentLineId)) {
4411
+ const parent = parentLineFor(line, lines);
4412
+ if (hasValue(parent == null ? void 0 : parent.productId)) {
4413
+ return `product:${parent.productId}`;
4414
+ }
4415
+ return `line:${line.parentLineId}`;
4416
+ }
4417
+ const lineIdentity = hasValue(line.subscriptionLineId) ? line.subscriptionLineId : line.id;
4418
+ if (!hasValue(lineIdentity)) {
4419
+ return null;
4420
+ }
4421
+ const isReferencedAsParent = lines.some(
4422
+ (candidate) => belongsToSameSubscription(candidate, line) && (hasValue(line.productId) && candidate.parentProductId === line.productId || hasValue(candidate.parentLineId) && (candidate.parentLineId === line.subscriptionLineId || candidate.parentLineId === line.id))
4423
+ );
4424
+ if (isReferencedAsParent && hasValue(line.productId)) {
4425
+ return `product:${line.productId}`;
4426
+ }
4427
+ return `line:${lineIdentity}`;
4428
+ }
4429
+ function remainingRecurringProductKeys(line, lines) {
4430
+ const removedProductKey = productKey(line, lines);
4431
+ return new Set(
4432
+ lines.filter(
4433
+ (item) => belongsToSameSubscription(item, line) && !isOneTimeLine(item)
4434
+ ).map((item) => productKey(item, lines)).filter((key) => key != null && key !== removedProductKey)
4435
+ );
4436
+ }
4437
+ function canRemoveLine(line, lines) {
4438
+ if (!hasIdentity(line)) {
4439
+ return false;
4440
+ }
4441
+ const targetExists = lines.some(
4442
+ (item) => belongsToSameSubscription(item, line) && isSameLine(item, line)
4443
+ );
4444
+ if (!targetExists) {
4445
+ return false;
4446
+ }
4447
+ if (isOneTimeLine(line)) {
4448
+ return true;
4449
+ }
4450
+ return remainingRecurringProductKeys(line, lines).size > 0;
4451
+ }
3185
4452
  function getDefaultBlockForAction(actionType, actionConfig, blockId) {
3186
4453
  const blockName = `action:${actionType}`;
3187
4454
  const definedBlocks = getDefinedBlocks();
3188
- const exists = definedBlocks.some((b2) => b2.name === blockName);
4455
+ const exists = definedBlocks.some((b3) => b3.name === blockName);
3189
4456
  if (!exists) {
3190
4457
  throw new Error(
3191
4458
  `No default block registered for action type "${actionType}". Expected a block named "${blockName}" to be registered in blocks-extensions.`
@@ -3195,7 +4462,7 @@ function getDefaultBlockForAction(actionType, actionConfig, blockId) {
3195
4462
  }
3196
4463
  function hasDefaultBlockForAction(actionType) {
3197
4464
  const blockName = `action:${actionType}`;
3198
- return getDefinedBlocks().some((b2) => b2.name === blockName);
4465
+ return getDefinedBlocks().some((b3) => b3.name === blockName);
3199
4466
  }
3200
4467
  const WorkflowServiceContext = createContext("services/workflow");
3201
4468
  const RUN_SCOPED_RESET = {
@@ -3333,7 +4600,7 @@ function createWorkflowService(deps) {
3333
4600
  outcome: null
3334
4601
  });
3335
4602
  if (editor.isEditorMode) {
3336
- const displayStepId = isInitialResponse && previewStepId && ((_e = data.interactiveSteps) == null ? void 0 : _e.some((s) => s.stepId === previewStepId)) ? previewStepId : currentStepId;
4603
+ const displayStepId = isInitialResponse && previewStepId && ((_e = data.interactiveSteps) == null ? void 0 : _e.some((s2) => s2.stepId === previewStepId)) ? previewStepId : currentStepId;
3337
4604
  const overlayBlocks = deps.themeState.overlay.blocks.value;
3338
4605
  const rootBlock = overlayBlocks[0];
3339
4606
  const stepSlot = displayStepId ? (_f = rootBlock == null ? void 0 : rootBlock.slots) == null ? void 0 : _f[displayStepId] : null;
@@ -3428,7 +4695,7 @@ function createWorkflowService(deps) {
3428
4695
  const presets = {};
3429
4696
  const baseLabelFor = (step) => {
3430
4697
  var _a;
3431
- return ((_a = getDefinedBlocks().find((b2) => b2.name === `action:${step.actionType}`)) == null ? void 0 : _a.displayName) ?? step.stepId;
4698
+ return ((_a = getDefinedBlocks().find((b3) => b3.name === `action:${step.actionType}`)) == null ? void 0 : _a.displayName) ?? step.stepId;
3432
4699
  };
3433
4700
  const totalCounts = /* @__PURE__ */ new Map();
3434
4701
  for (const step of allSteps) {
@@ -4023,9 +5290,9 @@ const gridV1Engine = {
4023
5290
  case "resize": {
4024
5291
  const current = layout.items[cmd.blockId];
4025
5292
  if (current) {
4026
- const w3 = Math.max(1, Math.min(cmd.size.w, ctx2.cols - current.c));
4027
- const h = Math.max(1, cmd.size.h);
4028
- layout.items[cmd.blockId] = { ...current, w: w3, h };
5293
+ const w4 = Math.max(1, Math.min(cmd.size.w, ctx2.cols - current.c));
5294
+ const h2 = Math.max(1, cmd.size.h);
5295
+ layout.items[cmd.blockId] = { ...current, w: w4, h: h2 };
4029
5296
  }
4030
5297
  break;
4031
5298
  }
@@ -4092,7 +5359,7 @@ function insertRectRelative(doc, args) {
4092
5359
  if (!layout) continue;
4093
5360
  const target = layout.items[args.targetId];
4094
5361
  if (!target) continue;
4095
- const cols = ((_a = doc.breakpoints.find((b2) => b2.id === breakpointId)) == null ? void 0 : _a.cols) ?? ((_b = layout.grid) == null ? void 0 : _b.cols) ?? DEFAULT_GRID.cols;
5362
+ const cols = ((_a = doc.breakpoints.find((b3) => b3.id === breakpointId)) == null ? void 0 : _a.cols) ?? ((_b = layout.grid) == null ? void 0 : _b.cols) ?? DEFAULT_GRID.cols;
4096
5363
  const insertRow = args.position === "before" ? target.r : target.r + target.h;
4097
5364
  for (const [id, rect] of Object.entries(layout.items)) {
4098
5365
  if (id === args.blockId) continue;
@@ -4143,20 +5410,23 @@ export {
4143
5410
  AuthenticationError,
4144
5411
  AuthenticationErrorReason,
4145
5412
  B as BlockWrapperEvent,
4146
- v as ContextProvideEvent,
4147
- x as ContextRequestEvent,
5413
+ q as ContextProvideEvent,
5414
+ t as ContextRequestEvent,
4148
5415
  CustomerServiceContext,
4149
- y as DEFAULT_BREAKPOINTS,
4150
- z as DEFAULT_GLOBAL_STYLES,
5416
+ h as DEFAULT_BREAKPOINTS,
5417
+ i2 as DEFAULT_GLOBAL_STYLES,
4151
5418
  DEFAULT_GRID,
4152
5419
  DEFAULT_NEW_BLOCK_HEIGHT,
4153
5420
  DISCOUNT_REJECTION_REASONS,
4154
5421
  GRID_V1_ENGINE_ID,
4155
- L as LAYOUT_SCOPE_ATTR,
5422
+ L2 as LAYOUT_SCOPE_ATTR,
4156
5423
  LoginServiceContext,
4157
- OrdersServiceContext,
5424
+ OrderServiceContext,
5425
+ OverlayServiceContext,
4158
5426
  P as PAGE_ROOT_SLOT,
5427
+ PAYMENT_INSTRUMENT_TYPES,
4159
5428
  ProductServiceContext,
5429
+ REFRESH_LOCK_NAME,
4160
5430
  RouterServiceContext,
4161
5431
  SUPPORTED_UI_LANGUAGES,
4162
5432
  SUPPORTED_UI_LANGUAGE_OPTIONS,
@@ -4167,101 +5437,118 @@ export {
4167
5437
  u as Signal,
4168
5438
  StateContext,
4169
5439
  SubscriptionServiceContext,
4170
- c as ThemeStateContext,
5440
+ a as ThemeStateContext,
4171
5441
  T as TranslationContext,
4172
5442
  WorkflowServiceContext,
4173
- A as attachEmptyTracking,
4174
- authenticationErrorFromBody,
4175
- d2 as backfillInstanceDefaults,
4176
- b as buildGridLayout,
4177
- F as buildLayoutCss,
5443
+ v as __recordDevtoolsInstance,
5444
+ _ as __recordDevtoolsPropSetter,
5445
+ x as attachEmptyTracking,
5446
+ c as backfillInstanceDefaults,
5447
+ b2 as buildGridLayout,
5448
+ j as buildLayoutCss,
5449
+ buildOrdersQuery,
5450
+ canRemoveLine,
4178
5451
  canvasMode,
4179
5452
  clampRect,
4180
- H as classifyRowDividers,
5453
+ k2 as classifyRowDividers,
4181
5454
  clearAllSurfaceContexts,
4182
5455
  clearLayoutModeAdapter,
4183
5456
  compactItems,
4184
- I as compactLayoutDocument,
5457
+ l2 as compactLayoutDocument,
4185
5458
  w as computed,
4186
5459
  createApiCustomerAdapter,
4187
5460
  createApiLoginAdapter,
4188
- createApiOrdersAdapter,
5461
+ createApiOrderAdapter,
4189
5462
  createApiProductAdapter,
4190
5463
  createApiSchedulesAdapter,
4191
5464
  createApiSubscriptionAdapter,
4192
5465
  createBlockInstance,
4193
- J as createBlockInstanceFromJSON,
4194
- K as createBlockInstanceFromObject,
4195
- N as createCeRenderer,
5466
+ y as createBlockInstanceFromJSON,
5467
+ g as createBlockInstanceFromObject,
5468
+ z as createCeRenderer,
4196
5469
  createContext,
4197
5470
  createCustomerService,
4198
- O as createDefaultLayoutDocument,
5471
+ m as createDefaultLayoutDocument,
4199
5472
  createLoginService,
4200
5473
  createMockCustomerAdapter,
4201
5474
  createMockLoginAdapter,
4202
- createMockOrdersAdapter,
5475
+ createMockOrderAdapter,
4203
5476
  createMockProductAdapter,
4204
5477
  createMockRouterService,
4205
5478
  createMockSchedulesAdapter,
4206
5479
  createMockSubscriptionAdapter,
4207
5480
  createMockWorkflowApiAdapter,
4208
- createOrdersService,
5481
+ createOrderService,
5482
+ createOverlayService,
4209
5483
  createProductService,
4210
5484
  createRouterService,
4211
5485
  createSchedulesService,
4212
- Q as createSelectedBlock,
5486
+ A as createSelectedBlock,
4213
5487
  createSettingsService,
4214
5488
  createShopService,
4215
5489
  createState,
4216
5490
  createSubscriptionService,
4217
- R as createThemeState,
4218
- U as createTranslationService,
5491
+ n as createThemeState,
5492
+ o2 as createTranslationService,
4219
5493
  createWorkflowApiAdapter,
4220
5494
  createWorkflowService,
4221
5495
  defineBlock,
4222
- V as defineBlockRuntime,
4223
- W as deriveLayout,
5496
+ D as defineBlockRuntime,
5497
+ defineOverlayWrapper,
5498
+ p as deriveLayout,
4224
5499
  E as effect,
4225
5500
  emitLayoutCommand,
4226
5501
  emitLayoutSetRects,
4227
- X as expandFillLayoutDocument,
5502
+ q2 as expandFillLayoutDocument,
4228
5503
  findFreeRect,
5504
+ fromV1Customer,
4229
5505
  getActiveSurfaceContext,
4230
5506
  getDefaultBlockForAction,
4231
5507
  getDefinedBlocks,
5508
+ F as getDevtoolsBlockState,
4232
5509
  getLayoutModeAdapter,
5510
+ getPaymentInstrumentDetail,
5511
+ getPaymentInstrumentDigits,
5512
+ getPaymentInstrumentExpiry,
5513
+ getPaymentInstrumentName,
4233
5514
  gridV1Engine,
4234
5515
  hasDefaultBlockForAction,
4235
- Y as hasRenderedContent,
4236
- Z as indexOverrides,
5516
+ G as hasRenderedContent,
5517
+ s as indexOverrides,
4237
5518
  i as injectContext,
4238
5519
  insertRectRelative,
4239
- _ as isEditorPreview,
4240
- a as isStubDefinition,
4241
- $ as layoutScopeSelector,
4242
- a0 as layoutSystemEnabled,
5520
+ H as isEditorPreview,
5521
+ isFilterQuery,
5522
+ isOneTimeLine,
5523
+ isStaleSubscriptionMessage,
5524
+ b as isStubDefinition,
5525
+ t2 as layoutScopeSelector,
5526
+ I as layoutSystemEnabled,
4243
5527
  loadBlockRegistry,
4244
5528
  loginService,
4245
5529
  o as onRegisterBlock,
4246
- a1 as projectToCss,
4247
- p as projectToGridStack,
4248
- a2 as provideContext,
4249
- a3 as readingOrder,
4250
- e as reconcileLayout,
4251
- a4 as rectsOverlap,
5530
+ u2 as projectToCss,
5531
+ p2 as projectToGridStack,
5532
+ J as provideContext,
5533
+ v2 as readingOrder,
5534
+ c2 as reconcileLayout,
5535
+ w3 as rectsOverlap,
4252
5536
  registerBlock,
4253
5537
  registerLayoutModeAdapter,
4254
5538
  resetBreakpoint,
4255
5539
  r as resolveLayout,
4256
- a5 as serializeBlocks,
5540
+ k as serializeBlocks,
5541
+ serializeV1PaymentInstrument,
4257
5542
  setActiveSurfaceContext,
5543
+ K as setDevtoolsBlockProp,
4258
5544
  setLayoutCommandDispatcher,
4259
5545
  setLayoutCommandEmitter,
4260
- a6 as setLayoutSystemEnabled,
5546
+ l as setLayoutSystemEnabled,
4261
5547
  d as signal,
4262
5548
  subscribeContext,
4263
5549
  toLanguageSelectOptions,
4264
- a7 as untracked,
5550
+ L as untracked,
4265
5551
  waitForDevBlocksUrl,
5552
+ withRefreshLock,
4266
5553
  w2 as withWrapper
4267
5554
  };