### Run TanStack Example Source: https://github.com/alexasomba/better-auth-paystack/blob/main/README.md Runs the TanStack Start example development server. ```bash vp run examples/tanstack dev ``` -------------------------------- ### Install Dependencies Source: https://github.com/alexasomba/better-auth-paystack/blob/main/README.md Installs project dependencies using the 'vp' CLI. ```bash vp i ``` -------------------------------- ### Run Development Server Source: https://github.com/alexasomba/better-auth-paystack/blob/main/examples/tanstack/README.md Starts the TanStack Start development server. Access the application at http://localhost:8787. ```bash pnpm dev ``` -------------------------------- ### Sync Paystack Products (Initialization Script) Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/api-reference-server-operations.md Example of calling `syncPaystackProducts` within an initialization script to ensure products are synchronized when the application starts. ```typescript async function initializeProducts() { const ctx = { context: await auth.$context }; await syncPaystackProducts(ctx, paystackOptions); console.log("Products synced successfully"); } ``` -------------------------------- ### Run TanStack Example Tests Source: https://github.com/alexasomba/better-auth-paystack/blob/main/skills/paystack-client-api/SKILL.md Run tests for the TanStack example integration when making changes to client usage or examples. Use the pnpm filter command. ```bash pnpm --filter ./examples/tanstack test ``` -------------------------------- ### Example of Calling Sign-In with Cookies Handled Source: https://github.com/alexasomba/better-auth-paystack/blob/main/examples/tanstack/better-auth-tanstack.md Demonstrates calling a sign-in function after configuring Better Auth with TanStack Start's cookie handling. Cookies will be automatically managed. ```typescript import { auth } from "@/lib/auth"; const signIn = async () => { await auth.api.signInEmail({ body: { email: "user@email.com", password: "password", }, }); }; ``` -------------------------------- ### Install Dependencies with npm Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/README.md Install the necessary packages for Better Auth and its Paystack integration. ```bash npm install better-auth @alexasomba/better-auth-paystack @alexasomba/paystack-node ``` -------------------------------- ### Build for Production Source: https://github.com/alexasomba/better-auth-paystack/blob/main/examples/tanstack/README.md Compiles the TanStack Start application for production deployment. ```bash pnpm build ``` -------------------------------- ### Install Optional Browser SDK Source: https://github.com/alexasomba/better-auth-paystack/blob/main/README.md Install the @alexasomba/paystack-inline package if you need to support Paystack's inline checkout experience via popup modals. ```bash npm install @alexasomba/paystack-inline ``` -------------------------------- ### Hook for Free Trial Start Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/configuration.md Execute logic when a free trial period begins for a subscription plan. Typically used to send trial start notifications. ```typescript subscription: { plans: [ { name: "pro", freeTrial: { days: 14, onTrialStart: async (subscription) => { await sendEmail({ to: subscription.userEmail, template: "trial_started", data: { endDate: subscription.trialEnd, }, }); }, }, }, ], } ``` -------------------------------- ### Build TanStack Example for Cloudflare Workers Source: https://github.com/alexasomba/better-auth-paystack/blob/main/skills/paystack-tanstack-start/SKILL.md Use the provided commands to build and deploy the TanStack example to Cloudflare Workers. This helps in reproducing and debugging Worker-specific issues. ```bash pnpm --filter ./examples/tanstack build pnpm --filter ./examples/tanstack exec wrangler deploy --dry-run ``` -------------------------------- ### Install AI Agent Skills with skills-npm Source: https://github.com/alexasomba/better-auth-paystack/blob/main/README.md Install the package and then run the skills-npm command to symlink installed package skills for compatible AI agents. This makes package skills discoverable by agents. ```bash npm install @alexasomba/better-auth-paystack npx skills-npm --yes ``` -------------------------------- ### Install Dependencies with pnpm Source: https://github.com/alexasomba/better-auth-paystack/blob/main/examples/tanstack/README.md Installs project dependencies using the pnpm package manager. ```bash pnpm install ``` -------------------------------- ### Install Paystack Browser Plugin Source: https://github.com/alexasomba/better-auth-paystack/blob/main/skills/paystack-client-api/SKILL.md Import and create the auth client with the Paystack plugin. Ensure the subscription option is enabled if needed. ```typescript import { createAuthClient } from "better-auth/client"; import { paystackClient } from "@alexasomba/better-auth-paystack/client"; export const authClient = createAuthClient({ plugins: [paystackClient({ subscription: true })], }); ``` -------------------------------- ### Local Plan Subscription Example Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/database-schema.md Example of a subscription record for a local plan managed by the application. Uses an authorization code for renewals. ```typescript { id: "sub_456", userId: "user_456", plan: "starter", referenceId: "user_456", paystackSubscriptionCode: "LOC_sub_456", paystackAuthorizationCode: "AUTH_xyz789", status: "active", seats: 5, periodStart: new Date("2024-06-01"), periodEnd: new Date("2024-07-01"), } ``` -------------------------------- ### Configure Better Auth with TanStack Start Cookies (Solid.js) Source: https://github.com/alexasomba/better-auth-paystack/blob/main/examples/tanstack/better-auth-tanstack.md Integrate the `tanstackStartCookies` plugin for automatic cookie handling in Solid.js-based TanStack Start applications. Ensure this is the last plugin. ```typescript import { betterAuth } from "better-auth"; import { tanstackStartCookies } from "better-auth/tanstack-start/solid"; export const auth = betterAuth({ //...your config plugins: [tanstackStartCookies()], // make sure this is the last plugin in the array }); ``` -------------------------------- ### Organization Billing Subscription Example Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/database-schema.md Example of a subscription record for an organization, including organization ID and customer code for Paystack. ```typescript { id: "sub_org_789", userId: "user_789", organizationId: "org_789", plan: "pro", referenceId: "org_789", paystackCustomerCode: "CUS_org_789", status: "active", seats: 10, } ``` -------------------------------- ### Native Plan Subscription Example Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/database-schema.md Example of a subscription record for a native plan managed by Paystack. Includes Paystack-specific codes and dates. ```typescript { id: "sub_123", userId: "user_123", plan: "pro", referenceId: "user_123", paystackSubscriptionCode: "SUB_abc123", paystackPlanCode: "PLN_pro_code", status: "active", seats: 1, periodStart: new Date("2024-06-01"), periodEnd: new Date("2024-07-01"), cancelAtPeriodEnd: false, } ``` -------------------------------- ### Initialize Paystack Plugin Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/configuration.md Configure the Paystack plugin with essential keys and subscription details. This is the primary setup for integrating Paystack. ```typescript import { paystack } from "@alexasomba/better-auth-paystack"; const auth = betterAuth({ plugins: [ paystack({ secretKey: process.env.PAYSTACK_SECRET_KEY, webhook: { secret: process.env.PAYSTACK_WEBHOOK_SECRET, }, subscription: { enabled: true, plans: [ { name: "pro", planCode: "PLN_pro_code", amount: 100000, currency: "NGN", interval: "monthly", }, ], }, }), ], }); ``` -------------------------------- ### Paystack Plugin Initialization Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/api-reference-main-plugin.md Initialize the Paystack plugin for Better Auth. This example demonstrates setting up the Paystack client, webhook verification, subscription plans, product configurations, and event handling. ```typescript import { betterAuth } from "better-auth"; import { paystack } from "@alexasomba/better-auth-paystack"; import { createPaystack } from "@alexasomba/paystack-node"; import { admin } from "better-auth/plugins"; const paystackClient = createPaystack({ secretKey: process.env.PAYSTACK_SECRET_KEY!, }); export const auth = betterAuth({ database: { provider: "postgresql", url: process.env.DATABASE_URL!, }, plugins: [ admin(), paystack({ paystackClient, webhook: { secret: process.env.PAYSTACK_WEBHOOK_SECRET!, verifyIP: true, }, createCustomerOnSignUp: true, subscription: { enabled: true, allowedPaymentChannels: ["card"], plans: [ { name: "pro", planCode: "PLN_pro_code", freeTrial: { days: 14 }, limits: { teams: 10, seats: 20 }, }, { name: "starter", amount: 50000, currency: "NGN", interval: "monthly", }, ], }, products: { products: [ { name: "credits_50", amount: 200000, currency: "NGN", }, ], }, onEvent: async (event) => { console.log("Paystack event:", event.event); }, }), ], }); ``` -------------------------------- ### Initialize and Use Paystack Client Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/api-reference-client-plugin.md Demonstrates how to create an authenticated client with the Paystack plugin enabled for subscription management. Shows examples for initializing transactions, verifying payments, creating and managing subscriptions, and accessing Paystack-specific configurations. ```typescript import { createAuthClient } from "better-auth/client"; import { paystackClient } from "@alexasomba/better-auth-paystack/client"; import { adminClient } from "better-auth/client/plugins"; export const client = createAuthClient({ baseURL: "http://localhost:3000", plugins: [adminClient(), paystackClient({ subscription: true })], }); // Usage in components: // 1. Initialize a transaction for a plan const { data, error } = await client.transaction.initialize({ plan: "pro", quantity: 5, email: "user@example.com", metadata: { customField: "value" }, }); if (data?.accessCode) { window.location.href = data.url; // Redirect to Paystack checkout } // 2. Verify transaction after payment const verifyResult = await client.transaction.verify({ reference: "txn_1234567890", }); // 3. Create a subscription const subResult = await client.subscription.create({ plan: "starter", email: "user@example.com", }); // 4. List user's subscriptions const { data: subscriptions } = await client.subscription.list(); // 5. Cancel subscription (deferred to period end) const cancelResult = await client.subscription.cancel({ subscriptionCode: "SUB_xyz", atPeriodEnd: true, }); // 6. Upgrade to pro and charge prorated delta const upgradeResult = await client.transaction.initialize({ plan: "pro", quantity: 10, prorateAndCharge: true, }); // 7. List one-time transactions const transResult = await client.transaction.list(); // 8. Get subscription management link const portalResult = await client.subscription.billingPortal({ subscriptionCode: "SUB_xyz", }); if (portalResult.data?.link) { window.location.href = portalResult.data.link; // Open Paystack portal } // 9. Get plugin configuration const configResult = await client.paystack.config(); // 10. List products const productsResult = await client.paystack.listProducts(); ``` -------------------------------- ### Setup Paystack Plugin with Products and Subscriptions Source: https://github.com/alexasomba/better-auth-paystack/blob/main/skills/paystack-catalog-limits/SKILL.md Configure the Paystack plugin with products, subscription plans, free trials, and limits. Ensure your environment variables for PAYSTACK_SECRET_KEY and PAYSTACK_WEBHOOK_SECRET are set. ```typescript import { paystack, } from "@alexasomba/better-auth-paystack"; export const paystackPlugin = paystack({ secretKey: process.env.PAYSTACK_SECRET_KEY!, webhook: { secret: process.env.PAYSTACK_WEBHOOK_SECRET!, }, products: { products: [ { name: "credits_50", amount: 200_000, currency: "NGN", }, ], }, subscription: { enabled: true, plans: [ { name: "pro", amount: 500_000, currency: "NGN", interval: "monthly", planCode: "PLN_pro_monthly", paystackId: "1001", freeTrial: { days: 14, }, limits: { seats: 10, teams: 5, }, }, ], }, }); ``` -------------------------------- ### Vercel Cron Integration Example Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/api-reference-server-operations.md Shows how to set up a Vercel Cron job for subscription renewals, including authorization validation. ```typescript // api/cron/renew-subscriptions.ts export async function GET(request: Request) { // Validate request token to prevent abuse if (request.headers.get("authorization") !== `Bearer ${process.env.CRON_SECRET}`) { return new Response("Unauthorized", { status: 401 }); } // Call chargeSubscriptionRenewal for each subscription } ``` -------------------------------- ### Node.js node-cron Integration Example Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/api-reference-server-operations.md Demonstrates using the node-cron library to schedule daily subscription renewal tasks. ```typescript import cron from "node-cron"; cron.schedule("0 0 * * *", async () => { // Run renewal at midnight daily const ctx = { context: await auth.$context }; // Call chargeSubscriptionRenewal for each subscription }); ``` -------------------------------- ### GET /paystack/list-products Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/endpoints.md Lists all available products for one-time purchase. ```APIDOC ## GET /paystack/list-products ### Description List all available products for one-time purchase. ### Method GET ### Endpoint /paystack/list-products ### Parameters #### Query Parameters None. ### Response #### Success Response (200) - **products** (PaystackProduct[]) - List of available products. ### Response Example { "products": [ { "id": "prod_1", "name": "Widget", "price": 500, "description": "A useful widget" } ] } ``` -------------------------------- ### GET /paystack/list-plans Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/endpoints.md Lists all available subscription plans. ```APIDOC ## GET /paystack/list-plans ### Description List all available plans for subscriptions. ### Method GET ### Endpoint /paystack/list-plans ### Parameters #### Query Parameters None. ### Response #### Success Response (200) - **plans** (PaystackPlan[]) - List of available subscription plans. ### Response Example { "plans": [ { "id": "plan_1", "name": "Basic Plan", "amount": 1000, "currency": "NGN", "interval": "monthly" } ] } ``` -------------------------------- ### Server Setup with Paystack Plugin Source: https://github.com/alexasomba/better-auth-paystack/blob/main/skills/better-auth-paystack-setup/SKILL.md Configure the Paystack server plugin for Better Auth. Ensure Paystack SDK, secret key, and webhook secret are provided. Subscription plans can be enabled and defined here. ```typescript import { betterAuth, } from "better-auth"; import { createPaystack, } from "@alexasomba/paystack-node"; import { paystack, } from "@alexasomba/better-auth-paystack"; const paystackSdk = createPaystack({ secretKey: process.env.PAYSTACK_SECRET_KEY!, }); export const auth = betterAuth({ database: { provider: "sqlite", url: process.env.DATABASE_URL!, }, plugins: [ paystack({ paystackClient: paystackSdk, secretKey: process.env.PAYSTACK_SECRET_KEY!, webhook: { secret: process.env.PAYSTACK_WEBHOOK_SECRET!, }, subscription: { enabled: true, plans: [ { name: "pro", amount: 500_000, currency: "NGN", interval: "monthly", planCode: "PLN_pro_monthly", paystackId: "123456", }, ], }, }), ], }); ``` -------------------------------- ### Configure Better Auth with TanStack Start Cookies (React) Source: https://github.com/alexasomba/better-auth-paystack/blob/main/examples/tanstack/better-auth-tanstack.md Integrate the `tanstackStartCookies` plugin for automatic cookie handling in React-based TanStack Start applications. Ensure this is the last plugin. ```typescript import { betterAuth } from "better-auth"; import { tanstackStartCookies } from "better-auth/tanstack-start"; export const auth = betterAuth({ //...your config plugins: [tanstackStartCookies()], // make sure this is the last plugin in the array }); ``` -------------------------------- ### Setup Paystack Subscriptions Source: https://github.com/alexasomba/better-auth-paystack/blob/main/skills/paystack-billing-flows/SKILL.md Configure the Paystack integration to enable subscription functionality by defining plans with their respective amounts, currencies, intervals, and Paystack-specific identifiers. Ensure Paystack plan metadata is correctly set up. ```typescript import { paystack, } from "@alexasomba/better-auth-paystack"; paystack({ secretKey: process.env.PAYSTACK_SECRET_KEY!, webhook: { secret: process.env.PAYSTACK_WEBHOOK_SECRET!, }, subscription: { enabled: true, plans: [ { name: "starter", amount: 250_000, currency: "NGN", interval: "monthly", planCode: "PLN_starter", paystackId: "1001", }, { name: "team", amount: 1_000_000, currency: "NGN", interval: "monthly", planCode: "PLN_team", paystackId: "1002", limits: { seats: 10, teams: 3, }, }, ], }, }); ``` -------------------------------- ### Setup Server Plugin with Paystack Source: https://github.com/alexasomba/better-auth-paystack/blob/main/README.md Configure the Better Auth server plugin with Paystack integration, including subscription and product settings. Ensure Paystack secret keys and webhook secrets are set in environment variables. ```typescript import { betterAuth, } from "better-auth"; import { paystack, } from "@alexasomba/better-auth-paystack"; import { createPaystack, } from "@alexasomba/paystack-node"; import { admin } from "better-auth/plugins"; const paystackClient = createPaystack({ secretKey: process.env.PAYSTACK_SECRET_KEY!, }); export const auth = betterAuth({ plugins: [ admin(), paystack({ paystackClient, webhook: { secret: process.env.PAYSTACK_WEBHOOK_SECRET! }, createCustomerOnSignUp: true, subscription: { enabled: true, allowedPaymentChannels: ["card"], // Optional: enforce card-only subscriptions plans: [ { name: "pro", planCode: "PLN_pro_123", // Native: Managed by Paystack freeTrial: { days: 14 }, limits: { teams: 5, seats: 10 }, // Custom resource & member limits }, { name: "starter", amount: 50000, // Local: Managed by your app (500 NGN) currency: "NGN", interval: "monthly", }, ], }, products: { products: [{ name: "credits_50", amount: 200000, currency: "NGN" }], }, }), ], }); ``` -------------------------------- ### Sync Paystack Products (Server Endpoint) Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/api-reference-server-operations.md Example of creating a server-only endpoint to manually sync products from Paystack. Requires admin authorization and handles potential errors during the sync process. ```typescript import { syncPaystackProducts } from "@alexasomba/better-auth-paystack"; // Manual bulk sync endpoint (server-only, not exposed to client) app.post("/admin/sync-products", async (req, res) => { // Verify admin authorization if (!req.user.isAdmin) return res.status(403).json({ error: "Forbidden" }); try { const ctx = { context: await auth.$context }; const result = await syncPaystackProducts(ctx, paystackOptions); res.json({ status: result.status, synced: result.count, message: `Synced ${result.count} products from Paystack`, }); } catch (error) { res.status(500).json({ error: error instanceof Error ? error.message : "Sync failed", }); } }); ``` -------------------------------- ### Initialize Transaction Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/api-reference-client-plugin.md Starts a new transaction with Paystack. Requires a plan identifier. ```APIDOC ## POST /paystack/initialize-transaction ### Description Starts a new transaction with Paystack. This is the initial step to process a payment. ### Method POST ### Endpoint /paystack/initialize-transaction ### Parameters #### Request Body - **plan** (string) - Required - The identifier for the plan to be used for the transaction. ### Request Example ```json { "plan": "pro" } ``` ### Response #### Success Response (200) - **accessCode** (string) - The code required to initiate the checkout modal. ``` -------------------------------- ### Configure Better Auth with Paystack and TanStack Start Cookies Source: https://github.com/alexasomba/better-auth-paystack/blob/main/skills/paystack-tanstack-start/SKILL.md Set up the Better Auth server configuration, including the Paystack plugin and `tanstackStartCookies()`. Ensure `tanstackStartCookies()` is the last plugin to correctly wrap auth behavior. ```typescript import { betterAuth } from "better-auth"; import { tanstackStartCookies } from "better-auth/tanstack-start"; import { paystack } from "@alexasomba/better-auth-paystack"; export const auth = betterAuth({ baseURL: process.env.BETTER_AUTH_URL, plugins: [ paystack({ secretKey: process.env.PAYSTACK_SECRET_KEY!, webhook: { secret: process.env.PAYSTACK_WEBHOOK_SECRET!, }, subscription: { enabled: true, plans: [], }, }), tanstackStartCookies(), ], }); ``` -------------------------------- ### GET /paystack/config Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/endpoints.md Retrieves the plugin configuration, including available plans and products. ```APIDOC ## GET /paystack/config ### Description Get plugin configuration (available plans and products). ### Method GET ### Endpoint /paystack/config ### Parameters #### Query Parameters None. ### Response #### Success Response (200) - **plans** (PaystackPlan[]) - Optional - Available subscription plans. - **products** (PaystackProduct[]) - Optional - Available products for one-time purchase. ### Response Example { "plans": [ { "id": "plan_1", "name": "Basic Plan", "amount": 1000, "currency": "NGN", "interval": "monthly" } ], "products": [ { "id": "prod_1", "name": "Widget", "price": 500, "description": "A useful widget" } ] } ``` -------------------------------- ### Client Setup with Paystack Client Plugin Source: https://github.com/alexasomba/better-auth-paystack/blob/main/skills/better-auth-paystack-setup/SKILL.md Add the Paystack client plugin to your Better Auth client configuration. This enables client-side interactions with Paystack-related features. ```typescript import { createAuthClient, } from "better-auth/client"; import { paystackClient, } from "@alexasomba/better-auth-paystack/client"; export const authClient = createAuthClient({ plugins: [paystackClient()], }); ``` -------------------------------- ### Install AI Agent Skills with TanStack Intent Source: https://github.com/alexasomba/better-auth-paystack/blob/main/README.md Use TanStack Intent to list or load package-specific guidance for AI coding agents. Run this command in your project to enable agent discovery of package skills. ```bash npx @tanstack/intent@latest list npx @tanstack/intent@latest load @alexasomba/better-auth-paystack#better-auth-paystack-setup npx @tanstack/intent@latest load @alexasomba/better-auth-paystack#paystack-testing-fixtures ``` -------------------------------- ### Get Product by Name Source: https://github.com/alexasomba/better-auth-paystack/blob/main/_autodocs/database-schema.md This TypeScript snippet demonstrates how to find a specific product by its name using Prisma's `findFirst` method. ```typescript const product = await db.paystackProduct.findFirst({ where: { name: "credits_50", }, }); ``` -------------------------------- ### Mount Better Auth Handler in TanStack Start Source: https://github.com/alexasomba/better-auth-paystack/blob/main/examples/tanstack/better-auth-tanstack.md Mount the Better Auth handler to a TanStack API endpoint. This setup handles GET and POST requests for authentication. ```typescript import { auth } from "@/lib/auth"; import { createFileRoute } from "@tanstack/react-router"; export const Route = createFileRoute("/api/auth/$")({ server: { handlers: { GET: async ({ request }: { request: Request }) => { return await auth.handler(request); }, POST: async ({ request }: { request: Request }) => { return await auth.handler(request); }, }, }, }); ``` -------------------------------- ### Plan Configuration with Free Trial Source: https://github.com/alexasomba/better-auth-paystack/blob/main/skills/paystack-catalog-limits/SKILL.md Configure a subscription plan with a free trial. The `onTrialStart` callback can be used to trigger custom logic when a trial begins. The plugin prevents repeat trials for the same reference ID. ```json { name: "starter", amount: 250_000, currency: "NGN", interval: "monthly", planCode: "PLN_starter", paystackId: "1002", freeTrial: { days: 7, onTrialStart: async (subscription) => { await notifyTrialStarted(subscription.referenceId); }, }, } ``` -------------------------------- ### Applying Authentication Middleware to a Route Source: https://github.com/alexasomba/better-auth-paystack/blob/main/examples/tanstack/better-auth-tanstack.md Example of applying the custom authentication middleware to a specific route definition in TanStack Start to protect it. ```typescript import { createFileRoute } from "@tanstack/react-router"; import { authMiddleware } from "@/lib/middleware"; export const Route = createFileRoute("/dashboard")({ component: RouteComponent, server: { middleware: [authMiddleware], }, }); function RouteComponent() { return