@usethrottle/checkout-react 1.0.1 → 1.2.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/README.md +54 -2
- package/dist/index.cjs +421 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +154 -1
- package/dist/index.d.ts +154 -1
- package/dist/index.js +425 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -203,10 +203,435 @@ function PaymentEmbed({
|
|
|
203
203
|
}
|
|
204
204
|
);
|
|
205
205
|
}
|
|
206
|
+
|
|
207
|
+
// src/useCartSession.tsx
|
|
208
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useMemo, useState as useState4 } from "react";
|
|
209
|
+
import {
|
|
210
|
+
CartSessionClient
|
|
211
|
+
} from "@usethrottle/cart";
|
|
212
|
+
var DEFAULT_STORAGE_KEY = "throttle.cartSessionId";
|
|
213
|
+
function readStored(key) {
|
|
214
|
+
if (!key || typeof window === "undefined") return null;
|
|
215
|
+
try {
|
|
216
|
+
return window.localStorage.getItem(key);
|
|
217
|
+
} catch {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function writeStored(key, value) {
|
|
222
|
+
if (!key || typeof window === "undefined") return;
|
|
223
|
+
try {
|
|
224
|
+
if (value === null) window.localStorage.removeItem(key);
|
|
225
|
+
else window.localStorage.setItem(key, value);
|
|
226
|
+
} catch {
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function useCartSession(options) {
|
|
230
|
+
const { applicationId, environmentId, quoteToken, baseUrl } = options;
|
|
231
|
+
const storageKey = options.storageKey === void 0 ? DEFAULT_STORAGE_KEY : options.storageKey;
|
|
232
|
+
const [cart, setCart] = useState4(null);
|
|
233
|
+
const [cartSessionId, setCartSessionId] = useState4(null);
|
|
234
|
+
const [loading, setLoading] = useState4(false);
|
|
235
|
+
const [error, setError] = useState4(null);
|
|
236
|
+
const { client, initError } = useMemo(() => {
|
|
237
|
+
try {
|
|
238
|
+
return {
|
|
239
|
+
client: new CartSessionClient({ applicationId, environmentId, quoteToken, baseUrl }),
|
|
240
|
+
initError: null
|
|
241
|
+
};
|
|
242
|
+
} catch (e) {
|
|
243
|
+
return { client: null, initError: e };
|
|
244
|
+
}
|
|
245
|
+
}, [applicationId, environmentId, quoteToken, baseUrl]);
|
|
246
|
+
useEffect3(() => {
|
|
247
|
+
if (initError) setError(initError);
|
|
248
|
+
}, [initError]);
|
|
249
|
+
useEffect3(() => {
|
|
250
|
+
if (!client) return;
|
|
251
|
+
const saved = readStored(storageKey);
|
|
252
|
+
if (!saved) return;
|
|
253
|
+
let cancelled = false;
|
|
254
|
+
client.resume(saved);
|
|
255
|
+
setCartSessionId(saved);
|
|
256
|
+
setLoading(true);
|
|
257
|
+
client.get().then((s) => {
|
|
258
|
+
if (cancelled) return;
|
|
259
|
+
setCart(s.cart);
|
|
260
|
+
}).catch(() => {
|
|
261
|
+
if (cancelled) return;
|
|
262
|
+
writeStored(storageKey, null);
|
|
263
|
+
client.resume("");
|
|
264
|
+
setCartSessionId(null);
|
|
265
|
+
setCart(null);
|
|
266
|
+
}).finally(() => {
|
|
267
|
+
if (!cancelled) setLoading(false);
|
|
268
|
+
});
|
|
269
|
+
return () => {
|
|
270
|
+
cancelled = true;
|
|
271
|
+
};
|
|
272
|
+
}, [client, storageKey]);
|
|
273
|
+
const ensureSession = useCallback3(
|
|
274
|
+
async (input) => {
|
|
275
|
+
if (!client) throw initError ?? new Error("CartSessionClient unavailable");
|
|
276
|
+
if (client.cartSessionId) return;
|
|
277
|
+
const session = await client.create(input ?? {});
|
|
278
|
+
writeStored(storageKey, session.cartSessionId);
|
|
279
|
+
setCartSessionId(session.cartSessionId);
|
|
280
|
+
setCart(session.cart);
|
|
281
|
+
},
|
|
282
|
+
[client, initError, storageKey]
|
|
283
|
+
);
|
|
284
|
+
const run = useCallback3(
|
|
285
|
+
async (fn, opts = {}) => {
|
|
286
|
+
if (!client) {
|
|
287
|
+
setError(initError ?? new Error("CartSessionClient unavailable"));
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
setLoading(true);
|
|
291
|
+
setError(null);
|
|
292
|
+
try {
|
|
293
|
+
if (opts.create) await ensureSession();
|
|
294
|
+
const next = await fn();
|
|
295
|
+
setCart(next);
|
|
296
|
+
} catch (e) {
|
|
297
|
+
setError(e);
|
|
298
|
+
throw e;
|
|
299
|
+
} finally {
|
|
300
|
+
setLoading(false);
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
[client, ensureSession, initError]
|
|
304
|
+
);
|
|
305
|
+
const addItem = useCallback3(
|
|
306
|
+
(input) => run(() => client.addItem(input), { create: true }),
|
|
307
|
+
[client, run]
|
|
308
|
+
);
|
|
309
|
+
const updateItem = useCallback3(
|
|
310
|
+
(itemId, input) => run(() => client.updateItem(itemId, input)),
|
|
311
|
+
[client, run]
|
|
312
|
+
);
|
|
313
|
+
const removeItem = useCallback3((itemId) => run(() => client.removeItem(itemId)), [client, run]);
|
|
314
|
+
const selectShipping = useCallback3(
|
|
315
|
+
(input) => run(() => client.selectShipping(input), { create: true }),
|
|
316
|
+
[client, run]
|
|
317
|
+
);
|
|
318
|
+
const clearShipping = useCallback3(() => run(() => client.clearShipping()), [client, run]);
|
|
319
|
+
const applyDiscount = useCallback3(
|
|
320
|
+
(code) => run(() => client.applyDiscount(code), { create: true }),
|
|
321
|
+
[client, run]
|
|
322
|
+
);
|
|
323
|
+
const removeDiscount = useCallback3(() => run(() => client.removeDiscount()), [client, run]);
|
|
324
|
+
const refresh = useCallback3(async () => {
|
|
325
|
+
if (!client?.cartSessionId) return;
|
|
326
|
+
await run(async () => (await client.get()).cart);
|
|
327
|
+
}, [client, run]);
|
|
328
|
+
const checkout = useCallback3(
|
|
329
|
+
async (input) => {
|
|
330
|
+
if (!client) throw initError ?? new Error("CartSessionClient unavailable");
|
|
331
|
+
setLoading(true);
|
|
332
|
+
setError(null);
|
|
333
|
+
try {
|
|
334
|
+
await ensureSession();
|
|
335
|
+
return await client.checkout(input);
|
|
336
|
+
} catch (e) {
|
|
337
|
+
setError(e);
|
|
338
|
+
throw e;
|
|
339
|
+
} finally {
|
|
340
|
+
setLoading(false);
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
[client, ensureSession, initError]
|
|
344
|
+
);
|
|
345
|
+
const reset = useCallback3(() => {
|
|
346
|
+
writeStored(storageKey, null);
|
|
347
|
+
client?.resume("");
|
|
348
|
+
setCartSessionId(null);
|
|
349
|
+
setCart(null);
|
|
350
|
+
setError(null);
|
|
351
|
+
}, [client, storageKey]);
|
|
352
|
+
return {
|
|
353
|
+
cart,
|
|
354
|
+
cartSessionId,
|
|
355
|
+
loading,
|
|
356
|
+
error,
|
|
357
|
+
addItem,
|
|
358
|
+
updateItem,
|
|
359
|
+
removeItem,
|
|
360
|
+
selectShipping,
|
|
361
|
+
clearShipping,
|
|
362
|
+
applyDiscount,
|
|
363
|
+
removeDiscount,
|
|
364
|
+
checkout,
|
|
365
|
+
refresh,
|
|
366
|
+
reset
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// src/useThrottleCheckout.tsx
|
|
371
|
+
import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef3, useState as useState5 } from "react";
|
|
372
|
+
import {
|
|
373
|
+
CartSessionClient as CartSessionClient2,
|
|
374
|
+
CartNotOpenError,
|
|
375
|
+
CartNotFoundError
|
|
376
|
+
} from "@usethrottle/cart";
|
|
377
|
+
var DEFAULT_STORAGE_KEY2 = "throttle.cartSessionId";
|
|
378
|
+
function readStored2(key) {
|
|
379
|
+
if (!key || typeof window === "undefined") return null;
|
|
380
|
+
try {
|
|
381
|
+
return window.localStorage.getItem(key);
|
|
382
|
+
} catch {
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
function writeStored2(key, value) {
|
|
387
|
+
if (!key || typeof window === "undefined") return;
|
|
388
|
+
try {
|
|
389
|
+
if (value === null) window.localStorage.removeItem(key);
|
|
390
|
+
else window.localStorage.setItem(key, value);
|
|
391
|
+
} catch {
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
function totalsOf(cart) {
|
|
395
|
+
if (!cart) return null;
|
|
396
|
+
return {
|
|
397
|
+
currency: cart.currency,
|
|
398
|
+
subtotal: cart.subtotal,
|
|
399
|
+
discountTotal: cart.discountTotal,
|
|
400
|
+
shippingTotal: cart.shippingTotal,
|
|
401
|
+
taxTotal: cart.taxTotal,
|
|
402
|
+
total: cart.total
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
function useThrottleCheckout(options) {
|
|
406
|
+
const { applicationId, environmentId, quoteToken, baseUrl } = options;
|
|
407
|
+
const autoRecover = options.autoRecover ?? true;
|
|
408
|
+
const storageKey = options.storageKey === void 0 ? DEFAULT_STORAGE_KEY2 : options.storageKey;
|
|
409
|
+
const [cart, setCart] = useState5(null);
|
|
410
|
+
const [cartSessionId, setCartSessionId] = useState5(null);
|
|
411
|
+
const [status, setStatus] = useState5("idle");
|
|
412
|
+
const [error, setError] = useState5(null);
|
|
413
|
+
const cartRef = useRef3(null);
|
|
414
|
+
cartRef.current = cart;
|
|
415
|
+
const { client, initError } = useMemo2(() => {
|
|
416
|
+
try {
|
|
417
|
+
return {
|
|
418
|
+
client: new CartSessionClient2({ applicationId, environmentId, quoteToken, baseUrl }),
|
|
419
|
+
initError: null
|
|
420
|
+
};
|
|
421
|
+
} catch (e) {
|
|
422
|
+
return { client: null, initError: e };
|
|
423
|
+
}
|
|
424
|
+
}, [applicationId, environmentId, quoteToken, baseUrl]);
|
|
425
|
+
useEffect4(() => {
|
|
426
|
+
if (initError) {
|
|
427
|
+
setError(initError);
|
|
428
|
+
setStatus("error");
|
|
429
|
+
}
|
|
430
|
+
}, [initError]);
|
|
431
|
+
useEffect4(() => {
|
|
432
|
+
if (!client) return;
|
|
433
|
+
const saved = readStored2(storageKey);
|
|
434
|
+
if (!saved) return;
|
|
435
|
+
let cancelled = false;
|
|
436
|
+
client.resume(saved);
|
|
437
|
+
setCartSessionId(saved);
|
|
438
|
+
setStatus("loading");
|
|
439
|
+
client.get().then((s) => {
|
|
440
|
+
if (cancelled) return;
|
|
441
|
+
setCart(s.cart);
|
|
442
|
+
setStatus("ready");
|
|
443
|
+
}).catch(() => {
|
|
444
|
+
if (cancelled) return;
|
|
445
|
+
writeStored2(storageKey, null);
|
|
446
|
+
client.resume("");
|
|
447
|
+
setCartSessionId(null);
|
|
448
|
+
setCart(null);
|
|
449
|
+
setStatus("idle");
|
|
450
|
+
});
|
|
451
|
+
return () => {
|
|
452
|
+
cancelled = true;
|
|
453
|
+
};
|
|
454
|
+
}, [client, storageKey]);
|
|
455
|
+
const ensureSession = useCallback4(
|
|
456
|
+
async (input) => {
|
|
457
|
+
if (!client) throw initError ?? new Error("CartSessionClient unavailable");
|
|
458
|
+
if (client.cartSessionId) return;
|
|
459
|
+
const session = await client.create(input ?? {});
|
|
460
|
+
writeStored2(storageKey, session.cartSessionId);
|
|
461
|
+
setCartSessionId(session.cartSessionId);
|
|
462
|
+
setCart(session.cart);
|
|
463
|
+
},
|
|
464
|
+
[client, initError, storageKey]
|
|
465
|
+
);
|
|
466
|
+
const rebuild = useCallback4(async () => {
|
|
467
|
+
if (!client) throw initError ?? new Error("CartSessionClient unavailable");
|
|
468
|
+
const prev = cartRef.current;
|
|
469
|
+
client.resume("");
|
|
470
|
+
setCartSessionId(null);
|
|
471
|
+
const session = await client.create({
|
|
472
|
+
currency: prev?.currency,
|
|
473
|
+
netN: prev?.netN ?? void 0
|
|
474
|
+
});
|
|
475
|
+
writeStored2(storageKey, session.cartSessionId);
|
|
476
|
+
setCartSessionId(session.cartSessionId);
|
|
477
|
+
let next = session.cart;
|
|
478
|
+
for (const item of prev?.lineItems ?? []) {
|
|
479
|
+
next = await client.addItem({
|
|
480
|
+
type: item.type,
|
|
481
|
+
referenceId: item.referenceId ?? void 0,
|
|
482
|
+
name: item.name,
|
|
483
|
+
description: item.description ?? void 0,
|
|
484
|
+
unitPrice: item.unitPrice,
|
|
485
|
+
quantity: item.quantity,
|
|
486
|
+
imageUrl: item.imageUrl ?? void 0,
|
|
487
|
+
metadata: item.metadata
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
const ship = prev?.selectedShipping;
|
|
491
|
+
if (ship) {
|
|
492
|
+
next = await client.selectShipping({
|
|
493
|
+
methodId: ship.methodId,
|
|
494
|
+
displayName: ship.displayName,
|
|
495
|
+
rateAmount: ship.rateAmount,
|
|
496
|
+
currency: ship.currency,
|
|
497
|
+
carrier: ship.carrier ?? void 0,
|
|
498
|
+
serviceCode: ship.serviceCode ?? void 0,
|
|
499
|
+
estimatedDeliveryDays: ship.estimatedDeliveryDays ?? void 0
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
setCart(next);
|
|
503
|
+
return next;
|
|
504
|
+
}, [client, initError, storageKey]);
|
|
505
|
+
const run = useCallback4(
|
|
506
|
+
async (fn, opts = {}) => {
|
|
507
|
+
if (!client) {
|
|
508
|
+
const e = initError ?? new Error("CartSessionClient unavailable");
|
|
509
|
+
setError(e);
|
|
510
|
+
setStatus("error");
|
|
511
|
+
throw e;
|
|
512
|
+
}
|
|
513
|
+
setStatus("loading");
|
|
514
|
+
setError(null);
|
|
515
|
+
try {
|
|
516
|
+
if (opts.create) await ensureSession();
|
|
517
|
+
const result = await fn();
|
|
518
|
+
setStatus("ready");
|
|
519
|
+
return result;
|
|
520
|
+
} catch (e) {
|
|
521
|
+
const stale = e instanceof CartNotOpenError || e instanceof CartNotFoundError;
|
|
522
|
+
if (stale && autoRecover) {
|
|
523
|
+
try {
|
|
524
|
+
setStatus("recovering");
|
|
525
|
+
await rebuild();
|
|
526
|
+
if (opts.retryAfterRecover) {
|
|
527
|
+
const retried = await fn();
|
|
528
|
+
setStatus("ready");
|
|
529
|
+
return retried;
|
|
530
|
+
}
|
|
531
|
+
setStatus("ready");
|
|
532
|
+
const stale2 = new CartNotOpenError({
|
|
533
|
+
message: "Cart was rebuilt after going stale; retry your action against the new cart."
|
|
534
|
+
});
|
|
535
|
+
setError(stale2);
|
|
536
|
+
throw stale2;
|
|
537
|
+
} catch (recoverErr) {
|
|
538
|
+
setError(recoverErr);
|
|
539
|
+
setStatus("error");
|
|
540
|
+
throw recoverErr;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
setError(e);
|
|
544
|
+
setStatus("error");
|
|
545
|
+
throw e;
|
|
546
|
+
}
|
|
547
|
+
},
|
|
548
|
+
[client, ensureSession, initError, autoRecover, rebuild]
|
|
549
|
+
);
|
|
550
|
+
const addItem = useCallback4(
|
|
551
|
+
async (input) => {
|
|
552
|
+
const next = await run(() => client.addItem(input), { create: true, retryAfterRecover: true });
|
|
553
|
+
setCart(next);
|
|
554
|
+
},
|
|
555
|
+
[client, run]
|
|
556
|
+
);
|
|
557
|
+
const updateItem = useCallback4(
|
|
558
|
+
async (itemId, input) => {
|
|
559
|
+
const next = await run(() => client.updateItem(itemId, input), { retryAfterRecover: false });
|
|
560
|
+
setCart(next);
|
|
561
|
+
},
|
|
562
|
+
[client, run]
|
|
563
|
+
);
|
|
564
|
+
const removeItem = useCallback4(
|
|
565
|
+
async (itemId) => {
|
|
566
|
+
const next = await run(() => client.removeItem(itemId), { retryAfterRecover: false });
|
|
567
|
+
setCart(next);
|
|
568
|
+
},
|
|
569
|
+
[client, run]
|
|
570
|
+
);
|
|
571
|
+
const selectMethod = useCallback4(
|
|
572
|
+
async (input) => {
|
|
573
|
+
const next = await run(() => client.selectShipping(input), { create: true, retryAfterRecover: true });
|
|
574
|
+
setCart(next);
|
|
575
|
+
},
|
|
576
|
+
[client, run]
|
|
577
|
+
);
|
|
578
|
+
const clearShipping = useCallback4(async () => {
|
|
579
|
+
const next = await run(() => client.clearShipping(), { retryAfterRecover: true });
|
|
580
|
+
setCart(next);
|
|
581
|
+
}, [client, run]);
|
|
582
|
+
const applyDiscount = useCallback4(
|
|
583
|
+
async (code) => {
|
|
584
|
+
const next = await run(() => client.applyDiscount(code), { create: true, retryAfterRecover: true });
|
|
585
|
+
setCart(next);
|
|
586
|
+
},
|
|
587
|
+
[client, run]
|
|
588
|
+
);
|
|
589
|
+
const removeDiscount = useCallback4(async () => {
|
|
590
|
+
const next = await run(() => client.removeDiscount(), { retryAfterRecover: true });
|
|
591
|
+
setCart(next);
|
|
592
|
+
}, [client, run]);
|
|
593
|
+
const refresh = useCallback4(async () => {
|
|
594
|
+
if (!client?.cartSessionId) return;
|
|
595
|
+
const next = await run(async () => (await client.get()).cart);
|
|
596
|
+
setCart(next);
|
|
597
|
+
}, [client, run]);
|
|
598
|
+
const createSession = useCallback4(
|
|
599
|
+
(input) => run(() => client.checkout(input), { create: true, retryAfterRecover: true }),
|
|
600
|
+
[client, run]
|
|
601
|
+
);
|
|
602
|
+
const reset = useCallback4(() => {
|
|
603
|
+
writeStored2(storageKey, null);
|
|
604
|
+
client?.resume("");
|
|
605
|
+
setCartSessionId(null);
|
|
606
|
+
setCart(null);
|
|
607
|
+
setError(null);
|
|
608
|
+
setStatus("idle");
|
|
609
|
+
}, [client, storageKey]);
|
|
610
|
+
return {
|
|
611
|
+
cart,
|
|
612
|
+
cartSessionId,
|
|
613
|
+
status,
|
|
614
|
+
error,
|
|
615
|
+
selectedMethod: cart?.selectedShipping ?? null,
|
|
616
|
+
totals: totalsOf(cart),
|
|
617
|
+
addItem,
|
|
618
|
+
updateItem,
|
|
619
|
+
removeItem,
|
|
620
|
+
selectMethod,
|
|
621
|
+
clearShipping,
|
|
622
|
+
applyDiscount,
|
|
623
|
+
removeDiscount,
|
|
624
|
+
createSession,
|
|
625
|
+
refresh,
|
|
626
|
+
reset
|
|
627
|
+
};
|
|
628
|
+
}
|
|
206
629
|
export {
|
|
207
630
|
CheckoutEmbed,
|
|
208
631
|
PaymentEmbed,
|
|
209
632
|
CheckoutEmbed as ThrottleCheckout,
|
|
633
|
+
useCartSession,
|
|
634
|
+
useThrottleCheckout,
|
|
210
635
|
useThrottleEvents
|
|
211
636
|
};
|
|
212
637
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/CheckoutEmbed.tsx","../src/useThrottleEvents.ts","../src/useParentCommands.ts","../src/PaymentEmbed.tsx"],"sourcesContent":["import { useCallback, useRef, useState } from 'react';\nimport { useThrottleEvents } from './useThrottleEvents.js';\nimport { useParentCommands } from './useParentCommands.js';\nimport type {\n ThrottleEmbedProps,\n CheckoutEmbedExtraProps,\n ThrottleMessage,\n} from './types.js';\n\nconst DEFAULT_BASE_URL = 'https://checkout.usethrottle.dev';\n\n/**\n * Full-checkout iframe embed. Renders the entire Throttle hosted\n * checkout (address / shipping / payment) inside an iframe and\n * surfaces lifecycle + terminal events through callbacks. The\n * iframe auto-resizes on `throttle.resize` events.\n *\n * `parentOrigin` must match an entry in the merchant's allow-list\n * (`throttle embed-config set --origins ...`). Mismatches render\n * an in-iframe \"Embed not authorized\" panel.\n */\nexport function CheckoutEmbed({\n sessionId,\n parentOrigin,\n baseUrl = DEFAULT_BASE_URL,\n primary,\n logo,\n initialHeight = 600,\n className,\n style,\n submitDisabled,\n onReady,\n onProcessing,\n onSucceeded,\n onFailed,\n onCanceled,\n onStepChanged,\n}: ThrottleEmbedProps & CheckoutEmbedExtraProps) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const expectedOrigin = new URL(baseUrl).origin;\n const [iframeReady, setIframeReady] = useState(false);\n\n const dispatch = useCallback(\n (msg: ThrottleMessage) => {\n switch (msg.type) {\n case 'throttle.ready':\n setIframeReady(true);\n onReady?.();\n break;\n case 'throttle.processing':\n onProcessing?.();\n break;\n case 'throttle.completed':\n onSucceeded?.({\n orderId: msg.orderId,\n paymentId: msg.paymentId,\n ...(msg.subscriptionId !== undefined ? { subscriptionId: msg.subscriptionId } : {}),\n });\n break;\n case 'throttle.error':\n onFailed?.({ code: msg.code, message: msg.message });\n break;\n case 'throttle.cancelled':\n onCanceled?.();\n break;\n case 'throttle.step.changed':\n onStepChanged?.({ step: msg.step });\n break;\n case 'throttle.resize':\n if (iframeRef.current) iframeRef.current.style.height = `${msg.height}px`;\n break;\n }\n },\n [onReady, onProcessing, onSucceeded, onFailed, onCanceled, onStepChanged],\n );\n\n useThrottleEvents({ iframeRef, expectedOrigin, onMessage: dispatch });\n useParentCommands({\n iframeRef,\n targetOrigin: expectedOrigin,\n submitDisabled,\n iframeReady,\n });\n\n const params = new URLSearchParams({ embed: '1', mode: 'checkout-full', parentOrigin });\n if (primary) params.set('primary', primary);\n if (logo) params.set('logo', logo);\n const cleanBase = baseUrl.replace(/\\/$/, '');\n const src = `${cleanBase}/c/${encodeURIComponent(sessionId)}?${params.toString()}`;\n\n return (\n <iframe\n ref={iframeRef}\n src={src}\n className={className}\n style={{ border: 0, width: '100%', minHeight: initialHeight, ...style }}\n allow=\"payment *\"\n title=\"Throttle checkout\"\n />\n );\n}\n","import { useEffect, type RefObject } from 'react';\nimport type { ThrottleMessage } from './types.js';\n\nexport interface UseThrottleEventsOptions {\n iframeRef: RefObject<HTMLIFrameElement | null>;\n /**\n * The Throttle origin (e.g. https://checkout.usethrottle.dev).\n * Strict-equals check against `MessageEvent.origin`. Anything else\n * is silently dropped.\n */\n expectedOrigin: string;\n onMessage: (msg: ThrottleMessage) => void;\n}\n\n/**\n * Subscribe to validated postMessage events from a Throttle iframe.\n *\n * Validation:\n * - event.origin === expectedOrigin (strict string match)\n * - event.source === iframeRef.current.contentWindow (defends against\n * other iframes on the same origin spoofing events)\n * - event.data.source === 'throttle' && event.data.version === 1\n * - event.data.type starts with 'throttle.'\n *\n * Anything failing validation is silently dropped — the parent page\n * may receive postMessages from analytics SDKs, browser extensions,\n * other iframes, etc. We must never throw on those.\n */\nexport function useThrottleEvents({ iframeRef, expectedOrigin, onMessage }: UseThrottleEventsOptions) {\n useEffect(() => {\n function handle(ev: MessageEvent) {\n if (ev.origin !== expectedOrigin) return;\n if (iframeRef.current && ev.source !== iframeRef.current.contentWindow) return;\n const data = ev.data as Partial<ThrottleMessage> | null | undefined;\n if (!data || typeof data !== 'object') return;\n if (data.source !== 'throttle' || data.version !== 1) return;\n if (typeof data.type !== 'string' || !data.type.startsWith('throttle.')) return;\n onMessage(data as ThrottleMessage);\n }\n window.addEventListener('message', handle);\n return () => window.removeEventListener('message', handle);\n }, [iframeRef, expectedOrigin, onMessage]);\n}\n","import { useEffect, useState, type RefObject } from 'react';\nimport type { ThrottleParentMessage } from './types.js';\n\ninterface UseParentCommandsOptions {\n iframeRef: RefObject<HTMLIFrameElement | null>;\n /** The Throttle origin to address messages to. */\n targetOrigin: string;\n /**\n * The current value of `submitDisabled` from the embed props. Posts a\n * `set-submit-disabled` parent command whenever it changes — and once\n * after the iframe reports `throttle.ready` so the iframe sees the\n * intent even if it boots after the prop is already set.\n *\n * `undefined` means the parent never explicitly enabled/disabled — we\n * never post in that case. Backward-compat with embeds that don't\n * pass the prop.\n */\n submitDisabled?: boolean;\n /**\n * Set to `true` once the iframe posts `throttle.ready`. Until then,\n * commands are buffered (we still try to post but the iframe may not\n * have its listener attached yet — and we re-post on ready as a\n * belt-and-braces guard).\n */\n iframeReady: boolean;\n}\n\n/**\n * Post parent → iframe commands when controlled props change. v1.2 adds\n * `set-submit-disabled`; future commands extend the same channel.\n *\n * postMessage is fire-and-forget — we don't wait for an ack from the\n * iframe. The iframe's listener is idempotent (setting the same value\n * twice is a no-op).\n */\nexport function useParentCommands({\n iframeRef,\n targetOrigin,\n submitDisabled,\n iframeReady,\n}: UseParentCommandsOptions) {\n const [lastSent, setLastSent] = useState<boolean | undefined>(undefined);\n\n // Post when the prop value changes OR when the iframe transitions to\n // ready (so the first state lands).\n useEffect(() => {\n if (submitDisabled === undefined) return;\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n // Skip if we already sent this value AND the iframe was already ready\n // — avoids spam on unrelated re-renders.\n if (lastSent === submitDisabled && iframeReady) return;\n if (!iframeReady) return; // Defer until ready\n\n const message: ThrottleParentMessage = {\n source: 'throttle-parent',\n version: 1,\n type: 'set-submit-disabled',\n disabled: submitDisabled,\n };\n win.postMessage(message, targetOrigin);\n setLastSent(submitDisabled);\n }, [iframeRef, targetOrigin, submitDisabled, iframeReady, lastSent]);\n}\n","import { useCallback, useRef, useState } from 'react';\nimport { useThrottleEvents } from './useThrottleEvents.js';\nimport { useParentCommands } from './useParentCommands.js';\nimport type { ThrottleEmbedProps, ThrottleMessage } from './types.js';\n\nconst DEFAULT_BASE_URL = 'https://checkout.usethrottle.dev';\n\n/**\n * Payment-only iframe embed. Renders just the Gr4vy provider iframe\n * (no address / shipping / cart UI). Email is collected by the Gr4vy\n * iframe in proxy-mode sessions. Used when the merchant has built\n * their own checkout UI and only needs Throttle to handle payment\n * authorization + capture.\n *\n * `parentOrigin` must match an entry in the merchant's allow-list.\n * The iframe auto-resizes on `throttle.resize` events.\n */\nexport function PaymentEmbed({\n sessionId,\n parentOrigin,\n baseUrl = DEFAULT_BASE_URL,\n primary,\n logo,\n initialHeight = 480,\n className,\n style,\n submitDisabled,\n onReady,\n onProcessing,\n onSucceeded,\n onFailed,\n onCanceled,\n}: ThrottleEmbedProps) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const expectedOrigin = new URL(baseUrl).origin;\n const [iframeReady, setIframeReady] = useState(false);\n\n const dispatch = useCallback(\n (msg: ThrottleMessage) => {\n switch (msg.type) {\n case 'throttle.ready':\n setIframeReady(true);\n onReady?.();\n break;\n case 'throttle.processing':\n onProcessing?.();\n break;\n case 'throttle.completed':\n onSucceeded?.({\n orderId: msg.orderId,\n paymentId: msg.paymentId,\n ...(msg.subscriptionId !== undefined ? { subscriptionId: msg.subscriptionId } : {}),\n });\n break;\n case 'throttle.error':\n onFailed?.({ code: msg.code, message: msg.message });\n break;\n case 'throttle.cancelled':\n onCanceled?.();\n break;\n case 'throttle.resize':\n if (iframeRef.current) iframeRef.current.style.height = `${msg.height}px`;\n break;\n }\n },\n [onReady, onProcessing, onSucceeded, onFailed, onCanceled],\n );\n\n useThrottleEvents({ iframeRef, expectedOrigin, onMessage: dispatch });\n useParentCommands({\n iframeRef,\n targetOrigin: expectedOrigin,\n submitDisabled,\n iframeReady,\n });\n\n const params = new URLSearchParams({ embed: '1', mode: 'payment-only', parentOrigin });\n if (primary) params.set('primary', primary);\n if (logo) params.set('logo', logo);\n const cleanBase = baseUrl.replace(/\\/$/, '');\n const src = `${cleanBase}/c/${encodeURIComponent(sessionId)}?${params.toString()}`;\n\n return (\n <iframe\n ref={iframeRef}\n src={src}\n className={className}\n style={{ border: 0, width: '100%', minHeight: initialHeight, ...style }}\n allow=\"payment *\"\n title=\"Throttle payment\"\n />\n );\n}\n"],"mappings":"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","names":["useState","useEffect","useState","useCallback","useRef","useState","jsx","DEFAULT_BASE_URL","useRef","useState","useCallback"]}
|
|
1
|
+
{"version":3,"sources":["../src/CheckoutEmbed.tsx","../src/useThrottleEvents.ts","../src/useParentCommands.ts","../src/PaymentEmbed.tsx","../src/useCartSession.tsx","../src/useThrottleCheckout.tsx"],"sourcesContent":["import { useCallback, useRef, useState } from 'react';\nimport { useThrottleEvents } from './useThrottleEvents.js';\nimport { useParentCommands } from './useParentCommands.js';\nimport type {\n ThrottleEmbedProps,\n CheckoutEmbedExtraProps,\n ThrottleMessage,\n} from './types.js';\n\nconst DEFAULT_BASE_URL = 'https://checkout.usethrottle.dev';\n\n/**\n * Full-checkout iframe embed. Renders the entire Throttle hosted\n * checkout (address / shipping / payment) inside an iframe and\n * surfaces lifecycle + terminal events through callbacks. The\n * iframe auto-resizes on `throttle.resize` events.\n *\n * `parentOrigin` must match an entry in the merchant's allow-list\n * (`throttle embed-config set --origins ...`). Mismatches render\n * an in-iframe \"Embed not authorized\" panel.\n */\nexport function CheckoutEmbed({\n sessionId,\n parentOrigin,\n baseUrl = DEFAULT_BASE_URL,\n primary,\n logo,\n initialHeight = 600,\n className,\n style,\n submitDisabled,\n onReady,\n onProcessing,\n onSucceeded,\n onFailed,\n onCanceled,\n onStepChanged,\n}: ThrottleEmbedProps & CheckoutEmbedExtraProps) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const expectedOrigin = new URL(baseUrl).origin;\n const [iframeReady, setIframeReady] = useState(false);\n\n const dispatch = useCallback(\n (msg: ThrottleMessage) => {\n switch (msg.type) {\n case 'throttle.ready':\n setIframeReady(true);\n onReady?.();\n break;\n case 'throttle.processing':\n onProcessing?.();\n break;\n case 'throttle.completed':\n onSucceeded?.({\n orderId: msg.orderId,\n paymentId: msg.paymentId,\n ...(msg.subscriptionId !== undefined ? { subscriptionId: msg.subscriptionId } : {}),\n });\n break;\n case 'throttle.error':\n onFailed?.({ code: msg.code, message: msg.message });\n break;\n case 'throttle.cancelled':\n onCanceled?.();\n break;\n case 'throttle.step.changed':\n onStepChanged?.({ step: msg.step });\n break;\n case 'throttle.resize':\n if (iframeRef.current) iframeRef.current.style.height = `${msg.height}px`;\n break;\n }\n },\n [onReady, onProcessing, onSucceeded, onFailed, onCanceled, onStepChanged],\n );\n\n useThrottleEvents({ iframeRef, expectedOrigin, onMessage: dispatch });\n useParentCommands({\n iframeRef,\n targetOrigin: expectedOrigin,\n submitDisabled,\n iframeReady,\n });\n\n const params = new URLSearchParams({ embed: '1', mode: 'checkout-full', parentOrigin });\n if (primary) params.set('primary', primary);\n if (logo) params.set('logo', logo);\n const cleanBase = baseUrl.replace(/\\/$/, '');\n const src = `${cleanBase}/c/${encodeURIComponent(sessionId)}?${params.toString()}`;\n\n return (\n <iframe\n ref={iframeRef}\n src={src}\n className={className}\n style={{ border: 0, width: '100%', minHeight: initialHeight, ...style }}\n allow=\"payment *\"\n title=\"Throttle checkout\"\n />\n );\n}\n","import { useEffect, type RefObject } from 'react';\nimport type { ThrottleMessage } from './types.js';\n\nexport interface UseThrottleEventsOptions {\n iframeRef: RefObject<HTMLIFrameElement | null>;\n /**\n * The Throttle origin (e.g. https://checkout.usethrottle.dev).\n * Strict-equals check against `MessageEvent.origin`. Anything else\n * is silently dropped.\n */\n expectedOrigin: string;\n onMessage: (msg: ThrottleMessage) => void;\n}\n\n/**\n * Subscribe to validated postMessage events from a Throttle iframe.\n *\n * Validation:\n * - event.origin === expectedOrigin (strict string match)\n * - event.source === iframeRef.current.contentWindow (defends against\n * other iframes on the same origin spoofing events)\n * - event.data.source === 'throttle' && event.data.version === 1\n * - event.data.type starts with 'throttle.'\n *\n * Anything failing validation is silently dropped — the parent page\n * may receive postMessages from analytics SDKs, browser extensions,\n * other iframes, etc. We must never throw on those.\n */\nexport function useThrottleEvents({ iframeRef, expectedOrigin, onMessage }: UseThrottleEventsOptions) {\n useEffect(() => {\n function handle(ev: MessageEvent) {\n if (ev.origin !== expectedOrigin) return;\n if (iframeRef.current && ev.source !== iframeRef.current.contentWindow) return;\n const data = ev.data as Partial<ThrottleMessage> | null | undefined;\n if (!data || typeof data !== 'object') return;\n if (data.source !== 'throttle' || data.version !== 1) return;\n if (typeof data.type !== 'string' || !data.type.startsWith('throttle.')) return;\n onMessage(data as ThrottleMessage);\n }\n window.addEventListener('message', handle);\n return () => window.removeEventListener('message', handle);\n }, [iframeRef, expectedOrigin, onMessage]);\n}\n","import { useEffect, useState, type RefObject } from 'react';\nimport type { ThrottleParentMessage } from './types.js';\n\ninterface UseParentCommandsOptions {\n iframeRef: RefObject<HTMLIFrameElement | null>;\n /** The Throttle origin to address messages to. */\n targetOrigin: string;\n /**\n * The current value of `submitDisabled` from the embed props. Posts a\n * `set-submit-disabled` parent command whenever it changes — and once\n * after the iframe reports `throttle.ready` so the iframe sees the\n * intent even if it boots after the prop is already set.\n *\n * `undefined` means the parent never explicitly enabled/disabled — we\n * never post in that case. Backward-compat with embeds that don't\n * pass the prop.\n */\n submitDisabled?: boolean;\n /**\n * Set to `true` once the iframe posts `throttle.ready`. Until then,\n * commands are buffered (we still try to post but the iframe may not\n * have its listener attached yet — and we re-post on ready as a\n * belt-and-braces guard).\n */\n iframeReady: boolean;\n}\n\n/**\n * Post parent → iframe commands when controlled props change. v1.2 adds\n * `set-submit-disabled`; future commands extend the same channel.\n *\n * postMessage is fire-and-forget — we don't wait for an ack from the\n * iframe. The iframe's listener is idempotent (setting the same value\n * twice is a no-op).\n */\nexport function useParentCommands({\n iframeRef,\n targetOrigin,\n submitDisabled,\n iframeReady,\n}: UseParentCommandsOptions) {\n const [lastSent, setLastSent] = useState<boolean | undefined>(undefined);\n\n // Post when the prop value changes OR when the iframe transitions to\n // ready (so the first state lands).\n useEffect(() => {\n if (submitDisabled === undefined) return;\n const win = iframeRef.current?.contentWindow;\n if (!win) return;\n // Skip if we already sent this value AND the iframe was already ready\n // — avoids spam on unrelated re-renders.\n if (lastSent === submitDisabled && iframeReady) return;\n if (!iframeReady) return; // Defer until ready\n\n const message: ThrottleParentMessage = {\n source: 'throttle-parent',\n version: 1,\n type: 'set-submit-disabled',\n disabled: submitDisabled,\n };\n win.postMessage(message, targetOrigin);\n setLastSent(submitDisabled);\n }, [iframeRef, targetOrigin, submitDisabled, iframeReady, lastSent]);\n}\n","import { useCallback, useRef, useState } from 'react';\nimport { useThrottleEvents } from './useThrottleEvents.js';\nimport { useParentCommands } from './useParentCommands.js';\nimport type { ThrottleEmbedProps, ThrottleMessage } from './types.js';\n\nconst DEFAULT_BASE_URL = 'https://checkout.usethrottle.dev';\n\n/**\n * Payment-only iframe embed. Renders just the Gr4vy provider iframe\n * (no address / shipping / cart UI). Email is collected by the Gr4vy\n * iframe in proxy-mode sessions. Used when the merchant has built\n * their own checkout UI and only needs Throttle to handle payment\n * authorization + capture.\n *\n * `parentOrigin` must match an entry in the merchant's allow-list.\n * The iframe auto-resizes on `throttle.resize` events.\n */\nexport function PaymentEmbed({\n sessionId,\n parentOrigin,\n baseUrl = DEFAULT_BASE_URL,\n primary,\n logo,\n initialHeight = 480,\n className,\n style,\n submitDisabled,\n onReady,\n onProcessing,\n onSucceeded,\n onFailed,\n onCanceled,\n}: ThrottleEmbedProps) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const expectedOrigin = new URL(baseUrl).origin;\n const [iframeReady, setIframeReady] = useState(false);\n\n const dispatch = useCallback(\n (msg: ThrottleMessage) => {\n switch (msg.type) {\n case 'throttle.ready':\n setIframeReady(true);\n onReady?.();\n break;\n case 'throttle.processing':\n onProcessing?.();\n break;\n case 'throttle.completed':\n onSucceeded?.({\n orderId: msg.orderId,\n paymentId: msg.paymentId,\n ...(msg.subscriptionId !== undefined ? { subscriptionId: msg.subscriptionId } : {}),\n });\n break;\n case 'throttle.error':\n onFailed?.({ code: msg.code, message: msg.message });\n break;\n case 'throttle.cancelled':\n onCanceled?.();\n break;\n case 'throttle.resize':\n if (iframeRef.current) iframeRef.current.style.height = `${msg.height}px`;\n break;\n }\n },\n [onReady, onProcessing, onSucceeded, onFailed, onCanceled],\n );\n\n useThrottleEvents({ iframeRef, expectedOrigin, onMessage: dispatch });\n useParentCommands({\n iframeRef,\n targetOrigin: expectedOrigin,\n submitDisabled,\n iframeReady,\n });\n\n const params = new URLSearchParams({ embed: '1', mode: 'payment-only', parentOrigin });\n if (primary) params.set('primary', primary);\n if (logo) params.set('logo', logo);\n const cleanBase = baseUrl.replace(/\\/$/, '');\n const src = `${cleanBase}/c/${encodeURIComponent(sessionId)}?${params.toString()}`;\n\n return (\n <iframe\n ref={iframeRef}\n src={src}\n className={className}\n style={{ border: 0, width: '100%', minHeight: initialHeight, ...style }}\n allow=\"payment *\"\n title=\"Throttle payment\"\n />\n );\n}\n","import { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n CartSessionClient,\n type Cart,\n type AddLineItemInput,\n type UpdateLineItemInput,\n type SelectShippingInput,\n type CreateCartSessionInput,\n type CheckoutHandoffInput,\n type CheckoutHandoff,\n} from '@usethrottle/cart';\n\nconst DEFAULT_STORAGE_KEY = 'throttle.cartSessionId';\n\nexport interface UseCartSessionOptions {\n /** Application UUID. */\n applicationId: string;\n /** Workspace environment UUID the publishable token was minted for. */\n environmentId: string;\n /** Publishable storefront quote token (`pk_…`). */\n quoteToken: string;\n baseUrl?: string;\n /**\n * localStorage key for persisting the session id across page loads. Default\n * `'throttle.cartSessionId'`. Pass `null` to disable persistence (in-memory\n * only).\n */\n storageKey?: string | null;\n}\n\nexport interface UseCartSessionResult {\n /** Current cart snapshot, or null before the first item / resume. */\n cart: Cart | null;\n /** Current opaque session id, or null before the first item. */\n cartSessionId: string | null;\n /** True while a request is in flight. */\n loading: boolean;\n /** Last error, or null. */\n error: Error | null;\n addItem: (input: AddLineItemInput) => Promise<void>;\n updateItem: (itemId: string, input: UpdateLineItemInput) => Promise<void>;\n removeItem: (itemId: string) => Promise<void>;\n selectShipping: (input: SelectShippingInput) => Promise<void>;\n clearShipping: () => Promise<void>;\n applyDiscount: (code: string) => Promise<void>;\n removeDiscount: () => Promise<void>;\n /** Hand off to checkout. Returns the hand-off (redirect the buyer to `checkoutUrl`). */\n checkout: (input: CheckoutHandoffInput) => Promise<CheckoutHandoff>;\n /** Re-fetch the current cart. */\n refresh: () => Promise<void>;\n /** Forget the current session (a new cart is created on the next item). */\n reset: () => void;\n}\n\nfunction readStored(key: string | null | undefined): string | null {\n if (!key || typeof window === 'undefined') return null;\n try {\n return window.localStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\nfunction writeStored(key: string | null | undefined, value: string | null): void {\n if (!key || typeof window === 'undefined') return;\n try {\n if (value === null) window.localStorage.removeItem(key);\n else window.localStorage.setItem(key, value);\n } catch {\n /* ignore quota / privacy-mode errors */\n }\n}\n\n/**\n * React hook for backend-less cart ownership. Wraps {@link CartSessionClient}:\n * creates the Throttle cart lazily on the first `addItem` (so empty carts\n * aren't created on every page load), persists the session id to localStorage,\n * and resumes it on the next visit. Mutations update reactive `cart` state.\n *\n * ```tsx\n * const cart = useCartSession({ applicationId, environmentId, quoteToken });\n * <button onClick={() => cart.addItem({ name: 'Widget', unitPrice: 2999, quantity: 1 })}>Add</button>\n * <button onClick={async () => {\n * const { checkoutUrl } = await cart.checkout({ returnUrl, cancelUrl });\n * window.location.href = checkoutUrl;\n * }}>Checkout</button>\n * ```\n */\nexport function useCartSession(options: UseCartSessionOptions): UseCartSessionResult {\n const { applicationId, environmentId, quoteToken, baseUrl } = options;\n const storageKey = options.storageKey === undefined ? DEFAULT_STORAGE_KEY : options.storageKey;\n\n const [cart, setCart] = useState<Cart | null>(null);\n const [cartSessionId, setCartSessionId] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Stable client across renders for a given config; construction validates the\n // token, so capture any constructor error instead of throwing during render.\n const { client, initError } = useMemo(() => {\n try {\n return {\n client: new CartSessionClient({ applicationId, environmentId, quoteToken, baseUrl }),\n initError: null as Error | null,\n };\n } catch (e) {\n return { client: null as CartSessionClient | null, initError: e as Error };\n }\n }, [applicationId, environmentId, quoteToken, baseUrl]);\n\n useEffect(() => {\n if (initError) setError(initError);\n }, [initError]);\n\n // Resume a persisted session on mount (and whenever the client identity changes).\n useEffect(() => {\n if (!client) return;\n const saved = readStored(storageKey);\n if (!saved) return;\n let cancelled = false;\n client.resume(saved);\n setCartSessionId(saved);\n setLoading(true);\n client\n .get()\n .then((s) => {\n if (cancelled) return;\n setCart(s.cart);\n })\n .catch(() => {\n // Expired / unknown / origin-rejected → drop the stale id and start fresh.\n if (cancelled) return;\n writeStored(storageKey, null);\n client.resume('');\n setCartSessionId(null);\n setCart(null);\n })\n .finally(() => {\n if (!cancelled) setLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [client, storageKey]);\n\n const ensureSession = useCallback(\n async (input?: CreateCartSessionInput): Promise<void> => {\n if (!client) throw initError ?? new Error('CartSessionClient unavailable');\n if (client.cartSessionId) return;\n const session = await client.create(input ?? {});\n writeStored(storageKey, session.cartSessionId);\n setCartSessionId(session.cartSessionId);\n setCart(session.cart);\n },\n [client, initError, storageKey],\n );\n\n /** Run a mutation that returns the updated cart, managing loading/error + creating the session first. */\n const run = useCallback(\n async (fn: () => Promise<Cart>, opts: { create?: boolean } = {}): Promise<void> => {\n if (!client) {\n setError(initError ?? new Error('CartSessionClient unavailable'));\n return;\n }\n setLoading(true);\n setError(null);\n try {\n if (opts.create) await ensureSession();\n const next = await fn();\n setCart(next);\n } catch (e) {\n setError(e as Error);\n throw e;\n } finally {\n setLoading(false);\n }\n },\n [client, ensureSession, initError],\n );\n\n const addItem = useCallback(\n (input: AddLineItemInput) => run(() => client!.addItem(input), { create: true }),\n [client, run],\n );\n const updateItem = useCallback(\n (itemId: string, input: UpdateLineItemInput) => run(() => client!.updateItem(itemId, input)),\n [client, run],\n );\n const removeItem = useCallback((itemId: string) => run(() => client!.removeItem(itemId)), [client, run]);\n const selectShipping = useCallback(\n (input: SelectShippingInput) => run(() => client!.selectShipping(input), { create: true }),\n [client, run],\n );\n const clearShipping = useCallback(() => run(() => client!.clearShipping()), [client, run]);\n const applyDiscount = useCallback(\n (code: string) => run(() => client!.applyDiscount(code), { create: true }),\n [client, run],\n );\n const removeDiscount = useCallback(() => run(() => client!.removeDiscount()), [client, run]);\n const refresh = useCallback(async () => {\n if (!client?.cartSessionId) return;\n await run(async () => (await client.get()).cart);\n }, [client, run]);\n\n const checkout = useCallback(\n async (input: CheckoutHandoffInput): Promise<CheckoutHandoff> => {\n if (!client) throw initError ?? new Error('CartSessionClient unavailable');\n setLoading(true);\n setError(null);\n try {\n await ensureSession();\n return await client.checkout(input);\n } catch (e) {\n setError(e as Error);\n throw e;\n } finally {\n setLoading(false);\n }\n },\n [client, ensureSession, initError],\n );\n\n const reset = useCallback(() => {\n writeStored(storageKey, null);\n client?.resume('');\n setCartSessionId(null);\n setCart(null);\n setError(null);\n }, [client, storageKey]);\n\n return {\n cart,\n cartSessionId,\n loading,\n error,\n addItem,\n updateItem,\n removeItem,\n selectShipping,\n clearShipping,\n applyDiscount,\n removeDiscount,\n checkout,\n refresh,\n reset,\n };\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n CartSessionClient,\n CartNotOpenError,\n CartNotFoundError,\n type Cart,\n type SelectedShipping,\n type AddLineItemInput,\n type UpdateLineItemInput,\n type SelectShippingInput,\n type CreateCartSessionInput,\n type CheckoutHandoffInput,\n type CheckoutHandoff,\n} from '@usethrottle/cart';\n\nconst DEFAULT_STORAGE_KEY = 'throttle.cartSessionId';\n\n/**\n * Lifecycle status for the checkout orchestration.\n * - `idle` — no work in flight, no cart yet\n * - `loading` — a request is in flight\n * - `recovering` — the cart went stale (converted/abandoned); rebuilding from the\n * last-known line items into a fresh session\n * - `ready` — a cart is present and no request is in flight\n * - `error` — the last operation failed (see `error`)\n */\nexport type ThrottleCheckoutStatus = 'idle' | 'loading' | 'recovering' | 'ready' | 'error';\n\nexport interface CheckoutTotals {\n currency: string;\n subtotal: number;\n discountTotal: number;\n shippingTotal: number;\n taxTotal: number;\n total: number;\n}\n\nexport interface UseThrottleCheckoutOptions {\n /** Application UUID. */\n applicationId: string;\n /** Workspace environment UUID the publishable token was minted for. */\n environmentId: string;\n /** Publishable storefront quote token (`pk_…`). */\n quoteToken: string;\n baseUrl?: string;\n /**\n * localStorage key for persisting the cart session id across page loads.\n * Default `'throttle.cartSessionId'`. Pass `null` to disable persistence.\n */\n storageKey?: string | null;\n /**\n * Auto-recover from a stale cart. When a mutation fails with\n * {@link CartNotOpenError} (the cart was converted by a completed order, or\n * abandoned), the hook starts a fresh session, re-adds the last-known line\n * items and re-selects the shipping method, then retries the operation once.\n * Default `true`. Set `false` to surface {@link CartNotOpenError} instead.\n */\n autoRecover?: boolean;\n}\n\nexport interface UseThrottleCheckoutResult {\n /** Current cart snapshot, or null before the first item / resume. */\n cart: Cart | null;\n /** Current cart session id, or null before the first item. */\n cartSessionId: string | null;\n /** Coarse lifecycle status — drive your UI off this rather than `cart === null`. */\n status: ThrottleCheckoutStatus;\n /** Last error, or null. */\n error: Error | null;\n /** The selected shipping method, bound to the cart (never a shadow copy). */\n selectedMethod: SelectedShipping | null;\n /** Live totals, bound to the cart. Null before a cart exists. */\n totals: CheckoutTotals | null;\n addItem: (input: AddLineItemInput) => Promise<void>;\n updateItem: (itemId: string, input: UpdateLineItemInput) => Promise<void>;\n removeItem: (itemId: string) => Promise<void>;\n /** Lock a shipping method. One call — the returned cart carries recomputed totals. */\n selectMethod: (input: SelectShippingInput) => Promise<void>;\n clearShipping: () => Promise<void>;\n applyDiscount: (code: string) => Promise<void>;\n removeDiscount: () => Promise<void>;\n /**\n * Hand off to checkout. Returns the hand-off — use `checkoutSessionId` with\n * `<PaymentEmbed sessionId={…}>` (or redirect the buyer to `checkoutUrl`).\n */\n createSession: (input: CheckoutHandoffInput) => Promise<CheckoutHandoff>;\n /** Re-fetch the current cart. */\n refresh: () => Promise<void>;\n /** Forget the current session (a new cart is created on the next item). */\n reset: () => void;\n}\n\nfunction readStored(key: string | null | undefined): string | null {\n if (!key || typeof window === 'undefined') return null;\n try {\n return window.localStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\nfunction writeStored(key: string | null | undefined, value: string | null): void {\n if (!key || typeof window === 'undefined') return;\n try {\n if (value === null) window.localStorage.removeItem(key);\n else window.localStorage.setItem(key, value);\n } catch {\n /* ignore quota / privacy-mode errors */\n }\n}\n\nfunction totalsOf(cart: Cart | null): CheckoutTotals | null {\n if (!cart) return null;\n return {\n currency: cart.currency,\n subtotal: cart.subtotal,\n discountTotal: cart.discountTotal,\n shippingTotal: cart.shippingTotal,\n taxTotal: cart.taxTotal,\n total: cart.total,\n };\n}\n\n/**\n * Orchestrates a backend-less storefront checkout on top of\n * {@link CartSessionClient}, bundling the pieces every storefront otherwise\n * re-implements:\n *\n * - **Cart as source of truth** — `selectedMethod` and `totals` are read straight\n * off the cart; there is no shadow copy to drift.\n * - **One-call shipping select** — `selectMethod` locks the method and returns the\n * cart with recomputed totals in a single round trip.\n * - **Stale-cart recovery** — a {@link CartNotOpenError} (cart converted by a\n * completed order, or abandoned) transparently rebuilds a fresh session from\n * the last-known line items + shipping and retries (`status === 'recovering'`).\n * - **Session handoff** — `createSession` returns the `checkoutSessionId` for\n * `<PaymentEmbed>`.\n *\n * Address collection is handled inside the checkout embed (the hosted/full\n * checkout collects shipping/billing), so this hook intentionally does not write\n * addresses to the cart.\n *\n * ```tsx\n * const { addItem, selectMethod, totals, createSession, status } =\n * useThrottleCheckout({ applicationId, environmentId, quoteToken });\n * ```\n */\nexport function useThrottleCheckout(\n options: UseThrottleCheckoutOptions,\n): UseThrottleCheckoutResult {\n const { applicationId, environmentId, quoteToken, baseUrl } = options;\n const autoRecover = options.autoRecover ?? true;\n const storageKey = options.storageKey === undefined ? DEFAULT_STORAGE_KEY : options.storageKey;\n\n const [cart, setCart] = useState<Cart | null>(null);\n const [cartSessionId, setCartSessionId] = useState<string | null>(null);\n const [status, setStatus] = useState<ThrottleCheckoutStatus>('idle');\n const [error, setError] = useState<Error | null>(null);\n\n // Keep the latest cart in a ref so recovery can read the last-known line items\n // without threading it through every callback's dependency list.\n const cartRef = useRef<Cart | null>(null);\n cartRef.current = cart;\n\n const { client, initError } = useMemo(() => {\n try {\n return {\n client: new CartSessionClient({ applicationId, environmentId, quoteToken, baseUrl }),\n initError: null as Error | null,\n };\n } catch (e) {\n return { client: null as CartSessionClient | null, initError: e as Error };\n }\n }, [applicationId, environmentId, quoteToken, baseUrl]);\n\n useEffect(() => {\n if (initError) {\n setError(initError);\n setStatus('error');\n }\n }, [initError]);\n\n // Resume a persisted session on mount.\n useEffect(() => {\n if (!client) return;\n const saved = readStored(storageKey);\n if (!saved) return;\n let cancelled = false;\n client.resume(saved);\n setCartSessionId(saved);\n setStatus('loading');\n client\n .get()\n .then((s) => {\n if (cancelled) return;\n setCart(s.cart);\n setStatus('ready');\n })\n .catch(() => {\n if (cancelled) return;\n writeStored(storageKey, null);\n client.resume('');\n setCartSessionId(null);\n setCart(null);\n setStatus('idle');\n });\n return () => {\n cancelled = true;\n };\n }, [client, storageKey]);\n\n const ensureSession = useCallback(\n async (input?: CreateCartSessionInput): Promise<void> => {\n if (!client) throw initError ?? new Error('CartSessionClient unavailable');\n if (client.cartSessionId) return;\n const session = await client.create(input ?? {});\n writeStored(storageKey, session.cartSessionId);\n setCartSessionId(session.cartSessionId);\n setCart(session.cart);\n },\n [client, initError, storageKey],\n );\n\n /**\n * Rebuild a fresh session from the last-known cart so a stale cart doesn't\n * strand the buyer. Re-adds line items and re-selects shipping, then returns\n * the rebuilt cart.\n */\n const rebuild = useCallback(async (): Promise<Cart> => {\n if (!client) throw initError ?? new Error('CartSessionClient unavailable');\n const prev = cartRef.current;\n // Drop the stale session and create a new one.\n client.resume('');\n setCartSessionId(null);\n const session = await client.create({\n currency: prev?.currency,\n netN: prev?.netN ?? undefined,\n });\n writeStored(storageKey, session.cartSessionId);\n setCartSessionId(session.cartSessionId);\n let next = session.cart;\n for (const item of prev?.lineItems ?? []) {\n next = await client.addItem({\n type: item.type,\n referenceId: item.referenceId ?? undefined,\n name: item.name,\n description: item.description ?? undefined,\n unitPrice: item.unitPrice,\n quantity: item.quantity,\n imageUrl: item.imageUrl ?? undefined,\n metadata: item.metadata,\n });\n }\n const ship = prev?.selectedShipping;\n if (ship) {\n next = await client.selectShipping({\n methodId: ship.methodId,\n displayName: ship.displayName,\n rateAmount: ship.rateAmount,\n currency: ship.currency,\n carrier: ship.carrier ?? undefined,\n serviceCode: ship.serviceCode ?? undefined,\n estimatedDeliveryDays: ship.estimatedDeliveryDays ?? undefined,\n });\n }\n setCart(next);\n return next;\n }, [client, initError, storageKey]);\n\n /**\n * Run a cart op with loading/error bookkeeping. On a stale-cart error, rebuild\n * (when `autoRecover`) and — for forward-progress ops (`retryAfterRecover`) —\n * retry once against the rebuilt session. Item-id-specific ops set\n * `retryAfterRecover: false` because the id no longer exists after rebuild.\n */\n const run = useCallback(\n async <T,>(\n fn: () => Promise<T>,\n opts: { create?: boolean; retryAfterRecover?: boolean } = {},\n ): Promise<T> => {\n if (!client) {\n const e = initError ?? new Error('CartSessionClient unavailable');\n setError(e);\n setStatus('error');\n throw e;\n }\n setStatus('loading');\n setError(null);\n try {\n if (opts.create) await ensureSession();\n const result = await fn();\n setStatus('ready');\n return result;\n } catch (e) {\n const stale = e instanceof CartNotOpenError || e instanceof CartNotFoundError;\n if (stale && autoRecover) {\n try {\n setStatus('recovering');\n await rebuild();\n if (opts.retryAfterRecover) {\n const retried = await fn();\n setStatus('ready');\n return retried;\n }\n // Rebuild-only: the original op targeted a now-gone id. Surface the\n // rebuilt cart and let the caller reconcile against fresh state.\n setStatus('ready');\n const stale2 = new CartNotOpenError({\n message: 'Cart was rebuilt after going stale; retry your action against the new cart.',\n });\n setError(stale2);\n throw stale2;\n } catch (recoverErr) {\n setError(recoverErr as Error);\n setStatus('error');\n throw recoverErr;\n }\n }\n setError(e as Error);\n setStatus('error');\n throw e;\n }\n },\n [client, ensureSession, initError, autoRecover, rebuild],\n );\n\n const addItem = useCallback(\n async (input: AddLineItemInput) => {\n const next = await run(() => client!.addItem(input), { create: true, retryAfterRecover: true });\n setCart(next);\n },\n [client, run],\n );\n const updateItem = useCallback(\n async (itemId: string, input: UpdateLineItemInput) => {\n const next = await run(() => client!.updateItem(itemId, input), { retryAfterRecover: false });\n setCart(next);\n },\n [client, run],\n );\n const removeItem = useCallback(\n async (itemId: string) => {\n const next = await run(() => client!.removeItem(itemId), { retryAfterRecover: false });\n setCart(next);\n },\n [client, run],\n );\n const selectMethod = useCallback(\n async (input: SelectShippingInput) => {\n const next = await run(() => client!.selectShipping(input), { create: true, retryAfterRecover: true });\n setCart(next);\n },\n [client, run],\n );\n const clearShipping = useCallback(async () => {\n const next = await run(() => client!.clearShipping(), { retryAfterRecover: true });\n setCart(next);\n }, [client, run]);\n const applyDiscount = useCallback(\n async (code: string) => {\n const next = await run(() => client!.applyDiscount(code), { create: true, retryAfterRecover: true });\n setCart(next);\n },\n [client, run],\n );\n const removeDiscount = useCallback(async () => {\n const next = await run(() => client!.removeDiscount(), { retryAfterRecover: true });\n setCart(next);\n }, [client, run]);\n\n const refresh = useCallback(async () => {\n if (!client?.cartSessionId) return;\n const next = await run(async () => (await client.get()).cart);\n setCart(next);\n }, [client, run]);\n\n const createSession = useCallback(\n (input: CheckoutHandoffInput): Promise<CheckoutHandoff> =>\n run(() => client!.checkout(input), { create: true, retryAfterRecover: true }),\n [client, run],\n );\n\n const reset = useCallback(() => {\n writeStored(storageKey, null);\n client?.resume('');\n setCartSessionId(null);\n setCart(null);\n setError(null);\n setStatus('idle');\n }, [client, storageKey]);\n\n return {\n cart,\n cartSessionId,\n status,\n error,\n selectedMethod: cart?.selectedShipping ?? null,\n totals: totalsOf(cart),\n addItem,\n updateItem,\n removeItem,\n selectMethod,\n clearShipping,\n applyDiscount,\n removeDiscount,\n createSession,\n refresh,\n reset,\n };\n}\n"],"mappings":"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","names":["useState","useEffect","useState","useCallback","useRef","useState","jsx","DEFAULT_BASE_URL","useRef","useState","useCallback","useCallback","useEffect","useState","useCallback","useEffect","useMemo","useRef","useState","CartSessionClient","DEFAULT_STORAGE_KEY","readStored","writeStored"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usethrottle/checkout-react",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "React component for embedded Throttle checkout",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -34,6 +34,9 @@
|
|
|
34
34
|
"publishConfig": {
|
|
35
35
|
"access": "public"
|
|
36
36
|
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@usethrottle/cart": "^3.6.0"
|
|
39
|
+
},
|
|
37
40
|
"scripts": {
|
|
38
41
|
"build": "tsup",
|
|
39
42
|
"dev": "tsup --watch",
|