@alexasomba/better-auth-paystack 2.4.3 → 2.5.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 (35) hide show
  1. package/README.md +42 -4
  2. package/dist/client.d.mts +1 -1
  3. package/dist/client.mjs +1 -1
  4. package/dist/index.d.mts +65 -3
  5. package/dist/index.d.mts.map +1 -1
  6. package/dist/index.mjs +338 -213
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/{types-DHZSS1K6.d.mts → types-D-iIbe9E.d.mts} +9 -2
  9. package/dist/types-D-iIbe9E.d.mts.map +1 -0
  10. package/dist/version-DRyh6Dnz.mjs +6 -0
  11. package/dist/version-DRyh6Dnz.mjs.map +1 -0
  12. package/package.json +40 -36
  13. package/skills/{setup → better-auth-paystack-setup}/SKILL.md +2 -2
  14. package/skills/better-auth-paystack-setup/agents/openai.yaml +6 -0
  15. package/skills/{subscriptions-and-transactions → paystack-billing-flows}/SKILL.md +11 -3
  16. package/skills/paystack-billing-flows/agents/openai.yaml +6 -0
  17. package/skills/{billing-catalog-and-limits → paystack-catalog-limits}/SKILL.md +2 -2
  18. package/skills/paystack-catalog-limits/agents/openai.yaml +6 -0
  19. package/skills/paystack-client-api/SKILL.md +117 -0
  20. package/skills/paystack-client-api/agents/openai.yaml +6 -0
  21. package/skills/paystack-local-subscriptions/SKILL.md +97 -0
  22. package/skills/paystack-local-subscriptions/agents/openai.yaml +6 -0
  23. package/skills/{organization-billing → paystack-organization-billing}/SKILL.md +25 -4
  24. package/skills/paystack-organization-billing/agents/openai.yaml +6 -0
  25. package/skills/paystack-schema-migrations/SKILL.md +94 -0
  26. package/skills/paystack-schema-migrations/agents/openai.yaml +6 -0
  27. package/skills/{tanstack-start → paystack-tanstack-start}/SKILL.md +2 -2
  28. package/skills/paystack-tanstack-start/agents/openai.yaml +6 -0
  29. package/skills/paystack-testing-fixtures/SKILL.md +95 -0
  30. package/skills/paystack-testing-fixtures/agents/openai.yaml +6 -0
  31. package/skills/paystack-webhooks-events/SKILL.md +108 -0
  32. package/skills/paystack-webhooks-events/agents/openai.yaml +6 -0
  33. package/dist/types-DHZSS1K6.d.mts.map +0 -1
  34. package/dist/version-GQ15aLQo.mjs +0 -6
  35. package/dist/version-GQ15aLQo.mjs.map +0 -1
@@ -193,6 +193,13 @@ interface PaystackOptions<TPaystackClient extends PaystackClientLike = PaystackC
193
193
  */
