@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.
- package/dist/{ExtensionRoot-DfpvN94s.js → ExtensionRoot-CG9dH98z.js} +24 -6
- package/dist/block-BjJztStr.js +993 -0
- package/dist/{block-dVP4Rqgz.js → block-DnhzyZ1H.js} +29 -3
- package/dist/block.d.ts +56 -0
- package/dist/block.d.ts.map +1 -1
- package/dist/{bridge-4Eq-G73Z.js → bridge-Bss7Xq3D.js} +39 -31
- package/dist/core.js +1620 -333
- package/dist/css-runtime-CjZl0K48.js +755 -0
- package/dist/devtools/hook.d.ts +0 -5
- package/dist/devtools/hook.d.ts.map +1 -1
- package/dist/devtools/index.d.ts +0 -1
- package/dist/devtools/index.d.ts.map +1 -1
- package/dist/devtools/protocol.d.ts +15 -1
- package/dist/devtools/protocol.d.ts.map +1 -1
- package/dist/devtools.js +42 -9
- package/dist/editor/bridge.d.ts +7 -7
- package/dist/editor/bridge.d.ts.map +1 -1
- package/dist/editor/components.d.ts.map +1 -1
- package/dist/editor/main.d.ts +2 -1
- package/dist/editor/main.d.ts.map +1 -1
- package/dist/editor/messages.d.ts +13 -2
- package/dist/editor/messages.d.ts.map +1 -1
- package/dist/editor/overlays.d.ts +14 -0
- package/dist/editor/overlays.d.ts.map +1 -0
- package/dist/editor/overlays.test.d.ts +2 -0
- package/dist/editor/overlays.test.d.ts.map +1 -0
- package/dist/editor.js +47 -33
- package/dist/{gridstack-adapter-BZWybRw1.js → gridstack-adapter-C1Q8gbsH.js} +2 -2
- package/dist/main.d.ts +3 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/{morph-DHn3ol8M.js → morph-LwttdRML.js} +1 -1
- package/dist/overlay-wrapper.d.ts +69 -0
- package/dist/overlay-wrapper.d.ts.map +1 -0
- package/dist/overlay-wrapper.test.d.ts +2 -0
- package/dist/overlay-wrapper.test.d.ts.map +1 -0
- package/dist/overlays/OverlayService.d.ts +34 -0
- package/dist/overlays/OverlayService.d.ts.map +1 -0
- package/dist/overlays/OverlayService.test.d.ts +2 -0
- package/dist/overlays/OverlayService.test.d.ts.map +1 -0
- package/dist/preact/block.d.ts.map +1 -1
- package/dist/preact/context.d.ts.map +1 -1
- package/dist/preact/context.test.d.ts +2 -0
- package/dist/preact/context.test.d.ts.map +1 -0
- package/dist/preact/signals.d.ts +19 -0
- package/dist/preact/signals.d.ts.map +1 -1
- package/dist/preact/useContextSubscription.test.d.ts +2 -0
- package/dist/preact/useContextSubscription.test.d.ts.map +1 -0
- package/dist/preact.js +33 -7
- package/dist/{project-gridstack-C2cSYRMx.js → project-gridstack-CRZ_7HoT.js} +1 -1
- package/dist/react/block.d.ts.map +1 -1
- package/dist/react/context.d.ts.map +1 -1
- package/dist/react/context.test.d.ts +2 -0
- package/dist/react/context.test.d.ts.map +1 -0
- package/dist/react/signals.d.ts +19 -0
- package/dist/react/signals.d.ts.map +1 -1
- package/dist/react/useContextSubscription.test.d.ts +2 -0
- package/dist/react/useContextSubscription.test.d.ts.map +1 -0
- package/dist/react.js +40 -8
- package/dist/services/customer/adapter.d.ts +14 -1
- package/dist/services/customer/adapter.d.ts.map +1 -1
- package/dist/services/customer/adapter.test.d.ts +2 -0
- package/dist/services/customer/adapter.test.d.ts.map +1 -0
- package/dist/services/customer/customerService.d.ts.map +1 -1
- package/dist/services/customer/customerService.test.d.ts +2 -0
- package/dist/services/customer/customerService.test.d.ts.map +1 -0
- package/dist/services/customer/index.d.ts +2 -2
- package/dist/services/customer/index.d.ts.map +1 -1
- package/dist/services/customer/types.d.ts +29 -0
- package/dist/services/customer/types.d.ts.map +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/login/adapter.d.ts +0 -10
- package/dist/services/login/adapter.d.ts.map +1 -1
- package/dist/services/login/index.d.ts +3 -3
- package/dist/services/login/index.d.ts.map +1 -1
- package/dist/services/login/loginService.d.ts +13 -1
- package/dist/services/login/loginService.d.ts.map +1 -1
- package/dist/services/login/refreshLock.d.ts +28 -0
- package/dist/services/login/refreshLock.d.ts.map +1 -0
- package/dist/services/login/refreshLock.test.d.ts +2 -0
- package/dist/services/login/refreshLock.test.d.ts.map +1 -0
- package/dist/services/order/adapter.d.ts +17 -6
- package/dist/services/order/adapter.d.ts.map +1 -1
- package/dist/services/order/adapter.test.d.ts +2 -0
- package/dist/services/order/adapter.test.d.ts.map +1 -0
- package/dist/services/order/index.d.ts +3 -4
- package/dist/services/order/index.d.ts.map +1 -1
- package/dist/services/order/orderService.d.ts +2 -3
- package/dist/services/order/orderService.d.ts.map +1 -1
- package/dist/services/order/orderService.test.d.ts +2 -0
- package/dist/services/order/orderService.test.d.ts.map +1 -0
- package/dist/services/order/types.d.ts +103 -14
- package/dist/services/order/types.d.ts.map +1 -1
- package/dist/services/product/adapter.d.ts +42 -0
- package/dist/services/product/adapter.d.ts.map +1 -1
- package/dist/services/product/index.d.ts +1 -1
- package/dist/services/product/index.d.ts.map +1 -1
- package/dist/services/settings/types.d.ts +15 -0
- package/dist/services/settings/types.d.ts.map +1 -1
- package/dist/services/subscription/adapter.d.ts +48 -7
- package/dist/services/subscription/adapter.d.ts.map +1 -1
- package/dist/services/subscription/index.d.ts +3 -1
- package/dist/services/subscription/index.d.ts.map +1 -1
- package/dist/services/subscription/instantOrderErrors.d.ts +11 -0
- package/dist/services/subscription/instantOrderErrors.d.ts.map +1 -1
- package/dist/services/subscription/lineRemoval.d.ts +56 -0
- package/dist/services/subscription/lineRemoval.d.ts.map +1 -0
- package/dist/services/subscription/lineRemoval.test.d.ts +2 -0
- package/dist/services/subscription/lineRemoval.test.d.ts.map +1 -0
- package/dist/services/subscription/paymentInstrument.d.ts +119 -0
- package/dist/services/subscription/paymentInstrument.d.ts.map +1 -0
- package/dist/services/subscription/paymentInstrument.test.d.ts +2 -0
- package/dist/services/subscription/paymentInstrument.test.d.ts.map +1 -0
- package/dist/services/subscription/store.d.ts.map +1 -1
- package/dist/services/subscription/subscriptionService.d.ts.map +1 -1
- package/dist/services/subscription/types.d.ts +265 -34
- package/dist/services/subscription/types.d.ts.map +1 -1
- package/dist/shared/context.d.ts +10 -3
- package/dist/shared/context.d.ts.map +1 -1
- package/dist/shared/touchSignals.d.ts +17 -0
- package/dist/shared/touchSignals.d.ts.map +1 -0
- package/dist/shared/touchSignals.test.d.ts +2 -0
- package/dist/shared/touchSignals.test.d.ts.map +1 -0
- package/dist/theme-state.d.ts +2 -1
- package/dist/theme-state.d.ts.map +1 -1
- package/dist/theme-state.params.test.d.ts +2 -0
- package/dist/theme-state.params.test.d.ts.map +1 -0
- package/dist/theme-state.translations.test.d.ts +2 -0
- package/dist/theme-state.translations.test.d.ts.map +1 -0
- package/dist/vue/block.d.ts.map +1 -1
- package/dist/vue.js +16 -13
- package/dist/web-components/ExtensionRoot.d.ts +1 -0
- package/dist/web-components/ExtensionRoot.d.ts.map +1 -1
- package/dist/web-components-editor.js +6 -5
- package/dist/web-components-runtime.js +3 -2
- package/package.json +1 -1
- package/dist/css-runtime-DTiXcYSs.js +0 -1576
- package/dist/devtools/instrumentation.d.ts +0 -47
- package/dist/devtools/instrumentation.d.ts.map +0 -1
- package/dist/index-JSv6UH_o.js +0 -169
- package/dist/services/login/errors.d.ts +0 -21
- package/dist/services/login/errors.d.ts.map +0 -1
- package/dist/services/orders/adapter.d.ts +0 -10
- package/dist/services/orders/adapter.d.ts.map +0 -1
- package/dist/services/orders/index.d.ts +0 -4
- package/dist/services/orders/index.d.ts.map +0 -1
- package/dist/services/orders/ordersService.d.ts +0 -6
- package/dist/services/orders/ordersService.d.ts.map +0 -1
- package/dist/services/orders/ordersService.test.d.ts +0 -2
- package/dist/services/orders/ordersService.test.d.ts.map +0 -1
- package/dist/services/orders/types.d.ts +0 -60
- 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 {
|
|
5
|
-
import { B,
|
|
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,
|
|
8
|
-
import { p } from "./project-gridstack-
|
|
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
|
-
|
|
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/
|
|
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:
|
|
484
|
+
data: fromV1Customer(await res.json())
|
|
213
485
|
};
|
|
214
|
-
} catch (
|
|
215
|
-
return { _tag: "Failure", error:
|
|
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
|
-
(
|
|
540
|
+
(c3) => (c3 ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c3 / 4).toString(16)
|
|
234
541
|
);
|
|
235
542
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
|
315
|
-
if (
|
|
316
|
-
|
|
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 (
|
|
334
|
-
return { _tag: "Failure", error:
|
|
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
|
|
350
|
-
if (
|
|
351
|
-
|
|
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 (
|
|
365
|
-
return { _tag: "Failure", error:
|
|
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
|
|
382
|
-
const storageKey = `auth:${key}`;
|
|
714
|
+
function webStorage(kind) {
|
|
383
715
|
try {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
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
|
|
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
|
-
|
|
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 =
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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((
|
|
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
|
-
|
|
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((
|
|
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((
|
|
1078
|
-
id:
|
|
1079
|
-
title:
|
|
1080
|
-
featuredImage:
|
|
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((
|
|
1550
|
+
return (data ?? []).map((p3) => {
|
|
1093
1551
|
var _a;
|
|
1094
1552
|
return {
|
|
1095
|
-
id:
|
|
1096
|
-
title:
|
|
1097
|
-
description:
|
|
1098
|
-
featuredImage:
|
|
1099
|
-
hasOnlyDefaultVariant:
|
|
1100
|
-
variants: (
|
|
1101
|
-
id:
|
|
1102
|
-
availableForSale:
|
|
1103
|
-
title:
|
|
1104
|
-
currentPrice:
|
|
1105
|
-
basePrice:
|
|
1106
|
-
image:
|
|
1107
|
-
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 (
|
|
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((
|
|
1582
|
+
return (data ?? []).map((p3) => {
|
|
1125
1583
|
var _a;
|
|
1126
1584
|
return {
|
|
1127
|
-
id:
|
|
1128
|
-
title:
|
|
1129
|
-
description:
|
|
1130
|
-
featuredImage:
|
|
1131
|
-
hasOnlyDefaultVariant:
|
|
1132
|
-
variants: (
|
|
1133
|
-
id:
|
|
1134
|
-
availableForSale:
|
|
1135
|
-
title:
|
|
1136
|
-
currentPrice:
|
|
1137
|
-
basePrice:
|
|
1138
|
-
image:
|
|
1139
|
-
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((
|
|
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((
|
|
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((
|
|
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
|
-
|
|
1514
|
-
|
|
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((
|
|
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((
|
|
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((
|
|
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((
|
|
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
|
|
1761
|
-
return
|
|
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
|
-
...
|
|
1771
|
-
|
|
1772
|
-
|
|
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
|
-
(
|
|
2674
|
+
(d2) => {
|
|
1814
2675
|
var _a2, _b2, _c;
|
|
1815
2676
|
return {
|
|
1816
|
-
id:
|
|
1817
|
-
type: ((_a2 =
|
|
1818
|
-
value: ((_b2 =
|
|
1819
|
-
code:
|
|
1820
|
-
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(([,
|
|
1855
|
-
(entries) => "(" + entries.map(([
|
|
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 (
|
|
1886
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
1899
|
-
return { _tag: "Failure", error:
|
|
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/
|
|
2832
|
+
`/customer/subscriptions/${subscriptionId}/lines`,
|
|
1906
2833
|
{
|
|
1907
2834
|
method: "POST",
|
|
1908
2835
|
headers: { "Content-Type": "application/json" },
|
|
1909
|
-
body: JSON.stringify(
|
|
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 (
|
|
1915
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
1927
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
1949
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
1965
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
1981
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
1997
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2013
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2970
|
+
} catch (e) {
|
|
2040
2971
|
return {
|
|
2041
2972
|
_tag: "Failure",
|
|
2042
|
-
error: { kind: "NETWORK", message:
|
|
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 (
|
|
2995
|
+
} catch (e) {
|
|
2065
2996
|
return {
|
|
2066
2997
|
_tag: "Failure",
|
|
2067
|
-
error: { kind: "NETWORK", message:
|
|
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 (
|
|
2086
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2104
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2117
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2130
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2143
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2160
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2173
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2186
|
-
return { _tag: "Failure", error:
|
|
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((
|
|
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:
|
|
2201
|
-
variantId: ((_b = (_a =
|
|
2202
|
-
title:
|
|
2203
|
-
imageUrl: ((_c =
|
|
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 =
|
|
2206
|
-
currencyCode: ((_i = (_h = (_g =
|
|
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 =
|
|
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 (
|
|
2214
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2235
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2252
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2273
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2296
|
-
return { _tag: "Failure", error:
|
|
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((
|
|
3513
|
+
discounts: (order.discounts ?? []).map((d2) => {
|
|
2358
3514
|
var _a, _b, _c;
|
|
2359
3515
|
return {
|
|
2360
|
-
id:
|
|
2361
|
-
title:
|
|
2362
|
-
type: ((_a =
|
|
2363
|
-
value: ((_b =
|
|
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
|
|
2403
|
-
return Number.isFinite(
|
|
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
|
|
3562
|
+
const d2 = new Date(date);
|
|
2407
3563
|
switch (interval) {
|
|
2408
3564
|
case "DAY":
|
|
2409
|
-
|
|
3565
|
+
d2.setDate(d2.getDate() + units);
|
|
2410
3566
|
break;
|
|
2411
3567
|
case "WEEK":
|
|
2412
|
-
|
|
3568
|
+
d2.setDate(d2.getDate() + units * 7);
|
|
2413
3569
|
break;
|
|
2414
3570
|
case "YEAR":
|
|
2415
|
-
|
|
3571
|
+
d2.setFullYear(d2.getFullYear() + units);
|
|
2416
3572
|
break;
|
|
2417
3573
|
default:
|
|
2418
|
-
|
|
3574
|
+
d2.setMonth(d2.getMonth() + units);
|
|
2419
3575
|
break;
|
|
2420
3576
|
}
|
|
2421
|
-
return
|
|
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((
|
|
2480
|
-
id:
|
|
2481
|
-
title:
|
|
2482
|
-
type:
|
|
2483
|
-
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((
|
|
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
|
-
(
|
|
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((
|
|
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
|
-
(
|
|
2584
|
-
).map((
|
|
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((
|
|
2590
|
-
(
|
|
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 &&
|
|
3750
|
+
excludeSkipped && o3.items.some((i3) => i3.skipped) ? { ...o3, items: o3.items.filter((i3) => !i3.skipped) } : o3
|
|
2595
3751
|
)
|
|
2596
|
-
).sort((
|
|
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((
|
|
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((
|
|
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 (
|
|
2690
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2704
|
-
return { _tag: "Failure", error:
|
|
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((
|
|
2721
|
-
id:
|
|
2722
|
-
matcher:
|
|
2723
|
-
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 (
|
|
2740
|
-
return { _tag: "Failure", error:
|
|
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 (
|
|
2817
|
-
return { _tag: "Failure", error:
|
|
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(
|
|
2824
|
-
const da = new Date(
|
|
2825
|
-
const db = new Date(
|
|
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
|
-
(
|
|
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((
|
|
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((
|
|
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
|
|
2924
|
-
const result = await adapter.removeAdjustment({ adjustmentId:
|
|
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,
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
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((
|
|
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((
|
|
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((
|
|
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((
|
|
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
|
|
4027
|
-
const
|
|
4028
|
-
layout.items[cmd.blockId] = { ...current, w:
|
|
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((
|
|
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
|
-
|
|
4147
|
-
|
|
5413
|
+
q as ContextProvideEvent,
|
|
5414
|
+
t as ContextRequestEvent,
|
|
4148
5415
|
CustomerServiceContext,
|
|
4149
|
-
|
|
4150
|
-
|
|
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
|
-
|
|
5422
|
+
L2 as LAYOUT_SCOPE_ATTR,
|
|
4156
5423
|
LoginServiceContext,
|
|
4157
|
-
|
|
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
|
-
|
|
5440
|
+
a as ThemeStateContext,
|
|
4171
5441
|
T as TranslationContext,
|
|
4172
5442
|
WorkflowServiceContext,
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
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
|
-
|
|
5453
|
+
k2 as classifyRowDividers,
|
|
4181
5454
|
clearAllSurfaceContexts,
|
|
4182
5455
|
clearLayoutModeAdapter,
|
|
4183
5456
|
compactItems,
|
|
4184
|
-
|
|
5457
|
+
l2 as compactLayoutDocument,
|
|
4185
5458
|
w as computed,
|
|
4186
5459
|
createApiCustomerAdapter,
|
|
4187
5460
|
createApiLoginAdapter,
|
|
4188
|
-
|
|
5461
|
+
createApiOrderAdapter,
|
|
4189
5462
|
createApiProductAdapter,
|
|
4190
5463
|
createApiSchedulesAdapter,
|
|
4191
5464
|
createApiSubscriptionAdapter,
|
|
4192
5465
|
createBlockInstance,
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
5466
|
+
y as createBlockInstanceFromJSON,
|
|
5467
|
+
g as createBlockInstanceFromObject,
|
|
5468
|
+
z as createCeRenderer,
|
|
4196
5469
|
createContext,
|
|
4197
5470
|
createCustomerService,
|
|
4198
|
-
|
|
5471
|
+
m as createDefaultLayoutDocument,
|
|
4199
5472
|
createLoginService,
|
|
4200
5473
|
createMockCustomerAdapter,
|
|
4201
5474
|
createMockLoginAdapter,
|
|
4202
|
-
|
|
5475
|
+
createMockOrderAdapter,
|
|
4203
5476
|
createMockProductAdapter,
|
|
4204
5477
|
createMockRouterService,
|
|
4205
5478
|
createMockSchedulesAdapter,
|
|
4206
5479
|
createMockSubscriptionAdapter,
|
|
4207
5480
|
createMockWorkflowApiAdapter,
|
|
4208
|
-
|
|
5481
|
+
createOrderService,
|
|
5482
|
+
createOverlayService,
|
|
4209
5483
|
createProductService,
|
|
4210
5484
|
createRouterService,
|
|
4211
5485
|
createSchedulesService,
|
|
4212
|
-
|
|
5486
|
+
A as createSelectedBlock,
|
|
4213
5487
|
createSettingsService,
|
|
4214
5488
|
createShopService,
|
|
4215
5489
|
createState,
|
|
4216
5490
|
createSubscriptionService,
|
|
4217
|
-
|
|
4218
|
-
|
|
5491
|
+
n as createThemeState,
|
|
5492
|
+
o2 as createTranslationService,
|
|
4219
5493
|
createWorkflowApiAdapter,
|
|
4220
5494
|
createWorkflowService,
|
|
4221
5495
|
defineBlock,
|
|
4222
|
-
|
|
4223
|
-
|
|
5496
|
+
D as defineBlockRuntime,
|
|
5497
|
+
defineOverlayWrapper,
|
|
5498
|
+
p as deriveLayout,
|
|
4224
5499
|
E as effect,
|
|
4225
5500
|
emitLayoutCommand,
|
|
4226
5501
|
emitLayoutSetRects,
|
|
4227
|
-
|
|
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
|
-
|
|
4236
|
-
|
|
5516
|
+
G as hasRenderedContent,
|
|
5517
|
+
s as indexOverrides,
|
|
4237
5518
|
i as injectContext,
|
|
4238
5519
|
insertRectRelative,
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
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
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
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
|
-
|
|
5540
|
+
k as serializeBlocks,
|
|
5541
|
+
serializeV1PaymentInstrument,
|
|
4257
5542
|
setActiveSurfaceContext,
|
|
5543
|
+
K as setDevtoolsBlockProp,
|
|
4258
5544
|
setLayoutCommandDispatcher,
|
|
4259
5545
|
setLayoutCommandEmitter,
|
|
4260
|
-
|
|
5546
|
+
l as setLayoutSystemEnabled,
|
|
4261
5547
|
d as signal,
|
|
4262
5548
|
subscribeContext,
|
|
4263
5549
|
toLanguageSelectOptions,
|
|
4264
|
-
|
|
5550
|
+
L as untracked,
|
|
4265
5551
|
waitForDevBlocksUrl,
|
|
5552
|
+
withRefreshLock,
|
|
4266
5553
|
w2 as withWrapper
|
|
4267
5554
|
};
|