@juo/blocks 1.13.0-alpha.2 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ExtensionRoot-peABLAZZ.js → ExtensionRoot-2xTGTu3K.js} +3 -15
- package/dist/block.d.ts +0 -50
- package/dist/block.d.ts.map +1 -1
- package/dist/{bridge-r7Yk8fjY.js → bridge-w5KQ-czl.js} +25 -34
- package/dist/context.d.ts.map +1 -1
- package/dist/core.js +344 -2121
- package/dist/editor/bridge.d.ts +0 -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 +1 -2
- package/dist/editor/main.d.ts.map +1 -1
- package/dist/editor/messages.d.ts +2 -13
- package/dist/editor/messages.d.ts.map +1 -1
- package/dist/editor.js +45 -64
- package/dist/flows/WorkflowService.d.ts +2 -0
- package/dist/flows/WorkflowService.d.ts.map +1 -1
- package/dist/{juo-workflow-DY4rd256.js → juo-workflow-BlG9CcAG.js} +887 -78
- package/dist/main.d.ts +1 -3
- package/dist/main.d.ts.map +1 -1
- package/dist/preact.js +1 -1
- package/dist/react.js +1 -1
- package/dist/services/customer/customerService.d.ts +2 -3
- package/dist/services/customer/customerService.d.ts.map +1 -1
- package/dist/services/customer/index.d.ts +0 -1
- package/dist/services/customer/index.d.ts.map +1 -1
- package/dist/services/customer/types.d.ts +1 -4
- package/dist/services/customer/types.d.ts.map +1 -1
- package/dist/services/index.d.ts +0 -3
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/login/index.d.ts +1 -3
- package/dist/services/login/index.d.ts.map +1 -1
- package/dist/services/login/loginService.d.ts +2 -6
- package/dist/services/login/loginService.d.ts.map +1 -1
- package/dist/services/orders/adapter.d.ts +0 -2
- package/dist/services/orders/adapter.d.ts.map +1 -1
- package/dist/services/orders/index.d.ts +1 -1
- package/dist/services/orders/index.d.ts.map +1 -1
- package/dist/services/product/adapter.d.ts +2 -27
- 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/product/productService.d.ts.map +1 -1
- package/dist/services/product/types.d.ts +0 -68
- package/dist/services/product/types.d.ts.map +1 -1
- package/dist/services/subscription/adapter.d.ts +2 -77
- package/dist/services/subscription/adapter.d.ts.map +1 -1
- package/dist/services/subscription/index.d.ts +1 -1
- package/dist/services/subscription/index.d.ts.map +1 -1
- package/dist/services/subscription/subscriptionService.d.ts +6 -1
- package/dist/services/subscription/subscriptionService.d.ts.map +1 -1
- package/dist/services/subscription/types.d.ts +9 -220
- package/dist/services/subscription/types.d.ts.map +1 -1
- package/dist/theme-state.d.ts +1 -2
- package/dist/theme-state.d.ts.map +1 -1
- package/dist/utils/index.d.ts +0 -6
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/vue/block.d.ts.map +1 -1
- package/dist/vue.js +4 -25
- package/dist/web-components/ExtensionRoot.d.ts +0 -1
- package/dist/web-components/ExtensionRoot.d.ts.map +1 -1
- package/dist/web-components-editor.js +3 -4
- package/dist/web-components-runtime.js +2 -3
- package/package.json +1 -1
- package/dist/block-B6s9jL7l.js +0 -966
- package/dist/block.devtools.test.d.ts +0 -2
- package/dist/block.devtools.test.d.ts.map +0 -1
- package/dist/context.devtools.test.d.ts +0 -2
- package/dist/context.devtools.test.d.ts.map +0 -1
- package/dist/devtools/env.d.ts +0 -3
- package/dist/devtools/env.d.ts.map +0 -1
- package/dist/devtools/hook.d.ts +0 -35
- package/dist/devtools/hook.d.ts.map +0 -1
- package/dist/devtools/index.d.ts +0 -4
- package/dist/devtools/index.d.ts.map +0 -1
- package/dist/devtools/protocol.d.ts +0 -91
- package/dist/devtools/protocol.d.ts.map +0 -1
- package/dist/devtools.js +0 -44
- package/dist/editor/messages.test.d.ts +0 -2
- package/dist/editor/messages.test.d.ts.map +0 -1
- package/dist/editor/overlays.d.ts +0 -14
- package/dist/editor/overlays.d.ts.map +0 -1
- package/dist/editor/overlays.test.d.ts +0 -2
- package/dist/editor/overlays.test.d.ts.map +0 -1
- package/dist/overlay-wrapper.d.ts +0 -69
- package/dist/overlay-wrapper.d.ts.map +0 -1
- package/dist/overlay-wrapper.test.d.ts +0 -2
- package/dist/overlay-wrapper.test.d.ts.map +0 -1
- package/dist/overlays/OverlayService.d.ts +0 -34
- package/dist/overlays/OverlayService.d.ts.map +0 -1
- package/dist/overlays/OverlayService.test.d.ts +0 -2
- package/dist/overlays/OverlayService.test.d.ts.map +0 -1
- package/dist/registry.devtools.test.d.ts +0 -2
- package/dist/registry.devtools.test.d.ts.map +0 -1
- package/dist/services/customer/adapter.d.ts +0 -8
- package/dist/services/customer/adapter.d.ts.map +0 -1
- package/dist/services/login/adapter.d.ts +0 -32
- package/dist/services/login/adapter.d.ts.map +0 -1
- package/dist/services/order/adapter.d.ts +0 -9
- package/dist/services/order/adapter.d.ts.map +0 -1
- package/dist/services/order/index.d.ts +0 -5
- package/dist/services/order/index.d.ts.map +0 -1
- package/dist/services/order/orderService.d.ts +0 -7
- package/dist/services/order/orderService.d.ts.map +0 -1
- package/dist/services/order/types.d.ts +0 -21
- package/dist/services/order/types.d.ts.map +0 -1
- package/dist/services/product/adapter.test.d.ts +0 -2
- package/dist/services/product/adapter.test.d.ts.map +0 -1
- package/dist/services/schedules/adapter.d.ts +0 -71
- package/dist/services/schedules/adapter.d.ts.map +0 -1
- package/dist/services/schedules/adapter.test.d.ts +0 -2
- package/dist/services/schedules/adapter.test.d.ts.map +0 -1
- package/dist/services/schedules/index.d.ts +0 -5
- package/dist/services/schedules/index.d.ts.map +0 -1
- package/dist/services/schedules/schedulesService.d.ts +0 -11
- package/dist/services/schedules/schedulesService.d.ts.map +0 -1
- package/dist/services/schedules/schedulesService.test.d.ts +0 -2
- package/dist/services/schedules/schedulesService.test.d.ts.map +0 -1
- package/dist/services/schedules/types.d.ts +0 -226
- package/dist/services/schedules/types.d.ts.map +0 -1
- package/dist/services/settings/index.d.ts +0 -3
- package/dist/services/settings/index.d.ts.map +0 -1
- package/dist/services/settings/settingsService.d.ts +0 -7
- package/dist/services/settings/settingsService.d.ts.map +0 -1
- package/dist/services/settings/settingsService.test.d.ts +0 -2
- package/dist/services/settings/settingsService.test.d.ts.map +0 -1
- package/dist/services/settings/types.d.ts +0 -35
- package/dist/services/settings/types.d.ts.map +0 -1
- package/dist/services/shop/index.d.ts +0 -3
- package/dist/services/shop/index.d.ts.map +0 -1
- package/dist/services/shop/shopService.d.ts +0 -12
- package/dist/services/shop/shopService.d.ts.map +0 -1
- package/dist/services/shop/shopService.test.d.ts +0 -2
- package/dist/services/shop/shopService.test.d.ts.map +0 -1
- package/dist/services/shop/types.d.ts +0 -7
- package/dist/services/shop/types.d.ts.map +0 -1
- package/dist/services/subscription/adapter.test.d.ts +0 -2
- package/dist/services/subscription/adapter.test.d.ts.map +0 -1
- package/dist/services/subscription/types.test.d.ts +0 -2
- package/dist/services/subscription/types.test.d.ts.map +0 -1
- package/dist/theme-state.params.test.d.ts +0 -2
- package/dist/theme-state.params.test.d.ts.map +0 -1
- package/dist/theme-state.translations.test.d.ts +0 -2
- package/dist/theme-state.translations.test.d.ts.map +0 -1
package/dist/core.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
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,
|
|
6
|
-
import { D as D2, a as a2, T, W, c, b as b2, d as d2, e, g, h, i as i2 } from "./juo-workflow-DY4rd256.js";
|
|
4
|
+
import { c as createContext, d, w, r as registerBlock, E, u } from "./juo-workflow-BlG9CcAG.js";
|
|
5
|
+
import { B, C, a, D, S, T, b, W, e, f, g, h, i, j, k, l, m, n, o, p, q, s, t, v, x, y, z, A, F, G, H, I, J, K, L } from "./juo-workflow-BlG9CcAG.js";
|
|
7
6
|
import { reportBlockWarning, reportBlockError } from "./observability.js";
|
|
8
7
|
function createState() {
|
|
9
8
|
const discountCode = d(null);
|
|
@@ -73,111 +72,6 @@ function createState() {
|
|
|
73
72
|
};
|
|
74
73
|
}
|
|
75
74
|
const StateContext = createContext("state");
|
|
76
|
-
const OVERLAY_WRAPPER_SCHEMA = {
|
|
77
|
-
type: "object",
|
|
78
|
-
properties: {
|
|
79
|
-
props: {
|
|
80
|
-
type: "object",
|
|
81
|
-
properties: {
|
|
82
|
-
layout: {
|
|
83
|
-
type: "string",
|
|
84
|
-
enum: ["modal", "sidebar"]
|
|
85
|
-
},
|
|
86
|
-
canAbort: {
|
|
87
|
-
type: "boolean"
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
required: ["layout"],
|
|
91
|
-
additionalProperties: false
|
|
92
|
-
},
|
|
93
|
-
slots: {
|
|
94
|
-
type: "object",
|
|
95
|
-
properties: {
|
|
96
|
-
content: {}
|
|
97
|
-
},
|
|
98
|
-
additionalProperties: false
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
required: ["props", "slots"],
|
|
102
|
-
additionalProperties: false
|
|
103
|
-
};
|
|
104
|
-
function defineOverlayWrapper(opts) {
|
|
105
|
-
const layout = opts.layout ?? "sidebar";
|
|
106
|
-
const canAbort = opts.canAbort ?? true;
|
|
107
|
-
return defineBlock(opts.name, {
|
|
108
|
-
displayName: opts.title,
|
|
109
|
-
group: "internal",
|
|
110
|
-
schema: OVERLAY_WRAPPER_SCHEMA,
|
|
111
|
-
initialValue: () => ({
|
|
112
|
-
props: { layout, canAbort },
|
|
113
|
-
slots: {
|
|
114
|
-
content: [createBlockInstance(opts.content)]
|
|
115
|
-
}
|
|
116
|
-
}),
|
|
117
|
-
renderer: () => null
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
const OVERLAY_PREFIX$1 = "overlay:";
|
|
121
|
-
function callInitialValue(block) {
|
|
122
|
-
if (typeof block.initialValue !== "function") return block.initialValue;
|
|
123
|
-
try {
|
|
124
|
-
return block.initialValue();
|
|
125
|
-
} catch (error) {
|
|
126
|
-
console.warn(
|
|
127
|
-
`[overlays] initialValue() threw for "${block.name}"; its content block will not be hidden from the palette.`,
|
|
128
|
-
error
|
|
129
|
-
);
|
|
130
|
-
return void 0;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
function buildOverlayRegistry(blocks) {
|
|
134
|
-
var _a, _b;
|
|
135
|
-
const registry = {};
|
|
136
|
-
for (const block of blocks) {
|
|
137
|
-
if (!block.name.startsWith(OVERLAY_PREFIX$1)) continue;
|
|
138
|
-
const id = block.name.slice(OVERLAY_PREFIX$1.length);
|
|
139
|
-
const initial = callInitialValue(block);
|
|
140
|
-
const first = (_b = (_a = initial == null ? void 0 : initial.slots) == null ? void 0 : _a.content) == null ? void 0 : _b[0];
|
|
141
|
-
const contentBlock = typeof (first == null ? void 0 : first.type) === "string" ? first.type : "";
|
|
142
|
-
registry[id] = {
|
|
143
|
-
block: block.name,
|
|
144
|
-
title: block.displayName ?? id,
|
|
145
|
-
contentBlock
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
return registry;
|
|
149
|
-
}
|
|
150
|
-
const OVERLAY_PREFIX = "overlay:";
|
|
151
|
-
const OverlayServiceContext = createContext("services/overlay");
|
|
152
|
-
function createOverlayService(themeState, options = {}) {
|
|
153
|
-
const getBlocks = options.getBlocks ?? getDefinedBlocks;
|
|
154
|
-
const current = w(() => {
|
|
155
|
-
const root = themeState.overlay.blocks.value[0];
|
|
156
|
-
const type = root == null ? void 0 : root.type;
|
|
157
|
-
if (typeof type !== "string" || !type.startsWith(OVERLAY_PREFIX)) {
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
const props = root.props ?? {};
|
|
161
|
-
return {
|
|
162
|
-
name: type,
|
|
163
|
-
// Defaults mirror defineOverlayWrapper's seeding in overlay-wrapper.ts — keep in sync.
|
|
164
|
-
layout: props.layout ?? "sidebar",
|
|
165
|
-
canAbort: Boolean(props.canAbort ?? true)
|
|
166
|
-
};
|
|
167
|
-
});
|
|
168
|
-
return {
|
|
169
|
-
getEditableOverlays() {
|
|
170
|
-
return buildOverlayRegistry(getBlocks());
|
|
171
|
-
},
|
|
172
|
-
open(name, params) {
|
|
173
|
-
void themeState.resolve("overlay", name, params);
|
|
174
|
-
},
|
|
175
|
-
close() {
|
|
176
|
-
themeState.overlay.blocks.value = [];
|
|
177
|
-
},
|
|
178
|
-
current
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
75
|
function isLocalhostOrigin(origin) {
|
|
182
76
|
try {
|
|
183
77
|
const url = new URL(origin);
|
|
@@ -238,7 +132,7 @@ async function loadBlockRegistry(options = {}) {
|
|
|
238
132
|
if ("registerBlocks" in module && typeof module.registerBlocks === "function") {
|
|
239
133
|
module.registerBlocks();
|
|
240
134
|
} else {
|
|
241
|
-
Object.entries(module).forEach(([
|
|
135
|
+
Object.entries(module).forEach(([_, item]) => {
|
|
242
136
|
if (typeof item === "object" && item != null) {
|
|
243
137
|
registerBlock(item);
|
|
244
138
|
}
|
|
@@ -262,43 +156,13 @@ async function loadBlockRegistry(options = {}) {
|
|
|
262
156
|
function createCustomerService(options) {
|
|
263
157
|
const current = d(null);
|
|
264
158
|
const accountOrdersUrl = d(options.getAccountOrdersUrl());
|
|
265
|
-
|
|
159
|
+
const service = {
|
|
266
160
|
current,
|
|
267
|
-
accountOrdersUrl
|
|
268
|
-
async getCurrent() {
|
|
269
|
-
const result = await options.adapter.getCurrent();
|
|
270
|
-
if (result._tag === "Success") current.value = result.data;
|
|
271
|
-
return result;
|
|
272
|
-
}
|
|
161
|
+
accountOrdersUrl
|
|
273
162
|
};
|
|
163
|
+
return service;
|
|
274
164
|
}
|
|
275
165
|
const CustomerServiceContext = createContext("services/customer");
|
|
276
|
-
function createMockCustomerAdapter() {
|
|
277
|
-
const customer = { id: "customer-1", name: "Customer 1" };
|
|
278
|
-
return {
|
|
279
|
-
async getCurrent() {
|
|
280
|
-
return { _tag: "Success", data: customer };
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
function createApiCustomerAdapter(fetcher) {
|
|
285
|
-
return {
|
|
286
|
-
async getCurrent() {
|
|
287
|
-
try {
|
|
288
|
-
const res = await fetcher("/customer/info");
|
|
289
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
290
|
-
const data = await res.json();
|
|
291
|
-
const name = [data.firstName, data.lastName].filter(Boolean).join(" ") || data.email || "";
|
|
292
|
-
return {
|
|
293
|
-
_tag: "Success",
|
|
294
|
-
data: { id: data.id, name, email: data.email }
|
|
295
|
-
};
|
|
296
|
-
} catch (e2) {
|
|
297
|
-
return { _tag: "Failure", error: e2 };
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
};
|
|
301
|
-
}
|
|
302
166
|
const PARAMS = {
|
|
303
167
|
DELETGATED_TOKEN: "delegated-token",
|
|
304
168
|
REDIRECT_TO: "redirect-to",
|
|
@@ -312,125 +176,9 @@ const PARAMS = {
|
|
|
312
176
|
function uuid() {
|
|
313
177
|
return ("10000000-1000-4000-8000" + -1e11).replace(
|
|
314
178
|
/[018]/g,
|
|
315
|
-
(
|
|
179
|
+
(c) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
|
316
180
|
);
|
|
317
181
|
}
|
|
318
|
-
function createMockLoginAdapter() {
|
|
319
|
-
return {
|
|
320
|
-
async passwordlessStart() {
|
|
321
|
-
return { _tag: "Success", data: void 0 };
|
|
322
|
-
},
|
|
323
|
-
async authenticate() {
|
|
324
|
-
return {
|
|
325
|
-
_tag: "Success",
|
|
326
|
-
data: {
|
|
327
|
-
access_token: "mock-access-token",
|
|
328
|
-
refresh_token: "mock-refresh-token",
|
|
329
|
-
expires_in: 3600
|
|
330
|
-
}
|
|
331
|
-
};
|
|
332
|
-
},
|
|
333
|
-
getAuthorizeUrl({ connection, state, shop, appUrl }) {
|
|
334
|
-
const url = new URL(`${appUrl}/auth/customer/authorize`);
|
|
335
|
-
url.searchParams.set("connection", connection);
|
|
336
|
-
url.searchParams.set("state", state);
|
|
337
|
-
url.searchParams.set("shop", shop);
|
|
338
|
-
return url.toString();
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
function createApiLoginAdapter(fetcher, opts) {
|
|
343
|
-
const { shopDomain, appUrl } = opts;
|
|
344
|
-
async function callAuthEndpoint(path, body, lang) {
|
|
345
|
-
const url = lang ? `${path}?lang=${lang}` : path;
|
|
346
|
-
const res = await fetcher(url, {
|
|
347
|
-
method: "POST",
|
|
348
|
-
headers: {
|
|
349
|
-
Accept: "application/json",
|
|
350
|
-
"Content-Type": "application/json",
|
|
351
|
-
"X-Shopify-Shop-Domain": shopDomain
|
|
352
|
-
},
|
|
353
|
-
body: JSON.stringify(body)
|
|
354
|
-
});
|
|
355
|
-
if (res.status === 403) {
|
|
356
|
-
const data = await res.json();
|
|
357
|
-
if ("error_description" in data) {
|
|
358
|
-
if (data.error_description === "Wrong email or verification code.") {
|
|
359
|
-
throw new AuthenticationError(AuthenticationErrorReason.IncorrectCode);
|
|
360
|
-
} else if (data.error_description === "You've reached the maximum number of attempts. Please try to login again.") {
|
|
361
|
-
throw new AuthenticationError(AuthenticationErrorReason.TooManyTries);
|
|
362
|
-
} else if (data.error_description === "The verification code has expired. Please try to login again.") {
|
|
363
|
-
throw new AuthenticationError(AuthenticationErrorReason.Expired);
|
|
364
|
-
}
|
|
365
|
-
} else if ("code" in data && data.code === "AUTH_ERROR") {
|
|
366
|
-
throw new AuthenticationError(AuthenticationErrorReason.NoEmail, {
|
|
367
|
-
connection: data.connection
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
if (!res.ok) {
|
|
372
|
-
throw new Error(`Unexpected response: ${res.statusText}`);
|
|
373
|
-
}
|
|
374
|
-
return { _tag: "Success", data: void 0 };
|
|
375
|
-
}
|
|
376
|
-
return {
|
|
377
|
-
async passwordlessStart({ email, lang }) {
|
|
378
|
-
try {
|
|
379
|
-
await callAuthEndpoint(
|
|
380
|
-
"/auth/customer/passwordless/start",
|
|
381
|
-
{ email },
|
|
382
|
-
lang
|
|
383
|
-
);
|
|
384
|
-
return { _tag: "Success", data: void 0 };
|
|
385
|
-
} catch (e2) {
|
|
386
|
-
return { _tag: "Failure", error: e2 };
|
|
387
|
-
}
|
|
388
|
-
},
|
|
389
|
-
async authenticate(params) {
|
|
390
|
-
try {
|
|
391
|
-
const res = await fetcher("/auth/customer/token", {
|
|
392
|
-
method: "POST",
|
|
393
|
-
headers: {
|
|
394
|
-
Accept: "application/json",
|
|
395
|
-
"Content-Type": "application/json",
|
|
396
|
-
"X-Shopify-Shop-Domain": shopDomain
|
|
397
|
-
},
|
|
398
|
-
body: JSON.stringify(params)
|
|
399
|
-
});
|
|
400
|
-
if (res.status === 403) {
|
|
401
|
-
const data = await res.json();
|
|
402
|
-
if ("error_description" in data) {
|
|
403
|
-
if (data.error_description === "Wrong email or verification code.") {
|
|
404
|
-
throw new AuthenticationError(AuthenticationErrorReason.IncorrectCode);
|
|
405
|
-
} else if (data.error_description === "You've reached the maximum number of attempts. Please try to login again.") {
|
|
406
|
-
throw new AuthenticationError(AuthenticationErrorReason.TooManyTries);
|
|
407
|
-
} else if (data.error_description === "The verification code has expired. Please try to login again.") {
|
|
408
|
-
throw new AuthenticationError(AuthenticationErrorReason.Expired);
|
|
409
|
-
}
|
|
410
|
-
} else if ("code" in data && data.code === "AUTH_ERROR") {
|
|
411
|
-
throw new AuthenticationError(AuthenticationErrorReason.NoEmail, {
|
|
412
|
-
connection: data.connection
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
if (!res.ok) {
|
|
417
|
-
throw new Error(`Unexpected response: ${res.statusText}`);
|
|
418
|
-
}
|
|
419
|
-
return { _tag: "Success", data: await res.json() };
|
|
420
|
-
} catch (e2) {
|
|
421
|
-
return { _tag: "Failure", error: e2 };
|
|
422
|
-
}
|
|
423
|
-
},
|
|
424
|
-
getAuthorizeUrl({ connection, state, shop }) {
|
|
425
|
-
const url = new URL(`${appUrl}/auth/customer/authorize`);
|
|
426
|
-
url.searchParams.set("connection", connection);
|
|
427
|
-
url.searchParams.set("state", state);
|
|
428
|
-
url.searchParams.set("shop", shop);
|
|
429
|
-
return url.toString();
|
|
430
|
-
}
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
const __vite_import_meta_env__ = {};
|
|
434
182
|
var AuthenticationErrorReason = /* @__PURE__ */ ((AuthenticationErrorReason2) => {
|
|
435
183
|
AuthenticationErrorReason2["Expired"] = "expired";
|
|
436
184
|
AuthenticationErrorReason2["IncorrectCode"] = "wrong-code";
|
|
@@ -449,9 +197,6 @@ class AuthenticationError extends Error {
|
|
|
449
197
|
this.data = data ?? {};
|
|
450
198
|
}
|
|
451
199
|
}
|
|
452
|
-
const STORAGE_DELEGATED_TOKEN = "delegated-token";
|
|
453
|
-
const STORAGE_REFRESH_TOKEN_KEY = "refresh-token";
|
|
454
|
-
const STORAGE_STATE_KEY = "state";
|
|
455
200
|
function storage(key, value) {
|
|
456
201
|
const storageKey = `auth:${key}`;
|
|
457
202
|
try {
|
|
@@ -467,33 +212,83 @@ function storage(key, value) {
|
|
|
467
212
|
}
|
|
468
213
|
return null;
|
|
469
214
|
}
|
|
215
|
+
const STORAGE_DELEGATED_TOKEN = "delegated-token";
|
|
216
|
+
const STORAGE_REFRESH_TOKEN_KEY = "refresh-token";
|
|
217
|
+
const STORAGE_STATE_KEY = "state";
|
|
218
|
+
function createAuthFunctions(basePath, shop) {
|
|
219
|
+
async function start(email, lang) {
|
|
220
|
+
const response = await fetch(
|
|
221
|
+
`${basePath}/auth/customer/passwordless/start?lang=${lang}`,
|
|
222
|
+
{
|
|
223
|
+
method: "POST",
|
|
224
|
+
headers: {
|
|
225
|
+
Accept: "application/json",
|
|
226
|
+
"Content-Type": "application/json",
|
|
227
|
+
"X-Shopify-Shop-Domain": shop
|
|
228
|
+
},
|
|
229
|
+
body: JSON.stringify({ email })
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
if (response.status !== 200) {
|
|
233
|
+
throw new Error(`Unexpected response: ${response.statusText}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async function authenticate(data) {
|
|
237
|
+
const response = await fetch(`${basePath}/auth/customer/token`, {
|
|
238
|
+
method: "POST",
|
|
239
|
+
headers: {
|
|
240
|
+
Accept: "application/json",
|
|
241
|
+
"Content-Type": "application/json",
|
|
242
|
+
"X-Shopify-Shop-Domain": shop
|
|
243
|
+
},
|
|
244
|
+
body: JSON.stringify(data)
|
|
245
|
+
});
|
|
246
|
+
if (response.status === 403) {
|
|
247
|
+
const data2 = await response.json();
|
|
248
|
+
if ("error_description" in data2) {
|
|
249
|
+
if (data2.error_description === "Wrong email or verification code.") {
|
|
250
|
+
throw new AuthenticationError(
|
|
251
|
+
"wrong-code"
|
|
252
|
+
/* IncorrectCode */
|
|
253
|
+
);
|
|
254
|
+
} else if (data2.error_description === "You've reached the maximum number of attempts. Please try to login again.") {
|
|
255
|
+
throw new AuthenticationError(
|
|
256
|
+
"too-many-tries"
|
|
257
|
+
/* TooManyTries */
|
|
258
|
+
);
|
|
259
|
+
} else if (data2.error_description === "The verification code has expired. Please try to login again.") {
|
|
260
|
+
throw new AuthenticationError(
|
|
261
|
+
"expired"
|
|
262
|
+
/* Expired */
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
} else if ("code" in data2) {
|
|
266
|
+
if (data2.code === "AUTH_ERROR") {
|
|
267
|
+
throw new AuthenticationError("no-email", {
|
|
268
|
+
connection: data2.connection
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
if (response.status !== 200) {
|
|
274
|
+
throw new Error(`Unexpected response: ${response.statusText}`);
|
|
275
|
+
}
|
|
276
|
+
return await response.json();
|
|
277
|
+
}
|
|
278
|
+
return { start, authenticate };
|
|
279
|
+
}
|
|
470
280
|
function nonce(len = 10) {
|
|
471
281
|
return uuid().replace(/-/g, "").slice(0, len);
|
|
472
282
|
}
|
|
473
|
-
function
|
|
474
|
-
const
|
|
475
|
-
const appUrl = (typeof import.meta !== "undefined" ? __vite_import_meta_env__ == null ? void 0 : __vite_import_meta_env__.VITE_APP_URL : void 0) ?? "https://admin.juo.io";
|
|
476
|
-
const fetcher = (path, init) => fetch(`${apiBase}${path}`, init);
|
|
477
|
-
const adapter = createApiLoginAdapter(fetcher, {
|
|
478
|
-
shopDomain: deps.shop.domain,
|
|
479
|
-
appUrl
|
|
480
|
-
});
|
|
481
|
-
return createLoginService({
|
|
482
|
-
adapter,
|
|
483
|
-
router: deps.router,
|
|
484
|
-
formatError: deps.formatError,
|
|
485
|
-
shop: {
|
|
486
|
-
domain: deps.shop.domain,
|
|
487
|
-
locale: w(() => deps.getLocale())
|
|
488
|
-
},
|
|
489
|
-
onLoginSuccess: deps.onLoginSuccess
|
|
490
|
-
});
|
|
491
|
-
}
|
|
492
|
-
function createLoginService(init) {
|
|
493
|
-
const { adapter, formatError, router, shop, onLoginSuccess } = init;
|
|
283
|
+
function createAuthService(apiUrl, shopDomain) {
|
|
284
|
+
const { start: authStart, authenticate: authAuthenticate } = createAuthFunctions(apiUrl, shopDomain);
|
|
494
285
|
const accessToken = d(null);
|
|
495
|
-
const delegatedToken = d(
|
|
496
|
-
|
|
286
|
+
const delegatedToken = d(
|
|
287
|
+
storage(STORAGE_DELEGATED_TOKEN)
|
|
288
|
+
);
|
|
289
|
+
const refreshToken = d(
|
|
290
|
+
storage(STORAGE_REFRESH_TOKEN_KEY)
|
|
291
|
+
);
|
|
497
292
|
const expires = d(null);
|
|
498
293
|
const state = d(storage(STORAGE_STATE_KEY));
|
|
499
294
|
E(() => {
|
|
@@ -505,28 +300,67 @@ function createLoginService(init) {
|
|
|
505
300
|
E(() => {
|
|
506
301
|
storage(STORAGE_STATE_KEY, state.value);
|
|
507
302
|
});
|
|
508
|
-
function
|
|
303
|
+
function store(data) {
|
|
509
304
|
const { access_token, refresh_token, expires_in } = data;
|
|
510
305
|
accessToken.value = access_token;
|
|
511
306
|
refreshToken.value = refresh_token;
|
|
512
307
|
expires.value = new Date(Date.now() + expires_in);
|
|
513
308
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
309
|
+
return {
|
|
310
|
+
state,
|
|
311
|
+
async start(email, lang) {
|
|
312
|
+
await authStart(email, lang);
|
|
313
|
+
},
|
|
314
|
+
async authenticate(data) {
|
|
315
|
+
store(await authAuthenticate(data));
|
|
316
|
+
},
|
|
317
|
+
getDelegatedToken() {
|
|
318
|
+
return delegatedToken.value;
|
|
319
|
+
},
|
|
320
|
+
setDelegatedToken(token) {
|
|
321
|
+
delegatedToken.value = token;
|
|
322
|
+
},
|
|
323
|
+
async getToken() {
|
|
324
|
+
if (refreshToken.value == null) {
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
if (accessToken.value == null || typeof accessToken.value === "string" && (expires.value == null || expires.value < /* @__PURE__ */ new Date())) {
|
|
328
|
+
accessToken.value = new Promise(
|
|
329
|
+
(resolve, reject) => authAuthenticate({ refreshToken: refreshToken.value }).then((data) => data).then((data) => {
|
|
330
|
+
store(data);
|
|
331
|
+
resolve(data.access_token);
|
|
521
332
|
return;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
333
|
+
}).catch(reject)
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
return Promise.resolve(accessToken.value);
|
|
337
|
+
},
|
|
338
|
+
logout() {
|
|
339
|
+
accessToken.value = null;
|
|
340
|
+
delegatedToken.value = null;
|
|
341
|
+
refreshToken.value = null;
|
|
342
|
+
expires.value = null;
|
|
343
|
+
},
|
|
344
|
+
isAuthenticated: w(
|
|
345
|
+
() => delegatedToken.value != null || refreshToken.value != null
|
|
346
|
+
)
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
function loginService(deps) {
|
|
350
|
+
return createLoginService({
|
|
351
|
+
apiUrl: `${deps.shop.rootUrl.replace(/\/$/, "")}/api`,
|
|
352
|
+
router: deps.router,
|
|
353
|
+
formatError: deps.formatError,
|
|
354
|
+
shop: {
|
|
355
|
+
domain: deps.shop.domain,
|
|
356
|
+
locale: w(() => deps.getLocale())
|
|
357
|
+
},
|
|
358
|
+
onLoginSuccess: deps.onLoginSuccess
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
function createLoginService(init) {
|
|
362
|
+
const { formatError, router, shop, onLoginSuccess } = init;
|
|
363
|
+
const auth = createAuthService(init.apiUrl.replace(/\/$/, ""), shop.domain);
|
|
530
364
|
const userEmail = d(null);
|
|
531
365
|
async function onSuccess(query) {
|
|
532
366
|
await (onLoginSuccess == null ? void 0 : onLoginSuccess());
|
|
@@ -539,9 +373,13 @@ function createLoginService(init) {
|
|
|
539
373
|
queryParams[key] = value;
|
|
540
374
|
}
|
|
541
375
|
});
|
|
542
|
-
router.push({
|
|
376
|
+
router.push({
|
|
377
|
+
path: decodeURIComponent(redirect),
|
|
378
|
+
query: queryParams
|
|
379
|
+
});
|
|
543
380
|
} else {
|
|
544
|
-
|
|
381
|
+
const redirect = query.get(PARAMS.REDIRECT_TO);
|
|
382
|
+
router.replace(decodeURIComponent(redirect));
|
|
545
383
|
}
|
|
546
384
|
} else {
|
|
547
385
|
router.replace("/");
|
|
@@ -553,17 +391,16 @@ function createLoginService(init) {
|
|
|
553
391
|
async start(email) {
|
|
554
392
|
try {
|
|
555
393
|
userEmail.value = email;
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
});
|
|
561
|
-
if (result._tag === "Failure") {
|
|
562
|
-
return { _tag: "Failure", error: formatError(result.error) };
|
|
563
|
-
}
|
|
394
|
+
await auth.start(
|
|
395
|
+
userEmail.value,
|
|
396
|
+
shop.locale instanceof u ? shop.locale.value : shop.locale
|
|
397
|
+
);
|
|
564
398
|
return { _tag: "Success", data: void 0 };
|
|
565
399
|
} catch (error) {
|
|
566
|
-
return {
|
|
400
|
+
return {
|
|
401
|
+
_tag: "Failure",
|
|
402
|
+
error: formatError(error)
|
|
403
|
+
};
|
|
567
404
|
}
|
|
568
405
|
},
|
|
569
406
|
async verify(email, code) {
|
|
@@ -574,61 +411,63 @@ function createLoginService(init) {
|
|
|
574
411
|
};
|
|
575
412
|
}
|
|
576
413
|
try {
|
|
577
|
-
const result = await
|
|
414
|
+
const result = await auth.authenticate({
|
|
578
415
|
email: userEmail.value,
|
|
579
416
|
code
|
|
580
417
|
});
|
|
581
|
-
if (result._tag === "Failure") {
|
|
582
|
-
return { _tag: "Failure", error: formatError(result.error) };
|
|
583
|
-
}
|
|
584
|
-
storeTokens(result.data);
|
|
585
418
|
await onSuccess();
|
|
586
|
-
return { _tag: "Success", data:
|
|
419
|
+
return { _tag: "Success", data: result };
|
|
587
420
|
} catch (error) {
|
|
588
|
-
return {
|
|
421
|
+
return {
|
|
422
|
+
_tag: "Failure",
|
|
423
|
+
error: formatError(error)
|
|
424
|
+
};
|
|
589
425
|
}
|
|
590
426
|
}
|
|
591
427
|
}
|
|
592
428
|
},
|
|
593
429
|
social: {
|
|
594
430
|
async start(provider) {
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
)
|
|
605
|
-
}
|
|
606
|
-
|
|
431
|
+
function socialUrl(key, shop2) {
|
|
432
|
+
auth.state.value = nonce();
|
|
433
|
+
const url = new URL(
|
|
434
|
+
// TODO: double check admin url
|
|
435
|
+
`${"https://admin.juo.io"}/auth/customer/authorize`
|
|
436
|
+
);
|
|
437
|
+
url.searchParams.append("connection", key);
|
|
438
|
+
url.searchParams.append("state", auth.state.value ?? "");
|
|
439
|
+
url.searchParams.append("shop", shop2);
|
|
440
|
+
return url.toString();
|
|
441
|
+
}
|
|
442
|
+
window.location.href = socialUrl(
|
|
443
|
+
provider === "Facebook" ? "facebook" : "google-oauth2",
|
|
444
|
+
shop.domain
|
|
445
|
+
);
|
|
446
|
+
return {
|
|
447
|
+
_tag: "Success",
|
|
448
|
+
data: void 0
|
|
449
|
+
};
|
|
607
450
|
},
|
|
608
451
|
async verify(code) {
|
|
609
452
|
try {
|
|
610
|
-
const result = await
|
|
611
|
-
if (result._tag === "Failure") {
|
|
612
|
-
return { _tag: "Failure", error: formatError(result.error) };
|
|
613
|
-
}
|
|
614
|
-
storeTokens(result.data);
|
|
453
|
+
const result = await auth.authenticate({ code });
|
|
615
454
|
await onSuccess();
|
|
616
|
-
return { _tag: "Success", data:
|
|
455
|
+
return { _tag: "Success", data: result };
|
|
617
456
|
} catch (error) {
|
|
618
|
-
return {
|
|
457
|
+
return {
|
|
458
|
+
_tag: "Failure",
|
|
459
|
+
error: formatError(error)
|
|
460
|
+
};
|
|
619
461
|
}
|
|
620
462
|
}
|
|
621
463
|
},
|
|
622
464
|
async logout() {
|
|
623
|
-
|
|
624
|
-
delegatedToken.value = null;
|
|
625
|
-
refreshToken.value = null;
|
|
626
|
-
expires.value = null;
|
|
465
|
+
await auth.logout();
|
|
627
466
|
return { _tag: "Success", data: void 0 };
|
|
628
467
|
},
|
|
629
468
|
async handleQueryParams(query) {
|
|
630
469
|
if (query.has(PARAMS.DELETGATED_TOKEN)) {
|
|
631
|
-
|
|
470
|
+
auth.setDelegatedToken(query.get(PARAMS.DELETGATED_TOKEN));
|
|
632
471
|
await onSuccess(query);
|
|
633
472
|
return { _tag: "Success", data: void 0 };
|
|
634
473
|
}
|
|
@@ -640,13 +479,16 @@ function createLoginService(init) {
|
|
|
640
479
|
}
|
|
641
480
|
const code = query.get(PARAMS.CODE);
|
|
642
481
|
if (code != null) {
|
|
643
|
-
if (query.get(PARAMS.STATE) !== state.value) {
|
|
644
|
-
return {
|
|
482
|
+
if (query.get(PARAMS.STATE) !== auth.state.value) {
|
|
483
|
+
return {
|
|
484
|
+
_tag: "Failure",
|
|
485
|
+
error: formatError("Invalid state")
|
|
486
|
+
};
|
|
645
487
|
} else {
|
|
646
488
|
return service.social.verify(code);
|
|
647
489
|
}
|
|
648
490
|
}
|
|
649
|
-
if (query.get(PARAMS.REFRESH) === "1" && await getToken() != null) {
|
|
491
|
+
if (query.get(PARAMS.REFRESH) === "1" && await auth.getToken() != null) {
|
|
650
492
|
await onSuccess();
|
|
651
493
|
return { _tag: "Success", data: void 0 };
|
|
652
494
|
}
|
|
@@ -663,20 +505,8 @@ function createLoginService(init) {
|
|
|
663
505
|
}
|
|
664
506
|
return { _tag: "Success", data: void 0 };
|
|
665
507
|
},
|
|
666
|
-
isAuthenticated:
|
|
667
|
-
|
|
668
|
-
),
|
|
669
|
-
getToken,
|
|
670
|
-
async getAuthHeaders() {
|
|
671
|
-
if (delegatedToken.value) {
|
|
672
|
-
return { "X-Delegated-Token": delegatedToken.value };
|
|
673
|
-
}
|
|
674
|
-
const token = await getToken();
|
|
675
|
-
if (token) {
|
|
676
|
-
return { Authorization: `Bearer ${token}` };
|
|
677
|
-
}
|
|
678
|
-
return {};
|
|
679
|
-
}
|
|
508
|
+
isAuthenticated: auth.isAuthenticated,
|
|
509
|
+
getToken: () => auth.getToken()
|
|
680
510
|
};
|
|
681
511
|
return service;
|
|
682
512
|
}
|
|
@@ -742,55 +572,6 @@ function createMockOrdersAdapter() {
|
|
|
742
572
|
}
|
|
743
573
|
};
|
|
744
574
|
}
|
|
745
|
-
function mapOrderLine(item) {
|
|
746
|
-
var _a;
|
|
747
|
-
return {
|
|
748
|
-
id: item.id,
|
|
749
|
-
title: item.title,
|
|
750
|
-
quantity: item.quantity,
|
|
751
|
-
variantImage: ((_a = item.variantImage) == null ? void 0 : _a.url) ? { url: item.variantImage.url, altText: item.variantImage.altText ?? void 0 } : null,
|
|
752
|
-
customAttributes: item.customAttributes
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
function mapOrder(order) {
|
|
756
|
-
return {
|
|
757
|
-
id: order.id,
|
|
758
|
-
createdAt: order.createdAt,
|
|
759
|
-
placedAt: order.placedAt,
|
|
760
|
-
currencyCode: order.currencyCode,
|
|
761
|
-
totalPrice: order.totalPrice,
|
|
762
|
-
financialStatus: order.financialStatus,
|
|
763
|
-
fulfillmentStatus: order.fulfillmentStatus,
|
|
764
|
-
lines: order.items.map(mapOrderLine),
|
|
765
|
-
customAttributes: order.customAttributes
|
|
766
|
-
};
|
|
767
|
-
}
|
|
768
|
-
function createApiOrdersAdapter(fetcher) {
|
|
769
|
-
return {
|
|
770
|
-
async getOrders(params) {
|
|
771
|
-
const query = new URLSearchParams();
|
|
772
|
-
if ((params == null ? void 0 : params.limit) != null) query.set("limit", String(params.limit));
|
|
773
|
-
if ((params == null ? void 0 : params.after) != null) query.set("after", params.after);
|
|
774
|
-
if ((params == null ? void 0 : params.before) != null) query.set("before", params.before);
|
|
775
|
-
if ((params == null ? void 0 : params.query) != null) query.set("query", params.query);
|
|
776
|
-
if ((params == null ? void 0 : params.includeOneTime) != null) query.set("includeOneTime", String(params.includeOneTime));
|
|
777
|
-
if ((params == null ? void 0 : params.sort) != null) query.set("sort", params.sort);
|
|
778
|
-
const qs = query.toString();
|
|
779
|
-
const res = await fetcher(`/customer/v1/orders${qs ? `?${qs}` : ""}`);
|
|
780
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
781
|
-
const body = await res.json();
|
|
782
|
-
return {
|
|
783
|
-
items: body.data.map(mapOrder),
|
|
784
|
-
pageInfo: {
|
|
785
|
-
hasNextPage: body.hasNextPage,
|
|
786
|
-
hasPrevPage: body.hasPrevPage,
|
|
787
|
-
startCursor: body.startCursor,
|
|
788
|
-
endCursor: body.endCursor
|
|
789
|
-
}
|
|
790
|
-
};
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
}
|
|
794
575
|
function createOrdersService(adapter) {
|
|
795
576
|
return {
|
|
796
577
|
async getOrders(params) {
|
|
@@ -810,7 +591,7 @@ function createMockProductAdapter() {
|
|
|
810
591
|
id: "sample-1",
|
|
811
592
|
title: "Hydrating Gel Cleanser for Face and Eye Area",
|
|
812
593
|
featuredImage: {
|
|
813
|
-
url: "https://
|
|
594
|
+
url: "https://via.placeholder.com/400x400?text=Product+1"
|
|
814
595
|
},
|
|
815
596
|
hasOnlyDefaultVariant: true,
|
|
816
597
|
variants: [
|
|
@@ -818,7 +599,7 @@ function createMockProductAdapter() {
|
|
|
818
599
|
id: "sample-1-1",
|
|
819
600
|
title: "150 ml bottle",
|
|
820
601
|
image: {
|
|
821
|
-
url: "https://
|
|
602
|
+
url: "https://via.placeholder.com/400x400?text=Product+1"
|
|
822
603
|
},
|
|
823
604
|
price: {
|
|
824
605
|
amount: "12.49",
|
|
@@ -844,7 +625,7 @@ function createMockProductAdapter() {
|
|
|
844
625
|
id: "sample-2",
|
|
845
626
|
title: "More COLLAGEN",
|
|
846
627
|
featuredImage: {
|
|
847
|
-
url: "https://
|
|
628
|
+
url: "https://via.placeholder.com/400x400?text=Product+2"
|
|
848
629
|
},
|
|
849
630
|
hasOnlyDefaultVariant: true,
|
|
850
631
|
variants: [
|
|
@@ -852,7 +633,7 @@ function createMockProductAdapter() {
|
|
|
852
633
|
id: "sample-2-1",
|
|
853
634
|
title: "blackcurrant",
|
|
854
635
|
image: {
|
|
855
|
-
url: "https://
|
|
636
|
+
url: "https://via.placeholder.com/400x400?text=Product+2"
|
|
856
637
|
},
|
|
857
638
|
price: {
|
|
858
639
|
amount: "12.49",
|
|
@@ -873,7 +654,7 @@ function createMockProductAdapter() {
|
|
|
873
654
|
id: "sample-3",
|
|
874
655
|
title: "Gentle deodorant for underarms and bust",
|
|
875
656
|
featuredImage: {
|
|
876
|
-
url: "https://
|
|
657
|
+
url: "https://via.placeholder.com/400x400?text=Product+3"
|
|
877
658
|
},
|
|
878
659
|
hasOnlyDefaultVariant: false,
|
|
879
660
|
variants: [
|
|
@@ -881,7 +662,7 @@ function createMockProductAdapter() {
|
|
|
881
662
|
id: "sample-3-1",
|
|
882
663
|
title: "Green tea and jasmine",
|
|
883
664
|
image: {
|
|
884
|
-
url: "https://
|
|
665
|
+
url: "https://via.placeholder.com/400x400?text=Product+3a"
|
|
885
666
|
},
|
|
886
667
|
price: {
|
|
887
668
|
amount: "6.7",
|
|
@@ -899,7 +680,7 @@ function createMockProductAdapter() {
|
|
|
899
680
|
id: "sample-3-2",
|
|
900
681
|
title: "Lavender and mint",
|
|
901
682
|
image: {
|
|
902
|
-
url: "https://
|
|
683
|
+
url: "https://via.placeholder.com/400x400?text=Product+3b"
|
|
903
684
|
},
|
|
904
685
|
price: {
|
|
905
686
|
amount: "7.5",
|
|
@@ -931,48 +712,6 @@ function createMockProductAdapter() {
|
|
|
931
712
|
}
|
|
932
713
|
};
|
|
933
714
|
}
|
|
934
|
-
function toAvailableProduct(product) {
|
|
935
|
-
return {
|
|
936
|
-
id: product.id,
|
|
937
|
-
title: product.title,
|
|
938
|
-
description: `Sample description for ${product.title}.`,
|
|
939
|
-
featuredImage: product.featuredImage ?? void 0,
|
|
940
|
-
hasOnlyDefaultVariant: product.hasOnlyDefaultVariant,
|
|
941
|
-
variants: product.variants.map((variant) => {
|
|
942
|
-
var _a, _b, _c;
|
|
943
|
-
const base = Number.parseFloat(variant.price.amount);
|
|
944
|
-
const sub = (_b = (_a = variant.purchaseOptions) == null ? void 0 : _a[0]) == null ? void 0 : _b.price.amount;
|
|
945
|
-
const current = sub == null ? base : Number.parseFloat(sub);
|
|
946
|
-
return {
|
|
947
|
-
id: variant.id,
|
|
948
|
-
availableForSale: true,
|
|
949
|
-
title: variant.title,
|
|
950
|
-
currentPrice: { amount: current, currencyCode: variant.price.currencyCode },
|
|
951
|
-
basePrice: { amount: base, currencyCode: variant.price.currencyCode },
|
|
952
|
-
image: variant.image ?? void 0,
|
|
953
|
-
recurring: (((_c = variant.purchaseOptions) == null ? void 0 : _c.length) ?? 0) > 0
|
|
954
|
-
};
|
|
955
|
-
})
|
|
956
|
-
};
|
|
957
|
-
}
|
|
958
|
-
const sampleBox = {
|
|
959
|
-
id: "sample-box-1",
|
|
960
|
-
title: "Build Your Own Box",
|
|
961
|
-
minProductsCount: 3,
|
|
962
|
-
parentProduct: "sample-1",
|
|
963
|
-
tiers: [
|
|
964
|
-
{ value: 5, threshold: 3 },
|
|
965
|
-
{ value: 10, threshold: 5 }
|
|
966
|
-
],
|
|
967
|
-
variants: products.map((product) => ({
|
|
968
|
-
id: product.id,
|
|
969
|
-
variants: product.variants.map((variant) => ({ id: variant.id }))
|
|
970
|
-
})),
|
|
971
|
-
freeVariants: [],
|
|
972
|
-
thresholdType: "LINES_COUNT",
|
|
973
|
-
type: "PERCENTAGE",
|
|
974
|
-
restrictQuantityToTiers: false
|
|
975
|
-
};
|
|
976
715
|
return {
|
|
977
716
|
async getById(id) {
|
|
978
717
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
@@ -986,27 +725,6 @@ function createMockProductAdapter() {
|
|
|
986
725
|
);
|
|
987
726
|
return product == null ? null : processProduct(product);
|
|
988
727
|
},
|
|
989
|
-
async getProductsByIds({ ids }) {
|
|
990
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
991
|
-
return products.filter((product) => ids.includes(product.id)).map(({ variants: _variants, ...product }) => product);
|
|
992
|
-
},
|
|
993
|
-
async getBoxVariants({ ids }) {
|
|
994
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
995
|
-
return products.filter((product) => ids.includes(product.id)).map(toAvailableProduct);
|
|
996
|
-
},
|
|
997
|
-
async getAvailableProducts({ q: q2 }) {
|
|
998
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
999
|
-
const queryLower = q2 == null ? void 0 : q2.toLowerCase();
|
|
1000
|
-
return products.filter(
|
|
1001
|
-
(product) => !queryLower || product.title.toLowerCase().includes(queryLower) || product.variants.some(
|
|
1002
|
-
(variant) => variant.title.toLowerCase().includes(queryLower)
|
|
1003
|
-
)
|
|
1004
|
-
).map(toAvailableProduct);
|
|
1005
|
-
},
|
|
1006
|
-
async getBox({ id }) {
|
|
1007
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1008
|
-
return id === sampleBox.id ? sampleBox : null;
|
|
1009
|
-
},
|
|
1010
728
|
async search(opts) {
|
|
1011
729
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1012
730
|
let filteredProducts = [...products];
|
|
@@ -1047,201 +765,18 @@ function createMockProductAdapter() {
|
|
|
1047
765
|
}
|
|
1048
766
|
};
|
|
1049
767
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
return {
|
|
1053
|
-
id: variant.id,
|
|
1054
|
-
title: variant.title,
|
|
1055
|
-
image: variant.image == null ? null : { url: variant.image.url, altText: variant.image.altText ?? void 0 },
|
|
1056
|
-
price: { amount: variant.price.toFixed(2), currencyCode },
|
|
1057
|
-
...((_a = variant.purchaseOptions) == null ? void 0 : _a.length) ? {
|
|
1058
|
-
purchaseOptions: variant.purchaseOptions.map((opt) => ({
|
|
1059
|
-
name: opt.name,
|
|
1060
|
-
price: { amount: opt.price.toFixed(2), currencyCode },
|
|
1061
|
-
interval: opt.interval
|
|
1062
|
-
}))
|
|
1063
|
-
} : {}
|
|
1064
|
-
};
|
|
1065
|
-
}
|
|
1066
|
-
function mapProduct(product, currencyCode) {
|
|
1067
|
-
return {
|
|
1068
|
-
id: product.id,
|
|
1069
|
-
title: product.title,
|
|
1070
|
-
featuredImage: product.image == null ? null : { url: product.image.url, altText: product.image.altText ?? void 0 },
|
|
1071
|
-
hasOnlyDefaultVariant: product.variants.length <= 1,
|
|
1072
|
-
variants: {
|
|
1073
|
-
items: product.variants.map((v2) => mapVariant(v2, currencyCode)),
|
|
1074
|
-
pageInfo: {
|
|
1075
|
-
hasNextPage: false,
|
|
1076
|
-
hasPrevPage: false,
|
|
1077
|
-
startCursor: null,
|
|
1078
|
-
endCursor: null
|
|
1079
|
-
}
|
|
1080
|
-
},
|
|
1081
|
-
collections: product.collections
|
|
1082
|
-
};
|
|
1083
|
-
}
|
|
1084
|
-
function createApiProductAdapter(fetcher, opts = { currencyCode: "USD" }) {
|
|
1085
|
-
const { currencyCode } = opts;
|
|
1086
|
-
async function fetchProducts(params) {
|
|
1087
|
-
const query = params.toString() ? `?${params.toString()}` : "";
|
|
1088
|
-
const res = await fetcher(`/customer/v1/products${query}`);
|
|
1089
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
1090
|
-
return res.json();
|
|
1091
|
-
}
|
|
768
|
+
const ProductServiceContext = createContext("services/product");
|
|
769
|
+
function createProductService(adapter) {
|
|
1092
770
|
return {
|
|
1093
771
|
async getById(id) {
|
|
1094
|
-
|
|
1095
|
-
const params = new URLSearchParams({ query: `id:"${id}"`, limit: "1" });
|
|
1096
|
-
const body = await fetchProducts(params);
|
|
1097
|
-
return body.data.length > 0 ? mapProduct(body.data[0], currencyCode) : null;
|
|
1098
|
-
} catch {
|
|
1099
|
-
return null;
|
|
1100
|
-
}
|
|
772
|
+
return adapter.getById(id);
|
|
1101
773
|
},
|
|
1102
774
|
async getByVariantId(variantId) {
|
|
1103
|
-
|
|
1104
|
-
const params = new URLSearchParams({
|
|
1105
|
-
query: `variants.id:"${variantId}"`,
|
|
1106
|
-
limit: "1"
|
|
1107
|
-
});
|
|
1108
|
-
const body = await fetchProducts(params);
|
|
1109
|
-
return body.data.length > 0 ? mapProduct(body.data[0], currencyCode) : null;
|
|
1110
|
-
} catch {
|
|
1111
|
-
return null;
|
|
1112
|
-
}
|
|
1113
|
-
},
|
|
1114
|
-
async search(opts2) {
|
|
1115
|
-
try {
|
|
1116
|
-
const params = new URLSearchParams();
|
|
1117
|
-
if (opts2 == null ? void 0 : opts2.query) {
|
|
1118
|
-
params.set("query", `"${opts2.query.trim().replace(/"/g, '\\"')}"`);
|
|
1119
|
-
}
|
|
1120
|
-
if (opts2 == null ? void 0 : opts2.pagination) {
|
|
1121
|
-
if ("after" in opts2.pagination)
|
|
1122
|
-
params.set("after", opts2.pagination.after);
|
|
1123
|
-
else if ("before" in opts2.pagination)
|
|
1124
|
-
params.set("before", opts2.pagination.before);
|
|
1125
|
-
}
|
|
1126
|
-
const body = await fetchProducts(params);
|
|
1127
|
-
return {
|
|
1128
|
-
items: body.data.map((p2) => mapProduct(p2, currencyCode)),
|
|
1129
|
-
pageInfo: {
|
|
1130
|
-
hasNextPage: body.hasNextPage,
|
|
1131
|
-
hasPrevPage: body.hasPrevPage,
|
|
1132
|
-
startCursor: body.startCursor,
|
|
1133
|
-
endCursor: body.endCursor
|
|
1134
|
-
}
|
|
1135
|
-
};
|
|
1136
|
-
} catch {
|
|
1137
|
-
return {
|
|
1138
|
-
items: [],
|
|
1139
|
-
pageInfo: {
|
|
1140
|
-
hasNextPage: false,
|
|
1141
|
-
hasPrevPage: false,
|
|
1142
|
-
startCursor: null,
|
|
1143
|
-
endCursor: null
|
|
1144
|
-
}
|
|
1145
|
-
};
|
|
1146
|
-
}
|
|
1147
|
-
},
|
|
1148
|
-
async getProductsByIds({ ids }) {
|
|
1149
|
-
const params = new URLSearchParams();
|
|
1150
|
-
for (const id of ids) params.append("ids", id);
|
|
1151
|
-
const res = await fetcher(`/customer/products/by-ids?${params.toString()}`);
|
|
1152
|
-
if (!res.ok) return [];
|
|
1153
|
-
const data = await res.json();
|
|
1154
|
-
return (data ?? []).map((p2) => ({
|
|
1155
|
-
id: p2.id,
|
|
1156
|
-
title: p2.title ?? "",
|
|
1157
|
-
featuredImage: p2.featuredImage ? { url: p2.featuredImage.url, altText: p2.featuredImage.altText } : null,
|
|
1158
|
-
hasOnlyDefaultVariant: true,
|
|
1159
|
-
collections: []
|
|
1160
|
-
}));
|
|
1161
|
-
},
|
|
1162
|
-
async getBoxVariants({ ids, subscriptionId }) {
|
|
1163
|
-
const params = new URLSearchParams();
|
|
1164
|
-
for (const id of ids) params.append("ids", id);
|
|
1165
|
-
params.set("subscriptionId", subscriptionId);
|
|
1166
|
-
const res = await fetcher(`/customer/products/variants?${params.toString()}`);
|
|
1167
|
-
if (!res.ok) return [];
|
|
1168
|
-
const data = await res.json();
|
|
1169
|
-
return (data ?? []).map((p2) => {
|
|
1170
|
-
var _a;
|
|
1171
|
-
return {
|
|
1172
|
-
id: p2.id,
|
|
1173
|
-
title: p2.title,
|
|
1174
|
-
description: p2.description ?? "",
|
|
1175
|
-
featuredImage: p2.featuredImage,
|
|
1176
|
-
hasOnlyDefaultVariant: p2.hasOnlyDefaultVariant ?? (((_a = p2.variants) == null ? void 0 : _a.length) ?? 0) <= 1,
|
|
1177
|
-
variants: (p2.variants ?? []).map((v2) => ({
|
|
1178
|
-
id: v2.id,
|
|
1179
|
-
availableForSale: v2.availableForSale,
|
|
1180
|
-
title: v2.title,
|
|
1181
|
-
currentPrice: v2.currentPrice,
|
|
1182
|
-
basePrice: v2.basePrice,
|
|
1183
|
-
image: v2.image,
|
|
1184
|
-
recurring: v2.recurring
|
|
1185
|
-
}))
|
|
1186
|
-
};
|
|
1187
|
-
});
|
|
1188
|
-
},
|
|
1189
|
-
async getAvailableProducts({ subscriptionId, lineId, q: q2, mode, action, pagination }) {
|
|
1190
|
-
const params = new URLSearchParams();
|
|
1191
|
-
params.set("action", action);
|
|
1192
|
-
if (q2) params.set("q", q2);
|
|
1193
|
-
if (mode) params.set("mode", mode);
|
|
1194
|
-
if (pagination && "after" in pagination) params.set("after", pagination.after);
|
|
1195
|
-
if (pagination && "before" in pagination) params.set("before", pagination.before);
|
|
1196
|
-
const res = await fetcher(
|
|
1197
|
-
`/customer/subscriptions/${subscriptionId}/lines/${lineId}/available-products?${params.toString()}`
|
|
1198
|
-
);
|
|
1199
|
-
if (!res.ok) return [];
|
|
1200
|
-
const data = await res.json();
|
|
1201
|
-
return (data ?? []).map((p2) => {
|
|
1202
|
-
var _a;
|
|
1203
|
-
return {
|
|
1204
|
-
id: p2.id,
|
|
1205
|
-
title: p2.title,
|
|
1206
|
-
description: p2.description ?? "",
|
|
1207
|
-
featuredImage: p2.featuredImage,
|
|
1208
|
-
hasOnlyDefaultVariant: p2.hasOnlyDefaultVariant ?? (((_a = p2.variants) == null ? void 0 : _a.length) ?? 0) <= 1,
|
|
1209
|
-
variants: (p2.variants ?? []).map((v2) => ({
|
|
1210
|
-
id: v2.id,
|
|
1211
|
-
availableForSale: v2.availableForSale,
|
|
1212
|
-
title: v2.title,
|
|
1213
|
-
currentPrice: v2.currentPrice,
|
|
1214
|
-
basePrice: v2.basePrice,
|
|
1215
|
-
image: v2.image,
|
|
1216
|
-
recurring: v2.recurring
|
|
1217
|
-
}))
|
|
1218
|
-
};
|
|
1219
|
-
});
|
|
1220
|
-
},
|
|
1221
|
-
async getBox({ id }) {
|
|
1222
|
-
const res = await fetcher(`/customer/boxes/${id}`);
|
|
1223
|
-
if (!res.ok) return null;
|
|
1224
|
-
const data = await res.json();
|
|
1225
|
-
return { id, ...data };
|
|
1226
|
-
}
|
|
1227
|
-
};
|
|
1228
|
-
}
|
|
1229
|
-
const ProductServiceContext = createContext("services/product");
|
|
1230
|
-
function createProductService(adapter) {
|
|
1231
|
-
return {
|
|
1232
|
-
async getById(id) {
|
|
1233
|
-
return adapter.getById(id);
|
|
1234
|
-
},
|
|
1235
|
-
async getByVariantId(variantId) {
|
|
1236
|
-
return adapter.getByVariantId(variantId);
|
|
775
|
+
return adapter.getByVariantId(variantId);
|
|
1237
776
|
},
|
|
1238
777
|
async search(opts) {
|
|
1239
778
|
return adapter.search(opts);
|
|
1240
|
-
}
|
|
1241
|
-
getProductsByIds: (ids) => adapter.getProductsByIds({ ids }),
|
|
1242
|
-
getBoxVariants: (ids, subscriptionId) => adapter.getBoxVariants({ ids, subscriptionId }),
|
|
1243
|
-
getAvailableProducts: (params) => adapter.getAvailableProducts(params),
|
|
1244
|
-
getBox: (id) => adapter.getBox({ id })
|
|
779
|
+
}
|
|
1245
780
|
};
|
|
1246
781
|
}
|
|
1247
782
|
function routeNameTableFromPages(pages) {
|
|
@@ -1295,74 +830,7 @@ function createMockRouterService() {
|
|
|
1295
830
|
}
|
|
1296
831
|
}).routerService;
|
|
1297
832
|
}
|
|
1298
|
-
function toAttributeArray(next) {
|
|
1299
|
-
return Object.entries(next).map(([key, value]) => ({ key, value }));
|
|
1300
|
-
}
|
|
1301
833
|
function createMockSubscriptionAdapter(options = {}) {
|
|
1302
|
-
const richBase = (id, itemId, renewalId) => ({
|
|
1303
|
-
id,
|
|
1304
|
-
customerId: "customer_1",
|
|
1305
|
-
items: [
|
|
1306
|
-
{
|
|
1307
|
-
id: itemId,
|
|
1308
|
-
// Aligned with the mock product catalog (createMockProductAdapter):
|
|
1309
|
-
// sample-3 "Gentle deodorant", variant sample-3-1 "Green tea and jasmine",
|
|
1310
|
-
// recurring price 5.36 EUR (10% off → 4.82 with SAVE10).
|
|
1311
|
-
productId: "sample-3",
|
|
1312
|
-
variantId: "sample-3-1",
|
|
1313
|
-
quantity: 2,
|
|
1314
|
-
price: { amount: "5.36", currencyCode: "EUR" },
|
|
1315
|
-
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
|
|
1316
|
-
isUpsell: false,
|
|
1317
|
-
isVirtual: false,
|
|
1318
|
-
nextBillingDate: "2025-11-15T00:00:00Z",
|
|
1319
|
-
currentPrice: { amount: "5.36", currencyCode: "EUR" },
|
|
1320
|
-
lineDiscountedPrice: { amount: "4.82", currencyCode: "EUR" },
|
|
1321
|
-
variantAvailableForSale: true,
|
|
1322
|
-
title: "Gentle deodorant for underarms and bust",
|
|
1323
|
-
variantTitle: "Green tea and jasmine",
|
|
1324
|
-
variantImage: { url: "https://placehold.co/400x400?text=Product+3a" },
|
|
1325
|
-
billingPolicy: { intervalCount: 1, interval: "MONTH" },
|
|
1326
|
-
deliveryPolicy: { intervalCount: 1, interval: "MONTH" }
|
|
1327
|
-
}
|
|
1328
|
-
],
|
|
1329
|
-
discounts: [
|
|
1330
|
-
{
|
|
1331
|
-
id: "discount_1",
|
|
1332
|
-
type: "percentage",
|
|
1333
|
-
value: 10,
|
|
1334
|
-
code: "SAVE10",
|
|
1335
|
-
description: "10% off subscription"
|
|
1336
|
-
}
|
|
1337
|
-
],
|
|
1338
|
-
status: "active",
|
|
1339
|
-
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
|
|
1340
|
-
frequency: "1 MONTH",
|
|
1341
|
-
createdAt: "2024-10-01T00:00:00Z",
|
|
1342
|
-
updatedAt: "2024-10-14T00:00:00Z",
|
|
1343
|
-
billingPolicy: { intervalCount: 1, interval: "MONTH", minCycles: 6 },
|
|
1344
|
-
deliveryPolicy: {
|
|
1345
|
-
intervalCount: 1,
|
|
1346
|
-
interval: "MONTH",
|
|
1347
|
-
anchors: [{ day: 15, type: "MONTHDAY" }]
|
|
1348
|
-
},
|
|
1349
|
-
nextBillingDate: "2025-11-15T00:00:00Z",
|
|
1350
|
-
nextBillingAttempt: { date: "2025-11-15T00:00:00Z", attempt: 1, ready: true },
|
|
1351
|
-
lastBillingAttempt: { date: "2025-10-15T00:00:00Z", ready: true },
|
|
1352
|
-
nextFulfillment: "2025-11-17T00:00:00Z",
|
|
1353
|
-
estimatedOrderDate: "2025-11-13T00:00:00Z",
|
|
1354
|
-
customerPaymentMethod: {
|
|
1355
|
-
id: "pm_1",
|
|
1356
|
-
instrument: { type: "credit_card", brand: "visa", maskedNumber: "************4242" },
|
|
1357
|
-
active: true,
|
|
1358
|
-
isRecurring: true
|
|
1359
|
-
},
|
|
1360
|
-
requiredBillingCyclesLeft: 3,
|
|
1361
|
-
renewal: { id: renewalId, isInActiveProcessState: false },
|
|
1362
|
-
lastPaymentStatus: "succeeded",
|
|
1363
|
-
pausePeriod: null,
|
|
1364
|
-
isEditable: true
|
|
1365
|
-
});
|
|
1366
834
|
const mockSubscriptions = [
|
|
1367
835
|
{
|
|
1368
836
|
id: "sub_1",
|
|
@@ -1370,27 +838,14 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1370
838
|
items: [
|
|
1371
839
|
{
|
|
1372
840
|
id: "item_1",
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
// 9.99 EUR (10% off → 8.99 with SAVE10).
|
|
1376
|
-
productId: "sample-1",
|
|
1377
|
-
variantId: "sample-1-1",
|
|
841
|
+
productId: "product_1",
|
|
842
|
+
variantId: "variant_1",
|
|
1378
843
|
quantity: 2,
|
|
1379
|
-
price: { amount: "
|
|
844
|
+
price: { amount: "29.99", currencyCode: "USD" },
|
|
1380
845
|
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
|
|
1381
|
-
isUpsell: false,
|
|
1382
|
-
isVirtual: false,
|
|
1383
|
-
nextBillingDate: "2025-11-15T00:00:00Z",
|
|
1384
|
-
currentPrice: { amount: "9.99", currencyCode: "EUR" },
|
|
1385
|
-
lineDiscountedPrice: { amount: "8.99", currencyCode: "EUR" },
|
|
1386
|
-
variantAvailableForSale: true,
|
|
1387
|
-
title: "Hydrating Gel Cleanser for Face and Eye Area",
|
|
1388
|
-
variantImage: { url: "https://placehold.co/400x400?text=Product+1" },
|
|
1389
|
-
billingPolicy: { intervalCount: 1, interval: "MONTH" },
|
|
1390
|
-
deliveryPolicy: { intervalCount: 1, interval: "MONTH" },
|
|
1391
846
|
customAttributes: [
|
|
1392
|
-
{ key: "
|
|
1393
|
-
{ key: "
|
|
847
|
+
{ key: "roast_level", value: "medium" },
|
|
848
|
+
{ key: "grind_type", value: "whole_bean" }
|
|
1394
849
|
]
|
|
1395
850
|
}
|
|
1396
851
|
],
|
|
@@ -1408,31 +863,9 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1408
863
|
frequency: "1 MONTH",
|
|
1409
864
|
createdAt: "2024-10-01T00:00:00Z",
|
|
1410
865
|
updatedAt: "2024-10-14T00:00:00Z",
|
|
1411
|
-
billingPolicy: { intervalCount: 1, interval: "MONTH", minCycles: 6 },
|
|
1412
|
-
deliveryPolicy: {
|
|
1413
|
-
intervalCount: 1,
|
|
1414
|
-
interval: "MONTH",
|
|
1415
|
-
anchors: [{ day: 15, type: "MONTHDAY" }]
|
|
1416
|
-
},
|
|
1417
|
-
nextBillingDate: "2025-11-15T00:00:00Z",
|
|
1418
|
-
nextBillingAttempt: { date: "2025-11-15T00:00:00Z", attempt: 1, ready: true },
|
|
1419
|
-
lastBillingAttempt: { date: "2025-10-15T00:00:00Z", ready: true },
|
|
1420
|
-
nextFulfillment: "2025-11-17T00:00:00Z",
|
|
1421
|
-
estimatedOrderDate: "2025-11-13T00:00:00Z",
|
|
1422
|
-
customerPaymentMethod: {
|
|
1423
|
-
id: "pm_1",
|
|
1424
|
-
instrument: { type: "credit_card", brand: "visa", maskedNumber: "************4242" },
|
|
1425
|
-
active: true,
|
|
1426
|
-
isRecurring: true
|
|
1427
|
-
},
|
|
1428
|
-
requiredBillingCyclesLeft: 3,
|
|
1429
|
-
renewal: { id: "ren_1", isInActiveProcessState: false },
|
|
1430
|
-
lastPaymentStatus: "succeeded",
|
|
1431
|
-
pausePeriod: null,
|
|
1432
|
-
isEditable: true,
|
|
1433
866
|
customAttributes: [
|
|
1434
867
|
{ key: "subscription_tier", value: "premium" },
|
|
1435
|
-
{ key: "gift_message", value: "Enjoy your
|
|
868
|
+
{ key: "gift_message", value: "Enjoy your coffee!" }
|
|
1436
869
|
]
|
|
1437
870
|
},
|
|
1438
871
|
{
|
|
@@ -1441,17 +874,11 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1441
874
|
items: [
|
|
1442
875
|
{
|
|
1443
876
|
id: "item_2",
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
productId: "sample-2",
|
|
1447
|
-
variantId: "sample-2-1",
|
|
877
|
+
productId: "product_2",
|
|
878
|
+
variantId: "variant_2",
|
|
1448
879
|
quantity: 1,
|
|
1449
|
-
price: { amount: "
|
|
880
|
+
price: { amount: "49.99", currencyCode: "USD" },
|
|
1450
881
|
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-20"),
|
|
1451
|
-
title: "More COLLAGEN",
|
|
1452
|
-
variantImage: { url: "https://placehold.co/400x400?text=Product+2" },
|
|
1453
|
-
billingPolicy: { intervalCount: 2, interval: "WEEK" },
|
|
1454
|
-
deliveryPolicy: { intervalCount: 2, interval: "WEEK" },
|
|
1455
882
|
customAttributes: []
|
|
1456
883
|
}
|
|
1457
884
|
],
|
|
@@ -1462,66 +889,17 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1462
889
|
createdAt: "2024-09-15T00:00:00Z",
|
|
1463
890
|
updatedAt: "2024-10-10T00:00:00Z",
|
|
1464
891
|
customAttributes: []
|
|
1465
|
-
},
|
|
1466
|
-
// Per-status fixtures: groundwork for the deferred editor preview picker
|
|
1467
|
-
// (docs/superpowers/specs/2026-06-17-renewalsummary-parity-and-mock-groundwork-design.md §9).
|
|
1468
|
-
// Not consumed yet — the editor still seeds the active sub_1 via getDefaultSubscriptionId().
|
|
1469
|
-
{
|
|
1470
|
-
...richBase("sub_paused", "item_paused", "ren_paused"),
|
|
1471
|
-
status: "paused",
|
|
1472
|
-
pausePeriod: { start: "2025-11-01T00:00:00Z", end: "2026-01-01T00:00:00Z" }
|
|
1473
|
-
},
|
|
1474
|
-
{
|
|
1475
|
-
...richBase("sub_canceled", "item_canceled", "ren_canceled"),
|
|
1476
|
-
status: "canceled",
|
|
1477
|
-
pausePeriod: null
|
|
1478
|
-
},
|
|
1479
|
-
{
|
|
1480
|
-
...richBase("sub_failed", "item_failed", "ren_failed"),
|
|
1481
|
-
status: "failed",
|
|
1482
|
-
lastPaymentStatus: "failed",
|
|
1483
|
-
pausePeriod: null
|
|
1484
|
-
},
|
|
1485
|
-
{
|
|
1486
|
-
...richBase("sub_expired", "item_expired", "ren_expired"),
|
|
1487
|
-
status: "expired",
|
|
1488
|
-
pausePeriod: null
|
|
1489
|
-
}
|
|
1490
|
-
];
|
|
1491
|
-
const mockUpsellProducts = [
|
|
1492
|
-
{
|
|
1493
|
-
id: "upsell-1",
|
|
1494
|
-
variantId: "upsell-v-1",
|
|
1495
|
-
title: "Retinol Night Cream",
|
|
1496
|
-
imageUrl: "https://images.unsplash.com/photo-1617897903246-719242758050?w=200",
|
|
1497
|
-
price: { amount: "38.00", currencyCode: "USD" },
|
|
1498
|
-
description: "Anti-aging night treatment"
|
|
1499
|
-
},
|
|
1500
|
-
{
|
|
1501
|
-
id: "upsell-2",
|
|
1502
|
-
variantId: "upsell-v-2",
|
|
1503
|
-
title: "SPF 50 Day Shield",
|
|
1504
|
-
imageUrl: "https://images.unsplash.com/photo-1556228578-8c89e6adf883?w=200",
|
|
1505
|
-
price: { amount: "24.00", currencyCode: "USD" },
|
|
1506
|
-
description: "Lightweight daily sun protection"
|
|
1507
892
|
}
|
|
1508
893
|
];
|
|
1509
894
|
return {
|
|
1510
895
|
async getById(id) {
|
|
1511
896
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1512
|
-
const subscription = mockSubscriptions.find((sub) => sub.id === id);
|
|
1513
|
-
return {
|
|
1514
|
-
_tag: "Success",
|
|
1515
|
-
data: subscription ? {
|
|
1516
|
-
...subscription,
|
|
1517
|
-
items: subscription.items.map((item) => ({ ...item })),
|
|
1518
|
-
discounts: subscription.discounts.map((d3) => ({ ...d3 }))
|
|
1519
|
-
} : null
|
|
1520
|
-
};
|
|
897
|
+
const subscription = mockSubscriptions.find((sub) => sub.id === id) || null;
|
|
898
|
+
return { _tag: "Success", data: subscription };
|
|
1521
899
|
},
|
|
1522
900
|
async search(options2 = {}) {
|
|
1523
901
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1524
|
-
const pageSize =
|
|
902
|
+
const pageSize = 1;
|
|
1525
903
|
const allItems = mockSubscriptions;
|
|
1526
904
|
let startIndex = 0;
|
|
1527
905
|
let endIndex = pageSize;
|
|
@@ -1537,108 +915,29 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1537
915
|
}
|
|
1538
916
|
}
|
|
1539
917
|
const pageItems = allItems.slice(startIndex, endIndex);
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
items:
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
startCursor: pageItems.length > 0 ? startIndex.toString() : null,
|
|
1552
|
-
endCursor: pageItems.length > 0 ? (endIndex - 1).toString() : null
|
|
1553
|
-
}
|
|
918
|
+
const paginatedList = {
|
|
919
|
+
items: pageItems.map((sub) => ({
|
|
920
|
+
...sub,
|
|
921
|
+
items: sub.items.map((item) => ({ ...item })),
|
|
922
|
+
discounts: sub.discounts.map((discount) => ({ ...discount }))
|
|
923
|
+
})),
|
|
924
|
+
pageInfo: {
|
|
925
|
+
hasNextPage: endIndex < allItems.length,
|
|
926
|
+
hasPrevPage: startIndex > 0,
|
|
927
|
+
startCursor: pageItems.length > 0 ? startIndex.toString() : null,
|
|
928
|
+
endCursor: pageItems.length > 0 ? (endIndex - 1).toString() : null
|
|
1554
929
|
}
|
|
1555
930
|
};
|
|
931
|
+
return { _tag: "Success", data: paginatedList };
|
|
1556
932
|
},
|
|
1557
|
-
async addItem(
|
|
1558
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
1559
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1560
|
-
const subscription = mockSubscriptions.find((sub) => sub.id === subscriptionId);
|
|
1561
|
-
if (!subscription) {
|
|
1562
|
-
return { _tag: "Failure", error: "Subscription not found" };
|
|
1563
|
-
}
|
|
1564
|
-
const currencyCode = ((_a = subscription.items[0]) == null ? void 0 : _a.price.currencyCode) ?? "USD";
|
|
1565
|
-
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;
|
|
1566
|
-
const variant = (product == null ? void 0 : product.variants.items.find((v2) => v2.id === item.variantId)) ?? (product == null ? void 0 : product.variants.items[0]);
|
|
1567
|
-
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);
|
|
1568
|
-
subscription.items.push({
|
|
1569
|
-
id: `item_${Date.now()}_${subscription.items.length}`,
|
|
1570
|
-
productId: (product == null ? void 0 : product.id) ?? "",
|
|
1571
|
-
variantId: item.variantId,
|
|
1572
|
-
quantity: item.quantity,
|
|
1573
|
-
price: linePrice ? { ...linePrice } : { amount: "0.00", currencyCode },
|
|
1574
|
-
...linePrice ? { currentPrice: { ...linePrice } } : {},
|
|
1575
|
-
title: (product == null ? void 0 : product.title) ?? `Product ${item.variantId}`,
|
|
1576
|
-
...variant && product && !product.hasOnlyDefaultVariant ? { variantTitle: variant.title } : {},
|
|
1577
|
-
...(variant == null ? void 0 : variant.image) ? { variantImage: variant.image } : {},
|
|
1578
|
-
variantAvailableForSale: true,
|
|
1579
|
-
billingPolicy: ((_f = subscription.items[0]) == null ? void 0 : _f.billingPolicy) ?? subscription.billingPolicy ?? null,
|
|
1580
|
-
deliveryPolicy: ((_g = subscription.items[0]) == null ? void 0 : _g.deliveryPolicy) ?? subscription.deliveryPolicy ?? null
|
|
1581
|
-
});
|
|
1582
|
-
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1583
|
-
return { _tag: "Success", data: void 0 };
|
|
1584
|
-
},
|
|
1585
|
-
async removeItem({ subscriptionId, itemId }) {
|
|
1586
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1587
|
-
const subscription = mockSubscriptions.find((sub) => sub.id === subscriptionId);
|
|
1588
|
-
if (!subscription) {
|
|
1589
|
-
return { _tag: "Failure", error: "Subscription not found" };
|
|
1590
|
-
}
|
|
1591
|
-
subscription.items = subscription.items.filter((i3) => i3.id !== itemId);
|
|
1592
|
-
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1593
|
-
return { _tag: "Success", data: void 0 };
|
|
1594
|
-
},
|
|
1595
|
-
async updateItem({ subscriptionId, lineId, update }) {
|
|
1596
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1597
|
-
const subscription = mockSubscriptions.find((sub) => sub.id === subscriptionId);
|
|
1598
|
-
if (!subscription) {
|
|
1599
|
-
return { _tag: "Failure", error: "Subscription not found" };
|
|
1600
|
-
}
|
|
1601
|
-
const item = subscription.items.find((i3) => i3.id === lineId);
|
|
1602
|
-
if (!item) {
|
|
1603
|
-
return { _tag: "Failure", error: "Line item not found" };
|
|
1604
|
-
}
|
|
1605
|
-
if (update.variantId !== void 0) item.variantId = update.variantId;
|
|
1606
|
-
if (update.quantity !== void 0) item.quantity = update.quantity;
|
|
1607
|
-
if (update.billingPolicy !== void 0) item.billingPolicy = update.billingPolicy;
|
|
1608
|
-
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1609
|
-
return { _tag: "Success", data: void 0 };
|
|
1610
|
-
},
|
|
1611
|
-
async updateItemAttributes({ subscriptionId, lineId, customAttributes }) {
|
|
1612
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1613
|
-
const subscription = mockSubscriptions.find((sub) => sub.id === subscriptionId);
|
|
1614
|
-
if (!subscription) {
|
|
1615
|
-
return { _tag: "Failure", error: "Subscription not found" };
|
|
1616
|
-
}
|
|
1617
|
-
const item = subscription.items.find((i3) => i3.id === lineId);
|
|
1618
|
-
if (!item) {
|
|
1619
|
-
return { _tag: "Failure", error: "Line item not found" };
|
|
1620
|
-
}
|
|
1621
|
-
item.customAttributes = toAttributeArray(customAttributes);
|
|
1622
|
-
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1623
|
-
return { _tag: "Success", data: void 0 };
|
|
1624
|
-
},
|
|
1625
|
-
async updateAttributes({ subscriptionId, customAttributes }) {
|
|
933
|
+
async addItem() {
|
|
1626
934
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1627
|
-
const subscription = mockSubscriptions.find((sub) => sub.id === subscriptionId);
|
|
1628
|
-
if (!subscription) {
|
|
1629
|
-
return { _tag: "Failure", error: "Subscription not found" };
|
|
1630
|
-
}
|
|
1631
|
-
subscription.customAttributes = toAttributeArray(customAttributes);
|
|
1632
|
-
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1633
935
|
return { _tag: "Success", data: void 0 };
|
|
1634
936
|
},
|
|
1635
|
-
async
|
|
937
|
+
async removeItem() {
|
|
1636
938
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1637
939
|
return { _tag: "Success", data: void 0 };
|
|
1638
940
|
},
|
|
1639
|
-
async updateBoxItems() {
|
|
1640
|
-
return { _tag: "Success", data: void 0 };
|
|
1641
|
-
},
|
|
1642
941
|
async addDiscount() {
|
|
1643
942
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1644
943
|
const behavior = options.addDiscountBehavior ?? { kind: "success" };
|
|
@@ -1667,29 +966,24 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1667
966
|
(sub) => sub.id === params.subscriptionId
|
|
1668
967
|
);
|
|
1669
968
|
if (!subscription) {
|
|
1670
|
-
return {
|
|
969
|
+
return {
|
|
970
|
+
_tag: "Failure",
|
|
971
|
+
error: "Subscription not found"
|
|
972
|
+
};
|
|
1671
973
|
}
|
|
1672
974
|
subscription.nextDeliveryDate = new Date(params.newDate);
|
|
1673
975
|
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
(attr) => attr.key.startsWith("_")
|
|
1686
|
-
);
|
|
1687
|
-
const next = Object.entries(params.customAttributes).map(
|
|
1688
|
-
([key, value]) => ({ key, value })
|
|
1689
|
-
);
|
|
1690
|
-
subscription.customAttributes = [...preserved, ...next];
|
|
1691
|
-
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1692
|
-
return { _tag: "Success", data: { ...subscription } };
|
|
976
|
+
subscription.items.forEach((item) => {
|
|
977
|
+
item.nextDeliveryDate = new Date(params.newDate);
|
|
978
|
+
});
|
|
979
|
+
return {
|
|
980
|
+
_tag: "Success",
|
|
981
|
+
data: {
|
|
982
|
+
...subscription,
|
|
983
|
+
items: subscription.items.map((item) => ({ ...item })),
|
|
984
|
+
discounts: subscription.discounts.map((discount) => ({ ...discount }))
|
|
985
|
+
}
|
|
986
|
+
};
|
|
1693
987
|
},
|
|
1694
988
|
async resume(params) {
|
|
1695
989
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1697,11 +991,21 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1697
991
|
(sub) => sub.id === params.subscriptionId
|
|
1698
992
|
);
|
|
1699
993
|
if (!subscription) {
|
|
1700
|
-
return {
|
|
994
|
+
return {
|
|
995
|
+
_tag: "Failure",
|
|
996
|
+
error: "Subscription not found"
|
|
997
|
+
};
|
|
1701
998
|
}
|
|
1702
999
|
subscription.status = "active";
|
|
1703
1000
|
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1704
|
-
return {
|
|
1001
|
+
return {
|
|
1002
|
+
_tag: "Success",
|
|
1003
|
+
data: {
|
|
1004
|
+
...subscription,
|
|
1005
|
+
items: subscription.items.map((item) => ({ ...item })),
|
|
1006
|
+
discounts: subscription.discounts.map((discount) => ({ ...discount }))
|
|
1007
|
+
}
|
|
1008
|
+
};
|
|
1705
1009
|
},
|
|
1706
1010
|
async pause(params) {
|
|
1707
1011
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1709,11 +1013,21 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1709
1013
|
(sub) => sub.id === params.subscriptionId
|
|
1710
1014
|
);
|
|
1711
1015
|
if (!subscription) {
|
|
1712
|
-
return {
|
|
1016
|
+
return {
|
|
1017
|
+
_tag: "Failure",
|
|
1018
|
+
error: "Subscription not found"
|
|
1019
|
+
};
|
|
1713
1020
|
}
|
|
1714
1021
|
subscription.status = "paused";
|
|
1715
1022
|
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1716
|
-
return {
|
|
1023
|
+
return {
|
|
1024
|
+
_tag: "Success",
|
|
1025
|
+
data: {
|
|
1026
|
+
...subscription,
|
|
1027
|
+
items: subscription.items.map((item) => ({ ...item })),
|
|
1028
|
+
discounts: subscription.discounts.map((discount) => ({ ...discount }))
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1717
1031
|
},
|
|
1718
1032
|
async reactivate(params) {
|
|
1719
1033
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1721,11 +1035,21 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1721
1035
|
(sub) => sub.id === params.subscriptionId
|
|
1722
1036
|
);
|
|
1723
1037
|
if (!subscription) {
|
|
1724
|
-
return {
|
|
1038
|
+
return {
|
|
1039
|
+
_tag: "Failure",
|
|
1040
|
+
error: "Subscription not found"
|
|
1041
|
+
};
|
|
1725
1042
|
}
|
|
1726
1043
|
subscription.status = "active";
|
|
1727
1044
|
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1728
|
-
return {
|
|
1045
|
+
return {
|
|
1046
|
+
_tag: "Success",
|
|
1047
|
+
data: {
|
|
1048
|
+
...subscription,
|
|
1049
|
+
items: subscription.items.map((item) => ({ ...item })),
|
|
1050
|
+
discounts: subscription.discounts.map((discount) => ({ ...discount }))
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1729
1053
|
},
|
|
1730
1054
|
async cancel(params) {
|
|
1731
1055
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1733,11 +1057,21 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1733
1057
|
(sub) => sub.id === params.subscriptionId
|
|
1734
1058
|
);
|
|
1735
1059
|
if (!subscription) {
|
|
1736
|
-
return {
|
|
1060
|
+
return {
|
|
1061
|
+
_tag: "Failure",
|
|
1062
|
+
error: "Subscription not found"
|
|
1063
|
+
};
|
|
1737
1064
|
}
|
|
1738
1065
|
subscription.status = "canceled";
|
|
1739
1066
|
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1740
|
-
return {
|
|
1067
|
+
return {
|
|
1068
|
+
_tag: "Success",
|
|
1069
|
+
data: {
|
|
1070
|
+
...subscription,
|
|
1071
|
+
items: subscription.items.map((item) => ({ ...item })),
|
|
1072
|
+
discounts: subscription.discounts.map((discount) => ({ ...discount }))
|
|
1073
|
+
}
|
|
1074
|
+
};
|
|
1741
1075
|
},
|
|
1742
1076
|
async getAvailablePlans() {
|
|
1743
1077
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1765,1042 +1099,13 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1765
1099
|
]
|
|
1766
1100
|
};
|
|
1767
1101
|
},
|
|
1768
|
-
async getLastOrder(params) {
|
|
1769
|
-
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
1770
|
-
const subscription = mockSubscriptions.find((sub) => sub.id === params.subscriptionId);
|
|
1771
|
-
if (!subscription) return { _tag: "Success", data: null };
|
|
1772
|
-
return {
|
|
1773
|
-
_tag: "Success",
|
|
1774
|
-
data: {
|
|
1775
|
-
id: `mock_last_order_${params.subscriptionId}`,
|
|
1776
|
-
createdAt: "2026-04-22T12:00:00Z"
|
|
1777
|
-
}
|
|
1778
|
-
};
|
|
1779
|
-
},
|
|
1780
|
-
async renewNow(_params) {
|
|
1781
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1782
|
-
return { _tag: "Success", data: { result: "success" } };
|
|
1783
|
-
},
|
|
1784
|
-
async changeFrequency(params) {
|
|
1785
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1786
|
-
const subscription = mockSubscriptions.find((sub) => sub.id === params.subscriptionId);
|
|
1787
|
-
if (!subscription) {
|
|
1788
|
-
return { _tag: "Failure", error: "Subscription not found" };
|
|
1789
|
-
}
|
|
1790
|
-
if (typeof params.plan === "string") {
|
|
1791
|
-
subscription.frequency = `1 ${params.plan}`;
|
|
1792
|
-
} else {
|
|
1793
|
-
subscription.frequency = `${params.plan.intervalCount} ${params.plan.interval}`;
|
|
1794
|
-
if (subscription.billingPolicy) {
|
|
1795
|
-
subscription.billingPolicy = { ...subscription.billingPolicy, ...params.plan };
|
|
1796
|
-
}
|
|
1797
|
-
if (subscription.deliveryPolicy) {
|
|
1798
|
-
subscription.deliveryPolicy = { ...subscription.deliveryPolicy, ...params.plan };
|
|
1799
|
-
}
|
|
1800
|
-
}
|
|
1801
|
-
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1802
|
-
return {
|
|
1803
|
-
_tag: "Success",
|
|
1804
|
-
data: {
|
|
1805
|
-
...subscription,
|
|
1806
|
-
items: subscription.items.map((item) => ({ ...item })),
|
|
1807
|
-
discounts: subscription.discounts.map((d3) => ({ ...d3 }))
|
|
1808
|
-
}
|
|
1809
|
-
};
|
|
1810
|
-
},
|
|
1811
1102
|
async getDefaultSubscriptionId() {
|
|
1812
1103
|
var _a;
|
|
1813
1104
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1814
1105
|
return { _tag: "Success", data: ((_a = mockSubscriptions[0]) == null ? void 0 : _a.id) ?? null };
|
|
1815
|
-
},
|
|
1816
|
-
async getUpsellProducts() {
|
|
1817
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1818
|
-
return { _tag: "Success", data: [...mockUpsellProducts] };
|
|
1819
|
-
},
|
|
1820
|
-
async addUpsellProduct() {
|
|
1821
|
-
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
1822
|
-
return { _tag: "Success", data: void 0 };
|
|
1823
|
-
}
|
|
1824
|
-
};
|
|
1825
|
-
}
|
|
1826
|
-
function normalizeInstrumentType(type) {
|
|
1827
|
-
return type.replace(/-/g, "_");
|
|
1828
|
-
}
|
|
1829
|
-
function mapPaymentMethod(rawPm) {
|
|
1830
|
-
if (!rawPm) return null;
|
|
1831
|
-
if (typeof rawPm === "string") {
|
|
1832
|
-
return { id: rawPm };
|
|
1833
|
-
}
|
|
1834
|
-
return {
|
|
1835
|
-
id: rawPm.id ?? "",
|
|
1836
|
-
...rawPm.instrument != null ? {
|
|
1837
|
-
instrument: {
|
|
1838
|
-
...rawPm.instrument,
|
|
1839
|
-
type: normalizeInstrumentType(rawPm.instrument.type)
|
|
1840
|
-
}
|
|
1841
|
-
} : {},
|
|
1842
|
-
...rawPm.active != null ? { active: rawPm.active } : {},
|
|
1843
|
-
...rawPm.isRecurring != null ? { isRecurring: rawPm.isRecurring } : {}
|
|
1844
|
-
};
|
|
1845
|
-
}
|
|
1846
|
-
function mapSubscription(raw) {
|
|
1847
|
-
var _a, _b;
|
|
1848
|
-
const status = raw.status === "merged" ? "canceled" : raw.status;
|
|
1849
|
-
const deliveryPolicy = raw.deliveryPolicy ?? ((_b = (_a = raw.items) == null ? void 0 : _a[0]) == null ? void 0 : _b.deliveryPolicy);
|
|
1850
|
-
const frequency = deliveryPolicy ? `${deliveryPolicy.intervalCount} ${deliveryPolicy.interval}` : "";
|
|
1851
|
-
return {
|
|
1852
|
-
id: raw.id,
|
|
1853
|
-
customerId: "",
|
|
1854
|
-
serial: raw.serial,
|
|
1855
|
-
items: (raw.items ?? []).map(
|
|
1856
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1857
|
-
(item) => ({
|
|
1858
|
-
id: item.id,
|
|
1859
|
-
productId: item.productId ?? item.product ?? "",
|
|
1860
|
-
variantId: item.variantId ?? item.variant ?? "",
|
|
1861
|
-
quantity: item.quantity,
|
|
1862
|
-
price: item.price ?? {
|
|
1863
|
-
amount: String(item.totalPrice ?? 0),
|
|
1864
|
-
currencyCode: raw.currencyCode ?? ""
|
|
1865
|
-
},
|
|
1866
|
-
nextDeliveryDate: item.nextDeliveryDate ? new Date(item.nextDeliveryDate) : null,
|
|
1867
|
-
billingPolicy: item.billingPolicy ?? raw.billingPolicy ?? null,
|
|
1868
|
-
deliveryPolicy: item.deliveryPolicy ?? raw.deliveryPolicy ?? null,
|
|
1869
|
-
// Map human-readable titles from the v1 SubscriptionItemResource
|
|
1870
|
-
title: item.title,
|
|
1871
|
-
variantTitle: item.subtitle ?? void 0,
|
|
1872
|
-
// recurringCycleLimit === 1 means the item charges exactly once (one-time upsell)
|
|
1873
|
-
recurringCycleLimit: item.recurringCycleLimit ?? null,
|
|
1874
|
-
customAttributes: Array.isArray(item.customAttributes) ? item.customAttributes : []
|
|
1875
|
-
})
|
|
1876
|
-
),
|
|
1877
|
-
discounts: (raw.discounts ?? []).map(
|
|
1878
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1879
|
-
(d3) => {
|
|
1880
|
-
var _a2, _b2, _c;
|
|
1881
|
-
return {
|
|
1882
|
-
id: d3.id,
|
|
1883
|
-
type: ((_a2 = d3.value) == null ? void 0 : _a2.type) === "fixed-amount" || d3.type === "fixed_amount" ? "fixed_amount" : "percentage",
|
|
1884
|
-
value: ((_b2 = d3.value) == null ? void 0 : _b2.amount) ?? ((_c = d3.value) == null ? void 0 : _c.percentage) ?? d3.value ?? 0,
|
|
1885
|
-
code: d3.title ?? d3.code ?? "",
|
|
1886
|
-
description: d3.description ?? ""
|
|
1887
|
-
};
|
|
1888
|
-
}
|
|
1889
|
-
),
|
|
1890
|
-
status,
|
|
1891
|
-
nextDeliveryDate: raw.nextBillingDate ? new Date(raw.nextBillingDate) : raw.nextDeliveryDate ? new Date(raw.nextDeliveryDate) : null,
|
|
1892
|
-
// Map nextBillingDate as the raw ISO string for ProductSelect skip() and other consumers
|
|
1893
|
-
nextBillingDate: raw.nextBillingDate ?? null,
|
|
1894
|
-
// Map customerPaymentMethod — note: arrives as bare id (not expanded) since the
|
|
1895
|
-
// subscriptions endpoint does not support ?expand=paymentMethod; instrument digits
|
|
1896
|
-
// remain a data gap pending backend API extension.
|
|
1897
|
-
customerPaymentMethod: mapPaymentMethod(raw.paymentMethod),
|
|
1898
|
-
frequency,
|
|
1899
|
-
createdAt: raw.createdAt,
|
|
1900
|
-
updatedAt: raw.updatedAt,
|
|
1901
|
-
billingPolicy: raw.billingPolicy ?? null,
|
|
1902
|
-
deliveryPolicy: raw.deliveryPolicy ?? null,
|
|
1903
|
-
customAttributes: Array.isArray(raw.customAttributes) ? raw.customAttributes : []
|
|
1904
|
-
};
|
|
1905
|
-
}
|
|
1906
|
-
function createApiSubscriptionAdapter(fetcher) {
|
|
1907
|
-
const adapter = {
|
|
1908
|
-
async search(options) {
|
|
1909
|
-
var _a;
|
|
1910
|
-
try {
|
|
1911
|
-
const params = new URLSearchParams();
|
|
1912
|
-
if ((_a = options == null ? void 0 : options.filters) == null ? void 0 : _a.length) {
|
|
1913
|
-
const q2 = options.filters.filter((f2) => Object.keys(f2).length > 0).flatMap((f2) => Object.entries(f2).filter(([, v2]) => Boolean(v2))).map(([k, v2]) => `${k}:'${v2}'`).join(" AND ");
|
|
1914
|
-
if (q2) params.set("query", q2);
|
|
1915
|
-
}
|
|
1916
|
-
if (options == null ? void 0 : options.pagination) {
|
|
1917
|
-
if ("after" in options.pagination)
|
|
1918
|
-
params.set("after", options.pagination.after);
|
|
1919
|
-
else if ("before" in options.pagination)
|
|
1920
|
-
params.set("before", options.pagination.before);
|
|
1921
|
-
}
|
|
1922
|
-
const query = params.toString() ? `?${params.toString()}` : "";
|
|
1923
|
-
const res = await fetcher(`/customer/v1/subscriptions${query}`);
|
|
1924
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1925
|
-
const body = await res.json();
|
|
1926
|
-
return {
|
|
1927
|
-
_tag: "Success",
|
|
1928
|
-
data: {
|
|
1929
|
-
items: body.data.map(mapSubscription),
|
|
1930
|
-
pageInfo: {
|
|
1931
|
-
hasNextPage: body.hasNextPage,
|
|
1932
|
-
hasPrevPage: body.hasPrevPage,
|
|
1933
|
-
startCursor: body.startCursor,
|
|
1934
|
-
endCursor: body.endCursor
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
};
|
|
1938
|
-
} catch (e2) {
|
|
1939
|
-
return { _tag: "Failure", error: e2 };
|
|
1940
|
-
}
|
|
1941
|
-
},
|
|
1942
|
-
async getById(id) {
|
|
1943
|
-
try {
|
|
1944
|
-
const res = await fetcher(
|
|
1945
|
-
`/customer/v1/subscriptions?query=id:"${id}"&limit=1`
|
|
1946
|
-
);
|
|
1947
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1948
|
-
const body = await res.json();
|
|
1949
|
-
const raw = body.data[0];
|
|
1950
|
-
return { _tag: "Success", data: raw ? mapSubscription(raw) : null };
|
|
1951
|
-
} catch (e2) {
|
|
1952
|
-
return { _tag: "Failure", error: e2 };
|
|
1953
|
-
}
|
|
1954
|
-
},
|
|
1955
|
-
async addItem({ subscriptionId, item }) {
|
|
1956
|
-
try {
|
|
1957
|
-
const res = await fetcher(
|
|
1958
|
-
`/customer/v1/subscriptions/${subscriptionId}/items`,
|
|
1959
|
-
{
|
|
1960
|
-
method: "POST",
|
|
1961
|
-
headers: { "Content-Type": "application/json" },
|
|
1962
|
-
body: JSON.stringify(item)
|
|
1963
|
-
}
|
|
1964
|
-
);
|
|
1965
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1966
|
-
return { _tag: "Success", data: void 0 };
|
|
1967
|
-
} catch (e2) {
|
|
1968
|
-
return { _tag: "Failure", error: e2 };
|
|
1969
|
-
}
|
|
1970
|
-
},
|
|
1971
|
-
async removeItem({ subscriptionId, itemId }) {
|
|
1972
|
-
try {
|
|
1973
|
-
const res = await fetcher(
|
|
1974
|
-
`/customer/v1/subscriptions/${subscriptionId}/items/${itemId}`,
|
|
1975
|
-
{ method: "DELETE" }
|
|
1976
|
-
);
|
|
1977
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1978
|
-
return { _tag: "Success", data: void 0 };
|
|
1979
|
-
} catch (e2) {
|
|
1980
|
-
return { _tag: "Failure", error: e2 };
|
|
1981
|
-
}
|
|
1982
|
-
},
|
|
1983
|
-
async updateItem({ subscriptionId, lineId, update }) {
|
|
1984
|
-
try {
|
|
1985
|
-
const body = {
|
|
1986
|
-
...update.variantId !== void 0 ? { productVariantId: update.variantId } : {},
|
|
1987
|
-
...update.quantity !== void 0 ? { quantity: update.quantity } : {},
|
|
1988
|
-
...update.billingPolicy !== void 0 ? { billingPolicy: update.billingPolicy } : {},
|
|
1989
|
-
...update.shippingMethodHandle !== void 0 ? { shippingMethodHandle: update.shippingMethodHandle } : {}
|
|
1990
|
-
};
|
|
1991
|
-
const res = await fetcher(
|
|
1992
|
-
`/customer/subscriptions/${subscriptionId}/lines/${lineId}`,
|
|
1993
|
-
{
|
|
1994
|
-
method: "PUT",
|
|
1995
|
-
headers: { "Content-Type": "application/json" },
|
|
1996
|
-
body: JSON.stringify(body)
|
|
1997
|
-
}
|
|
1998
|
-
);
|
|
1999
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2000
|
-
return { _tag: "Success", data: void 0 };
|
|
2001
|
-
} catch (e2) {
|
|
2002
|
-
return { _tag: "Failure", error: e2 };
|
|
2003
|
-
}
|
|
2004
|
-
},
|
|
2005
|
-
async updateItemAttributes({ subscriptionId, lineId, customAttributes }) {
|
|
2006
|
-
try {
|
|
2007
|
-
const res = await fetcher(
|
|
2008
|
-
`/customer/v1/subscriptions/${subscriptionId}/items/${lineId}`,
|
|
2009
|
-
{
|
|
2010
|
-
method: "PATCH",
|
|
2011
|
-
headers: { "Content-Type": "application/json" },
|
|
2012
|
-
body: JSON.stringify({ customAttributes })
|
|
2013
|
-
}
|
|
2014
|
-
);
|
|
2015
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2016
|
-
return { _tag: "Success", data: void 0 };
|
|
2017
|
-
} catch (e2) {
|
|
2018
|
-
return { _tag: "Failure", error: e2 };
|
|
2019
|
-
}
|
|
2020
|
-
},
|
|
2021
|
-
async updateAttributes({ subscriptionId, customAttributes }) {
|
|
2022
|
-
try {
|
|
2023
|
-
const res = await fetcher(
|
|
2024
|
-
`/customer/v1/subscriptions/${subscriptionId}`,
|
|
2025
|
-
{
|
|
2026
|
-
method: "PATCH",
|
|
2027
|
-
headers: { "Content-Type": "application/json" },
|
|
2028
|
-
body: JSON.stringify({ customAttributes })
|
|
2029
|
-
}
|
|
2030
|
-
);
|
|
2031
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2032
|
-
return { _tag: "Success", data: void 0 };
|
|
2033
|
-
} catch (e2) {
|
|
2034
|
-
return { _tag: "Failure", error: e2 };
|
|
2035
|
-
}
|
|
2036
|
-
},
|
|
2037
|
-
async skipLineItem({ subscriptionId, lineId, nextBillingDate }) {
|
|
2038
|
-
try {
|
|
2039
|
-
const res = await fetcher(
|
|
2040
|
-
`/customer/subscriptions/${subscriptionId}/lines/${lineId}`,
|
|
2041
|
-
{
|
|
2042
|
-
method: "PUT",
|
|
2043
|
-
headers: { "Content-Type": "application/json" },
|
|
2044
|
-
body: JSON.stringify({ nextBillingDate })
|
|
2045
|
-
}
|
|
2046
|
-
);
|
|
2047
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2048
|
-
return { _tag: "Success", data: void 0 };
|
|
2049
|
-
} catch (e2) {
|
|
2050
|
-
return { _tag: "Failure", error: e2 };
|
|
2051
|
-
}
|
|
2052
|
-
},
|
|
2053
|
-
async updateBoxItems({ subscriptionId, parentId, items, shippingMethodHandle }) {
|
|
2054
|
-
try {
|
|
2055
|
-
const res = await fetcher(
|
|
2056
|
-
`/customer/subscriptions/${subscriptionId}/update-box-products`,
|
|
2057
|
-
{
|
|
2058
|
-
method: "POST",
|
|
2059
|
-
headers: { "Content-Type": "application/json" },
|
|
2060
|
-
body: JSON.stringify({ parentId, items, shippingMethodHandle })
|
|
2061
|
-
}
|
|
2062
|
-
);
|
|
2063
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2064
|
-
return { _tag: "Success", data: void 0 };
|
|
2065
|
-
} catch (e2) {
|
|
2066
|
-
return { _tag: "Failure", error: e2 };
|
|
2067
|
-
}
|
|
2068
|
-
},
|
|
2069
|
-
async addDiscount({ subscriptionId, code }) {
|
|
2070
|
-
try {
|
|
2071
|
-
const res = await fetcher(
|
|
2072
|
-
`/customer/v1/subscriptions/${subscriptionId}/discounts`,
|
|
2073
|
-
{
|
|
2074
|
-
method: "POST",
|
|
2075
|
-
headers: { "Content-Type": "application/json" },
|
|
2076
|
-
body: JSON.stringify({ code })
|
|
2077
|
-
}
|
|
2078
|
-
);
|
|
2079
|
-
if (!res.ok) return { _tag: "Failure", error: { kind: "NETWORK", message: `HTTP ${res.status}` } };
|
|
2080
|
-
return { _tag: "Success", data: void 0 };
|
|
2081
|
-
} catch (e2) {
|
|
2082
|
-
return { _tag: "Failure", error: { kind: "UNKNOWN", message: e2 instanceof Error ? e2.message : void 0 } };
|
|
2083
|
-
}
|
|
2084
|
-
},
|
|
2085
|
-
async removeDiscount({ subscriptionId, discountId }) {
|
|
2086
|
-
try {
|
|
2087
|
-
const res = await fetcher(
|
|
2088
|
-
`/customer/v1/subscriptions/${subscriptionId}/discounts/${discountId}`,
|
|
2089
|
-
{ method: "DELETE" }
|
|
2090
|
-
);
|
|
2091
|
-
if (!res.ok) return { _tag: "Failure", error: { kind: "NETWORK", message: `HTTP ${res.status}` } };
|
|
2092
|
-
return { _tag: "Success", data: void 0 };
|
|
2093
|
-
} catch (e2) {
|
|
2094
|
-
return { _tag: "Failure", error: { kind: "UNKNOWN", message: e2 instanceof Error ? e2.message : void 0 } };
|
|
2095
|
-
}
|
|
2096
|
-
},
|
|
2097
|
-
// Uses PATCH /customer/v1/subscriptions/{id} — the dedicated /reschedule route does not exist.
|
|
2098
|
-
async reschedule({ subscriptionId, newDate }) {
|
|
2099
|
-
try {
|
|
2100
|
-
const res = await fetcher(
|
|
2101
|
-
`/customer/v1/subscriptions/${subscriptionId}`,
|
|
2102
|
-
{
|
|
2103
|
-
method: "PATCH",
|
|
2104
|
-
headers: { "Content-Type": "application/json" },
|
|
2105
|
-
body: JSON.stringify({ nextBillingDate: newDate })
|
|
2106
|
-
}
|
|
2107
|
-
);
|
|
2108
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2109
|
-
const data = await res.json();
|
|
2110
|
-
return { _tag: "Success", data: mapSubscription(data) };
|
|
2111
|
-
} catch (e2) {
|
|
2112
|
-
return { _tag: "Failure", error: e2 };
|
|
2113
|
-
}
|
|
2114
|
-
},
|
|
2115
|
-
// PATCH /customer/v1/subscriptions/{id} with the full customer-visible set.
|
|
2116
|
-
async updateCustomAttributes({ subscriptionId, customAttributes }) {
|
|
2117
|
-
try {
|
|
2118
|
-
const res = await fetcher(
|
|
2119
|
-
`/customer/v1/subscriptions/${subscriptionId}`,
|
|
2120
|
-
{
|
|
2121
|
-
method: "PATCH",
|
|
2122
|
-
headers: { "Content-Type": "application/json" },
|
|
2123
|
-
body: JSON.stringify({ customAttributes })
|
|
2124
|
-
}
|
|
2125
|
-
);
|
|
2126
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2127
|
-
const data = await res.json();
|
|
2128
|
-
return { _tag: "Success", data: mapSubscription(data) };
|
|
2129
|
-
} catch (e2) {
|
|
2130
|
-
return { _tag: "Failure", error: e2 };
|
|
2131
|
-
}
|
|
2132
|
-
},
|
|
2133
|
-
async resume({ subscriptionId }) {
|
|
2134
|
-
try {
|
|
2135
|
-
const res = await fetcher(
|
|
2136
|
-
`/customer/v1/subscriptions/${subscriptionId}/resume`,
|
|
2137
|
-
{ method: "POST" }
|
|
2138
|
-
);
|
|
2139
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2140
|
-
const data = await res.json();
|
|
2141
|
-
return { _tag: "Success", data: mapSubscription(data) };
|
|
2142
|
-
} catch (e2) {
|
|
2143
|
-
return { _tag: "Failure", error: e2 };
|
|
2144
|
-
}
|
|
2145
|
-
},
|
|
2146
|
-
async pause({ subscriptionId }) {
|
|
2147
|
-
try {
|
|
2148
|
-
const res = await fetcher(
|
|
2149
|
-
`/customer/v1/subscriptions/${subscriptionId}/pause`,
|
|
2150
|
-
{ method: "POST" }
|
|
2151
|
-
);
|
|
2152
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2153
|
-
const data = await res.json();
|
|
2154
|
-
return { _tag: "Success", data: mapSubscription(data) };
|
|
2155
|
-
} catch (e2) {
|
|
2156
|
-
return { _tag: "Failure", error: e2 };
|
|
2157
|
-
}
|
|
2158
|
-
},
|
|
2159
|
-
async reactivate({ subscriptionId }) {
|
|
2160
|
-
try {
|
|
2161
|
-
const res = await fetcher(
|
|
2162
|
-
`/customer/v1/subscriptions/${subscriptionId}/reactivate`,
|
|
2163
|
-
{ method: "POST" }
|
|
2164
|
-
);
|
|
2165
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2166
|
-
const data = await res.json();
|
|
2167
|
-
return { _tag: "Success", data: mapSubscription(data) };
|
|
2168
|
-
} catch (e2) {
|
|
2169
|
-
return { _tag: "Failure", error: e2 };
|
|
2170
|
-
}
|
|
2171
|
-
},
|
|
2172
|
-
async cancel({ subscriptionId, reason }) {
|
|
2173
|
-
try {
|
|
2174
|
-
const res = await fetcher(
|
|
2175
|
-
`/customer/v1/subscriptions/${subscriptionId}/cancel`,
|
|
2176
|
-
{
|
|
2177
|
-
method: "POST",
|
|
2178
|
-
headers: { "Content-Type": "application/json" },
|
|
2179
|
-
body: JSON.stringify({ cancellationReason: reason })
|
|
2180
|
-
}
|
|
2181
|
-
);
|
|
2182
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2183
|
-
const data = await res.json();
|
|
2184
|
-
return { _tag: "Success", data: mapSubscription(data) };
|
|
2185
|
-
} catch (e2) {
|
|
2186
|
-
return { _tag: "Failure", error: e2 };
|
|
2187
|
-
}
|
|
2188
|
-
},
|
|
2189
|
-
// Legacy endpoint — no /customer/v1/subscriptions/{id}/plans exists yet.
|
|
2190
|
-
async getAvailablePlans({ subscriptionId }) {
|
|
2191
|
-
try {
|
|
2192
|
-
const res = await fetcher(
|
|
2193
|
-
`/customer/subscriptions/${subscriptionId}/plans`
|
|
2194
|
-
);
|
|
2195
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2196
|
-
const data = await res.json();
|
|
2197
|
-
return { _tag: "Success", data };
|
|
2198
|
-
} catch (e2) {
|
|
2199
|
-
return { _tag: "Failure", error: e2 };
|
|
2200
|
-
}
|
|
2201
|
-
},
|
|
2202
|
-
// Legacy endpoint — no /customer/v1 equivalent exists yet.
|
|
2203
|
-
async getDefaultSubscriptionId() {
|
|
2204
|
-
try {
|
|
2205
|
-
const res = await fetcher(
|
|
2206
|
-
`/customer/subscriptions/one-by-next-billing-date`
|
|
2207
|
-
);
|
|
2208
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2209
|
-
const data = await res.json();
|
|
2210
|
-
return { _tag: "Success", data: (data == null ? void 0 : data.id) ?? null };
|
|
2211
|
-
} catch (e2) {
|
|
2212
|
-
return { _tag: "Failure", error: e2 };
|
|
2213
|
-
}
|
|
2214
|
-
},
|
|
2215
|
-
// Legacy endpoint — no /customer/v1/subscriptions/{id}/upsells exists yet.
|
|
2216
|
-
async getUpsellProducts({ subscriptionId }) {
|
|
2217
|
-
try {
|
|
2218
|
-
const res = await fetcher(
|
|
2219
|
-
`/customer/subscriptions/${subscriptionId}/upsell-products`
|
|
2220
|
-
);
|
|
2221
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2222
|
-
const data = await res.json();
|
|
2223
|
-
const products = data.map((p2) => {
|
|
2224
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
2225
|
-
return {
|
|
2226
|
-
id: p2.id,
|
|
2227
|
-
variantId: ((_b = (_a = p2.variants) == null ? void 0 : _a[0]) == null ? void 0 : _b.id) ?? "",
|
|
2228
|
-
title: p2.title ?? "",
|
|
2229
|
-
imageUrl: ((_c = p2.featuredImage) == null ? void 0 : _c.url) ?? void 0,
|
|
2230
|
-
price: {
|
|
2231
|
-
amount: String(((_f = (_e = (_d = p2.variants) == null ? void 0 : _d[0]) == null ? void 0 : _e.currentPrice) == null ? void 0 : _f.amount) ?? 0),
|
|
2232
|
-
currencyCode: ((_i = (_h = (_g = p2.variants) == null ? void 0 : _g[0]) == null ? void 0 : _h.currentPrice) == null ? void 0 : _i.currencyCode) ?? ""
|
|
2233
|
-
},
|
|
2234
|
-
// recurring comes from the upsell rule on variants[0]; present in PreparedProductSchema
|
|
2235
|
-
recurring: (_k = (_j = p2.variants) == null ? void 0 : _j[0]) == null ? void 0 : _k.recurring
|
|
2236
|
-
};
|
|
2237
|
-
});
|
|
2238
|
-
return { _tag: "Success", data: products };
|
|
2239
|
-
} catch (e2) {
|
|
2240
|
-
return { _tag: "Failure", error: e2 };
|
|
2241
|
-
}
|
|
2242
|
-
},
|
|
2243
|
-
// Legacy endpoint — no /customer/v1/subscriptions/{id}/upsells POST exists yet.
|
|
2244
|
-
async addUpsellProduct({ subscriptionId, variantId, quantity, oneTime }) {
|
|
2245
|
-
try {
|
|
2246
|
-
const res = await fetcher(
|
|
2247
|
-
`/customer/subscriptions/${subscriptionId}/upsell`,
|
|
2248
|
-
{
|
|
2249
|
-
method: "POST",
|
|
2250
|
-
headers: { "Content-Type": "application/json" },
|
|
2251
|
-
body: JSON.stringify({
|
|
2252
|
-
productVariantId: variantId,
|
|
2253
|
-
quantity,
|
|
2254
|
-
...oneTime ? { renewalLimit: 1 } : {}
|
|
2255
|
-
})
|
|
2256
|
-
}
|
|
2257
|
-
);
|
|
2258
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2259
|
-
return { _tag: "Success", data: void 0 };
|
|
2260
|
-
} catch (e2) {
|
|
2261
|
-
return { _tag: "Failure", error: e2 };
|
|
2262
|
-
}
|
|
2263
|
-
},
|
|
2264
|
-
// Legacy endpoint — no /customer/v1 equivalent exists yet.
|
|
2265
|
-
async getLastOrder({ subscriptionId }) {
|
|
2266
|
-
try {
|
|
2267
|
-
const res = await fetcher(
|
|
2268
|
-
`/customer/subscriptions/${subscriptionId}/last-order`
|
|
2269
|
-
);
|
|
2270
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2271
|
-
const data = await res.json();
|
|
2272
|
-
if (!data) return { _tag: "Success", data: null };
|
|
2273
|
-
return {
|
|
2274
|
-
_tag: "Success",
|
|
2275
|
-
data: { id: data.id, createdAt: data.createdAt }
|
|
2276
|
-
};
|
|
2277
|
-
} catch (e2) {
|
|
2278
|
-
return { _tag: "Failure", error: e2 };
|
|
2279
|
-
}
|
|
2280
|
-
},
|
|
2281
|
-
// Legacy endpoints, split by stage (see SubscriptionService.renewNow docs):
|
|
2282
|
-
// retry → POST /customer/subscriptions/{id}/retry
|
|
2283
|
-
// renewalId → POST /customer/renewals/{renewalId}/renew
|
|
2284
|
-
// default → POST /customer/subscriptions/{id}/order-now
|
|
2285
|
-
async renewNow({ subscriptionId, renewalId, retry }) {
|
|
2286
|
-
try {
|
|
2287
|
-
const url = retry ? `/customer/subscriptions/${subscriptionId}/retry` : renewalId ? `/customer/renewals/${renewalId}/renew` : `/customer/subscriptions/${subscriptionId}/order-now`;
|
|
2288
|
-
const res = await fetcher(url, { method: "POST" });
|
|
2289
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2290
|
-
const body = res.status === 204 ? null : await res.json();
|
|
2291
|
-
return {
|
|
2292
|
-
_tag: "Success",
|
|
2293
|
-
data: {
|
|
2294
|
-
nextActionUrl: (body == null ? void 0 : body.nextActionUrl) ?? void 0,
|
|
2295
|
-
result: (body == null ? void 0 : body.result) ?? "success"
|
|
2296
|
-
}
|
|
2297
|
-
};
|
|
2298
|
-
} catch (e2) {
|
|
2299
|
-
return { _tag: "Failure", error: e2 };
|
|
2300
|
-
}
|
|
2301
|
-
},
|
|
2302
|
-
// Legacy endpoint — POST /plan returns 204; re-fetch to return the updated subscription.
|
|
2303
|
-
async changeFrequency({ subscriptionId, plan }) {
|
|
2304
|
-
try {
|
|
2305
|
-
const res = await fetcher(
|
|
2306
|
-
`/customer/subscriptions/${subscriptionId}/plan`,
|
|
2307
|
-
{
|
|
2308
|
-
method: "POST",
|
|
2309
|
-
headers: { "Content-Type": "application/json" },
|
|
2310
|
-
body: JSON.stringify({ plan })
|
|
2311
|
-
}
|
|
2312
|
-
);
|
|
2313
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2314
|
-
const refreshed = await adapter.getById(subscriptionId);
|
|
2315
|
-
if (refreshed._tag === "Failure") return refreshed;
|
|
2316
|
-
if (refreshed.data) return { _tag: "Success", data: refreshed.data };
|
|
2317
|
-
return {
|
|
2318
|
-
_tag: "Failure",
|
|
2319
|
-
error: "Subscription not found after frequency change"
|
|
2320
|
-
};
|
|
2321
|
-
} catch (e2) {
|
|
2322
|
-
return { _tag: "Failure", error: e2 };
|
|
2323
|
-
}
|
|
2324
1106
|
}
|
|
2325
1107
|
};
|
|
2326
|
-
return adapter;
|
|
2327
|
-
}
|
|
2328
|
-
function toIsoOrNull(value) {
|
|
2329
|
-
const date = new Date(value);
|
|
2330
|
-
return Number.isNaN(date.getTime()) ? null : date.toISOString();
|
|
2331
|
-
}
|
|
2332
|
-
function buildMatcher(params) {
|
|
2333
|
-
const { cycle, date } = params;
|
|
2334
|
-
let iso;
|
|
2335
|
-
if (date != null) {
|
|
2336
|
-
const parsed = toIsoOrNull(date);
|
|
2337
|
-
if (parsed == null) return { ok: false, error: "date must be a valid date" };
|
|
2338
|
-
iso = parsed;
|
|
2339
|
-
}
|
|
2340
|
-
if (cycle != null && iso != null) {
|
|
2341
|
-
return { ok: true, matcher: { type: "CYCLE_AND_DATE", input: { cycle, date: iso } } };
|
|
2342
|
-
}
|
|
2343
|
-
if (cycle != null) return { ok: true, matcher: { type: "CYCLE", input: { cycle } } };
|
|
2344
|
-
if (iso != null) return { ok: true, matcher: { type: "DATE", input: { date: iso } } };
|
|
2345
|
-
return { ok: false, error: "Either cycle or date is required" };
|
|
2346
|
-
}
|
|
2347
|
-
const DELIVERY_PRICE_CENTS = 500;
|
|
2348
|
-
const DELIVERY_OFFSET_DAYS = 2;
|
|
2349
|
-
function toCents(amount) {
|
|
2350
|
-
const n2 = Number.parseFloat(amount ?? "0");
|
|
2351
|
-
return Number.isFinite(n2) ? Math.round(n2 * 100) : 0;
|
|
2352
|
-
}
|
|
2353
|
-
function addInterval(date, interval, units) {
|
|
2354
|
-
const d3 = new Date(date);
|
|
2355
|
-
switch (interval) {
|
|
2356
|
-
case "DAY":
|
|
2357
|
-
d3.setDate(d3.getDate() + units);
|
|
2358
|
-
break;
|
|
2359
|
-
case "WEEK":
|
|
2360
|
-
d3.setDate(d3.getDate() + units * 7);
|
|
2361
|
-
break;
|
|
2362
|
-
case "YEAR":
|
|
2363
|
-
d3.setFullYear(d3.getFullYear() + units);
|
|
2364
|
-
break;
|
|
2365
|
-
default:
|
|
2366
|
-
d3.setMonth(d3.getMonth() + units);
|
|
2367
|
-
break;
|
|
2368
|
-
}
|
|
2369
|
-
return d3;
|
|
2370
|
-
}
|
|
2371
|
-
function mapItem(sub, item, cycle) {
|
|
2372
|
-
var _a, _b;
|
|
2373
|
-
const price = toCents(((_a = item.currentPrice) == null ? void 0 : _a.amount) ?? item.price.amount);
|
|
2374
|
-
return {
|
|
2375
|
-
id: `${sub.id}_cycle_${cycle}_${item.id}`,
|
|
2376
|
-
title: item.title ?? `Product ${item.variantId}`,
|
|
2377
|
-
subtitle: item.variantTitle ?? null,
|
|
2378
|
-
imageUrl: (_b = item.variantImage) == null ? void 0 : _b.url,
|
|
2379
|
-
variantId: item.variantId,
|
|
2380
|
-
quantity: item.quantity,
|
|
2381
|
-
price,
|
|
2382
|
-
totalPrice: price * item.quantity,
|
|
2383
|
-
variantImage: item.variantImage ?? null,
|
|
2384
|
-
variantAvailableForSale: item.variantAvailableForSale ?? true,
|
|
2385
|
-
subscriptionId: sub.id,
|
|
2386
|
-
subscriptionLineId: item.id,
|
|
2387
|
-
productId: item.productId,
|
|
2388
|
-
parentProductId: item.parentProductId ?? null,
|
|
2389
|
-
parentLineId: item.parentLineId ?? null,
|
|
2390
|
-
isVirtual: item.isVirtual ?? false,
|
|
2391
|
-
isUpsell: item.isUpsell ?? false,
|
|
2392
|
-
recurringCycleLimit: item.recurringCycleLimit ?? null,
|
|
2393
|
-
customAttributes: item.customAttributes ?? []
|
|
2394
|
-
};
|
|
2395
|
-
}
|
|
2396
|
-
function projectUpcomingOrders(sub, count) {
|
|
2397
|
-
var _a, _b;
|
|
2398
|
-
if (sub.status !== "active") return [];
|
|
2399
|
-
const billing = sub.billingPolicy ?? ((_a = sub.items[0]) == null ? void 0 : _a.billingPolicy) ?? { interval: "MONTH", intervalCount: 1 };
|
|
2400
|
-
const baseStr = sub.nextBillingDate ?? (sub.nextDeliveryDate ? sub.nextDeliveryDate.toISOString() : null);
|
|
2401
|
-
const base = baseStr ? new Date(baseStr) : /* @__PURE__ */ new Date();
|
|
2402
|
-
const currencyCode = ((_b = sub.items[0]) == null ? void 0 : _b.price.currencyCode) ?? "USD";
|
|
2403
|
-
const orders = [];
|
|
2404
|
-
for (let cycle = 0; cycle < count; cycle++) {
|
|
2405
|
-
const billingDate = addInterval(
|
|
2406
|
-
base,
|
|
2407
|
-
billing.interval,
|
|
2408
|
-
cycle * billing.intervalCount
|
|
2409
|
-
);
|
|
2410
|
-
const deliveryDate = addInterval(billingDate, "DAY", DELIVERY_OFFSET_DAYS);
|
|
2411
|
-
const items = sub.items.map((item) => mapItem(sub, item, cycle));
|
|
2412
|
-
const subtotal = items.reduce((sum, it) => sum + it.totalPrice, 0);
|
|
2413
|
-
orders.push({
|
|
2414
|
-
id: `${sub.id}_cycle_${cycle}`,
|
|
2415
|
-
customerId: sub.customerId,
|
|
2416
|
-
subscriptionId: sub.id,
|
|
2417
|
-
date: billingDate.toISOString(),
|
|
2418
|
-
skipped: false,
|
|
2419
|
-
currencyCode,
|
|
2420
|
-
subtotal,
|
|
2421
|
-
deliveryPrice: DELIVERY_PRICE_CENTS,
|
|
2422
|
-
cycleIndex: cycle,
|
|
2423
|
-
deliveryDate: deliveryDate.toISOString(),
|
|
2424
|
-
status: "scheduled",
|
|
2425
|
-
items,
|
|
2426
|
-
discounts: sub.discounts.map((d3) => ({
|
|
2427
|
-
id: d3.id,
|
|
2428
|
-
title: d3.code,
|
|
2429
|
-
type: d3.type,
|
|
2430
|
-
value: d3.value
|
|
2431
|
-
}))
|
|
2432
|
-
});
|
|
2433
|
-
}
|
|
2434
|
-
return orders;
|
|
2435
|
-
}
|
|
2436
|
-
function applyAdjustments(orders, stored) {
|
|
2437
|
-
return orders.map((order) => {
|
|
2438
|
-
let next = order;
|
|
2439
|
-
for (const { adjustment, subscriptionId, cycle } of stored) {
|
|
2440
|
-
if (subscriptionId !== order.subscriptionId) continue;
|
|
2441
|
-
if (cycle !== order.cycleIndex) continue;
|
|
2442
|
-
const { action } = adjustment;
|
|
2443
|
-
if (action.type === "SKIP_ORDER") {
|
|
2444
|
-
next = { ...next, skipped: true, status: "skipped" };
|
|
2445
|
-
} else if (action.type === "CHANGE_DATE") {
|
|
2446
|
-
next = {
|
|
2447
|
-
...next,
|
|
2448
|
-
date: action.input.newDate,
|
|
2449
|
-
deliveryDate: action.input.newDate
|
|
2450
|
-
};
|
|
2451
|
-
}
|
|
2452
|
-
}
|
|
2453
|
-
return next;
|
|
2454
|
-
});
|
|
2455
1108
|
}
|
|
2456
|
-
function createMockSchedulesAdapter(subscriptions = createMockSubscriptionAdapter()) {
|
|
2457
|
-
const RESOLVE_DEPTH = 12;
|
|
2458
|
-
let stored = [];
|
|
2459
|
-
let idSeq = 0;
|
|
2460
|
-
async function subscriptionsToProject(subscriptionId) {
|
|
2461
|
-
if (subscriptionId) {
|
|
2462
|
-
const res = await subscriptions.getById(subscriptionId);
|
|
2463
|
-
return res._tag === "Success" && res.data ? [res.data] : [];
|
|
2464
|
-
}
|
|
2465
|
-
const all = [];
|
|
2466
|
-
let pagination;
|
|
2467
|
-
for (let guard = 0; guard < 50; guard++) {
|
|
2468
|
-
const res = await subscriptions.search(pagination ? { pagination } : {});
|
|
2469
|
-
if (res._tag !== "Success") break;
|
|
2470
|
-
all.push(...res.data.items);
|
|
2471
|
-
const { hasNextPage, endCursor } = res.data.pageInfo;
|
|
2472
|
-
if (!hasNextPage || !endCursor) break;
|
|
2473
|
-
pagination = { after: endCursor };
|
|
2474
|
-
}
|
|
2475
|
-
return all;
|
|
2476
|
-
}
|
|
2477
|
-
function resolveCycle(orders, opts) {
|
|
2478
|
-
if (opts.cycle != null) return opts.cycle;
|
|
2479
|
-
if (opts.date) {
|
|
2480
|
-
const iso = toIsoOrNull(opts.date);
|
|
2481
|
-
const target = iso == null ? void 0 : iso.split("T")[0];
|
|
2482
|
-
const match = target ? orders.find(
|
|
2483
|
-
(o2) => o2.deliveryDate.split("T")[0] === target || o2.date.split("T")[0] === target
|
|
2484
|
-
) : void 0;
|
|
2485
|
-
if (match) return match.cycleIndex;
|
|
2486
|
-
}
|
|
2487
|
-
const firstScheduled = orders.find((o2) => o2.status === "scheduled");
|
|
2488
|
-
return (firstScheduled == null ? void 0 : firstScheduled.cycleIndex) ?? null;
|
|
2489
|
-
}
|
|
2490
|
-
async function recordAdjustment(subscriptionId, opts, buildAction) {
|
|
2491
|
-
const res = await subscriptions.getById(subscriptionId);
|
|
2492
|
-
const sub = res._tag === "Success" ? res.data : null;
|
|
2493
|
-
if (!sub) return { _tag: "Failure", error: "No scheduled order found" };
|
|
2494
|
-
const orders = applyAdjustments(
|
|
2495
|
-
projectUpcomingOrders(sub, RESOLVE_DEPTH),
|
|
2496
|
-
stored
|
|
2497
|
-
);
|
|
2498
|
-
const cycle = resolveCycle(orders, opts);
|
|
2499
|
-
if (cycle == null) {
|
|
2500
|
-
return { _tag: "Failure", error: "No scheduled order found" };
|
|
2501
|
-
}
|
|
2502
|
-
const built = buildMatcher({ cycle, date: opts.date });
|
|
2503
|
-
const matcher = built.ok ? built.matcher : { type: "CYCLE", input: { cycle } };
|
|
2504
|
-
stored = [
|
|
2505
|
-
...stored,
|
|
2506
|
-
{
|
|
2507
|
-
adjustment: { id: `adj-${idSeq++}`, matcher, action: buildAction() },
|
|
2508
|
-
subscriptionId,
|
|
2509
|
-
cycle
|
|
2510
|
-
}
|
|
2511
|
-
];
|
|
2512
|
-
return { _tag: "Success", data: void 0 };
|
|
2513
|
-
}
|
|
2514
|
-
return {
|
|
2515
|
-
async getUpcomingOrders({ count, subscriptionId }) {
|
|
2516
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
2517
|
-
const subs = await subscriptionsToProject(subscriptionId);
|
|
2518
|
-
const orders = subs.flatMap(
|
|
2519
|
-
(sub) => applyAdjustments(projectUpcomingOrders(sub, count), stored)
|
|
2520
|
-
).sort((a3, b3) => a3.date.localeCompare(b3.date));
|
|
2521
|
-
return { _tag: "Success", data: orders.slice(0, count) };
|
|
2522
|
-
},
|
|
2523
|
-
async getAdjustments() {
|
|
2524
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
2525
|
-
return { _tag: "Success", data: stored.map((s2) => s2.adjustment) };
|
|
2526
|
-
},
|
|
2527
|
-
async skipOrder({ subscriptionId, cycle, date }) {
|
|
2528
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
2529
|
-
return recordAdjustment(subscriptionId, { cycle, date }, () => ({
|
|
2530
|
-
type: "SKIP_ORDER",
|
|
2531
|
-
input: { reason: "" }
|
|
2532
|
-
}));
|
|
2533
|
-
},
|
|
2534
|
-
async changeDateAdjustment({ subscriptionId, newDate, cycle, currentDate }) {
|
|
2535
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
2536
|
-
const newIso = toIsoOrNull(newDate);
|
|
2537
|
-
if (newIso == null) {
|
|
2538
|
-
return { _tag: "Failure", error: "newDate must be a valid date" };
|
|
2539
|
-
}
|
|
2540
|
-
return recordAdjustment(
|
|
2541
|
-
subscriptionId,
|
|
2542
|
-
{ cycle, date: currentDate },
|
|
2543
|
-
() => ({
|
|
2544
|
-
type: "CHANGE_DATE",
|
|
2545
|
-
input: { newDate: newIso }
|
|
2546
|
-
})
|
|
2547
|
-
);
|
|
2548
|
-
},
|
|
2549
|
-
async updateShippingAdjustment({ subscriptionId, address, cycle, date }) {
|
|
2550
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
2551
|
-
return recordAdjustment(subscriptionId, { cycle, date }, () => ({
|
|
2552
|
-
type: "UPDATE_SHIPPING",
|
|
2553
|
-
input: { address }
|
|
2554
|
-
}));
|
|
2555
|
-
},
|
|
2556
|
-
async updatePaymentMethodAdjustment({
|
|
2557
|
-
subscriptionId,
|
|
2558
|
-
paymentMethodId,
|
|
2559
|
-
cycle,
|
|
2560
|
-
date
|
|
2561
|
-
}) {
|
|
2562
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
2563
|
-
return recordAdjustment(subscriptionId, { cycle, date }, () => ({
|
|
2564
|
-
type: "UPDATE_PAYMENT_METHOD",
|
|
2565
|
-
input: { paymentMethodId }
|
|
2566
|
-
}));
|
|
2567
|
-
},
|
|
2568
|
-
async updateProductsAdjustment({ subscriptionId, lines, cycle, date }) {
|
|
2569
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
2570
|
-
return recordAdjustment(subscriptionId, { cycle, date }, () => ({
|
|
2571
|
-
type: "UPDATE_PRODUCTS",
|
|
2572
|
-
input: { lines }
|
|
2573
|
-
}));
|
|
2574
|
-
},
|
|
2575
|
-
async applyDiscountAdjustment({ subscriptionId, discountCode, cycle }) {
|
|
2576
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
2577
|
-
return recordAdjustment(subscriptionId, { cycle }, () => ({
|
|
2578
|
-
type: "APPLY_DISCOUNT",
|
|
2579
|
-
input: { discountSource: "code", discountCode }
|
|
2580
|
-
}));
|
|
2581
|
-
},
|
|
2582
|
-
async removeAdjustment({ adjustmentId }) {
|
|
2583
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
2584
|
-
stored = stored.filter((s2) => s2.adjustment.id !== adjustmentId);
|
|
2585
|
-
return { _tag: "Success", data: void 0 };
|
|
2586
|
-
}
|
|
2587
|
-
};
|
|
2588
|
-
}
|
|
2589
|
-
function createApiSchedulesAdapter(fetcher) {
|
|
2590
|
-
async function postAdjustment(matcher, action) {
|
|
2591
|
-
try {
|
|
2592
|
-
const res = await fetcher(`/customer/v1/schedules/adjustments`, {
|
|
2593
|
-
method: "POST",
|
|
2594
|
-
headers: { "Content-Type": "application/json" },
|
|
2595
|
-
body: JSON.stringify({ matcher, action })
|
|
2596
|
-
});
|
|
2597
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2598
|
-
return { _tag: "Success", data: void 0 };
|
|
2599
|
-
} catch (e2) {
|
|
2600
|
-
return { _tag: "Failure", error: e2 };
|
|
2601
|
-
}
|
|
2602
|
-
}
|
|
2603
|
-
return {
|
|
2604
|
-
async getUpcomingOrders({ count, subscriptionId }) {
|
|
2605
|
-
try {
|
|
2606
|
-
const params = new URLSearchParams({ count: String(count) });
|
|
2607
|
-
if (subscriptionId) params.set("query", `id:"${subscriptionId}"`);
|
|
2608
|
-
const res = await fetcher(`/customer/v1/schedules/?${params.toString()}`);
|
|
2609
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2610
|
-
const data = await res.json();
|
|
2611
|
-
return { _tag: "Success", data: data.orders };
|
|
2612
|
-
} catch (e2) {
|
|
2613
|
-
return { _tag: "Failure", error: e2 };
|
|
2614
|
-
}
|
|
2615
|
-
},
|
|
2616
|
-
async getAdjustments() {
|
|
2617
|
-
try {
|
|
2618
|
-
const res = await fetcher(`/customer/v1/schedules/adjustments`);
|
|
2619
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2620
|
-
const data = await res.json();
|
|
2621
|
-
const adjustments = data.data.map((a3) => ({
|
|
2622
|
-
id: a3.id,
|
|
2623
|
-
matcher: a3.matcher,
|
|
2624
|
-
action: a3.action
|
|
2625
|
-
}));
|
|
2626
|
-
return { _tag: "Success", data: adjustments };
|
|
2627
|
-
} catch (e2) {
|
|
2628
|
-
return { _tag: "Failure", error: e2 };
|
|
2629
|
-
}
|
|
2630
|
-
},
|
|
2631
|
-
async skipOrder({ cycle, date }) {
|
|
2632
|
-
const built = buildMatcher({ cycle, date });
|
|
2633
|
-
if (!built.ok) return { _tag: "Failure", error: built.error };
|
|
2634
|
-
return postAdjustment(built.matcher, {
|
|
2635
|
-
type: "SKIP_ORDER",
|
|
2636
|
-
input: { reason: "" }
|
|
2637
|
-
});
|
|
2638
|
-
},
|
|
2639
|
-
async changeDateAdjustment({ newDate, cycle }) {
|
|
2640
|
-
if (cycle == null) {
|
|
2641
|
-
return {
|
|
2642
|
-
_tag: "Failure",
|
|
2643
|
-
error: "cycle is required for changeDateAdjustment"
|
|
2644
|
-
};
|
|
2645
|
-
}
|
|
2646
|
-
const newIso = toIsoOrNull(newDate);
|
|
2647
|
-
if (newIso == null) {
|
|
2648
|
-
return { _tag: "Failure", error: "newDate must be a valid date" };
|
|
2649
|
-
}
|
|
2650
|
-
return postAdjustment(
|
|
2651
|
-
{ type: "CYCLE", input: { cycle } },
|
|
2652
|
-
{ type: "CHANGE_DATE", input: { newDate: newIso } }
|
|
2653
|
-
);
|
|
2654
|
-
},
|
|
2655
|
-
async updateShippingAdjustment({ address, cycle, date }) {
|
|
2656
|
-
const built = buildMatcher({ cycle, date });
|
|
2657
|
-
if (!built.ok) return { _tag: "Failure", error: built.error };
|
|
2658
|
-
return postAdjustment(built.matcher, {
|
|
2659
|
-
type: "UPDATE_SHIPPING",
|
|
2660
|
-
input: { address }
|
|
2661
|
-
});
|
|
2662
|
-
},
|
|
2663
|
-
async updatePaymentMethodAdjustment({ paymentMethodId, cycle, date }) {
|
|
2664
|
-
const built = buildMatcher({ cycle, date });
|
|
2665
|
-
if (!built.ok) return { _tag: "Failure", error: built.error };
|
|
2666
|
-
return postAdjustment(built.matcher, {
|
|
2667
|
-
type: "UPDATE_PAYMENT_METHOD",
|
|
2668
|
-
input: { paymentMethodId }
|
|
2669
|
-
});
|
|
2670
|
-
},
|
|
2671
|
-
async updateProductsAdjustment({ lines, cycle, date }) {
|
|
2672
|
-
const built = buildMatcher({ cycle, date });
|
|
2673
|
-
if (!built.ok) return { _tag: "Failure", error: built.error };
|
|
2674
|
-
return postAdjustment(built.matcher, {
|
|
2675
|
-
type: "UPDATE_PRODUCTS",
|
|
2676
|
-
input: { lines }
|
|
2677
|
-
});
|
|
2678
|
-
},
|
|
2679
|
-
async applyDiscountAdjustment({ discountCode, cycle }) {
|
|
2680
|
-
return postAdjustment(
|
|
2681
|
-
{ type: "CYCLE", input: { cycle } },
|
|
2682
|
-
{
|
|
2683
|
-
type: "APPLY_DISCOUNT",
|
|
2684
|
-
input: { discountSource: "code", discountCode }
|
|
2685
|
-
}
|
|
2686
|
-
);
|
|
2687
|
-
},
|
|
2688
|
-
async removeAdjustment({ adjustmentId }) {
|
|
2689
|
-
try {
|
|
2690
|
-
const res = await fetcher(
|
|
2691
|
-
`/customer/v1/schedules/adjustments/${adjustmentId}`,
|
|
2692
|
-
{ method: "DELETE" }
|
|
2693
|
-
);
|
|
2694
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
2695
|
-
return { _tag: "Success", data: void 0 };
|
|
2696
|
-
} catch (e2) {
|
|
2697
|
-
return { _tag: "Failure", error: e2 };
|
|
2698
|
-
}
|
|
2699
|
-
}
|
|
2700
|
-
};
|
|
2701
|
-
}
|
|
2702
|
-
const SchedulesServiceContext = createContext("services/schedules");
|
|
2703
|
-
function createSchedulesService(adapter, opts) {
|
|
2704
|
-
const current = d(null);
|
|
2705
|
-
const currentLoading = d(false);
|
|
2706
|
-
const hasPendingBilling = (opts == null ? void 0 : opts.hasPendingBilling) ?? d(false);
|
|
2707
|
-
let reloadToken = 0;
|
|
2708
|
-
async function getUpcomingOrder() {
|
|
2709
|
-
const result = await adapter.getUpcomingOrders({ count: 1 });
|
|
2710
|
-
if (result._tag === "Failure") return result;
|
|
2711
|
-
return { _tag: "Success", data: result.data[0] ?? null };
|
|
2712
|
-
}
|
|
2713
|
-
async function getUpcomingOrders(count) {
|
|
2714
|
-
return adapter.getUpcomingOrders({ count });
|
|
2715
|
-
}
|
|
2716
|
-
async function reloadCurrent(subscriptionId) {
|
|
2717
|
-
var _a;
|
|
2718
|
-
const token = ++reloadToken;
|
|
2719
|
-
currentLoading.value = true;
|
|
2720
|
-
const count = Math.max(((_a = current.value) == null ? void 0 : _a.length) ?? 0, 3);
|
|
2721
|
-
const result = await adapter.getUpcomingOrders({
|
|
2722
|
-
count,
|
|
2723
|
-
subscriptionId
|
|
2724
|
-
});
|
|
2725
|
-
if (token !== reloadToken) return;
|
|
2726
|
-
currentLoading.value = false;
|
|
2727
|
-
if (result._tag === "Success") {
|
|
2728
|
-
current.value = result.data;
|
|
2729
|
-
}
|
|
2730
|
-
}
|
|
2731
|
-
return {
|
|
2732
|
-
current,
|
|
2733
|
-
currentLoading,
|
|
2734
|
-
hasPendingBilling,
|
|
2735
|
-
getUpcomingOrder,
|
|
2736
|
-
getUpcomingOrders,
|
|
2737
|
-
async getAdjustments() {
|
|
2738
|
-
return adapter.getAdjustments();
|
|
2739
|
-
},
|
|
2740
|
-
async skipOrder(params) {
|
|
2741
|
-
const result = await adapter.skipOrder(params);
|
|
2742
|
-
if (result._tag === "Success") {
|
|
2743
|
-
await reloadCurrent(params.subscriptionId);
|
|
2744
|
-
}
|
|
2745
|
-
return result;
|
|
2746
|
-
},
|
|
2747
|
-
async changeDateAdjustment(params) {
|
|
2748
|
-
const result = await adapter.changeDateAdjustment(params);
|
|
2749
|
-
if (result._tag === "Success") {
|
|
2750
|
-
await reloadCurrent(params.subscriptionId);
|
|
2751
|
-
}
|
|
2752
|
-
return result;
|
|
2753
|
-
},
|
|
2754
|
-
async updateShippingAdjustment(params) {
|
|
2755
|
-
const result = await adapter.updateShippingAdjustment(params);
|
|
2756
|
-
if (result._tag === "Success") {
|
|
2757
|
-
await reloadCurrent(params.subscriptionId);
|
|
2758
|
-
}
|
|
2759
|
-
return result;
|
|
2760
|
-
},
|
|
2761
|
-
async updatePaymentMethodAdjustment(params) {
|
|
2762
|
-
const result = await adapter.updatePaymentMethodAdjustment(params);
|
|
2763
|
-
if (result._tag === "Success") {
|
|
2764
|
-
await reloadCurrent(params.subscriptionId);
|
|
2765
|
-
}
|
|
2766
|
-
return result;
|
|
2767
|
-
},
|
|
2768
|
-
async updateProductsAdjustment(params) {
|
|
2769
|
-
const result = await adapter.updateProductsAdjustment(params);
|
|
2770
|
-
if (result._tag === "Success") {
|
|
2771
|
-
await reloadCurrent(params.subscriptionId);
|
|
2772
|
-
}
|
|
2773
|
-
return result;
|
|
2774
|
-
},
|
|
2775
|
-
async applyDiscountAdjustment(params) {
|
|
2776
|
-
const result = await adapter.applyDiscountAdjustment(params);
|
|
2777
|
-
if (result._tag === "Success") {
|
|
2778
|
-
await reloadCurrent(params.subscriptionId);
|
|
2779
|
-
}
|
|
2780
|
-
return result;
|
|
2781
|
-
},
|
|
2782
|
-
async removeAdjustment(params) {
|
|
2783
|
-
return adapter.removeAdjustment(params);
|
|
2784
|
-
},
|
|
2785
|
-
reloadCurrent
|
|
2786
|
-
};
|
|
2787
|
-
}
|
|
2788
|
-
const SettingsServiceContext = createContext("services/settings");
|
|
2789
|
-
function createSettingsService(initial = {}) {
|
|
2790
|
-
const current = d(initial);
|
|
2791
|
-
return {
|
|
2792
|
-
current,
|
|
2793
|
-
get(key) {
|
|
2794
|
-
return current.value[key];
|
|
2795
|
-
}
|
|
2796
|
-
};
|
|
2797
|
-
}
|
|
2798
|
-
function createShopService(options) {
|
|
2799
|
-
const contactEmail = d(options.getContactEmail());
|
|
2800
|
-
const service = { contactEmail };
|
|
2801
|
-
return service;
|
|
2802
|
-
}
|
|
2803
|
-
const ShopServiceContext = createContext("services/shop");
|
|
2804
1109
|
const SubscriptionServiceContext = createContext("services/subscription");
|
|
2805
1110
|
function getCurrentSubscriptionId() {
|
|
2806
1111
|
if (typeof window === "undefined") {
|
|
@@ -2823,97 +1128,41 @@ function getCurrentSubscriptionId() {
|
|
|
2823
1128
|
}
|
|
2824
1129
|
function createSubscriptionService(adapter) {
|
|
2825
1130
|
const current = d(null);
|
|
2826
|
-
const
|
|
2827
|
-
const
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
1131
|
+
const discountsChangedAtSignal = d(0);
|
|
1132
|
+
const itemsChangedAtSignal = d(0);
|
|
1133
|
+
async function refreshCurrent(subscriptionId) {
|
|
1134
|
+
const result = await adapter.getById(subscriptionId);
|
|
1135
|
+
if (result._tag === "Success" && result.data != null) {
|
|
1136
|
+
current.value = result.data;
|
|
1137
|
+
}
|
|
2833
1138
|
}
|
|
2834
|
-
async function
|
|
2835
|
-
await
|
|
2836
|
-
|
|
1139
|
+
async function refreshAfterDiscountChange(subscriptionId) {
|
|
1140
|
+
await refreshCurrent(subscriptionId);
|
|
1141
|
+
discountsChangedAtSignal.value = discountsChangedAtSignal.value + 1;
|
|
1142
|
+
}
|
|
1143
|
+
async function refreshAfterItemChange(subscriptionId) {
|
|
1144
|
+
await refreshCurrent(subscriptionId);
|
|
1145
|
+
itemsChangedAtSignal.value = itemsChangedAtSignal.value + 1;
|
|
2837
1146
|
}
|
|
2838
1147
|
function subscriptionIdFromCurrent() {
|
|
2839
1148
|
var _a;
|
|
2840
1149
|
return ((_a = current.value) == null ? void 0 : _a.id) ?? null;
|
|
2841
1150
|
}
|
|
2842
|
-
async function reload() {
|
|
2843
|
-
var _a, _b;
|
|
2844
|
-
const id = (_a = current.value) == null ? void 0 : _a.id;
|
|
2845
|
-
if (!id) return;
|
|
2846
|
-
const [subResult, lastOrderResult] = await Promise.all([
|
|
2847
|
-
adapter.getById(id),
|
|
2848
|
-
adapter.getLastOrder({ subscriptionId: id })
|
|
2849
|
-
]);
|
|
2850
|
-
if (((_b = current.value) == null ? void 0 : _b.id) !== id) return;
|
|
2851
|
-
if (subResult._tag === "Success") current.value = subResult.data;
|
|
2852
|
-
if (lastOrderResult._tag === "Success") lastOrder.value = lastOrderResult.data;
|
|
2853
|
-
}
|
|
2854
1151
|
const service = {
|
|
2855
|
-
current,
|
|
2856
|
-
hasPendingBilling,
|
|
2857
|
-
discountsChangedAt,
|
|
2858
|
-
itemsChangedAt,
|
|
2859
|
-
lastOrder,
|
|
2860
1152
|
search: adapter.search,
|
|
2861
|
-
// Prefer the adapter's rich cross-subscription list (legacy endpoint, active-first).
|
|
2862
|
-
// Fall back to a single `search` page for adapters that don't implement it
|
|
2863
|
-
// (e.g. the editor mock) so the cross-subscription views still render.
|
|
2864
|
-
listAll: adapter.listAll ? adapter.listAll.bind(adapter) : async () => {
|
|
2865
|
-
const result = await adapter.search();
|
|
2866
|
-
if (result._tag !== "Success") return result;
|
|
2867
|
-
return { _tag: "Success", data: result.data.items };
|
|
2868
|
-
},
|
|
2869
1153
|
getById: adapter.getById,
|
|
2870
1154
|
getCurrentSubscriptionId,
|
|
2871
1155
|
addItem: async (subscriptionId, item) => {
|
|
2872
1156
|
const result = await adapter.addItem({ subscriptionId, item });
|
|
2873
1157
|
if (result._tag === "Success") {
|
|
2874
|
-
await refreshAfterItemChange();
|
|
1158
|
+
await refreshAfterItemChange(subscriptionId);
|
|
2875
1159
|
}
|
|
2876
1160
|
return result;
|
|
2877
1161
|
},
|
|
2878
1162
|
removeItem: async (subscriptionId, itemId) => {
|
|
2879
1163
|
const result = await adapter.removeItem({ subscriptionId, itemId });
|
|
2880
1164
|
if (result._tag === "Success") {
|
|
2881
|
-
await refreshAfterItemChange();
|
|
2882
|
-
}
|
|
2883
|
-
return result;
|
|
2884
|
-
},
|
|
2885
|
-
updateItem: async (subscriptionId, lineId, update) => {
|
|
2886
|
-
const result = await adapter.updateItem({ subscriptionId, lineId, update });
|
|
2887
|
-
if (result._tag === "Success") {
|
|
2888
|
-
await refreshAfterItemChange();
|
|
2889
|
-
}
|
|
2890
|
-
return result;
|
|
2891
|
-
},
|
|
2892
|
-
updateItemAttributes: async (subscriptionId, lineId, customAttributes) => {
|
|
2893
|
-
const result = await adapter.updateItemAttributes({ subscriptionId, lineId, customAttributes });
|
|
2894
|
-
if (result._tag === "Success") {
|
|
2895
|
-
await refreshAfterItemChange();
|
|
2896
|
-
}
|
|
2897
|
-
return result;
|
|
2898
|
-
},
|
|
2899
|
-
updateAttributes: async (subscriptionId, customAttributes) => {
|
|
2900
|
-
const result = await adapter.updateAttributes({ subscriptionId, customAttributes });
|
|
2901
|
-
if (result._tag === "Success") {
|
|
2902
|
-
await reload();
|
|
2903
|
-
}
|
|
2904
|
-
return result;
|
|
2905
|
-
},
|
|
2906
|
-
skipLineItem: async (subscriptionId, lineId, nextBillingDate) => {
|
|
2907
|
-
const result = await adapter.skipLineItem({ subscriptionId, lineId, nextBillingDate });
|
|
2908
|
-
if (result._tag === "Success") {
|
|
2909
|
-
await refreshAfterItemChange();
|
|
2910
|
-
}
|
|
2911
|
-
return result;
|
|
2912
|
-
},
|
|
2913
|
-
updateBoxItems: async (subscriptionId, params) => {
|
|
2914
|
-
const result = await adapter.updateBoxItems({ subscriptionId, ...params });
|
|
2915
|
-
if (result._tag === "Success") {
|
|
2916
|
-
await refreshAfterItemChange();
|
|
1165
|
+
await refreshAfterItemChange(subscriptionId);
|
|
2917
1166
|
}
|
|
2918
1167
|
return result;
|
|
2919
1168
|
},
|
|
@@ -2927,7 +1176,7 @@ function createSubscriptionService(adapter) {
|
|
|
2927
1176
|
}
|
|
2928
1177
|
const result = await adapter.addDiscount({ subscriptionId: id, code });
|
|
2929
1178
|
if (result._tag === "Success") {
|
|
2930
|
-
await refreshAfterDiscountChange();
|
|
1179
|
+
await refreshAfterDiscountChange(id);
|
|
2931
1180
|
}
|
|
2932
1181
|
return result;
|
|
2933
1182
|
},
|
|
@@ -2944,23 +1193,20 @@ function createSubscriptionService(adapter) {
|
|
|
2944
1193
|
discountId
|
|
2945
1194
|
});
|
|
2946
1195
|
if (result._tag === "Success") {
|
|
2947
|
-
await refreshAfterDiscountChange();
|
|
1196
|
+
await refreshAfterDiscountChange(id);
|
|
2948
1197
|
}
|
|
2949
1198
|
return result;
|
|
2950
1199
|
},
|
|
2951
1200
|
reschedule: (subscriptionId, newDate) => adapter.reschedule({ subscriptionId, newDate }),
|
|
2952
|
-
updateCustomAttributes: (subscriptionId, customAttributes) => adapter.updateCustomAttributes({ subscriptionId, customAttributes }),
|
|
2953
1201
|
resume: (subscriptionId) => adapter.resume({ subscriptionId }),
|
|
2954
1202
|
pause: (subscriptionId) => adapter.pause({ subscriptionId }),
|
|
2955
1203
|
reactivate: (subscriptionId) => adapter.reactivate({ subscriptionId }),
|
|
2956
1204
|
cancel: (subscriptionId, reason) => adapter.cancel({ subscriptionId, reason }),
|
|
2957
|
-
renewNow: (params) => adapter.renewNow(params),
|
|
2958
|
-
changeFrequency: (subscriptionId, plan) => adapter.changeFrequency({ subscriptionId, plan }),
|
|
2959
|
-
reload,
|
|
2960
1205
|
getAvailablePlans: (subscriptionId) => adapter.getAvailablePlans({ subscriptionId }),
|
|
2961
1206
|
getDefaultSubscriptionId: () => adapter.getDefaultSubscriptionId(),
|
|
2962
|
-
|
|
2963
|
-
|
|
1207
|
+
current,
|
|
1208
|
+
discountsChangedAt: discountsChangedAtSignal,
|
|
1209
|
+
itemsChangedAt: itemsChangedAtSignal
|
|
2964
1210
|
};
|
|
2965
1211
|
return service;
|
|
2966
1212
|
}
|
|
@@ -3229,89 +1475,66 @@ export {
|
|
|
3229
1475
|
AuthenticationError,
|
|
3230
1476
|
AuthenticationErrorReason,
|
|
3231
1477
|
B as BlockWrapperEvent,
|
|
3232
|
-
|
|
3233
|
-
|
|
1478
|
+
C as ContextProvideEvent,
|
|
1479
|
+
a as ContextRequestEvent,
|
|
3234
1480
|
CustomerServiceContext,
|
|
3235
|
-
|
|
1481
|
+
D as DEFAULT_GLOBAL_STYLES,
|
|
3236
1482
|
DISCOUNT_REJECTION_REASONS,
|
|
3237
1483
|
LoginServiceContext,
|
|
3238
1484
|
OrdersServiceContext,
|
|
3239
|
-
OverlayServiceContext,
|
|
3240
1485
|
ProductServiceContext,
|
|
3241
1486
|
RouterServiceContext,
|
|
3242
|
-
SchedulesServiceContext,
|
|
3243
1487
|
S as SelectedBlockContext,
|
|
3244
|
-
SettingsServiceContext,
|
|
3245
|
-
ShopServiceContext,
|
|
3246
1488
|
u as Signal,
|
|
3247
1489
|
StateContext,
|
|
3248
1490
|
SubscriptionServiceContext,
|
|
3249
|
-
|
|
3250
|
-
|
|
1491
|
+
T as ThemeStateContext,
|
|
1492
|
+
b as TranslationContext,
|
|
3251
1493
|
W as WorkflowServiceContext,
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
t as attachEmptyTracking,
|
|
3255
|
-
b as backfillInstanceDefaults,
|
|
1494
|
+
e as attachEmptyTracking,
|
|
1495
|
+
f as backfillInstanceDefaults,
|
|
3256
1496
|
w as computed,
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
createApiSchedulesAdapter,
|
|
3262
|
-
createApiSubscriptionAdapter,
|
|
3263
|
-
createBlockInstance,
|
|
3264
|
-
v as createBlockInstanceFromJSON,
|
|
3265
|
-
f as createBlockInstanceFromObject,
|
|
3266
|
-
x as createCeRenderer,
|
|
1497
|
+
g as createBlockInstance,
|
|
1498
|
+
h as createBlockInstanceFromJSON,
|
|
1499
|
+
i as createBlockInstanceFromObject,
|
|
1500
|
+
j as createCeRenderer,
|
|
3267
1501
|
createContext,
|
|
3268
1502
|
createCustomerService,
|
|
3269
|
-
createLoginService,
|
|
3270
|
-
createMockCustomerAdapter,
|
|
3271
|
-
createMockLoginAdapter,
|
|
3272
1503
|
createMockOrdersAdapter,
|
|
3273
1504
|
createMockProductAdapter,
|
|
3274
1505
|
createMockRouterService,
|
|
3275
|
-
createMockSchedulesAdapter,
|
|
3276
1506
|
createMockSubscriptionAdapter,
|
|
3277
1507
|
createMockWorkflowApiAdapter,
|
|
3278
1508
|
createOrdersService,
|
|
3279
|
-
createOverlayService,
|
|
3280
1509
|
createProductService,
|
|
3281
1510
|
createRouterService,
|
|
3282
|
-
|
|
3283
|
-
y as createSelectedBlock,
|
|
3284
|
-
createSettingsService,
|
|
3285
|
-
createShopService,
|
|
1511
|
+
k as createSelectedBlock,
|
|
3286
1512
|
createState,
|
|
3287
1513
|
createSubscriptionService,
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
defineBlock,
|
|
3293
|
-
|
|
3294
|
-
defineOverlayWrapper,
|
|
1514
|
+
l as createThemeState,
|
|
1515
|
+
m as createTranslationService,
|
|
1516
|
+
n as createWorkflowApiAdapter,
|
|
1517
|
+
o as createWorkflowService,
|
|
1518
|
+
p as defineBlock,
|
|
1519
|
+
q as defineBlockRuntime,
|
|
3295
1520
|
E as effect,
|
|
3296
|
-
|
|
3297
|
-
getDefinedBlocks,
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
F as
|
|
3304
|
-
a as isStubDefinition,
|
|
1521
|
+
s as getDefaultBlockForAction,
|
|
1522
|
+
t as getDefinedBlocks,
|
|
1523
|
+
v as hasDefaultBlockForAction,
|
|
1524
|
+
x as hasRenderedContent,
|
|
1525
|
+
y as indexOverrides,
|
|
1526
|
+
z as injectContext,
|
|
1527
|
+
A as isEditorPreview,
|
|
1528
|
+
F as isStubDefinition,
|
|
3305
1529
|
loadBlockRegistry,
|
|
3306
1530
|
loginService,
|
|
3307
|
-
|
|
3308
|
-
|
|
1531
|
+
G as onRegisterBlock,
|
|
1532
|
+
H as provideContext,
|
|
3309
1533
|
registerBlock,
|
|
3310
|
-
|
|
3311
|
-
H as setDevtoolsBlockProp,
|
|
1534
|
+
I as serializeBlocks,
|
|
3312
1535
|
d as signal,
|
|
3313
|
-
|
|
3314
|
-
|
|
1536
|
+
J as subscribeContext,
|
|
1537
|
+
K as untracked,
|
|
3315
1538
|
waitForDevBlocksUrl,
|
|
3316
|
-
|
|
1539
|
+
L as withWrapper
|
|
3317
1540
|
};
|