@patientos/website-kit 0.2.6 → 0.2.8
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/README.md +54 -2
- package/dist/booking-block-D-UOAPx3.d.ts +74 -0
- package/dist/cart-block-B-ytc9us.d.ts +20 -0
- package/dist/cart-button-BCLFittB.d.ts +24 -0
- package/dist/cart-storage.d.ts +110 -0
- package/dist/cart-storage.js +39 -0
- package/dist/checkout-block-BeXwpqYe.d.ts +24 -0
- package/dist/chunk-2CZFJOKK.js +79 -0
- package/dist/{chunk-ZYX4TXBN.js → chunk-3T7UWKAH.js} +4 -310
- package/dist/{chunk-7ZOQ6UKG.js → chunk-4GKSSM5N.js} +578 -3163
- package/dist/chunk-4NF7SSIX.js +367 -0
- package/dist/chunk-7BUDUYXN.js +80 -0
- package/dist/chunk-FZ4WKWIE.js +310 -0
- package/dist/{chunk-ZZFBTLR4.js → chunk-HTVKKLWI.js} +20 -5
- package/dist/chunk-IOC6QLB7.js +159 -0
- package/dist/chunk-S3ZQQOQT.js +2057 -0
- package/dist/chunk-UTAMB2SK.js +214 -0
- package/dist/chunk-WQSJ46TP.js +19 -0
- package/dist/chunk-ZNH6TSYP.js +167 -0
- package/dist/index.d.ts +12 -32
- package/dist/index.js +88 -26
- package/dist/islands-impl/cart-button.d.ts +19 -0
- package/dist/islands-impl/cart-button.js +13 -0
- package/dist/islands-impl/cart.d.ts +31 -0
- package/dist/islands-impl/cart.js +11 -0
- package/dist/islands-impl/checkout.d.ts +6 -0
- package/dist/islands-impl/checkout.js +13 -0
- package/dist/islands-impl/store.d.ts +30 -0
- package/dist/islands-impl/store.js +16 -0
- package/dist/islands-impl.d.ts +14 -10
- package/dist/islands-impl.js +22 -7
- package/dist/islands-registry.js +13 -4
- package/dist/{portal-account-8uQc_Ncx.d.ts → portal-account-DRJyr3nz.d.ts} +1 -82
- package/dist/{portal-account.client-BBe_q9yC.d.ts → portal-account.client-Bke4NsgW.d.ts} +2 -1
- package/dist/portal-booking-client.d.ts +3 -2
- package/dist/portal-booking-client.js +2 -1
- package/dist/portal-client-my3q5GME.d.ts +83 -0
- package/dist/store-block-CFxnsfKU.d.ts +37 -0
- package/dist/store-catalog-p7TFOpfk.d.ts +78 -0
- package/dist/store-catalog.d.ts +3 -0
- package/dist/store-catalog.js +11 -0
- package/dist/website-kit.css +193 -0
- package/package.json +31 -1
- package/dist/checkout-block-BdpPIuQ5.d.ts +0 -136
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
// src/cart-storage.ts
|
|
2
|
+
var CART_STORAGE_KEY = "patientos.cart.v1";
|
|
3
|
+
var MAX_LINES = 50;
|
|
4
|
+
var MAX_QUANTITY = 99;
|
|
5
|
+
function emptyCart() {
|
|
6
|
+
return { v: 1, lines: [] };
|
|
7
|
+
}
|
|
8
|
+
var EMPTY_CART = Object.freeze({
|
|
9
|
+
v: 1,
|
|
10
|
+
lines: Object.freeze([])
|
|
11
|
+
});
|
|
12
|
+
function cartLineId(value) {
|
|
13
|
+
if (typeof value !== "string") return null;
|
|
14
|
+
const normalized = value.trim();
|
|
15
|
+
return normalized.length > 0 && normalized.length <= 128 ? normalized : null;
|
|
16
|
+
}
|
|
17
|
+
function legacyCartLineId(kind, variantId) {
|
|
18
|
+
const input = `${kind}\0${variantId}`;
|
|
19
|
+
let first = 2166136261;
|
|
20
|
+
let second = 2246822507;
|
|
21
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
22
|
+
const code = input.charCodeAt(index);
|
|
23
|
+
first = Math.imul(first ^ code, 16777619);
|
|
24
|
+
second = Math.imul(second ^ code, 3266489909);
|
|
25
|
+
}
|
|
26
|
+
return `legacy-${(first >>> 0).toString(16).padStart(8, "0")}${(second >>> 0).toString(16).padStart(8, "0")}`;
|
|
27
|
+
}
|
|
28
|
+
function newCartLineId() {
|
|
29
|
+
return crypto.randomUUID();
|
|
30
|
+
}
|
|
31
|
+
function storage() {
|
|
32
|
+
try {
|
|
33
|
+
if (typeof window === "undefined" || !window.localStorage) return null;
|
|
34
|
+
return window.localStorage;
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function parseLine(raw) {
|
|
40
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
41
|
+
const line = raw;
|
|
42
|
+
const variantId = typeof line.variantId === "string" ? line.variantId.trim() : "";
|
|
43
|
+
if (!variantId) return null;
|
|
44
|
+
const kind = line.kind === "retail" ? "retail" : "fill";
|
|
45
|
+
const n = typeof line.quantity === "number" ? line.quantity : Number(line.quantity);
|
|
46
|
+
if (!Number.isFinite(n)) return null;
|
|
47
|
+
const quantity = Math.min(Math.max(Math.floor(n), 1), MAX_QUANTITY);
|
|
48
|
+
const lineId = cartLineId(line.lineId) ?? legacyCartLineId(kind, variantId);
|
|
49
|
+
return { lineId, kind, variantId, quantity };
|
|
50
|
+
}
|
|
51
|
+
function normalizeCartLines(entries) {
|
|
52
|
+
const lines = [];
|
|
53
|
+
const byIdentity = /* @__PURE__ */ new Map();
|
|
54
|
+
for (const entry of entries) {
|
|
55
|
+
const line = parseLine(entry);
|
|
56
|
+
if (!line) continue;
|
|
57
|
+
const identity = `${line.kind}\0${line.variantId}`;
|
|
58
|
+
const existing = byIdentity.get(identity);
|
|
59
|
+
if (existing) {
|
|
60
|
+
existing.quantity = Math.min(
|
|
61
|
+
existing.quantity + line.quantity,
|
|
62
|
+
MAX_QUANTITY
|
|
63
|
+
);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (lines.length >= MAX_LINES) continue;
|
|
67
|
+
lines.push(line);
|
|
68
|
+
byIdentity.set(identity, line);
|
|
69
|
+
}
|
|
70
|
+
return lines;
|
|
71
|
+
}
|
|
72
|
+
function normalizeSettledAttemptTokens(entries) {
|
|
73
|
+
if (!Array.isArray(entries)) return [];
|
|
74
|
+
return Array.from(
|
|
75
|
+
new Set(
|
|
76
|
+
entries.filter(
|
|
77
|
+
(entry) => typeof entry === "string" && entry.length > 0 && entry.length <= 128
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
).slice(-32);
|
|
81
|
+
}
|
|
82
|
+
function readCart() {
|
|
83
|
+
const store = storage();
|
|
84
|
+
if (!store) return emptyCart();
|
|
85
|
+
let raw;
|
|
86
|
+
try {
|
|
87
|
+
raw = store.getItem(CART_STORAGE_KEY);
|
|
88
|
+
} catch {
|
|
89
|
+
return emptyCart();
|
|
90
|
+
}
|
|
91
|
+
if (!raw) return emptyCart();
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(raw);
|
|
94
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
95
|
+
return emptyCart();
|
|
96
|
+
const bag = parsed;
|
|
97
|
+
if (bag.v !== 1 || !Array.isArray(bag.lines)) return emptyCart();
|
|
98
|
+
const settledAttemptTokens = normalizeSettledAttemptTokens(
|
|
99
|
+
bag.settledAttemptTokens
|
|
100
|
+
);
|
|
101
|
+
return {
|
|
102
|
+
v: 1,
|
|
103
|
+
lines: normalizeCartLines(bag.lines),
|
|
104
|
+
...settledAttemptTokens.length > 0 ? { settledAttemptTokens } : {}
|
|
105
|
+
};
|
|
106
|
+
} catch {
|
|
107
|
+
return emptyCart();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
var CART_MUTATION_LOCK = "patientos-cart-mutation-v1";
|
|
111
|
+
var CART_MUTATION_VALIDATION_TIMEOUT_MS = 5e3;
|
|
112
|
+
function persistCart(cart) {
|
|
113
|
+
const settledAttemptTokens = normalizeSettledAttemptTokens(
|
|
114
|
+
cart.settledAttemptTokens
|
|
115
|
+
);
|
|
116
|
+
const normalised = {
|
|
117
|
+
v: 1,
|
|
118
|
+
lines: normalizeCartLines(cart.lines),
|
|
119
|
+
...settledAttemptTokens.length > 0 ? { settledAttemptTokens } : {}
|
|
120
|
+
};
|
|
121
|
+
const store = storage();
|
|
122
|
+
if (!store)
|
|
123
|
+
return {
|
|
124
|
+
cart: readCart(),
|
|
125
|
+
persisted: false,
|
|
126
|
+
status: "cart_storage_unavailable"
|
|
127
|
+
};
|
|
128
|
+
try {
|
|
129
|
+
store.setItem(CART_STORAGE_KEY, JSON.stringify(normalised));
|
|
130
|
+
} catch {
|
|
131
|
+
return {
|
|
132
|
+
cart: readCart(),
|
|
133
|
+
persisted: false,
|
|
134
|
+
status: "cart_storage_unavailable"
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
notify(normalised);
|
|
138
|
+
return { cart: normalised, persisted: true, status: "updated" };
|
|
139
|
+
}
|
|
140
|
+
function unavailableMutation() {
|
|
141
|
+
return {
|
|
142
|
+
cart: readCart(),
|
|
143
|
+
persisted: false,
|
|
144
|
+
status: "cart_storage_unavailable"
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
async function mutateCart(mutation, beforePersist) {
|
|
148
|
+
const locks = typeof navigator === "undefined" ? void 0 : navigator.locks;
|
|
149
|
+
if (!storage() || !locks) return unavailableMutation();
|
|
150
|
+
try {
|
|
151
|
+
return await locks.request(CART_MUTATION_LOCK, async () => {
|
|
152
|
+
const latest = readCart();
|
|
153
|
+
const mutated = mutation(latest);
|
|
154
|
+
const proposed = {
|
|
155
|
+
...mutated,
|
|
156
|
+
lines: normalizeCartLines(mutated.lines),
|
|
157
|
+
...mutated.settledAttemptTokens === void 0 && latest.settledAttemptTokens ? { settledAttemptTokens: latest.settledAttemptTokens } : {}
|
|
158
|
+
};
|
|
159
|
+
if (beforePersist) {
|
|
160
|
+
const controller = new AbortController();
|
|
161
|
+
let timer;
|
|
162
|
+
const accepted = await Promise.race([
|
|
163
|
+
beforePersist(proposed, controller.signal).catch(() => false),
|
|
164
|
+
new Promise((resolve) => {
|
|
165
|
+
timer = setTimeout(() => {
|
|
166
|
+
controller.abort();
|
|
167
|
+
resolve(false);
|
|
168
|
+
}, CART_MUTATION_VALIDATION_TIMEOUT_MS);
|
|
169
|
+
})
|
|
170
|
+
]);
|
|
171
|
+
if (timer) clearTimeout(timer);
|
|
172
|
+
if (!accepted) {
|
|
173
|
+
return {
|
|
174
|
+
cart: readCart(),
|
|
175
|
+
persisted: false,
|
|
176
|
+
status: "not_committed"
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return persistCart(proposed);
|
|
181
|
+
});
|
|
182
|
+
} catch {
|
|
183
|
+
return unavailableMutation();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async function withCartLock(operation) {
|
|
187
|
+
const locks = typeof navigator === "undefined" ? void 0 : navigator.locks;
|
|
188
|
+
if (!storage() || !locks)
|
|
189
|
+
return { status: "cart_storage_unavailable", cart: readCart() };
|
|
190
|
+
try {
|
|
191
|
+
return await locks.request(CART_MUTATION_LOCK, async () => {
|
|
192
|
+
const latest = readCart();
|
|
193
|
+
const controller = new AbortController();
|
|
194
|
+
let timer;
|
|
195
|
+
const outcome = await Promise.race([
|
|
196
|
+
operation(latest, controller.signal).then((result) => ({
|
|
197
|
+
completed: true,
|
|
198
|
+
result
|
|
199
|
+
})),
|
|
200
|
+
new Promise((resolve) => {
|
|
201
|
+
timer = setTimeout(() => {
|
|
202
|
+
controller.abort();
|
|
203
|
+
resolve({ completed: false });
|
|
204
|
+
}, CART_MUTATION_VALIDATION_TIMEOUT_MS);
|
|
205
|
+
})
|
|
206
|
+
]);
|
|
207
|
+
if (timer) clearTimeout(timer);
|
|
208
|
+
return outcome.completed ? { status: "completed", cart: latest, result: outcome.result } : { status: "not_completed", cart: latest };
|
|
209
|
+
});
|
|
210
|
+
} catch {
|
|
211
|
+
return { status: "not_completed", cart: readCart() };
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
async function writeCart(cart) {
|
|
215
|
+
return mutateCart(() => cart);
|
|
216
|
+
}
|
|
217
|
+
async function addToCart(variantId, quantity = 1) {
|
|
218
|
+
let status = "added";
|
|
219
|
+
const result = await mutateCart((cart) => {
|
|
220
|
+
const add = Math.min(Math.max(Math.floor(quantity), 1), MAX_QUANTITY);
|
|
221
|
+
const existing = cart.lines.find(
|
|
222
|
+
(line) => line.kind === "retail" && line.variantId === variantId
|
|
223
|
+
);
|
|
224
|
+
if (existing) {
|
|
225
|
+
if (existing.quantity >= MAX_QUANTITY) {
|
|
226
|
+
status = "quantity_limit";
|
|
227
|
+
return cart;
|
|
228
|
+
}
|
|
229
|
+
existing.quantity = Math.min(existing.quantity + add, MAX_QUANTITY);
|
|
230
|
+
} else {
|
|
231
|
+
if (cart.lines.length >= MAX_LINES) {
|
|
232
|
+
status = "line_limit";
|
|
233
|
+
return cart;
|
|
234
|
+
}
|
|
235
|
+
cart.lines.push({
|
|
236
|
+
lineId: newCartLineId(),
|
|
237
|
+
kind: "retail",
|
|
238
|
+
variantId,
|
|
239
|
+
quantity: add
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
return cart;
|
|
243
|
+
});
|
|
244
|
+
return {
|
|
245
|
+
cart: result.cart,
|
|
246
|
+
status: result.status === "cart_storage_unavailable" ? result.status : status
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
async function setCartQuantity(kind, variantId, quantity) {
|
|
250
|
+
const result = await mutateCart((cart) => {
|
|
251
|
+
const next = Math.floor(quantity);
|
|
252
|
+
return {
|
|
253
|
+
v: 1,
|
|
254
|
+
lines: next < 1 ? cart.lines.filter(
|
|
255
|
+
(line) => line.kind !== kind || line.variantId !== variantId
|
|
256
|
+
) : cart.lines.map(
|
|
257
|
+
(line) => line.kind === kind && line.variantId === variantId ? { ...line, quantity: Math.min(next, MAX_QUANTITY) } : line
|
|
258
|
+
)
|
|
259
|
+
};
|
|
260
|
+
});
|
|
261
|
+
return result;
|
|
262
|
+
}
|
|
263
|
+
async function adjustCartQuantity(kind, variantId, delta, maximumBaseline) {
|
|
264
|
+
const result = await mutateCart((cart) => ({
|
|
265
|
+
v: 1,
|
|
266
|
+
lines: cart.lines.flatMap((line) => {
|
|
267
|
+
if (line.kind !== kind || line.variantId !== variantId) return [line];
|
|
268
|
+
const baseline = maximumBaseline === void 0 ? line.quantity : Math.min(line.quantity, Math.max(0, Math.floor(maximumBaseline)));
|
|
269
|
+
const quantity = Math.min(baseline + Math.floor(delta), MAX_QUANTITY);
|
|
270
|
+
return quantity > 0 ? [{ ...line, quantity }] : [];
|
|
271
|
+
})
|
|
272
|
+
}));
|
|
273
|
+
return result;
|
|
274
|
+
}
|
|
275
|
+
async function removeFromCart(variantId, kind) {
|
|
276
|
+
const result = await mutateCart((cart) => ({
|
|
277
|
+
v: 1,
|
|
278
|
+
lines: cart.lines.filter(
|
|
279
|
+
(line) => line.variantId !== variantId || kind && line.kind !== kind
|
|
280
|
+
)
|
|
281
|
+
}));
|
|
282
|
+
return result;
|
|
283
|
+
}
|
|
284
|
+
async function clearCart() {
|
|
285
|
+
return writeCart(emptyCart());
|
|
286
|
+
}
|
|
287
|
+
async function subtractPurchasedCartLines(purchasedLines, attemptToken) {
|
|
288
|
+
const purchased = new Map(
|
|
289
|
+
normalizeCartLines(
|
|
290
|
+
purchasedLines.filter(
|
|
291
|
+
(line) => Boolean(line) && typeof line === "object" && !Array.isArray(line) && cartLineId(line.lineId) !== null
|
|
292
|
+
)
|
|
293
|
+
).map((line) => [line.lineId, line])
|
|
294
|
+
);
|
|
295
|
+
return mutateCart((cart) => {
|
|
296
|
+
if (attemptToken && cart.settledAttemptTokens?.includes(attemptToken))
|
|
297
|
+
return cart;
|
|
298
|
+
return {
|
|
299
|
+
v: 1,
|
|
300
|
+
lines: cart.lines.flatMap((line) => {
|
|
301
|
+
const purchasedLine = purchased.get(line.lineId);
|
|
302
|
+
const purchasedQuantity = purchasedLine?.kind === line.kind && purchasedLine.variantId === line.variantId ? purchasedLine.quantity : 0;
|
|
303
|
+
const quantity = line.quantity - purchasedQuantity;
|
|
304
|
+
return quantity > 0 ? [{ ...line, quantity }] : [];
|
|
305
|
+
}),
|
|
306
|
+
...attemptToken ? {
|
|
307
|
+
settledAttemptTokens: [
|
|
308
|
+
...cart.settledAttemptTokens ?? [],
|
|
309
|
+
attemptToken
|
|
310
|
+
]
|
|
311
|
+
} : {}
|
|
312
|
+
};
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
function cartItemCount(cart = readCart()) {
|
|
316
|
+
return cart.lines.reduce((sum, l) => sum + l.quantity, 0);
|
|
317
|
+
}
|
|
318
|
+
function cartToWireLines(cart) {
|
|
319
|
+
return cart.lines.map((l) => ({
|
|
320
|
+
kind: l.kind,
|
|
321
|
+
variantId: l.variantId,
|
|
322
|
+
quantity: l.quantity
|
|
323
|
+
}));
|
|
324
|
+
}
|
|
325
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
326
|
+
function notify(cart) {
|
|
327
|
+
for (const fn of listeners) {
|
|
328
|
+
try {
|
|
329
|
+
fn(cart);
|
|
330
|
+
} catch {
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
function subscribeToCart(fn) {
|
|
335
|
+
listeners.add(fn);
|
|
336
|
+
const onStorage = (e) => {
|
|
337
|
+
if (e.key !== null && e.key !== CART_STORAGE_KEY) return;
|
|
338
|
+
fn(readCart());
|
|
339
|
+
};
|
|
340
|
+
if (typeof window !== "undefined")
|
|
341
|
+
window.addEventListener("storage", onStorage);
|
|
342
|
+
return () => {
|
|
343
|
+
listeners.delete(fn);
|
|
344
|
+
if (typeof window !== "undefined")
|
|
345
|
+
window.removeEventListener("storage", onStorage);
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
export {
|
|
350
|
+
CART_STORAGE_KEY,
|
|
351
|
+
emptyCart,
|
|
352
|
+
EMPTY_CART,
|
|
353
|
+
normalizeCartLines,
|
|
354
|
+
readCart,
|
|
355
|
+
mutateCart,
|
|
356
|
+
withCartLock,
|
|
357
|
+
writeCart,
|
|
358
|
+
addToCart,
|
|
359
|
+
setCartQuantity,
|
|
360
|
+
adjustCartQuantity,
|
|
361
|
+
removeFromCart,
|
|
362
|
+
clearCart,
|
|
363
|
+
subtractPurchasedCartLines,
|
|
364
|
+
cartItemCount,
|
|
365
|
+
cartToWireLines,
|
|
366
|
+
subscribeToCart
|
|
367
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
encodePortalReturnTarget,
|
|
3
|
+
normalizePortalApiOrigin
|
|
4
|
+
} from "./chunk-FZ4WKWIE.js";
|
|
5
|
+
|
|
6
|
+
// src/store-client.ts
|
|
7
|
+
var STORE_REQUEST_INIT = {
|
|
8
|
+
credentials: "include",
|
|
9
|
+
cache: "no-store"
|
|
10
|
+
};
|
|
11
|
+
async function readResult(response) {
|
|
12
|
+
let body;
|
|
13
|
+
try {
|
|
14
|
+
body = await response.json();
|
|
15
|
+
} catch {
|
|
16
|
+
return response.ok ? { ok: false, status: null, error: null, message: null } : { ok: false, status: response.status, error: null, message: null };
|
|
17
|
+
}
|
|
18
|
+
if (response.ok) return { ok: true, data: body };
|
|
19
|
+
const failure = body;
|
|
20
|
+
return {
|
|
21
|
+
ok: false,
|
|
22
|
+
status: response.status,
|
|
23
|
+
error: typeof failure?.error === "string" ? failure.error : null,
|
|
24
|
+
message: typeof failure?.message === "string" ? failure.message : null
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function createStoreClient(config = {}) {
|
|
28
|
+
const rawOrigin = config.apiOrigin?.trim() ?? "";
|
|
29
|
+
const normalizedOrigin = rawOrigin ? normalizePortalApiOrigin(rawOrigin) : "";
|
|
30
|
+
if (rawOrigin && !normalizedOrigin) {
|
|
31
|
+
console.error("[store] ignoring a malformed store API origin", rawOrigin);
|
|
32
|
+
}
|
|
33
|
+
const apiOrigin = normalizedOrigin ?? "";
|
|
34
|
+
const fetchImpl = config.fetchImpl ?? ((input, init) => globalThis.fetch(input, init));
|
|
35
|
+
const url = (path) => apiOrigin && path.startsWith("/") ? apiOrigin + path : path;
|
|
36
|
+
async function request(path, init) {
|
|
37
|
+
try {
|
|
38
|
+
return await readResult(
|
|
39
|
+
await fetchImpl(url(path), {
|
|
40
|
+
...STORE_REQUEST_INIT,
|
|
41
|
+
...init
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
} catch {
|
|
45
|
+
return { ok: false, status: null, error: null, message: null };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
apiOrigin,
|
|
50
|
+
url,
|
|
51
|
+
get: (path) => request(path, { headers: { accept: "application/json" } }),
|
|
52
|
+
post: (path, body, options) => request(path, {
|
|
53
|
+
signal: options?.signal,
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: {
|
|
56
|
+
accept: "application/json",
|
|
57
|
+
"content-type": "application/json"
|
|
58
|
+
},
|
|
59
|
+
body: JSON.stringify(body ?? {})
|
|
60
|
+
}),
|
|
61
|
+
signInHref(returnPath = "/checkout") {
|
|
62
|
+
if (typeof window === "undefined") return `${apiOrigin}/portal/sign-in`;
|
|
63
|
+
const target = new URL(returnPath, window.location.origin).toString();
|
|
64
|
+
const redirect = `/portal/return?to=${encodePortalReturnTarget(target)}`;
|
|
65
|
+
return `${apiOrigin}/portal/sign-in?redirect=${encodeURIComponent(redirect)}`;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/money.ts
|
|
71
|
+
function formatMoney(value) {
|
|
72
|
+
const n = Number(value);
|
|
73
|
+
if (!Number.isFinite(n)) return value;
|
|
74
|
+
return `$${n.toFixed(2)}`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
createStoreClient,
|
|
79
|
+
formatMoney
|
|
80
|
+
};
|