@juo/blocks 1.12.0-alpha.0 → 1.12.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ExtensionRoot-9XfhG8YM.js → ExtensionRoot-peABLAZZ.js} +15 -3
- package/dist/block-B6s9jL7l.js +966 -0
- package/dist/block.d.ts +50 -0
- package/dist/block.d.ts.map +1 -1
- package/dist/block.devtools.test.d.ts +2 -0
- package/dist/block.devtools.test.d.ts.map +1 -0
- package/dist/{bridge-w5KQ-czl.js → bridge-r7Yk8fjY.js} +34 -25
- package/dist/context.d.ts.map +1 -1
- package/dist/context.devtools.test.d.ts +2 -0
- package/dist/context.devtools.test.d.ts.map +1 -0
- package/dist/core.js +857 -149
- package/dist/devtools/env.d.ts +3 -0
- package/dist/devtools/env.d.ts.map +1 -0
- package/dist/devtools/hook.d.ts +35 -0
- package/dist/devtools/hook.d.ts.map +1 -0
- package/dist/devtools/index.d.ts +4 -0
- package/dist/devtools/index.d.ts.map +1 -0
- package/dist/devtools/protocol.d.ts +91 -0
- package/dist/devtools/protocol.d.ts.map +1 -0
- package/dist/devtools.js +44 -0
- package/dist/editor/bridge.d.ts +7 -0
- package/dist/editor/bridge.d.ts.map +1 -1
- package/dist/editor/components.d.ts.map +1 -1
- package/dist/editor/main.d.ts +6 -1
- package/dist/editor/main.d.ts.map +1 -1
- package/dist/editor/main.test.d.ts +2 -0
- package/dist/editor/main.test.d.ts.map +1 -0
- package/dist/editor/messages.d.ts +13 -2
- package/dist/editor/messages.d.ts.map +1 -1
- package/dist/editor/messages.test.d.ts +2 -0
- package/dist/editor/messages.test.d.ts.map +1 -0
- package/dist/editor/overlays.d.ts +14 -0
- package/dist/editor/overlays.d.ts.map +1 -0
- package/dist/editor/overlays.test.d.ts +2 -0
- package/dist/editor/overlays.test.d.ts.map +1 -0
- package/dist/editor.js +82 -47
- package/dist/{juo-workflow-CkyZRq60.js → juo-workflow-DY4rd256.js} +74 -873
- package/dist/main.d.ts +3 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/overlay-wrapper.d.ts +69 -0
- package/dist/overlay-wrapper.d.ts.map +1 -0
- package/dist/overlay-wrapper.test.d.ts +2 -0
- package/dist/overlay-wrapper.test.d.ts.map +1 -0
- package/dist/overlays/OverlayService.d.ts +34 -0
- package/dist/overlays/OverlayService.d.ts.map +1 -0
- package/dist/overlays/OverlayService.test.d.ts +2 -0
- package/dist/overlays/OverlayService.test.d.ts.map +1 -0
- package/dist/preact.js +1 -1
- package/dist/react.js +1 -1
- package/dist/registry.devtools.test.d.ts +2 -0
- package/dist/registry.devtools.test.d.ts.map +1 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/orders/adapter.d.ts +2 -1
- package/dist/services/orders/adapter.d.ts.map +1 -1
- package/dist/services/orders/types.d.ts +8 -0
- package/dist/services/orders/types.d.ts.map +1 -1
- package/dist/services/product/adapter.d.ts +23 -1
- package/dist/services/product/adapter.d.ts.map +1 -1
- package/dist/services/product/adapter.test.d.ts +2 -0
- package/dist/services/product/adapter.test.d.ts.map +1 -0
- package/dist/services/product/productService.d.ts.map +1 -1
- package/dist/services/product/types.d.ts +66 -0
- package/dist/services/product/types.d.ts.map +1 -1
- package/dist/services/schedules/adapter.d.ts +4 -1
- package/dist/services/schedules/adapter.d.ts.map +1 -1
- package/dist/services/schedules/adapter.test.d.ts +2 -0
- package/dist/services/schedules/adapter.test.d.ts.map +1 -0
- package/dist/services/schedules/index.d.ts +3 -3
- package/dist/services/schedules/index.d.ts.map +1 -1
- package/dist/services/schedules/schedulesService.d.ts +4 -3
- package/dist/services/schedules/schedulesService.d.ts.map +1 -1
- package/dist/services/schedules/schedulesService.test.d.ts +2 -0
- package/dist/services/schedules/schedulesService.test.d.ts.map +1 -0
- package/dist/services/schedules/types.d.ts +66 -12
- package/dist/services/schedules/types.d.ts.map +1 -1
- package/dist/services/settings/index.d.ts +3 -0
- package/dist/services/settings/index.d.ts.map +1 -0
- package/dist/services/settings/settingsService.d.ts +7 -0
- package/dist/services/settings/settingsService.d.ts.map +1 -0
- package/dist/services/settings/settingsService.test.d.ts +2 -0
- package/dist/services/settings/settingsService.test.d.ts.map +1 -0
- package/dist/services/settings/types.d.ts +35 -0
- package/dist/services/settings/types.d.ts.map +1 -0
- package/dist/services/shop/index.d.ts +3 -0
- package/dist/services/shop/index.d.ts.map +1 -0
- package/dist/services/shop/shopService.d.ts +12 -0
- package/dist/services/shop/shopService.d.ts.map +1 -0
- package/dist/services/shop/shopService.test.d.ts +2 -0
- package/dist/services/shop/shopService.test.d.ts.map +1 -0
- package/dist/services/shop/types.d.ts +7 -0
- package/dist/services/shop/types.d.ts.map +1 -0
- package/dist/services/subscription/adapter.d.ts +38 -1
- package/dist/services/subscription/adapter.d.ts.map +1 -1
- package/dist/services/subscription/adapter.test.d.ts +2 -0
- package/dist/services/subscription/adapter.test.d.ts.map +1 -0
- package/dist/services/subscription/subscriptionService.d.ts.map +1 -1
- package/dist/services/subscription/types.d.ts +200 -1
- package/dist/services/subscription/types.d.ts.map +1 -1
- package/dist/services/subscription/types.test.d.ts +2 -0
- package/dist/services/subscription/types.test.d.ts.map +1 -0
- package/dist/theme-state.d.ts +2 -1
- package/dist/theme-state.d.ts.map +1 -1
- package/dist/theme-state.params.test.d.ts +2 -0
- package/dist/theme-state.params.test.d.ts.map +1 -0
- package/dist/theme-state.translations.test.d.ts +2 -0
- package/dist/theme-state.translations.test.d.ts.map +1 -0
- package/dist/vue/block.d.ts.map +1 -1
- package/dist/vue.js +25 -4
- package/dist/web-components/ExtensionRoot.d.ts +1 -0
- package/dist/web-components/ExtensionRoot.d.ts.map +1 -1
- package/dist/web-components-editor.js +4 -3
- package/dist/web-components-runtime.js +3 -2
- package/package.json +5 -1
package/dist/core.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
-
import {
|
|
5
|
-
import { B,
|
|
4
|
+
import { e as createContext, 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";
|
|
6
7
|
import { reportBlockWarning, reportBlockError } from "./observability.js";
|
|
7
8
|
function createState() {
|
|
8
9
|
const discountCode = d(null);
|
|
@@ -72,6 +73,111 @@ function createState() {
|
|
|
72
73
|
};
|
|
73
74
|
}
|
|
74
75
|
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
|
+
}
|
|
75
181
|
function isLocalhostOrigin(origin) {
|
|
76
182
|
try {
|
|
77
183
|
const url = new URL(origin);
|
|
@@ -132,7 +238,7 @@ async function loadBlockRegistry(options = {}) {
|
|
|
132
238
|
if ("registerBlocks" in module && typeof module.registerBlocks === "function") {
|
|
133
239
|
module.registerBlocks();
|
|
134
240
|
} else {
|
|
135
|
-
Object.entries(module).forEach(([
|
|
241
|
+
Object.entries(module).forEach(([_2, item]) => {
|
|
136
242
|
if (typeof item === "object" && item != null) {
|
|
137
243
|
registerBlock(item);
|
|
138
244
|
}
|
|
@@ -206,7 +312,7 @@ const PARAMS = {
|
|
|
206
312
|
function uuid() {
|
|
207
313
|
return ("10000000-1000-4000-8000" + -1e11).replace(
|
|
208
314
|
/[018]/g,
|
|
209
|
-
(
|
|
315
|
+
(c2) => (c2 ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c2 / 4).toString(16)
|
|
210
316
|
);
|
|
211
317
|
}
|
|
212
318
|
function createMockLoginAdapter() {
|
|
@@ -576,10 +682,56 @@ function createLoginService(init) {
|
|
|
576
682
|
}
|
|
577
683
|
const LoginServiceContext = createContext("services/login");
|
|
578
684
|
function createMockOrdersAdapter() {
|
|
685
|
+
const mockOrders = [
|
|
686
|
+
{
|
|
687
|
+
id: "10001",
|
|
688
|
+
createdAt: "2024-10-15T09:30:00Z",
|
|
689
|
+
placedAt: "2024-10-15T09:30:00Z",
|
|
690
|
+
currencyCode: "USD",
|
|
691
|
+
totalPrice: 89.97,
|
|
692
|
+
financialStatus: "PAID",
|
|
693
|
+
fulfillmentStatus: "FULFILLED",
|
|
694
|
+
lines: [
|
|
695
|
+
{
|
|
696
|
+
id: "line_1",
|
|
697
|
+
title: "Monthly Coffee Subscription",
|
|
698
|
+
quantity: 1,
|
|
699
|
+
variantImage: null,
|
|
700
|
+
customAttributes: [
|
|
701
|
+
{ key: "roast", value: "dark" },
|
|
702
|
+
{ key: "size", value: "1lb" }
|
|
703
|
+
]
|
|
704
|
+
}
|
|
705
|
+
],
|
|
706
|
+
customAttributes: [
|
|
707
|
+
{ key: "order_type", value: "subscription_renewal" },
|
|
708
|
+
{ key: "gift_wrap", value: "false" }
|
|
709
|
+
]
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
id: "10002",
|
|
713
|
+
createdAt: "2024-09-20T14:15:00Z",
|
|
714
|
+
placedAt: "2024-09-20T14:15:00Z",
|
|
715
|
+
currencyCode: "USD",
|
|
716
|
+
totalPrice: 45.99,
|
|
717
|
+
financialStatus: "PAID",
|
|
718
|
+
fulfillmentStatus: "PARTIALLY_FULFILLED",
|
|
719
|
+
lines: [
|
|
720
|
+
{
|
|
721
|
+
id: "line_2",
|
|
722
|
+
title: "Premium Tea Set",
|
|
723
|
+
quantity: 2,
|
|
724
|
+
variantImage: null,
|
|
725
|
+
customAttributes: []
|
|
726
|
+
}
|
|
727
|
+
],
|
|
728
|
+
customAttributes: []
|
|
729
|
+
}
|
|
730
|
+
];
|
|
579
731
|
return {
|
|
580
732
|
async getOrders() {
|
|
581
733
|
return {
|
|
582
|
-
items:
|
|
734
|
+
items: mockOrders,
|
|
583
735
|
pageInfo: {
|
|
584
736
|
hasNextPage: false,
|
|
585
737
|
hasPrevPage: false,
|
|
@@ -743,6 +895,18 @@ function createMockProductAdapter() {
|
|
|
743
895
|
);
|
|
744
896
|
return product == null ? null : processProduct(product);
|
|
745
897
|
},
|
|
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
|
+
},
|
|
746
910
|
async search(opts) {
|
|
747
911
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
748
912
|
let filteredProducts = [...products];
|
|
@@ -880,6 +1044,85 @@ function createApiProductAdapter(fetcher, opts = { currencyCode: "USD" }) {
|
|
|
880
1044
|
}
|
|
881
1045
|
};
|
|
882
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 };
|
|
883
1126
|
}
|
|
884
1127
|
};
|
|
885
1128
|
}
|
|
@@ -894,7 +1137,11 @@ function createProductService(adapter) {
|
|
|
894
1137
|
},
|
|
895
1138
|
async search(opts) {
|
|
896
1139
|
return adapter.search(opts);
|
|
897
|
-
}
|
|
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 })
|
|
898
1145
|
};
|
|
899
1146
|
}
|
|
900
1147
|
function routeNameTableFromPages(pages) {
|
|
@@ -949,66 +1196,135 @@ function createMockRouterService() {
|
|
|
949
1196
|
}).routerService;
|
|
950
1197
|
}
|
|
951
1198
|
function futureDateStr(daysFromNow) {
|
|
952
|
-
const
|
|
953
|
-
|
|
954
|
-
return
|
|
1199
|
+
const d3 = /* @__PURE__ */ new Date();
|
|
1200
|
+
d3.setDate(d3.getDate() + daysFromNow);
|
|
1201
|
+
return d3.toISOString().split("T")[0] ?? "";
|
|
955
1202
|
}
|
|
956
1203
|
function createMockSchedulesAdapter() {
|
|
957
1204
|
let orders = [
|
|
958
1205
|
{
|
|
959
|
-
id: "
|
|
1206
|
+
id: "sched_1",
|
|
1207
|
+
customerId: "customer_1",
|
|
960
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,
|
|
961
1215
|
deliveryDate: futureDateStr(7),
|
|
1216
|
+
status: "scheduled",
|
|
962
1217
|
items: [
|
|
963
1218
|
{
|
|
964
|
-
id: "
|
|
965
|
-
productId: "p-beauty-1",
|
|
966
|
-
variantId: "v-beauty-1",
|
|
967
|
-
quantity: 1,
|
|
1219
|
+
id: "sched_item_1",
|
|
968
1220
|
title: "Rose Face Serum",
|
|
969
|
-
|
|
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: []
|
|
970
1238
|
},
|
|
971
1239
|
{
|
|
972
|
-
id: "
|
|
973
|
-
productId: "p-beauty-2",
|
|
974
|
-
variantId: "v-beauty-2",
|
|
975
|
-
quantity: 1,
|
|
1240
|
+
id: "sched_item_2",
|
|
976
1241
|
title: "Vitamin C Moisturizer",
|
|
977
|
-
|
|
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: []
|
|
978
1259
|
}
|
|
979
1260
|
],
|
|
980
|
-
|
|
1261
|
+
discounts: []
|
|
981
1262
|
},
|
|
982
1263
|
{
|
|
983
|
-
id: "
|
|
1264
|
+
id: "sched_2",
|
|
1265
|
+
customerId: "customer_1",
|
|
984
1266
|
subscriptionId: "sub_1",
|
|
985
|
-
|
|
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",
|
|
986
1275
|
items: [
|
|
987
1276
|
{
|
|
988
|
-
id: "
|
|
989
|
-
productId: "p-beauty-1",
|
|
990
|
-
variantId: "v-beauty-1",
|
|
991
|
-
quantity: 1,
|
|
1277
|
+
id: "sched_item_3",
|
|
992
1278
|
title: "Rose Face Serum",
|
|
993
|
-
|
|
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: []
|
|
994
1296
|
},
|
|
995
1297
|
{
|
|
996
|
-
id: "
|
|
997
|
-
productId: "p-beauty-3",
|
|
998
|
-
variantId: "v-beauty-3",
|
|
999
|
-
quantity: 1,
|
|
1298
|
+
id: "sched_item_4",
|
|
1000
1299
|
title: "Hyaluronic Acid Serum",
|
|
1001
|
-
|
|
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: []
|
|
1002
1317
|
}
|
|
1003
1318
|
],
|
|
1004
|
-
|
|
1319
|
+
discounts: []
|
|
1005
1320
|
}
|
|
1006
1321
|
];
|
|
1007
1322
|
let adjustments = [];
|
|
1008
1323
|
return {
|
|
1009
|
-
async getUpcomingOrders(
|
|
1324
|
+
async getUpcomingOrders(params) {
|
|
1010
1325
|
await new Promise((r) => setTimeout(r, 200));
|
|
1011
|
-
|
|
1326
|
+
const filtered = params.subscriptionId ? orders.filter((o2) => o2.subscriptionId === params.subscriptionId) : orders;
|
|
1327
|
+
return { _tag: "Success", data: filtered.slice(0, params.count) };
|
|
1012
1328
|
},
|
|
1013
1329
|
async getAdjustments() {
|
|
1014
1330
|
await new Promise((r) => setTimeout(r, 200));
|
|
@@ -1051,16 +1367,18 @@ function createMockSchedulesAdapter() {
|
|
|
1051
1367
|
},
|
|
1052
1368
|
async removeAdjustment({ adjustmentId }) {
|
|
1053
1369
|
await new Promise((r) => setTimeout(r, 200));
|
|
1054
|
-
adjustments = adjustments.filter((
|
|
1370
|
+
adjustments = adjustments.filter((a3) => a3.id !== adjustmentId);
|
|
1055
1371
|
return { _tag: "Success", data: void 0 };
|
|
1056
1372
|
}
|
|
1057
1373
|
};
|
|
1058
1374
|
}
|
|
1059
1375
|
function createApiSchedulesAdapter(fetcher) {
|
|
1060
1376
|
return {
|
|
1061
|
-
async getUpcomingOrders(count) {
|
|
1377
|
+
async getUpcomingOrders({ count, subscriptionId }) {
|
|
1062
1378
|
try {
|
|
1063
|
-
const
|
|
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()}`);
|
|
1064
1382
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1065
1383
|
const data = await res.json();
|
|
1066
1384
|
return { _tag: "Success", data: data.orders };
|
|
@@ -1073,11 +1391,11 @@ function createApiSchedulesAdapter(fetcher) {
|
|
|
1073
1391
|
const res = await fetcher(`/customer/v1/schedules/adjustments`);
|
|
1074
1392
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1075
1393
|
const data = await res.json();
|
|
1076
|
-
const adjustments = data.data.map((
|
|
1077
|
-
id:
|
|
1078
|
-
subscriptionId:
|
|
1079
|
-
type:
|
|
1080
|
-
newDate:
|
|
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
|
|
1081
1399
|
}));
|
|
1082
1400
|
return { _tag: "Success", data: adjustments };
|
|
1083
1401
|
} catch (e2) {
|
|
@@ -1146,53 +1464,135 @@ function createApiSchedulesAdapter(fetcher) {
|
|
|
1146
1464
|
}
|
|
1147
1465
|
const SchedulesServiceContext = createContext("services/schedules");
|
|
1148
1466
|
function createSchedulesService(adapter, opts) {
|
|
1149
|
-
const
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
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;
|
|
1153
1490
|
if (result._tag === "Success") {
|
|
1154
|
-
|
|
1491
|
+
current.value = result.data;
|
|
1155
1492
|
}
|
|
1156
1493
|
}
|
|
1157
1494
|
return {
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
upcoming.value = result.data;
|
|
1164
|
-
return { _tag: "Success", data: result.data[0] ?? null };
|
|
1165
|
-
},
|
|
1166
|
-
async getUpcomingOrders(count) {
|
|
1167
|
-
const result = await adapter.getUpcomingOrders(count);
|
|
1168
|
-
if (result._tag === "Success") {
|
|
1169
|
-
upcoming.value = result.data;
|
|
1170
|
-
}
|
|
1171
|
-
return result;
|
|
1172
|
-
},
|
|
1495
|
+
current,
|
|
1496
|
+
currentLoading,
|
|
1497
|
+
hasPendingBilling,
|
|
1498
|
+
getUpcomingOrder,
|
|
1499
|
+
getUpcomingOrders,
|
|
1173
1500
|
async getAdjustments() {
|
|
1174
1501
|
return adapter.getAdjustments();
|
|
1175
1502
|
},
|
|
1176
1503
|
async skipOrder(params) {
|
|
1177
1504
|
const result = await adapter.skipOrder(params);
|
|
1178
1505
|
if (result._tag === "Success") {
|
|
1179
|
-
await
|
|
1506
|
+
await reloadCurrent(params.subscriptionId);
|
|
1180
1507
|
}
|
|
1181
1508
|
return result;
|
|
1182
1509
|
},
|
|
1183
1510
|
async changeDateAdjustment(params) {
|
|
1184
1511
|
const result = await adapter.changeDateAdjustment(params);
|
|
1185
1512
|
if (result._tag === "Success") {
|
|
1186
|
-
await
|
|
1513
|
+
await reloadCurrent(params.subscriptionId);
|
|
1187
1514
|
}
|
|
1188
1515
|
return result;
|
|
1189
1516
|
},
|
|
1190
1517
|
async removeAdjustment(params) {
|
|
1191
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];
|
|
1192
1530
|
}
|
|
1193
1531
|
};
|
|
1194
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");
|
|
1195
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
|
+
});
|
|
1196
1596
|
const mockSubscriptions = [
|
|
1197
1597
|
{
|
|
1198
1598
|
id: "sub_1",
|
|
@@ -1205,8 +1605,18 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1205
1605
|
quantity: 2,
|
|
1206
1606
|
price: { amount: "29.99", currencyCode: "USD" },
|
|
1207
1607
|
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,
|
|
1208
1614
|
billingPolicy: { intervalCount: 1, interval: "MONTH" },
|
|
1209
|
-
deliveryPolicy: { intervalCount: 1, interval: "MONTH" }
|
|
1615
|
+
deliveryPolicy: { intervalCount: 1, interval: "MONTH" },
|
|
1616
|
+
customAttributes: [
|
|
1617
|
+
{ key: "roast_level", value: "medium" },
|
|
1618
|
+
{ key: "grind_type", value: "whole_bean" }
|
|
1619
|
+
]
|
|
1210
1620
|
}
|
|
1211
1621
|
],
|
|
1212
1622
|
discounts: [
|
|
@@ -1222,7 +1632,33 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1222
1632
|
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-15"),
|
|
1223
1633
|
frequency: "1 MONTH",
|
|
1224
1634
|
createdAt: "2024-10-01T00:00:00Z",
|
|
1225
|
-
updatedAt: "2024-10-14T00:00:00Z"
|
|
1635
|
+
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
|
+
customAttributes: [
|
|
1659
|
+
{ key: "subscription_tier", value: "premium" },
|
|
1660
|
+
{ key: "gift_message", value: "Enjoy your coffee!" }
|
|
1661
|
+
]
|
|
1226
1662
|
},
|
|
1227
1663
|
{
|
|
1228
1664
|
id: "sub_2",
|
|
@@ -1236,7 +1672,8 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1236
1672
|
price: { amount: "49.99", currencyCode: "USD" },
|
|
1237
1673
|
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-20"),
|
|
1238
1674
|
billingPolicy: { intervalCount: 2, interval: "WEEK" },
|
|
1239
|
-
deliveryPolicy: { intervalCount: 2, interval: "WEEK" }
|
|
1675
|
+
deliveryPolicy: { intervalCount: 2, interval: "WEEK" },
|
|
1676
|
+
customAttributes: []
|
|
1240
1677
|
}
|
|
1241
1678
|
],
|
|
1242
1679
|
discounts: [],
|
|
@@ -1244,7 +1681,32 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1244
1681
|
nextDeliveryDate: /* @__PURE__ */ new Date("2025-11-20"),
|
|
1245
1682
|
frequency: "2 WEEK",
|
|
1246
1683
|
createdAt: "2024-09-15T00:00:00Z",
|
|
1247
|
-
updatedAt: "2024-10-10T00:00:00Z"
|
|
1684
|
+
updatedAt: "2024-10-10T00:00:00Z",
|
|
1685
|
+
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
|
|
1248
1710
|
}
|
|
1249
1711
|
];
|
|
1250
1712
|
const mockUpsellProducts = [
|
|
@@ -1314,6 +1776,17 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1314
1776
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1315
1777
|
return { _tag: "Success", data: void 0 };
|
|
1316
1778
|
},
|
|
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
|
+
},
|
|
1317
1790
|
async addDiscount() {
|
|
1318
1791
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1319
1792
|
const behavior = options.addDiscountBehavior ?? { kind: "success" };
|
|
@@ -1422,6 +1895,49 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1422
1895
|
]
|
|
1423
1896
|
};
|
|
1424
1897
|
},
|
|
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
|
+
},
|
|
1425
1941
|
async getDefaultSubscriptionId() {
|
|
1426
1942
|
var _a;
|
|
1427
1943
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
@@ -1437,6 +1953,26 @@ function createMockSubscriptionAdapter(options = {}) {
|
|
|
1437
1953
|
}
|
|
1438
1954
|
};
|
|
1439
1955
|
}
|
|
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
|
+
}
|
|
1440
1976
|
function mapSubscription(raw) {
|
|
1441
1977
|
var _a, _b;
|
|
1442
1978
|
const status = raw.status === "merged" ? "canceled" : raw.status;
|
|
@@ -1445,6 +1981,7 @@ function mapSubscription(raw) {
|
|
|
1445
1981
|
return {
|
|
1446
1982
|
id: raw.id,
|
|
1447
1983
|
customerId: "",
|
|
1984
|
+
serial: raw.serial,
|
|
1448
1985
|
items: (raw.items ?? []).map(
|
|
1449
1986
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1450
1987
|
(item) => ({
|
|
@@ -1458,37 +1995,50 @@ function mapSubscription(raw) {
|
|
|
1458
1995
|
},
|
|
1459
1996
|
nextDeliveryDate: item.nextDeliveryDate ? new Date(item.nextDeliveryDate) : null,
|
|
1460
1997
|
billingPolicy: item.billingPolicy ?? raw.billingPolicy ?? null,
|
|
1461
|
-
deliveryPolicy: item.deliveryPolicy ?? raw.deliveryPolicy ?? 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
|
|
1462
2004
|
})
|
|
1463
2005
|
),
|
|
1464
2006
|
discounts: (raw.discounts ?? []).map(
|
|
1465
2007
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1466
|
-
(
|
|
2008
|
+
(d3) => {
|
|
1467
2009
|
var _a2, _b2, _c;
|
|
1468
2010
|
return {
|
|
1469
|
-
id:
|
|
1470
|
-
type: ((_a2 =
|
|
1471
|
-
value: ((_b2 =
|
|
1472
|
-
code:
|
|
1473
|
-
description:
|
|
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 ?? ""
|
|
1474
2016
|
};
|
|
1475
2017
|
}
|
|
1476
2018
|
),
|
|
1477
2019
|
status,
|
|
1478
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),
|
|
1479
2027
|
frequency,
|
|
1480
2028
|
createdAt: raw.createdAt,
|
|
1481
|
-
updatedAt: raw.updatedAt
|
|
2029
|
+
updatedAt: raw.updatedAt,
|
|
2030
|
+
billingPolicy: raw.billingPolicy ?? null,
|
|
2031
|
+
deliveryPolicy: raw.deliveryPolicy ?? null
|
|
1482
2032
|
};
|
|
1483
2033
|
}
|
|
1484
2034
|
function createApiSubscriptionAdapter(fetcher) {
|
|
1485
|
-
|
|
2035
|
+
const adapter = {
|
|
1486
2036
|
async search(options) {
|
|
1487
2037
|
var _a;
|
|
1488
2038
|
try {
|
|
1489
2039
|
const params = new URLSearchParams();
|
|
1490
2040
|
if ((_a = options == null ? void 0 : options.filters) == null ? void 0 : _a.length) {
|
|
1491
|
-
const q2 = options.filters.filter((f2) => Object.keys(f2).length > 0).flatMap((f2) => Object.entries(f2).filter(([, v2]) => Boolean(v2))).map(([
|
|
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 ");
|
|
1492
2042
|
if (q2) params.set("query", q2);
|
|
1493
2043
|
}
|
|
1494
2044
|
if (options == null ? void 0 : options.pagination) {
|
|
@@ -1558,6 +2108,60 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
1558
2108
|
return { _tag: "Failure", error: e2 };
|
|
1559
2109
|
}
|
|
1560
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
|
+
},
|
|
1561
2165
|
async addDiscount({ subscriptionId, code }) {
|
|
1562
2166
|
try {
|
|
1563
2167
|
const res = await fetcher(
|
|
@@ -1695,16 +2299,18 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
1695
2299
|
if (!res.ok) return { _tag: "Failure", error: `HTTP ${res.status}` };
|
|
1696
2300
|
const data = await res.json();
|
|
1697
2301
|
const products = data.map((p2) => {
|
|
1698
|
-
var _a, _b, _c, _d, _e;
|
|
2302
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
1699
2303
|
return {
|
|
1700
2304
|
id: p2.id,
|
|
1701
2305
|
variantId: ((_b = (_a = p2.variants) == null ? void 0 : _a[0]) == null ? void 0 : _b.id) ?? "",
|
|
1702
2306
|
title: p2.title ?? "",
|
|
1703
2307
|
imageUrl: ((_c = p2.featuredImage) == null ? void 0 : _c.url) ?? void 0,
|
|
1704
2308
|
price: {
|
|
1705
|
-
amount: String(((_e = (_d = p2.variants) == null ? void 0 : _d[0]) == null ? void 0 : _e.
|
|
1706
|
-
currencyCode: p2.currencyCode ?? ""
|
|
1707
|
-
}
|
|
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
|
|
1708
2314
|
};
|
|
1709
2315
|
});
|
|
1710
2316
|
return { _tag: "Success", data: products };
|
|
@@ -1732,8 +2338,70 @@ function createApiSubscriptionAdapter(fetcher) {
|
|
|
1732
2338
|
} catch (e2) {
|
|
1733
2339
|
return { _tag: "Failure", error: e2 };
|
|
1734
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
|
+
}
|
|
1735
2402
|
}
|
|
1736
2403
|
};
|
|
2404
|
+
return adapter;
|
|
1737
2405
|
}
|
|
1738
2406
|
const SubscriptionServiceContext = createContext("services/subscription");
|
|
1739
2407
|
function getCurrentSubscriptionId() {
|
|
@@ -1758,57 +2426,82 @@ function getCurrentSubscriptionId() {
|
|
|
1758
2426
|
function createSubscriptionService(adapter) {
|
|
1759
2427
|
const current = d(null);
|
|
1760
2428
|
const hasPendingBilling = d(false);
|
|
1761
|
-
const
|
|
1762
|
-
const
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
}
|
|
1768
|
-
}
|
|
1769
|
-
async function refreshAfterDiscountChange(subscriptionId) {
|
|
1770
|
-
await refreshCurrent(subscriptionId);
|
|
1771
|
-
discountsChangedAtSignal.value = discountsChangedAtSignal.value + 1;
|
|
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;
|
|
1772
2435
|
}
|
|
1773
|
-
async function refreshAfterItemChange(
|
|
1774
|
-
await
|
|
1775
|
-
|
|
2436
|
+
async function refreshAfterItemChange() {
|
|
2437
|
+
await reload();
|
|
2438
|
+
itemsChangedAt.value = itemsChangedAt.value + 1;
|
|
1776
2439
|
}
|
|
1777
2440
|
function subscriptionIdFromCurrent() {
|
|
1778
2441
|
var _a;
|
|
1779
2442
|
return ((_a = current.value) == null ? void 0 : _a.id) ?? null;
|
|
1780
2443
|
}
|
|
1781
|
-
|
|
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
|
+
const service = {
|
|
1782
2457
|
current,
|
|
1783
2458
|
hasPendingBilling,
|
|
1784
|
-
discountsChangedAt
|
|
1785
|
-
itemsChangedAt
|
|
1786
|
-
|
|
1787
|
-
|
|
2459
|
+
discountsChangedAt,
|
|
2460
|
+
itemsChangedAt,
|
|
2461
|
+
lastOrder,
|
|
2462
|
+
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
|
+
getById: adapter.getById,
|
|
2472
|
+
getCurrentSubscriptionId,
|
|
2473
|
+
addItem: async (subscriptionId, item) => {
|
|
2474
|
+
const result = await adapter.addItem({ subscriptionId, item });
|
|
1788
2475
|
if (result._tag === "Success") {
|
|
1789
|
-
|
|
2476
|
+
await refreshAfterItemChange();
|
|
1790
2477
|
}
|
|
1791
2478
|
return result;
|
|
1792
2479
|
},
|
|
1793
|
-
async
|
|
1794
|
-
const result = await adapter.
|
|
1795
|
-
if (result._tag === "Success"
|
|
1796
|
-
|
|
2480
|
+
removeItem: async (subscriptionId, itemId) => {
|
|
2481
|
+
const result = await adapter.removeItem({ subscriptionId, itemId });
|
|
2482
|
+
if (result._tag === "Success") {
|
|
2483
|
+
await refreshAfterItemChange();
|
|
1797
2484
|
}
|
|
1798
2485
|
return result;
|
|
1799
2486
|
},
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
const result = await adapter.addItem({ subscriptionId, item });
|
|
2487
|
+
updateItem: async (subscriptionId, lineId, update) => {
|
|
2488
|
+
const result = await adapter.updateItem({ subscriptionId, lineId, update });
|
|
1803
2489
|
if (result._tag === "Success") {
|
|
1804
|
-
await refreshAfterItemChange(
|
|
2490
|
+
await refreshAfterItemChange();
|
|
1805
2491
|
}
|
|
1806
2492
|
return result;
|
|
1807
2493
|
},
|
|
1808
|
-
|
|
1809
|
-
const result = await adapter.
|
|
2494
|
+
skipLineItem: async (subscriptionId, lineId, nextBillingDate) => {
|
|
2495
|
+
const result = await adapter.skipLineItem({ subscriptionId, lineId, nextBillingDate });
|
|
1810
2496
|
if (result._tag === "Success") {
|
|
1811
|
-
await refreshAfterItemChange(
|
|
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();
|
|
1812
2505
|
}
|
|
1813
2506
|
return result;
|
|
1814
2507
|
},
|
|
@@ -1822,7 +2515,7 @@ function createSubscriptionService(adapter) {
|
|
|
1822
2515
|
}
|
|
1823
2516
|
const result = await adapter.addDiscount({ subscriptionId: id, code });
|
|
1824
2517
|
if (result._tag === "Success") {
|
|
1825
|
-
await refreshAfterDiscountChange(
|
|
2518
|
+
await refreshAfterDiscountChange();
|
|
1826
2519
|
}
|
|
1827
2520
|
return result;
|
|
1828
2521
|
},
|
|
@@ -1839,7 +2532,7 @@ function createSubscriptionService(adapter) {
|
|
|
1839
2532
|
discountId
|
|
1840
2533
|
});
|
|
1841
2534
|
if (result._tag === "Success") {
|
|
1842
|
-
await refreshAfterDiscountChange(
|
|
2535
|
+
await refreshAfterDiscountChange();
|
|
1843
2536
|
}
|
|
1844
2537
|
return result;
|
|
1845
2538
|
},
|
|
@@ -1848,11 +2541,15 @@ function createSubscriptionService(adapter) {
|
|
|
1848
2541
|
pause: (subscriptionId) => adapter.pause({ subscriptionId }),
|
|
1849
2542
|
reactivate: (subscriptionId) => adapter.reactivate({ subscriptionId }),
|
|
1850
2543
|
cancel: (subscriptionId, reason) => adapter.cancel({ subscriptionId, reason }),
|
|
2544
|
+
renewNow: (params) => adapter.renewNow(params),
|
|
2545
|
+
changeFrequency: (subscriptionId, plan) => adapter.changeFrequency({ subscriptionId, plan }),
|
|
2546
|
+
reload,
|
|
1851
2547
|
getAvailablePlans: (subscriptionId) => adapter.getAvailablePlans({ subscriptionId }),
|
|
1852
2548
|
getDefaultSubscriptionId: () => adapter.getDefaultSubscriptionId(),
|
|
1853
2549
|
getUpsellProducts: (params) => adapter.getUpsellProducts ? adapter.getUpsellProducts(params) : Promise.resolve({ _tag: "Success", data: [] }),
|
|
1854
2550
|
addUpsellProduct: (params) => adapter.addUpsellProduct ? adapter.addUpsellProduct(params) : Promise.resolve({ _tag: "Success", data: void 0 })
|
|
1855
2551
|
};
|
|
2552
|
+
return service;
|
|
1856
2553
|
}
|
|
1857
2554
|
const DISCOUNT_REJECTION_REASONS = [
|
|
1858
2555
|
"INVALID_CODE",
|
|
@@ -2119,35 +2816,40 @@ export {
|
|
|
2119
2816
|
AuthenticationError,
|
|
2120
2817
|
AuthenticationErrorReason,
|
|
2121
2818
|
B as BlockWrapperEvent,
|
|
2122
|
-
|
|
2123
|
-
|
|
2819
|
+
m as ContextProvideEvent,
|
|
2820
|
+
p as ContextRequestEvent,
|
|
2124
2821
|
CustomerServiceContext,
|
|
2125
|
-
|
|
2822
|
+
D2 as DEFAULT_GLOBAL_STYLES,
|
|
2126
2823
|
DISCOUNT_REJECTION_REASONS,
|
|
2127
2824
|
LoginServiceContext,
|
|
2128
2825
|
OrdersServiceContext,
|
|
2826
|
+
OverlayServiceContext,
|
|
2129
2827
|
ProductServiceContext,
|
|
2130
2828
|
RouterServiceContext,
|
|
2131
2829
|
SchedulesServiceContext,
|
|
2132
2830
|
S as SelectedBlockContext,
|
|
2831
|
+
SettingsServiceContext,
|
|
2832
|
+
ShopServiceContext,
|
|
2133
2833
|
u as Signal,
|
|
2134
2834
|
StateContext,
|
|
2135
2835
|
SubscriptionServiceContext,
|
|
2136
|
-
|
|
2137
|
-
|
|
2836
|
+
a2 as ThemeStateContext,
|
|
2837
|
+
T as TranslationContext,
|
|
2138
2838
|
W as WorkflowServiceContext,
|
|
2139
|
-
|
|
2140
|
-
|
|
2839
|
+
q as __recordDevtoolsInstance,
|
|
2840
|
+
_ as __recordDevtoolsPropSetter,
|
|
2841
|
+
t as attachEmptyTracking,
|
|
2842
|
+
b as backfillInstanceDefaults,
|
|
2141
2843
|
w as computed,
|
|
2142
2844
|
createApiCustomerAdapter,
|
|
2143
2845
|
createApiLoginAdapter,
|
|
2144
2846
|
createApiProductAdapter,
|
|
2145
2847
|
createApiSchedulesAdapter,
|
|
2146
2848
|
createApiSubscriptionAdapter,
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2849
|
+
createBlockInstance,
|
|
2850
|
+
v as createBlockInstanceFromJSON,
|
|
2851
|
+
f as createBlockInstanceFromObject,
|
|
2852
|
+
x as createCeRenderer,
|
|
2151
2853
|
createContext,
|
|
2152
2854
|
createCustomerService,
|
|
2153
2855
|
createLoginService,
|
|
@@ -2160,36 +2862,42 @@ export {
|
|
|
2160
2862
|
createMockSubscriptionAdapter,
|
|
2161
2863
|
createMockWorkflowApiAdapter,
|
|
2162
2864
|
createOrdersService,
|
|
2865
|
+
createOverlayService,
|
|
2163
2866
|
createProductService,
|
|
2164
2867
|
createRouterService,
|
|
2165
2868
|
createSchedulesService,
|
|
2166
|
-
|
|
2869
|
+
y as createSelectedBlock,
|
|
2870
|
+
createSettingsService,
|
|
2871
|
+
createShopService,
|
|
2167
2872
|
createState,
|
|
2168
2873
|
createSubscriptionService,
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2874
|
+
c as createThemeState,
|
|
2875
|
+
b2 as createTranslationService,
|
|
2876
|
+
d2 as createWorkflowApiAdapter,
|
|
2877
|
+
e as createWorkflowService,
|
|
2878
|
+
defineBlock,
|
|
2879
|
+
z as defineBlockRuntime,
|
|
2880
|
+
defineOverlayWrapper,
|
|
2175
2881
|
E as effect,
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
F as
|
|
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,
|
|
2184
2891
|
loadBlockRegistry,
|
|
2185
2892
|
loginService,
|
|
2186
|
-
|
|
2187
|
-
|
|
2893
|
+
o as onRegisterBlock,
|
|
2894
|
+
G as provideContext,
|
|
2188
2895
|
registerBlock,
|
|
2189
|
-
|
|
2896
|
+
j as serializeBlocks,
|
|
2897
|
+
H as setDevtoolsBlockProp,
|
|
2190
2898
|
d as signal,
|
|
2191
|
-
|
|
2192
|
-
|
|
2899
|
+
s as subscribeContext,
|
|
2900
|
+
n as untracked,
|
|
2193
2901
|
waitForDevBlocksUrl,
|
|
2194
|
-
|
|
2902
|
+
w2 as withWrapper
|
|
2195
2903
|
};
|