@juo/blocks 1.12.0-alpha.2 → 1.12.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 (137) hide show
  1. package/dist/{ExtensionRoot-peABLAZZ.js → ExtensionRoot-9XfhG8YM.js} +3 -15
  2. package/dist/block.d.ts +0 -50
  3. package/dist/block.d.ts.map +1 -1
  4. package/dist/{bridge-r7Yk8fjY.js → bridge-w5KQ-czl.js} +25 -34
  5. package/dist/context.d.ts.map +1 -1
  6. package/dist/core.js +323 -1686
  7. package/dist/editor/bridge.d.ts +0 -7
  8. package/dist/editor/bridge.d.ts.map +1 -1
  9. package/dist/editor/components.d.ts.map +1 -1
  10. package/dist/editor/main.d.ts +1 -2
  11. package/dist/editor/main.d.ts.map +1 -1
  12. package/dist/editor/messages.d.ts +2 -13
  13. package/dist/editor/messages.d.ts.map +1 -1
  14. package/dist/editor.js +45 -64
  15. package/dist/{juo-workflow-DY4rd256.js → juo-workflow-CkyZRq60.js} +873 -74
  16. package/dist/main.d.ts +1 -3
  17. package/dist/main.d.ts.map +1 -1
  18. package/dist/preact.js +1 -1
  19. package/dist/react.js +1 -1
  20. package/dist/services/customer/customerService.d.ts +2 -3
  21. package/dist/services/customer/customerService.d.ts.map +1 -1
  22. package/dist/services/customer/index.d.ts +0 -1
  23. package/dist/services/customer/index.d.ts.map +1 -1
  24. package/dist/services/customer/types.d.ts +1 -4
  25. package/dist/services/customer/types.d.ts.map +1 -1
  26. package/dist/services/index.d.ts +0 -3
  27. package/dist/services/index.d.ts.map +1 -1
  28. package/dist/services/login/index.d.ts +1 -3
  29. package/dist/services/login/index.d.ts.map +1 -1
  30. package/dist/services/login/loginService.d.ts +2 -6
  31. package/dist/services/login/loginService.d.ts.map +1 -1
  32. package/dist/services/product/adapter.d.ts +2 -27
  33. package/dist/services/product/adapter.d.ts.map +1 -1
  34. package/dist/services/product/index.d.ts +1 -1
  35. package/dist/services/product/index.d.ts.map +1 -1
  36. package/dist/services/product/productService.d.ts.map +1 -1
  37. package/dist/services/product/types.d.ts +0 -68
  38. package/dist/services/product/types.d.ts.map +1 -1
  39. package/dist/services/subscription/adapter.d.ts +2 -49
  40. package/dist/services/subscription/adapter.d.ts.map +1 -1
  41. package/dist/services/subscription/index.d.ts +1 -1
  42. package/dist/services/subscription/index.d.ts.map +1 -1
  43. package/dist/services/subscription/subscriptionService.d.ts +6 -1
  44. package/dist/services/subscription/subscriptionService.d.ts.map +1 -1
  45. package/dist/services/subscription/types.d.ts +9 -216
  46. package/dist/services/subscription/types.d.ts.map +1 -1
  47. package/dist/theme-state.d.ts +1 -2
  48. package/dist/theme-state.d.ts.map +1 -1
  49. package/dist/utils/index.d.ts +0 -6
  50. package/dist/utils/index.d.ts.map +1 -1
  51. package/dist/vue/block.d.ts.map +1 -1
  52. package/dist/vue.js +4 -25
  53. package/dist/web-components/ExtensionRoot.d.ts +0 -1
  54. package/dist/web-components/ExtensionRoot.d.ts.map +1 -1
  55. package/dist/web-components-editor.js +3 -4
  56. package/dist/web-components-runtime.js +2 -3
  57. package/package.json +1 -5
  58. package/dist/block-B6s9jL7l.js +0 -966
  59. package/dist/block.devtools.test.d.ts +0 -2
  60. package/dist/block.devtools.test.d.ts.map +0 -1
  61. package/dist/context.devtools.test.d.ts +0 -2
  62. package/dist/context.devtools.test.d.ts.map +0 -1
  63. package/dist/devtools/env.d.ts +0 -3
  64. package/dist/devtools/env.d.ts.map +0 -1
  65. package/dist/devtools/hook.d.ts +0 -35
  66. package/dist/devtools/hook.d.ts.map +0 -1
  67. package/dist/devtools/index.d.ts +0 -4
  68. package/dist/devtools/index.d.ts.map +0 -1
  69. package/dist/devtools/protocol.d.ts +0 -91
  70. package/dist/devtools/protocol.d.ts.map +0 -1
  71. package/dist/devtools.js +0 -44
  72. package/dist/editor/messages.test.d.ts +0 -2
  73. package/dist/editor/messages.test.d.ts.map +0 -1
  74. package/dist/editor/overlays.d.ts +0 -14
  75. package/dist/editor/overlays.d.ts.map +0 -1
  76. package/dist/editor/overlays.test.d.ts +0 -2
  77. package/dist/editor/overlays.test.d.ts.map +0 -1
  78. package/dist/overlay-wrapper.d.ts +0 -69
  79. package/dist/overlay-wrapper.d.ts.map +0 -1
  80. package/dist/overlay-wrapper.test.d.ts +0 -2
  81. package/dist/overlay-wrapper.test.d.ts.map +0 -1
  82. package/dist/overlays/OverlayService.d.ts +0 -34
  83. package/dist/overlays/OverlayService.d.ts.map +0 -1
  84. package/dist/overlays/OverlayService.test.d.ts +0 -2
  85. package/dist/overlays/OverlayService.test.d.ts.map +0 -1
  86. package/dist/registry.devtools.test.d.ts +0 -2
  87. package/dist/registry.devtools.test.d.ts.map +0 -1
  88. package/dist/services/customer/adapter.d.ts +0 -8
  89. package/dist/services/customer/adapter.d.ts.map +0 -1
  90. package/dist/services/login/adapter.d.ts +0 -32
  91. package/dist/services/login/adapter.d.ts.map +0 -1
  92. package/dist/services/order/adapter.d.ts +0 -9
  93. package/dist/services/order/adapter.d.ts.map +0 -1
  94. package/dist/services/order/index.d.ts +0 -5
  95. package/dist/services/order/index.d.ts.map +0 -1
  96. package/dist/services/order/orderService.d.ts +0 -7
  97. package/dist/services/order/orderService.d.ts.map +0 -1
  98. package/dist/services/order/types.d.ts +0 -21
  99. package/dist/services/order/types.d.ts.map +0 -1
  100. package/dist/services/product/adapter.test.d.ts +0 -2
  101. package/dist/services/product/adapter.test.d.ts.map +0 -1
  102. package/dist/services/schedules/adapter.d.ts +0 -25
  103. package/dist/services/schedules/adapter.d.ts.map +0 -1
  104. package/dist/services/schedules/adapter.test.d.ts +0 -2
  105. package/dist/services/schedules/adapter.test.d.ts.map +0 -1
  106. package/dist/services/schedules/index.d.ts +0 -5
  107. package/dist/services/schedules/index.d.ts.map +0 -1
  108. package/dist/services/schedules/schedulesService.d.ts +0 -11
  109. package/dist/services/schedules/schedulesService.d.ts.map +0 -1
  110. package/dist/services/schedules/schedulesService.test.d.ts +0 -2
  111. package/dist/services/schedules/schedulesService.test.d.ts.map +0 -1
  112. package/dist/services/schedules/types.d.ts +0 -101
  113. package/dist/services/schedules/types.d.ts.map +0 -1
  114. package/dist/services/settings/index.d.ts +0 -3
  115. package/dist/services/settings/index.d.ts.map +0 -1
  116. package/dist/services/settings/settingsService.d.ts +0 -7
  117. package/dist/services/settings/settingsService.d.ts.map +0 -1
  118. package/dist/services/settings/settingsService.test.d.ts +0 -2
  119. package/dist/services/settings/settingsService.test.d.ts.map +0 -1
  120. package/dist/services/settings/types.d.ts +0 -35
  121. package/dist/services/settings/types.d.ts.map +0 -1
  122. package/dist/services/shop/index.d.ts +0 -3
  123. package/dist/services/shop/index.d.ts.map +0 -1
  124. package/dist/services/shop/shopService.d.ts +0 -12
  125. package/dist/services/shop/shopService.d.ts.map +0 -1
  126. package/dist/services/shop/shopService.test.d.ts +0 -2
  127. package/dist/services/shop/shopService.test.d.ts.map +0 -1
  128. package/dist/services/shop/types.d.ts +0 -7
  129. package/dist/services/shop/types.d.ts.map +0 -1
  130. package/dist/services/subscription/adapter.test.d.ts +0 -2
  131. package/dist/services/subscription/adapter.test.d.ts.map +0 -1
  132. package/dist/services/subscription/types.test.d.ts +0 -2
  133. package/dist/services/subscription/types.test.d.ts.map +0 -1
  134. package/dist/theme-state.params.test.d.ts +0 -2
  135. package/dist/theme-state.params.test.d.ts.map +0 -1
  136. package/dist/theme-state.translations.test.d.ts +0 -2
  137. package/dist/theme-state.translations.test.d.ts.map +0 -1
package/dist/core.js CHANGED
@@ -1,9 +1,8 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { e as createContext, d, k as w, l as defineBlock, g as createBlockInstance, h as getDefinedBlocks, r as registerBlock, E, u } from "./block-B6s9jL7l.js";
5
- import { B, m, p, S, q, _, t, b, v, f, x, y, z, A, D, i, F, a, o, G, j, H, s, n, w as w2 } from "./block-B6s9jL7l.js";
6
- import { D as D2, a as a2, T, W, c, b as b2, d as d2, e, g, h, i as i2 } from "./juo-workflow-DY4rd256.js";
4
+ import { c as createContext, d, w, r as registerBlock, E, u } from "./juo-workflow-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";
7
6
  import { reportBlockWarning, reportBlockError } from "./observability.js";
8
7
  function createState() {
9
8
  const discountCode = d(null);
@@ -73,111 +72,6 @@ function createState() {
73
72
  };
74
73
  }
75
74
  const StateContext = createContext("state");
