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