UNPKG

@better-auth-ui/core

Version:

Authentication components and data utilities for [Better Auth](https://better-auth.com), available for React and Solid.

548 lines (547 loc) 15.8 kB
import { t as e } from "../../create-auth-plugin-BXWyolC8.js"; import { skipToken as t } from "@tanstack/query-core"; //#region src/plugins/billing/billing-adapter.ts var n = (e) => e.type === "user" ? `user:${e.userId}` : `organization:${e.organizationId}:${e.organizationSlug}`; function r(e) { if (!(!e.url || typeof window > "u")) try { let t = new URL(e.url, window.location.href); (t.protocol === "http:" || t.protocol === "https:") && window.location.assign(t.href); } catch {} } //#endregion //#region src/plugins/billing/billing-localization.ts var i = { billing: "Billing", billingDescription: "Manage plans, subscription details, seats, and usage.", plans: "Plans", currentPlan: "Current plan", choosePlan: "Choose plan", changePlan: "Change plan", perMonth: "per month", perYear: "per year", oneTime: "one time", popular: "Popular", subscription: "Subscription", noSubscription: "No active subscription", noSubscriptionDescription: "Choose a plan to start a subscription.", manageBilling: "Manage billing", renewsOn: "Renews on {{date}}", endsOn: "Ends on {{date}}", cancelSubscription: "Cancel subscription", cancelSubscriptionTitle: "Cancel subscription?", cancelSubscriptionDescription: "Your access remains available until the end of the current billing period.", restoreSubscription: "Restore subscription", restoreSubscriptionTitle: "Restore subscription?", restoreSubscriptionDescription: "Your subscription will continue renewing on its current plan.", confirm: "Confirm", cancel: "Cancel", seats: "Seats", updateSeats: "Update seats", usage: "Usage", unlimited: "Unlimited", used: "{{used}} used", loadingBilling: "Loading billing information" }, a = { all: ["auth", "billing"], scope: (e) => [...a.all, n(e)], plans: (e) => [...a.scope(e), "plans"], state: (e) => [...a.scope(e), "state"] }, o = (e, n) => ({ queryKey: n ? a.plans(n) : [ ...a.all, null, "plans" ], queryFn: n ? ({ signal: t }) => e.listPlans(n, t) : t }), s = (e, n) => ({ queryKey: n ? a.state(n) : [ ...a.all, null, "state" ], queryFn: n ? ({ signal: t }) => e.getState(n, t) : t }), c = { all: ["auth", "billing"], checkout: (e) => [ ...c.all, n(e), "checkout" ], portal: (e) => [ ...c.all, n(e), "portal" ], cancel: (e) => [ ...c.all, n(e), "cancel" ], restore: (e) => [ ...c.all, n(e), "restore" ], seats: (e) => [ ...c.all, n(e), "seats" ] }, l = (e) => ({ awaits: [a.state(e)] }), u = (e, t) => ({ mutationKey: c.checkout(t), mutationFn: (n) => e.checkout(t, n), meta: l(t) }), d = (e, t) => ({ mutationKey: c.portal(t), mutationFn: () => e.openPortal(t) }), f = (e, t) => ({ mutationKey: c.cancel(t), mutationFn: (n) => e.cancel(t, n), meta: l(t) }), p = (e, t) => ({ mutationKey: c.restore(t), mutationFn: (n) => e.restore(t, n), meta: l(t) }), m = (e, t) => ({ mutationKey: c.seats(t), mutationFn: ({ subscriptionId: n, seats: r }) => e.updateSeats(t, n, r), meta: l(t) }), h = e("billing", (e) => { let t = e.user ?? !0, n = e.organization ?? !1; if (t && e.adapter.scopes?.user === !1) throw Error(`${e.adapter.id} does not support user billing.`); if (n && e.adapter.scopes?.organization === !1) throw Error(`${e.adapter.id} does not support explicit organization billing.`); return { adapter: e.adapter, localization: { ...i, ...e.localization }, user: t, organization: n, viewPaths: { settings: { billing: e.path ?? "billing" } } }; }), g = (e) => e && typeof e == "object" ? e : void 0, _ = (e) => { let t = g(e), n = t?.error; if (n) { let e = g(n); throw Error(String(e?.message ?? n)); } return t && "data" in t ? t.data : e; }, v = (e) => { let t = _(e); if (Array.isArray(t)) return t; let n = g(t), r = n?.items ?? g(n?.result)?.items; return Array.isArray(r) ? r : []; }, y = (e) => typeof e == "string" ? e : void 0, b = (e) => typeof e == "number" && Number.isFinite(e) ? e : void 0, x = (e) => { if (!e) return; let t = new Date(e); return Number.isNaN(t.getTime()) ? void 0 : t; }, S = (e) => { let t = y(e); return t === "cancelled" ? "canceled" : t === "scheduled_cancel" ? "active" : t === "active" || t === "trialing" || t === "past_due" || t === "paused" || t === "canceled" || t === "incomplete" ? t : "unknown"; }, C = (e) => { let t = y(e); if (t === "month" || t === "monthly") return "month"; if (t === "year" || t === "yearly" || t === "annual") return "year"; if (t === "one-time" || t === "one_time") return "one-time"; }, w = (e) => { let t = g(e), n = y(t?.id) ?? y(t?.subscriptionId) ?? y(t?.subscription_id) ?? y(t?.creemSubscriptionId); if (!t || !n) return; let r = g(t.product), i = g(t.plan), a = g(t.price) ?? g(i?.price), o = g(t.currentPeriod), s = t.canceledAt ?? t.canceled_at ?? t.cancelledAt ?? t.cancelled_at; return { id: n, planId: y(t.planId) ?? y(t.plan) ?? y(t.productId) ?? y(t.product_id) ?? y(r?.id) ?? y(i?.id) ?? "unknown", planName: y(t.planName) ?? y(r?.name) ?? y(i?.name) ?? y(t.name), priceId: y(t.priceId) ?? y(t.price_id) ?? y(a?.id), interval: C(t.interval ?? t.billingInterval ?? t.recurringInterval ?? t.recurring_interval ?? a?.interval) ?? (typeof t.annual == "boolean" ? t.annual ? "year" : "month" : void 0), status: S(t.status), currentPeriodEnd: x(t.currentPeriodEnd ?? t.current_period_end ?? t.currentPeriodEndDate ?? t.current_period_end_date ?? t.periodEnd ?? t.period_end ?? t.nextBillingDate ?? t.next_billing_date ?? o?.end), cancelAtPeriodEnd: !!(t.cancelAtPeriodEnd ?? t.cancel_at_period_end ?? t.cancelAtNextBillingDate ?? t.cancel_at_next_billing_date ?? t.status === "scheduled_cancel"), canceledAt: x(s), seats: b(t.seats) ?? b(t.quantity) ?? b(t.units) }; }, T = (e) => { let t = g(e), n = g(t?.meter), r = y(t?.id) ?? y(n?.id); if (!t || !r) return; let i = b(t.consumedUnits) ?? b(t.consumed_units) ?? b(t.used) ?? 0, a = b(t.creditedUnits) ?? b(t.credited_units) ?? b(t.limit); return { id: r, label: y(t.label) ?? y(n?.name) ?? y(n?.slug) ?? r, used: i, limit: a, unit: y(t.unit) ?? y(n?.unit) }; }, E = (e) => { let t = g(_(e)); return { url: y(t?.url ?? t?.paymentUrl ?? t?.redirectUrl ?? t?.redirect_url ?? t?.customerPortalUrl) }; }, D = (e, t) => { if (e.type === "organization") throw Error(`${t} does not accept an explicit organization ID in its Better Auth client API.`); }, O = (e, t) => Object.entries(t ?? {}).find(([, t]) => t === e)?.[0] ?? e, k = (e) => Object.entries(g(e.balances) ?? {}).map(([e, t]) => { let n = g(t), r = g(n?.feature), i = n?.unlimited === !0; return { id: e, label: y(r?.name) ?? e, used: b(n?.usage) ?? 0, limit: i ? void 0 : b(n?.granted), unit: y(r?.displayName) ?? y(r?.name) }; }), A = (e) => { let t = g(e), n = g(t?.consumption), r = y(t?.code), i = b(n?.unitsUsed); if (!(!r || i === void 0)) return { id: r, label: y(t?.name) ?? r, used: i, limit: n?.unlimited === !0 ? void 0 : b(n?.includedUnits), unit: y(t?.unitName) }; }, j = (e) => ({ referenceId: e.type === "organization" ? e.organizationId : e.userId, customerType: e.type }); function M(e, t) { let n = (e) => t.plans.find((t) => t.id === e), r = async (r, i, a) => { let o = n(i.planId)?.prices.find((e) => e.id === i.priceId); return E(await e.subscription.upgrade({ plan: i.planId, annual: o?.interval === "year", ...j(r), ...a ? { subscriptionId: a } : {}, ...i.seats ? { seats: i.seats } : {}, successUrl: t.successUrl, cancelUrl: t.cancelUrl, returnUrl: t.returnUrl, disableRedirect: !0 })); }, i = async (t, n) => ({ subscription: v(await e.subscription.list({ query: j(t), fetchOptions: { signal: n, throw: !0 } })).map(w).filter((e) => !!e)[0], usage: [] }); return { id: "stripe", supports: { cancel: !0, restore: !0, seats: !0 }, async listPlans() { return t.plans; }, getState: i, checkout: (e, t) => r(e, t), async openPortal(n) { return E(await e.subscription.billingPortal({ ...j(n), returnUrl: t.returnUrl, disableRedirect: !0 })); }, async cancel(n, r) { return E(await e.subscription.cancel({ ...j(n), subscriptionId: r, returnUrl: t.returnUrl, disableRedirect: !0 })); }, async restore(t, n) { return E(await e.subscription.restore({ ...j(t), subscriptionId: n })); }, async updateSeats(e, t, a) { let o = (await i(e)).subscription, s = o?.planId, c = s ? n(s) : void 0, l = o?.priceId ? c?.prices.find((e) => e.id === o.priceId) : o?.interval ? c?.prices.find((e) => e.interval === o.interval) : c?.prices.length === 1 ? c.prices[0] : void 0; if (!c || !l) throw Error("The current billing price is unavailable."); return r(e, { planId: c.id, priceId: l.id, seats: a }, t); } }; } function N(e, t) { let n = (e) => Object.entries(t.products ?? {}).find(([, t]) => t.value === e)?.[0] ?? e, r = async (t) => E(await e.customer.portal({ fetchOptions: { throw: !0 } })); return { id: "polar", supports: { cancel: !1, restore: !1, seats: !1 }, async listPlans() { return t.plans; }, async getState(t, r) { let i = { page: 1, limit: 100, active: !0, ...t.type === "organization" ? { referenceId: t.organizationId } : {} }, [a, o] = await Promise.all([e.customer.subscriptions.list({ query: i, fetchOptions: { signal: r, throw: !0 } }), e.usage.meters.list({ query: { page: 1, limit: 100 }, fetchOptions: { signal: r, throw: !0 } })]), s = v(a).map(w).find(Boolean); return { subscription: s ? { ...s, planId: n(s.planId) } : void 0, usage: v(o).map(T).filter((e) => !!e) }; }, async checkout(n, r) { let i = t.products?.[r.planId]; return E(await e.checkout({ ...i?.type === "product" ? { products: [i.value] } : { slug: i?.value ?? r.planId }, ...n.type === "organization" ? { referenceId: n.organizationId } : {}, ...r.seats ? { seats: r.seats } : {}, successUrl: t.successUrl, redirect: !1 })); }, openPortal: r, async cancel(e) { return r(e); }, async restore(e) { return r(e); }, async updateSeats(e) { return r(e); } }; } function P(e, t) { let n = async (t, n) => { D(t, "Autumn"); let r = g(await e.getOrCreateCustomer({ expand: ["subscriptions.plan", "balances.feature"] })); return { subscription: (Array.isArray(r?.subscriptions) ? r.subscriptions : []).map(w).find(Boolean), usage: r ? k(r) : [] }; }, r = async (t, n) => (D(t, "Autumn"), E(await e.updateSubscription(n))); return { id: "autumn", scopes: { user: !0, organization: !1 }, supports: { cancel: !0, restore: !0, seats: !!t.seatLicensePlans }, async listPlans(e) { return D(e, "Autumn"), t.plans; }, getState: n, async checkout(n, r) { D(n, "Autumn"); let i = t.seatLicensePlans?.[r.planId]; return E(await e.attach({ planId: r.planId, successUrl: t.successUrl, redirectMode: "always", ...i && r.seats ? { licenseQuantities: [{ licensePlanId: i, quantity: r.seats }] } : {} })); }, async openPortal(n) { return D(n, "Autumn"), E(await e.openCustomerPortal({ returnUrl: t.returnUrl })); }, cancel: (e, t) => r(e, { subscriptionId: t, cancelAction: "cancel_end_of_cycle" }), restore: (e, t) => r(e, { subscriptionId: t, cancelAction: "uncancel" }), async updateSeats(e, i, a) { let o = (await n(e)).subscription?.planId, s = o ? t.seatLicensePlans?.[o] : void 0; if (!s) throw Error("The Autumn seat license plan is unavailable."); return r(e, { subscriptionId: i, licenseQuantities: [{ licensePlanId: s, quantity: a }] }); } }; } function F(e, t) { let n = async (t) => (D(t, "Creem"), E(await e.creem.createPortal())); return { id: "creem", scopes: { user: !0, organization: !1 }, supports: { cancel: !0, restore: !1, seats: !1 }, async listPlans(e) { return D(e, "Creem"), t.plans; }, async getState(n) { D(n, "Creem"); let r = w(g(_(await e.creem.hasAccessGranted()))?.subscription); return { subscription: r ? { ...r, planId: O(r.planId, t.products) } : void 0, usage: [] }; }, async checkout(n, r) { return D(n, "Creem"), E(await e.creem.createCheckout({ productId: t.products?.[r.planId] ?? r.planId, ...r.seats ? { units: r.seats } : {}, successUrl: t.successUrl })); }, openPortal: n, async cancel(t, n) { return D(t, "Creem"), E(await e.creem.cancelSubscription({ id: n })); }, restore: n, updateSeats: n }; } function I(e, t) { let n = async (t) => (D(t, "Dodo Payments"), E(await e.dodopayments.customer.portal())); return { id: "dodo-payments", scopes: { user: !0, organization: !1 }, supports: { cancel: !1, restore: !1, seats: !1 }, async listPlans(e) { return D(e, "Dodo Payments"), t.plans; }, async getState(n, r) { D(n, "Dodo Payments"); let i = v(await e.dodopayments.customer.subscriptions.list({ query: { limit: 100, page: 1 }, fetchOptions: { signal: r, throw: !0 } })).map(w).find(Boolean); if (!i) return { usage: [] }; let a = i.planId, o = Object.entries(t.products ?? {}).find(([, e]) => e.value === a)?.[0] ?? a; return { subscription: { ...i, planId: o }, usage: [] }; }, async checkout(n, r) { D(n, "Dodo Payments"); let i = t.products?.[r.planId]; return E(await e.dodopayments.checkoutSession({ ...i?.type === "product" ? { product_cart: [{ product_id: i.value, quantity: r.seats ?? 1 }] } : { slug: i?.value ?? r.planId }, referenceId: n.type === "user" ? n.userId : n.organizationId })); }, openPortal: n, cancel: n, restore: n, updateSeats: n }; } function L(e, t) { let n = async (t) => (D(t, "Commet"), E(await e.customer.portal())); return { id: "commet", scopes: { user: !0, organization: !1 }, supports: { cancel: !0, restore: !1, seats: !!t.seatFeatureCode }, async listPlans(e) { return D(e, "Commet"), t.plans; }, async getState(n, r) { D(n, "Commet"); let [i, a, o] = await Promise.all([ e.subscription.get({ signal: r, throw: !0 }), t.usage ? e.features.list({ signal: r, throw: !0 }) : void 0, t.seatFeatureCode ? e.seats.list({ signal: r, throw: !0 }) : void 0 ]), s = w(_(i)), c = t.seatFeatureCode ? g(g(_(o))?.[t.seatFeatureCode]) : void 0; return { subscription: s ? { ...s, planId: O(s.planId, t.planIds), seats: b(c?.current) ?? s.seats } : void 0, usage: t.usage ? v(a).map(A).filter((e) => !!e) : [] }; }, checkout: n, openPortal: n, async cancel(t) { return D(t, "Commet"), E(await e.subscription.cancel({ immediate: !1 }, { throw: !0 })); }, restore: n, async updateSeats(r, i, a) { return D(r, "Commet"), t.seatFeatureCode ? E(await e.seats.set({ featureCode: t.seatFeatureCode, count: a }, { throw: !0 })) : n(r); } }; } //#endregion export { u as billingCheckoutOptions, i as billingLocalization, c as billingMutationKeys, o as billingPlansOptions, h as billingPlugin, d as billingPortalOptions, a as billingQueryKeys, n as billingScopeKey, s as billingStateOptions, f as cancelBillingSubscriptionOptions, P as createAutumnBillingAdapter, L as createCommetBillingAdapter, F as createCreemBillingAdapter, I as createDodoPaymentsBillingAdapter, N as createPolarBillingAdapter, M as createStripeBillingAdapter, r as followBillingAction, p as restoreBillingSubscriptionOptions, m as updateBillingSeatsOptions };