76
- const OVERLAY_WRAPPER_SCHEMA = {
77
- type: "object",
78
- properties: {
79
- props: {
80
- type: "object",
81
- properties: {
82
- layout: {
83
- type: "string",
84
- enum: ["modal", "sidebar"]
85
- },
86
- canAbort: {
87
- type: "boolean"
88
- }
89
- },
90
- required: ["layout"],
91
- additionalProperties: false
92
- },
93
- slots: {
94
- type: "object",
95
- properties: {
96
- content: {}
97
- },
98
- additionalProperties: false
99
- }
100
- },
101
- required: ["props", "slots"],
102
- additionalProperties: false
103
- };
104
- function defineOverlayWrapper(opts) {
105
- const layout = opts.layout ?? "sidebar";
106
- const canAbort = opts.canAbort ?? true;
107
- return defineBlock(opts.name, {
108
- displayName: opts.title,
109
- group: "internal",
110
- schema: OVERLAY_WRAPPER_SCHEMA,
111
- initialValue: () => ({
112
- props: { layout, canAbort },
113
- slots: {
114
- content: [createBlockInstance(opts.content)]
115
- }
116
- }),
117
- renderer: () => null
118
- });
119
- }
120
- const OVERLAY_PREFIX$1 = "overlay:";
121
- function callInitialValue(block) {
122
- if (typeof block.initialValue !== "function") return block.initialValue;
123
- try {
124
- return block.initialValue();
125
- } catch (error) {
126
- console.warn(
127
- `[overlays] initialValue() threw for "${block.name}"; its content block will not be hidden from the palette.`,
128
- error
129
- );
130
- return void 0;
131
- }
132
- }
133
- function buildOverlayRegistry(blocks) {
134
- var _a, _b;
135
- const registry = {};
136
- for (const block of blocks) {
137
- if (!block.name.startsWith(OVERLAY_PREFIX$1)) continue;
138
- const id = block.name.slice(OVERLAY_PREFIX$1.length);
139
- const initial = callInitialValue(block);
140
- const first = (_b = (_a = initial == null ? void 0 : initial.slots) == null ? void 0 : _a.content) == null ? void 0 : _b[0];
141
- const contentBlock = typeof (first == null ? void 0 : first.type) === "string" ? first.type : "";
142
- registry[id] = {
143
- block: block.name,
144
- title: block.displayName ?? id,
145
- contentBlock
146
- };
147
- }
148
- return registry;
149
- }
150
- const OVERLAY_PREFIX = "overlay:";
151
- const OverlayServiceContext = createContext("services/overlay");
152
- function createOverlayService(themeState, options = {}) {
153
- const getBlocks = options.getBlocks ?? getDefinedBlocks;
154
- const current = w(() => {
155
- const root = themeState.overlay.blocks.value[0];
156
- const type = root == null ? void 0 : root.type;
157
- if (typeof type !== "string" || !type.startsWith(OVERLAY_PREFIX)) {
158
- return null;
159
- }
160
- const props = root.props ?? {};
161
- return {
162
- name: type,
163
- // Defaults mirror defineOverlayWrapper's seeding in overlay-wrapper.ts — keep in sync.
164
- layout: props.layout ?? "sidebar",
165
- canAbort: Boolean(props.canAbort ?? true)
166
- };
167
- });
168
- return {
169
- getEditableOverlays() {
170
- return buildOverlayRegistry(getBlocks());
171
- },
172
- open(name, params) {
173
- void themeState.resolve("overlay", name, params);
174
- },
175
- close() {
176
- themeState.overlay.blocks.value = [];
177
- },
178
- current
179
- };
180
- }
181
75
  function isLocalhostOrigin(origin) {
182
76
  try {
183
77
  const url = new URL(origin);
@@ -238,7 +132,7 @@ async function loadBlockRegistry(options = {}) {
238
132
  if ("registerBlocks" in module && typeof module.registerBlocks === "function") {
239
133
  module.registerBlocks();
240
134
  } else {
241
- Object.entries(module).forEach(([_2, item]) => {
135
+ Object.entries(module).forEach(([_, item]) => {
242
136
  if (typeof item === "object" && item != null) {
243
137
  registerBlock(item);
244
138
  }
@@ -262,43 +156,13 @@ async function loadBlockRegistry(options = {}) {
262
156
  function createCustomerService(options) {
263
157
  const current = d(null);
264
158
  const accountOrdersUrl = d(options.getAccountOrdersUrl());
265
- return {
159
+ const service = {
266
160
  current,
267
- accountOrdersUrl,
268
- async getCurrent() {
269
- const result = await options.adapter.getCurrent();
270
- if (result._tag === "Success") current.value = result.data;
271
- return result;
272
- }
161
+ accountOrdersUrl
273
162
  };
163
+ return service;
274
164
  }
275
165
  const CustomerServiceContext = createContext("services/customer");
276
- function createMockCustomerAdapter() {
277
- const customer = { id: "customer-1", name: "Customer 1" };
278
- return {
279
- async getCurrent() {
280
- return { _tag: "Success", data: customer };
281
- }
282
- };
283
- }
284
- function createApiCustomerAdapter(fetcher) {
285
- return {
286
- async getCurrent() {
287
- try {
288
- const res = await fetcher("/customer/info");
289
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
290
- const data = await res.json();
291
- const name = [data.firstName, data.lastName].filter(Boolean).join(" ") || data.email || "";
292
- return {
293
- _tag: "Success",
294
- data: { id: data.id, name, email: data.email }
295
- };
296
- } catch (e2) {
297
- return { _tag: "Failure", error: e2 };
298
- }
299
- }
300
- };
301
- }
302
166
  const PARAMS = {
303
167
  DELETGATED_TOKEN: "delegated-token",
304
168
  REDIRECT_TO: "redirect-to",
@@ -312,125 +176,9 @@ const PARAMS = {
312
176
  function uuid() {
313
177
  return ("10000000-1000-4000-8000" + -1e11).replace(
314
178
  /[018]/g,
315
- (c2) => (c2 ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c2 / 4).toString(16)
179
+ (c) => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
316
180
  );
317
181
  }
318
- function createMockLoginAdapter() {
319
- return {
320
- async passwordlessStart() {
321
- return { _tag: "Success", data: void 0 };
322
- },
323
- async authenticate() {
324
- return {
325
- _tag: "Success",
326
- data: {
327
- access_token: "mock-access-token",
328
- refresh_token: "mock-refresh-token",
329
- expires_in: 3600
330
- }
331
- };
332
- },
333
- getAuthorizeUrl({ connection, state, shop, appUrl }) {
334
- const url = new URL(`${appUrl}/auth/customer/authorize`);
335
- url.searchParams.set("connection", connection);
336
- url.searchParams.set("state", state);
337
- url.searchParams.set("shop", shop);
338
- return url.toString();
339
- }
340
- };
341
- }
342
- function createApiLoginAdapter(fetcher, opts) {
343
- const { shopDomain, appUrl } = opts;
344
- async function callAuthEndpoint(path, body, lang) {
345
- const url = lang ? `${path}?lang=${lang}` : path;
346
- const res = await fetcher(url, {
347
- method: "POST",
348
- headers: {
349
- Accept: "application/json",
350
- "Content-Type": "application/json",
351
- "X-Shopify-Shop-Domain": shopDomain
352
- },
353
- body: JSON.stringify(body)
354
- });
355
- if (res.status === 403) {
356
- const data = await res.json();
357
- if ("error_description" in data) {
358
- if (data.error_description === "Wrong email or verification code.") {
359
- throw new AuthenticationError(AuthenticationErrorReason.IncorrectCode);
360
- } else if (data.error_description === "You've reached the maximum number of attempts. Please try to login again.") {
361
- throw new AuthenticationError(AuthenticationErrorReason.TooManyTries);
362
- } else if (data.error_description === "The verification code has expired. Please try to login again.") {
363
- throw new AuthenticationError(AuthenticationErrorReason.Expired);
364
- }
365
- } else if ("code" in data && data.code === "AUTH_ERROR") {
366
- throw new AuthenticationError(AuthenticationErrorReason.NoEmail, {
367
- connection: data.connection
368
- });
369
- }
370
- }
371
- if (!res.ok) {
372
- throw new Error(`Unexpected response: ${res.statusText}`);
373
- }
374
- return { _tag: "Success", data: void 0 };
375
- }
376
- return {
377
- async passwordlessStart({ email, lang }) {
378
- try {
379
- await callAuthEndpoint(
380
- "/auth/customer/passwordless/start",
381
- { email },
382
- lang
383
- );
384
- return { _tag: "Success", data: void 0 };
385
- } catch (e2) {
386
- return { _tag: "Failure", error: e2 };
387
- }
388
- },
389
- async authenticate(params) {
390
- try {
391
- const res = await fetcher("/auth/customer/token", {
392
- method: "POST",
393
- headers: {
394
- Accept: "application/json",
395
- "Content-Type": "application/json",
396
- "X-Shopify-Shop-Domain": shopDomain
397
- },
398
- body: JSON.stringify(params)
399
- });
400
- if (res.status === 403) {
401
- const data = await res.json();
402
- if ("error_description" in data) {
403
- if (data.error_description === "Wrong email or verification code.") {
404
- throw new AuthenticationError(AuthenticationErrorReason.IncorrectCode);
405
- } else if (data.error_description === "You've reached the maximum number of attempts. Please try to login again.") {
406
- throw new AuthenticationError(AuthenticationErrorReason.TooManyTries);
407
- } else if (data.error_description === "The verification code has expired. Please try to login again.") {
408
- throw new AuthenticationError(AuthenticationErrorReason.Expired);
409
- }
410
- } else if ("code" in data && data.code === "AUTH_ERROR") {
411
- throw new AuthenticationError(AuthenticationErrorReason.NoEmail, {
412
- connection: data.connection
413
- });
414
- }
415
- }
416
- if (!res.ok) {
417
- throw new Error(`Unexpected response: ${res.statusText}`);
418
- }
419
- return { _tag: "Success", data: await res.json() };
420
- } catch (e2) {
421
- return { _tag: "Failure", error: e2 };
422
- }
423
- },
424
- getAuthorizeUrl({ connection, state, shop }) {
425
- const url = new URL(`${appUrl}/auth/customer/authorize`);
426
- url.searchParams.set("connection", connection);
427
- url.searchParams.set("state", state);
428
- url.searchParams.set("shop", shop);
429
- return url.toString();
430
- }
431
- };
432
- }
433
- const __vite_import_meta_env__ = {};
434
182
  var AuthenticationErrorReason = /* @__PURE__ */ ((AuthenticationErrorReason2) => {
435
183
  AuthenticationErrorReason2["Expired"] = "expired";
436
184
  AuthenticationErrorReason2["IncorrectCode"] = "wrong-code";
@@ -449,9 +197,6 @@ class AuthenticationError extends Error {
449
197
  this.data = data ?? {};
450
198
  }
451
199
  }
452
- const STORAGE_DELEGATED_TOKEN = "delegated-token";
453
- const STORAGE_REFRESH_TOKEN_KEY = "refresh-token";
454
- const STORAGE_STATE_KEY = "state";
455
200
  function storage(key, value) {
456
201
  const storageKey = `auth:${key}`;
457
202
  try {
@@ -467,33 +212,83 @@ function storage(key, value) {
467
212
  }
468
213
  return null;
469
214
  }
215
+ const STORAGE_DELEGATED_TOKEN = "delegated-token";
216
+ const STORAGE_REFRESH_TOKEN_KEY = "refresh-token";
217
+ const STORAGE_STATE_KEY = "state";
218
+ function createAuthFunctions(basePath, shop) {
219
+ async function start(email, lang) {
220
+ const response = await fetch(
221
+ `${basePath}/auth/customer/passwordless/start?lang=${lang}`,
222
+ {
223
+ method: "POST",
224
+ headers: {
225
+ Accept: "application/json",
226
+ "Content-Type": "application/json",
227
+ "X-Shopify-Shop-Domain": shop
228
+ },
229
+ body: JSON.stringify({ email })
230
+ }
231
+ );
232
+ if (response.status !== 200) {
233
+ throw new Error(`Unexpected response: ${response.statusText}`);
234
+ }
235
+ }
236
+ async function authenticate(data) {
237
+ const response = await fetch(`${basePath}/auth/customer/token`, {
238
+ method: "POST",
239
+ headers: {
240
+ Accept: "application/json",
241
+ "Content-Type": "application/json",
242
+ "X-Shopify-Shop-Domain": shop
243
+ },
244
+ body: JSON.stringify(data)
245
+ });
246
+ if (response.status === 403) {
247
+ const data2 = await response.json();
248
+ if ("error_description" in data2) {
249
+ if (data2.error_description === "Wrong email or verification code.") {
250
+ throw new AuthenticationError(
251
+ "wrong-code"
252
+ /* IncorrectCode */
253
+ );
254
+ } else if (data2.error_description === "You've reached the maximum number of attempts. Please try to login again.") {
255
+ throw new AuthenticationError(
256
+ "too-many-tries"
257
+ /* TooManyTries */
258
+ );
259
+ } else if (data2.error_description === "The verification code has expired. Please try to login again.") {
260
+ throw new AuthenticationError(
261
+ "expired"
262
+ /* Expired */
263
+ );
264
+ }
265
+ } else if ("code" in data2) {
266
+ if (data2.code === "AUTH_ERROR") {
267
+ throw new AuthenticationError("no-email", {
268
+ connection: data2.connection
269
+ });
270
+ }
271
+ }
272
+ }
273
+ if (response.status !== 200) {
274
+ throw new Error(`Unexpected response: ${response.statusText}`);
275
+ }
276
+ return await response.json();
277
+ }
278
+ return { start, authenticate };
279
+ }
470
280
  function nonce(len = 10) {
471
281
  return uuid().replace(/-/g, "").slice(0, len);
472
282
  }
473
- function loginService(deps) {
474
- const apiBase = deps.shop.rootUrl.replace(/\/$/, "") + "/api";
475
- const appUrl = (typeof import.meta !== "undefined" ? __vite_import_meta_env__ == null ? void 0 : __vite_import_meta_env__.VITE_APP_URL : void 0) ?? "https://admin.juo.io";
476
- const fetcher = (path, init) => fetch(`${apiBase}${path}`, init);
477
- const adapter = createApiLoginAdapter(fetcher, {
478
- shopDomain: deps.shop.domain,
479
- appUrl
480
- });
481
- return createLoginService({
482
- adapter,
483
- router: deps.router,
484
- formatError: deps.formatError,
485
- shop: {
486
- domain: deps.shop.domain,
487
- locale: w(() => deps.getLocale())
488
- },
489
- onLoginSuccess: deps.onLoginSuccess
490
- });
491
- }
492
- function createLoginService(init) {
493
- const { adapter, formatError, router, shop, onLoginSuccess } = init;
283
+ function createAuthService(apiUrl, shopDomain) {
284
+ const { start: authStart, authenticate: authAuthenticate } = createAuthFunctions(apiUrl, shopDomain);
494
285
  const accessToken = d(null);
495
- const delegatedToken = d(storage(STORAGE_DELEGATED_TOKEN));
496
- 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
+ );
497
292
  const expires = d(null);
498
293
  const state = d(storage(STORAGE_STATE_KEY));
499
294
  E(() => {
@@ -505,28 +300,67 @@ function createLoginService(init) {
505
300
  E(() => {
506
301
  storage(STORAGE_STATE_KEY, state.value);
507
302
  });
508
- function storeTokens(data) {
303
+ function store(data) {
509
304
  const { access_token, refresh_token, expires_in } = data;
510
305
  accessToken.value = access_token;
511
306
  refreshToken.value = refresh_token;
512
307
  expires.value = new Date(Date.now() + expires_in);
513
308
  }
514
- async function getToken() {
515
- if (refreshToken.value == null) return null;
516
- if (accessToken.value == null || typeof accessToken.value === "string" && (expires.value == null || expires.value < /* @__PURE__ */ new Date())) {
517
- accessToken.value = new Promise(
518
- (resolve, reject) => adapter.authenticate({ refreshToken: refreshToken.value }).then((result) => {
519
- if (result._tag === "Failure") {
520
- 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);
521
332
  return;
522
- }
523
- storeTokens(result.data);
524
- resolve(result.data.access_token);
525
- }).catch(reject)
526
- );
527
- }
528
- return Promise.resolve(accessToken.value);
529
- }
333
+ }).catch(reject)
334
+ );
335
+ }
336
+ return Promise.resolve(accessToken.value);
337
+ },
338
+ logout() {
339
+ accessToken.value = null;
340
+ delegatedToken.value = null;
341
+ refreshToken.value = null;
342
+ expires.value = null;
343
+ },
344
+ isAuthenticated: w(
345
+ () => delegatedToken.value != null || refreshToken.value != null
346
+ )
347
+ };
348
+ }
349
+ function loginService(deps) {
350
+ return createLoginService({
351
+ apiUrl: `${deps.shop.rootUrl.replace(/\/$/, "")}/api`,
352
+ router: deps.router,
353
+ formatError: deps.formatError,
354
+ shop: {
355
+ domain: deps.shop.domain,
356
+ locale: w(() => deps.getLocale())
357
+ },
358
+ onLoginSuccess: deps.onLoginSuccess
359
+ });
360
+ }
361
+ function createLoginService(init) {
362
+ const { formatError, router, shop, onLoginSuccess } = init;
363
+ const auth = createAuthService(init.apiUrl.replace(/\/$/, ""), shop.domain);
530
364
  const userEmail = d(null);
531
365
  async function onSuccess(query) {
532
366
  await (onLoginSuccess == null ? void 0 : onLoginSuccess());
@@ -539,9 +373,13 @@ function createLoginService(init) {
539
373
  queryParams[key] = value;
540
374
  }
541
375
  });
542
- router.push({ path: decodeURIComponent(redirect), query: queryParams });
376
+ router.push({
377
+ path: decodeURIComponent(redirect),
378
+ query: queryParams
379
+ });
543
380
  } else {
544
- router.replace(decodeURIComponent(query.get(PARAMS.REDIRECT_TO)));
381
+ const redirect = query.get(PARAMS.REDIRECT_TO);
382
+ router.replace(decodeURIComponent(redirect));
545
383
  }
546
384
  } else {
547
385
  router.replace("/");
@@ -553,17 +391,16 @@ function createLoginService(init) {
553
391
  async start(email) {
554
392
  try {
555
393
  userEmail.value = email;
556
- const lang = shop.locale instanceof u ? shop.locale.value : shop.locale;
557
- const result = await adapter.passwordlessStart({
558
- email: userEmail.value,
559
- lang
560
- });
561
- if (result._tag === "Failure") {
562
- return { _tag: "Failure", error: formatError(result.error) };
563
- }
394
+ await auth.start(
395
+ userEmail.value,
396
+ shop.locale instanceof u ? shop.locale.value : shop.locale
397
+ );
564
398
  return { _tag: "Success", data: void 0 };
565
399
  } catch (error) {
566
- return { _tag: "Failure", error: formatError(error) };
400
+ return {
401
+ _tag: "Failure",
402
+ error: formatError(error)
403
+ };
567
404
  }
568
405
  },
569
406
  async verify(email, code) {
@@ -574,61 +411,63 @@ function createLoginService(init) {
574
411
  };
575
412
  }
576
413
  try {
577
- const result = await adapter.authenticate({
414
+ const result = await auth.authenticate({
578
415
  email: userEmail.value,
579
416
  code
580
417
  });
581
- if (result._tag === "Failure") {
582
- return { _tag: "Failure", error: formatError(result.error) };
583
- }
584
- storeTokens(result.data);
585
418
  await onSuccess();
586
- return { _tag: "Success", data: void 0 };
419
+ return { _tag: "Success", data: result };
587
420
  } catch (error) {
588
- return { _tag: "Failure", error: formatError(error) };
421
+ return {
422
+ _tag: "Failure",
423
+ error: formatError(error)
424
+ };
589
425
  }
590
426
  }
591
427
  }
592
428
  },
593
429
  social: {
594
430
  async start(provider) {
595
- state.value = nonce();
596
- const connection = provider === "Facebook" ? "facebook" : "google-oauth2";
597
- window.location.href = adapter.getAuthorizeUrl({
598
- connection,
599
- state: state.value ?? "",
600
- shop: shop.domain,
601
- appUrl: (
602
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
603
- (typeof import.meta !== "undefined" ? __vite_import_meta_env__ == null ? void 0 : __vite_import_meta_env__.VITE_APP_URL : void 0) ?? "https://admin.juo.io"
604
- )
605
- });
606
- 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
+ };
607
450
  },
608
451
  async verify(code) {
609
452
  try {
610
- const result = await adapter.authenticate({ code });
611
- if (result._tag === "Failure") {
612
- return { _tag: "Failure", error: formatError(result.error) };
613
- }
614
- storeTokens(result.data);
453
+ const result = await auth.authenticate({ code });
615
454
  await onSuccess();
616
- return { _tag: "Success", data: void 0 };
455
+ return { _tag: "Success", data: result };
617
456
  } catch (error) {
618
- return { _tag: "Failure", error: formatError(error) };
457
+ return {
458
+ _tag: "Failure",
459
+ error: formatError(error)
460
+ };
619
461
  }
620
462
  }
621
463
  },
622
464
  async logout() {
623
- accessToken.value = null;
624
- delegatedToken.value = null;
625
- refreshToken.value = null;
626
- expires.value = null;
465
+ await auth.logout();
627
466
  return { _tag: "Success", data: void 0 };
628
467
  },
629
468
  async handleQueryParams(query) {
630
469
  if (query.has(PARAMS.DELETGATED_TOKEN)) {
631
- delegatedToken.value = query.get(PARAMS.DELETGATED_TOKEN);
470
+ auth.setDelegatedToken(query.get(PARAMS.DELETGATED_TOKEN));
632
471
  await onSuccess(query);
633
472
  return { _tag: "Success", data: void 0 };
634
473
  }
@@ -640,13 +479,16 @@ function createLoginService(init) {
640
479
  }
641
480
  const code = query.get(PARAMS.CODE);
642
481
  if (code != null) {
643
- if (query.get(PARAMS.STATE) !== state.value) {
644
- return { _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
+ };
645
487
  } else {
646
488
  return service.social.verify(code);
647
489
  }
648
490
  }
649
- if (query.get(PARAMS.REFRESH) === "1" && await getToken() != null) {
491
+ if (query.get(PARAMS.REFRESH) === "1" && await auth.getToken() != null) {
650
492
  await onSuccess();
651
493
  return { _tag: "Success", data: void 0 };
652
494
  }
@@ -663,20 +505,8 @@ function createLoginService(init) {
663
505
  }
664
506
  return { _tag: "Success", data: void 0 };
665
507
  },
666
- isAuthenticated: w(
667
- () => delegatedToken.value != null || refreshToken.value != null
668
- ),
669
- getToken,
670
- async getAuthHeaders() {
671
- if (delegatedToken.value) {
672
- return { "X-Delegated-Token": delegatedToken.value };
673
- }
674
- const token = await getToken();
675
- if (token) {
676
- return { Authorization: `Bearer ${token}` };
677
- }
678
- return {};
679
- }
508
+ isAuthenticated: auth.isAuthenticated,
509
+ getToken: () => auth.getToken()
680
510
  };
681
511
  return service;
682
512
  }
@@ -895,18 +725,6 @@ function createMockProductAdapter() {
895
725
  );
896
726
  return product == null ? null : processProduct(product);
897
727
  },
898
- async getProductsByIds() {
899
- return [];
900
- },
901
- async getBoxVariants() {
902
- return [];
903
- },
904
- async getAvailableProducts() {
905
- return [];
906
- },
907
- async getBox() {
908
- return null;
909
- },
910
728
  async search(opts) {
911
729
  await new Promise((resolve) => setTimeout(resolve, 100));
912
730
  let filteredProducts = [...products];
@@ -947,185 +765,6 @@ function createMockProductAdapter() {
947
765
  }
948
766
  };
949
767
  }
950
- function mapVariant(variant, currencyCode) {
951
- var _a;
952
- return {
953
- id: variant.id,
954
- title: variant.title,
955
- image: variant.image == null ? null : { url: variant.image.url, altText: variant.image.altText ?? void 0 },
956
- price: { amount: variant.price.toFixed(2), currencyCode },
957
- ...((_a = variant.purchaseOptions) == null ? void 0 : _a.length) ? {
958
- purchaseOptions: variant.purchaseOptions.map((opt) => ({
959
- name: opt.name,
960
- price: { amount: opt.price.toFixed(2), currencyCode },
961
- interval: opt.interval
962
- }))
963
- } : {}
964
- };
965
- }
966
- function mapProduct(product, currencyCode) {
967
- return {
968
- id: product.id,
969
- title: product.title,
970
- featuredImage: product.image == null ? null : { url: product.image.url, altText: product.image.altText ?? void 0 },
971
- hasOnlyDefaultVariant: product.variants.length <= 1,
972
- variants: {
973
- items: product.variants.map((v2) => mapVariant(v2, currencyCode)),
974
- pageInfo: {
975
- hasNextPage: false,
976
- hasPrevPage: false,
977
- startCursor: null,
978
- endCursor: null
979
- }
980
- },
981
- collections: product.collections
982
- };
983
- }
984
- function createApiProductAdapter(fetcher, opts = { currencyCode: "USD" }) {
985
- const { currencyCode } = opts;
986
- async function fetchProducts(params) {
987
- const query = params.toString() ? `?${params.toString()}` : "";
988
- const res = await fetcher(`/customer/v1/products${query}`);
989
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
990
- return res.json();
991
- }
992
- return {
993
- async getById(id) {
994
- try {
995
- const params = new URLSearchParams({ query: `id:"${id}"`, limit: "1" });
996
- const body = await fetchProducts(params);
997
- return body.data.length > 0 ? mapProduct(body.data[0], currencyCode) : null;
998
- } catch {
999
- return null;
1000
- }
1001
- },
1002
- async getByVariantId(variantId) {
1003
- try {
1004
- const params = new URLSearchParams({
1005
- query: `variants.id:"${variantId}"`,
1006
- limit: "1"
1007
- });
1008
- const body = await fetchProducts(params);
1009
- return body.data.length > 0 ? mapProduct(body.data[0], currencyCode) : null;
1010
- } catch {
1011
- return null;
1012
- }
1013
- },
1014
- async search(opts2) {
1015
- try {
1016
- const params = new URLSearchParams();
1017
- if (opts2 == null ? void 0 : opts2.query) {
1018
- params.set("query", `"${opts2.query.trim().replace(/"/g, '\\"')}"`);
1019
- }
1020
- if (opts2 == null ? void 0 : opts2.pagination) {
1021
- if ("after" in opts2.pagination)
1022
- params.set("after", opts2.pagination.after);
1023
- else if ("before" in opts2.pagination)
1024
- params.set("before", opts2.pagination.before);
1025
- }
1026
- const body = await fetchProducts(params);
1027
- return {
1028
- items: body.data.map((p2) => mapProduct(p2, currencyCode)),
1029
- pageInfo: {
1030
- hasNextPage: body.hasNextPage,
1031
- hasPrevPage: body.hasPrevPage,
1032
- startCursor: body.startCursor,
1033
- endCursor: body.endCursor
1034
- }
1035
- };
1036
- } catch {
1037
- return {
1038
- items: [],
1039
- pageInfo: {
1040
- hasNextPage: false,
1041
- hasPrevPage: false,
1042
- startCursor: null,
1043
- endCursor: null
1044
- }
1045
- };
1046
- }
1047
- },
1048
- async getProductsByIds({ ids }) {
1049
- const params = new URLSearchParams();
1050
- for (const id of ids) params.append("ids", id);
1051
- const res = await fetcher(`/customer/products/by-ids?${params.toString()}`);
1052
- if (!res.ok) return [];
1053
- const data = await res.json();
1054
- return (data ?? []).map((p2) => ({
1055
- id: p2.id,
1056
- title: p2.title ?? "",
1057
- featuredImage: p2.featuredImage ? { url: p2.featuredImage.url, altText: p2.featuredImage.altText } : null,
1058
- hasOnlyDefaultVariant: true,
1059
- collections: []
1060
- }));
1061
- },
1062
- async getBoxVariants({ ids, subscriptionId }) {
1063
- const params = new URLSearchParams();
1064
- for (const id of ids) params.append("ids", id);
1065
- params.set("subscriptionId", subscriptionId);
1066
- const res = await fetcher(`/customer/products/variants?${params.toString()}`);
1067
- if (!res.ok) return [];
1068
- const data = await res.json();
1069
- return (data ?? []).map((p2) => {
1070
- var _a;
1071
- return {
1072
- id: p2.id,
1073
- title: p2.title,
1074
- description: p2.description ?? "",
1075
- featuredImage: p2.featuredImage,
1076
- hasOnlyDefaultVariant: p2.hasOnlyDefaultVariant ?? (((_a = p2.variants) == null ? void 0 : _a.length) ?? 0) <= 1,
1077
- variants: (p2.variants ?? []).map((v2) => ({
1078
- id: v2.id,
1079
- availableForSale: v2.availableForSale,
1080
- title: v2.title,
1081
- currentPrice: v2.currentPrice,
1082
- basePrice: v2.basePrice,
1083
- image: v2.image,
1084
- recurring: v2.recurring
1085
- }))
1086
- };
1087
- });
1088
- },
1089
- async getAvailableProducts({ subscriptionId, lineId, q: q2, mode, action, pagination }) {
1090
- const params = new URLSearchParams();
1091
- params.set("action", action);
1092
- if (q2) params.set("q", q2);
1093
- if (mode) params.set("mode", mode);
1094
- if (pagination && "after" in pagination) params.set("after", pagination.after);
1095
- if (pagination && "before" in pagination) params.set("before", pagination.before);
1096
- const res = await fetcher(
1097
- `/customer/subscriptions/${subscriptionId}/lines/${lineId}/available-products?${params.toString()}`
1098
- );
1099
- if (!res.ok) return [];
1100
- const data = await res.json();
1101
- return (data ?? []).map((p2) => {
1102
- var _a;
1103
- return {
1104
- id: p2.id,
1105
- title: p2.title,
1106
- description: p2.description ?? "",
1107
- featuredImage: p2.featuredImage,
1108
- hasOnlyDefaultVariant: p2.hasOnlyDefaultVariant ?? (((_a = p2.variants) == null ? void 0 : _a.length) ?? 0) <= 1,
1109
- variants: (p2.variants ?? []).map((v2) => ({
1110
- id: v2.id,
1111
- availableForSale: v2.availableForSale,
1112
- title: v2.title,
1113
- currentPrice: v2.currentPrice,
1114
- basePrice: v2.basePrice,
1115
- image: v2.image,
1116
- recurring: v2.recurring
1117
- }))
1118
- };
1119
- });
1120
- },
1121
- async getBox({ id }) {
1122
- const res = await fetcher(`/customer/boxes/${id}`);
1123
- if (!res.ok) return null;
1124
- const data = await res.json();
1125
- return { id, ...data };
1126
- }
1127
- };
1128
- }
1129
768
  const ProductServiceContext = createContext("services/product");
1130
769
  function createProductService(adapter) {
1131
770
  return {
@@ -1137,11 +776,7 @@ function createProductService(adapter) {
1137
776
  },
1138
777
  async search(opts) {
1139
778
  return adapter.search(opts);
1140
- },
1141
- getProductsByIds: (ids) => adapter.getProductsByIds({ ids }),
1142
- getBoxVariants: (ids, subscriptionId) => adapter.getBoxVariants({ ids, subscriptionId }),
1143
- getAvailableProducts: (params) => adapter.getAvailableProducts(params),
1144
- getBox: (id) => adapter.getBox({ id })
779
+ }
1145
780
  };
1146
781
  }
1147
782
  function routeNameTableFromPages(pages) {
@@ -1195,407 +830,10 @@ function createMockRouterService() {
1195
830
  }
1196
831
  }).routerService;
1197
832
  }
1198
- function futureDateStr(daysFromNow) {
1199
- const d3 = /* @__PURE__ */ new Date();
1200
- d3.setDate(d3.getDate() + daysFromNow);
1201
- return d3.toISOString().split("T")[0] ?? "";
1202
- }
1203
- function createMockSchedulesAdapter() {
1204
- let orders = [
833
+ function createMockSubscriptionAdapter(options = {}) {
834
+ const mockSubscriptions = [
1205
835
  {
1206
- id: "sched_1",
1207
- customerId: "customer_1",
1208
- subscriptionId: "sub_1",
1209
- date: "2026-05-22T12:00:00Z",
1210
- skipped: false,
1211
- currencyCode: "USD",
1212
- subtotal: 2999,
1213
- deliveryPrice: 500,
1214
- cycleIndex: 4,
1215
- deliveryDate: futureDateStr(7),
1216
- status: "scheduled",
1217
- items: [
1218
- {
1219
- id: "sched_item_1",
1220
- title: "Rose Face Serum",
1221
- subtitle: null,
1222
- imageUrl: "https://images.unsplash.com/photo-1611930022073-b7a4ba5fcccd?w=200",
1223
- variantId: "variant_1",
1224
- quantity: 1,
1225
- price: 2999,
1226
- totalPrice: 2999,
1227
- variantImage: null,
1228
- variantAvailableForSale: true,
1229
- subscriptionId: "sub_1",
1230
- subscriptionLineId: "item_1",
1231
- productId: "product_1",
1232
- parentProductId: null,
1233
- parentLineId: null,
1234
- isVirtual: false,
1235
- isUpsell: false,
1236
- isOneTime: false,
1237
- customAttributes: []
1238
- },
1239
- {
1240
- id: "sched_item_2",
1241
- title: "Vitamin C Moisturizer",
1242
- subtitle: null,
1243
- imageUrl: "https://images.unsplash.com/photo-1556228578-8c89e6adf883?w=200",
1244
- variantId: "variant_2",
1245
- quantity: 1,
1246
- price: 2999,
1247
- totalPrice: 2999,
1248
- variantImage: null,
1249
- variantAvailableForSale: true,
1250
- subscriptionId: "sub_1",
1251
- subscriptionLineId: "item_2",
1252
- productId: "product_2",
1253
- parentProductId: null,
1254
- parentLineId: null,
1255
- isVirtual: false,
1256
- isUpsell: false,
1257
- isOneTime: false,
1258
- customAttributes: []
1259
- }
1260
- ],
1261
- discounts: []
1262
- },
1263
- {
1264
- id: "sched_2",
1265
- customerId: "customer_1",
1266
- subscriptionId: "sub_1",
1267
- date: "2026-05-22T12:00:00Z",
1268
- skipped: false,
1269
- currencyCode: "USD",
1270
- subtotal: 2999,
1271
- deliveryPrice: 500,
1272
- cycleIndex: 4,
1273
- deliveryDate: futureDateStr(7),
1274
- status: "scheduled",
1275
- items: [
1276
- {
1277
- id: "sched_item_3",
1278
- title: "Rose Face Serum",
1279
- subtitle: null,
1280
- imageUrl: "https://images.unsplash.com/photo-1611930022073-b7a4ba5fcccd?w=200",
1281
- variantId: "variant_1",
1282
- quantity: 1,
1283
- price: 2999,
1284
- totalPrice: 2999,
1285
- variantImage: null,
1286
- variantAvailableForSale: true,
1287
- subscriptionId: "sub_1",
1288
- subscriptionLineId: "item_1",
1289
- productId: "product_1",
1290
- parentProductId: null,
1291
- parentLineId: null,
1292
- isVirtual: false,
1293
- isUpsell: false,
1294
- isOneTime: false,
1295
- customAttributes: []
1296
- },
1297
- {
1298
- id: "sched_item_4",
1299
- title: "Hyaluronic Acid Serum",
1300
- subtitle: null,
1301
- imageUrl: "https://images.unsplash.com/photo-1621232201696-ba6c9db10a97?w=200",
1302
- variantId: "variant_3",
1303
- quantity: 1,
1304
- price: 2999,
1305
- totalPrice: 2999,
1306
- variantImage: null,
1307
- variantAvailableForSale: true,
1308
- subscriptionId: "sub_1",
1309
- subscriptionLineId: "item_3",
1310
- productId: "product_3",
1311
- parentProductId: null,
1312
- parentLineId: null,
1313
- isVirtual: false,
1314
- isUpsell: false,
1315
- isOneTime: false,
1316
- customAttributes: []
1317
- }
1318
- ],
1319
- discounts: []
1320
- }
1321
- ];
1322
- let adjustments = [];
1323
- return {
1324
- async getUpcomingOrders(params) {
1325
- await new Promise((r) => setTimeout(r, 200));
1326
- const filtered = params.subscriptionId ? orders.filter((o2) => o2.subscriptionId === params.subscriptionId) : orders;
1327
- return { _tag: "Success", data: filtered.slice(0, params.count) };
1328
- },
1329
- async getAdjustments() {
1330
- await new Promise((r) => setTimeout(r, 200));
1331
- return { _tag: "Success", data: [...adjustments] };
1332
- },
1333
- async skipOrder({ subscriptionId }) {
1334
- await new Promise((r) => setTimeout(r, 300));
1335
- const order = orders.find(
1336
- (o2) => o2.subscriptionId === subscriptionId && o2.status === "scheduled"
1337
- );
1338
- if (!order) return { _tag: "Failure", error: "No scheduled order found" };
1339
- orders = orders.map(
1340
- (o2) => o2.id === order.id ? { ...o2, status: "skipped" } : o2
1341
- );
1342
- const adj = {
1343
- id: `adj-${Date.now()}`,
1344
- subscriptionId,
1345
- type: "skip"
1346
- };
1347
- adjustments = [...adjustments, adj];
1348
- return { _tag: "Success", data: void 0 };
1349
- },
1350
- async changeDateAdjustment({ subscriptionId, newDate }) {
1351
- await new Promise((r) => setTimeout(r, 300));
1352
- const order = orders.find(
1353
- (o2) => o2.subscriptionId === subscriptionId && o2.status === "scheduled"
1354
- );
1355
- if (!order) return { _tag: "Failure", error: "No scheduled order found" };
1356
- orders = orders.map(
1357
- (o2) => o2.id === order.id ? { ...o2, deliveryDate: newDate } : o2
1358
- );
1359
- const adj = {
1360
- id: `adj-${Date.now()}`,
1361
- subscriptionId,
1362
- type: "date_change",
1363
- newDate
1364
- };
1365
- adjustments = [...adjustments, adj];
1366
- return { _tag: "Success", data: void 0 };
1367
- },
1368
- async removeAdjustment({ adjustmentId }) {
1369
- await new Promise((r) => setTimeout(r, 200));
1370
- adjustments = adjustments.filter((a3) => a3.id !== adjustmentId);
1371
- return { _tag: "Success", data: void 0 };
1372
- }
1373
- };
1374
- }
1375
- function createApiSchedulesAdapter(fetcher) {
1376
- return {
1377
- async getUpcomingOrders({ count, subscriptionId }) {
1378
- try {
1379
- const params = new URLSearchParams({ count: String(count) });
1380
- if (subscriptionId) params.set("query", `id:"${subscriptionId}"`);
1381
- const res = await fetcher(`/customer/v1/schedules/?${params.toString()}`);
1382
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1383
- const data = await res.json();
1384
- return { _tag: "Success", data: data.orders };
1385
- } catch (e2) {
1386
- return { _tag: "Failure", error: e2 };
1387
- }
1388
- },
1389
- async getAdjustments() {
1390
- try {
1391
- const res = await fetcher(`/customer/v1/schedules/adjustments`);
1392
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1393
- const data = await res.json();
1394
- const adjustments = data.data.map((a3) => ({
1395
- id: a3.id,
1396
- subscriptionId: a3.subscriptionId ?? "",
1397
- type: a3.type === "CHANGE_DATE" ? "date_change" : "skip",
1398
- newDate: a3.newDate
1399
- }));
1400
- return { _tag: "Success", data: adjustments };
1401
- } catch (e2) {
1402
- return { _tag: "Failure", error: e2 };
1403
- }
1404
- },
1405
- async skipOrder({ cycle, date }) {
1406
- if (cycle == null && date == null) {
1407
- return { _tag: "Failure", error: "Either cycle or date is required for skipOrder" };
1408
- }
1409
- try {
1410
- const matcher = cycle != null ? { type: "CYCLE", input: { cycle } } : { type: "DATE", input: { date: new Date(date).toISOString() } };
1411
- const res = await fetcher(`/customer/v1/schedules/adjustments`, {
1412
- method: "POST",
1413
- headers: { "Content-Type": "application/json" },
1414
- body: JSON.stringify({
1415
- matcher,
1416
- action: { type: "SKIP_ORDER", input: { reason: "" } }
1417
- })
1418
- });
1419
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1420
- return { _tag: "Success", data: void 0 };
1421
- } catch (e2) {
1422
- return { _tag: "Failure", error: e2 };
1423
- }
1424
- },
1425
- async changeDateAdjustment({ newDate, currentDate }) {
1426
- if (currentDate == null) {
1427
- return {
1428
- _tag: "Failure",
1429
- error: "currentDate is required for changeDateAdjustment"
1430
- };
1431
- }
1432
- try {
1433
- const matcher = { type: "DATE", input: { date: new Date(currentDate).toISOString() } };
1434
- const res = await fetcher(`/customer/v1/schedules/adjustments`, {
1435
- method: "POST",
1436
- headers: { "Content-Type": "application/json" },
1437
- body: JSON.stringify({
1438
- matcher,
1439
- action: {
1440
- type: "CHANGE_DATE",
1441
- input: { newDate: new Date(newDate).toISOString() }
1442
- }
1443
- })
1444
- });
1445
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1446
- return { _tag: "Success", data: void 0 };
1447
- } catch (e2) {
1448
- return { _tag: "Failure", error: e2 };
1449
- }
1450
- },
1451
- async removeAdjustment({ adjustmentId }) {
1452
- try {
1453
- const res = await fetcher(
1454
- `/customer/v1/schedules/adjustments/${adjustmentId}`,
1455
- { method: "DELETE" }
1456
- );
1457
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
1458
- return { _tag: "Success", data: void 0 };
1459
- } catch (e2) {
1460
- return { _tag: "Failure", error: e2 };
1461
- }
1462
- }
1463
- };
1464
- }
1465
- const SchedulesServiceContext = createContext("services/schedules");
1466
- function createSchedulesService(adapter, opts) {
1467
- const current = d(null);
1468
- const currentLoading = d(false);
1469
- const hasPendingBilling = (opts == null ? void 0 : opts.hasPendingBilling) ?? d(false);
1470
- let reloadToken = 0;
1471
- async function getUpcomingOrder() {
1472
- const result = await adapter.getUpcomingOrders({ count: 1 });
1473
- if (result._tag === "Failure") return result;
1474
- return { _tag: "Success", data: result.data[0] ?? null };
1475
- }
1476
- async function getUpcomingOrders(count) {
1477
- return adapter.getUpcomingOrders({ count });
1478
- }
1479
- async function reloadCurrent(subscriptionId) {
1480
- var _a;
1481
- const token = ++reloadToken;
1482
- currentLoading.value = true;
1483
- const count = Math.max(((_a = current.value) == null ? void 0 : _a.length) ?? 0, 3);
1484
- const result = await adapter.getUpcomingOrders({
1485
- count,
1486
- subscriptionId
1487
- });
1488
- if (token !== reloadToken) return;
1489
- currentLoading.value = false;
1490
- if (result._tag === "Success") {
1491
- current.value = result.data;
1492
- }
1493
- }
1494
- return {
1495
- current,
1496
- currentLoading,
1497
- hasPendingBilling,
1498
- getUpcomingOrder,
1499
- getUpcomingOrders,
1500
- async getAdjustments() {
1501
- return adapter.getAdjustments();
1502
- },
1503
- async skipOrder(params) {
1504
- const result = await adapter.skipOrder(params);
1505
- if (result._tag === "Success") {
1506
- await reloadCurrent(params.subscriptionId);
1507
- }
1508
- return result;
1509
- },
1510
- async changeDateAdjustment(params) {
1511
- const result = await adapter.changeDateAdjustment(params);
1512
- if (result._tag === "Success") {
1513
- await reloadCurrent(params.subscriptionId);
1514
- }
1515
- return result;
1516
- },
1517
- async removeAdjustment(params) {
1518
- return adapter.removeAdjustment(params);
1519
- },
1520
- reloadCurrent
1521
- };
1522
- }
1523
- const SettingsServiceContext = createContext("services/settings");
1524
- function createSettingsService(initial = {}) {
1525
- const current = d(initial);
1526
- return {
1527
- current,
1528
- get(key) {
1529
- return current.value[key];
1530
- }
1531
- };
1532
- }
1533
- function createShopService(options) {
1534
- const contactEmail = d(options.getContactEmail());
1535
- const service = { contactEmail };
1536
- return service;
1537
- }
1538
- const ShopServiceContext = createContext("services/shop");
1539
- function createMockSubscriptionAdapter(options = {}) {
1540
- const richBase = (id, itemId, renewalId) => ({
1541
- id,
1542
- customerId: "customer_1",
1543
- items: [
1544
- {
1545
- id: itemId,
1546
- productId: "product_1",
1547
- variantId: "variant_1",
1548
- quantity: 2,
1549
- price: { amount: "29.99", currencyCode: "USD" },
1550
- nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
1551
- isUpsell: false,
1552
- isVirtual: false,
1553
- nextBillingDate: "2025-11-15T00:00:00Z",
1554
- currentPrice: { amount: "29.99", currencyCode: "USD" },
1555
- lineDiscountedPrice: { amount: "26.99", currencyCode: "USD" },
1556
- variantAvailableForSale: true
1557
- }
1558
- ],
1559
- discounts: [
1560
- {
1561
- id: "discount_1",
1562
- type: "percentage",
1563
- value: 10,
1564
- code: "SAVE10",
1565
- description: "10% off subscription"
1566
- }
1567
- ],
1568
- status: "active",
1569
- nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
1570
- frequency: "1 MONTH",
1571
- createdAt: "2024-10-01T00:00:00Z",
1572
- updatedAt: "2024-10-14T00:00:00Z",
1573
- billingPolicy: { intervalCount: 1, interval: "MONTH", minCycles: 6 },
1574
- deliveryPolicy: {
1575
- intervalCount: 1,
1576
- interval: "MONTH",
1577
- anchors: [{ day: 15, type: "MONTHDAY" }]
1578
- },
1579
- nextBillingDate: "2025-11-15T00:00:00Z",
1580
- nextBillingAttempt: { date: "2025-11-15T00:00:00Z", attempt: 1, ready: true },
1581
- lastBillingAttempt: { date: "2025-10-15T00:00:00Z", ready: true },
1582
- nextFulfillment: "2025-11-17T00:00:00Z",
1583
- estimatedOrderDate: "2025-11-13T00:00:00Z",
1584
- customerPaymentMethod: {
1585
- id: "pm_1",
1586
- instrument: { type: "credit_card", brand: "visa", maskedNumber: "************4242" },
1587
- active: true,
1588
- isRecurring: true
1589
- },
1590
- requiredBillingCyclesLeft: 3,
1591
- renewal: { id: renewalId, isInActiveProcessState: false },
1592
- lastPaymentStatus: "succeeded",
1593
- pausePeriod: null,
1594
- isEditable: true
1595
- });
1596
- const mockSubscriptions = [
1597
- {
1598
- id: "sub_1",
836
+ id: "sub_1",
1599
837
  customerId: "customer_1",
1600
838
  items: [
1601
839
  {
@@ -1605,14 +843,6 @@ function createMockSubscriptionAdapter(options = {}) {
1605
843
  quantity: 2,
1606
844
  price: { amount: "29.99", currencyCode: "USD" },
1607
845
  nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
1608
- isUpsell: false,
1609
- isVirtual: false,
1610
- nextBillingDate: "2025-11-15T00:00:00Z",
1611
- currentPrice: { amount: "29.99", currencyCode: "USD" },
1612
- lineDiscountedPrice: { amount: "26.99", currencyCode: "USD" },
1613
- variantAvailableForSale: true,
1614
- billingPolicy: { intervalCount: 1, interval: "MONTH" },
1615
- deliveryPolicy: { intervalCount: 1, interval: "MONTH" },
1616
846
  customAttributes: [
1617
847
  { key: "roast_level", value: "medium" },
1618
848
  { key: "grind_type", value: "whole_bean" }
@@ -1633,28 +863,6 @@ function createMockSubscriptionAdapter(options = {}) {
1633
863
  frequency: "1 MONTH",
1634
864
  createdAt: "2024-10-01T00:00:00Z",
1635
865
  updatedAt: "2024-10-14T00:00:00Z",
1636
- billingPolicy: { intervalCount: 1, interval: "MONTH", minCycles: 6 },
1637
- deliveryPolicy: {
1638
- intervalCount: 1,
1639
- interval: "MONTH",
1640
- anchors: [{ day: 15, type: "MONTHDAY" }]
1641
- },
1642
- nextBillingDate: "2025-11-15T00:00:00Z",
1643
- nextBillingAttempt: { date: "2025-11-15T00:00:00Z", attempt: 1, ready: true },
1644
- lastBillingAttempt: { date: "2025-10-15T00:00:00Z", ready: true },
1645
- nextFulfillment: "2025-11-17T00:00:00Z",
1646
- estimatedOrderDate: "2025-11-13T00:00:00Z",
1647
- customerPaymentMethod: {
1648
- id: "pm_1",
1649
- instrument: { type: "credit_card", brand: "visa", maskedNumber: "************4242" },
1650
- active: true,
1651
- isRecurring: true
1652
- },
1653
- requiredBillingCyclesLeft: 3,
1654
- renewal: { id: "ren_1", isInActiveProcessState: false },
1655
- lastPaymentStatus: "succeeded",
1656
- pausePeriod: null,
1657
- isEditable: true,
1658
866
  customAttributes: [
1659
867
  { key: "subscription_tier", value: "premium" },
1660
868
  { key: "gift_message", value: "Enjoy your coffee!" }
@@ -1671,8 +879,6 @@ function createMockSubscriptionAdapter(options = {}) {
1671
879
  quantity: 1,
1672
880
  price: { amount: "49.99", currencyCode: "USD" },
1673
881
  nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-20"),
1674
- billingPolicy: { intervalCount: 2, interval: "WEEK" },
1675
- deliveryPolicy: { intervalCount: 2, interval: "WEEK" },
1676
882
  customAttributes: []
1677
883
  }
1678
884
  ],
@@ -1683,48 +889,6 @@ function createMockSubscriptionAdapter(options = {}) {
1683
889
  createdAt: "2024-09-15T00:00:00Z",
1684
890
  updatedAt: "2024-10-10T00:00:00Z",
1685
891
  customAttributes: []
1686
- },
1687
- // Per-status fixtures: groundwork for the deferred editor preview picker
1688
- // (docs/superpowers/specs/2026-06-17-renewalsummary-parity-and-mock-groundwork-design.md §9).
1689
- // Not consumed yet — the editor still seeds the active sub_1 via getDefaultSubscriptionId().
1690
- {
1691
- ...richBase("sub_paused", "item_paused", "ren_paused"),
1692
- status: "paused",
1693
- pausePeriod: { start: "2025-11-01T00:00:00Z", end: "2026-01-01T00:00:00Z" }
1694
- },
1695
- {
1696
- ...richBase("sub_canceled", "item_canceled", "ren_canceled"),
1697
- status: "canceled",
1698
- pausePeriod: null
1699
- },
1700
- {
1701
- ...richBase("sub_failed", "item_failed", "ren_failed"),
1702
- status: "failed",
1703
- lastPaymentStatus: "failed",
1704
- pausePeriod: null
1705
- },
1706
- {
1707
- ...richBase("sub_expired", "item_expired", "ren_expired"),
1708
- status: "expired",
1709
- pausePeriod: null
1710
- }
1711
- ];
1712
- const mockUpsellProducts = [
1713
- {
1714
- id: "upsell-1",
1715
- variantId: "upsell-v-1",
1716
- title: "Retinol Night Cream",
1717
- imageUrl: "https://images.unsplash.com/photo-1617897903246-719242758050?w=200",
1718
- price: { amount: "38.00", currencyCode: "USD" },
1719
- description: "Anti-aging night treatment"
1720
- },
1721
- {
1722
- id: "upsell-2",
1723
- variantId: "upsell-v-2",
1724
- title: "SPF 50 Day Shield",
1725
- imageUrl: "https://images.unsplash.com/photo-1556228578-8c89e6adf883?w=200",
1726
- price: { amount: "24.00", currencyCode: "USD" },
1727
- description: "Lightweight daily sun protection"
1728
892
  }
1729
893
  ];
1730
894
  return {
@@ -1735,7 +899,7 @@ function createMockSubscriptionAdapter(options = {}) {
1735
899
  },
1736
900
  async search(options2 = {}) {
1737
901
  await new Promise((resolve) => setTimeout(resolve, 300));
1738
- const pageSize = 2;
902
+ const pageSize = 1;
1739
903
  const allItems = mockSubscriptions;
1740
904
  let startIndex = 0;
1741
905
  let endIndex = pageSize;
@@ -1751,22 +915,20 @@ function createMockSubscriptionAdapter(options = {}) {
1751
915
  }
1752
916
  }
1753
917
  const pageItems = allItems.slice(startIndex, endIndex);
1754
- return {
1755
- _tag: "Success",
1756
- data: {
1757
- items: pageItems.map((sub) => ({
1758
- ...sub,
1759
- items: sub.items.map((item) => ({ ...item })),
1760
- discounts: sub.discounts.map((discount) => ({ ...discount }))
1761
- })),
1762
- pageInfo: {
1763
- hasNextPage: endIndex < allItems.length,
1764
- hasPrevPage: startIndex > 0,
1765
- startCursor: pageItems.length > 0 ? startIndex.toString() : null,
1766
- endCursor: pageItems.length > 0 ? (endIndex - 1).toString() : null
1767
- }
918
+ const paginatedList = {
919
+ items: pageItems.map((sub) => ({
920
+ ...sub,
921
+ items: sub.items.map((item) => ({ ...item })),
922
+ discounts: sub.discounts.map((discount) => ({ ...discount }))
923
+ })),
924
+ pageInfo: {
925
+ hasNextPage: endIndex < allItems.length,
926
+ hasPrevPage: startIndex > 0,
927
+ startCursor: pageItems.length > 0 ? startIndex.toString() : null,
928
+ endCursor: pageItems.length > 0 ? (endIndex - 1).toString() : null
1768
929
  }
1769
930
  };
931
+ return { _tag: "Success", data: paginatedList };
1770
932
  },
1771
933
  async addItem() {
1772
934
  await new Promise((resolve) => setTimeout(resolve, 300));
@@ -1776,17 +938,6 @@ function createMockSubscriptionAdapter(options = {}) {
1776
938
  await new Promise((resolve) => setTimeout(resolve, 300));
1777
939
  return { _tag: "Success", data: void 0 };
1778
940
  },
1779
- async updateItem() {
1780
- await new Promise((resolve) => setTimeout(resolve, 300));
1781
- return { _tag: "Success", data: void 0 };
1782
- },
1783
- async skipLineItem() {
1784
- await new Promise((resolve) => setTimeout(resolve, 300));
1785
- return { _tag: "Success", data: void 0 };
1786
- },
1787
- async updateBoxItems() {
1788
- return { _tag: "Success", data: void 0 };
1789
- },
1790
941
  async addDiscount() {
1791
942
  await new Promise((resolve) => setTimeout(resolve, 300));
1792
943
  const behavior = options.addDiscountBehavior ?? { kind: "success" };
@@ -1815,11 +966,24 @@ function createMockSubscriptionAdapter(options = {}) {
1815
966
  (sub) => sub.id === params.subscriptionId
1816
967
  );
1817
968
  if (!subscription) {
1818
- return { _tag: "Failure", error: "Subscription not found" };
969
+ return {
970
+ _tag: "Failure",
971
+ error: "Subscription not found"
972
+ };
1819
973
  }
1820
974
  subscription.nextDeliveryDate = new Date(params.newDate);
1821
975
  subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1822
- return { _tag: "Success", data: { ...subscription } };
976
+ subscription.items.forEach((item) => {
977
+ item.nextDeliveryDate = new Date(params.newDate);
978
+ });
979
+ return {
980
+ _tag: "Success",
981
+ data: {
982
+ ...subscription,
983
+ items: subscription.items.map((item) => ({ ...item })),
984
+ discounts: subscription.discounts.map((discount) => ({ ...discount }))
985
+ }
986
+ };
1823
987
  },
1824
988
  async resume(params) {
1825
989
  await new Promise((resolve) => setTimeout(resolve, 300));
@@ -1827,11 +991,21 @@ function createMockSubscriptionAdapter(options = {}) {
1827
991
  (sub) => sub.id === params.subscriptionId
1828
992
  );
1829
993
  if (!subscription) {
1830
- return { _tag: "Failure", error: "Subscription not found" };
994
+ return {
995
+ _tag: "Failure",
996
+ error: "Subscription not found"
997
+ };
1831
998
  }
1832
999
  subscription.status = "active";
1833
1000
  subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1834
- return { _tag: "Success", data: { ...subscription } };
1001
+ return {
1002
+ _tag: "Success",
1003
+ data: {
1004
+ ...subscription,
1005
+ items: subscription.items.map((item) => ({ ...item })),
1006
+ discounts: subscription.discounts.map((discount) => ({ ...discount }))
1007
+ }
1008
+ };
1835
1009
  },
1836
1010
  async pause(params) {
1837
1011
  await new Promise((resolve) => setTimeout(resolve, 300));
@@ -1839,11 +1013,21 @@ function createMockSubscriptionAdapter(options = {}) {
1839
1013
  (sub) => sub.id === params.subscriptionId
1840
1014
  );
1841
1015
  if (!subscription) {
1842
- return { _tag: "Failure", error: "Subscription not found" };
1016
+ return {
1017
+ _tag: "Failure",
1018
+ error: "Subscription not found"
1019
+ };
1843
1020
  }
1844
1021
  subscription.status = "paused";
1845
1022
  subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1846
- return { _tag: "Success", data: { ...subscription } };
1023
+ return {
1024
+ _tag: "Success",
1025
+ data: {
1026
+ ...subscription,
1027
+ items: subscription.items.map((item) => ({ ...item })),
1028
+ discounts: subscription.discounts.map((discount) => ({ ...discount }))
1029
+ }
1030
+ };
1847
1031
  },
1848
1032
  async reactivate(params) {
1849
1033
  await new Promise((resolve) => setTimeout(resolve, 300));
@@ -1851,11 +1035,21 @@ function createMockSubscriptionAdapter(options = {}) {
1851
1035
  (sub) => sub.id === params.subscriptionId
1852
1036
  );
1853
1037
  if (!subscription) {
1854
- return { _tag: "Failure", error: "Subscription not found" };
1038
+ return {
1039
+ _tag: "Failure",
1040
+ error: "Subscription not found"
1041
+ };
1855
1042
  }
1856
1043
  subscription.status = "active";
1857
1044
  subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1858
- return { _tag: "Success", data: { ...subscription } };
1045
+ return {
1046
+ _tag: "Success",
1047
+ data: {
1048
+ ...subscription,
1049
+ items: subscription.items.map((item) => ({ ...item })),
1050
+ discounts: subscription.discounts.map((discount) => ({ ...discount }))
1051
+ }
1052
+ };
1859
1053
  },
1860
1054
  async cancel(params) {
1861
1055
  await new Promise((resolve) => setTimeout(resolve, 300));
@@ -1863,11 +1057,21 @@ function createMockSubscriptionAdapter(options = {}) {
1863
1057
  (sub) => sub.id === params.subscriptionId
1864
1058
  );
1865
1059
  if (!subscription) {
1866
- return { _tag: "Failure", error: "Subscription not found" };
1060
+ return {
1061
+ _tag: "Failure",
1062
+ error: "Subscription not found"
1063
+ };
1867
1064
  }
1868
1065
  subscription.status = "canceled";
1869
1066
  subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1870
- return { _tag: "Success", data: { ...subscription } };
1067
+ return {
1068
+ _tag: "Success",
1069
+ data: {
1070
+ ...subscription,
1071
+ items: subscription.items.map((item) => ({ ...item })),
1072
+ discounts: subscription.discounts.map((discount) => ({ ...discount }))
1073
+ }
1074
+ };
1871
1075
  },
1872
1076
  async getAvailablePlans() {
1873
1077
  await new Promise((resolve) => setTimeout(resolve, 300));
@@ -1895,514 +1099,13 @@ function createMockSubscriptionAdapter(options = {}) {
1895
1099
  ]
1896
1100
  };
1897
1101
  },
1898
- async getLastOrder(params) {
1899
- await new Promise((resolve) => setTimeout(resolve, 200));
1900
- const subscription = mockSubscriptions.find((sub) => sub.id === params.subscriptionId);
1901
- if (!subscription) return { _tag: "Success", data: null };
1902
- return {
1903
- _tag: "Success",
1904
- data: {
1905
- id: `mock_last_order_${params.subscriptionId}`,
1906
- createdAt: "2026-04-22T12:00:00Z"
1907
- }
1908
- };
1909
- },
1910
- async renewNow(_params) {
1911
- await new Promise((resolve) => setTimeout(resolve, 300));
1912
- return { _tag: "Success", data: { result: "success" } };
1913
- },
1914
- async changeFrequency(params) {
1915
- await new Promise((resolve) => setTimeout(resolve, 300));
1916
- const subscription = mockSubscriptions.find((sub) => sub.id === params.subscriptionId);
1917
- if (!subscription) {
1918
- return { _tag: "Failure", error: "Subscription not found" };
1919
- }
1920
- if (typeof params.plan === "string") {
1921
- subscription.frequency = `1 ${params.plan}`;
1922
- } else {
1923
- subscription.frequency = `${params.plan.intervalCount} ${params.plan.interval}`;
1924
- if (subscription.billingPolicy) {
1925
- subscription.billingPolicy = { ...subscription.billingPolicy, ...params.plan };
1926
- }
1927
- if (subscription.deliveryPolicy) {
1928
- subscription.deliveryPolicy = { ...subscription.deliveryPolicy, ...params.plan };
1929
- }
1930
- }
1931
- subscription.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
1932
- return {
1933
- _tag: "Success",
1934
- data: {
1935
- ...subscription,
1936
- items: subscription.items.map((item) => ({ ...item })),
1937
- discounts: subscription.discounts.map((d3) => ({ ...d3 }))
1938
- }
1939
- };
1940
- },
1941
1102
  async getDefaultSubscriptionId() {
1942
1103
  var _a;
1943
1104
  await new Promise((resolve) => setTimeout(resolve, 300));
1944
1105
  return { _tag: "Success", data: ((_a = mockSubscriptions[0]) == null ? void 0 : _a.id) ?? null };
1945
- },
1946
- async getUpsellProducts() {
1947
- await new Promise((resolve) => setTimeout(resolve, 300));
1948
- return { _tag: "Success", data: [...mockUpsellProducts] };
1949
- },
1950
- async addUpsellProduct() {
1951
- await new Promise((resolve) => setTimeout(resolve, 400));
1952
- return { _tag: "Success", data: void 0 };
1953
1106
  }
1954
1107
  };
1955
1108
  }
1956
- function normalizeInstrumentType(type) {
1957
- return type.replace(/-/g, "_");
1958
- }
1959
- function mapPaymentMethod(rawPm) {
1960
- if (!rawPm) return null;
1961
- if (typeof rawPm === "string") {
1962
- return { id: rawPm };
1963
- }
1964
- return {
1965
- id: rawPm.id ?? "",
1966
- ...rawPm.instrument != null ? {
1967
- instrument: {
1968
- ...rawPm.instrument,
1969
- type: normalizeInstrumentType(rawPm.instrument.type)
1970
- }
1971
- } : {},
1972
- ...rawPm.active != null ? { active: rawPm.active } : {},
1973
- ...rawPm.isRecurring != null ? { isRecurring: rawPm.isRecurring } : {}
1974
- };
1975
- }
1976
- function mapSubscription(raw) {
1977
- var _a, _b;
1978
- const status = raw.status === "merged" ? "canceled" : raw.status;
1979
- const deliveryPolicy = raw.deliveryPolicy ?? ((_b = (_a = raw.items) == null ? void 0 : _a[0]) == null ? void 0 : _b.deliveryPolicy);
1980
- const frequency = deliveryPolicy ? `${deliveryPolicy.intervalCount} ${deliveryPolicy.interval}` : "";
1981
- return {
1982
- id: raw.id,
1983
- customerId: "",
1984
- serial: raw.serial,
1985
- items: (raw.items ?? []).map(
1986
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1987
- (item) => ({
1988
- id: item.id,
1989
- productId: item.productId ?? item.product ?? "",
1990
- variantId: item.variantId ?? item.variant ?? "",
1991
- quantity: item.quantity,
1992
- price: item.price ?? {
1993
- amount: String(item.totalPrice ?? 0),
1994
- currencyCode: raw.currencyCode ?? ""
1995
- },
1996
- nextDeliveryDate: item.nextDeliveryDate ? new Date(item.nextDeliveryDate) : null,
1997
- billingPolicy: item.billingPolicy ?? raw.billingPolicy ?? null,
1998
- deliveryPolicy: item.deliveryPolicy ?? raw.deliveryPolicy ?? null,
1999
- // Map human-readable titles from the v1 SubscriptionItemResource
2000
- title: item.title,
2001
- variantTitle: item.subtitle ?? void 0,
2002
- // recurringCycleLimit === 1 means the item charges exactly once (one-time upsell)
2003
- isOneTime: item.recurringCycleLimit === 1
2004
- })
2005
- ),
2006
- discounts: (raw.discounts ?? []).map(
2007
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2008
- (d3) => {
2009
- var _a2, _b2, _c;
2010
- return {
2011
- id: d3.id,
2012
- type: ((_a2 = d3.value) == null ? void 0 : _a2.type) === "fixed-amount" || d3.type === "fixed_amount" ? "fixed_amount" : "percentage",
2013
- value: ((_b2 = d3.value) == null ? void 0 : _b2.amount) ?? ((_c = d3.value) == null ? void 0 : _c.percentage) ?? d3.value ?? 0,
2014
- code: d3.title ?? d3.code ?? "",
2015
- description: d3.description ?? ""
2016
- };
2017
- }
2018
- ),
2019
- status,
2020
- nextDeliveryDate: raw.nextBillingDate ? new Date(raw.nextBillingDate) : raw.nextDeliveryDate ? new Date(raw.nextDeliveryDate) : null,
2021
- // Map nextBillingDate as the raw ISO string for ProductSelect skip() and other consumers
2022
- nextBillingDate: raw.nextBillingDate ?? null,
2023
- // Map customerPaymentMethod — note: arrives as bare id (not expanded) since the
2024
- // subscriptions endpoint does not support ?expand=paymentMethod; instrument digits
2025
- // remain a data gap pending backend API extension.
2026
- customerPaymentMethod: mapPaymentMethod(raw.paymentMethod),
2027
- frequency,
2028
- createdAt: raw.createdAt,
2029
- updatedAt: raw.updatedAt,
2030
- billingPolicy: raw.billingPolicy ?? null,
2031
- deliveryPolicy: raw.deliveryPolicy ?? null
2032
- };
2033
- }
2034
- function createApiSubscriptionAdapter(fetcher) {
2035
- const adapter = {
2036
- async search(options) {
2037
- var _a;
2038
- try {
2039
- const params = new URLSearchParams();
2040
- if ((_a = options == null ? void 0 : options.filters) == null ? void 0 : _a.length) {
2041
- const q2 = options.filters.filter((f2) => Object.keys(f2).length > 0).flatMap((f2) => Object.entries(f2).filter(([, v2]) => Boolean(v2))).map(([k, v2]) => `${k}:'${v2}'`).join(" AND ");
2042
- if (q2) params.set("query", q2);
2043
- }
2044
- if (options == null ? void 0 : options.pagination) {
2045
- if ("after" in options.pagination)
2046
- params.set("after", options.pagination.after);
2047
- else if ("before" in options.pagination)
2048
- params.set("before", options.pagination.before);
2049
- }
2050
- const query = params.toString() ? `?${params.toString()}` : "";
2051
- const res = await fetcher(`/customer/v1/subscriptions${query}`);
2052
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2053
- const body = await res.json();
2054
- return {
2055
- _tag: "Success",
2056
- data: {
2057
- items: body.data.map(mapSubscription),
2058
- pageInfo: {
2059
- hasNextPage: body.hasNextPage,
2060
- hasPrevPage: body.hasPrevPage,
2061
- startCursor: body.startCursor,
2062
- endCursor: body.endCursor
2063
- }
2064
- }
2065
- };
2066
- } catch (e2) {
2067
- return { _tag: "Failure", error: e2 };
2068
- }
2069
- },
2070
- async getById(id) {
2071
- try {
2072
- const res = await fetcher(
2073
- `/customer/v1/subscriptions?query=id:"${id}"&limit=1`
2074
- );
2075
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2076
- const body = await res.json();
2077
- const raw = body.data[0];
2078
- return { _tag: "Success", data: raw ? mapSubscription(raw) : null };
2079
- } catch (e2) {
2080
- return { _tag: "Failure", error: e2 };
2081
- }
2082
- },
2083
- async addItem({ subscriptionId, item }) {
2084
- try {
2085
- const res = await fetcher(
2086
- `/customer/v1/subscriptions/${subscriptionId}/items`,
2087
- {
2088
- method: "POST",
2089
- headers: { "Content-Type": "application/json" },
2090
- body: JSON.stringify(item)
2091
- }
2092
- );
2093
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2094
- return { _tag: "Success", data: void 0 };
2095
- } catch (e2) {
2096
- return { _tag: "Failure", error: e2 };
2097
- }
2098
- },
2099
- async removeItem({ subscriptionId, itemId }) {
2100
- try {
2101
- const res = await fetcher(
2102
- `/customer/v1/subscriptions/${subscriptionId}/items/${itemId}`,
2103
- { method: "DELETE" }
2104
- );
2105
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2106
- return { _tag: "Success", data: void 0 };
2107
- } catch (e2) {
2108
- return { _tag: "Failure", error: e2 };
2109
- }
2110
- },
2111
- async updateItem({ subscriptionId, lineId, update }) {
2112
- try {
2113
- const body = {
2114
- ...update.variantId !== void 0 ? { productVariantId: update.variantId } : {},
2115
- ...update.quantity !== void 0 ? { quantity: update.quantity } : {},
2116
- ...update.billingPolicy !== void 0 ? { billingPolicy: update.billingPolicy } : {},
2117
- ...update.shippingMethodHandle !== void 0 ? { shippingMethodHandle: update.shippingMethodHandle } : {}
2118
- };
2119
- const res = await fetcher(
2120
- `/customer/subscriptions/${subscriptionId}/lines/${lineId}`,
2121
- {
2122
- method: "PUT",
2123
- headers: { "Content-Type": "application/json" },
2124
- body: JSON.stringify(body)
2125
- }
2126
- );
2127
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2128
- return { _tag: "Success", data: void 0 };
2129
- } catch (e2) {
2130
- return { _tag: "Failure", error: e2 };
2131
- }
2132
- },
2133
- async skipLineItem({ subscriptionId, lineId, nextBillingDate }) {
2134
- try {
2135
- const res = await fetcher(
2136
- `/customer/subscriptions/${subscriptionId}/lines/${lineId}`,
2137
- {
2138
- method: "PUT",
2139
- headers: { "Content-Type": "application/json" },
2140
- body: JSON.stringify({ nextBillingDate })
2141
- }
2142
- );
2143
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2144
- return { _tag: "Success", data: void 0 };
2145
- } catch (e2) {
2146
- return { _tag: "Failure", error: e2 };
2147
- }
2148
- },
2149
- async updateBoxItems({ subscriptionId, parentId, items, shippingMethodHandle }) {
2150
- try {
2151
- const res = await fetcher(
2152
- `/customer/subscriptions/${subscriptionId}/update-box-products`,
2153
- {
2154
- method: "POST",
2155
- headers: { "Content-Type": "application/json" },
2156
- body: JSON.stringify({ parentId, items, shippingMethodHandle })
2157
- }
2158
- );
2159
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2160
- return { _tag: "Success", data: void 0 };
2161
- } catch (e2) {
2162
- return { _tag: "Failure", error: e2 };
2163
- }
2164
- },
2165
- async addDiscount({ subscriptionId, code }) {
2166
- try {
2167
- const res = await fetcher(
2168
- `/customer/v1/subscriptions/${subscriptionId}/discounts`,
2169
- {
2170
- method: "POST",
2171
- headers: { "Content-Type": "application/json" },
2172
- body: JSON.stringify({ code })
2173
- }
2174
- );
2175
- if (!res.ok) return { _tag: "Failure", error: { kind: "NETWORK", message: `HTTP ${res.status}` } };
2176
- return { _tag: "Success", data: void 0 };
2177
- } catch (e2) {
2178
- return { _tag: "Failure", error: { kind: "UNKNOWN", message: e2 instanceof Error ? e2.message : void 0 } };
2179
- }
2180
- },
2181
- async removeDiscount({ subscriptionId, discountId }) {
2182
- try {
2183
- const res = await fetcher(
2184
- `/customer/v1/subscriptions/${subscriptionId}/discounts/${discountId}`,
2185
- { method: "DELETE" }
2186
- );
2187
- if (!res.ok) return { _tag: "Failure", error: { kind: "NETWORK", message: `HTTP ${res.status}` } };
2188
- return { _tag: "Success", data: void 0 };
2189
- } catch (e2) {
2190
- return { _tag: "Failure", error: { kind: "UNKNOWN", message: e2 instanceof Error ? e2.message : void 0 } };
2191
- }
2192
- },
2193
- // Uses PATCH /customer/v1/subscriptions/{id} — the dedicated /reschedule route does not exist.
2194
- async reschedule({ subscriptionId, newDate }) {
2195
- try {
2196
- const res = await fetcher(
2197
- `/customer/v1/subscriptions/${subscriptionId}`,
2198
- {
2199
- method: "PATCH",
2200
- headers: { "Content-Type": "application/json" },
2201
- body: JSON.stringify({ nextBillingDate: newDate })
2202
- }
2203
- );
2204
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2205
- const data = await res.json();
2206
- return { _tag: "Success", data: mapSubscription(data) };
2207
- } catch (e2) {
2208
- return { _tag: "Failure", error: e2 };
2209
- }
2210
- },
2211
- async resume({ subscriptionId }) {
2212
- try {
2213
- const res = await fetcher(
2214
- `/customer/v1/subscriptions/${subscriptionId}/resume`,
2215
- { method: "POST" }
2216
- );
2217
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2218
- const data = await res.json();
2219
- return { _tag: "Success", data: mapSubscription(data) };
2220
- } catch (e2) {
2221
- return { _tag: "Failure", error: e2 };
2222
- }
2223
- },
2224
- async pause({ subscriptionId }) {
2225
- try {
2226
- const res = await fetcher(
2227
- `/customer/v1/subscriptions/${subscriptionId}/pause`,
2228
- { method: "POST" }
2229
- );
2230
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2231
- const data = await res.json();
2232
- return { _tag: "Success", data: mapSubscription(data) };
2233
- } catch (e2) {
2234
- return { _tag: "Failure", error: e2 };
2235
- }
2236
- },
2237
- async reactivate({ subscriptionId }) {
2238
- try {
2239
- const res = await fetcher(
2240
- `/customer/v1/subscriptions/${subscriptionId}/reactivate`,
2241
- { method: "POST" }
2242
- );
2243
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2244
- const data = await res.json();
2245
- return { _tag: "Success", data: mapSubscription(data) };
2246
- } catch (e2) {
2247
- return { _tag: "Failure", error: e2 };
2248
- }
2249
- },
2250
- async cancel({ subscriptionId, reason }) {
2251
- try {
2252
- const res = await fetcher(
2253
- `/customer/v1/subscriptions/${subscriptionId}/cancel`,
2254
- {
2255
- method: "POST",
2256
- headers: { "Content-Type": "application/json" },
2257
- body: JSON.stringify({ cancellationReason: reason })
2258
- }
2259
- );
2260
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2261
- const data = await res.json();
2262
- return { _tag: "Success", data: mapSubscription(data) };
2263
- } catch (e2) {
2264
- return { _tag: "Failure", error: e2 };
2265
- }
2266
- },
2267
- // Legacy endpoint — no /customer/v1/subscriptions/{id}/plans exists yet.
2268
- async getAvailablePlans({ subscriptionId }) {
2269
- try {
2270
- const res = await fetcher(
2271
- `/customer/subscriptions/${subscriptionId}/plans`
2272
- );
2273
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2274
- const data = await res.json();
2275
- return { _tag: "Success", data };
2276
- } catch (e2) {
2277
- return { _tag: "Failure", error: e2 };
2278
- }
2279
- },
2280
- // Legacy endpoint — no /customer/v1 equivalent exists yet.
2281
- async getDefaultSubscriptionId() {
2282
- try {
2283
- const res = await fetcher(
2284
- `/customer/subscriptions/one-by-next-billing-date`
2285
- );
2286
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2287
- const data = await res.json();
2288
- return { _tag: "Success", data: (data == null ? void 0 : data.id) ?? null };
2289
- } catch (e2) {
2290
- return { _tag: "Failure", error: e2 };
2291
- }
2292
- },
2293
- // Legacy endpoint — no /customer/v1/subscriptions/{id}/upsells exists yet.
2294
- async getUpsellProducts({ subscriptionId }) {
2295
- try {
2296
- const res = await fetcher(
2297
- `/customer/subscriptions/${subscriptionId}/upsell-products`
2298
- );
2299
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2300
- const data = await res.json();
2301
- const products = data.map((p2) => {
2302
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2303
- return {
2304
- id: p2.id,
2305
- variantId: ((_b = (_a = p2.variants) == null ? void 0 : _a[0]) == null ? void 0 : _b.id) ?? "",
2306
- title: p2.title ?? "",
2307
- imageUrl: ((_c = p2.featuredImage) == null ? void 0 : _c.url) ?? void 0,
2308
- price: {
2309
- amount: String(((_f = (_e = (_d = p2.variants) == null ? void 0 : _d[0]) == null ? void 0 : _e.currentPrice) == null ? void 0 : _f.amount) ?? 0),
2310
- currencyCode: ((_i = (_h = (_g = p2.variants) == null ? void 0 : _g[0]) == null ? void 0 : _h.currentPrice) == null ? void 0 : _i.currencyCode) ?? ""
2311
- },
2312
- // recurring comes from the upsell rule on variants[0]; present in PreparedProductSchema
2313
- recurring: (_k = (_j = p2.variants) == null ? void 0 : _j[0]) == null ? void 0 : _k.recurring
2314
- };
2315
- });
2316
- return { _tag: "Success", data: products };
2317
- } catch (e2) {
2318
- return { _tag: "Failure", error: e2 };
2319
- }
2320
- },
2321
- // Legacy endpoint — no /customer/v1/subscriptions/{id}/upsells POST exists yet.
2322
- async addUpsellProduct({ subscriptionId, variantId, quantity, oneTime }) {
2323
- try {
2324
- const res = await fetcher(
2325
- `/customer/subscriptions/${subscriptionId}/upsell`,
2326
- {
2327
- method: "POST",
2328
- headers: { "Content-Type": "application/json" },
2329
- body: JSON.stringify({
2330
- productVariantId: variantId,
2331
- quantity,
2332
- ...oneTime ? { renewalLimit: 1 } : {}
2333
- })
2334
- }
2335
- );
2336
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2337
- return { _tag: "Success", data: void 0 };
2338
- } catch (e2) {
2339
- return { _tag: "Failure", error: e2 };
2340
- }
2341
- },
2342
- // Legacy endpoint — no /customer/v1 equivalent exists yet.
2343
- async getLastOrder({ subscriptionId }) {
2344
- try {
2345
- const res = await fetcher(
2346
- `/customer/subscriptions/${subscriptionId}/last-order`
2347
- );
2348
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2349
- const data = await res.json();
2350
- if (!data) return { _tag: "Success", data: null };
2351
- return {
2352
- _tag: "Success",
2353
- data: { id: data.id, createdAt: data.createdAt }
2354
- };
2355
- } catch (e2) {
2356
- return { _tag: "Failure", error: e2 };
2357
- }
2358
- },
2359
- // Legacy endpoints, split by stage (see SubscriptionService.renewNow docs):
2360
- // retry → POST /customer/subscriptions/{id}/retry
2361
- // renewalId → POST /customer/renewals/{renewalId}/renew
2362
- // default → POST /customer/subscriptions/{id}/order-now
2363
- async renewNow({ subscriptionId, renewalId, retry }) {
2364
- try {
2365
- const url = retry ? `/customer/subscriptions/${subscriptionId}/retry` : renewalId ? `/customer/renewals/${renewalId}/renew` : `/customer/subscriptions/${subscriptionId}/order-now`;
2366
- const res = await fetcher(url, { method: "POST" });
2367
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2368
- const body = res.status === 204 ? null : await res.json();
2369
- return {
2370
- _tag: "Success",
2371
- data: {
2372
- nextActionUrl: (body == null ? void 0 : body.nextActionUrl) ?? void 0,
2373
- result: (body == null ? void 0 : body.result) ?? "success"
2374
- }
2375
- };
2376
- } catch (e2) {
2377
- return { _tag: "Failure", error: e2 };
2378
- }
2379
- },
2380
- // Legacy endpoint — POST /plan returns 204; re-fetch to return the updated subscription.
2381
- async changeFrequency({ subscriptionId, plan }) {
2382
- try {
2383
- const res = await fetcher(
2384
- `/customer/subscriptions/${subscriptionId}/plan`,
2385
- {
2386
- method: "POST",
2387
- headers: { "Content-Type": "application/json" },
2388
- body: JSON.stringify({ plan })
2389
- }
2390
- );
2391
- if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
2392
- const refreshed = await adapter.getById(subscriptionId);
2393
- if (refreshed._tag === "Failure") return refreshed;
2394
- if (refreshed.data) return { _tag: "Success", data: refreshed.data };
2395
- return {
2396
- _tag: "Failure",
2397
- error: "Subscription not found after frequency change"
2398
- };
2399
- } catch (e2) {
2400
- return { _tag: "Failure", error: e2 };
2401
- }
2402
- }
2403
- };
2404
- return adapter;
2405
- }
2406
1109
  const SubscriptionServiceContext = createContext("services/subscription");
2407
1110
  function getCurrentSubscriptionId() {
2408
1111
  if (typeof window === "undefined") {
@@ -2425,83 +1128,41 @@ function getCurrentSubscriptionId() {
2425
1128
  }
2426
1129
  function createSubscriptionService(adapter) {
2427
1130
  const current = d(null);
2428
- const hasPendingBilling = d(false);
2429
- const discountsChangedAt = d(0);
2430
- const itemsChangedAt = d(0);
2431
- const lastOrder = d(null);
2432
- async function refreshAfterDiscountChange() {
2433
- await reload();
2434
- discountsChangedAt.value = discountsChangedAt.value + 1;
1131
+ const discountsChangedAtSignal = d(0);
1132
+ const itemsChangedAtSignal = d(0);
1133
+ async function refreshCurrent(subscriptionId) {
1134
+ const result = await adapter.getById(subscriptionId);
1135
+ if (result._tag === "Success" && result.data != null) {
1136
+ current.value = result.data;
1137
+ }
1138
+ }
1139
+ async function refreshAfterDiscountChange(subscriptionId) {
1140
+ await refreshCurrent(subscriptionId);
1141
+ discountsChangedAtSignal.value = discountsChangedAtSignal.value + 1;
2435
1142
  }
2436
- async function refreshAfterItemChange() {
2437
- await reload();
2438
- itemsChangedAt.value = itemsChangedAt.value + 1;
1143
+ async function refreshAfterItemChange(subscriptionId) {
1144
+ await refreshCurrent(subscriptionId);
1145
+ itemsChangedAtSignal.value = itemsChangedAtSignal.value + 1;
2439
1146
  }
2440
1147
  function subscriptionIdFromCurrent() {
2441
1148
  var _a;
2442
1149
  return ((_a = current.value) == null ? void 0 : _a.id) ?? null;
2443
1150
  }
2444
- async function reload() {
2445
- var _a, _b;
2446
- const id = (_a = current.value) == null ? void 0 : _a.id;
2447
- if (!id) return;
2448
- const [subResult, lastOrderResult] = await Promise.all([
2449
- adapter.getById(id),
2450
- adapter.getLastOrder({ subscriptionId: id })
2451
- ]);
2452
- if (((_b = current.value) == null ? void 0 : _b.id) !== id) return;
2453
- if (subResult._tag === "Success") current.value = subResult.data;
2454
- if (lastOrderResult._tag === "Success") lastOrder.value = lastOrderResult.data;
2455
- }
2456
1151
  const service = {
2457
- current,
2458
- hasPendingBilling,
2459
- discountsChangedAt,
2460
- itemsChangedAt,
2461
- lastOrder,
2462
1152
  search: adapter.search,
2463
- // Prefer the adapter's rich cross-subscription list (legacy endpoint, active-first).
2464
- // Fall back to a single `search` page for adapters that don't implement it
2465
- // (e.g. the editor mock) so the cross-subscription views still render.
2466
- listAll: adapter.listAll ? adapter.listAll.bind(adapter) : async () => {
2467
- const result = await adapter.search();
2468
- if (result._tag !== "Success") return result;
2469
- return { _tag: "Success", data: result.data.items };
2470
- },
2471
1153
  getById: adapter.getById,
2472
1154
  getCurrentSubscriptionId,
2473
1155
  addItem: async (subscriptionId, item) => {
2474
1156
  const result = await adapter.addItem({ subscriptionId, item });
2475
1157
  if (result._tag === "Success") {
2476
- await refreshAfterItemChange();
1158
+ await refreshAfterItemChange(subscriptionId);
2477
1159
  }
2478
1160
  return result;
2479
1161
  },
2480
1162
  removeItem: async (subscriptionId, itemId) => {
2481
1163
  const result = await adapter.removeItem({ subscriptionId, itemId });
2482
1164
  if (result._tag === "Success") {
2483
- await refreshAfterItemChange();
2484
- }
2485
- return result;
2486
- },
2487
- updateItem: async (subscriptionId, lineId, update) => {
2488
- const result = await adapter.updateItem({ subscriptionId, lineId, update });
2489
- if (result._tag === "Success") {
2490
- await refreshAfterItemChange();
2491
- }
2492
- return result;
2493
- },
2494
- skipLineItem: async (subscriptionId, lineId, nextBillingDate) => {
2495
- const result = await adapter.skipLineItem({ subscriptionId, lineId, nextBillingDate });
2496
- if (result._tag === "Success") {
2497
- await refreshAfterItemChange();
2498
- }
2499
- return result;
2500
- },
2501
- updateBoxItems: async (subscriptionId, params) => {
2502
- const result = await adapter.updateBoxItems({ subscriptionId, ...params });
2503
- if (result._tag === "Success") {
2504
- await refreshAfterItemChange();
1165
+ await refreshAfterItemChange(subscriptionId);
2505
1166
  }
2506
1167
  return result;
2507
1168
  },
@@ -2515,7 +1176,7 @@ function createSubscriptionService(adapter) {
2515
1176
  }
2516
1177
  const result = await adapter.addDiscount({ subscriptionId: id, code });
2517
1178
  if (result._tag === "Success") {
2518
- await refreshAfterDiscountChange();
1179
+ await refreshAfterDiscountChange(id);
2519
1180
  }
2520
1181
  return result;
2521
1182
  },
@@ -2532,7 +1193,7 @@ function createSubscriptionService(adapter) {
2532
1193
  discountId
2533
1194
  });
2534
1195
  if (result._tag === "Success") {
2535
- await refreshAfterDiscountChange();
1196
+ await refreshAfterDiscountChange(id);
2536
1197
  }
2537
1198
  return result;
2538
1199
  },
@@ -2541,13 +1202,11 @@ function createSubscriptionService(adapter) {
2541
1202
  pause: (subscriptionId) => adapter.pause({ subscriptionId }),
2542
1203
  reactivate: (subscriptionId) => adapter.reactivate({ subscriptionId }),
2543
1204
  cancel: (subscriptionId, reason) => adapter.cancel({ subscriptionId, reason }),
2544
- renewNow: (params) => adapter.renewNow(params),
2545
- changeFrequency: (subscriptionId, plan) => adapter.changeFrequency({ subscriptionId, plan }),
2546
- reload,
2547
1205
  getAvailablePlans: (subscriptionId) => adapter.getAvailablePlans({ subscriptionId }),
2548
1206
  getDefaultSubscriptionId: () => adapter.getDefaultSubscriptionId(),
2549
- getUpsellProducts: (params) => adapter.getUpsellProducts ? adapter.getUpsellProducts(params) : Promise.resolve({ _tag: "Success", data: [] }),
2550
- addUpsellProduct: (params) => adapter.addUpsellProduct ? adapter.addUpsellProduct(params) : Promise.resolve({ _tag: "Success", data: void 0 })
1207
+ current,
1208
+ discountsChangedAt: discountsChangedAtSignal,
1209
+ itemsChangedAt: itemsChangedAtSignal
2551
1210
  };
2552
1211
  return service;
2553
1212
  }
@@ -2816,88 +1475,66 @@ export {
2816
1475
  AuthenticationError,
2817
1476
  AuthenticationErrorReason,
2818
1477
  B as BlockWrapperEvent,
2819
- m as ContextProvideEvent,
2820
- p as ContextRequestEvent,
1478
+ C as ContextProvideEvent,
1479
+ a as ContextRequestEvent,
2821
1480
  CustomerServiceContext,
2822
- D2 as DEFAULT_GLOBAL_STYLES,
1481
+ D as DEFAULT_GLOBAL_STYLES,
2823
1482
  DISCOUNT_REJECTION_REASONS,
2824
1483
  LoginServiceContext,
2825
1484
  OrdersServiceContext,
2826
- OverlayServiceContext,
2827
1485
  ProductServiceContext,
2828
1486
  RouterServiceContext,
2829
- SchedulesServiceContext,
2830
1487
  S as SelectedBlockContext,
2831
- SettingsServiceContext,
2832
- ShopServiceContext,
2833
1488
  u as Signal,
2834
1489
  StateContext,
2835
1490
  SubscriptionServiceContext,
2836
- a2 as ThemeStateContext,
2837
- T as TranslationContext,
1491
+ T as ThemeStateContext,
1492
+ b as TranslationContext,
2838
1493
  W as WorkflowServiceContext,
2839
- q as __recordDevtoolsInstance,
2840
- _ as __recordDevtoolsPropSetter,
2841
- t as attachEmptyTracking,
2842
- b as backfillInstanceDefaults,
1494
+ e as attachEmptyTracking,
1495
+ f as backfillInstanceDefaults,
2843
1496
  w as computed,
2844
- createApiCustomerAdapter,
2845
- createApiLoginAdapter,
2846
- createApiProductAdapter,
2847
- createApiSchedulesAdapter,
2848
- createApiSubscriptionAdapter,
2849
- createBlockInstance,
2850
- v as createBlockInstanceFromJSON,
2851
- f as createBlockInstanceFromObject,
2852
- x as createCeRenderer,
1497
+ g as createBlockInstance,
1498
+ h as createBlockInstanceFromJSON,
1499
+ i as createBlockInstanceFromObject,
1500
+ j as createCeRenderer,
2853
1501
  createContext,
2854
1502
  createCustomerService,
2855
- createLoginService,
2856
- createMockCustomerAdapter,
2857
- createMockLoginAdapter,
2858
1503
  createMockOrdersAdapter,
2859
1504
  createMockProductAdapter,
2860
1505
  createMockRouterService,
2861
- createMockSchedulesAdapter,
2862
1506
  createMockSubscriptionAdapter,
2863
1507
  createMockWorkflowApiAdapter,
2864
1508
  createOrdersService,
2865
- createOverlayService,
2866
1509
  createProductService,
2867
1510
  createRouterService,
2868
- createSchedulesService,
2869
- y as createSelectedBlock,
2870
- createSettingsService,
2871
- createShopService,
1511
+ k as createSelectedBlock,
2872
1512
  createState,
2873
1513
  createSubscriptionService,
2874
- c as createThemeState,
2875
- b2 as createTranslationService,
2876
- d2 as createWorkflowApiAdapter,
2877
- e as createWorkflowService,
2878
- defineBlock,
2879
- z as defineBlockRuntime,
2880
- defineOverlayWrapper,
1514
+ l as createThemeState,
1515
+ m as createTranslationService,
1516
+ n as createWorkflowApiAdapter,
1517
+ o as createWorkflowService,
1518
+ p as defineBlock,
1519
+ q as defineBlockRuntime,
2881
1520
  E as effect,
2882
- g as getDefaultBlockForAction,
2883
- getDefinedBlocks,
2884
- A as getDevtoolsBlockState,
2885
- h as hasDefaultBlockForAction,
2886
- D as hasRenderedContent,
2887
- i2 as indexOverrides,
2888
- i as injectContext,
2889
- F as isEditorPreview,
2890
- a as isStubDefinition,
1521
+ s as getDefaultBlockForAction,
1522
+ t as getDefinedBlocks,
1523
+ v as hasDefaultBlockForAction,
1524
+ x as hasRenderedContent,
1525
+ y as indexOverrides,
1526
+ z as injectContext,
1527
+ A as isEditorPreview,
1528
+ F as isStubDefinition,
2891
1529
  loadBlockRegistry,
2892
1530
  loginService,
2893
- o as onRegisterBlock,
2894
- G as provideContext,
1531
+ G as onRegisterBlock,
1532
+ H as provideContext,
2895
1533
  registerBlock,
2896
- j as serializeBlocks,
2897
- H as setDevtoolsBlockProp,
1534
+ I as serializeBlocks,
2898
1535
  d as signal,
2899
- s as subscribeContext,
2900
- n as untracked,
1536
+ J as subscribeContext,
1537
+ K as untracked,
2901
1538
  waitForDevBlocksUrl,
2902
- w2 as withWrapper
1539
+ L as withWrapper
2903
1540
  };