194
194
  organization?: {
195
195
  enabled?: boolean;
196
+ /**
197
+ * Organization member roles allowed to manage billing when `subscription.authorizeReference`
198
+ * is not provided.
199
+ *
200
+ * @default ["owner", "admin"]
201
+ */
202
+ billingRoles?: string[];
196
203
  getCustomerCreateParams?: (org: {
197
204
  id: string;
198
205
  name: string;
@@ -268,5 +275,5 @@ interface PaystackClientLike {
268
275
  plan: Pick<PaystackPlanClient, "list" | "create">;
269
276
  }
270
277
  //#endregion
271
- export { PaystackOptions as a, PaystackSyncResult as c, Subscription as d, SubscriptionOptions as f, PaystackClientLike as i, PaystackTransaction as l, ChargeRecurringSubscriptionInput as n, PaystackPlan as o, getSchema as p, ChargeRecurringSubscriptionResult as r, PaystackProduct as s, AnyPaystackOptions as t, PaystackTransactionResponse as u };
272
- //# sourceMappingURL=types-DHZSS1K6.d.mts.map
278
+ export { PaystackOptions as a, PaystackSyncResult as c, Session as d, Subscription as f, getSchema as h, PaystackClientLike as i, PaystackTransaction as l, User as m, ChargeRecurringSubscriptionInput as n, PaystackPlan as o, SubscriptionOptions as p, ChargeRecurringSubscriptionResult as r, PaystackProduct as s, AnyPaystackOptions as t, PaystackTransactionResponse as u };
279
+ //# sourceMappingURL=types-D-iIbe9E.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-D-iIbe9E.d.mts","names":["GenericEndpointContext","InferOptionSchema","Session","User","Organization","Member","PaystackPaths","PaystackResponse","PaystackWebhookEvent","PaystackClient","PaystackCustomerClient","PaystackPlanClient","PaystackProductClient","PaystackSubscriptionClient","PaystackTransactionClient","TransactionChargeAuthorizationResponseData","TransactionVerifyResponseData","PlanListResponseData","CustomerCreateResponseData","SubscriptionListResponseData","ProductFetchResponseData","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","PaystackChargeAuthorizationResponse","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","billingRoles","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":";;;;KAIK,iBAAA,uDAAwE,MAAA,CAC3E,SAAA;EAEE,MAAA,EAAQ,MAAA,CAAO,SAAA,EAAW,gBAAA;EAC1B,gBAAA;EACA,SAAA;AAAA;AAAA,KAIC,kBAAA,GAAqB,iBAAA;AAAA,KAgBrB,mBAAA,GAAsB,iBAAA;AAAA,KAoBtB,UAAA,GAAa,iBAAA;AAAA,KAEb,kBAAA,GAAqB,iBAAA;AAAA,KAErB,cAAA,GAAiB,iBAAA;AAAA,KAejB,WAAA,GAAc,iBAAA;AAAA,KAcP,oBAAA,GAAuB,mBAAA,GACjC,kBAAA,GACA,UAAA,GACA,kBAAA,GACA,cAAA,GACA,WAAA;AAAA,cAqSW,SAAA,GAAa,OAAA,EAAS,eAAA,KAAkB,wBAAA;;;KCpXzCwB,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,GAAYZ,IAAAA;EACZa,SAAAA,GAAYb,IAAAA;AAAAA;AAAAA,UAiBCyB,YAAAA;EACbxB,EAAAA;EACAc,IAAAA;EACAC,WAAAA;EACAV,MAAAA;EACAC,QAAAA;EACAsB,QAAAA;EACAC,QAAAA;EACA3B,UAAAA;EACA4B,UAAAA;EDcF;;;;ECTEC,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;;;;KAKJyC,sBAAAA,GAAyB3D,oBAAAA;AA1ErC;;;AAAA,KA8EY4D,2BAAAA,GAA8BpD,6BAAAA;AAAAA,KAC9BqD,mCAAAA,GAAsCtD,0CAAAA;AAAAA,UAKjC2D,mBAAAA;EA7EbzC;;;EAiFA0C,OAAAA;EA7EAtC;;;EAiFAuC,KAAAA,EAAOzB,YAAAA,YAAwBE,OAAAA,CAAQF,YAAAA;EA/E5BzB;;;EAmFXmD,gBAAAA;EAjF4B;;;;EAsF5BC,cAAAA;EAnFApC;;;EAuFAqC,sBAAAA,IAA0BE,IAAAA;IACtBD,KAAAA,EAAOb,sBAAAA;IACPH,YAAAA,EAAcZ,YAAAA;IACdjB,IAAAA,EAAMgB,YAAAA;EAAAA,GACP+B,GAAAA,EAAKlF,sBAAAA,KAA2BqD,OAAAA;EACnC8B,qBAAAA,IAAyBF,IAAAA;IACrBD,KAAAA,EAAOb,sBAAAA;IACPH,YAAAA,EAAcZ,YAAAA;IACdjB,IAAAA,EAAMgB,YAAAA;EAAAA,GACP+B,GAAAA,EAAKlF,sBAAAA,KAA2BqD,OAAAA;EACnC+B,oBAAAA,IAAwBH,IAAAA;IACpBD,KAAAA,EAAOb,sBAAAA;IACPH,YAAAA,EAAcZ,YAAAA;EAAAA,GACf8B,GAAAA,EAAKlF,sBAAAA,KAA2BqD,OAAAA;EAvDDD;;;EA2DlCiC,kBAAAA,IAAsBJ,IAAAA;IAClBK,IAAAA,EAAMnF,IAAAA;IACNoF,OAAAA,EAASrF,OAAAA;IACT4B,WAAAA;IACA0D,MAAAA;EAAAA,GACDN,GAAAA,EAAKlF,sBAAAA,KAA2BqD,OAAAA;EAhFnCX;;;EAoFA+C,wBAAAA;EAhFAjC;;;;EAqFAkC,sBAAAA,GAAyBlE,uBAAAA;AAAAA;AAAAA,UAEZmE,eAAAA,yBAAwCE,kBAAAA,GAAqBA,kBAAAA;EA5EtE/B;;;EAgFJgC,SAAAA;EA/EmDzC;;;;EAoFnD0C,qBAAAA;EA/EAzD;;;;EAoFA0D,cAAAA,GAAiBJ,eAAAA;EAnFD;AAKpB;;EAkFIK,OAAAA;IAlFqD;;AAIzD;IAkFQC,MAAAA;IAlFkClF;;;AAC1C;IAsFQmF,QAAAA;IAtF0CpF;;;AAKlD;IAsFQqF,UAAAA;EAAAA;EA9EGjD;;;EAmFPa,YAAAA,GAAeU,mBAAAA;EApEGtB;;;;EAyElBiD,cAAAA;EApEkBjD;;;EAwElBkD,OAAAA,IAAWtB,KAAAA,EAAOxE,oBAAAA,KAAyB6C,OAAAA;EApEhCc;;;EAwEXoC,YAAAA;IACI5B,OAAAA;IAjESzE;;;;;;IAwETsG,YAAAA;IACAC,uBAAAA,IAA2BE,GAAAA;MACvBhF,EAAAA;MACAc,IAAAA;MACAiE,KAAAA;IAAAA,GACDxB,GAAAA,EAAKlF,sBAAAA,KAA2BqD,OAAAA,CAAQC,MAAAA;IAC3CsD,gBAAAA,IAAoB3B,IAAAA;MAChB4B,gBAAAA,EAAkBvD,MAAAA;MAClBiD,YAAAA;IAAAA,GACDrB,GAAAA,EAAKlF,sBAAAA,KAA2BqD,OAAAA;EAAAA;EAlGrBD;;;EAuGlB0D,QAAAA;IACIA,QAAAA,GAAWtE,eAAAA,YAA2Ba,OAAAA,CAAQb,eAAAA;EAAAA;EAElDuE,sBAAAA;EACAH,gBAAAA,IAAoB3B,IAAAA;IAChB4B,gBAAAA,EAAkBvD,MAAAA;IAClBgC,IAAAA;EAAAA,GACDJ,GAAAA,EAAKlF,sBAAAA,KAA2BqD,OAAAA;EAzGjBD;;;EA6GlB4D,MAAAA,GAAS/G,iBAAAA,CAAkBqB,oBAAAA;AAAAA;AAAAA,UAEd8B,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;EACA+C,IAAAA,EAAMZ,mCAAAA;AAAAA;AAAAA,UAEO6D,kBAAAA;EACbhG,MAAAA;EACAiG,KAAAA;AAAAA;AAAAA,KAEQC,kBAAAA,GAAqBzC,eAAAA,CAAgBE,kBAAAA;;;;;UAKhCA,kBAAAA;EACbyC,WAAAA,EAAaD,IAAAA,CAAKvH,yBAAAA;EAClByH,QAAAA,EAAUF,IAAAA,CAAK3H,sBAAAA;EACfsD,YAAAA,EAAcqE,IAAAA,CAAKxH,0BAAAA;EACnBuB,OAAAA,EAASiG,IAAAA,CAAKzH,qBAAAA;EACduB,IAAAA,EAAMkG,IAAAA,CAAK1H,kBAAAA;AAAAA"}
@@ -0,0 +1,6 @@
1
+ //#region src/version.ts
2
+ const PACKAGE_VERSION = "2.5.0";
3
+ //#endregion
4
+ export { PACKAGE_VERSION as t };
5
+
6
+ //# sourceMappingURL=version-DRyh6Dnz.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-DRyh6Dnz.mjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["export const PACKAGE_VERSION = \"2.5.0\"; // x-release-please-version\n"],"mappings":";AAAA,MAAa,kBAAkB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alexasomba/better-auth-paystack",
3
- "version": "2.4.3",
3
+ "version": "2.5.0",
4
4
  "description": "Production-ready Paystack billing plugin for Better Auth. Supports subscriptions, one-time payments, organization billing, secure webhooks and more",
5
5
  "keywords": [
6
6
  "africa",
@@ -66,53 +66,57 @@
66
66
  "publishConfig": {
67
67
  "access": "public"
68
68
  },
69
+ "scripts": {
70
+ "build": "vp pack",
71
+ "dev": "vp pack --watch",
72
+ "test": "vp test run",
73
+ "test:integration": "RUN_INTEGRATION_TESTS=1 vp test run",
74
+ "coverage": "vp test run --coverage",
75
+ "lint": "vp lint src",
76
+ "lint:package": "publint run --strict",
77
+ "lint:types": "attw --profile esm-only --pack .",
78
+ "typecheck": "tsc -p tsconfig.json --noEmit",
79
+ "skills:install": "skills-npm --cwd examples/tanstack --yes --force",
80
+ "skills:dry-run": "skills-npm --cwd examples/tanstack --dry-run --yes --agents universal --force"
81
+ },
69
82
  "dependencies": {
70
- "@alexasomba/paystack-node": "^1.10.1",
71
- "better-call": "~1.3.5",
72
- "defu": "^6.1.7",
73
- "zod": "^4.4.3"
83
+ "@alexasomba/paystack-node": "catalog:",
84
+ "better-call": "catalog:",
85
+ "defu": "catalog:",
86
+ "zod": "catalog:"
74
87
  },
75
88
  "devDependencies": {
76
- "@arethetypeswrong/cli": "^0.18.2",
77
- "@better-fetch/fetch": "^1.1.21",
89
+ "@arethetypeswrong/cli": "catalog:",
90
+ "@better-fetch/fetch": "catalog:",
78
91
  "@commitlint/cli": "^21.0.0",
79
92
  "@commitlint/config-conventional": "^21.0.0",
80
- "@eslint/compat": "^2.1.0",
81
- "@eslint/js": "^10.0.1",
93
+ "@eslint/compat": "catalog:",
94
+ "@eslint/js": "catalog:",
82
95
  "@tanstack/intent": "^0.0.40",
83
- "@types/node": "^24.12.3",
84
- "@typescript-eslint/eslint-plugin": "^8.59.2",
85
- "@typescript-eslint/parser": "^8.59.2",
86
- "@vitest/coverage-v8": "^4.1.5",
87
- "better-auth": "^1.6.9",
88
- "eslint-plugin-import-x": "^4.16.2",
89
- "eslint-plugin-promise": "^7.3.0",
90
- "eslint-plugin-react-hooks": "^7.1.1",
91
- "eslint-plugin-unicorn": "^64.0.0",
92
- "publint": "^0.3.20",
93
- "typescript": "^6.0.3",
94
- "typescript-eslint": "^8.59.2",
95
- "vite-plus": "^0.1.20",
96
+ "@types/node": "catalog:",
97
+ "@typescript-eslint/eslint-plugin": "catalog:",
98
+ "@typescript-eslint/parser": "catalog:",
99
+ "@vitest/coverage-v8": "catalog:",
100
+ "better-auth": "catalog:",
101
+ "eslint-plugin-import-x": "catalog:",
102
+ "eslint-plugin-promise": "catalog:",
103
+ "eslint-plugin-react-hooks": "catalog:",
104
+ "eslint-plugin-unicorn": "catalog:",
105
+ "publint": "catalog:",
106
+ "skills-npm": "^1.1.1",
107
+ "typescript": "catalog:",
108
+ "typescript-eslint": "catalog:",
109
+ "vite-plus": "catalog:",
96
110
  "vitest": "npm:@voidzero-dev/vite-plus-test@^0.1.20"
97
111
  },
98
112
  "peerDependencies": {
99
113
  "better-auth": "^1.6.9"
100
114
  },
101
115
  "optionalDependencies": {
102
- "@rollup/rollup-linux-x64-gnu": "^4.60.3"
116
+ "@rollup/rollup-linux-x64-gnu": "catalog:"
103
117
  },
104
118
  "engines": {
105
- "node": ">=24.0.0"
119
+ "node": ">=22.0.0"
106
120
  },
107
- "scripts": {
108
- "build": "vp pack",
109
- "dev": "vp pack --watch",
110
- "test": "vp test run",
111
- "test:integration": "RUN_INTEGRATION_TESTS=1 vp test run",
112
- "coverage": "vp test run --coverage",
113
- "lint": "vp lint src",
114
- "lint:package": "publint run --strict",
115
- "lint:types": "attw --profile esm-only --pack .",
116
- "typecheck": "tsc -p tsconfig.json --noEmit"
117
- }
118
- }
121
+ "packageManager": "pnpm@11.0.9"
122
+ }
@@ -1,10 +1,10 @@
1
1
  ---
2
- name: setup
2
+ name: better-auth-paystack-setup
3
3
  description: >
4
4
  Configure @alexasomba/better-auth-paystack with Better Auth. Use when adding the paystack() server plugin, paystackClient() client plugin, schema overrides, products/plans, webhook secrets, or canonical authClient.paystack/subscription/transaction actions.
5
5
  type: core
6
6
  library: "@alexasomba/better-auth-paystack"
7
- library_version: "2.4.3" # x-release-please-version
7
+ library_version: "2.5.0" # x-release-please-version
8
8
  license: "MIT"
9
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
10
  sources:
@@ -0,0 +1,6 @@
1
+ interface:
2
+ display_name: "Better Auth Paystack Setup"
3
+ short_description: "Server and client plugin setup guidance"
4
+ default_prompt: "Use $better-auth-paystack-setup to configure the Better Auth Paystack server and client plugins."
5
+ policy:
6
+ allow_implicit_invocation: true
@@ -1,10 +1,10 @@
1
1
  ---
2
- name: subscriptions-and-transactions
2
+ name: paystack-billing-flows
3
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.
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, reconcilePaystackTransaction, chargeSubscriptionRenewal, syncPaystackProducts, and syncPaystackPlans.
5
5
  type: core
6
6
  library: "@alexasomba/better-auth-paystack"
7
- library_version: "2.4.3" # x-release-please-version
7
+ library_version: "2.5.0" # x-release-please-version
8
8
  license: "MIT"
9
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
10
  sources:
@@ -115,11 +115,17 @@ These helpers are exported by the server package and are intentionally not clien
115
115
  ```ts
116
116
  import {
117
117
  chargeSubscriptionRenewal,
118
+ reconcilePaystackTransaction,
118
119
  syncPaystackPlans,
119
120
  syncPaystackProducts,
120
121
  } from "@alexasomba/better-auth-paystack";
121
122
 
122
123
  export async function runBillingJob(ctx: unknown, options: unknown) {
124
+ await reconcilePaystackTransaction(ctx, options, {
125
+ reference: "paystack_reference",
126
+ source: "queue",
127
+ referenceId: "user_or_org_id",
128
+ });
123
129
  await syncPaystackProducts(ctx, options);
124
130
  await syncPaystackPlans(ctx, options);
125
131
  await chargeSubscriptionRenewal(ctx, options, {
@@ -130,6 +136,8 @@ export async function runBillingJob(ctx: unknown, options: unknown) {
130
136
 
131
137
  Use cron, background jobs, or trusted server functions. Do not call these from a browser component.
132
138
 
139
+ `reconcilePaystackTransaction` verifies the Paystack reference and applies the same local transaction, customer, product, subscription, trial, and proration side effects used by the browser verify endpoint. Use it for webhook handlers, queue retries, cron jobs, and admin repair actions.
140
+
133
141
  ## Common Mistakes
134
142
 
135
143
  ### Mutating Paystack-managed subscriptions like local subscriptions
@@ -0,0 +1,6 @@
1
+ interface:
2
+ display_name: "Better Auth Paystack Billing Flows"
3
+ short_description: "Transactions, subscriptions, and billing flows"
4
+ default_prompt: "Use $paystack-billing-flows to build Paystack transaction, subscription, product, and billing portal flows."
5
+ policy:
6
+ allow_implicit_invocation: true
@@ -1,10 +1,10 @@
1
1
  ---
2
- name: billing-catalog-and-limits
2
+ name: paystack-catalog-limits
3
3
  description: >
4
4
  Configure products, Paystack-native plans, local-managed plans, free trials, seat billing, resource limits, and catalog sync in @alexasomba/better-auth-paystack. Use when tasks mention planCode, freeTrial, trial eligibility, seatAmount, seatPlanCode, limits, products, syncPaystackProducts, or syncPaystackPlans.
5
5
  type: core
6
6
  library: "@alexasomba/better-auth-paystack"
7
- library_version: "2.4.3" # x-release-please-version
7
+ library_version: "2.5.0" # x-release-please-version
8
8
  license: "MIT"
9
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
10
  sources:
@@ -0,0 +1,6 @@
1
+ interface:
2
+ display_name: "Better Auth Paystack Catalog"
3
+ short_description: "Products, plans, trials, seats, and limits"
4
+ default_prompt: "Use $paystack-catalog-limits to configure Paystack products, subscription plans, free trials, seat billing, and resource limits."
5
+ policy:
6
+ allow_implicit_invocation: true
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: paystack-client-api
3
+ description: >
4
+ Modify or use the @alexasomba/better-auth-paystack browser client API. Use for paystackClient(), authClient.paystack, authClient.transaction, authClient.subscription, initializeTransaction, verifyTransaction, listTransactions, listSubscriptions, listProducts, listPlans, subscription billingPortal/manageLink, cancel/restore aliases, BetterFetch throw option return types, and deprecated disable/enable behavior.
5
+ type: core
6
+ library: "@alexasomba/better-auth-paystack"
7
+ library_version: "2.5.0" # 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:src/client.ts"
12
+ - "alexasomba/better-auth-paystack:src/routes.ts"
13
+ - "alexasomba/better-auth-paystack:test/typesafety.test.ts"
14
+ - "alexasomba/better-auth-paystack:examples/tanstack/src/lib/paystack-client.ts"
15
+ ---
16
+
17
+ ## Client Contract
18
+
19
+ Install the browser plugin from the client entrypoint:
20
+
21
+ ```ts
22
+ import { createAuthClient } from "better-auth/client";
23
+ import { paystackClient } from "@alexasomba/better-auth-paystack/client";
24
+
25
+ export const authClient = createAuthClient({
26
+ plugins: [paystackClient({ subscription: true })],
27
+ });
28
+ ```
29
+
30
+ The plugin exposes three public surfaces:
31
+
32
+ - `authClient.paystack`: top-level Paystack actions
33
+ - `authClient.transaction`: transaction namespace
34
+ - `authClient.subscription`: subscription namespace
35
+
36
+ `authClient.paystack.paystack` points back to the same actions object for compatibility.
37
+
38
+ ## Core Patterns
39
+
40
+ ### Prefer stable names in examples
41
+
42
+ Use these methods in new examples and application code:
43
+
44
+ ```ts
45
+ await authClient.paystack.config();
46
+ await authClient.paystack.listProducts();
47
+ await authClient.paystack.listPlans();
48
+ await authClient.paystack.initializeTransaction({ amount: 500_000 });
49
+ await authClient.paystack.verifyTransaction({ reference: "REF" });
50
+ await authClient.paystack.listTransactions();
51
+
52
+ await authClient.transaction.initialize({ amount: 500_000 });
53
+ await authClient.transaction.verify({ reference: "REF" });
54
+ await authClient.transaction.list();
55
+
56
+ await authClient.subscription.create({ plan: "starter" });
57
+ await authClient.subscription.upgrade({ plan: "team" });
58
+ await authClient.subscription.list();
59
+ await authClient.subscription.billingPortal({ subscriptionCode: "SUB_code" });
60
+ await authClient.subscription.cancel({ subscriptionCode: "SUB_code", atPeriodEnd: true });
61
+ await authClient.subscription.restore({ subscriptionCode: "SUB_code" });
62
+ ```
63
+
64
+ `subscription.manageLink` is an alias for `subscription.billingPortal`.
65
+
66
+ ### Preserve deprecated aliases
67
+
68
+ `subscription.disable` maps to `subscription.cancel`.
69
+ `subscription.enable` maps to `subscription.restore`.
70
+
71
+ Keep these aliases in the 2.x line for compatibility, but do not introduce them in new examples.
72
+
73
+ ### Respect BetterFetch return typing
74
+
75
+ Methods use `FetchResult<T, O>`:
76
+
77
+ - with `{ throw: true }`, the promise resolves to `T`
78
+ - without `{ throw: true }`, the promise resolves to `BetterFetchResponse<T>`
79
+
80
+ When changing method signatures, update both the interface and implementation, then run type tests.
81
+
82
+ ## Common Mistakes
83
+
84
+ ### Using old `getConfig`
85
+
86
+ The stable method is `authClient.paystack.config()`. Do not add new examples that call
87
+ `authClient.paystack.getConfig()`.
88
+
89
+ ### Passing query data in the body for list endpoints
90
+
91
+ List endpoints use GET with query data:
92
+
93
+ ```ts
94
+ await authClient.subscription.list({ query: { referenceId: "org_123" } });
95
+ await authClient.transaction.list({ query: { referenceId: "org_123" } });
96
+ ```
97
+
98
+ ### Importing the server package in browser code
99
+
100
+ Browser code should import only `@alexasomba/better-auth-paystack/client`. Server helpers such as
101
+ `syncPaystackPlans` and `chargeSubscriptionRenewal` belong in server functions, cron jobs, or trusted
102
+ routes.
103
+
104
+ ## Verification
105
+
106
+ Run these after client API changes:
107
+
108
+ ```bash
109
+ vp test test/typesafety.test.ts
110
+ vp test test/paystack.test.ts
111
+ ```
112
+
113
+ Run TanStack example tests when examples or client usage are changed:
114
+
115
+ ```bash
116
+ pnpm --filter ./examples/tanstack test
117
+ ```
@@ -0,0 +1,6 @@
1
+ interface:
2
+ display_name: "Better Auth Paystack Client API"
3
+ short_description: "Browser client methods and return contracts"
4
+ default_prompt: "Use $paystack-client-api to wire or review authClient Paystack, transaction, and subscription browser APIs."
5
+ policy:
6
+ allow_implicit_invocation: true
@@ -0,0 +1,97 @@
1
+ ---
2
+ name: paystack-local-subscriptions
3
+ description: >
4
+ Implement, debug, or test local-managed subscription behavior in @alexasomba/better-auth-paystack. Use for local plans without planCode, saved authorization renewal, chargeSubscriptionRenewal, seat billing, prorateAndCharge, pendingPlan, LOC_ subscription codes, trial transitions, schedule-at-period-end upgrades, and Paystack-managed vs local-managed behavior.
5
+ type: core
6
+ library: "@alexasomba/better-auth-paystack"
7
+ library_version: "2.5.0" # 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:src/subscription-lifecycle.ts"
12
+ - "alexasomba/better-auth-paystack:src/operations.ts"
13
+ - "alexasomba/better-auth-paystack:src/routes.ts"
14
+ - "alexasomba/better-auth-paystack:src/utils.ts"
15
+ - "alexasomba/better-auth-paystack:test/local_subscription.test.ts"
16
+ - "alexasomba/better-auth-paystack:test/seat_billing.test.ts"
17
+ ---
18
+
19
+ ## Local Subscription Model
20
+
21
+ A plan without `planCode` is locally managed. The plugin stores subscription state in the Better Auth
22
+ database and charges future renewals with a saved Paystack authorization code.
23
+
24
+ Local-managed subscriptions are required for:
25
+
26
+ - seat-based local billing
27
+ - prorated mid-cycle seat or plan upgrades
28
+ - trusted backend renewal jobs through `chargeSubscriptionRenewal`
29
+ - local trial and pending plan transitions
30
+
31
+ Use Paystack-native `planCode` plans for simple fixed recurring billing.
32
+
33
+ ## Core Patterns
34
+
35
+ ### Capture reusable authorization during verification
36
+
37
+ Local subscriptions become renewable after transaction verification or webhook reconciliation stores
38
+ `authorization.authorization_code` on the subscription. If the authorization is absent, renewal must
39
+ fail with a clear error instead of inventing a charge path.
40
+
41
+ ### Use server-only renewal helpers
42
+
43
+ `chargeSubscriptionRenewal(ctx, options, { subscriptionId })` is for cron jobs, admin server
44
+ functions, or trusted server routes. Never expose it directly as a browser action.
45
+
46
+ Before charging, verify the caller can manage the subscription reference. For organization billing,
47
+ only owners/admins should trigger renewals.
48
+
49
+ ### Prorate only local active subscriptions
50
+
51
+ `prorateAndCharge` is handled by `handleProratedUpgrade`.
52
+
53
+ The existing active subscription must have:
54
+
55
+ - status `active`
56
+ - a Paystack or local subscription code
57
+ - `periodStart` and `periodEnd`
58
+ - local-management compatibility for plan or seat changes
59
+
60
+ If a saved authorization exists, the prorated amount is charged immediately. If not, the code creates
61
+ a checkout transaction and applies the upgrade after the reference is verified.
62
+
63
+ Paystack minimum charge behavior matters. If the prorated amount is below the supported minimum,
64
+ surface a BAD_REQUEST and advise scheduling the change for period end.
65
+
66
+ ### Preserve pending plan semantics
67
+
68
+ Scheduled changes should use `pendingPlan` rather than silently changing the active plan. Immediate
69
+ local changes should update `plan`, `seats`, and transaction reference consistently.
70
+
71
+ ## Common Mistakes
72
+
73
+ ### Adding `planCode` to a local billing plan
74
+
75
+ Do not add `planCode` to a plan that needs local seat billing, prorated upgrades, or local renewals.
76
+ That turns the plan into a Paystack-managed subscription path.
77
+
78
+ ### Updating seats for Paystack-managed subscriptions
79
+
80
+ Seat and proration helpers intentionally reject Paystack-managed subscriptions. Use local-managed
81
+ plans for seat-aware billing.
82
+
83
+ ### Charging renewals from client components
84
+
85
+ The client may trigger checkout. Renewal jobs require trusted server code and a validated session or
86
+ job context.
87
+
88
+ ## Verification
89
+
90
+ Run focused tests after lifecycle changes:
91
+
92
+ ```bash
93
+ vp test test/local_subscription.test.ts
94
+ vp test test/seat_billing.test.ts
95
+ ```
96
+
97
+ Run `vp test test/paystack.test.ts` when route behavior, trials, or organization billing are touched.
@@ -0,0 +1,6 @@
1
+ interface:
2
+ display_name: "Better Auth Paystack Local Subs"
3
+ short_description: "Local subscriptions, renewals, and proration"
4
+ default_prompt: "Use $paystack-local-subscriptions to implement or debug local-managed Paystack subscription lifecycle behavior."
5
+ policy:
6
+ allow_implicit_invocation: true
@@ -1,10 +1,10 @@
1
1
  ---
2
- name: organization-billing
2
+ name: paystack-organization-billing
3
3
  description: >
4
- Configure organization billing in @alexasomba/better-auth-paystack. Use for organization.enabled, Better Auth organization plugin setup, owner/admin default billing authorization, subscription.authorizeReference, organization Paystack customers, seats, invitations, members, and team limits.
4
+ Configure organization billing in @alexasomba/better-auth-paystack. Use for organization.enabled, Better Auth organization plugin setup, owner/admin default billing authorization, organization.billingRoles, subscription.authorizeReference, organization Paystack customers, seats, invitations, members, and team limits.
5
5
  type: core
6
6
  library: "@alexasomba/better-auth-paystack"
7
- library_version: "2.4.3" # x-release-please-version
7
+ library_version: "2.5.0" # x-release-please-version
8
8
  license: "MIT"
9
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
10
  sources:
@@ -50,6 +50,7 @@ export const auth = betterAuth({
50
50
  },
51
51
  organization: {
52
52
  enabled: true,
53
+ billingRoles: ["owner", "admin", "billing"],
53
54
  },
54
55
  }),
55
56
  ],
@@ -64,9 +65,29 @@ When `subscription.authorizeReference` is not supplied, organization billing act
64
65
 
65
66
  Ordinary members are rejected by default. Do not write UI or tests that assume any member can create, upgrade, cancel, or restore organization subscriptions.
66
67
 
68
+ ### Add trusted billing roles without replacing the default
69
+
70
+ Use `organization.billingRoles` when a product needs a role such as `billing`, `finance`, or `accounting` to manage organization billing while preserving the built-in user self-access, organization membership lookup, and action scoping.
71
+
72
+ ```ts
73
+ paystack({
74
+ secretKey: process.env.PAYSTACK_SECRET_KEY!,
75
+ subscription: {
76
+ enabled: true,
77
+ plans: [],
78
+ },
79
+ organization: {
80
+ enabled: true,
81
+ billingRoles: ["owner", "admin", "billing"],
82
+ },
83
+ });
84
+ ```
85
+
86
+ Role matching supports Better Auth string roles, comma-separated role strings like `"member,billing"`, and array roles like `["member", "billing"]`.
87
+
67
88
  ### Override authorization explicitly for custom workflows
68
89
 
69
- Use `subscription.authorizeReference` when a product intentionally allows non-owner/admin billing access:
90
+ Use `subscription.authorizeReference` when a product needs lower-level policy checks that cannot be represented as organization roles:
70
91
 
71
92
  ```ts
72
93
  paystack({
@@ -0,0 +1,6 @@
1
+ interface:
2
+ display_name: "Better Auth Paystack Org Billing"
3
+ short_description: "Organization billing, seats, and access"
4
+ default_prompt: "Use $paystack-organization-billing to configure Paystack billing for Better Auth organizations, seats, and admin access."
5
+ policy:
6
+ allow_implicit_invocation: true
@@ -0,0 +1,94 @@
1
+ ---
2
+ name: paystack-schema-migrations
3
+ description: >
4
+ Modify or review @alexasomba/better-auth-paystack database schema behavior. Use for paystackProduct, paystackPlan, paystackTransaction, subscription, user.paystackCustomerCode, organization.paystackCustomerCode/email, Better Auth schema overrides, mergeSchema behavior, migrations, indexes, unique fields, and backward-compatible table or field changes.
5
+ type: core
6
+ library: "@alexasomba/better-auth-paystack"
7
+ library_version: "2.5.0" # 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:src/schema.ts"
12
+ - "alexasomba/better-auth-paystack:src/types.ts"
13
+ - "alexasomba/better-auth-paystack:test/paystack.test.ts"
14
+ - "alexasomba/better-auth-paystack:test/typesafety.test.ts"
15
+ ---
16
+
17
+ ## Schema Contract
18
+
19
+ The plugin contributes Better Auth schema through `getSchema(options)`.
20
+
21
+ Always included:
22
+
23
+ - `user.paystackCustomerCode`
24
+ - `paystackTransaction`
25
+ - `paystackProduct`
26
+ - `paystackPlan`
27
+
28
+ Included when `subscription.enabled` is true:
29
+
30
+ - `subscription`
31
+
32
+ Included when `organization.enabled` is true:
33
+
34
+ - `organization.paystackCustomerCode`
35
+ - `organization.email`
36
+
37
+ Product and plan tables are intentionally always present. Do not make them optional in a
38
+ compatibility-preserving release.
39
+
40
+ ## Core Patterns
41
+
42
+ ### Use schema overrides only for Better Auth-supported customization
43
+
44
+ Consumers can pass `options.schema` and the plugin merges it with the default schema via
45
+ `mergeSchema`. Use this for model/field naming and migration metadata, not for removing core billing
46
+ state.
47
+
48
+ When subscriptions are disabled, `getSchema` strips a user-provided `subscription` override before
49
+ merging so the subscription model is not reintroduced accidentally.
50
+
51
+ ### Preserve field compatibility
52
+
53
+ Schema changes affect persisted billing state. Treat these as migration-sensitive:
54
+
55
+ - changing required fields
56
+ - changing uniqueness or indexes
57
+ - renaming `paystack*` identity fields
58
+ - changing transaction `reference` uniqueness
59
+ - changing subscription `paystackSubscriptionCode` uniqueness
60
+ - changing product/plan `paystackId` or `planCode` uniqueness
61
+
62
+ Prefer additive optional fields in minor releases. Required field changes need clear migrations and
63
+ major-version scrutiny.
64
+
65
+ ### Keep TypeScript schema exports aligned
66
+
67
+ `PaystackPluginSchema`, individual schema exports, and `PaystackOptions["schema"]` should stay in
68
+ sync. If a field is added to a schema table, update the corresponding TypeScript table type in
69
+ `src/schema.ts`.
70
+
71
+ ## Common Mistakes
72
+
73
+ ### Removing catalog tables when products are unused
74
+
75
+ The package supports catalog sync and discovery. `paystackProduct` and `paystackPlan` remain part of
76
+ the plugin schema even if a specific app only uses subscriptions or only uses transactions.
77
+
78
+ ### Reintroducing subscription schema when subscriptions are disabled
79
+
80
+ Keep the guard in `getSchema` that removes `options.schema.subscription` unless
81
+ `subscription.enabled` is true.
82
+
83
+ ### Forgetting organization schema conditions
84
+
85
+ Organization billing fields should only be added when `organization.enabled` is true.
86
+
87
+ ## Verification
88
+
89
+ Run schema and type tests after schema changes:
90
+
91
+ ```bash
92
+ vp test test/paystack.test.ts test/typesafety.test.ts
93
+ vp check
94
+ ```
@@ -0,0 +1,6 @@
1
+ interface:
2
+ display_name: "Better Auth Paystack Schema"
3
+ short_description: "Database schema and migration guidance"
4
+ default_prompt: "Use $paystack-schema-migrations to review or change Better Auth Paystack schema and migration behavior."
5
+ policy:
6
+ allow_implicit_invocation: true
@@ -1,10 +1,10 @@
1
1
  ---
2
- name: tanstack-start
2
+ name: paystack-tanstack-start
3
3
  description: >
4
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
5
  type: composition
6
6
  library: "@alexasomba/better-auth-paystack"
7
- library_version: "2.4.3" # x-release-please-version
7
+ library_version: "2.5.0" # x-release-please-version
8
8
  license: "MIT"
9
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
10
  sources: