@openrails/billing-ui 0.234.0 → 0.235.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +39 -2
  2. package/README.md +18 -14
  3. package/dist/account/account-billing.d.ts +6 -3
  4. package/dist/account/change-card-dialog.d.ts +5 -2
  5. package/dist/account/payment-methods-panel.d.ts +6 -3
  6. package/dist/client/client.d.ts +28 -17
  7. package/dist/client/errors.d.ts +1 -4
  8. package/dist/client/generated/error-codes.d.ts +1 -1
  9. package/dist/client/generated/routes.d.ts +42 -28
  10. package/dist/client/generated/wire.d.ts +100 -35
  11. package/dist/client/index.d.ts +2 -2
  12. package/dist/client/types.d.ts +42 -12
  13. package/dist/{client-CWX6QpLa.js → client-BpzCZes3.js} +45 -34
  14. package/dist/client-BpzCZes3.js.map +1 -0
  15. package/dist/client.js +1 -1
  16. package/dist/{config-DZ97SQG2.js → config-qLcHvK0Q.js} +13 -13
  17. package/dist/config-qLcHvK0Q.js.map +1 -0
  18. package/dist/i18n/context.d.ts +1 -1
  19. package/dist/i18n/messages.d.ts +1 -1
  20. package/dist/index.js +184 -177
  21. package/dist/index.js.map +1 -1
  22. package/dist/locales/de.js +5 -4
  23. package/dist/locales/de.js.map +1 -1
  24. package/dist/locales/en.d.ts +5 -4
  25. package/dist/locales/en.js +5 -4
  26. package/dist/locales/en.js.map +1 -1
  27. package/dist/locales/es.js +5 -4
  28. package/dist/locales/es.js.map +1 -1
  29. package/dist/locales/ja.js +5 -4
  30. package/dist/locales/ja.js.map +1 -1
  31. package/dist/locales/ko.js +5 -4
  32. package/dist/locales/ko.js.map +1 -1
  33. package/dist/locales/zh.js +5 -4
  34. package/dist/locales/zh.js.map +1 -1
  35. package/dist/react/context.d.ts +6 -5
  36. package/dist/react/hooks.d.ts +10 -10
  37. package/dist/react.js +1 -1
  38. package/dist/styles.css +1 -1
  39. package/package.json +2 -2
  40. package/dist/client-CWX6QpLa.js.map +0 -1
  41. package/dist/config-DZ97SQG2.js.map +0 -1
@@ -342,6 +342,7 @@ var P = e.string().refine(i, "amount must be an int64 string"), F = e.string(),
342
342
  id: e.string(),
343
343
  key: e.string(),
344
344
  revision: e.number().int().nonnegative().optional(),
345
+ version: e.number().int().nonnegative().optional(),
345
346
  product_id: e.string(),
346
347
  archived: e.boolean(),
347
348
  unit_amount: P,
@@ -395,7 +396,9 @@ var P = e.string().refine(i, "amount must be an int64 string"), F = e.string(),
395
396
  rail: e.string().nullish(),
396
397
  product_id: e.string().nullish(),
397
398
  price_id: e.string().nullish(),
399
+ quantity: e.number().nullish(),
398
400
  psp_id: e.string().nullish(),
401
+ collection_policy: e.string().nullish(),
399
402
  payment_method_id: e.string().nullish(),
400
403
  started_at: F.nullish(),
401
404
  ended_at: F.nullish(),
@@ -455,7 +458,7 @@ var P = e.string().refine(i, "amount must be an int64 string"), F = e.string(),
455
458
  id: e.string(),
456
459
  display_name: e.string().nullish()
457
460
  })).nullish(),
458
- collection_currencies: e.array(e.string()).nullish(),
461
+ default_currencies: e.array(e.string()).nullish(),
459
462
  created_at: F.nullish()
460
463
  }), ye = e.object({
461
464
  id: e.string(),
@@ -506,7 +509,7 @@ var P = e.string().refine(i, "amount must be an int64 string"), F = e.string(),
506
509
  }), Se = e.object({
507
510
  id: e.string(),
508
511
  balances: e.array(xe),
509
- collection_payment_methods: e.array(e.object({
512
+ default_payment_methods: e.array(e.object({
510
513
  currency: e.string(),
511
514
  payment_method_id: e.string()
512
515
  })),
@@ -532,8 +535,8 @@ var P = e.string().refine(i, "amount must be an int64 string"), F = e.string(),
532
535
  decimals: e.number(),
533
536
  minor_decimals: e.number().nullish()
534
537
  }), we = e.object({
535
- action: e.string(),
536
538
  price_id: e.string(),
539
+ quantity: e.number().nullish(),
537
540
  rail: e.string().nullish(),
538
541
  currency: e.string(),
539
542
  amount_due_now: P,
@@ -544,9 +547,9 @@ var P = e.string().refine(i, "amount must be an int64 string"), F = e.string(),
544
547
  message: e.string().nullish()
545
548
  }), Te = e.object({
546
549
  status: e.string(),
547
- action: e.string().nullish(),
548
550
  effective: e.string().nullish(),
549
551
  price_id: e.string().nullish(),
552
+ quantity: e.number().nullish(),
550
553
  subscription_id: e.string().nullish(),
551
554
  next_action: U.nullish(),
552
555
  delayed_start: F.nullish(),
@@ -594,27 +597,34 @@ var P = e.string().refine(i, "amount must be an int64 string"), F = e.string(),
594
597
  })).nullish().transform((e) => e ?? [])
595
598
  }).nullish()
596
599
  }), ke = e.object({
600
+ provider: e.string(),
601
+ site_key: e.string(),
602
+ script_url: e.string(),
603
+ action: e.string(),
604
+ token_header: e.string()
605
+ }), Ae = e.object({
597
606
  capabilities: e.object({
598
607
  route_groups: e.record(e.string(), e.boolean()),
599
608
  features: e.record(e.string(), e.boolean())
600
609
  }),
601
610
  currencies: e.array(Ce).nullish().transform((e) => e ?? []),
602
- payment: Oe.nullish()
611
+ payment: Oe.nullish(),
612
+ captcha: ke.nullish()
603
613
  }), J = e.object({
604
614
  id: e.string(),
605
615
  status: e.string(),
606
616
  client_secret: e.string().nullish(),
607
617
  payment_method_id: e.string().nullish()
608
- }), Ae = e.object({ client_secret: e.string().nullish() }), je = e.object({
618
+ }), je = e.object({ client_secret: e.string().nullish() }), Y = e.object({
609
619
  id: e.string().startsWith("ocs_"),
610
620
  url: e.string().url().nullish(),
611
621
  expires_at: F
612
- }), Y = class extends Error {
622
+ }), X = class extends Error {
613
623
  constructor(e = "The wallet request was declined.") {
614
624
  super(e), this.name = "WalletRejectedError";
615
625
  }
616
- }, Me = 4, Ne = 500, X = (e) => e?.type === "solana_sign_transactions" && !!e.transactions?.length;
617
- async function Pe(e, t) {
626
+ }, Me = 4, Ne = 500, Pe = (e) => e?.type === "solana_sign_transactions" && !!e.transactions?.length;
627
+ async function Fe(e, t) {
618
628
  let n = "";
619
629
  for (let r of e.transactions ?? []) {
620
630
  try {
@@ -627,9 +637,9 @@ async function Pe(e, t) {
627
637
  if (!n) throw O("wallet_no_signature", "The wallet returned no signature.");
628
638
  return n;
629
639
  }
630
- var Fe = 2e3, Z = 300;
631
- function Ie(e) {
632
- let t = Le(e.headers.get("Retry-After"));
640
+ var Ie = 2e3, Z = 300;
641
+ function Le(e) {
642
+ let t = Re(e.headers.get("Retry-After"));
633
643
  switch (e.status) {
634
644
  case 429: return t;
635
645
  case 503: return t ?? Z;
@@ -638,7 +648,7 @@ function Ie(e) {
638
648
  default: return null;
639
649
  }
640
650
  }
641
- function Le(e) {
651
+ function Re(e) {
642
652
  if (!e) return null;
643
653
  if (/^\d+$/.test(e.trim())) return Number(e.trim()) * 1e3;
644
654
  let t = Date.parse(e);
@@ -655,8 +665,8 @@ function Q(e, t) {
655
665
  t?.addEventListener("abort", a, { once: !0 });
656
666
  });
657
667
  }
658
- function Re(e = {}) {
659
- let t = (e.baseUrl ?? "/billing/v1").replace(/\/+$/, ""), n = e.fetch ?? ((e, t) => fetch(e, t)), r = ze({
668
+ function ze(e = {}) {
669
+ let t = (e.baseUrl ?? "/billing/v1").replace(/\/+$/, ""), n = e.fetch ?? ((e, t) => fetch(e, t)), r = Be({
660
670
  ...A,
661
671
  ...e.currencies
662
672
  });
@@ -693,7 +703,7 @@ function Re(e = {}) {
693
703
  continue;
694
704
  }
695
705
  if (a.ok) return a;
696
- let o = Ie(a);
706
+ let o = Le(a);
697
707
  if (e >= u || o === null || d + o > 2e3) throw await k(a);
698
708
  await a.body?.cancel().catch(() => void 0), d += await Q(o, r.signal);
699
709
  }
@@ -748,18 +758,22 @@ function Re(e = {}) {
748
758
  body: { payment_method_id: t }
749
759
  });
750
760
  },
751
- previewTierChange(e, t, n) {
752
- return o(we, `/me/subscriptions/${s(e)}/change-tier/preview`, {
761
+ previewSubscriptionChange(e, t, n) {
762
+ return o(we, `/me/subscriptions/${s(e)}/change/preview`, {
753
763
  method: "POST",
754
- body: { price_id: t },
764
+ body: {
765
+ price_id: t.priceId,
766
+ quantity: t.quantity
767
+ },
755
768
  signal: n
756
769
  });
757
770
  },
758
- changeTier(e, t) {
759
- return o(Te, `/me/subscriptions/${s(e)}/change-tier`, {
771
+ changeSubscription(e, t) {
772
+ return o(Te, `/me/subscriptions/${s(e)}/change`, {
760
773
  method: "POST",
761
774
  body: {
762
775
  price_id: t.priceId,
776
+ quantity: t.quantity,
763
777
  signature: t.signature
764
778
  },
765
779
  headers: { "Idempotency-Key": t.idempotencyKey }
@@ -797,7 +811,7 @@ function Re(e = {}) {
797
811
  });
798
812
  },
799
813
  getPaymentAuthentication(e) {
800
- return o(Ae, `/me/payment-operations/${s(e)}/authentication`);
814
+ return o(je, `/me/payment-operations/${s(e)}/authentication`);
801
815
  },
802
816
  async confirmPaymentAuthentication(e) {
803
817
  await a(`/me/payment-operations/${s(e)}/authentication/confirm`, {
@@ -808,13 +822,10 @@ function Re(e = {}) {
808
822
  async removePaymentMethod(e) {
809
823
  return (await a(`/me/payment-methods/${s(e)}`, { method: "DELETE" })).status === 202 ? "pending" : "removed";
810
824
  },
811
- async setCollectionPaymentMethod(e) {
812
- await a("/me/collection-payment-method", {
825
+ async setDefaultPaymentMethod(e) {
826
+ await a(`/me/default-payment-methods/${s(e.currency.toUpperCase())}`, {
813
827
  method: "PUT",
814
- body: {
815
- currency: e.currency.toUpperCase(),
816
- payment_method_id: e.paymentMethodId
817
- }
828
+ body: { payment_method_id: e.paymentMethodId }
818
829
  });
819
830
  },
820
831
  listPayments(e = {}) {
@@ -848,7 +859,7 @@ function Re(e = {}) {
848
859
  });
849
860
  },
850
861
  createCheckoutSession(e) {
851
- return !e.priceKey == !e.priceId || !!e.priceKey != !!e.productKey ? Promise.reject(O("invalid_request", "Pass priceId, or both productKey and priceKey.")) : o(je, "/me/checkout-sessions", {
862
+ return !e.priceKey == !e.priceId || !!e.priceKey != !!e.productKey ? Promise.reject(O("invalid_request", "Pass priceId, or both productKey and priceKey.")) : o(Y, "/me/checkout-sessions", {
852
863
  method: "POST",
853
864
  body: {
854
865
  price_key: e.priceKey,
@@ -892,7 +903,7 @@ function Re(e = {}) {
892
903
  };
893
904
  },
894
905
  getConfig(e) {
895
- return o(ke, "/config", {
906
+ return o(Ae, "/config", {
896
907
  signal: e,
897
908
  anonymous: !0
898
909
  });
@@ -910,11 +921,11 @@ function Re(e = {}) {
910
921
  currencies: r
911
922
  };
912
923
  }
913
- function ze(e) {
924
+ function Be(e) {
914
925
  return Object.fromEntries(Object.entries(e).map(([e, t]) => [e.toUpperCase(), t]));
915
926
  }
916
- var $ = (e) => e instanceof Y || e instanceof Error && e.name === "WalletRejectedError" || e instanceof E && e.code === "wallet_rejected";
927
+ var $ = (e) => e instanceof X || e instanceof Error && e.name === "WalletRejectedError" || e instanceof E && e.code === "wallet_rejected";
917
928
  //#endregion
918
- export { ne as A, i as B, ie as C, w as D, C as E, h as F, o as I, u as L, _ as M, y as N, g as O, x as P, d as R, k as S, S as T, le as _, Re as a, re as b, Pe as c, ce as d, N as f, me as g, j as h, Y as i, T as j, b as k, pe as l, M as m, Me as n, X as o, oe as p, Fe as r, $ as s, Ne as t, fe as u, E as v, m as w, O as x, D as y, f as z };
929
+ export { ne as A, i as B, ie as C, w as D, C as E, h as F, o as I, u as L, _ as M, y as N, g as O, x as P, d as R, k as S, S as T, le as _, ze as a, re as b, Fe as c, ce as d, N as f, me as g, j as h, X as i, T as j, b as k, pe as l, M as m, Me as n, Pe as o, oe as p, Ie as r, $ as s, Ne as t, fe as u, E as v, m as w, O as x, D as y, f as z };
919
930
 
920
- //# sourceMappingURL=client-CWX6QpLa.js.map
931
+ //# sourceMappingURL=client-BpzCZes3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-BpzCZes3.js","names":[],"sources":["../src/lib/money.ts","../src/types.ts","../src/client/errors.ts","../src/client/generated/currencies.ts","../src/psp.ts","../src/client/types.ts","../src/client/client.ts"],"sourcesContent":["// Exact money. Every amount OpenRails serves is a signed int64 decimal string\n// of the plan currency's native unit, at plan.unit_decimals (the currency\n// registry's scale). Amounts are scaled with BigInt, never a JS number; only\n// the exact major-unit decimal reaches Intl.\n\n// Amount is an int64 decimal string, e.g. \"99000000\" (99 USD at 6 decimals).\nexport type Amount = string\n\nconst INT64_MIN = -(1n << 63n)\nconst INT64_MAX = (1n << 63n) - 1n\nexport const MAX_UNIT_DECIMALS = 18\n\n// amountUnits parses an exact int64 decimal string, or null.\nexport function amountUnits(amount: unknown): bigint | null {\n if (typeof amount !== \"string\" || !/^-?\\d{1,19}$/.test(amount)) return null\n const value = BigInt(amount)\n return value < INT64_MIN || value > INT64_MAX ? null : value\n}\n\nexport function isAmount(value: unknown): value is Amount {\n return amountUnits(value) !== null\n}\n\nexport function isUnitDecimals(value: unknown): value is number {\n return (\n typeof value === \"number\" &&\n Number.isInteger(value) &&\n value >= 0 &&\n value <= MAX_UNIT_DECIMALS\n )\n}\n\n// addAmounts sums exact amounts; null when an input or the sum leaves int64.\nexport function addAmounts(...amounts: Amount[]): Amount | null {\n let total = 0n\n for (const amount of amounts) {\n const units = amountUnits(amount)\n if (units === null) return null\n total += units\n }\n return total < INT64_MIN || total > INT64_MAX ? null : total.toString()\n}\n\n// Intl.NumberFormat formats a decimal string exactly only since ECMA-402 2023\n// (Chrome/Edge 106, Firefox 116, Safari 15.4); older engines coerce it through\n// Number. Probed once with 2^53 + 1, which a Number cannot hold.\nexport const intlFormatsDecimalStringsExactly: boolean = (() => {\n try {\n return (\n new Intl.NumberFormat(\"en\", { useGrouping: false }).format(\n \"9007199254740993\" as `${number}`\n ) === \"9007199254740993\"\n )\n } catch {\n return false\n }\n})()\n\n// Below 10^15 native units a Number-coerced decimal still rounds back to the\n// exact digits at every registry scale; from 10^15 the coerced value can differ\n// in the last digit, so a legacy engine refuses instead of misformatting.\nconst LEGACY_EXACT_UNITS = 10n ** 15n\n\nfunction decimalFromUnits(value: bigint, decimals: number): string {\n const absolute = value < 0n ? -value : value\n const scale = 10n ** BigInt(decimals)\n const fraction = (absolute % scale)\n .toString()\n .padStart(decimals, \"0\")\n .replace(/0+$/, \"\")\n return `${value < 0n ? \"-\" : \"\"}${absolute / scale}${fraction ? `.${fraction}` : \"\"}`\n}\n\n// amountToDecimal renders native units as the exact major-unit decimal with\n// trailing zeros trimmed (\"99000000\" at 6 -> \"99\", \"1234567\" -> \"1.234567\"),\n// or null when the amount or scale is invalid.\nexport function amountToDecimal(\n amount: Amount,\n decimals: number\n): string | null {\n const units = amountUnits(amount)\n if (units === null || !isUnitDecimals(decimals)) return null\n return decimalFromUnits(units, decimals)\n}\n\n// decimalToAmount parses a major-unit decimal exactly (\"100.25\" at 6 ->\n// \"100250000\"). Excess precision, scientific notation and int64 overflow\n// are refused; input is never rounded or converted through a JS number.\nexport function decimalToAmount(\n decimal: string,\n decimals: number\n): Amount | null {\n if (!isUnitDecimals(decimals) || decimal.length > 40) return null\n const match = /^(-?)(\\d+)(?:\\.(\\d+))?$/.exec(decimal)\n if (!match) return null\n const fraction = match[3] ?? \"\"\n if (fraction.length > decimals) return null\n const units =\n BigInt(match[2]) * 10n ** BigInt(decimals) +\n BigInt(fraction.padEnd(decimals, \"0\") || \"0\")\n const signed = match[1] ? -units : units\n return signed < INT64_MIN || signed > INT64_MAX ? null : signed.toString()\n}\n\n// formatAmount renders an exact amount in its currency for the buyer. It never\n// passes money through a JS number; an amount it cannot show exactly is\n// refused with a visible notice rather than a rounded figure.\nexport function formatAmount(\n amount: Amount | null | undefined,\n currency: string,\n decimals: number,\n locale?: string\n): string {\n const code = currency.trim().toUpperCase()\n const units = amountUnits(amount)\n if (units === null || !isUnitDecimals(decimals))\n return `${code} amount exceeds the exact display range`\n if (\n !intlFormatsDecimalStringsExactly &&\n (units >= LEGACY_EXACT_UNITS || units <= -LEGACY_EXACT_UNITS)\n )\n return `${code} amount exceeds this browser's exact display range`\n const decimal = decimalFromUnits(units, decimals) as `${number}`\n try {\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency: code,\n maximumFractionDigits: decimals,\n }).format(decimal)\n } catch {\n return `${decimal} ${code}`\n }\n}\n","// Wire types for the checkout session surface, validated at runtime with zod\n// so a drifting API fails loudly at the boundary instead of rendering garbage.\n// OpenRails serves the session (GET /v1/checkout-sessions/{id}) and pins its\n// shape in testdata/wire/checkout_session.json; src/types.test.ts decodes a copy.\nimport { z } from \"zod\"\n\nimport { isAmount, isUnitDecimals, MAX_UNIT_DECIMALS } from \"./lib/money\"\n\n// optional reads a field OpenRails always sends, null when empty, as\n// undefined.\nconst optional = <T extends z.ZodType>(schema: T) =>\n schema\n .nullish()\n .transform((value) => value ?? undefined)\n .optional()\n\n// Money is an exact signed int64 decimal string of the plan currency's native\n// unit (\"99000000\" is 99 USD at unit_decimals 6). A JSON number is refused:\n// it cannot carry every int64 and a scale must never be assumed.\nexport const amountSchema = z\n .string()\n .refine(isAmount, \"amount must be an int64 decimal string\")\n\n// The currency's scale from OpenRails' currency registry\n// (billing.LookupCurrency / GET /v1/config).\nexport const unitDecimalsSchema = z\n .number()\n .refine(\n isUnitDecimals,\n `unit_decimals must be an integer from 0 to ${MAX_UNIT_DECIMALS}`\n )\n\nconst httpsURLSchema = z\n .string()\n .url()\n .refine((value) => {\n try {\n const parsed = new URL(value)\n return (\n parsed.protocol === \"https:\" && !parsed.username && !parsed.password\n )\n } catch {\n return false\n }\n }, \"redirect URL must be HTTPS\")\n\nconst returnURLSchema = z\n .string()\n .url()\n .refine((value) => {\n try {\n const parsed = new URL(value)\n return (\n (parsed.protocol === \"https:\" || parsed.protocol === \"http:\") &&\n !parsed.username &&\n !parsed.password\n )\n } catch {\n return false\n }\n }, \"return URL must be HTTP(S)\")\n\nexport const checkoutSessionStatusSchema = z.enum([\n \"created\",\n \"requires_action\",\n \"processing\",\n \"succeeded\",\n \"failed\",\n \"blocked\",\n \"expired\",\n \"canceled\",\n])\nexport type CheckoutSessionStatus = z.infer<typeof checkoutSessionStatusSchema>\n\n// A definite decline, normalized by OpenRails. `field` places the message\n// next to the card field it concerns (\"\" = the card as a whole).\nexport const paymentFailureSchema = z.object({\n reason: z.string(),\n message: z.string(),\n field: z.string().nullish(),\n})\nexport type PaymentFailure = z.infer<typeof paymentFailureSchema>\n\n// The accepted payment operation; `requires_action` sessions authenticate it.\nexport const checkoutOperationSchema = z.object({\n id: z.string(),\n status: z.string(),\n})\n\nexport const paymentOptionSchema = z.object({\n id: z.string().min(1),\n /** The PSP the option pays on; saving a Stripe Elements card names it. */\n psp_id: optional(z.string()),\n rail: z.string(),\n mode: z.enum([\"one_off\", \"subscription\"]),\n // card: the PSP takes cards on OpenRails itself (card_entry: server); the\n // page posts the card and loads no gateway script.\n driver: z.enum([\n \"collect_js\",\n \"card\",\n \"stripe_elements\",\n \"redirect\",\n \"solana_pay\",\n ]),\n /** The PSP's checkout key; saving a new card names it. */\n psp_key: optional(z.string()),\n // Browser-safe rail config (nmi: Collect.js tokenization_key +\n // tokenization_url; stripe: publishable_key; driver card: none).\n public_config: optional(z.record(z.string(), z.string())),\n})\nexport type PaymentOption = z.infer<typeof paymentOptionSchema>\n\n// The step a payment awaits: Stripe's or CCBill's page (an https URL, opened\n// in the top window), or a Solana Pay link shown as a QR code.\nexport const nextActionSchema = z.discriminatedUnion(\"type\", [\n z.object({ type: z.literal(\"redirect_to_url\"), url: httpsURLSchema }),\n z.object({\n type: z.literal(\"solana_pay\"),\n url: z.string().startsWith(\"solana:\"),\n }),\n])\nexport type NextAction = z.infer<typeof nextActionSchema>\n\n// A card the session's customer has already stored with this merchant. Display\n// data only — paying with one sends its id, which OpenRails resolves.\nexport const savedPaymentMethodSchema = z.object({\n id: z.string(),\n option_id: z.string(),\n rail: z.string(),\n card: z\n .object({\n brand: z.string().nullish(),\n last4: z.string().nullish(),\n exp_month: z.number().nullish(),\n exp_year: z.number().nullish(),\n })\n .nullish(),\n})\nexport type SavedPaymentMethod = z.infer<typeof savedPaymentMethodSchema>\n\n// Amounts are in the plan's currency at the plan's unit_decimals.\nexport const checkoutLineItemSchema = z.object({\n label: z.string(),\n sublabel: optional(z.string()),\n amount: amountSchema,\n})\nexport type CheckoutLineItem = z.infer<typeof checkoutLineItemSchema>\n\nexport const checkoutPlanSchema = z.object({\n auto_renew: z.boolean(),\n display_name: z.string(),\n unit_amount: amountSchema,\n currency: z.string().min(1),\n unit_decimals: unitDecimalsSchema,\n billing_interval_hours: optional(z.number()),\n access_duration_hours: optional(z.number()),\n})\nexport type CheckoutPlan = z.infer<typeof checkoutPlanSchema>\n\nexport const checkoutSessionSchema = z.object({\n id: z.string(),\n status: checkoutSessionStatusSchema,\n merchant: z.object({ display_name: z.string() }),\n plan: checkoutPlanSchema,\n line_items: optional(z.array(checkoutLineItemSchema)),\n tax: optional(amountSchema),\n due_today: optional(amountSchema),\n options: z.array(paymentOptionSchema),\n saved_methods: optional(z.array(savedPaymentMethodSchema)),\n next_action: nextActionSchema.nullish(),\n payment_id: optional(z.string()),\n subscription_id: optional(z.string()),\n failure_message: optional(z.string()),\n failure: paymentFailureSchema.nullish(),\n operation: checkoutOperationSchema.nullish(),\n // Lets the page's host redirect on success.\n success_url: optional(returnURLSchema),\n // The origin of the app that framed the payment page: the only origin the\n // page exchanges frame messages with.\n embed_origin: optional(z.string().url()),\n expires_at: optional(z.string()),\n})\nexport type CheckoutSession = z.infer<typeof checkoutSessionSchema>\n\nexport const payRequestSchema = z.object({\n option_id: z.string(),\n payment_token: z.string().optional(),\n payment_method_id: z.string().optional(),\n // A new card for a rail whose driver is card; never beside payment_token.\n card: z\n .object({\n number: z.string(),\n exp_month: z.number(),\n exp_year: z.number(),\n cvc: z.string(),\n })\n .optional(),\n // A new card's billing identity; the compact card form sends the name,\n // postal code and country.\n billing_details: z\n .object({\n name: z.string().optional(),\n email: z.string().optional(),\n phone: z.string().optional(),\n address: z\n .object({\n line1: z.string().optional(),\n line2: z.string().optional(),\n city: z.string().optional(),\n state: z.string().optional(),\n postal_code: z.string().optional(),\n country: z.string().optional(),\n })\n .optional(),\n })\n .optional(),\n token_symbol: z.string().optional(),\n})\nexport type PayRequest = z.infer<typeof payRequestSchema>\n\nexport const payResultSchema = z.object({\n status: checkoutSessionStatusSchema,\n next_action: nextActionSchema.nullish(),\n /** The card payment to authenticate when status is requires_action. */\n operation: checkoutOperationSchema.nullish(),\n payment_id: optional(z.string()),\n subscription_id: optional(z.string()),\n failure_message: optional(z.string()),\n failure: paymentFailureSchema.nullish(),\n})\nexport type PayResult = z.infer<typeof payResultSchema>\n\n// The lifecycle phases the Checkout component moves through. Superset of\n// session statuses: load/ready concerns are the component's, not the wire's.\nexport type CheckoutPhase =\n | \"loading\"\n | \"ready\"\n | \"processing\"\n | \"succeeded\"\n | \"failed\"\n | \"blocked\"\n | \"expired\"\n | \"unavailable\"\n | \"error\"\n","// Mirrors OpenRails internal/api.ErrorResponse:\n// {\"error\":{\"type\",\"code\",\"message\",\"request_id?\",\"param?\",\"metadata?\"}}.\nexport interface BillingErrorBody {\n type: string\n code: string\n message: string\n request_id?: string\n param?: string\n metadata?: Record<string, unknown>\n}\n\n// Local codes: network_error, invalid_response, unknown_error, and the wallet\n// codes a wallet next action raises (wallet_rejected, wallet_no_signature,\n// wallet_required).\nexport class BillingError extends Error {\n readonly status: number\n readonly type: string\n readonly code: string\n readonly param?: string\n readonly requestId?: string\n readonly metadata: Record<string, unknown>\n\n constructor(status: number, body: BillingErrorBody) {\n super(body.message)\n this.name = \"BillingError\"\n this.status = status\n this.type = body.type\n this.code = body.code\n this.param = body.param\n this.requestId = body.request_id\n this.metadata = body.metadata ?? {}\n }\n}\n\nexport const isBillingError = (value: unknown): value is BillingError =>\n value instanceof BillingError\n\n/** A server failure (HTTP 5xx) from any client or host source that carries a numeric `status`. */\nexport const isServerError = (value: unknown): boolean => {\n const status = (value as { status?: unknown } | null)?.status\n return typeof status === \"number\" && status >= 500 && status < 600\n}\n\nexport function localError(code: string, message: string): BillingError {\n return new BillingError(0, { type: \"local\", code, message })\n}\n\nexport async function readBillingError(res: Response): Promise<BillingError> {\n let body: unknown\n try {\n body = await res.json()\n } catch {\n body = undefined\n }\n const err = (body as { error?: unknown } | undefined)?.error\n if (err && typeof err === \"object\") {\n const e = err as Partial<BillingErrorBody>\n if (typeof e.code === \"string\" && e.code) {\n return new BillingError(res.status, {\n type: typeof e.type === \"string\" ? e.type : \"\",\n code: e.code,\n message: typeof e.message === \"string\" ? e.message : e.code,\n request_id:\n typeof e.request_id === \"string\"\n ? e.request_id\n : (res.headers.get(\"X-Request-ID\") ?? undefined),\n param: typeof e.param === \"string\" ? e.param : undefined,\n metadata:\n e.metadata && typeof e.metadata === \"object\" ? e.metadata : undefined,\n })\n }\n }\n return new BillingError(res.status, {\n type: res.status >= 500 ? \"api_error\" : \"\",\n code:\n typeof err === \"string\" && err\n ? err\n : res.status >= 500\n ? \"server_error\"\n : \"unknown_error\",\n message: `HTTP ${res.status}`,\n })\n}\n\n// Normalizes anything a client call can throw into a BillingError.\nexport function toBillingError(error: unknown): BillingError {\n if (error instanceof BillingError) return error\n if (error instanceof TypeError)\n return localError(\"network_error\", error.message)\n return localError(\n \"unknown_error\",\n error instanceof Error ? error.message : String(error)\n )\n}\n","// Generated by `go run ./scripts/contracts -write` from the currency registry (billing.Currencies). Do not edit.\n\n// Currency code to native-unit decimals.\nexport const OPENRAILS_CURRENCY_SCALES: Readonly<Record<string, number>> = {\n AED: 6,\n AUD: 6,\n BRL: 6,\n CAD: 6,\n CHF: 6,\n CNY: 6,\n CZK: 6,\n DKK: 6,\n EUR: 6,\n GBP: 6,\n HKD: 6,\n ILS: 6,\n INR: 6,\n JPY: 4,\n KRW: 4,\n MXN: 6,\n MYR: 6,\n NOK: 6,\n NZD: 6,\n PHP: 6,\n PLN: 6,\n PYUSD: 6,\n SAR: 6,\n SEK: 6,\n SGD: 6,\n SOL: 9,\n THB: 6,\n TRY: 6,\n USD: 6,\n USD1: 6,\n USDC: 6,\n USDG: 6,\n USDT: 6,\n ZAR: 6,\n}\n","// OpenRails's browser-safe PSP projection (GET /config's payment). Which\n// browser flow a PSP needs is decided here, never by the host.\nimport { z } from \"zod\"\n\nimport type { PaymentMethod } from \"./client/types\"\nimport type { PaymentOption, SavedPaymentMethod } from \"./types\"\n\nexport const pspConfigSchema = z.object({\n psp_id: z.string().min(1),\n /** The PSP's key. */\n key: z.string().min(1),\n rail: z.string(),\n /** Who holds the card: \"psp\" or a third-party custodian. */\n custodian: z.string(),\n display_name: z.string(),\n /** `tokenize | card | elements | redirect | wallet` */\n flow: z.string(),\n config: z.record(z.string(), z.string()).nullish(),\n /**\n * New purchases and new cards use this PSP (the operator's checkout PSP).\n * Other PSPs stay listed so existing cards and subscriptions keep working.\n */\n checkout: z.boolean().nullish(),\n /**\n * `temporarily_unavailable`: the PSP could not be checked just now and is\n * listed without `config`; ask again after `retry_after` seconds.\n */\n status: z.string().nullish(),\n retry_after: z.number().int().nullish(),\n})\nexport type PspConfig = z.infer<typeof pspConfigSchema>\n\nconst cardDrivers = new Set<PaymentOption[\"driver\"]>([\n \"collect_js\",\n \"card\",\n \"stripe_elements\",\n])\n\n/** Whether a rail takes a card in the page (saved or new). */\nexport const isCardRail = (rail: PaymentOption): boolean =>\n cardDrivers.has(rail.driver)\n\n/** PSPs that take new purchases and new cards. */\nexport const checkoutPsps = (psps: readonly PspConfig[]): PspConfig[] =>\n psps.filter((psp) => psp.checkout !== false)\n\nconst cardFlows = new Set([\"tokenize\", \"card\", \"elements\"])\n\n/**\n * Seconds until a card PSP listed as temporarily unavailable is worth asking\n * for again; null when none is.\n */\nexport function cardRetryAfter(psps: readonly PspConfig[]): number | null {\n const waits = psps\n .filter(\n (psp) =>\n !!psp.status && psp.custodian === \"psp\" && cardFlows.has(psp.flow)\n )\n .map((psp) => psp.retry_after ?? 30)\n return waits.length > 0 ? Math.min(...waits) : null\n}\n\n/** Saved cards the checkout can charge in place, for the given rails, newest first. */\nexport function savedMethodsFor(\n methods: readonly PaymentMethod[],\n rails: readonly PaymentOption[]\n): SavedPaymentMethod[] {\n const recent = [...methods].sort((a, b) =>\n (b.created_at ?? \"\").localeCompare(a.created_at ?? \"\")\n )\n return recent.flatMap((method) => {\n const rail = rails.find(\n (item) => (item.psp_id ?? item.id) === method.psp_id && isCardRail(item)\n )\n if (!rail || method.health?.active === false) return []\n return [\n {\n id: method.id,\n option_id: rail.id,\n rail: rail.rail,\n card: method.card ?? null,\n },\n ]\n })\n}\n\nexport type CardSetupDriver = \"collect_js\" | \"card\" | \"stripe_elements\"\n\nconst usable = (value?: string) => !!value && !value.startsWith(\"preview_\")\n\nconst stripeKey = (psp: PspConfig) =>\n psp.rail === \"stripe\" && !!psp.config?.publishable_key?.startsWith(\"pk_\")\n\n/** How a card is saved with this PSP in the page, or null when it cannot be. */\nexport function cardSetupDriver(psp: PspConfig): CardSetupDriver | null {\n if (psp.custodian !== \"psp\" || psp.status) return null\n // The PSP takes cards on OpenRails itself (card_entry: server).\n if (psp.flow === \"card\" && psp.rail === \"nmi\") return \"card\"\n if (\n psp.flow === \"tokenize\" &&\n usable(psp.config?.tokenization_key) &&\n !!psp.config?.tokenization_url\n )\n return \"collect_js\"\n if (stripeKey(psp)) return \"stripe_elements\"\n return null\n}\n\nexport const canSavePaymentMethod = (psp: PspConfig): boolean =>\n cardSetupDriver(psp) !== null\n\n/** Whether a pending payment on this PSP can be authenticated in the page. */\nexport const canAuthenticatePayment = (psp: PspConfig): boolean =>\n cardSetupDriver(psp) === \"stripe_elements\"\n\n/** The PSP config behind a checkout rail, for card setup and authentication. */\nexport function railPsp(rail: PaymentOption): PspConfig {\n return {\n psp_id: rail.psp_id ?? rail.id,\n key: rail.psp_key ?? rail.rail,\n rail: rail.rail,\n custodian: \"psp\",\n display_name: \"\",\n flow:\n rail.driver === \"stripe_elements\"\n ? \"elements\"\n : rail.driver === \"card\"\n ? \"card\"\n : \"tokenize\",\n config: rail.public_config ?? null,\n }\n}\n","// Wire types of the OpenRails customer surface (`/billing/v1/me/*`) and public\n// catalog, validated at the boundary. Money is an int64 string in the\n// currency's native unit; its scale comes from GET /config's currencies.\n// Fixtures: the repository's canonical testdata/wire.\nimport { z } from \"zod\"\n\nimport { pspConfigSchema } from \"../psp\"\n\nimport type { CardEntry } from \"../lib/card-entry\"\nimport { isAmount } from \"../lib/money\"\n\nconst amount = z.string().refine(isAmount, \"amount must be an int64 string\")\nconst time = z.string()\n\nexport const pageSchema = <T extends z.ZodType>(item: T) =>\n z.object({\n data: z\n .array(item)\n .nullish()\n .transform((v) => v ?? []),\n total: z.number().nullish(),\n limit: z.number().nullish(),\n offset: z.number().nullish(),\n has_more: z.boolean().nullish(),\n next_cursor: z.string().nullish(),\n })\n\nexport interface Page<T> {\n data: T[]\n total?: number | null\n limit?: number | null\n offset?: number | null\n has_more?: boolean | null\n /** The next page's cursor; null on the last page of a cursor list. */\n next_cursor?: string | null\n}\n\n/** One page of a cursor list; `next_cursor` is null on the last page. */\nexport const listPageSchema = <T extends z.ZodType>(item: T) =>\n z.object({\n data: z\n .array(item)\n .nullish()\n .transform((v) => v ?? []),\n next_cursor: z\n .string()\n .nullish()\n .transform((v) => v ?? null),\n })\n\nexport interface ListPage<T> {\n data: T[]\n next_cursor: string | null\n}\n\nexport const subscriptionStatusSchema = z.string()\n/** `pending | active | past_due | awaiting_method | unverified | canceled`; kept open for new values. */\nexport type SubscriptionStatus =\n | \"pending\"\n | \"active\"\n | \"past_due\"\n | \"awaiting_method\"\n | \"unverified\"\n | \"canceled\"\n | (string & {})\n\nexport const pspLinkStateSchema = z.object({\n /** `linked | pending_manual_link | sync_disabled | error` */\n status: z.string(),\n ids: z.record(z.string(), z.string()).nullish(),\n sync_status: z.string().nullish(),\n})\n\n/**\n * A catalog price, embedded in a product (`GET /catalog/products`): `unit_amount` of\n * `currency` for `access_duration_hours` of access (null: for good),\n * charging every `billing_interval_hours` (null: one-time).\n */\nexport const priceSchema = z.object({\n id: z.string(),\n key: z.string(),\n /** The price key's revision: every change to any of its versions; absent on older servers. */\n revision: z.number().int().nonnegative().optional(),\n /** This price's terms within its key, from zero; absent on older servers. */\n version: z.number().int().nonnegative().optional(),\n product_id: z.string(),\n archived: z.boolean(),\n unit_amount: amount,\n /** Optional bounds for a deposit whose amount is selected before checkout. */\n customer_amount: z\n .object({ min_amount: amount, max_amount: amount })\n .nullish(),\n currency: z.string(),\n access_duration_hours: z.number().nullable(),\n billing_interval_hours: z.number().nullable(),\n trial_unit_amount: amount.nullable(),\n trial_duration_hours: z.number().nullable(),\n /** Keyed by PSP key. */\n psps: z.record(z.string(), pspLinkStateSchema).nullish(),\n created_at: time,\n updated_at: time,\n})\nexport type Price = z.infer<typeof priceSchema>\n\nexport const subscriptionProductSchema = z.object({\n id: z.string(),\n key: z.string().nullish(),\n revision: z.number().int().nonnegative().optional(),\n display_name: z.string().nullish(),\n description: z.string().nullish(),\n tier_group: z.string().nullish(),\n tier_rank: z.number().nullish(),\n})\nexport type SubscriptionProduct = z.infer<typeof subscriptionProductSchema>\n\nexport const cardSummarySchema = z.object({\n brand: z.string().nullish(),\n last4: z.string().nullish(),\n exp_month: z.number().nullish(),\n exp_year: z.number().nullish(),\n})\nexport type CardSummary = z.infer<typeof cardSummarySchema>\n\nexport const paymentOperationSchema = z.object({\n id: z.string(),\n status: z.string(),\n})\nexport type PaymentOperation = z.infer<typeof paymentOperationSchema>\n\nexport const paymentRecoverySchema = z.object({\n last_failure_reason: z.string().nullish(),\n retryable: z.boolean(),\n blocked_reason: z.string().nullish(),\n operation: paymentOperationSchema.nullish(),\n})\nexport type PaymentRecovery = z.infer<typeof paymentRecoverySchema>\n\n/**\n * A step the customer takes before an action completes. With\n * `solana_sign_transactions` the wallet signs and sends `transactions` in\n * order; the action is then repeated with the last signature.\n */\nexport const nextActionSchema = z.object({\n /** `redirect_to_url | payment_authentication | solana_sign_transactions` */\n type: z.string(),\n redirect_to_url: z.object({ url: z.string().nullish() }).nullish(),\n transactions: z.array(z.string()).nullish(),\n})\nexport type NextAction = z.infer<typeof nextActionSchema>\n\n/**\n * A declined renewal being collected. `retries_left` and `final_retry_at`\n * follow the merchant's dunning policy; both are null when the provider runs\n * the retries. While `waiting_for_new_card`, nothing is charged until the card\n * is replaced, and the subscription ends at `final_retry_at`.\n */\nexport const subscriptionDunningSchema = z.object({\n attempts: z.number(),\n retries_left: z.number().nullish(),\n next_retry_at: time.nullish(),\n final_retry_at: time.nullish(),\n waiting_for_new_card: z.boolean(),\n last_failure_reason: z.string().nullish(),\n})\nexport type SubscriptionDunning = z.infer<typeof subscriptionDunningSchema>\n\nexport const subscriptionSchema = z.object({\n id: z.string(),\n status: subscriptionStatusSchema,\n rail: z.string().nullish(),\n product_id: z.string().nullish(),\n price_id: z.string().nullish(),\n /** Seats of a per-seat price; null otherwise. */\n quantity: z.number().nullish(),\n psp_id: z.string().nullish(),\n /** `engine | nmi_schedule | provider` */\n collection_policy: z.string().nullish(),\n /** The subscription's own card; null follows the default card. */\n payment_method_id: z.string().nullish(),\n started_at: time.nullish(),\n ended_at: time.nullish(),\n current_period_starts_at: time.nullish(),\n current_period_ends_at: time.nullish(),\n canceled_at: time.nullish(),\n cancel_type: z.string().nullish(),\n resumable: z.boolean().nullish(),\n cancel_scheduled: z.boolean().nullish(),\n /** `reversible | destructive | external_portal` */\n cancel_mode: z.string().nullish(),\n cancel_portal_url: z.string().nullish(),\n access: z.object({ starts_at: time, ends_at: time.nullish() }).nullish(),\n /** Null unless the subscription is `past_due` or `awaiting_method`. */\n dunning: subscriptionDunningSchema.nullish(),\n price: priceSchema.nullish(),\n product: subscriptionProductSchema.nullish(),\n /** The change waiting for the next renewal, with its price and product. */\n scheduled_change: z\n .object({\n price_id: z.string(),\n quantity: z.number().nullish(),\n effective_at: time,\n /** `change | migration` */\n source: z.string(),\n price: priceSchema.nullish(),\n product: subscriptionProductSchema.nullish(),\n })\n .nullish(),\n card: cardSummarySchema.nullish(),\n recovery: paymentRecoverySchema.nullish(),\n /** Set on an action's answer when the rail needs the customer's step. */\n next_action: nextActionSchema.nullish(),\n created_at: time.nullish(),\n updated_at: time.nullish(),\n})\nexport type Subscription = z.infer<typeof subscriptionSchema> & {\n status: SubscriptionStatus\n}\n\nexport const billingDetailsSchema = z.object({\n name: z.string().nullish(),\n email: z.string().nullish(),\n phone: z.string().nullish(),\n address: z\n .object({\n line1: z.string().nullish(),\n line2: z.string().nullish(),\n city: z.string().nullish(),\n state: z.string().nullish(),\n postal_code: z.string().nullish(),\n country: z.string().nullish(),\n })\n .nullish(),\n})\nexport type BillingDetails = z.infer<typeof billingDetailsSchema>\n\nexport const paymentMethodSchema = z.object({\n id: z.string(),\n rail: z.string().nullish(),\n /** The PSP holding the card; null for a card a custodian holds. */\n psp_id: z.string().nullish(),\n card: cardSummarySchema.nullish(),\n billing_details: billingDetailsSchema.nullish(),\n health: z\n .object({\n /** `valid | expiring_soon | expired` */\n expiry_status: z.string().nullish(),\n last_charged_at: time.nullish(),\n last_charge_outcome: z.string().nullish(),\n active: z.boolean().nullish(),\n })\n .nullish(),\n subscriptions: z\n .array(\n z.object({\n id: z.string(),\n display_name: z.string().nullish(),\n })\n )\n .nullish(),\n /** Currencies whose invoices this card collects. */\n default_currencies: z.array(z.string()).nullish(),\n created_at: time.nullish(),\n})\nexport type PaymentMethod = z.infer<typeof paymentMethodSchema>\n\n/** A price's state on one PSP; public routes carry the status only. */\nexport const productSchema = z.object({\n id: z.string(),\n key: z.string(),\n /** Current mutation counter; absent on older servers. */\n revision: z.number().int().nonnegative().optional(),\n display_name: z.string(),\n description: z.string(),\n /** Opaque entitlement keys granted by the product. */\n entitlements: z.array(z.string()),\n /** Prepaid balance fulfilled once for each qualifying successful payment. */\n credit_grant: z\n .object({\n currency: z.string(),\n amount: amount.nullish(),\n from_payment: z.boolean().optional(),\n expires_after_days: z.number().int().positive().nullish(),\n })\n .nullish(),\n /** Products sharing a group are tiers a subscription can change between. */\n tier_group: z.string().nullable(),\n tier_rank: z.number(),\n archived: z.boolean(),\n prices: z\n .array(priceSchema)\n .nullish()\n .transform((v) => v ?? []),\n created_at: time,\n updated_at: time,\n})\nexport type Product = z.infer<typeof productSchema>\n\nexport const paymentSchema = z.object({\n id: z.string(),\n /** `charge | refund | chargeback | dispute_reversal` */\n kind: z.string(),\n /** `succeeded | pending | failed | refunded | partially_refunded` */\n status: z.string(),\n /** Negative for a refund or chargeback. */\n amount: amount,\n amount_refunded: amount.nullish(),\n currency: z.string(),\n subscription_id: z.string().nullish(),\n price_id: z.string().nullish(),\n /** `rail | manual | admin` */\n channel: z.string().nullish(),\n rail: z.string().nullish(),\n created_at: time,\n /** What was bought. */\n price: priceSchema.nullish(),\n product: subscriptionProductSchema.nullish(),\n card: cardSummarySchema.nullish(),\n /** Normalized decline of a failed payment. */\n failure: z\n .object({\n reason: z.string(),\n message: z.string(),\n field: z.string().nullish(),\n })\n .nullish(),\n})\nexport type Payment = z.infer<typeof paymentSchema>\n\n/** A customer's money in one currency. */\nexport const balanceSchema = z.object({\n currency: z.string(),\n billing_mode: z.string(),\n balance_amount: amount,\n held_amount: amount,\n available_amount: amount,\n owed_amount: amount,\n})\nexport type Balance = z.infer<typeof balanceSchema>\n\n/**\n * The signed-in customer's summary (`GET /me`): money per currency, the\n * default card of each currency, and how many notices are unread.\n */\nexport const accountSchema = z.object({\n id: z.string(),\n balances: z.array(balanceSchema),\n default_payment_methods: z.array(\n z.object({ currency: z.string(), payment_method_id: z.string() })\n ),\n unread_notifications: z.number(),\n})\nexport type Account = z.infer<typeof accountSchema>\n\nexport const invoiceSchema = z.object({\n id: z.string(),\n currency: z.string(),\n invoice_number: z.string().nullish(),\n period_starts_at: time,\n period_ends_at: time,\n total_amount: amount,\n amount_paid: amount,\n amount_due: amount,\n status: z.string(),\n issued_at: time.nullish(),\n due_at: time.nullish(),\n /** Overdue past grace: new usage in its currency is refused until paid. */\n delinquent: z.boolean().nullish(),\n paid_at: time.nullish(),\n recovery: paymentRecoverySchema.nullish(),\n created_at: time,\n})\nexport type Invoice = z.infer<typeof invoiceSchema>\n\n/** Currency code (upper case) to its native-unit scale. */\nexport type CurrencyScales = Readonly<Record<string, number>>\n\nexport const currencySchema = z.object({\n code: z.string(),\n /** Native-unit decimals of every amount on the wire. */\n decimals: z.number(),\n /** Decimals the provider settles in. */\n minor_decimals: z.number().nullish(),\n})\nexport type Currency = z.infer<typeof currencySchema>\n\nexport const subscriptionChangePreviewSchema = z.object({\n price_id: z.string(),\n /** Seats of a per-seat price; null otherwise. */\n quantity: z.number().nullish(),\n rail: z.string().nullish(),\n currency: z.string(),\n /** Charged immediately; `\"0\"` for a change at period end. */\n amount_due_now: amount,\n /** The new price, charged at the next renewal. */\n next_charge_amount: amount,\n next_charge_date: time.nullish(),\n /** `now | period_end` */\n effective: z.string(),\n /** The rail finalizes the exact amount (Stripe provider changes). */\n is_estimate: z.boolean().nullish(),\n message: z.string().nullish(),\n})\nexport type SubscriptionChangePreview = z.infer<\n typeof subscriptionChangePreviewSchema\n>\n\nexport const subscriptionChangeSchema = z.object({\n /** `succeeded | processing | requires_action | blocked` */\n status: z.string(),\n /** `now | period_end` */\n effective: z.string().nullish(),\n price_id: z.string().nullish(),\n quantity: z.number().nullish(),\n /** The subscription now carrying the plan (an upgrade may open a successor). */\n subscription_id: z.string().nullish(),\n /** `payment_authentication` uses `operation_id`. */\n next_action: nextActionSchema.nullish(),\n /** When a change at period end takes effect. */\n delayed_start: time.nullish(),\n currency: z.string().nullish(),\n amount_due_now: amount.nullish(),\n next_charge_amount: amount.nullish(),\n next_charge_date: time.nullish(),\n message: z.string().nullish(),\n /** The durable operation: unresolved while `processing`, the payment to authenticate on `requires_action`. */\n operation_id: z.string().nullish(),\n})\nexport type SubscriptionChange = z.infer<typeof subscriptionChangeSchema>\n\nconst tokenUnits = z.string().regex(/^\\d+$/, \"units must be a uint64 string\")\n\nexport const solanaTokenSchema = z.object({\n symbol: z.string(),\n name: z.string().nullish(),\n mint: z.string(),\n decimals: z.number(),\n /** USD price as an exact decimal string; absent without a feed quote. */\n price: z.string().nullish(),\n /** The stablecoin to present first. */\n preferred: z.boolean().nullish(),\n /** Can back a recurring subscription, not only a one-off payment. */\n recurring_eligible: z.boolean().nullish(),\n /** What the requested price costs in this token. */\n quote: z\n .object({\n /** Display decimal of `units`. */\n amount: z.string(),\n /** Exact on-chain base units. */\n units: tokenUnits,\n token_price_usd: z.string().nullish(),\n fx_rate: z.string().nullish(),\n fx_currency: z.string().nullish(),\n quoted_at: time.nullish(),\n expires_at: time.nullish(),\n })\n .nullish(),\n /** The requested wallet's holding. */\n balance: z\n .object({\n amount: z.string(),\n units: tokenUnits,\n /** Covers `quote`. */\n sufficient: z.boolean().nullish(),\n })\n .nullish(),\n})\nexport type SolanaToken = z.infer<typeof solanaTokenSchema>\n\nexport const solanaTokensSchema = z.object({\n tokens: z\n .array(solanaTokenSchema)\n .nullish()\n .transform((v) => v ?? []),\n})\n\n/**\n * The merchant's browser payment setup: its armed PSPs with their public\n * values and, with a Solana PSP, the network and accepted tokens a wallet\n * adapter is configured with.\n */\nexport const paymentConfigSchema = z.object({\n psps: z\n .array(pspConfigSchema)\n .nullish()\n .transform((v) => v ?? []),\n solana: z\n .object({\n /** `mainnet | devnet | testnet` */\n network: z.string(),\n /** `solana:<network>` */\n chain: z.string(),\n preferred_token: z.string().nullish(),\n tokens: z\n .array(\n z.object({\n symbol: z.string(),\n name: z.string().nullish(),\n mint: z.string(),\n decimals: z.number().int(),\n preferred: z.boolean().nullish(),\n recurring_eligible: z.boolean().nullish(),\n })\n )\n .nullish()\n .transform((v) => v ?? []),\n })\n .nullish(),\n})\nexport type PaymentConfig = z.infer<typeof paymentConfigSchema>\n\n/**\n * The challenge to solve when a request answers 403 `captcha_required`: load\n * `script_url`, solve with `site_key` and `action`, and resend the request\n * with the token in the `token_header` header.\n */\nexport const captchaConfigSchema = z.object({\n provider: z.string(),\n site_key: z.string(),\n script_url: z.string(),\n action: z.string(),\n token_header: z.string(),\n})\nexport type CaptchaConfig = z.infer<typeof captchaConfigSchema>\n\n/**\n * What a browser needs to know about the deployment and its merchant\n * (`GET /config`): the mount's capabilities, the currency registry, the\n * merchant's payment setup (null when the request resolves no merchant) and\n * the captcha (null when the deployment challenges nobody).\n */\nexport const publicConfigSchema = z.object({\n capabilities: z.object({\n route_groups: z.record(z.string(), z.boolean()),\n features: z.record(z.string(), z.boolean()),\n }),\n currencies: z\n .array(currencySchema)\n .nullish()\n .transform((v) => v ?? []),\n payment: paymentConfigSchema.nullish(),\n captcha: captchaConfigSchema.nullish(),\n})\nexport type PublicConfig = z.infer<typeof publicConfigSchema>\n\n/** An in-page card setup; `payment_method_id` is set once the card is saved. */\nexport const cardSetupSchema = z.object({\n id: z.string(),\n status: z.string(),\n client_secret: z.string().nullish(),\n payment_method_id: z.string().nullish(),\n})\nexport type CardSetup = z.infer<typeof cardSetupSchema>\n\nexport const paymentAuthenticationSchema = z.object({\n client_secret: z.string().nullish(),\n})\nexport type PaymentAuthentication = z.infer<typeof paymentAuthenticationSchema>\n\n/**\n * What a card setup hands the server: tokenized data only, never a PAN.\n * OpenRails reads the saved card's brand, last four and expiry from the PSP.\n */\ninterface NewCardFields {\n /** The PSP the card is saved with (`psp_id` of a rail option); required. */\n psp_id: string\n billing_details?: {\n name?: string\n email?: string\n address?: { postal_code?: string; country?: string }\n }\n}\n\n/**\n * A card to save: a token from the PSP's own fields (`payment_token`), or,\n * for a PSP whose card_entry is server (`cardSetupDriver` \"card\"), the card\n * itself, posted to OpenRails and never kept by this package.\n */\nexport type NewCard = NewCardFields &\n (\n | { payment_token: string; card?: never }\n | { card: CardEntry; payment_token?: never }\n )\n\n/**\n * A minted checkout session. `id` reads and pays it with no other credential\n * (`client.checkoutSource(id)`); hand it to this customer's browser only.\n * `url` is the shared payment page (`<CheckoutFrame url>`), null when the app\n * renders `<Checkout>` itself.\n */\nexport const checkoutSessionLinkSchema = z.object({\n id: z.string().startsWith(\"ocs_\"),\n url: z.string().url().nullish(),\n expires_at: time,\n})\nexport type CheckoutSessionLink = z.infer<typeof checkoutSessionLinkSchema>\n","import type { z } from \"zod\"\n\nimport type { CheckoutSource } from \"../source\"\nimport {\n checkoutSessionSchema,\n payResultSchema,\n type PayRequest,\n type PayResult,\n} from \"../types\"\nimport {\n BillingError,\n isBillingError,\n localError,\n readBillingError,\n} from \"./errors\"\nimport { OPENRAILS_CURRENCY_SCALES } from \"./generated/currencies\"\nimport type * as wire from \"./generated/wire\"\nimport {\n accountSchema,\n cardSetupSchema,\n checkoutSessionLinkSchema,\n publicConfigSchema,\n paymentAuthenticationSchema,\n invoiceSchema,\n listPageSchema,\n pageSchema,\n paymentMethodSchema,\n paymentSchema,\n productSchema,\n solanaTokensSchema,\n subscriptionSchema,\n subscriptionChangePreviewSchema,\n subscriptionChangeSchema,\n type Account,\n type CardSetup,\n type CheckoutSessionLink,\n type PublicConfig,\n type PaymentAuthentication,\n type CurrencyScales,\n type Invoice,\n type ListPage,\n type NewCard,\n type NextAction,\n type Page,\n type Payment,\n type PaymentMethod,\n type Product,\n type SolanaToken,\n type Subscription,\n type SubscriptionChange,\n type SubscriptionChangePreview,\n} from \"./types\"\n\nexport interface BillingClientOptions {\n /** OpenRails embedded mount. Default \"/billing/v1\". */\n baseUrl?: string\n /**\n * Transport. Pass an authenticating fetch (auth-ui's `client.authFetch`)\n * or combine the default with `getToken`.\n */\n fetch?: (input: string, init: RequestInit) => Promise<Response>\n /** Bearer for each request; omit when `fetch` authenticates. */\n getToken?: () =>\n string | null | undefined | Promise<string | null | undefined>\n /** Sent as Accept-Language. */\n language?: () => string | null | undefined\n /**\n * Extra or overriding currency scales (code -> native-unit decimals). The\n * pinned OpenRails registry is built in; `/me` amounts carry no scale.\n */\n currencies?: CurrencyScales\n}\n\nexport interface CheckoutSourceOptions {\n /**\n * A customer surface's base: its `/me` prefix, such as `/billing/v1/me` or\n * a host's own `/api/v1/merchants/acme/billing/me`. The session is read and\n * paid there with this client's credential, which proves the session's\n * customer, so its saved cards pay. Default: the session id alone, at\n * `{baseUrl}/checkout-sessions`.\n */\n customerBase?: string\n}\n\nexport interface ListOptions {\n limit?: number\n offset?: number\n /** A cursor list's next page: the previous page's `next_cursor`. */\n cursor?: string\n signal?: AbortSignal\n}\n\n/**\n * A subscription change: another price of its tier group, other seats of a\n * per-seat price, or both. A quantity for a price that is not per seat is\n * refused (`quantity_not_allowed`).\n */\nexport interface SubscriptionChangeInput {\n priceId?: string\n quantity?: number\n}\n\nexport interface CursorOptions {\n limit?: number\n cursor?: string | null\n signal?: AbortSignal\n}\n\n/**\n * Signs and submits a base64 transaction with the customer's wallet and\n * returns its signature. Throw `WalletRejectedError` when the user declines.\n */\nexport type SendSolanaTransaction = (\n transactionBase64: string\n) => Promise<string>\n\nexport class WalletRejectedError extends Error {\n constructor(message = \"The wallet request was declined.\") {\n super(message)\n this.name = \"WalletRejectedError\"\n }\n}\n\nexport const CANCEL_REASON_MIN = 4\nexport const CANCEL_REASON_MAX = 500\n\n/** A next action the customer's wallet completes. */\nexport const isWalletAction = (next: NextAction | null | undefined): boolean =>\n next?.type === \"solana_sign_transactions\" && !!next.transactions?.length\n\n/**\n * Signs and sends a `solana_sign_transactions` next action's transactions in\n * order and returns the last signature, the value the action is repeated\n * with. A declined prompt is a local `wallet_rejected` error.\n */\nexport async function signWalletAction(\n next: NextAction,\n sendTransaction: SendSolanaTransaction\n): Promise<string> {\n let signature = \"\"\n for (const transaction of next.transactions ?? []) {\n try {\n signature = await sendTransaction(transaction)\n } catch (err) {\n if (isWalletRejection(err))\n throw localError(\"wallet_rejected\", \"The wallet request was declined.\")\n throw err\n }\n if (!signature)\n throw localError(\n \"wallet_no_signature\",\n \"The wallet returned no signature.\"\n )\n }\n if (!signature)\n throw localError(\"wallet_no_signature\", \"The wallet returned no signature.\")\n return signature\n}\n\ntype Query = Record<string, string | number | boolean | undefined>\n\ninterface RequestOptions {\n method?: string\n query?: Query\n body?: unknown\n signal?: AbortSignal\n headers?: Record<string, string>\n /** Sends no bearer: the hosted checkout session id is the credential. */\n anonymous?: boolean\n /** Replaces `baseUrl` for this request. */\n root?: string\n}\n\n/** Total wait a GET may spend on its one retry. */\nexport const RETRY_BUDGET_MS = 2_000\nconst RETRY_DELAY_MS = 300\n\n// The wait before retrying a GET answered with res, or null if it is final.\nfunction retryDelay(res: Response): number | null {\n const retryAfter = parseRetryAfter(res.headers.get(\"Retry-After\"))\n switch (res.status) {\n case 429:\n return retryAfter\n case 503:\n return retryAfter ?? RETRY_DELAY_MS\n case 502:\n case 504:\n return RETRY_DELAY_MS\n default:\n return null\n }\n}\n\nfunction parseRetryAfter(value: string | null): number | null {\n if (!value) return null\n if (/^\\d+$/.test(value.trim())) return Number(value.trim()) * 1000\n const at = Date.parse(value)\n return Number.isNaN(at) ? null : Math.max(0, at - Date.now())\n}\n\nfunction pause(ms: number, signal?: AbortSignal): Promise<number> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(signal.reason)\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", abort)\n resolve(ms)\n }, ms)\n const abort = () => {\n clearTimeout(timer)\n reject(signal?.reason)\n }\n signal?.addEventListener(\"abort\", abort, { once: true })\n })\n}\n\nexport function createBillingClient(options: BillingClientOptions = {}) {\n const base = (options.baseUrl ?? \"/billing/v1\").replace(/\\/+$/, \"\")\n const doFetch =\n options.fetch ?? ((input: string, init: RequestInit) => fetch(input, init))\n const currencies = normalizeScales({\n ...OPENRAILS_CURRENCY_SCALES,\n ...options.currencies,\n })\n\n function url(path: string, query?: Query, root = base): string {\n const qs = new URLSearchParams()\n for (const [k, v] of Object.entries(query ?? {}))\n if (v !== undefined && v !== \"\") qs.set(k, String(v))\n const q = qs.toString()\n return `${root}${path}${q ? `?${q}` : \"\"}`\n }\n\n async function send(\n path: string,\n opts: RequestOptions = {}\n ): Promise<Response> {\n const headers = new Headers({ Accept: \"application/json\", ...opts.headers })\n if (opts.body !== undefined) headers.set(\"Content-Type\", \"application/json\")\n const token = opts.anonymous ? undefined : await options.getToken?.()\n if (token) headers.set(\"Authorization\", `Bearer ${token}`)\n const lang = options.language?.()\n if (lang) headers.set(\"Accept-Language\", lang)\n const method = opts.method ?? \"GET\"\n const init = {\n method,\n headers,\n body: opts.body === undefined ? undefined : JSON.stringify(opts.body),\n signal: opts.signal,\n }\n // Only a GET is retried: once, on a network error or 502/503/504 (and a\n // 429 that names its wait), within RETRY_BUDGET_MS. Writes never are.\n const retries = method === \"GET\" ? 1 : 0\n let waited = 0\n for (let attempt = 0; ; attempt++) {\n let res: Response\n try {\n res = await doFetch(url(path, opts.query, opts.root), init)\n } catch (cause) {\n const delay = RETRY_DELAY_MS\n if (\n attempt >= retries ||\n opts.signal?.aborted ||\n !(cause instanceof TypeError) ||\n waited + delay > RETRY_BUDGET_MS\n )\n throw cause\n waited += await pause(delay, opts.signal)\n continue\n }\n if (res.ok) return res\n const delay = retryDelay(res)\n if (\n attempt >= retries ||\n delay === null ||\n waited + delay > RETRY_BUDGET_MS\n )\n throw await readBillingError(res)\n await res.body?.cancel().catch(() => undefined)\n waited += await pause(delay, opts.signal)\n }\n }\n\n async function json<S extends z.ZodType>(\n schema: S,\n path: string,\n opts?: RequestOptions\n ): Promise<z.output<S>> {\n const res = await send(path, opts)\n let body: unknown\n try {\n body = await res.json()\n } catch {\n throw localError(\"invalid_response\", `${path}: body is not JSON`)\n }\n const parsed = schema.safeParse(body)\n if (!parsed.success)\n throw localError(\n \"invalid_response\",\n `${path}: ${parsed.error.issues[0]?.path.join(\".\")} ${parsed.error.issues[0]?.message}`\n )\n return parsed.data\n }\n\n const id = (value: string) => encodeURIComponent(value)\n const subscriptionPage = listPageSchema(subscriptionSchema)\n const methodPage = listPageSchema(paymentMethodSchema)\n const paymentPage = listPageSchema(paymentSchema)\n const invoicePage = listPageSchema(invoiceSchema)\n const cursorQuery = (opts: CursorOptions, limit: number) => ({\n limit: opts.limit ?? limit,\n cursor: opts.cursor ?? undefined,\n })\n const productPage = pageSchema(productSchema)\n\n return {\n baseUrl: base,\n\n /** One page of the customer's subscriptions, newest first. */\n listSubscriptions(\n opts: CursorOptions & { status?: string } = {}\n ): Promise<ListPage<Subscription>> {\n return json(subscriptionPage, \"/me/subscriptions\", {\n query: { status: opts.status ?? \"all\", ...cursorQuery(opts, 100) },\n signal: opts.signal,\n })\n },\n\n /** Includes `recovery` (list rows do not). */\n getSubscription(\n subscriptionId: string,\n signal?: AbortSignal\n ): Promise<Subscription> {\n return json(\n subscriptionSchema,\n `/me/subscriptions/${id(subscriptionId)}`,\n {\n signal,\n }\n )\n },\n\n /**\n * Cancels at period end and answers the subscription. When the rail needs\n * the customer's step (`next_action`, a Solana wallet signature), the\n * subscription is unchanged: complete it with `signWalletAction` and\n * repeat with `signature`.\n */\n cancelSubscription(\n subscriptionId: string,\n input: { reason: string; signature?: string }\n ): Promise<Subscription> {\n return json(\n subscriptionSchema,\n `/me/subscriptions/${id(subscriptionId)}/cancel`,\n {\n method: \"POST\",\n body: {\n reason: input.reason.trim(),\n signature: input.signature,\n } satisfies wire.CustomerCancelSubscriptionParams,\n }\n )\n },\n\n /** Undoes a scheduled cancel before the period ends. */\n resumeSubscription(subscriptionId: string): Promise<Subscription> {\n return json(\n subscriptionSchema,\n `/me/subscriptions/${id(subscriptionId)}/resume`,\n { method: \"POST\", body: {} }\n )\n },\n\n /** Gives the subscription its own card; `null` makes it follow the default. */\n setSubscriptionPaymentMethod(\n subscriptionId: string,\n paymentMethodId: string | null\n ): Promise<Subscription> {\n return json(\n subscriptionSchema,\n `/me/subscriptions/${id(subscriptionId)}/payment-method`,\n {\n method: \"PUT\",\n body: {\n payment_method_id: paymentMethodId,\n } satisfies wire.SetSubscriptionPaymentMethodParams,\n }\n )\n },\n\n /** What `changeSubscription` would charge now and at the next renewal. */\n previewSubscriptionChange(\n subscriptionId: string,\n change: SubscriptionChangeInput,\n signal?: AbortSignal\n ): Promise<SubscriptionChangePreview> {\n return json(\n subscriptionChangePreviewSchema,\n `/me/subscriptions/${id(subscriptionId)}/change/preview`,\n {\n method: \"POST\",\n body: {\n price_id: change.priceId,\n quantity: change.quantity,\n } satisfies wire.PreviewSubscriptionChangeParams,\n signal,\n }\n )\n },\n\n /**\n * Moves the subscription to another price of its tier group, to other\n * seats of a per-seat price, or both. An upgrade and more seats charge\n * the saved card now; a downgrade and fewer seats apply at period end.\n * Reuse `idempotencyKey` until the change resolves (`processing`, a\n * `subscription_change_in_flight` refusal or a lost response) so the\n * stored result replays instead of charging twice. A Solana wallet next\n * action is completed with `signWalletAction`, then repeated with `signature`.\n */\n changeSubscription(\n subscriptionId: string,\n input: SubscriptionChangeInput & {\n idempotencyKey: string\n signature?: string\n }\n ): Promise<SubscriptionChange> {\n return json(\n subscriptionChangeSchema,\n `/me/subscriptions/${id(subscriptionId)}/change`,\n {\n method: \"POST\",\n body: {\n price_id: input.priceId,\n quantity: input.quantity,\n signature: input.signature,\n } satisfies wire.CustomerChangeSubscriptionParams,\n headers: { \"Idempotency-Key\": input.idempotencyKey },\n }\n )\n },\n\n listPaymentMethods(\n opts: CursorOptions = {}\n ): Promise<ListPage<PaymentMethod>> {\n return json(methodPage, \"/me/payment-methods\", {\n query: cursorQuery(opts, 100),\n signal: opts.signal,\n })\n },\n\n /**\n * Stores a card entered in the page with the PSP `psp_id`: a Collect.js\n * token (`cardSetupDriver` \"collect_js\") or the card itself (\"card\").\n */\n addPaymentMethod(card: NewCard): Promise<PaymentMethod> {\n return json(paymentMethodSchema, \"/me/payment-methods\", {\n method: \"POST\",\n body: card,\n })\n },\n\n /**\n * Starts an in-page card setup with a PSP whose browser SDK collects the\n * card (see `cardSetupDriver`). `idempotencyKey` identifies this attempt.\n */\n createCardSetup(input: {\n pspId: string\n idempotencyKey: string\n }): Promise<CardSetup> {\n return json(cardSetupSchema, \"/me/payment-method-setups\", {\n method: \"POST\",\n body: { psp_id: input.pspId, consent: true },\n headers: { \"Idempotency-Key\": input.idempotencyKey },\n })\n },\n\n getCardSetup(setupId: string, signal?: AbortSignal): Promise<CardSetup> {\n return json(cardSetupSchema, `/me/payment-method-setups/${id(setupId)}`, {\n signal,\n })\n },\n\n /** Verifies the setup with the provider; `payment_method_id` once saved. */\n confirmCardSetup(setupId: string): Promise<CardSetup> {\n return json(\n cardSetupSchema,\n `/me/payment-method-setups/${id(setupId)}/confirm`,\n { method: \"POST\", body: {} }\n )\n },\n\n /** The provider challenge a pending payment operation is waiting on. */\n getPaymentAuthentication(\n operationId: string\n ): Promise<PaymentAuthentication> {\n return json(\n paymentAuthenticationSchema,\n `/me/payment-operations/${id(operationId)}/authentication`\n )\n },\n\n async confirmPaymentAuthentication(operationId: string): Promise<void> {\n await send(\n `/me/payment-operations/${id(operationId)}/authentication/confirm`,\n { method: \"POST\", body: {} }\n )\n },\n\n /** `pending` when the provider is still converging (202). */\n async removePaymentMethod(\n paymentMethodId: string\n ): Promise<\"removed\" | \"pending\"> {\n const res = await send(`/me/payment-methods/${id(paymentMethodId)}`, {\n method: \"DELETE\",\n })\n return res.status === 202 ? \"pending\" : \"removed\"\n },\n\n /**\n * Makes the card the default for one currency: it pays the currency's\n * invoices and every subscription in it without its own card.\n */\n async setDefaultPaymentMethod(input: {\n currency: string\n paymentMethodId: string\n }): Promise<void> {\n await send(\n `/me/default-payment-methods/${id(input.currency.toUpperCase())}`,\n {\n method: \"PUT\",\n body: {\n payment_method_id: input.paymentMethodId,\n } satisfies wire.SetDefaultPaymentMethodParams,\n }\n )\n },\n\n /** Charges and refunds, newest first. `rail` filters by rail. */\n listPayments(\n opts: CursorOptions & { rail?: string } = {}\n ): Promise<ListPage<Payment>> {\n return json(paymentPage, \"/me/payments\", {\n query: { ...cursorQuery(opts, 20), rail: opts.rail },\n signal: opts.signal,\n })\n },\n\n listInvoices(opts: CursorOptions = {}): Promise<ListPage<Invoice>> {\n return json(invoicePage, \"/me/invoices\", {\n query: cursorQuery(opts, 20),\n signal: opts.signal,\n })\n },\n\n /**\n * The customer's summary: balance and amount owed per currency, the card\n * that pays each currency, and unread notices.\n */\n getAccount(signal?: AbortSignal): Promise<Account> {\n return json(accountSchema, \"/me\", { signal })\n },\n\n getInvoice(invoiceId: string, signal?: AbortSignal): Promise<Invoice> {\n return json(invoiceSchema, `/me/invoices/${id(invoiceId)}`, { signal })\n },\n\n /** Products on sale, each with its current prices. */\n listProducts(opts: ListOptions = {}): Promise<Page<Product>> {\n return json(productPage, \"/catalog/products\", {\n query: { limit: opts.limit ?? 100, cursor: opts.cursor },\n signal: opts.signal,\n })\n },\n\n\n /**\n * Mints a hosted checkout session for the signed-in customer and one\n * price. Render it with `<CheckoutFrame url>` when the session has a\n * `url`, else with `<Checkout source={client.checkoutSource(id)}>`.\n * Select a price by `priceId`, or by both `productKey` and `priceKey`.\n * `successUrl` brings the buyer back from a redirect rail; it must be on\n * one of this app's return origins.\n */\n createCheckoutSession(input: {\n priceKey?: string\n productKey?: string\n priceId?: string\n /** Customer-selected deposit in the price currency’s native units. */\n amount?: string\n /** Defaults to true for recurring prices; false buys the initial term only. */\n autoRenew?: boolean\n successUrl?: string\n }): Promise<CheckoutSessionLink> {\n if (\n !input.priceKey === !input.priceId ||\n !!input.priceKey !== !!input.productKey\n )\n return Promise.reject(\n localError(\n \"invalid_request\",\n \"Pass priceId, or both productKey and priceKey.\"\n )\n )\n return json(checkoutSessionLinkSchema, \"/me/checkout-sessions\", {\n method: \"POST\",\n body: {\n price_key: input.priceKey,\n product_key: input.productKey,\n price_id: input.priceId,\n auto_renew: input.autoRenew,\n amount: input.amount,\n success_url: input.successUrl,\n } satisfies wire.MintCheckoutSessionParams,\n })\n },\n\n /**\n * Reads and pays one hosted checkout session. By default the id is the\n * only credential: no bearer is sent. With `customerBase` the session's\n * customer reads and pays it on that customer surface, signed in. A\n * refusal the buyer can answer (an invalid card form, too many attempts)\n * resolves as `failed`; an expired or unknown session as `expired`.\n */\n checkoutSource(\n sessionId: string,\n opts: CheckoutSourceOptions = {}\n ): CheckoutSource {\n const path = `/checkout-sessions/${id(sessionId)}`\n const customer = opts.customerBase?.replace(/\\/+$/, \"\")\n const via: RequestOptions =\n customer === undefined ? { anonymous: true } : { root: customer }\n return {\n getSession: () => json(checkoutSessionSchema, path, via),\n async pay(request: PayRequest): Promise<PayResult> {\n try {\n return await json(payResultSchema, `${path}/pay`, {\n ...via,\n method: \"POST\",\n body: request satisfies Omit<wire.PayCheckoutSessionParams, \"billing_details\">,\n })\n } catch (err) {\n if (!isBillingError(err)) throw err\n switch (err.status) {\n case 404:\n case 410:\n return { status: \"expired\" }\n case 403:\n return { status: \"blocked\", failure_message: err.message }\n case 422:\n case 429:\n return { status: \"failed\", failure_message: err.message }\n }\n throw err\n }\n },\n }\n },\n\n /**\n * The deployment's public configuration: what the mount serves, the\n * currency registry and the merchant's payment setup. React components\n * share one copy through `useConfig()`.\n */\n getConfig(signal?: AbortSignal): Promise<PublicConfig> {\n return json(publicConfigSchema, \"/config\", { signal, anonymous: true })\n },\n\n /**\n * Accepted tokens with live prices. `priceId` adds each token's `quote`;\n * `wallet` adds its `balance`.\n */\n async listSolanaTokens(\n opts: {\n priceId?: string\n wallet?: string\n signal?: AbortSignal\n } = {}\n ): Promise<SolanaToken[]> {\n const { tokens } = await json(solanaTokensSchema, \"/solana/tokens\", {\n query: {\n price_id: opts.priceId,\n wallet: opts.wallet,\n },\n signal: opts.signal,\n })\n return tokens\n },\n\n /** Currency code (upper case) to native-unit decimals. */\n currencies,\n }\n}\n\nfunction normalizeScales(scales: CurrencyScales): CurrencyScales {\n return Object.fromEntries(\n Object.entries(scales).map(([code, decimals]) => [\n code.toUpperCase(),\n decimals,\n ])\n )\n}\n\nexport type BillingClient = ReturnType<typeof createBillingClient>\n\nexport const isWalletRejection = (error: unknown): boolean =>\n error instanceof WalletRejectedError ||\n (error instanceof Error && error.name === \"WalletRejectedError\") ||\n (error instanceof BillingError && error.code === \"wallet_rejected\")\n"],"mappings":"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"}
package/dist/client.js CHANGED
@@ -1,2 +1,2 @@
1
- import { C as e, L as t, R as n, S as r, a as i, b as a, c as o, i as s, n as c, o as l, r as u, s as d, t as f, v as p, y as m, z as h } from "./client-CWX6QpLa.js";
1
+ import { C as e, L as t, R as n, S as r, a as i, b as a, c as o, i as s, n as c, o as l, r as u, s as d, t as f, v as p, y as m, z as h } from "./client-BpzCZes3.js";
2
2
  export { p as BillingError, f as CANCEL_REASON_MAX, c as CANCEL_REASON_MIN, u as RETRY_BUDGET_MS, s as WalletRejectedError, t as amountToDecimal, i as createBillingClient, n as decimalToAmount, h as formatAmount, m as isBillingError, a as isServerError, l as isWalletAction, d as isWalletRejection, r as readBillingError, o as signWalletAction, e as toBillingError };
@@ -1,4 +1,4 @@
1
- import { C as e, c as t, o as n, x as r } from "./client-CWX6QpLa.js";
1
+ import { C as e, c as t, o as n, x as r } from "./client-BpzCZes3.js";
2
2
  import { createContext as i, useCallback as a, useContext as o, useEffect as s, useMemo as c, useRef as l, useState as u, useSyncExternalStore as d } from "react";
3
3
  //#region src/react/context.ts
4
4
  var f = i(null);
@@ -108,19 +108,19 @@ function b(r = {}) {
108
108
  i,
109
109
  s
110
110
  ]), C = a(async (r, a, o) => {
111
- f(r, "change_tier");
111
+ f(r, "change");
112
112
  try {
113
- let e = await i.changeTier(r, a);
113
+ let e = await i.changeSubscription(r, a);
114
114
  if (e.status === "requires_action" && n(e.next_action) && o) {
115
115
  f(r, "signing");
116
116
  let n = await t(e.next_action, o);
117
- f(r, "confirming"), e = await i.changeTier(r, {
117
+ f(r, "confirming"), e = await i.changeSubscription(r, {
118
118
  ...a,
119
119
  signature: n
120
120
  });
121
121
  }
122
122
  return s({
123
- type: "subscription.tier_changed",
123
+ type: "subscription.changed",
124
124
  subscriptionId: r,
125
125
  change: e
126
126
  }), e;
@@ -144,7 +144,7 @@ function b(r = {}) {
144
144
  cancel: b,
145
145
  resume: x,
146
146
  setPaymentMethod: S,
147
- changeTier: C
147
+ changeSubscription: C
148
148
  };
149
149
  }
150
150
  function x(e = {}) {
@@ -202,9 +202,9 @@ function S() {
202
202
  r,
203
203
  d
204
204
  ]), h = a(async (n, i) => {
205
- s(n, "collection");
205
+ s(n, "default");
206
206
  try {
207
- await t.setCollectionPaymentMethod({
207
+ await t.setDefaultPaymentMethod({
208
208
  currency: i,
209
209
  paymentMethodId: n
210
210
  });
@@ -212,14 +212,14 @@ function S() {
212
212
  return d((t) => ({
213
213
  ...t,
214
214
  data: t.data.map((t) => {
215
- let r = (t.collection_currencies ?? []).filter((t) => t !== e);
215
+ let r = (t.default_currencies ?? []).filter((t) => t !== e);
216
216
  return {
217
217
  ...t,
218
- collection_currencies: t.id === n ? [...r, e] : r
218
+ default_currencies: t.id === n ? [...r, e] : r
219
219
  };
220
220
  })
221
221
  })), r({
222
- type: "payment_method.collection_changed",
222
+ type: "payment_method.default_changed",
223
223
  paymentMethodId: n
224
224
  }), null;
225
225
  } catch (t) {
@@ -242,7 +242,7 @@ function S() {
242
242
  adding: c,
243
243
  add: f,
244
244
  remove: m,
245
- setCollection: h
245
+ setDefault: h
246
246
  };
247
247
  }
248
248
  function C(e = {}) {
@@ -338,4 +338,4 @@ function E() {
338
338
  //#endregion
339
339
  export { C as a, f as c, h as d, g as f, S as i, m as l, T as n, x as o, E as r, b as s, w as t, p as u };
340
340
 
341
- //# sourceMappingURL=config-DZ97SQG2.js.map
341
+ //# sourceMappingURL=config-qLcHvK0Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-qLcHvK0Q.js","names":[],"sources":["../src/react/context.ts","../src/react/remote.ts","../src/react/hooks.ts","../src/react/config.ts"],"sourcesContent":["import { createContext, useContext } from \"react\"\n\nimport type { BillingClient } from \"../client/client\"\nimport type { SubscriptionChange } from \"../client/types\"\nimport type { ConfigStore } from \"./config\"\n\nexport type BillingChange =\n | {\n type: \"subscription.canceled\" | \"subscription.resumed\"\n subscriptionId: string\n }\n | {\n type: \"subscription.payment_method_changed\"\n subscriptionId: string\n /** null: the subscription follows the default card. */\n paymentMethodId: string | null\n }\n | {\n type: \"subscription.changed\"\n subscriptionId: string\n /** `status` may still be `processing` or `requires_action`. */\n change: SubscriptionChange\n }\n | {\n type:\n | \"payment_method.added\"\n | \"payment_method.removed\"\n | \"payment_method.default_changed\"\n paymentMethodId: string\n }\n\nexport interface BillingContextValue {\n client: BillingClient\n /** Bumped after every mutation; hooks refetch on change. */\n version: number\n notify(change: BillingChange): void\n /** Refetch every hook after a host-side change such as a plan switch. */\n refresh(): void\n /** The shared `GET /config`; read it with `useConfig()`. */\n config: ConfigStore\n}\n\nexport const BillingContext = createContext<BillingContextValue | null>(null)\n\nexport function useBillingContext(): BillingContextValue {\n const ctx = useContext(BillingContext)\n if (!ctx) throw new Error(\"billing-ui: wrap the tree in <BillingProvider>\")\n return ctx\n}\n\nexport const useBillingClient = (): BillingClient => useBillingContext().client\n\nexport const useBillingRefresh = (): (() => void) => useBillingContext().refresh\n\n/** The billing context when a BillingProvider is present, else null. */\nexport const useOptionalBillingContext = (): BillingContextValue | null =>\n useContext(BillingContext)\n","import { useCallback, useEffect, useRef, useState } from \"react\"\n\nimport { toBillingError, type BillingError } from \"../client/errors\"\n\nexport interface RemoteState<T> {\n data: T | null\n loading: boolean\n error: BillingError | null\n refetch: () => void\n}\n\n// Keyed fetch that keeps the previous data while a newer key loads, so a\n// refetch after a mutation never flashes an empty list.\nexport function useRemote<T>(\n key: string,\n load: (signal: AbortSignal) => Promise<T>\n): RemoteState<T> & { replace: (update: (data: T) => T) => void } {\n const [nonce, setNonce] = useState(0)\n const request = `${key}|${nonce}`\n const [state, setState] = useState<{\n request: string | null\n data: T | null\n error: BillingError | null\n }>({ request: null, data: null, error: null })\n const loadRef = useRef(load)\n useEffect(() => {\n loadRef.current = load\n })\n\n useEffect(() => {\n const ctl = new AbortController()\n loadRef.current(ctl.signal).then(\n (data) => setState({ request, data, error: null }),\n (err: unknown) => {\n if (!ctl.signal.aborted)\n setState((s) => ({\n request,\n data: s.data,\n error: toBillingError(err),\n }))\n }\n )\n return () => ctl.abort()\n }, [request])\n\n const refetch = useCallback(() => setNonce((n) => n + 1), [])\n const replace = useCallback(\n (update: (data: T) => T) =>\n setState((s) => (s.data === null ? s : { ...s, data: update(s.data) })),\n []\n )\n return {\n data: state.data,\n loading: state.request !== request,\n error: state.request === request ? state.error : null,\n refetch,\n replace,\n }\n}\n","import { useCallback, useMemo, useState } from \"react\"\n\nimport {\n isWalletAction,\n signWalletAction,\n type SendSolanaTransaction,\n type SubscriptionChangeInput,\n} from \"../client/client\"\nimport { localError, toBillingError, type BillingError } from \"../client/errors\"\nimport type {\n NewCard,\n Payment,\n PaymentMethod,\n Product,\n Subscription,\n SubscriptionChange,\n} from \"../client/types\"\nimport { useBillingContext } from \"./context\"\nimport { useRemote } from \"./remote\"\n\n// Actions never throw: they resolve to null on success or the error.\nexport type ActionResult = Promise<BillingError | null>\n\n/** `signing` and `confirming` are a wallet step's stages. */\nexport type SubscriptionAction =\n | \"cancel\"\n | \"resume\"\n | \"payment_method\"\n | \"change\"\n | \"signing\"\n | \"confirming\"\n\nexport interface SubscriptionsOptions {\n /** Server filter; default `all`. */\n status?: string\n limit?: number\n}\n\nexport interface SubscriptionsState {\n subscriptions: Subscription[] | null\n /** The next page's cursor; null on the last page. */\n nextCursor: string | null\n loading: boolean\n error: BillingError | null\n refetch: () => void\n /** In-flight action per subscription id. */\n pending: Readonly<Record<string, SubscriptionAction>>\n /**\n * Cancels at period end. A Solana subscription is canceled by the wallet:\n * pass `sendTransaction`; without it the cancel resolves to a\n * `wallet_required` error.\n */\n cancel: (\n subscriptionId: string,\n reason: string,\n sendTransaction?: SendSolanaTransaction\n ) => ActionResult\n resume: (subscriptionId: string) => ActionResult\n /** `null` makes the subscription follow the default card. */\n setPaymentMethod: (\n subscriptionId: string,\n paymentMethodId: string | null\n ) => ActionResult\n /**\n * Resolves to the change, whose `status` may still be `processing` or\n * `requires_action`, or to the error. A Solana change is signed with\n * `sendTransaction` and resolves once the chain confirms it.\n */\n changeSubscription: (\n subscriptionId: string,\n input: SubscriptionChangeInput & { idempotencyKey: string },\n sendTransaction?: SendSolanaTransaction\n ) => Promise<SubscriptionChange | BillingError>\n}\n\nfunction usePending<A extends string>() {\n const [pending, setPending] = useState<Readonly<Record<string, A>>>({})\n const mark = useCallback((id: string, action: A | null) => {\n setPending((p) => {\n const next = { ...p }\n if (action) next[id] = action\n else delete next[id]\n return next\n })\n }, [])\n return [pending, mark] as const\n}\n\nconst walletRequired = () =>\n localError(\"wallet_required\", \"A wallet must sign this action.\")\n\nexport function useSubscriptions(\n options: SubscriptionsOptions = {}\n): SubscriptionsState {\n const { client, version, notify } = useBillingContext()\n const status = options.status ?? \"all\"\n const limit = options.limit ?? 100\n const remote = useRemote(`${status}|${limit}|${version}`, (signal) =>\n client.listSubscriptions({ status, limit, signal })\n )\n const [pending, mark] = usePending<SubscriptionAction>()\n const { replace } = remote\n\n const patchRow = useCallback(\n (next: Subscription) =>\n replace((page) => ({\n ...page,\n data: page.data.map((s) => (s.id === next.id ? next : s)),\n })),\n [replace]\n )\n\n const act = useCallback(\n async (\n id: string,\n action: SubscriptionAction,\n run: () => Promise<Subscription>,\n done: (subscription: Subscription) => void\n ): ActionResult => {\n mark(id, action)\n try {\n const next = await run()\n patchRow(next)\n done(next)\n return null\n } catch (err) {\n return toBillingError(err)\n } finally {\n mark(id, null)\n }\n },\n [mark, patchRow]\n )\n\n // A declined wallet prompt resolves to a `wallet_rejected` error.\n const cancel = useCallback(\n (id: string, reason: string, sendTransaction?: SendSolanaTransaction) =>\n act(\n id,\n \"cancel\",\n async () => {\n const sub = await client.cancelSubscription(id, { reason })\n if (!sub.next_action) return sub\n if (!isWalletAction(sub.next_action) || !sendTransaction)\n throw walletRequired()\n mark(id, \"signing\")\n const signature = await signWalletAction(\n sub.next_action,\n sendTransaction\n )\n mark(id, \"confirming\")\n return client.cancelSubscription(id, { reason, signature })\n },\n () => notify({ type: \"subscription.canceled\", subscriptionId: id })\n ),\n [act, client, mark, notify]\n )\n\n const resume = useCallback(\n (id: string) =>\n act(\n id,\n \"resume\",\n () => client.resumeSubscription(id),\n () => notify({ type: \"subscription.resumed\", subscriptionId: id })\n ),\n [act, client, notify]\n )\n\n const setPaymentMethod = useCallback(\n (id: string, paymentMethodId: string | null) =>\n act(\n id,\n \"payment_method\",\n () => client.setSubscriptionPaymentMethod(id, paymentMethodId),\n () =>\n notify({\n type: \"subscription.payment_method_changed\",\n subscriptionId: id,\n paymentMethodId,\n })\n ),\n [act, client, notify]\n )\n\n // An upgrade may open a successor subscription: notify refetches the list.\n const changeSubscription = useCallback(\n async (\n id: string,\n input: SubscriptionChangeInput & { idempotencyKey: string },\n sendTransaction?: SendSolanaTransaction\n ) => {\n mark(id, \"change\")\n try {\n let change = await client.changeSubscription(id, input)\n if (\n change.status === \"requires_action\" &&\n isWalletAction(change.next_action) &&\n sendTransaction\n ) {\n mark(id, \"signing\")\n const signature = await signWalletAction(\n change.next_action!,\n sendTransaction\n )\n mark(id, \"confirming\")\n change = await client.changeSubscription(id, { ...input, signature })\n }\n notify({\n type: \"subscription.changed\",\n subscriptionId: id,\n change,\n })\n return change\n } catch (err) {\n return toBillingError(err)\n } finally {\n mark(id, null)\n }\n },\n [client, mark, notify]\n )\n\n return {\n subscriptions: remote.data?.data ?? null,\n nextCursor: remote.data?.next_cursor ?? null,\n loading: remote.loading,\n error: remote.error,\n refetch: remote.refetch,\n pending,\n cancel,\n resume,\n setPaymentMethod,\n changeSubscription,\n }\n}\n\nexport interface ProductsState {\n products: Product[] | null\n /** The cursor of the next page; null on the last. */\n nextCursor: string | null\n loading: boolean\n error: BillingError | null\n refetch: () => void\n}\n\n/** The catalog: active products with their active prices. */\nexport function useProducts(options: { limit?: number } = {}): ProductsState {\n const { client } = useBillingContext()\n const limit = options.limit ?? 100\n const remote = useRemote(`${limit}`, (signal) =>\n client.listProducts({ limit, signal })\n )\n return {\n products: remote.data?.data ?? null,\n nextCursor: remote.data?.next_cursor ?? null,\n loading: remote.loading,\n error: remote.error,\n refetch: remote.refetch,\n }\n}\n\nexport type PaymentMethodAction = \"remove\" | \"default\"\n\nexport interface PaymentMethodsState {\n methods: PaymentMethod[] | null\n loading: boolean\n error: BillingError | null\n refetch: () => void\n pending: Readonly<Record<string, PaymentMethodAction>>\n adding: boolean\n add: (card: NewCard) => ActionResult\n remove: (paymentMethodId: string) => ActionResult\n /** Makes the card the default for the currency. */\n setDefault: (paymentMethodId: string, currency: string) => ActionResult\n}\n\nexport function usePaymentMethods(): PaymentMethodsState {\n const { client, version, notify } = useBillingContext()\n const remote = useRemote(`${version}`, (signal) =>\n client.listPaymentMethods({ signal })\n )\n const [pending, mark] = usePending<PaymentMethodAction>()\n const [adding, setAdding] = useState(false)\n const { replace } = remote\n\n const add = useCallback(\n async (card: NewCard): ActionResult => {\n setAdding(true)\n try {\n const method = await client.addPaymentMethod(card)\n replace((page) => ({ ...page, data: [...page.data, method] }))\n notify({ type: \"payment_method.added\", paymentMethodId: method.id })\n return null\n } catch (err) {\n return toBillingError(err)\n } finally {\n setAdding(false)\n }\n },\n [client, notify, replace]\n )\n\n const remove = useCallback(\n async (id: string): ActionResult => {\n mark(id, \"remove\")\n try {\n await client.removePaymentMethod(id)\n replace((page) => ({\n ...page,\n data: page.data.filter((m) => m.id !== id),\n }))\n notify({ type: \"payment_method.removed\", paymentMethodId: id })\n return null\n } catch (err) {\n return toBillingError(err)\n } finally {\n mark(id, null)\n }\n },\n [client, mark, notify, replace]\n )\n\n const setDefault = useCallback(\n async (id: string, currency: string): ActionResult => {\n mark(id, \"default\")\n try {\n await client.setDefaultPaymentMethod({\n currency,\n paymentMethodId: id,\n })\n const code = currency.toUpperCase()\n replace((page) => ({\n ...page,\n data: page.data.map((m) => {\n const others = (m.default_currencies ?? []).filter(\n (c) => c !== code\n )\n return {\n ...m,\n default_currencies: m.id === id ? [...others, code] : others,\n }\n }),\n }))\n notify({\n type: \"payment_method.default_changed\",\n paymentMethodId: id,\n })\n return null\n } catch (err) {\n return toBillingError(err)\n } finally {\n mark(id, null)\n }\n },\n [client, mark, notify, replace]\n )\n\n return {\n methods: remote.data?.data ?? null,\n loading: remote.loading,\n error: remote.error,\n refetch: remote.refetch,\n pending,\n adding,\n add,\n remove,\n setDefault,\n }\n}\n\nexport interface PaymentsOptions {\n pageSize?: number\n /** Filter by rail. */\n rail?: string\n}\n\nexport interface PaymentsState {\n payments: Payment[] | null\n /** Zero-based. */\n page: number\n hasMore: boolean\n loading: boolean\n error: BillingError | null\n next: () => void\n previous: () => void\n refetch: () => void\n}\n\nexport function usePayments(options: PaymentsOptions = {}): PaymentsState {\n const { client, version } = useBillingContext()\n const pageSize = options.pageSize ?? 20\n // cursors[i] reads page i of this filter; page 0 is the newest payments.\n const filter = `${pageSize}|${options.rail ?? \"\"}`\n const [state, setState] = useState({\n filter,\n cursors: [null] as (string | null)[],\n })\n const cursors = useMemo(\n () => (state.filter === filter ? state.cursors : [null]),\n [state, filter]\n )\n const page = cursors.length - 1\n const cursor = cursors[page]\n const remote = useRemote(`${filter}|${cursor ?? \"\"}|${version}`, (signal) =>\n client.listPayments({\n limit: pageSize,\n cursor,\n rail: options.rail,\n signal,\n })\n )\n const data = remote.data\n const nextCursor = data?.next_cursor ?? null\n return {\n payments: data?.data ?? null,\n page,\n hasMore: nextCursor !== null,\n loading: remote.loading,\n error: remote.error,\n next: useCallback(() => {\n if (nextCursor !== null)\n setState({ filter, cursors: [...cursors, nextCursor] })\n }, [filter, cursors, nextCursor]),\n previous: useCallback(() => {\n if (cursors.length > 1)\n setState({ filter, cursors: cursors.slice(0, -1) })\n }, [filter, cursors]),\n refetch: remote.refetch,\n }\n}\n","import { useEffect, useMemo, useSyncExternalStore } from \"react\"\n\nimport type { BillingClient } from \"../client/client\"\nimport { toBillingError, type BillingError } from \"../client/errors\"\nimport type { CurrencyScales, PublicConfig } from \"../client/types\"\nimport { useBillingContext } from \"./context\"\n\nexport interface ConfigState {\n config: PublicConfig | null\n loading: boolean\n error: BillingError | null\n refetch: () => void\n}\n\ninterface Snapshot {\n config: PublicConfig | null\n loading: boolean\n error: BillingError | null\n}\n\n/** One shared copy of `GET /config` per client, fetched on first use. */\nexport interface ConfigStore {\n subscribe(listener: () => void): () => void\n snapshot(): Snapshot\n /** Fetches the document unless it was already requested. */\n ensure(): void\n refetch(): void\n}\n\nexport function createConfigStore(client: BillingClient): ConfigStore {\n let snapshot: Snapshot = { config: null, loading: true, error: null }\n let started = false\n let latest = 0\n const listeners = new Set<() => void>()\n const set = (next: Snapshot) => {\n snapshot = next\n for (const listener of listeners) listener()\n }\n const load = () => {\n started = true\n const request = ++latest\n if (!snapshot.loading) set({ ...snapshot, loading: true })\n client.getConfig().then(\n (config) => {\n if (request === latest) set({ config, loading: false, error: null })\n },\n (err: unknown) => {\n if (request === latest)\n set({\n config: snapshot.config,\n loading: false,\n error: toBillingError(err),\n })\n }\n )\n }\n return {\n subscribe(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n snapshot: () => snapshot,\n ensure() {\n if (!started) load()\n },\n refetch: load,\n }\n}\n\n/**\n * The deployment's public configuration (`GET /config`), fetched once per\n * `BillingProvider` and shared by every component that reads it.\n */\nexport function useConfig(): ConfigState {\n const { config: store } = useBillingContext()\n const snapshot = useSyncExternalStore(\n store.subscribe,\n store.snapshot,\n store.snapshot\n )\n useEffect(() => store.ensure(), [store])\n return { ...snapshot, refetch: store.refetch }\n}\n\n/**\n * Currency scales: the server's registry, under the client's pinned copy and\n * host overrides, which stand alone until the registry loads.\n */\nexport function useCurrencyScales(): CurrencyScales {\n const { client } = useBillingContext()\n const { config } = useConfig()\n return useMemo(() => {\n const served = Object.fromEntries(\n (config?.currencies ?? []).map((c) => [c.code.toUpperCase(), c.decimals])\n )\n return { ...served, ...client.currencies }\n }, [config, client])\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  import { Translator } from './messages.ts';
2
2
  export declare const MessagesContext: import('react').Context<Translator>;
3
- /** English defaults when rendered outside an `BillingUiProvider`. */
3
+ /** English defaults when rendered outside a `BillingUiProvider`. */
4
4
  export declare function useMessages(): Translator;
@@ -51,7 +51,7 @@ export interface Translator {
51
51
  * category, then `<key>.other`. `{count}` is locale-formatted.
52
52
  */
53
53
  plural(key: PluralKey, count: number, vars?: MessageVars): string;
54
- /** Message for an billing error, error code, or thrown value. */
54
+ /** Message for a billing error, error code, or thrown value. */
55
55
  error(error: unknown, vars?: MessageVars): string;
56
56
  }
57
57
  export declare function createTranslator(messages: BillingUiMessages, hostT?: BillingUiTranslate, locale?: string): Translator;