@juo/blocks 1.11.0-alpha.0 → 1.11.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-C7tcvV-n.js → ExtensionRoot-9XfhG8YM.js} +1 -3
- package/dist/block.d.ts.map +1 -1
- package/dist/core.js +319 -1010
- package/dist/editor/handler.d.ts +1 -1
- package/dist/editor/handler.d.ts.map +1 -1
- package/dist/editor.js +1 -3
- package/dist/juo-workflow-CkyZRq60.js +1667 -0
- 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 -1
- 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/product/adapter.d.ts +1 -4
- 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/types.d.ts +0 -2
- package/dist/services/product/types.d.ts.map +1 -1
- package/dist/services/subscription/adapter.d.ts +2 -12
- 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 +16 -25
- package/dist/services/subscription/types.d.ts.map +1 -1
- package/dist/utils/editor.d.ts +18 -0
- package/dist/utils/editor.d.ts.map +1 -0
- package/dist/utils/editor.test.d.ts +2 -0
- package/dist/utils/editor.test.d.ts.map +1 -0
- package/dist/utils/index.d.ts +1 -6
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/vue/block.d.ts +2 -2
- package/dist/vue/block.d.ts.map +1 -1
- package/dist/vue.js +3 -4
- package/dist/web-components-editor.js +2 -3
- package/dist/web-components-runtime.js +2 -3
- package/package.json +1 -1
- package/dist/block-WoHZvF51.js +0 -858
- package/dist/juo-workflow-DRauDEnU.js +0 -617
- 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/schedules/adapter.d.ts +0 -22
- package/dist/services/schedules/adapter.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 -10
- package/dist/services/schedules/schedulesService.d.ts.map +0 -1
- package/dist/services/schedules/types.d.ts +0 -47
- package/dist/services/schedules/types.d.ts.map +0 -1
- package/dist/theme-state-CzXQGOTk.js +0 -202
package/dist/core.js
CHANGED
|
@@ -1,10 +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 { c as createContext, d, w, r as registerBlock, E, u } from "./
|
|
5
|
-
import { B, C, a, S, b, e, f, g, h, i, j, k, l, m, n, o, p, q, s, t, v, x, y } from "./
|
|
6
|
-
import { D, T, c, i as i2 } from "./theme-state-CzXQGOTk.js";
|
|
7
|
-
import { T as T2, W, c as c2, a as a2, b as b2, g as g2, h as h2 } from "./juo-workflow-DRauDEnU.js";
|
|
4
|
+
import { c as createContext, d, w, r as registerBlock, E, u } from "./juo-workflow-CkyZRq60.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-CkyZRq60.js";
|
|
8
6
|
import { reportBlockWarning, reportBlockError } from "./observability.js";
|
|
9
7
|
function createState() {
|
|
10
8
|
const discountCode = d(null);
|
|
@@ -158,43 +156,13 @@ async function loadBlockRegistry(options = {}) {
|
|
|
158
156
|
function createCustomerService(options) {
|
|
159
157
|
const current = d(null);
|
|
160
158
|
const accountOrdersUrl = d(options.getAccountOrdersUrl());
|
|
161
|
-
|
|
159
|
+
const service = {
|
|
162
160
|
current,
|
|
163
|
-
accountOrdersUrl
|
|
164
|
-
async getCurrent() {
|
|
165
|
-
const result = await options.adapter.getCurrent();
|
|
166
|
-
if (result._tag === "Success") current.value = result.data;
|
|
167
|
-
return result;
|
|
168
|
-
}
|
|
161
|
+
accountOrdersUrl
|
|
169
162
|
};
|
|
163
|
+
return service;
|
|
170
164
|
}
|
|
171
165
|
const CustomerServiceContext = createContext("services/customer");
|
|
172
|
-
function createMockCustomerAdapter() {
|
|
173
|
-
const customer = { id: "customer-1", name: "Customer 1" };
|
|
174
|
-
return {
|
|
175
|
-
async getCurrent() {
|
|
176
|
-
return { _tag: "Success", data: customer };
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
function createApiCustomerAdapter(fetcher) {
|
|
181
|
-
return {
|
|
182
|
-
async getCurrent() {
|
|
183
|
-
try {
|
|
184
|
-
const res = await fetcher("/customer/info");
|
|
185
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
186
|
-
const data = await res.json();
|
|
187
|
-
const name = [data.firstName, data.lastName].filter(Boolean).join(" ") || data.email || "";
|
|
188
|
-
return {
|
|
189
|
-
_tag: "Success",
|
|
190
|
-
data: { id: data.id, name, email: data.email }
|
|
191
|
-
};
|
|
192
|
-
} catch (e2) {
|
|
193
|
-
return { _tag: "Failure", error: e2 };
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
166
|
const PARAMS = {
|
|
199
167
|
DELETGATED_TOKEN: "delegated-token",
|
|
200
168
|
REDIRECT_TO: "redirect-to",
|
|
@@ -208,125 +176,9 @@ const PARAMS = {
|
|
|
208
176
|
function uuid() {
|
|
209
177
|
return ("10000000-1000-4000-8000" + -1e11).replace(
|
|
210
178
|
/[018]/g,
|
|
211
|
-
(
|
|
179
|
+
(c) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
|
212
180
|
);
|
|
213
181
|
}
|
|
214
|
-
function createMockLoginAdapter() {
|
|
215
|
-
return {
|
|
216
|
-
async passwordlessStart() {
|
|
217
|
-
return { _tag: "Success", data: void 0 };
|
|
218
|
-
},
|
|
219
|
-
async authenticate() {
|
|
220
|
-
return {
|
|
221
|
-
_tag: "Success",
|
|
222
|
-
data: {
|
|
223
|
-
access_token: "mock-access-token",
|
|
224
|
-
refresh_token: "mock-refresh-token",
|
|
225
|
-
expires_in: 3600
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
},
|
|
229
|
-
getAuthorizeUrl({ connection, state, shop, appUrl }) {
|
|
230
|
-
const url = new URL(`${appUrl}/auth/customer/authorize`);
|
|
231
|
-
url.searchParams.set("connection", connection);
|
|
232
|
-
url.searchParams.set("state", state);
|
|
233
|
-
url.searchParams.set("shop", shop);
|
|
234
|
-
return url.toString();
|
|
235
|
-
}
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
function createApiLoginAdapter(fetcher, opts) {
|
|
239
|
-
const { shopDomain, appUrl } = opts;
|
|
240
|
-
async function callAuthEndpoint(path, body, lang) {
|
|
241
|
-
const url = lang ? `${path}?lang=${lang}` : path;
|
|
242
|
-
const res = await fetcher(url, {
|
|
243
|
-
method: "POST",
|
|
244
|
-
headers: {
|
|
245
|
-
Accept: "application/json",
|
|
246
|
-
"Content-Type": "application/json",
|
|
247
|
-
"X-Shopify-Shop-Domain": shopDomain
|
|
248
|
-
},
|
|
249
|
-
body: JSON.stringify(body)
|
|
250
|
-
});
|
|
251
|
-
if (res.status === 403) {
|
|
252
|
-
const data = await res.json();
|
|
253
|
-
if ("error_description" in data) {
|
|
254
|
-
if (data.error_description === "Wrong email or verification code.") {
|
|
255
|
-
throw new AuthenticationError(AuthenticationErrorReason.IncorrectCode);
|
|
256
|
-
} else if (data.error_description === "You've reached the maximum number of attempts. Please try to login again.") {
|
|
257
|
-
throw new AuthenticationError(AuthenticationErrorReason.TooManyTries);
|
|
258
|
-
} else if (data.error_description === "The verification code has expired. Please try to login again.") {
|
|
259
|
-
throw new AuthenticationError(AuthenticationErrorReason.Expired);
|
|
260
|
-
}
|
|
261
|
-
} else if ("code" in data && data.code === "AUTH_ERROR") {
|
|
262
|
-
throw new AuthenticationError(AuthenticationErrorReason.NoEmail, {
|
|
263
|
-
connection: data.connection
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
if (!res.ok) {
|
|
268
|
-
throw new Error(`Unexpected response: ${res.statusText}`);
|
|
269
|
-
}
|
|
270
|
-
return { _tag: "Success", data: void 0 };
|
|
271
|
-
}
|
|
272
|
-
return {
|
|
273
|
-
async passwordlessStart({ email, lang }) {
|
|
274
|
-
try {
|
|
275
|
-
await callAuthEndpoint(
|
|
276
|
-
"/auth/customer/passwordless/start",
|
|
277
|
-
{ email },
|
|
278
|
-
lang
|
|
279
|
-
);
|
|
280
|
-
return { _tag: "Success", data: void 0 };
|
|
281
|
-
} catch (e2) {
|
|
282
|
-
return { _tag: "Failure", error: e2 };
|
|
283
|
-
}
|
|
284
|
-
},
|
|
285
|
-
async authenticate(params) {
|
|
286
|
-
try {
|
|
287
|
-
const res = await fetcher("/auth/customer/token", {
|
|
288
|
-
method: "POST",
|
|
289
|
-
headers: {
|
|
290
|
-
Accept: "application/json",
|
|
291
|
-
"Content-Type": "application/json",
|
|
292
|
-
"X-Shopify-Shop-Domain": shopDomain
|
|
293
|
-
},
|
|
294
|
-
body: JSON.stringify(params)
|
|
295
|
-
});
|
|
296
|
-
if (res.status === 403) {
|
|
297
|
-
const data = await res.json();
|
|
298
|
-
if ("error_description" in data) {
|
|
299
|
-
if (data.error_description === "Wrong email or verification code.") {
|
|
300
|
-
throw new AuthenticationError(AuthenticationErrorReason.IncorrectCode);
|
|
301
|
-
} else if (data.error_description === "You've reached the maximum number of attempts. Please try to login again.") {
|
|
302
|
-
throw new AuthenticationError(AuthenticationErrorReason.TooManyTries);
|
|
303
|
-
} else if (data.error_description === "The verification code has expired. Please try to login again.") {
|
|
304
|
-
throw new AuthenticationError(AuthenticationErrorReason.Expired);
|
|
305
|
-
}
|
|
306
|
-
} else if ("code" in data && data.code === "AUTH_ERROR") {
|
|
307
|
-
throw new AuthenticationError(AuthenticationErrorReason.NoEmail, {
|
|
308
|
-
connection: data.connection
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
if (!res.ok) {
|
|
313
|
-
throw new Error(`Unexpected response: ${res.statusText}`);
|
|
314
|
-
}
|
|
315
|
-
return { _tag: "Success", data: await res.json() };
|
|
316
|
-
} catch (e2) {
|
|
317
|
-
return { _tag: "Failure", error: e2 };
|
|
318
|
-
}
|
|
319
|
-
},
|
|
320
|
-
getAuthorizeUrl({ connection, state, shop }) {
|
|
321
|
-
const url = new URL(`${appUrl}/auth/customer/authorize`);
|
|
322
|
-
url.searchParams.set("connection", connection);
|
|
323
|
-
url.searchParams.set("state", state);
|
|
324
|
-
url.searchParams.set("shop", shop);
|
|
325
|
-
return url.toString();
|
|
326
|
-
}
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
const __vite_import_meta_env__ = {};
|
|
330
182
|
var AuthenticationErrorReason = /* @__PURE__ */ ((AuthenticationErrorReason2) => {
|
|
331
183
|
AuthenticationErrorReason2["Expired"] = "expired";
|
|
332
184
|
AuthenticationErrorReason2["IncorrectCode"] = "wrong-code";
|
|
@@ -345,9 +197,6 @@ class AuthenticationError extends Error {
|
|
|
345
197
|
this.data = data ?? {};
|
|
346
198
|
}
|
|
347
199
|
}
|
|
348
|
-
const STORAGE_DELEGATED_TOKEN = "delegated-token";
|
|
349
|
-
const STORAGE_REFRESH_TOKEN_KEY = "refresh-token";
|
|
350
|
-
const STORAGE_STATE_KEY = "state";
|
|
351
200
|
function storage(key, value) {
|
|
352
201
|
const storageKey = `auth:${key}`;
|
|
353
202
|
try {
|
|
@@ -363,33 +212,83 @@ function storage(key, value) {
|
|
|
363
212
|
}
|
|
364
213
|
return null;
|
|
365
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
|
+
}
|
|
366
280
|
function nonce(len = 10) {
|
|
367
281
|
return uuid().replace(/-/g, "").slice(0, len);
|
|
368
282
|
}
|
|
369
|
-
function
|
|
370
|
-
const
|
|
371
|
-
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";
|
|
372
|
-
const fetcher = (path, init) => fetch(`${apiBase}${path}`, init);
|
|
373
|
-
const adapter = createApiLoginAdapter(fetcher, {
|
|
374
|
-
shopDomain: deps.shop.domain,
|
|
375
|
-
appUrl
|
|
376
|
-
});
|
|
377
|
-
return createLoginService({
|
|
378
|
-
adapter,
|
|
379
|
-
router: deps.router,
|
|
380
|
-
formatError: deps.formatError,
|
|
381
|
-
shop: {
|
|
382
|
-
domain: deps.shop.domain,
|
|
383
|
-
locale: w(() => deps.getLocale())
|
|
384
|
-
},
|
|
385
|
-
onLoginSuccess: deps.onLoginSuccess
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
function createLoginService(init) {
|
|
389
|
-
const { adapter, formatError, router, shop, onLoginSuccess } = init;
|
|
283
|
+
function createAuthService(apiUrl, shopDomain) {
|
|
284
|
+
const { start: authStart, authenticate: authAuthenticate } = createAuthFunctions(apiUrl, shopDomain);
|
|
390
285
|
const accessToken = d(null);
|
|
391
|
-
const delegatedToken = d(
|
|
392
|
-
|
|
286
|
+
const delegatedToken = d(
|
|
287
|
+
storage(STORAGE_DELEGATED_TOKEN)
|
|
288
|
+
);
|
|
289
|
+
const refreshToken = d(
|
|
290
|
+
storage(STORAGE_REFRESH_TOKEN_KEY)
|
|
291
|
+
);
|
|
393
292
|
const expires = d(null);
|
|
394
293
|
const state = d(storage(STORAGE_STATE_KEY));
|
|
395
294
|
E(() => {
|
|
@@ -401,28 +300,67 @@ function createLoginService(init) {
|
|
|
401
300
|
E(() => {
|
|
402
301
|
storage(STORAGE_STATE_KEY, state.value);
|
|
403
302
|
});
|
|
404
|
-
function
|
|
303
|
+
function store(data) {
|
|
405
304
|
const { access_token, refresh_token, expires_in } = data;
|
|
406
305
|
accessToken.value = access_token;
|
|
407
306
|
refreshToken.value = refresh_token;
|
|
408
307
|
expires.value = new Date(Date.now() + expires_in);
|
|
409
308
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
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);
|
|
417
332
|
return;
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
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);
|
|
426
364
|
const userEmail = d(null);
|
|
427
365
|
async function onSuccess(query) {
|
|
428
366
|
await (onLoginSuccess == null ? void 0 : onLoginSuccess());
|
|
@@ -435,9 +373,13 @@ function createLoginService(init) {
|
|
|
435
373
|
queryParams[key] = value;
|
|
436
374
|
}
|
|
437
375
|
});
|
|
438
|
-
router.push({
|
|
376
|
+
router.push({
|
|
377
|
+
path: decodeURIComponent(redirect),
|
|
378
|
+
query: queryParams
|
|
379
|
+
});
|
|
439
380
|
} else {
|
|
440
|
-
|
|
381
|
+
const redirect = query.get(PARAMS.REDIRECT_TO);
|
|
382
|
+
router.replace(decodeURIComponent(redirect));
|
|
441
383
|
}
|
|
442
384
|
} else {
|
|
443
385
|
router.replace("/");
|
|
@@ -449,17 +391,16 @@ function createLoginService(init) {
|
|
|
449
391
|
async start(email) {
|
|
450
392
|
try {
|
|
451
393
|
userEmail.value = email;
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
});
|
|
457
|
-
if (result._tag === "Failure") {
|
|
458
|
-
return { _tag: "Failure", error: formatError(result.error) };
|
|
459
|
-
}
|
|
394
|
+
await auth.start(
|
|
395
|
+
userEmail.value,
|
|
396
|
+
shop.locale instanceof u ? shop.locale.value : shop.locale
|
|
397
|
+
);
|
|
460
398
|
return { _tag: "Success", data: void 0 };
|
|
461
399
|
} catch (error) {
|
|
462
|
-
return {
|
|
400
|
+
return {
|
|
401
|
+
_tag: "Failure",
|
|
402
|
+
error: formatError(error)
|
|
403
|
+
};
|
|
463
404
|
}
|
|
464
405
|
},
|
|
465
406
|
async verify(email, code) {
|
|
@@ -470,61 +411,63 @@ function createLoginService(init) {
|
|
|
470
411
|
};
|
|
471
412
|
}
|
|
472
413
|
try {
|
|
473
|
-
const result = await
|
|
414
|
+
const result = await auth.authenticate({
|
|
474
415
|
email: userEmail.value,
|
|
475
416
|
code
|
|
476
417
|
});
|
|
477
|
-
if (result._tag === "Failure") {
|
|
478
|
-
return { _tag: "Failure", error: formatError(result.error) };
|
|
479
|
-
}
|
|
480
|
-
storeTokens(result.data);
|
|
481
418
|
await onSuccess();
|
|
482
|
-
return { _tag: "Success", data:
|
|
419
|
+
return { _tag: "Success", data: result };
|
|
483
420
|
} catch (error) {
|
|
484
|
-
return {
|
|
421
|
+
return {
|
|
422
|
+
_tag: "Failure",
|
|
423
|
+
error: formatError(error)
|
|
424
|
+
};
|
|
485
425
|
}
|
|
486
426
|
}
|
|
487
427
|
}
|
|
488
428
|
},
|
|
489
429
|
social: {
|
|
490
430
|
async start(provider) {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
)
|
|
501
|
-
}
|
|
502
|
-
|
|
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
|
+
};
|
|
503
450
|
},
|
|
504
451
|
async verify(code) {
|
|
505
452
|
try {
|
|
506
|
-
const result = await
|
|
507
|
-
if (result._tag === "Failure") {
|
|
508
|
-
return { _tag: "Failure", error: formatError(result.error) };
|
|
509
|
-
}
|
|
510
|
-
storeTokens(result.data);
|
|
453
|
+
const result = await auth.authenticate({ code });
|
|
511
454
|
await onSuccess();
|
|
512
|
-
return { _tag: "Success", data:
|
|
455
|
+
return { _tag: "Success", data: result };
|
|
513
456
|
} catch (error) {
|
|
514
|
-
return {
|
|
457
|
+
return {
|
|
458
|
+
_tag: "Failure",
|
|
459
|
+
error: formatError(error)
|
|
460
|
+
};
|
|
515
461
|
}
|
|
516
462
|
}
|
|
517
463
|
},
|
|
518
464
|
async logout() {
|
|
519
|
-
|
|
520
|
-
delegatedToken.value = null;
|
|
521
|
-
refreshToken.value = null;
|
|
522
|
-
expires.value = null;
|
|
465
|
+
await auth.logout();
|
|
523
466
|
return { _tag: "Success", data: void 0 };
|
|
524
467
|
},
|
|
525
468
|
async handleQueryParams(query) {
|
|
526
469
|
if (query.has(PARAMS.DELETGATED_TOKEN)) {
|
|
527
|
-
|
|
470
|
+
auth.setDelegatedToken(query.get(PARAMS.DELETGATED_TOKEN));
|
|
528
471
|
await onSuccess(query);
|
|
529
472
|
return { _tag: "Success", data: void 0 };
|
|
530
473
|
}
|
|
@@ -536,13 +479,16 @@ function createLoginService(init) {
|
|
|
536
479
|
}
|
|
537
480
|
const code = query.get(PARAMS.CODE);
|
|
538
481
|
if (code != null) {
|
|
539
|
-
if (query.get(PARAMS.STATE) !== state.value) {
|
|
540
|
-
return {
|
|
482
|
+
if (query.get(PARAMS.STATE) !== auth.state.value) {
|
|
483
|
+
return {
|
|
484
|
+
_tag: "Failure",
|
|
485
|
+
error: formatError("Invalid state")
|
|
486
|
+
};
|
|
541
487
|
} else {
|
|
542
488
|
return service.social.verify(code);
|
|
543
489
|
}
|
|
544
490
|
}
|
|
545
|
-
if (query.get(PARAMS.REFRESH) === "1" && await getToken() != null) {
|
|
491
|
+
if (query.get(PARAMS.REFRESH) === "1" && await auth.getToken() != null) {
|
|
546
492
|
await onSuccess();
|
|
547
493
|
return { _tag: "Success", data: void 0 };
|
|
548
494
|
}
|
|
@@ -559,20 +505,8 @@ function createLoginService(init) {
|
|
|
559
505
|
}
|
|
560
506
|
return { _tag: "Success", data: void 0 };
|
|
561
507
|
},
|
|
562
|
-
isAuthenticated:
|
|
563
|
-
|
|
564
|
-
),
|
|
565
|
-
getToken,
|
|
566
|
-
async getAuthHeaders() {
|
|
567
|
-
if (delegatedToken.value) {
|
|
568
|
-
return { "X-Delegated-Token": delegatedToken.value };
|
|
569
|
-
}
|
|
570
|
-
const token = await getToken();
|
|
571
|
-
if (token) {
|
|
572
|
-
return { Authorization: `Bearer ${token}` };
|
|
573
|
-
}
|
|
574
|
-
return {};
|
|
575
|
-
}
|
|
508
|
+
isAuthenticated: auth.isAuthenticated,
|
|
509
|
+
getToken: () => auth.getToken()
|
|
576
510
|
};
|
|
577
511
|
return service;
|
|
578
512
|
}
|
|
@@ -785,106 +719,6 @@ function createMockProductAdapter() {
|
|
|
785
719
|
}
|
|
786
720
|
};
|
|
787
721
|
}
|
|
788
|
-
function mapVariant(variant, currencyCode) {
|
|
789
|
-
var _a;
|
|
790
|
-
return {
|
|
791
|
-
id: variant.id,
|
|
792
|
-
title: variant.title,
|
|
793
|
-
image: variant.image == null ? null : { url: variant.image.url, altText: variant.image.altText ?? void 0 },
|
|
794
|
-
price: { amount: variant.price.toFixed(2), currencyCode },
|
|
795
|
-
...((_a = variant.purchaseOptions) == null ? void 0 : _a.length) ? {
|
|
796
|
-
purchaseOptions: variant.purchaseOptions.map((opt) => ({
|
|
797
|
-
name: opt.name,
|
|
798
|
-
price: { amount: opt.price.toFixed(2), currencyCode },
|
|
799
|
-
interval: opt.interval
|
|
800
|
-
}))
|
|
801
|
-
} : {}
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
|
-
function mapProduct(product, currencyCode) {
|
|
805
|
-
return {
|
|
806
|
-
id: product.id,
|
|
807
|
-
title: product.title,
|
|
808
|
-
featuredImage: product.image == null ? null : { url: product.image.url, altText: product.image.altText ?? void 0 },
|
|
809
|
-
hasOnlyDefaultVariant: product.variants.length <= 1,
|
|
810
|
-
variants: {
|
|
811
|
-
items: product.variants.map((v2) => mapVariant(v2, currencyCode)),
|
|
812
|
-
pageInfo: {
|
|
813
|
-
hasNextPage: false,
|
|
814
|
-
hasPrevPage: false,
|
|
815
|
-
startCursor: null,
|
|
816
|
-
endCursor: null
|
|
817
|
-
}
|
|
818
|
-
},
|
|
819
|
-
collections: product.collections
|
|
820
|
-
};
|
|
821
|
-
}
|
|
822
|
-
function createApiProductAdapter(fetcher, opts = { currencyCode: "USD" }) {
|
|
823
|
-
const { currencyCode } = opts;
|
|
824
|
-
async function fetchProducts(params) {
|
|
825
|
-
const query = params.toString() ? `?${params.toString()}` : "";
|
|
826
|
-
const res = await fetcher(`/customer/v1/products${query}`);
|
|
827
|
-
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
828
|
-
return res.json();
|
|
829
|
-
}
|
|
830
|
-
return {
|
|
831
|
-
async getById(id) {
|
|
832
|
-
try {
|
|
833
|
-
const params = new URLSearchParams({ query: `id:"${id}"`, limit: "1" });
|
|
834
|
-
const body = await fetchProducts(params);
|
|
835
|
-
return body.data.length > 0 ? mapProduct(body.data[0], currencyCode) : null;
|
|
836
|
-
} catch {
|
|
837
|
-
return null;
|
|
838
|
-
}
|
|
839
|
-
},
|
|
840
|
-
async getByVariantId(variantId) {
|
|
841
|
-
try {
|
|
842
|
-
const params = new URLSearchParams({
|
|
843
|
-
query: `variants.id:"${variantId}"`,
|
|
844
|
-
limit: "1"
|
|
845
|
-
});
|
|
846
|
-
const body = await fetchProducts(params);
|
|
847
|
-
return body.data.length > 0 ? mapProduct(body.data[0], currencyCode) : null;
|
|
848
|
-
} catch {
|
|
849
|
-
return null;
|
|
850
|
-
}
|
|
851
|
-
},
|
|
852
|
-
async search(opts2) {
|
|
853
|
-
try {
|
|
854
|
-
const params = new URLSearchParams();
|
|
855
|
-
if (opts2 == null ? void 0 : opts2.query) {
|
|
856
|
-
params.set("query", `"${opts2.query.trim().replace(/"/g, '\\"')}"`);
|
|
857
|
-
}
|
|
858
|
-
if (opts2 == null ? void 0 : opts2.pagination) {
|
|
859
|
-
if ("after" in opts2.pagination)
|
|
860
|
-
params.set("after", opts2.pagination.after);
|
|
861
|
-
else if ("before" in opts2.pagination)
|
|
862
|
-
params.set("before", opts2.pagination.before);
|
|
863
|
-
}
|
|
864
|
-
const body = await fetchProducts(params);
|
|
865
|
-
return {
|
|
866
|
-
items: body.data.map((p2) => mapProduct(p2, currencyCode)),
|
|
867
|
-
pageInfo: {
|
|
868
|
-
hasNextPage: body.hasNextPage,
|
|
869
|
-
hasPrevPage: body.hasPrevPage,
|
|
870
|
-
startCursor: body.startCursor,
|
|
871
|
-
endCursor: body.endCursor
|
|
872
|
-
}
|
|
873
|
-
};
|
|
874
|
-
} catch {
|
|
875
|
-
return {
|
|
876
|
-
items: [],
|
|
877
|
-
pageInfo: {
|
|
878
|
-
hasNextPage: false,
|
|
879
|
-
hasPrevPage: false,
|
|
880
|
-
startCursor: null,
|
|
881
|
-
endCursor: null
|
|
882
|
-
}
|
|
883
|
-
};
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
};
|
|
887
|
-
}
|
|
888
722
|
const ProductServiceContext = createContext("services/product");
|
|
889
723
|
function createProductService(adapter) {
|
|
890
724
|
return {
|
|
@@ -950,250 +784,6 @@ function createMockRouterService() {
|
|
|
950
784
|
}
|
|
951
785
|
}).routerService;
|
|
952
786
|
}
|
|
953
|
-
function futureDateStr(daysFromNow) {
|
|
954
|
-
const d2 = /* @__PURE__ */ new Date();
|
|
955
|
-
d2.setDate(d2.getDate() + daysFromNow);
|
|
956
|
-
return d2.toISOString().split("T")[0] ?? "";
|
|
957
|
-
}
|
|
958
|
-
function createMockSchedulesAdapter() {
|
|
959
|
-
let orders = [
|
|
960
|
-
{
|
|
961
|
-
id: "schedule-order-1",
|
|
962
|
-
subscriptionId: "sub_1",
|
|
963
|
-
deliveryDate: futureDateStr(7),
|
|
964
|
-
items: [
|
|
965
|
-
{
|
|
966
|
-
id: "si-1",
|
|
967
|
-
productId: "p-beauty-1",
|
|
968
|
-
variantId: "v-beauty-1",
|
|
969
|
-
quantity: 1,
|
|
970
|
-
title: "Rose Face Serum",
|
|
971
|
-
imageUrl: "https://images.unsplash.com/photo-1611930022073-b7a4ba5fcccd?w=200"
|
|
972
|
-
},
|
|
973
|
-
{
|
|
974
|
-
id: "si-2",
|
|
975
|
-
productId: "p-beauty-2",
|
|
976
|
-
variantId: "v-beauty-2",
|
|
977
|
-
quantity: 1,
|
|
978
|
-
title: "Vitamin C Moisturizer",
|
|
979
|
-
imageUrl: "https://images.unsplash.com/photo-1556228578-8c89e6adf883?w=200"
|
|
980
|
-
}
|
|
981
|
-
],
|
|
982
|
-
status: "scheduled"
|
|
983
|
-
},
|
|
984
|
-
{
|
|
985
|
-
id: "schedule-order-2",
|
|
986
|
-
subscriptionId: "sub_1",
|
|
987
|
-
deliveryDate: futureDateStr(35),
|
|
988
|
-
items: [
|
|
989
|
-
{
|
|
990
|
-
id: "si-3",
|
|
991
|
-
productId: "p-beauty-1",
|
|
992
|
-
variantId: "v-beauty-1",
|
|
993
|
-
quantity: 1,
|
|
994
|
-
title: "Rose Face Serum",
|
|
995
|
-
imageUrl: "https://images.unsplash.com/photo-1611930022073-b7a4ba5fcccd?w=200"
|
|
996
|
-
},
|
|
997
|
-
{
|
|
998
|
-
id: "si-4",
|
|
999
|
-
productId: "p-beauty-3",
|
|
1000
|
-
variantId: "v-beauty-3",
|
|
1001
|
-
quantity: 1,
|
|
1002
|
-
title: "Hyaluronic Acid Serum",
|
|
1003
|
-
imageUrl: "https://images.unsplash.com/photo-1621232201696-ba6c9db10a97?w=200"
|
|
1004
|
-
}
|
|
1005
|
-
],
|
|
1006
|
-
status: "scheduled"
|
|
1007
|
-
}
|
|
1008
|
-
];
|
|
1009
|
-
let adjustments = [];
|
|
1010
|
-
return {
|
|
1011
|
-
async getUpcomingOrders(count) {
|
|
1012
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
1013
|
-
return { _tag: "Success", data: orders.slice(0, count) };
|
|
1014
|
-
},
|
|
1015
|
-
async getAdjustments() {
|
|
1016
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
1017
|
-
return { _tag: "Success", data: [...adjustments] };
|
|
1018
|
-
},
|
|
1019
|
-
async skipOrder({ subscriptionId }) {
|
|
1020
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
1021
|
-
const order = orders.find(
|
|
1022
|
-
(o2) => o2.subscriptionId === subscriptionId && o2.status === "scheduled"
|
|
1023
|
-
);
|
|
1024
|
-
if (!order) return { _tag: "Failure", error: "No scheduled order found" };
|
|
1025
|
-
orders = orders.map(
|
|
1026
|
-
(o2) => o2.id === order.id ? { ...o2, status: "skipped" } : o2
|
|
1027
|
-
);
|
|
1028
|
-
const adj = {
|
|
1029
|
-
id: `adj-${Date.now()}`,
|
|
1030
|
-
subscriptionId,
|
|
1031
|
-
type: "skip"
|
|
1032
|
-
};
|
|
1033
|
-
adjustments = [...adjustments, adj];
|
|
1034
|
-
return { _tag: "Success", data: void 0 };
|
|
1035
|
-
},
|
|
1036
|
-
async changeDateAdjustment({ subscriptionId, newDate }) {
|
|
1037
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
1038
|
-
const order = orders.find(
|
|
1039
|
-
(o2) => o2.subscriptionId === subscriptionId && o2.status === "scheduled"
|
|
1040
|
-
);
|
|
1041
|
-
if (!order) return { _tag: "Failure", error: "No scheduled order found" };
|
|
1042
|
-
orders = orders.map(
|
|
1043
|
-
(o2) => o2.id === order.id ? { ...o2, deliveryDate: newDate } : o2
|
|
1044
|
-
);
|
|
1045
|
-
const adj = {
|
|
1046
|
-
id: `adj-${Date.now()}`,
|
|
1047
|
-
subscriptionId,
|
|
1048
|
-
type: "date_change",
|
|
1049
|
-
newDate
|
|
1050
|
-
};
|
|
1051
|
-
adjustments = [...adjustments, adj];
|
|
1052
|
-
return { _tag: "Success", data: void 0 };
|
|
1053
|
-
},
|
|
1054
|
-
async removeAdjustment({ adjustmentId }) {
|
|
1055
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
1056
|
-
adjustments = adjustments.filter((a3) => a3.id !== adjustmentId);
|
|
1057
|
-
return { _tag: "Success", data: void 0 };
|
|
1058
|
-
}
|
|
1059
|
-
};
|
|
1060
|
-
}
|
|
1061
|
-
function createApiSchedulesAdapter(fetcher) {
|
|
1062
|
-
return {
|
|
1063
|
-
async getUpcomingOrders(count) {
|
|
1064
|
-
try {
|
|
1065
|
-
const res = await fetcher(`/customer/v1/schedules/?count=${count}`);
|
|
1066
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1067
|
-
const data = await res.json();
|
|
1068
|
-
return { _tag: "Success", data: data.orders };
|
|
1069
|
-
} catch (e2) {
|
|
1070
|
-
return { _tag: "Failure", error: e2 };
|
|
1071
|
-
}
|
|
1072
|
-
},
|
|
1073
|
-
async getAdjustments() {
|
|
1074
|
-
try {
|
|
1075
|
-
const res = await fetcher(`/customer/v1/schedules/adjustments`);
|
|
1076
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1077
|
-
const data = await res.json();
|
|
1078
|
-
const adjustments = data.data.map((a3) => ({
|
|
1079
|
-
id: a3.id,
|
|
1080
|
-
subscriptionId: a3.subscriptionId ?? "",
|
|
1081
|
-
type: a3.type === "CHANGE_DATE" ? "date_change" : "skip",
|
|
1082
|
-
newDate: a3.newDate
|
|
1083
|
-
}));
|
|
1084
|
-
return { _tag: "Success", data: adjustments };
|
|
1085
|
-
} catch (e2) {
|
|
1086
|
-
return { _tag: "Failure", error: e2 };
|
|
1087
|
-
}
|
|
1088
|
-
},
|
|
1089
|
-
async skipOrder({ cycle, date }) {
|
|
1090
|
-
if (cycle == null && date == null) {
|
|
1091
|
-
return { _tag: "Failure", error: "Either cycle or date is required for skipOrder" };
|
|
1092
|
-
}
|
|
1093
|
-
try {
|
|
1094
|
-
const matcher = cycle != null ? { type: "CYCLE", input: { cycle } } : { type: "DATE", input: { date: new Date(date).toISOString() } };
|
|
1095
|
-
const res = await fetcher(`/customer/v1/schedules/adjustments`, {
|
|
1096
|
-
method: "POST",
|
|
1097
|
-
headers: { "Content-Type": "application/json" },
|
|
1098
|
-
body: JSON.stringify({
|
|
1099
|
-
matcher,
|
|
1100
|
-
action: { type: "SKIP_ORDER", input: { reason: "" } }
|
|
1101
|
-
})
|
|
1102
|
-
});
|
|
1103
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1104
|
-
return { _tag: "Success", data: void 0 };
|
|
1105
|
-
} catch (e2) {
|
|
1106
|
-
return { _tag: "Failure", error: e2 };
|
|
1107
|
-
}
|
|
1108
|
-
},
|
|
1109
|
-
async changeDateAdjustment({ newDate, currentDate }) {
|
|
1110
|
-
if (currentDate == null) {
|
|
1111
|
-
return {
|
|
1112
|
-
_tag: "Failure",
|
|
1113
|
-
error: "currentDate is required for changeDateAdjustment"
|
|
1114
|
-
};
|
|
1115
|
-
}
|
|
1116
|
-
try {
|
|
1117
|
-
const matcher = { type: "DATE", input: { date: new Date(currentDate).toISOString() } };
|
|
1118
|
-
const res = await fetcher(`/customer/v1/schedules/adjustments`, {
|
|
1119
|
-
method: "POST",
|
|
1120
|
-
headers: { "Content-Type": "application/json" },
|
|
1121
|
-
body: JSON.stringify({
|
|
1122
|
-
matcher,
|
|
1123
|
-
action: {
|
|
1124
|
-
type: "CHANGE_DATE",
|
|
1125
|
-
input: { newDate: new Date(newDate).toISOString() }
|
|
1126
|
-
}
|
|
1127
|
-
})
|
|
1128
|
-
});
|
|
1129
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1130
|
-
return { _tag: "Success", data: void 0 };
|
|
1131
|
-
} catch (e2) {
|
|
1132
|
-
return { _tag: "Failure", error: e2 };
|
|
1133
|
-
}
|
|
1134
|
-
},
|
|
1135
|
-
async removeAdjustment({ adjustmentId }) {
|
|
1136
|
-
try {
|
|
1137
|
-
const res = await fetcher(
|
|
1138
|
-
`/customer/v1/schedules/adjustments/${adjustmentId}`,
|
|
1139
|
-
{ method: "DELETE" }
|
|
1140
|
-
);
|
|
1141
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1142
|
-
return { _tag: "Success", data: void 0 };
|
|
1143
|
-
} catch (e2) {
|
|
1144
|
-
return { _tag: "Failure", error: e2 };
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
};
|
|
1148
|
-
}
|
|
1149
|
-
const SchedulesServiceContext = createContext("services/schedules");
|
|
1150
|
-
function createSchedulesService(adapter, opts) {
|
|
1151
|
-
const upcoming = d([]);
|
|
1152
|
-
async function refreshUpcoming() {
|
|
1153
|
-
const count = Math.max(upcoming.value.length, 3);
|
|
1154
|
-
const result = await adapter.getUpcomingOrders(count);
|
|
1155
|
-
if (result._tag === "Success") {
|
|
1156
|
-
upcoming.value = result.data;
|
|
1157
|
-
}
|
|
1158
|
-
}
|
|
1159
|
-
return {
|
|
1160
|
-
upcoming,
|
|
1161
|
-
hasPendingBilling: opts.hasPendingBilling,
|
|
1162
|
-
async getUpcomingOrder() {
|
|
1163
|
-
const result = await adapter.getUpcomingOrders(1);
|
|
1164
|
-
if (result._tag === "Failure") return result;
|
|
1165
|
-
upcoming.value = result.data;
|
|
1166
|
-
return { _tag: "Success", data: result.data[0] ?? null };
|
|
1167
|
-
},
|
|
1168
|
-
async getUpcomingOrders(count) {
|
|
1169
|
-
const result = await adapter.getUpcomingOrders(count);
|
|
1170
|
-
if (result._tag === "Success") {
|
|
1171
|
-
upcoming.value = result.data;
|
|
1172
|
-
}
|
|
1173
|
-
return result;
|
|
1174
|
-
},
|
|
1175
|
-
async getAdjustments() {
|
|
1176
|
-
return adapter.getAdjustments();
|
|
1177
|
-
},
|
|
1178
|
-
async skipOrder(params) {
|
|
1179
|
-
const result = await adapter.skipOrder(params);
|
|
1180
|
-
if (result._tag === "Success") {
|
|
1181
|
-
await refreshUpcoming();
|
|
1182
|
-
}
|
|
1183
|
-
return result;
|
|
1184
|
-
},
|
|
1185
|
-
async changeDateAdjustment(params) {
|
|
1186
|
-
const result = await adapter.changeDateAdjustment(params);
|
|
1187
|
-
if (result._tag === "Success") {
|
|
1188
|
-
await refreshUpcoming();
|
|
1189
|
-
}
|
|
1190
|
-
return result;
|
|
1191
|
-
},
|
|
1192
|
-
async removeAdjustment(params) {
|
|
1193
|
-
return adapter.removeAdjustment(params);
|
|
1194
|
-
}
|
|
1195
|
-
};
|
|
1196
|
-
}
|
|
1197
787
|
function createMockSubscriptionAdapter(options = {}) {
|
|
1198
788
|
const mockSubscriptions = [
|
|
1199
789
|
{
|
|
@@ -1206,9 +796,7 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1206
796
|
variantId: "variant_1",
|
|
1207
797
|
quantity: 2,
|
|
1208
798
|
price: { amount: "29.99", currencyCode: "USD" },
|
|
1209
|
-
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15")
|
|
1210
|
-
billingPolicy: { intervalCount: 1, interval: "MONTH" },
|
|
1211
|
-
deliveryPolicy: { intervalCount: 1, interval: "MONTH" }
|
|
799
|
+
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15")
|
|
1212
800
|
}
|
|
1213
801
|
],
|
|
1214
802
|
discounts: [
|
|
@@ -1236,9 +824,7 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1236
824
|
variantId: "variant_2",
|
|
1237
825
|
quantity: 1,
|
|
1238
826
|
price: { amount: "49.99", currencyCode: "USD" },
|
|
1239
|
-
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-20")
|
|
1240
|
-
billingPolicy: { intervalCount: 2, interval: "WEEK" },
|
|
1241
|
-
deliveryPolicy: { intervalCount: 2, interval: "WEEK" }
|
|
827
|
+
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-20")
|
|
1242
828
|
}
|
|
1243
829
|
],
|
|
1244
830
|
discounts: [],
|
|
@@ -1249,24 +835,6 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1249
835
|
updatedAt: "2024-10-10T00:00:00Z"
|
|
1250
836
|
}
|
|
1251
837
|
];
|
|
1252
|
-
const mockUpsellProducts = [
|
|
1253
|
-
{
|
|
1254
|
-
id: "upsell-1",
|
|
1255
|
-
variantId: "upsell-v-1",
|
|
1256
|
-
title: "Retinol Night Cream",
|
|
1257
|
-
imageUrl: "https://images.unsplash.com/photo-1617897903246-719242758050?w=200",
|
|
1258
|
-
price: { amount: "38.00", currencyCode: "USD" },
|
|
1259
|
-
description: "Anti-aging night treatment"
|
|
1260
|
-
},
|
|
1261
|
-
{
|
|
1262
|
-
id: "upsell-2",
|
|
1263
|
-
variantId: "upsell-v-2",
|
|
1264
|
-
title: "SPF 50 Day Shield",
|
|
1265
|
-
imageUrl: "https://images.unsplash.com/photo-1556228578-8c89e6adf883?w=200",
|
|
1266
|
-
price: { amount: "24.00", currencyCode: "USD" },
|
|
1267
|
-
description: "Lightweight daily sun protection"
|
|
1268
|
-
}
|
|
1269
|
-
];
|
|
1270
838
|
return {
|
|
1271
839
|
async getById(id) {
|
|
1272
840
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1275,7 +843,7 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1275
843
|
},
|
|
1276
844
|
async search(options2 = {}) {
|
|
1277
845
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1278
|
-
const pageSize =
|
|
846
|
+
const pageSize = 1;
|
|
1279
847
|
const allItems = mockSubscriptions;
|
|
1280
848
|
let startIndex = 0;
|
|
1281
849
|
let endIndex = pageSize;
|
|
@@ -1291,22 +859,20 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1291
859
|
}
|
|
1292
860
|
}
|
|
1293
861
|
const pageItems = allItems.slice(startIndex, endIndex);
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
items:
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
startCursor: pageItems.length > 0 ? startIndex.toString() : null,
|
|
1306
|
-
endCursor: pageItems.length > 0 ? (endIndex - 1).toString() : null
|
|
1307
|
-
}
|
|
862
|
+
const paginatedList = {
|
|
863
|
+
items: pageItems.map((sub) => ({
|
|
864
|
+
...sub,
|
|
865
|
+
items: sub.items.map((item) => ({ ...item })),
|
|
866
|
+
discounts: sub.discounts.map((discount) => ({ ...discount }))
|
|
867
|
+
})),
|
|
868
|
+
pageInfo: {
|
|
869
|
+
hasNextPage: endIndex < allItems.length,
|
|
870
|
+
hasPrevPage: startIndex > 0,
|
|
871
|
+
startCursor: pageItems.length > 0 ? startIndex.toString() : null,
|
|
872
|
+
endCursor: pageItems.length > 0 ? (endIndex - 1).toString() : null
|
|
1308
873
|
}
|
|
1309
874
|
};
|
|
875
|
+
return { _tag: "Success", data: paginatedList };
|
|
1310
876
|
},
|
|
1311
877
|
async addItem() {
|
|
1312
878
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1344,11 +910,24 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1344
910
|
(sub) => sub.id === params.subscriptionId
|
|
1345
911
|
);
|
|
1346
912
|
if (!subscription) {
|
|
1347
|
-
return {
|
|
913
|
+
return {
|
|
914
|
+
_tag: "Failure",
|
|
915
|
+
error: "Subscription not found"
|
|
916
|
+
};
|
|
1348
917
|
}
|
|
1349
918
|
subscription.nextDeliveryDate = new Date(params.newDate);
|
|
1350
919
|
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1351
|
-
|
|
920
|
+
subscription.items.forEach((item) => {
|
|
921
|
+
item.nextDeliveryDate = new Date(params.newDate);
|
|
922
|
+
});
|
|
923
|
+
return {
|
|
924
|
+
_tag: "Success",
|
|
925
|
+
data: {
|
|
926
|
+
...subscription,
|
|
927
|
+
items: subscription.items.map((item) => ({ ...item })),
|
|
928
|
+
discounts: subscription.discounts.map((discount) => ({ ...discount }))
|
|
929
|
+
}
|
|
930
|
+
};
|
|
1352
931
|
},
|
|
1353
932
|
async resume(params) {
|
|
1354
933
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1356,11 +935,21 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1356
935
|
(sub) => sub.id === params.subscriptionId
|
|
1357
936
|
);
|
|
1358
937
|
if (!subscription) {
|
|
1359
|
-
return {
|
|
938
|
+
return {
|
|
939
|
+
_tag: "Failure",
|
|
940
|
+
error: "Subscription not found"
|
|
941
|
+
};
|
|
1360
942
|
}
|
|
1361
943
|
subscription.status = "active";
|
|
1362
944
|
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1363
|
-
return {
|
|
945
|
+
return {
|
|
946
|
+
_tag: "Success",
|
|
947
|
+
data: {
|
|
948
|
+
...subscription,
|
|
949
|
+
items: subscription.items.map((item) => ({ ...item })),
|
|
950
|
+
discounts: subscription.discounts.map((discount) => ({ ...discount }))
|
|
951
|
+
}
|
|
952
|
+
};
|
|
1364
953
|
},
|
|
1365
954
|
async pause(params) {
|
|
1366
955
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1368,11 +957,21 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1368
957
|
(sub) => sub.id === params.subscriptionId
|
|
1369
958
|
);
|
|
1370
959
|
if (!subscription) {
|
|
1371
|
-
return {
|
|
960
|
+
return {
|
|
961
|
+
_tag: "Failure",
|
|
962
|
+
error: "Subscription not found"
|
|
963
|
+
};
|
|
1372
964
|
}
|
|
1373
965
|
subscription.status = "paused";
|
|
1374
966
|
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1375
|
-
return {
|
|
967
|
+
return {
|
|
968
|
+
_tag: "Success",
|
|
969
|
+
data: {
|
|
970
|
+
...subscription,
|
|
971
|
+
items: subscription.items.map((item) => ({ ...item })),
|
|
972
|
+
discounts: subscription.discounts.map((discount) => ({ ...discount }))
|
|
973
|
+
}
|
|
974
|
+
};
|
|
1376
975
|
},
|
|
1377
976
|
async reactivate(params) {
|
|
1378
977
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1380,11 +979,21 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1380
979
|
(sub) => sub.id === params.subscriptionId
|
|
1381
980
|
);
|
|
1382
981
|
if (!subscription) {
|
|
1383
|
-
return {
|
|
982
|
+
return {
|
|
983
|
+
_tag: "Failure",
|
|
984
|
+
error: "Subscription not found"
|
|
985
|
+
};
|
|
1384
986
|
}
|
|
1385
987
|
subscription.status = "active";
|
|
1386
988
|
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1387
|
-
return {
|
|
989
|
+
return {
|
|
990
|
+
_tag: "Success",
|
|
991
|
+
data: {
|
|
992
|
+
...subscription,
|
|
993
|
+
items: subscription.items.map((item) => ({ ...item })),
|
|
994
|
+
discounts: subscription.discounts.map((discount) => ({ ...discount }))
|
|
995
|
+
}
|
|
996
|
+
};
|
|
1388
997
|
},
|
|
1389
998
|
async cancel(params) {
|
|
1390
999
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1392,11 +1001,21 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1392
1001
|
(sub) => sub.id === params.subscriptionId
|
|
1393
1002
|
);
|
|
1394
1003
|
if (!subscription) {
|
|
1395
|
-
return {
|
|
1004
|
+
return {
|
|
1005
|
+
_tag: "Failure",
|
|
1006
|
+
error: "Subscription not found"
|
|
1007
|
+
};
|
|
1396
1008
|
}
|
|
1397
1009
|
subscription.status = "canceled";
|
|
1398
1010
|
subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1399
|
-
return {
|
|
1011
|
+
return {
|
|
1012
|
+
_tag: "Success",
|
|
1013
|
+
data: {
|
|
1014
|
+
...subscription,
|
|
1015
|
+
items: subscription.items.map((item) => ({ ...item })),
|
|
1016
|
+
discounts: subscription.discounts.map((discount) => ({ ...discount }))
|
|
1017
|
+
}
|
|
1018
|
+
};
|
|
1400
1019
|
},
|
|
1401
1020
|
async getAvailablePlans() {
|
|
1402
1021
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1428,312 +1047,6 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1428
1047
|
var _a;
|
|
1429
1048
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1430
1049
|
return { _tag: "Success", data: ((_a = mockSubscriptions[0]) == null ? void 0 : _a.id) ?? null };
|
|
1431
|
-
},
|
|
1432
|
-
async getUpsellProducts() {
|
|
1433
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1434
|
-
return { _tag: "Success", data: [...mockUpsellProducts] };
|
|
1435
|
-
},
|
|
1436
|
-
async addUpsellProduct() {
|
|
1437
|
-
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
1438
|
-
return { _tag: "Success", data: void 0 };
|
|
1439
|
-
}
|
|
1440
|
-
};
|
|
1441
|
-
}
|
|
1442
|
-
function mapSubscription(raw) {
|
|
1443
|
-
var _a, _b;
|
|
1444
|
-
const status = raw.status === "merged" ? "canceled" : raw.status;
|
|
1445
|
-
const deliveryPolicy = raw.deliveryPolicy ?? ((_b = (_a = raw.items) == null ? void 0 : _a[0]) == null ? void 0 : _b.deliveryPolicy);
|
|
1446
|
-
const frequency = deliveryPolicy ? `${deliveryPolicy.intervalCount} ${deliveryPolicy.interval}` : "";
|
|
1447
|
-
return {
|
|
1448
|
-
id: raw.id,
|
|
1449
|
-
customerId: "",
|
|
1450
|
-
items: (raw.items ?? []).map(
|
|
1451
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1452
|
-
(item) => ({
|
|
1453
|
-
id: item.id,
|
|
1454
|
-
productId: item.productId ?? item.product ?? "",
|
|
1455
|
-
variantId: item.variantId ?? item.variant ?? "",
|
|
1456
|
-
quantity: item.quantity,
|
|
1457
|
-
price: item.price ?? {
|
|
1458
|
-
amount: String(item.totalPrice ?? 0),
|
|
1459
|
-
currencyCode: raw.currencyCode ?? ""
|
|
1460
|
-
},
|
|
1461
|
-
nextDeliveryDate: item.nextDeliveryDate ? new Date(item.nextDeliveryDate) : null,
|
|
1462
|
-
billingPolicy: item.billingPolicy ?? raw.billingPolicy ?? null,
|
|
1463
|
-
deliveryPolicy: item.deliveryPolicy ?? raw.deliveryPolicy ?? null
|
|
1464
|
-
})
|
|
1465
|
-
),
|
|
1466
|
-
discounts: (raw.discounts ?? []).map(
|
|
1467
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1468
|
-
(d2) => {
|
|
1469
|
-
var _a2, _b2, _c;
|
|
1470
|
-
return {
|
|
1471
|
-
id: d2.id,
|
|
1472
|
-
type: ((_a2 = d2.value) == null ? void 0 : _a2.type) === "fixed-amount" || d2.type === "fixed_amount" ? "fixed_amount" : "percentage",
|
|
1473
|
-
value: ((_b2 = d2.value) == null ? void 0 : _b2.amount) ?? ((_c = d2.value) == null ? void 0 : _c.percentage) ?? d2.value ?? 0,
|
|
1474
|
-
code: d2.title ?? d2.code ?? "",
|
|
1475
|
-
description: d2.description ?? ""
|
|
1476
|
-
};
|
|
1477
|
-
}
|
|
1478
|
-
),
|
|
1479
|
-
status,
|
|
1480
|
-
nextDeliveryDate: raw.nextBillingDate ? new Date(raw.nextBillingDate) : raw.nextDeliveryDate ? new Date(raw.nextDeliveryDate) : null,
|
|
1481
|
-
frequency,
|
|
1482
|
-
createdAt: raw.createdAt,
|
|
1483
|
-
updatedAt: raw.updatedAt
|
|
1484
|
-
};
|
|
1485
|
-
}
|
|
1486
|
-
function createApiSubscriptionAdapter(fetcher) {
|
|
1487
|
-
return {
|
|
1488
|
-
async search(options) {
|
|
1489
|
-
var _a;
|
|
1490
|
-
try {
|
|
1491
|
-
const params = new URLSearchParams();
|
|
1492
|
-
if ((_a = options == null ? void 0 : options.filters) == null ? void 0 : _a.length) {
|
|
1493
|
-
const q2 = options.filters.filter((f2) => Object.keys(f2).length > 0).flatMap((f2) => Object.entries(f2).filter(([, v2]) => Boolean(v2))).map(([k2, v2]) => `${k2}:'${v2}'`).join(" AND ");
|
|
1494
|
-
if (q2) params.set("query", q2);
|
|
1495
|
-
}
|
|
1496
|
-
if (options == null ? void 0 : options.pagination) {
|
|
1497
|
-
if ("after" in options.pagination)
|
|
1498
|
-
params.set("after", options.pagination.after);
|
|
1499
|
-
else if ("before" in options.pagination)
|
|
1500
|
-
params.set("before", options.pagination.before);
|
|
1501
|
-
}
|
|
1502
|
-
const query = params.toString() ? `?${params.toString()}` : "";
|
|
1503
|
-
const res = await fetcher(`/customer/v1/subscriptions${query}`);
|
|
1504
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1505
|
-
const body = await res.json();
|
|
1506
|
-
return {
|
|
1507
|
-
_tag: "Success",
|
|
1508
|
-
data: {
|
|
1509
|
-
items: body.data.map(mapSubscription),
|
|
1510
|
-
pageInfo: {
|
|
1511
|
-
hasNextPage: body.hasNextPage,
|
|
1512
|
-
hasPrevPage: body.hasPrevPage,
|
|
1513
|
-
startCursor: body.startCursor,
|
|
1514
|
-
endCursor: body.endCursor
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
};
|
|
1518
|
-
} catch (e2) {
|
|
1519
|
-
return { _tag: "Failure", error: e2 };
|
|
1520
|
-
}
|
|
1521
|
-
},
|
|
1522
|
-
async getById(id) {
|
|
1523
|
-
try {
|
|
1524
|
-
const res = await fetcher(
|
|
1525
|
-
`/customer/v1/subscriptions?query=id:"${id}"&limit=1`
|
|
1526
|
-
);
|
|
1527
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1528
|
-
const body = await res.json();
|
|
1529
|
-
const raw = body.data[0];
|
|
1530
|
-
return { _tag: "Success", data: raw ? mapSubscription(raw) : null };
|
|
1531
|
-
} catch (e2) {
|
|
1532
|
-
return { _tag: "Failure", error: e2 };
|
|
1533
|
-
}
|
|
1534
|
-
},
|
|
1535
|
-
async addItem({ subscriptionId, item }) {
|
|
1536
|
-
try {
|
|
1537
|
-
const res = await fetcher(
|
|
1538
|
-
`/customer/v1/subscriptions/${subscriptionId}/items`,
|
|
1539
|
-
{
|
|
1540
|
-
method: "POST",
|
|
1541
|
-
headers: { "Content-Type": "application/json" },
|
|
1542
|
-
body: JSON.stringify(item)
|
|
1543
|
-
}
|
|
1544
|
-
);
|
|
1545
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1546
|
-
return { _tag: "Success", data: void 0 };
|
|
1547
|
-
} catch (e2) {
|
|
1548
|
-
return { _tag: "Failure", error: e2 };
|
|
1549
|
-
}
|
|
1550
|
-
},
|
|
1551
|
-
async removeItem({ subscriptionId, itemId }) {
|
|
1552
|
-
try {
|
|
1553
|
-
const res = await fetcher(
|
|
1554
|
-
`/customer/v1/subscriptions/${subscriptionId}/items/${itemId}`,
|
|
1555
|
-
{ method: "DELETE" }
|
|
1556
|
-
);
|
|
1557
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1558
|
-
return { _tag: "Success", data: void 0 };
|
|
1559
|
-
} catch (e2) {
|
|
1560
|
-
return { _tag: "Failure", error: e2 };
|
|
1561
|
-
}
|
|
1562
|
-
},
|
|
1563
|
-
async addDiscount({ subscriptionId, code }) {
|
|
1564
|
-
try {
|
|
1565
|
-
const res = await fetcher(
|
|
1566
|
-
`/customer/v1/subscriptions/${subscriptionId}/discounts`,
|
|
1567
|
-
{
|
|
1568
|
-
method: "POST",
|
|
1569
|
-
headers: { "Content-Type": "application/json" },
|
|
1570
|
-
body: JSON.stringify({ code })
|
|
1571
|
-
}
|
|
1572
|
-
);
|
|
1573
|
-
if (!res.ok) return { _tag: "Failure", error: { kind: "NETWORK", message: `HTTP ${res.status}` } };
|
|
1574
|
-
return { _tag: "Success", data: void 0 };
|
|
1575
|
-
} catch (e2) {
|
|
1576
|
-
return { _tag: "Failure", error: { kind: "UNKNOWN", message: e2 instanceof Error ? e2.message : void 0 } };
|
|
1577
|
-
}
|
|
1578
|
-
},
|
|
1579
|
-
async removeDiscount({ subscriptionId, discountId }) {
|
|
1580
|
-
try {
|
|
1581
|
-
const res = await fetcher(
|
|
1582
|
-
`/customer/v1/subscriptions/${subscriptionId}/discounts/${discountId}`,
|
|
1583
|
-
{ method: "DELETE" }
|
|
1584
|
-
);
|
|
1585
|
-
if (!res.ok) return { _tag: "Failure", error: { kind: "NETWORK", message: `HTTP ${res.status}` } };
|
|
1586
|
-
return { _tag: "Success", data: void 0 };
|
|
1587
|
-
} catch (e2) {
|
|
1588
|
-
return { _tag: "Failure", error: { kind: "UNKNOWN", message: e2 instanceof Error ? e2.message : void 0 } };
|
|
1589
|
-
}
|
|
1590
|
-
},
|
|
1591
|
-
// Uses PATCH /customer/v1/subscriptions/{id} — the dedicated /reschedule route does not exist.
|
|
1592
|
-
async reschedule({ subscriptionId, newDate }) {
|
|
1593
|
-
try {
|
|
1594
|
-
const res = await fetcher(
|
|
1595
|
-
`/customer/v1/subscriptions/${subscriptionId}`,
|
|
1596
|
-
{
|
|
1597
|
-
method: "PATCH",
|
|
1598
|
-
headers: { "Content-Type": "application/json" },
|
|
1599
|
-
body: JSON.stringify({ nextBillingDate: newDate })
|
|
1600
|
-
}
|
|
1601
|
-
);
|
|
1602
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1603
|
-
const data = await res.json();
|
|
1604
|
-
return { _tag: "Success", data: mapSubscription(data) };
|
|
1605
|
-
} catch (e2) {
|
|
1606
|
-
return { _tag: "Failure", error: e2 };
|
|
1607
|
-
}
|
|
1608
|
-
},
|
|
1609
|
-
async resume({ subscriptionId }) {
|
|
1610
|
-
try {
|
|
1611
|
-
const res = await fetcher(
|
|
1612
|
-
`/customer/v1/subscriptions/${subscriptionId}/resume`,
|
|
1613
|
-
{ method: "POST" }
|
|
1614
|
-
);
|
|
1615
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1616
|
-
const data = await res.json();
|
|
1617
|
-
return { _tag: "Success", data: mapSubscription(data) };
|
|
1618
|
-
} catch (e2) {
|
|
1619
|
-
return { _tag: "Failure", error: e2 };
|
|
1620
|
-
}
|
|
1621
|
-
},
|
|
1622
|
-
async pause({ subscriptionId }) {
|
|
1623
|
-
try {
|
|
1624
|
-
const res = await fetcher(
|
|
1625
|
-
`/customer/v1/subscriptions/${subscriptionId}/pause`,
|
|
1626
|
-
{ method: "POST" }
|
|
1627
|
-
);
|
|
1628
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1629
|
-
const data = await res.json();
|
|
1630
|
-
return { _tag: "Success", data: mapSubscription(data) };
|
|
1631
|
-
} catch (e2) {
|
|
1632
|
-
return { _tag: "Failure", error: e2 };
|
|
1633
|
-
}
|
|
1634
|
-
},
|
|
1635
|
-
async reactivate({ subscriptionId }) {
|
|
1636
|
-
try {
|
|
1637
|
-
const res = await fetcher(
|
|
1638
|
-
`/customer/v1/subscriptions/${subscriptionId}/reactivate`,
|
|
1639
|
-
{ method: "POST" }
|
|
1640
|
-
);
|
|
1641
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1642
|
-
const data = await res.json();
|
|
1643
|
-
return { _tag: "Success", data: mapSubscription(data) };
|
|
1644
|
-
} catch (e2) {
|
|
1645
|
-
return { _tag: "Failure", error: e2 };
|
|
1646
|
-
}
|
|
1647
|
-
},
|
|
1648
|
-
async cancel({ subscriptionId, reason }) {
|
|
1649
|
-
try {
|
|
1650
|
-
const res = await fetcher(
|
|
1651
|
-
`/customer/v1/subscriptions/${subscriptionId}/cancel`,
|
|
1652
|
-
{
|
|
1653
|
-
method: "POST",
|
|
1654
|
-
headers: { "Content-Type": "application/json" },
|
|
1655
|
-
body: JSON.stringify({ cancellationReason: reason })
|
|
1656
|
-
}
|
|
1657
|
-
);
|
|
1658
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1659
|
-
const data = await res.json();
|
|
1660
|
-
return { _tag: "Success", data: mapSubscription(data) };
|
|
1661
|
-
} catch (e2) {
|
|
1662
|
-
return { _tag: "Failure", error: e2 };
|
|
1663
|
-
}
|
|
1664
|
-
},
|
|
1665
|
-
// Legacy endpoint — no /customer/v1/subscriptions/{id}/plans exists yet.
|
|
1666
|
-
async getAvailablePlans({ subscriptionId }) {
|
|
1667
|
-
try {
|
|
1668
|
-
const res = await fetcher(
|
|
1669
|
-
`/customer/subscriptions/${subscriptionId}/plans`
|
|
1670
|
-
);
|
|
1671
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1672
|
-
const data = await res.json();
|
|
1673
|
-
return { _tag: "Success", data };
|
|
1674
|
-
} catch (e2) {
|
|
1675
|
-
return { _tag: "Failure", error: e2 };
|
|
1676
|
-
}
|
|
1677
|
-
},
|
|
1678
|
-
// Legacy endpoint — no /customer/v1 equivalent exists yet.
|
|
1679
|
-
async getDefaultSubscriptionId() {
|
|
1680
|
-
try {
|
|
1681
|
-
const res = await fetcher(
|
|
1682
|
-
`/customer/subscriptions/one-by-next-billing-date`
|
|
1683
|
-
);
|
|
1684
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1685
|
-
const data = await res.json();
|
|
1686
|
-
return { _tag: "Success", data: (data == null ? void 0 : data.id) ?? null };
|
|
1687
|
-
} catch (e2) {
|
|
1688
|
-
return { _tag: "Failure", error: e2 };
|
|
1689
|
-
}
|
|
1690
|
-
},
|
|
1691
|
-
// Legacy endpoint — no /customer/v1/subscriptions/{id}/upsells exists yet.
|
|
1692
|
-
async getUpsellProducts({ subscriptionId }) {
|
|
1693
|
-
try {
|
|
1694
|
-
const res = await fetcher(
|
|
1695
|
-
`/customer/subscriptions/${subscriptionId}/upsell-products`
|
|
1696
|
-
);
|
|
1697
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1698
|
-
const data = await res.json();
|
|
1699
|
-
const products = data.map((p2) => {
|
|
1700
|
-
var _a, _b, _c, _d, _e;
|
|
1701
|
-
return {
|
|
1702
|
-
id: p2.id,
|
|
1703
|
-
variantId: ((_b = (_a = p2.variants) == null ? void 0 : _a[0]) == null ? void 0 : _b.id) ?? "",
|
|
1704
|
-
title: p2.title ?? "",
|
|
1705
|
-
imageUrl: ((_c = p2.featuredImage) == null ? void 0 : _c.url) ?? void 0,
|
|
1706
|
-
price: {
|
|
1707
|
-
amount: String(((_e = (_d = p2.variants) == null ? void 0 : _d[0]) == null ? void 0 : _e.price) ?? 0),
|
|
1708
|
-
currencyCode: p2.currencyCode ?? ""
|
|
1709
|
-
}
|
|
1710
|
-
};
|
|
1711
|
-
});
|
|
1712
|
-
return { _tag: "Success", data: products };
|
|
1713
|
-
} catch (e2) {
|
|
1714
|
-
return { _tag: "Failure", error: e2 };
|
|
1715
|
-
}
|
|
1716
|
-
},
|
|
1717
|
-
// Legacy endpoint — no /customer/v1/subscriptions/{id}/upsells POST exists yet.
|
|
1718
|
-
async addUpsellProduct({ subscriptionId, variantId, quantity, oneTime }) {
|
|
1719
|
-
try {
|
|
1720
|
-
const res = await fetcher(
|
|
1721
|
-
`/customer/subscriptions/${subscriptionId}/upsell`,
|
|
1722
|
-
{
|
|
1723
|
-
method: "POST",
|
|
1724
|
-
headers: { "Content-Type": "application/json" },
|
|
1725
|
-
body: JSON.stringify({
|
|
1726
|
-
productVariantId: variantId,
|
|
1727
|
-
quantity,
|
|
1728
|
-
...oneTime ? { renewalLimit: 1 } : {}
|
|
1729
|
-
})
|
|
1730
|
-
}
|
|
1731
|
-
);
|
|
1732
|
-
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1733
|
-
return { _tag: "Success", data: void 0 };
|
|
1734
|
-
} catch (e2) {
|
|
1735
|
-
return { _tag: "Failure", error: e2 };
|
|
1736
|
-
}
|
|
1737
1050
|
}
|
|
1738
1051
|
};
|
|
1739
1052
|
}
|
|
@@ -1759,40 +1072,44 @@ function getCurrentSubscriptionId() {
|
|
|
1759
1072
|
}
|
|
1760
1073
|
function createSubscriptionService(adapter) {
|
|
1761
1074
|
const current = d(null);
|
|
1762
|
-
const hasPendingBilling = d(false);
|
|
1763
1075
|
const discountsChangedAtSignal = d(0);
|
|
1764
|
-
|
|
1076
|
+
const itemsChangedAtSignal = d(0);
|
|
1077
|
+
async function refreshCurrent(subscriptionId) {
|
|
1765
1078
|
const result = await adapter.getById(subscriptionId);
|
|
1766
1079
|
if (result._tag === "Success" && result.data != null) {
|
|
1767
1080
|
current.value = result.data;
|
|
1768
1081
|
}
|
|
1082
|
+
}
|
|
1083
|
+
async function refreshAfterDiscountChange(subscriptionId) {
|
|
1084
|
+
await refreshCurrent(subscriptionId);
|
|
1769
1085
|
discountsChangedAtSignal.value = discountsChangedAtSignal.value + 1;
|
|
1770
1086
|
}
|
|
1087
|
+
async function refreshAfterItemChange(subscriptionId) {
|
|
1088
|
+
await refreshCurrent(subscriptionId);
|
|
1089
|
+
itemsChangedAtSignal.value = itemsChangedAtSignal.value + 1;
|
|
1090
|
+
}
|
|
1771
1091
|
function subscriptionIdFromCurrent() {
|
|
1772
1092
|
var _a;
|
|
1773
1093
|
return ((_a = current.value) == null ? void 0 : _a.id) ?? null;
|
|
1774
1094
|
}
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
async
|
|
1780
|
-
const result = await adapter.
|
|
1095
|
+
const service = {
|
|
1096
|
+
search: adapter.search,
|
|
1097
|
+
getById: adapter.getById,
|
|
1098
|
+
getCurrentSubscriptionId,
|
|
1099
|
+
addItem: async (subscriptionId, item) => {
|
|
1100
|
+
const result = await adapter.addItem({ subscriptionId, item });
|
|
1781
1101
|
if (result._tag === "Success") {
|
|
1782
|
-
|
|
1102
|
+
await refreshAfterItemChange(subscriptionId);
|
|
1783
1103
|
}
|
|
1784
1104
|
return result;
|
|
1785
1105
|
},
|
|
1786
|
-
async
|
|
1787
|
-
const result = await adapter.
|
|
1788
|
-
if (result._tag === "Success"
|
|
1789
|
-
|
|
1106
|
+
removeItem: async (subscriptionId, itemId) => {
|
|
1107
|
+
const result = await adapter.removeItem({ subscriptionId, itemId });
|
|
1108
|
+
if (result._tag === "Success") {
|
|
1109
|
+
await refreshAfterItemChange(subscriptionId);
|
|
1790
1110
|
}
|
|
1791
1111
|
return result;
|
|
1792
1112
|
},
|
|
1793
|
-
getCurrentSubscriptionId,
|
|
1794
|
-
addItem: (subscriptionId, item) => adapter.addItem({ subscriptionId, item }),
|
|
1795
|
-
removeItem: (subscriptionId, itemId) => adapter.removeItem({ subscriptionId, itemId }),
|
|
1796
1113
|
addDiscount: async (code, subscriptionId) => {
|
|
1797
1114
|
const id = subscriptionId ?? subscriptionIdFromCurrent();
|
|
1798
1115
|
if (id == null) {
|
|
@@ -1831,9 +1148,11 @@ function createSubscriptionService(adapter) {
|
|
|
1831
1148
|
cancel: (subscriptionId, reason) => adapter.cancel({ subscriptionId, reason }),
|
|
1832
1149
|
getAvailablePlans: (subscriptionId) => adapter.getAvailablePlans({ subscriptionId }),
|
|
1833
1150
|
getDefaultSubscriptionId: () => adapter.getDefaultSubscriptionId(),
|
|
1834
|
-
|
|
1835
|
-
|
|
1151
|
+
current,
|
|
1152
|
+
discountsChangedAt: discountsChangedAtSignal,
|
|
1153
|
+
itemsChangedAt: itemsChangedAtSignal
|
|
1836
1154
|
};
|
|
1155
|
+
return service;
|
|
1837
1156
|
}
|
|
1838
1157
|
const DISCOUNT_REJECTION_REASONS = [
|
|
1839
1158
|
"INVALID_CODE",
|
|
@@ -2109,67 +1428,57 @@ export {
|
|
|
2109
1428
|
OrdersServiceContext,
|
|
2110
1429
|
ProductServiceContext,
|
|
2111
1430
|
RouterServiceContext,
|
|
2112
|
-
SchedulesServiceContext,
|
|
2113
1431
|
S as SelectedBlockContext,
|
|
2114
1432
|
u as Signal,
|
|
2115
1433
|
StateContext,
|
|
2116
1434
|
SubscriptionServiceContext,
|
|
2117
1435
|
T as ThemeStateContext,
|
|
2118
|
-
|
|
1436
|
+
b as TranslationContext,
|
|
2119
1437
|
W as WorkflowServiceContext,
|
|
2120
|
-
|
|
2121
|
-
|
|
1438
|
+
e as attachEmptyTracking,
|
|
1439
|
+
f as backfillInstanceDefaults,
|
|
2122
1440
|
w as computed,
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
createApiSubscriptionAdapter,
|
|
2128
|
-
f as createBlockInstance,
|
|
2129
|
-
g as createBlockInstanceFromJSON,
|
|
2130
|
-
h as createBlockInstanceFromObject,
|
|
2131
|
-
i as createCeRenderer,
|
|
1441
|
+
g as createBlockInstance,
|
|
1442
|
+
h as createBlockInstanceFromJSON,
|
|
1443
|
+
i as createBlockInstanceFromObject,
|
|
1444
|
+
j as createCeRenderer,
|
|
2132
1445
|
createContext,
|
|
2133
1446
|
createCustomerService,
|
|
2134
|
-
createLoginService,
|
|
2135
|
-
createMockCustomerAdapter,
|
|
2136
|
-
createMockLoginAdapter,
|
|
2137
1447
|
createMockOrdersAdapter,
|
|
2138
1448
|
createMockProductAdapter,
|
|
2139
1449
|
createMockRouterService,
|
|
2140
|
-
createMockSchedulesAdapter,
|
|
2141
1450
|
createMockSubscriptionAdapter,
|
|
2142
1451
|
createMockWorkflowApiAdapter,
|
|
2143
1452
|
createOrdersService,
|
|
2144
1453
|
createProductService,
|
|
2145
1454
|
createRouterService,
|
|
2146
|
-
|
|
2147
|
-
j as createSelectedBlock,
|
|
1455
|
+
k as createSelectedBlock,
|
|
2148
1456
|
createState,
|
|
2149
1457
|
createSubscriptionService,
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
1458
|
+
l as createThemeState,
|
|
1459
|
+
m as createTranslationService,
|
|
1460
|
+
n as createWorkflowApiAdapter,
|
|
1461
|
+
o as createWorkflowService,
|
|
1462
|
+
p as defineBlock,
|
|
1463
|
+
q as defineBlockRuntime,
|
|
2156
1464
|
E as effect,
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
1465
|
+
s as getDefaultBlockForAction,
|
|
1466
|
+
t as getDefinedBlocks,
|
|
1467
|
+
v as hasDefaultBlockForAction,
|
|
1468
|
+
x as hasRenderedContent,
|
|
1469
|
+
y as indexOverrides,
|
|
1470
|
+
z as injectContext,
|
|
1471
|
+
A as isEditorPreview,
|
|
1472
|
+
F as isStubDefinition,
|
|
2164
1473
|
loadBlockRegistry,
|
|
2165
1474
|
loginService,
|
|
2166
|
-
|
|
2167
|
-
|
|
1475
|
+
G as onRegisterBlock,
|
|
1476
|
+
H as provideContext,
|
|
2168
1477
|
registerBlock,
|
|
2169
|
-
|
|
1478
|
+
I as serializeBlocks,
|
|
2170
1479
|
d as signal,
|
|
2171
|
-
|
|
2172
|
-
|
|
1480
|
+
J as subscribeContext,
|
|
1481
|
+
K as untracked,
|
|
2173
1482
|
waitForDevBlocksUrl,
|
|
2174
|
-
|
|
1483
|
+
L as withWrapper
|
|
2175
1484
|
};
|