@alexasomba/better-auth-paystack 2.2.0 → 2.4.1

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.
@@ -0,0 +1,145 @@
1
+ ---
2
+ name: subscriptions-and-transactions
3
+ description: >
4
+ Build Paystack transaction and subscription flows with @alexasomba/better-auth-paystack. Use for initialize/verify transaction, create/upgrade/cancel/restore/list subscriptions, products/plans, billing portal links, webhooks, chargeSubscriptionRenewal, syncPaystackProducts, and syncPaystackPlans.
5
+ type: core
6
+ library: "@alexasomba/better-auth-paystack"
7
+ library_version: "2.4.1" # x-release-please-version
8
+ sources:
9
+ - "alexasomba/better-auth-paystack:README.md"
10
+ - "alexasomba/better-auth-paystack:src/routes.ts"
11
+ - "alexasomba/better-auth-paystack:src/operations.ts"
12
+ - "alexasomba/better-auth-paystack:src/client.ts"
13
+ ---
14
+
15
+ ## Setup
16
+
17
+ Enable subscriptions with concrete Paystack plan metadata:
18
+
19
+ ```ts
20
+ import { paystack } from "@alexasomba/better-auth-paystack";
21
+
22
+ paystack({
23
+ secretKey: process.env.PAYSTACK_SECRET_KEY!,
24
+ webhook: {
25
+ secret: process.env.PAYSTACK_WEBHOOK_SECRET!,
26
+ },
27
+ subscription: {
28
+ enabled: true,
29
+ plans: [
30
+ {
31
+ name: "starter",
32
+ amount: 250_000,
33
+ currency: "NGN",
34
+ interval: "monthly",
35
+ planCode: "PLN_starter",
36
+ paystackId: "1001",
37
+ },
38
+ {
39
+ name: "team",
40
+ amount: 1_000_000,
41
+ currency: "NGN",
42
+ interval: "monthly",
43
+ planCode: "PLN_team",
44
+ paystackId: "1002",
45
+ limits: {
46
+ seats: 10,
47
+ teams: 3,
48
+ },
49
+ },
50
+ ],
51
+ },
52
+ });
53
+ ```
54
+
55
+ ## Core Patterns
56
+
57
+ ### Initialize and verify a transaction
58
+
59
+ Use the client plugin for browser-triggered checkout:
60
+
61
+ ```ts
62
+ const initialized = await authClient.transaction.initialize({
63
+ amount: 250_000,
64
+ email: "customer@example.com",
65
+ currency: "NGN",
66
+ metadata: {
67
+ product: "starter-pack",
68
+ },
69
+ });
70
+
71
+ const verified = await authClient.transaction.verify({
72
+ reference: initialized.data.reference,
73
+ });
74
+ ```
75
+
76
+ Do not trust a redirect callback alone. Always verify the Paystack reference before granting access or updating billing state.
77
+
78
+ ### Manage subscription lifecycle
79
+
80
+ Use canonical methods in new code:
81
+
82
+ ```ts
83
+ await authClient.subscription.create({
84
+ plan: "starter",
85
+ });
86
+
87
+ await authClient.subscription.upgrade({
88
+ plan: "team",
89
+ });
90
+
91
+ await authClient.subscription.cancel({
92
+ subscriptionId: "subscription_id",
93
+ });
94
+
95
+ await authClient.subscription.restore({
96
+ subscriptionId: "subscription_id",
97
+ });
98
+
99
+ const subscriptions = await authClient.subscription.list();
100
+ ```
101
+
102
+ Deprecated aliases:
103
+
104
+ - `subscription.disable` maps to `subscription.cancel`
105
+ - `subscription.enable` maps to `subscription.restore`
106
+
107
+ Keep aliases only for compatibility tests or migration examples.
108
+
109
+ ### Keep renewal and catalog sync server-side
110
+
111
+ These helpers are exported by the server package and are intentionally not client actions:
112
+
113
+ ```ts
114
+ import {
115
+ chargeSubscriptionRenewal,
116
+ syncPaystackPlans,
117
+ syncPaystackProducts,
118
+ } from "@alexasomba/better-auth-paystack";
119
+
120
+ export async function runBillingJob(ctx: unknown, options: unknown) {
121
+ await syncPaystackProducts(ctx, options);
122
+ await syncPaystackPlans(ctx, options);
123
+ await chargeSubscriptionRenewal(ctx, options, {
124
+ subscriptionId: "subscription_id",
125
+ });
126
+ }
127
+ ```
128
+
129
+ Use cron, background jobs, or trusted server functions. Do not call these from a browser component.
130
+
131
+ ## Common Mistakes
132
+
133
+ ### Mutating Paystack-managed subscriptions like local subscriptions
134
+
135
+ Seat-based or prorated subscription changes require locally managed subscription state. Paystack-managed subscriptions do not support every local mutation path.
136
+
137
+ Before implementing seat changes, check whether the target plan is local/seat-aware and whether the operation is supported by the helper being used.
138
+
139
+ ### Skipping webhook verification
140
+
141
+ Configure `webhook.secret` and let the plugin verify incoming webhook payloads. Do not process Paystack webhook bodies through an unrelated JSON route that bypasses the plugin endpoint.
142
+
143
+ ### Mixing plan name and Paystack plan code
144
+
145
+ Use `plan.name` for app-facing plan selection and `plan.planCode`/`paystackId` for Paystack identity. Do not send a Paystack plan code where the plugin expects the configured plan name.
@@ -0,0 +1,161 @@
1
+ ---
2
+ name: tanstack-start
3
+ description: >
4
+ Integrate @alexasomba/better-auth-paystack in TanStack Start. Use for Better Auth API routes, tanstackStartCookies(), server functions, getRequestHeaders(), authClient Paystack actions, admin billing server functions, and Cloudflare Workers deployment.
5
+ type: composition
6
+ library: "@alexasomba/better-auth-paystack"
7
+ library_version: "2.4.1" # x-release-please-version
8
+ sources:
9
+ - "alexasomba/better-auth-paystack:examples/tanstack/README.md"
10
+ - "alexasomba/better-auth-paystack:examples/tanstack/src/lib/auth.ts"
11
+ - "alexasomba/better-auth-paystack:examples/tanstack/src/lib/auth-client.ts"
12
+ - "alexasomba/better-auth-paystack:examples/tanstack/src/routes/api/auth/$.ts"
13
+ ---
14
+
15
+ ## Setup
16
+
17
+ Create the Better Auth server config with Paystack and `tanstackStartCookies()` last:
18
+
19
+ ```ts
20
+ import { betterAuth } from "better-auth";
21
+ import { tanstackStartCookies } from "better-auth/tanstack-start";
22
+ import { paystack } from "@alexasomba/better-auth-paystack";
23
+
24
+ export const auth = betterAuth({
25
+ baseURL: process.env.BETTER_AUTH_URL,
26
+ plugins: [
27
+ paystack({
28
+ secretKey: process.env.PAYSTACK_SECRET_KEY!,
29
+ webhook: {
30
+ secret: process.env.PAYSTACK_WEBHOOK_SECRET!,
31
+ },
32
+ subscription: {
33
+ enabled: true,
34
+ plans: [],
35
+ },
36
+ }),
37
+ tanstackStartCookies(),
38
+ ],
39
+ });
40
+ ```
41
+
42
+ Wire the catch-all auth route:
43
+
44
+ ```ts
45
+ import { createFileRoute } from "@tanstack/react-router";
46
+ import { auth } from "../../../lib/auth";
47
+
48
+ export const Route = createFileRoute("/api/auth/$")({
49
+ server: {
50
+ handlers: {
51
+ GET: ({ request }) => auth.handler(request),
52
+ POST: ({ request }) => auth.handler(request),
53
+ },
54
+ },
55
+ });
56
+ ```
57
+
58
+ Create the client plugin:
59
+
60
+ ```ts
61
+ import { createAuthClient } from "better-auth/client";
62
+ import { paystackClient } from "@alexasomba/better-auth-paystack/client";
63
+
64
+ export const authClient = createAuthClient({
65
+ plugins: [paystackClient()],
66
+ });
67
+ ```
68
+
69
+ ## Core Patterns
70
+
71
+ ### Use Paystack client actions in client components
72
+
73
+ ```tsx
74
+ import { authClient } from "../lib/auth-client";
75
+
76
+ export function SubscribeButton() {
77
+ return (
78
+ <button
79
+ type="button"
80
+ onClick={async () => {
81
+ await authClient.subscription.create({
82
+ plan: "starter",
83
+ });
84
+ }}
85
+ >
86
+ Subscribe
87
+ </button>
88
+ );
89
+ }
90
+ ```
91
+
92
+ Use client actions for checkout and user-triggered subscription lifecycle calls. Do not import server helpers into React components.
93
+
94
+ ### Use server functions for trusted billing operations
95
+
96
+ ```ts
97
+ import { createServerFn } from "@tanstack/react-start";
98
+ import { getRequestHeaders } from "@tanstack/react-start/server";
99
+ import { auth } from "./auth";
100
+ import { syncPaystackPlans } from "@alexasomba/better-auth-paystack";
101
+
102
+ export const syncPlans = createServerFn({ method: "POST" }).handler(async () => {
103
+ const session = await auth.api.getSession({
104
+ headers: await getRequestHeaders(),
105
+ });
106
+
107
+ if (!session?.user) {
108
+ throw new Response("Unauthorized", { status: 401 });
109
+ }
110
+
111
+ await syncPaystackPlans(await auth.$context, {
112
+ secretKey: process.env.PAYSTACK_SECRET_KEY!,
113
+ });
114
+
115
+ return { ok: true };
116
+ });
117
+ ```
118
+
119
+ Pass request headers when Better Auth needs session context.
120
+
121
+ ### Keep Cloudflare Worker dependencies compatible
122
+
123
+ The TanStack example deploys to Cloudflare Workers. Keep Better Auth companion packages on compatible versions. If `@better-auth/infra` pulls in `@better-auth/sso`, avoid mixing a beta SSO package with stable `better-auth`.
124
+
125
+ The known safe pin for this package version is:
126
+
127
+ ```yaml
128
+ overrides:
129
+ "@better-auth/sso": 1.6.9
130
+ ```
131
+
132
+ ## Common Mistakes
133
+
134
+ ### Putting `tanstackStartCookies()` before Paystack
135
+
136
+ `tanstackStartCookies()` should be last in the Better Auth plugin array so cookie handling wraps the final auth behavior.
137
+
138
+ ### Omitting auth headers in server functions
139
+
140
+ Wrong:
141
+
142
+ ```ts
143
+ const session = await auth.api.getSession();
144
+ ```
145
+
146
+ Correct:
147
+
148
+ ```ts
149
+ const session = await auth.api.getSession({
150
+ headers: await getRequestHeaders(),
151
+ });
152
+ ```
153
+
154
+ ### Debugging only root package builds
155
+
156
+ The root package can pass `vp pack` while the example Worker build fails. Reproduce Worker issues with:
157
+
158
+ ```bash
159
+ pnpm --filter ./examples/tanstack build
160
+ pnpm --filter ./examples/tanstack exec wrangler deploy --dry-run
161
+ ```
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-B5ZnlFrq.d.mts","names":["GenericEndpointContext","Session","User","Organization","Member","PaystackPaths","PaystackResponse","PaystackWebhookEvent","PaystackClient","PaystackCustomerClient","PaystackPlanClient","PaystackProductClient","PaystackSubscriptionClient","PaystackTransactionClient","components","PaystackCurrency","PaystackCheckoutChannel","PaystackTransaction","Date","id","reference","paystackId","referenceId","userId","amount","currency","status","plan","product","metadata","createdAt","updatedAt","PaystackProduct","name","description","price","quantity","unlimited","slug","InputPaystackProduct","PaystackUser","paystackCustomerCode","PaystackOrganization","PaystackPlan","Subscription","Promise","Record","interval","planCode","seatAmount","seatPriceId","seatPlanCode","invoiceLimit","freeTrial","days","onTrialStart","subscription","limits","features","PaystackWebhookPayload","PaystackTransactionResponse","PaystackPlanResponse","PaystackCustomerResponse","PaystackSubscriptionResponse","PaystackProductResponse","SubscriptionOptions","enabled","plans","autoSyncQuantity","cancelBehavior","onSubscriptionComplete","event","data","ctx","onSubscriptionCreated","onSubscriptionCancel","authorizeReference","user","session","action","requireEmailVerification","allowedPaymentChannels","PaystackOptions","TPaystackClient","PaystackClientLike","secretKey","paystackWebhookSecret","paystackClient","webhook","secret","verifyIP","trustedIPs","billingPattern","onEvent","organization","getCustomerCreateParams","email","org","onCustomerCreate","paystackCustomer","products","createCustomerOnSignUp","schema","modelName","fields","organizationId","pendingPlan","paystackSubscriptionCode","paystackPlanCode","paystackAuthorizationCode","paystackTransactionReference","paystackEmailToken","seats","periodStart","periodEnd","cancelAtPeriodEnd","trialStart","trialEnd","groupId","ChargeRecurringSubscriptionInput","subscriptionId","ChargeRecurringSubscriptionResult","PaystackSyncResult","count","AnyPaystackOptions","Pick","transaction","customer"],"sources":["../src/types.d.ts"],"mappings":";;;KAOYgB,uBAAAA;;;;;UAWKC,mBAAAA;EACbE,EAAAA;EACAC,SAAAA;EACAC,UAAAA;EACAC,WAAAA;EACAC,MAAAA;EACAC,MAAAA;EACAC,QAAAA;EACAC,MAAAA;EACAC,IAAAA;EACAC,OAAAA;EACAC,QAAAA;EACAC,SAAAA,EAAWZ,IAAAA;EACXa,SAAAA,EAAWb,IAAAA;AAAAA;AAAAA,UAEEc,eAAAA;EACbb,EAAAA;EACAc,IAAAA;EACAC,WAAAA;EACAC,KAAAA;EACAV,QAAAA;EACAW,QAAAA;EACAC,SAAAA;EACAhB,UAAAA;EACAiB,IAAAA;EACAT,QAAAA;EACAC,SAAAA,EAAWZ,IAAAA;EACXa,SAAAA,EAAWb,IAAAA;AAAAA;AAAAA,UAiBEyB,YAAAA;EACbxB,EAAAA;EACAc,IAAAA;EACAC,WAAAA;EACAV,MAAAA;EACAC,QAAAA;EACAsB,QAAAA;EACAC,QAAAA;EACA3B,UAAAA;EACA4B,UAAAA;EAOAG;;;;EAFAF,WAAAA;EACAC,YAAAA;EACAC,YAAAA;EACAC,SAAAA;IACIC,IAAAA;IACAC,YAAAA,IAAgBC,YAAAA,EAAcZ,YAAAA,KAAiBC,OAAAA;EAAAA;EAEnDY,MAAAA,GAASX,MAAAA;EACTY,QAAAA;EACA7B,QAAAA;EACAC,SAAAA,GAAYZ,IAAAA;EACZa,SAAAA,GAAYb,IAAAA;AAAAA;AAKhB;;;AAAA,KAAYyC,sBAAAA,GAAyBpD,oBAAAA;;AAIrC;;KAAYqD,2BAAAA,GAA8B9C,UAAAA;AAAAA,UAKzBmD,mBAAAA;EAQNtB;;;EAJPuB,OAAAA;EAmBkBtB;;;EAflBuB,KAAAA,EAAOxB,YAAAA,YAAwBE,OAAAA,CAAQF,YAAAA;EAmB5BgB;;;EAfXS,gBAAAA;EAkBmCvB;;;;EAbnCwB,cAAAA;EAsBUnE;;;EAlBVoE,sBAAAA,IAA0BE,IAAAA;IACtBD,KAAAA,EAAOZ,sBAAAA;IACPH,YAAAA,EAAcZ,YAAAA;IACdjB,IAAAA,EAAMgB,YAAAA;EAAAA,GACP8B,GAAAA,EAAKzE,sBAAAA,KAA2B6C,OAAAA;EACnC6B,qBAAAA,IAAyBF,IAAAA;IACrBD,KAAAA,EAAOZ,sBAAAA;IACPH,YAAAA,EAAcZ,YAAAA;IACdjB,IAAAA,EAAMgB,YAAAA;EAAAA,GACP8B,GAAAA,EAAKzE,sBAAAA,KAA2B6C,OAAAA;EACnC8B,oBAAAA,IAAwBH,IAAAA;IACpBD,KAAAA,EAAOZ,sBAAAA;IACPH,YAAAA,EAAcZ,YAAAA;EAAAA,GACf6B,GAAAA,EAAKzE,sBAAAA,KAA2B6C,OAAAA;EAX/BW;;;EAeJoB,kBAAAA,IAAsBJ,IAAAA;IAClBK,IAAAA,EAAM3E,IAAAA;IACN4E,OAAAA,EAAS7E,OAAAA;IACTqB,WAAAA;IACAyD,MAAAA;EAAAA,GACDN,GAAAA,EAAKzE,sBAAAA,KAA2B6C,OAAAA;EAhB/B0B;;;EAoBJS,wBAAAA;EAlBIrD;;;;EAuBJsD,sBAAAA,GAAyBjE,uBAAAA;AAAAA;AAAAA,UAEZkE,eAAAA,yBAAwCE,kBAAAA,GAAqBA,kBAAAA;EAtBtEb;;;EA0BJc,SAAAA;EA3BwBb;;;;EAgCxBc,qBAAAA;EAxBIT;;;;EA6BJU,cAAAA,GAAiBJ,eAAAA;EA1BbJ;;;EA8BJS,OAAAA;IA7BmC3C;;;IAiC/B4C,MAAAA;IAxB4C;;AAEpD;;IA2BQC,QAAAA;IA3BiDN;;;;IAgCjDO,UAAAA;EAAAA;EAwBQ3F;;;EAnBZwD,YAAAA,GAAeS,mBAAAA;EAuBHjE;;;;EAlBZ4F,cAAAA;EA4BsB9C;;;EAxBtB+C,OAAAA,IAAWtB,KAAAA,EAAOhE,oBAAAA,KAAyBsC,OAAAA;EA8BlCC;;;EA1BTgD,YAAAA;IACI5B,OAAAA;IACA6B,uBAAAA,IAA2BE,GAAAA;MACvB9E,EAAAA;MACAc,IAAAA;MACA+D,KAAAA;IAAAA,GACDvB,GAAAA,EAAKzE,sBAAAA,KAA2B6C,OAAAA,CAAQC,MAAAA;IAC3CoD,gBAAAA,IAAoB1B,IAAAA;MAChB2B,gBAAAA,EAAkBrD,MAAAA;MAClBgD,YAAAA;IAAAA,GACDrB,GAAAA,EAAKzE,sBAAAA,KAA2B6C,OAAAA;EAAAA;EAvBxBoB;;;EA4BfmC,QAAAA;IACIA,QAAAA,GAAWpE,eAAAA,YAA2Ba,OAAAA,CAAQb,eAAAA;EAAAA;EAElDqE,sBAAAA;EACAH,gBAAAA,IAAoB1B,IAAAA;IAChB2B,gBAAAA,EAAkBrD,MAAAA;IAClB+B,IAAAA;EAAAA,GACDJ,GAAAA,EAAKzE,sBAAAA,KAA2B6C,OAAAA;EAjB3BmD;;;EAqBRM,MAAAA,GAASxD,MAAAA;IACLyD,SAAAA;IACAC,MAAAA,GAAS1D,MAAAA;EAAAA;AAAAA;AAAAA,UAGAF,YAAAA;EACbzB,EAAAA;EACAI,MAAAA;EACAkF,cAAAA;EACA9E,IAAAA;EACA+E,WAAAA;EACAC,wBAAAA;EACAlE,oBAAAA;EACAmE,gBAAAA;EACAC,yBAAAA;EACAC,4BAAAA;EACAC,kBAAAA;EACArF,MAAAA;EACAsF,KAAAA;EACA1F,WAAAA;EACA2F,WAAAA,GAAc/F,IAAAA;EACdgG,SAAAA,GAAYhG,IAAAA;EACZiG,iBAAAA;EACAC,UAAAA,GAAalG,IAAAA;EACbmG,QAAAA,GAAWnG,IAAAA;EACXoG,OAAAA;EACAxF,SAAAA,EAAWZ,IAAAA;EACXa,SAAAA,EAAWb,IAAAA;AAAAA;AAAAA,UAEEqG,gCAAAA;EACbC,cAAAA;EACAhG,MAAAA;AAAAA;AAAAA,UAEaiG,iCAAAA;EACb/F,MAAAA;EACA8C,IAAAA,EAAMZ,2BAAAA;AAAAA;AAAAA,UAEO8D,kBAAAA;EACbhG,MAAAA;EACAiG,KAAAA;AAAAA;AAAAA,KAEQC,kBAAAA,GAAqB1C,eAAAA,CAAgBE,kBAAAA;;;;;UAKhCA,kBAAAA;EACb0C,WAAAA,EAAaD,IAAAA,CAAKhH,yBAAAA;EAClBkH,QAAAA,EAAUF,IAAAA,CAAKpH,sBAAAA;EACf+C,YAAAA,EAAcqE,IAAAA,CAAKjH,0BAAAA;EACnBgB,OAAAA,EAASiG,IAAAA,CAAKlH,qBAAAA;EACdgB,IAAAA,EAAMkG,IAAAA,CAAKnH,kBAAAA;AAAAA"}