@alexasomba/better-auth-paystack 2.4.0 → 2.4.3

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,147 @@
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.3" # x-release-please-version
8
+ license: "MIT"
9
+ compatibility: "Node.js >=24.0.0; better-auth ^1.6.9; @alexasomba/paystack-node 1.10.x; @alexasomba/better-auth-paystack >=2.4.2 <3.0.0"
10
+ sources:
11
+ - "alexasomba/better-auth-paystack:README.md"
12
+ - "alexasomba/better-auth-paystack:src/routes.ts"
13
+ - "alexasomba/better-auth-paystack:src/operations.ts"
14
+ - "alexasomba/better-auth-paystack:src/client.ts"
15
+ ---
16
+
17
+ ## Setup
18
+
19
+ Enable subscriptions with concrete Paystack plan metadata:
20
+
21
+ ```ts
22
+ import { paystack } from "@alexasomba/better-auth-paystack";
23
+
24
+ paystack({
25
+ secretKey: process.env.PAYSTACK_SECRET_KEY!,
26
+ webhook: {
27
+ secret: process.env.PAYSTACK_WEBHOOK_SECRET!,
28
+ },
29
+ subscription: {
30
+ enabled: true,
31
+ plans: [
32
+ {
33
+ name: "starter",
34
+ amount: 250_000,
35
+ currency: "NGN",
36
+ interval: "monthly",
37
+ planCode: "PLN_starter",
38
+ paystackId: "1001",
39
+ },
40
+ {
41
+ name: "team",
42
+ amount: 1_000_000,
43
+ currency: "NGN",
44
+ interval: "monthly",
45
+ planCode: "PLN_team",
46
+ paystackId: "1002",
47
+ limits: {
48
+ seats: 10,
49
+ teams: 3,
50
+ },
51
+ },
52
+ ],
53
+ },
54
+ });
55
+ ```
56
+
57
+ ## Core Patterns
58
+
59
+ ### Initialize and verify a transaction
60
+
61
+ Use the client plugin for browser-triggered checkout:
62
+
63
+ ```ts
64
+ const initialized = await authClient.transaction.initialize({
65
+ amount: 250_000,
66
+ email: "customer@example.com",
67
+ currency: "NGN",
68
+ metadata: {
69
+ product: "starter-pack",
70
+ },
71
+ });
72
+
73
+ const verified = await authClient.transaction.verify({
74
+ reference: initialized.data.reference,
75
+ });
76
+ ```
77
+
78
+ Do not trust a redirect callback alone. Always verify the Paystack reference before granting access or updating billing state.
79
+
80
+ ### Manage subscription lifecycle
81
+
82
+ Use canonical methods in new code:
83
+
84
+ ```ts
85
+ await authClient.subscription.create({
86
+ plan: "starter",
87
+ });
88
+
89
+ await authClient.subscription.upgrade({
90
+ plan: "team",
91
+ });
92
+
93
+ await authClient.subscription.cancel({
94
+ subscriptionId: "subscription_id",
95
+ });
96
+
97
+ await authClient.subscription.restore({
98
+ subscriptionId: "subscription_id",
99
+ });
100
+
101
+ const subscriptions = await authClient.subscription.list();
102
+ ```
103
+
104
+ Deprecated aliases:
105
+
106
+ - `subscription.disable` maps to `subscription.cancel`
107
+ - `subscription.enable` maps to `subscription.restore`
108
+
109
+ Keep aliases only for compatibility tests or migration examples.
110
+
111
+ ### Keep renewal and catalog sync server-side
112
+
113
+ These helpers are exported by the server package and are intentionally not client actions:
114
+
115
+ ```ts
116
+ import {
117
+ chargeSubscriptionRenewal,
118
+ syncPaystackPlans,
119
+ syncPaystackProducts,
120
+ } from "@alexasomba/better-auth-paystack";
121
+
122
+ export async function runBillingJob(ctx: unknown, options: unknown) {
123
+ await syncPaystackProducts(ctx, options);
124
+ await syncPaystackPlans(ctx, options);
125
+ await chargeSubscriptionRenewal(ctx, options, {
126
+ subscriptionId: "subscription_id",
127
+ });
128
+ }
129
+ ```
130
+
131
+ Use cron, background jobs, or trusted server functions. Do not call these from a browser component.
132
+
133
+ ## Common Mistakes
134
+
135
+ ### Mutating Paystack-managed subscriptions like local subscriptions
136
+
137
+ Seat-based or prorated subscription changes require locally managed subscription state. Paystack-managed subscriptions do not support every local mutation path.
138
+
139
+ Before implementing seat changes, check whether the target plan is local/seat-aware and whether the operation is supported by the helper being used.
140
+
141
+ ### Skipping webhook verification
142
+
143
+ 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.
144
+
145
+ ### Mixing plan name and Paystack plan code
146
+
147
+ 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,163 @@
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.3" # x-release-please-version
8
+ license: "MIT"
9
+ compatibility: "Node.js >=24.0.0; better-auth ^1.6.9; @alexasomba/paystack-node 1.10.x; @alexasomba/better-auth-paystack >=2.4.2 <3.0.0"
10
+ sources:
11
+ - "alexasomba/better-auth-paystack:examples/tanstack/README.md"
12
+ - "alexasomba/better-auth-paystack:examples/tanstack/src/lib/auth.ts"
13
+ - "alexasomba/better-auth-paystack:examples/tanstack/src/lib/auth-client.ts"
14
+ - "alexasomba/better-auth-paystack:examples/tanstack/src/routes/api/auth/$.ts"
15
+ ---
16
+
17
+ ## Setup
18
+
19
+ Create the Better Auth server config with Paystack and `tanstackStartCookies()` last:
20
+
21
+ ```ts
22
+ import { betterAuth } from "better-auth";
23
+ import { tanstackStartCookies } from "better-auth/tanstack-start";
24
+ import { paystack } from "@alexasomba/better-auth-paystack";
25
+
26
+ export const auth = betterAuth({
27
+ baseURL: process.env.BETTER_AUTH_URL,
28
+ plugins: [
29
+ paystack({
30
+ secretKey: process.env.PAYSTACK_SECRET_KEY!,
31
+ webhook: {
32
+ secret: process.env.PAYSTACK_WEBHOOK_SECRET!,
33
+ },
34
+ subscription: {
35
+ enabled: true,
36
+ plans: [],
37
+ },
38
+ }),
39
+ tanstackStartCookies(),
40
+ ],
41
+ });
42
+ ```
43
+
44
+ Wire the catch-all auth route:
45
+
46
+ ```ts
47
+ import { createFileRoute } from "@tanstack/react-router";
48
+ import { auth } from "../../../lib/auth";
49
+
50
+ export const Route = createFileRoute("/api/auth/$")({
51
+ server: {
52
+ handlers: {
53
+ GET: ({ request }) => auth.handler(request),
54
+ POST: ({ request }) => auth.handler(request),
55
+ },
56
+ },
57
+ });
58
+ ```
59
+
60
+ Create the client plugin:
61
+
62
+ ```ts
63
+ import { createAuthClient } from "better-auth/client";
64
+ import { paystackClient } from "@alexasomba/better-auth-paystack/client";
65
+
66
+ export const authClient = createAuthClient({
67
+ plugins: [paystackClient()],
68
+ });
69
+ ```
70
+
71
+ ## Core Patterns
72
+
73
+ ### Use Paystack client actions in client components
74
+
75
+ ```tsx
76
+ import { authClient } from "../lib/auth-client";
77
+
78
+ export function SubscribeButton() {
79
+ return (
80
+ <button
81
+ type="button"
82
+ onClick={async () => {
83
+ await authClient.subscription.create({
84
+ plan: "starter",
85
+ });
86
+ }}
87
+ >
88
+ Subscribe
89
+ </button>
90
+ );
91
+ }
92
+ ```
93
+
94
+ Use client actions for checkout and user-triggered subscription lifecycle calls. Do not import server helpers into React components.
95
+
96
+ ### Use server functions for trusted billing operations
97
+
98
+ ```ts
99
+ import { createServerFn } from "@tanstack/react-start";
100
+ import { getRequestHeaders } from "@tanstack/react-start/server";
101
+ import { auth } from "./auth";
102
+ import { syncPaystackPlans } from "@alexasomba/better-auth-paystack";
103
+
104
+ export const syncPlans = createServerFn({ method: "POST" }).handler(async () => {
105
+ const session = await auth.api.getSession({
106
+ headers: await getRequestHeaders(),
107
+ });
108
+
109
+ if (!session?.user) {
110
+ throw new Response("Unauthorized", { status: 401 });
111
+ }
112
+
113
+ await syncPaystackPlans(await auth.$context, {
114
+ secretKey: process.env.PAYSTACK_SECRET_KEY!,
115
+ });
116
+
117
+ return { ok: true };
118
+ });
119
+ ```
120
+
121
+ Pass request headers when Better Auth needs session context.
122
+
123
+ ### Keep Cloudflare Worker dependencies compatible
124
+
125
+ 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`.
126
+
127
+ The known safe pin for this package version is:
128
+
129
+ ```yaml
130
+ overrides:
131
+ "@better-auth/sso": 1.6.9
132
+ ```
133
+
134
+ ## Common Mistakes
135
+
136
+ ### Putting `tanstackStartCookies()` before Paystack
137
+
138
+ `tanstackStartCookies()` should be last in the Better Auth plugin array so cookie handling wraps the final auth behavior.
139
+
140
+ ### Omitting auth headers in server functions
141
+
142
+ Wrong:
143
+
144
+ ```ts
145
+ const session = await auth.api.getSession();
146
+ ```
147
+
148
+ Correct:
149
+
150
+ ```ts
151
+ const session = await auth.api.getSession({
152
+ headers: await getRequestHeaders(),
153
+ });
154
+ ```
155
+
156
+ ### Debugging only root package builds
157
+
158
+ The root package can pass `vp pack` while the example Worker build fails. Reproduce Worker issues with:
159
+
160
+ ```bash
161
+ pnpm --filter ./examples/tanstack build
162
+ pnpm --filter ./examples/tanstack exec wrangler deploy --dry-run
163
+ ```
@@ -1 +0,0 @@
1
- {"version":3,"file":"types-CNI2ur0p.d.mts","names":["GenericEndpointContext","InferOptionSchema","Session","User","Organization","Member","PaystackPaths","PaystackResponse","PaystackWebhookEvent","PaystackClient","PaystackCustomerClient","PaystackPlanClient","PaystackProductClient","PaystackSubscriptionClient","PaystackTransactionClient","components","PaystackPluginSchema","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","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/schema.ts","../src/types.d.ts"],"mappings":"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"}
@@ -1,6 +0,0 @@
1
- //#region src/version.ts
2
- const PACKAGE_VERSION = "2.3.0";
3
- //#endregion
4
- export { PACKAGE_VERSION as t };
5
-
6
- //# sourceMappingURL=version-C_50YiuM.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"version-C_50YiuM.mjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["export const PACKAGE_VERSION = \"2.3.0\";\n"],"mappings":";AAAA,MAAa,kBAAkB"}