@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.
Files changed (68) hide show
  1. package/dist/{ExtensionRoot-C7tcvV-n.js → ExtensionRoot-9XfhG8YM.js} +1 -3
  2. package/dist/block.d.ts.map +1 -1
  3. package/dist/core.js +319 -1010
  4. package/dist/editor/handler.d.ts +1 -1
  5. package/dist/editor/handler.d.ts.map +1 -1
  6. package/dist/editor.js +1 -3
  7. package/dist/juo-workflow-CkyZRq60.js +1667 -0
  8. package/dist/services/customer/customerService.d.ts +2 -3
  9. package/dist/services/customer/customerService.d.ts.map +1 -1
  10. package/dist/services/customer/index.d.ts +0 -1
  11. package/dist/services/customer/index.d.ts.map +1 -1
  12. package/dist/services/customer/types.d.ts +1 -4
  13. package/dist/services/customer/types.d.ts.map +1 -1
  14. package/dist/services/index.d.ts +0 -1
  15. package/dist/services/index.d.ts.map +1 -1
  16. package/dist/services/login/index.d.ts +1 -3
  17. package/dist/services/login/index.d.ts.map +1 -1
  18. package/dist/services/login/loginService.d.ts +2 -6
  19. package/dist/services/login/loginService.d.ts.map +1 -1
  20. package/dist/services/product/adapter.d.ts +1 -4
  21. package/dist/services/product/adapter.d.ts.map +1 -1
  22. package/dist/services/product/index.d.ts +1 -1
  23. package/dist/services/product/index.d.ts.map +1 -1
  24. package/dist/services/product/types.d.ts +0 -2
  25. package/dist/services/product/types.d.ts.map +1 -1
  26. package/dist/services/subscription/adapter.d.ts +2 -12
  27. package/dist/services/subscription/adapter.d.ts.map +1 -1
  28. package/dist/services/subscription/index.d.ts +1 -1
  29. package/dist/services/subscription/index.d.ts.map +1 -1
  30. package/dist/services/subscription/subscriptionService.d.ts +6 -1
  31. package/dist/services/subscription/subscriptionService.d.ts.map +1 -1
  32. package/dist/services/subscription/types.d.ts +16 -25
  33. package/dist/services/subscription/types.d.ts.map +1 -1
  34. package/dist/utils/editor.d.ts +18 -0
  35. package/dist/utils/editor.d.ts.map +1 -0
  36. package/dist/utils/editor.test.d.ts +2 -0
  37. package/dist/utils/editor.test.d.ts.map +1 -0
  38. package/dist/utils/index.d.ts +1 -6
  39. package/dist/utils/index.d.ts.map +1 -1
  40. package/dist/vue/block.d.ts +2 -2
  41. package/dist/vue/block.d.ts.map +1 -1
  42. package/dist/vue.js +3 -4
  43. package/dist/web-components-editor.js +2 -3
  44. package/dist/web-components-runtime.js +2 -3
  45. package/package.json +1 -1
  46. package/dist/block-WoHZvF51.js +0 -858
  47. package/dist/juo-workflow-DRauDEnU.js +0 -617
  48. package/dist/services/customer/adapter.d.ts +0 -8
  49. package/dist/services/customer/adapter.d.ts.map +0 -1
  50. package/dist/services/login/adapter.d.ts +0 -32
  51. package/dist/services/login/adapter.d.ts.map +0 -1
  52. package/dist/services/order/adapter.d.ts +0 -9
  53. package/dist/services/order/adapter.d.ts.map +0 -1
  54. package/dist/services/order/index.d.ts +0 -5
  55. package/dist/services/order/index.d.ts.map +0 -1
  56. package/dist/services/order/orderService.d.ts +0 -7
  57. package/dist/services/order/orderService.d.ts.map +0 -1
  58. package/dist/services/order/types.d.ts +0 -21
  59. package/dist/services/order/types.d.ts.map +0 -1
  60. package/dist/services/schedules/adapter.d.ts +0 -22
  61. package/dist/services/schedules/adapter.d.ts.map +0 -1
  62. package/dist/services/schedules/index.d.ts +0 -5
  63. package/dist/services/schedules/index.d.ts.map +0 -1
  64. package/dist/services/schedules/schedulesService.d.ts +0 -10
  65. package/dist/services/schedules/schedulesService.d.ts.map +0 -1
  66. package/dist/services/schedules/types.d.ts +0 -47
  67. package/dist/services/schedules/types.d.ts.map +0 -1
  68. 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 "./block-WoHZvF51.js";
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 "./block-WoHZvF51.js";
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
- return {
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
- (c3) => (c3 ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c3 / 4).toString(16)
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 loginService(deps) {
370
- const apiBase = deps.shop.rootUrl.replace(/\/$/, "") + "/api";
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(storage(STORAGE_DELEGATED_TOKEN));
392
- const refreshToken = d(storage(STORAGE_REFRESH_TOKEN_KEY));
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 storeTokens(data) {
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
- async function getToken() {
411
- if (refreshToken.value == null) return null;
412
- if (accessToken.value == null || typeof accessToken.value === "string" && (expires.value == null || expires.value < /* @__PURE__ */ new Date())) {
413
- accessToken.value = new Promise(
414
- (resolve, reject) => adapter.authenticate({ refreshToken: refreshToken.value }).then((result) => {
415
- if (result._tag === "Failure") {
416
- reject(result.error);
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
- storeTokens(result.data);
420
- resolve(result.data.access_token);
421
- }).catch(reject)
422
- );
423
- }
424
- return Promise.resolve(accessToken.value);
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({ path: decodeURIComponent(redirect), query: queryParams });
376
+ router.push({
377
+ path: decodeURIComponent(redirect),
378
+ query: queryParams
379
+ });
439
380
  } else {
440
- router.replace(decodeURIComponent(query.get(PARAMS.REDIRECT_TO)));
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
- const lang = shop.locale instanceof u ? shop.locale.value : shop.locale;
453
- const result = await adapter.passwordlessStart({
454
- email: userEmail.value,
455
- lang
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 { _tag: "Failure", error: formatError(error) };
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 adapter.authenticate({
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: void 0 };
419
+ return { _tag: "Success", data: result };
483
420
  } catch (error) {
484
- return { _tag: "Failure", error: formatError(error) };
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
- state.value = nonce();
492
- const connection = provider === "Facebook" ? "facebook" : "google-oauth2";
493
- window.location.href = adapter.getAuthorizeUrl({
494
- connection,
495
- state: state.value ?? "",
496
- shop: shop.domain,
497
- appUrl: (
498
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
499
- (typeof import.meta !== "undefined" ? __vite_import_meta_env__ == null ? void 0 : __vite_import_meta_env__.VITE_APP_URL : void 0) ?? "https://admin.juo.io"
500
- )
501
- });
502
- return { _tag: "Success", data: void 0 };
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 adapter.authenticate({ code });
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: void 0 };
455
+ return { _tag: "Success", data: result };
513
456
  } catch (error) {
514
- return { _tag: "Failure", error: formatError(error) };
457
+ return {
458
+ _tag: "Failure",
459
+ error: formatError(error)
460
+ };
515
461
  }
516
462
  }
517
463
  },
518
464
  async logout() {
519
- accessToken.value = null;
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
- delegatedToken.value = query.get(PARAMS.DELETGATED_TOKEN);
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 { _tag: "Failure", error: formatError("Invalid state") };
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: w(
563
- () => delegatedToken.value != null || refreshToken.value != null
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 = 2;
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
- return {
1295
- _tag: "Success",
1296
- data: {
1297
- items: pageItems.map((sub) => ({
1298
- ...sub,
1299
- items: sub.items.map((item) => ({ ...item })),
1300
- discounts: sub.discounts.map((discount) => ({ ...discount }))
1301
- })),
1302
- pageInfo: {
1303
- hasNextPage: endIndex < allItems.length,
1304
- hasPrevPage: startIndex > 0,
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 { _tag: "Failure", error: "Subscription not found" };
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
- return { _tag: "Success", data: { ...subscription } };
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 { _tag: "Failure", error: "Subscription not found" };
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 { _tag: "Success", data: { ...subscription } };
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 { _tag: "Failure", error: "Subscription not found" };
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 { _tag: "Success", data: { ...subscription } };
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 { _tag: "Failure", error: "Subscription not found" };
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 { _tag: "Success", data: { ...subscription } };
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 { _tag: "Failure", error: "Subscription not found" };
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 { _tag: "Success", data: { ...subscription } };
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
- async function refreshAfterDiscountChange(subscriptionId) {
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
- return {
1776
- current,
1777
- hasPendingBilling,
1778
- discountsChangedAt: discountsChangedAtSignal,
1779
- async search(options) {
1780
- const result = await adapter.search(options);
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
- current.value = result.data.items[0] ?? null;
1102
+ await refreshAfterItemChange(subscriptionId);
1783
1103
  }
1784
1104
  return result;
1785
1105
  },
1786
- async getById(id) {
1787
- const result = await adapter.getById(id);
1788
- if (result._tag === "Success" && result.data) {
1789
- current.value = result.data;
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
- getUpsellProducts: (params) => adapter.getUpsellProducts ? adapter.getUpsellProducts(params) : Promise.resolve({ _tag: "Success", data: [] }),
1835
- addUpsellProduct: (params) => adapter.addUpsellProduct ? adapter.addUpsellProduct(params) : Promise.resolve({ _tag: "Success", data: void 0 })
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
- T2 as TranslationContext,
1436
+ b as TranslationContext,
2119
1437
  W as WorkflowServiceContext,
2120
- b as attachEmptyTracking,
2121
- e as backfillInstanceDefaults,
1438
+ e as attachEmptyTracking,
1439
+ f as backfillInstanceDefaults,
2122
1440
  w as computed,
2123
- createApiCustomerAdapter,
2124
- createApiLoginAdapter,
2125
- createApiProductAdapter,
2126
- createApiSchedulesAdapter,
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
- createSchedulesService,
2147
- j as createSelectedBlock,
1455
+ k as createSelectedBlock,
2148
1456
  createState,
2149
1457
  createSubscriptionService,
2150
- c as createThemeState,
2151
- c2 as createTranslationService,
2152
- a2 as createWorkflowApiAdapter,
2153
- b2 as createWorkflowService,
2154
- k as defineBlock,
2155
- l as defineBlockRuntime,
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
- g2 as getDefaultBlockForAction,
2158
- m as getDefinedBlocks,
2159
- h2 as hasDefaultBlockForAction,
2160
- n as hasRenderedContent,
2161
- i2 as indexOverrides,
2162
- o as injectContext,
2163
- p as isStubDefinition,
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
- q as onRegisterBlock,
2167
- s as provideContext,
1475
+ G as onRegisterBlock,
1476
+ H as provideContext,
2168
1477
  registerBlock,
2169
- t as serializeBlocks,
1478
+ I as serializeBlocks,
2170
1479
  d as signal,
2171
- v as subscribeContext,
2172
- x as untracked,
1480
+ J as subscribeContext,
1481
+ K as untracked,
2173
1482
  waitForDevBlocksUrl,
2174
- y as withWrapper
1483
+ L as withWrapper
2175
1484
  };