@alexasomba/better-auth-paystack 1.1.2 → 1.2.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.
- package/README.md +22 -2
- package/dist/client.d.mts +23 -1
- package/dist/client.d.mts.map +1 -1
- package/dist/client.mjs.map +1 -1
- package/dist/index.d.mts +51 -87
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +308 -63
- package/dist/index.mjs.map +1 -1
- package/dist/{types-CMXvth6C.d.mts → types-BOpjdQrr.d.mts} +31 -4
- package/dist/types-BOpjdQrr.d.mts.map +1 -0
- package/package.json +8 -8
- package/dist/types-CMXvth6C.d.mts.map +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/paystack-sdk.ts","../src/utils.ts","../src/middleware.ts","../src/routes.ts","../src/schema.ts","../src/limits.ts","../src/index.ts"],"sourcesContent":["import type {\n\tPaystackClientLike,\n\tPaystackCustomerCreateInput,\n\tPaystackCustomerUpdateInput,\n\tPaystackNodeClient,\n\tPaystackOpenApiFetchResponse,\n\tPaystackSubscriptionFetchInit,\n\tPaystackSubscriptionCreateInput,\n\tPaystackSubscriptionToggleInput,\n\tPaystackTransactionInitializeInput,\n\tPaystackTransactionChargeAuthorizationInput,\n} from \"./types\";\n\nfunction isOpenApiFetchResponse(\n\tvalue: unknown,\n): value is PaystackOpenApiFetchResponse {\n\treturn (\n\t\tvalue !== null &&\n\t\tvalue !== undefined &&\n typeof value === \"object\" &&\n (\"data\" in value || \"error\" in value || \"response\" in value)\n\t);\n}\n\nexport function unwrapSdkResult<T = unknown>(result: unknown): T {\n\tif (isOpenApiFetchResponse(result)) {\n\t\tif (result.error !== undefined && result.error !== null) {\n\t\t\tthrow new Error(typeof result.error === \"string\" ? result.error : JSON.stringify(result.error));\n\t\t}\n\t\treturn (result.data as T) ?? (result as T);\n\t}\n\tif (result !== null && result !== undefined && typeof result === \"object\" && \"data\" in result) {\n\t\tconst data = (result as { data: unknown }).data;\n\t\t// If data is also an object with a data property, unwrap it (legacy SDK style)\n\t\tif (data !== null && typeof data === \"object\" && \"data\" in data) {\n\t\t\treturn (data as { data: T }).data;\n\t\t}\n\t\treturn data as T;\n\t}\n\treturn result as T;\n}\n\n\n\n\n\ntype TransactionInitializeBody = Parameters<PaystackNodeClient[\"transaction_initialize\"]>[0] extends {\n\tbody?: infer B;\n}\n\t? B\n\t: never;\n\nexport function getPaystackOps(\n\tpaystackClient: PaystackClientLike,\n) {\n\treturn {\n\t\tcustomerCreate: (params: PaystackCustomerCreateInput) => {\n\t\t\tif (paystackClient?.customer_create !== undefined) {\n\t\t\t\treturn paystackClient.customer_create({ body: params as unknown as NonNullable<Parameters<PaystackNodeClient[\"customer_create\"]>[0]>[\"body\"] });\n\t\t\t}\n\t\t\treturn paystackClient?.customer?.create?.(params);\n\t\t},\n\t\tcustomerUpdate: (code: string, params: PaystackCustomerUpdateInput) => {\n\t\t\tif (paystackClient?.customer_update !== undefined) {\n\t\t\t\treturn paystackClient.customer_update({\n\t\t\t\t\tparams: { path: { code } },\n\t\t\t\t\tbody: params as unknown as NonNullable<Parameters<PaystackNodeClient[\"customer_update\"]>[0]>[\"body\"],\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.customer?.update?.(code, params);\n\t\t},\n\t\ttransactionInitialize: (body: PaystackTransactionInitializeInput) => {\n\t\t\tif (paystackClient?.transaction_initialize !== undefined) {\n\t\t\t\treturn paystackClient.transaction_initialize({\n\t\t\t\t\tbody: body as TransactionInitializeBody,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.transaction?.initialize?.(body);\n\t\t},\n\t\ttransactionVerify: (reference: string) => {\n\t\t\tif (paystackClient?.transaction_verify !== undefined) {\n\t\t\t\treturn paystackClient.transaction_verify({\n\t\t\t\t\tparams: { path: { reference } },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.transaction?.verify?.(reference);\n\t\t},\n\t\tsubscriptionCreate: (body: PaystackSubscriptionCreateInput) => {\n\t\t\tif (paystackClient?.subscription_create !== undefined) {\n\t\t\t\treturn paystackClient.subscription_create({ body });\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.create?.(body);\n\t\t},\n\t\tsubscriptionDisable: (body: PaystackSubscriptionToggleInput) => {\n\t\t\tif (paystackClient?.subscription_disable !== undefined) {\n\t\t\t\treturn paystackClient.subscription_disable({ body });\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.disable?.(body);\n\t\t},\n\t\tsubscriptionEnable: (body: PaystackSubscriptionToggleInput) => {\n\t\t\tif (paystackClient?.subscription_enable !== undefined) {\n\t\t\t\treturn paystackClient.subscription_enable({ body });\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.enable?.(body);\n\t\t},\n\t\tsubscriptionFetch: async (idOrCode: string) => {\n\t\t\tif (paystackClient?.subscription_fetch !== undefined) {\n\t\t\t\ttry {\n\t\t\t\t\treturn await paystackClient.subscription_fetch({\n\t\t\t\t\t\tparams: { path: { code: idOrCode } },\n\t\t\t\t\t});\n\t\t\t\t} catch {\n\t\t\t\t\tconst compatFetch = paystackClient.subscription_fetch as unknown as (\n init: PaystackSubscriptionFetchInit,\n ) => Promise<unknown>;\n\t\t\t\t\treturn compatFetch({\n\t\t\t\t\t\tparams: { path: { id_or_code: idOrCode } },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.fetch?.(idOrCode);\n\t\t},\n\t\tsubscriptionManageLink: (code: string) => {\n\t\t\tif (paystackClient?.subscription_manageLink !== undefined) {\n\t\t\t\treturn paystackClient.subscription_manageLink({\n\t\t\t\t\tparams: { path: { code } },\n\t\t\t\t});\n\t\t\t}\n\t\t\t// Fallback for snake_case if older SDK version or different generator\n\t\t\tif (paystackClient?.subscription_manage_link !== undefined) {\n\t\t\t\treturn paystackClient.subscription_manage_link({\n\t\t\t\t\tparams: { path: { code } },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.manage?.link?.(code);\n\t\t},\n\t\tsubscriptionManageEmail: (code: string, email: string) => {\n\t\t\tif (paystackClient?.subscription_manageEmail !== undefined) {\n\t\t\t\treturn paystackClient.subscription_manageEmail({\n\t\t\t\t\tparams: { path: { code } },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.manage?.email?.(code, email);\n\t\t},\n\t\ttransactionChargeAuthorization: (body: PaystackTransactionChargeAuthorizationInput) => {\n\t\t\tif (paystackClient?.transaction_chargeAuthorization !== undefined) {\n\t\t\t\treturn paystackClient.transaction_chargeAuthorization({\n\t\t\t\t\t \n\t\t\t\t\t// casting to avoid deep type issues with metadata\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\t\tbody: body as any, // casting to avoid deep type issues with metadata\n\t\t\t\t});\n\t\t\t}\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\treturn paystackClient?.transaction?.chargeAuthorization?.(body as any);\n\t\t},\n\t\tproductList: () => {\n\t\t\tif (paystackClient?.product_list !== undefined) {\n\t\t\t\treturn paystackClient.product_list();\n\t\t\t}\n\t\t\treturn paystackClient?.product?.list?.();\n\t\t},\n\t\tproductFetch: (idOrCode: string) => {\n\t\t\tif (paystackClient?.product_fetch !== undefined) {\n\t\t\t\treturn paystackClient.product_fetch({\n\t\t\t\t\tparams: { path: { id_or_code: idOrCode } },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.product?.fetch?.(idOrCode);\n\t\t},\n\t\tproductCreate: (params: Record<string, unknown>) => {\n\t\t\tif (paystackClient?.product_create !== undefined) {\n\t\t\t\treturn paystackClient.product_create({ body: params });\n\t\t\t}\n\t\t\treturn paystackClient?.product?.create?.(params);\n\t\t},\n\t\tproductUpdate: (idOrCode: string, params: Record<string, unknown>) => {\n\t\t\tif (paystackClient?.product_update !== undefined) {\n\t\t\t\treturn paystackClient.product_update({\n\t\t\t\t\tparams: { path: { id_or_code: idOrCode } },\n\t\t\t\t\tbody: params,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.product?.update?.(idOrCode, params);\n\t\t},\n\t\tproductDelete: (idOrCode: string) => {\n\t\t\tif (paystackClient?.product_delete !== undefined) {\n\t\t\t\treturn paystackClient.product_delete({\n\t\t\t\t\tparams: { path: { id_or_code: idOrCode } },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.product?.delete?.(idOrCode);\n\t\t},\n\t\tplanList: () => {\n\t\t\tif (paystackClient?.plan_list !== undefined) {\n\t\t\t\treturn paystackClient.plan_list();\n\t\t\t}\n\t\t\treturn paystackClient?.plan?.list?.();\n\t\t},\n\t};\n}\n","import type { GenericEndpointContext, PaystackClientLike, PaystackOptions, PaystackProduct } from \"./types\";\nimport { getPaystackOps, unwrapSdkResult } from \"./paystack-sdk\";\n\nexport async function getPlans(subscriptionOptions: PaystackOptions[\"subscription\"]) {\n\tif (subscriptionOptions?.enabled === true) {\n\t\treturn typeof subscriptionOptions.plans === \"function\"\n\t\t\t? subscriptionOptions.plans()\n\t\t\t: subscriptionOptions.plans;\n\t}\n\tthrow new Error(\"Subscriptions are not enabled in the Paystack options.\");\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const getPlan = async (options: PaystackOptions<PaystackClientLike, any, any>, planId: string) => {\n\tif (options.subscription?.enabled === true) {\n\t\tconst plans = await getPlans(options.subscription);\n\t\treturn plans.find((plan) => plan.name === planId) ?? null;\n\t}\n\treturn null;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function getPlanByName(options: PaystackOptions<PaystackClientLike, any, any>, name: string) {\n\tif (options.subscription?.enabled === true) {\n\t\tconst plans = await getPlans(options.subscription);\n\t\treturn plans.find(\n\t\t\t(plan) => plan.name.toLowerCase() === name.toLowerCase(),\n\t\t) ?? null;\n\t}\n\treturn null;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function getPlanByPriceId(options: PaystackOptions<PaystackClientLike, any, any>, priceId: string) {\n\tif (options.subscription?.enabled === true) {\n\t\tconst plans = await getPlans(options.subscription);\n\t\treturn plans.find((plan) => plan.name === priceId) ?? null;\n\t}\n\treturn null;\n}\n\n\nexport async function getProducts(productOptions: PaystackOptions[\"products\"]) {\n\tif (productOptions?.products) {\n\t\treturn typeof productOptions.products === \"function\"\n\t\t\t? await productOptions.products()\n\t\t\t: productOptions.products;\n\t}\n\treturn [];\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function getProductByName(options: PaystackOptions<PaystackClientLike, any, any>, name: string) {\n\treturn await getProducts(options.products).then((products) =>\n\t\tproducts?.find((product) => product.name.toLowerCase() === name.toLowerCase()) ?? null,\n\t);\n}\n\nexport function getNextPeriodEnd(startDate: Date, interval: string): Date {\n\tconst date = new Date(startDate);\n\tswitch (interval) {\n\tcase \"daily\":\n\t\tdate.setDate(date.getDate() + 1);\n\t\tbreak;\n\tcase \"weekly\":\n\t\tdate.setDate(date.getDate() + 7);\n\t\tbreak;\n\tcase \"monthly\":\n\t\tdate.setMonth(date.getMonth() + 1);\n\t\tbreak;\n\tcase \"quarterly\":\n\t\tdate.setMonth(date.getMonth() + 3);\n\t\tbreak;\n\tcase \"biannually\":\n\t\tdate.setMonth(date.getMonth() + 6);\n\t\tbreak;\n\tcase \"annually\":\n\t\tdate.setFullYear(date.getFullYear() + 1);\n\t\tbreak;\n\tdefault:\n\t\t// Default to monthly if unknown\n\t\tdate.setMonth(date.getMonth() + 1);\n\t}\n\treturn date;\n}\n\n/**\n * Validates if the amount meets Paystack's minimum transaction requirements.\n * Amounts should be in the smallest currency unit (e.g., kobo, cents).\n */\nexport function validateMinAmount(amount: number, currency: string): boolean {\n\tconst minAmounts: Record<string, number> = {\n\t\tNGN: 5000, // 50.00\n\t\tGHS: 10, // 0.10\n\t\tZAR: 100, // 1.00\n\t\tKES: 300, // 3.00\n\t\tUSD: 200, // 2.00\n\t\tXOF: 100, // 1.00\n\t};\n\tconst min = minAmounts[currency.toUpperCase()];\n\treturn min !== undefined ? amount >= min : true;\n}\n\nexport async function syncProductQuantityFromPaystack(\n\tctx: GenericEndpointContext,\n\tproductName: string,\n\tpaystackClient: PaystackClientLike,\n): Promise<void> {\n\t// Find the local product record (by name or slug)\n\tlet localProduct = await ctx.context.adapter.findOne<PaystackProduct>({\n\t\tmodel: \"paystackProduct\",\n\t\twhere: [{ field: \"name\", value: productName }],\n\t});\n\n\tlocalProduct ??= await ctx.context.adapter.findOne<PaystackProduct>({\n\t\tmodel: \"paystackProduct\",\n\t\twhere: [{ field: \"slug\", value: productName.toLowerCase().replace(/\\s+/g, \"-\") }],\n\t});\n\n\tif (localProduct?.paystackId === undefined || localProduct?.paystackId === null || localProduct?.paystackId === \"\") {\n\t\t// No local record with a Paystack ID — fall back to local decrement\n\t\tif (localProduct && localProduct.unlimited !== true && localProduct.quantity !== undefined && localProduct.quantity > 0) {\n\t\t\tawait ctx.context.adapter.update({\n\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\tupdate: { quantity: localProduct.quantity - 1, updatedAt: new Date() },\n\t\t\t\twhere: [{ field: \"id\", value: localProduct.id }],\n\t\t\t});\n\t\t}\n\t\treturn;\n\t}\n\n\t// Fetch the latest quantity from Paystack\n\ttry {\n\t\tconst ops = getPaystackOps(paystackClient);\n\t\tconst raw = await ops.productFetch(localProduct.paystackId);\n\t\tconst data = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\tconst remoteQuantity = data?.quantity as number | undefined;\n\n\t\tif (remoteQuantity !== undefined) {\n\t\t\tawait ctx.context.adapter.update({\n\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\tupdate: { quantity: remoteQuantity, updatedAt: new Date() },\n\t\t\t\twhere: [{ field: \"id\", value: localProduct.id }],\n\t\t\t});\n\t\t}\n\t} catch {\n\t\t// If API call fails, fall back to local decrement\n\t\tif (localProduct.unlimited !== true && localProduct.quantity !== undefined && localProduct.quantity > 0) {\n\t\t\tawait ctx.context.adapter.update({\n\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\tupdate: { quantity: localProduct.quantity - 1, updatedAt: new Date() },\n\t\t\t\twhere: [{ field: \"id\", value: localProduct.id }],\n\t\t\t});\n\t\t}\n\t}\n}\n\n/** @deprecated Use syncProductQuantityFromPaystack instead */\nexport async function decrementProductQuantity(ctx: GenericEndpointContext, productName: string) {\n\tlet product = await ctx.context.adapter.findOne<PaystackProduct>({\n\t\tmodel: \"paystackProduct\",\n\t\twhere: [{ field: \"name\", value: productName }],\n\t});\n\n\tproduct ??= await ctx.context.adapter.findOne<PaystackProduct>({\n\t\tmodel: \"paystackProduct\",\n\t\twhere: [{ field: \"slug\", value: productName.toLowerCase().replace(/\\s+/g, \"-\") }],\n\t});\n\n\tif (product) {\n\t\tif (product.unlimited !== true && product.quantity !== undefined && product.quantity > 0) {\n\t\t\tawait ctx.context.adapter.update({\n\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\tupdate: {\n\t\t\t\t\tquantity: product.quantity - 1,\n\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t},\n\t\t\t\twhere: [{ field: \"id\", value: product.id }],\n\t\t\t});\n\t\t}\n\t}\n}\n","import { createAuthMiddleware } from \"@better-auth/core/api\";\nimport { logger } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\n\n\nimport type { PaystackClientLike, PaystackOptions, Session, User } from \"./types\";\n\nexport const referenceMiddleware = (\n\toptions: PaystackOptions<PaystackClientLike>,\n\taction:\n | \"initialize-transaction\"\n | \"verify-transaction\"\n | \"list-subscriptions\"\n | \"list-transactions\"\n | \"disable-subscription\"\n | \"enable-subscription\"\n | \"get-subscription-manage-link\",\n) =>\n\tcreateAuthMiddleware(async (ctx) => {\n\t\tconst session = ctx.context.session as {\n\t\t\tuser: User;\n\t\t\tsession: Session;\n\t\t} | null;\n\n\t\tif (session === null || session === undefined) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t}\n\t\tconst body = (ctx.body ?? {}) as Record<string, unknown>;\n\t\tconst query = (ctx.query ?? {}) as Record<string, unknown>;\n\t\tconst referenceId =\n (body.referenceId as string | undefined) ?? (query.referenceId as string | undefined) ?? session.user.id;\n \n\t\tconst subscriptionOptions = options.subscription;\n\n\n\n\t\tif (referenceId === session.user.id) {\n\t\t\treturn {\n\t\t\t\treferenceId,\n\t\t\t};\n\t\t}\n\n\n \n\t\t// 1. Try custom authorization first if provided\n\t\tif (subscriptionOptions?.enabled === true && 'authorizeReference' in subscriptionOptions && subscriptionOptions.authorizeReference) {\n\t\t\tconst authorized = await subscriptionOptions.authorizeReference(\n\t\t\t\t{\n\t\t\t\t\tuser: session.user,\n\t\t\t\t\tsession: session.session,\n\t\t\t\t\treferenceId,\n\t\t\t\t\taction,\n\t\t\t\t},\n\t\t\t\tctx,\n\t\t\t);\n\t\t\tif (authorized === true) {\n\t\t\t\treturn {\n\t\t\t\t\treferenceId,\n\t\t\t\t};\n\t\t\t}\n\t\t\t// If explicit authorizeReference returns false, do we fail immediately?\n\t\t\t// Usually yes, but maybe we fallback to org check?\n\t\t\t// Let's assume authorizeReference overrides everything.\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t}\n\n\t\t// 2. Fallback: Organization Check\n\t\tif (options.organization?.enabled === true) {\n\t\t\t// Check if referenceId indicates an organization the user is a member of\n\t\t\tconst member = await ctx.context.adapter.findOne<{ id: string }>({\n\t\t\t\tmodel: \"member\",\n\t\t\t\twhere: [\n\t\t\t\t\t{ field: \"userId\", value: session.user.id },\n\t\t\t\t\t{ field: \"organizationId\", value: referenceId }\n\t\t\t\t]\n\t\t\t});\n \n\t\t\tif (member !== null && member !== undefined) {\n\t\t\t\tlogger.debug(\"DEBUG MIDDLEWARE MEMBER FOUND:\", member);\n\t\t\t\t// User is a member of the organization.\n\t\t\t\t// We could check roles here, but for now allow any member.\n\t\t\t\treturn {\n\t\t\t\t\treferenceId,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tlogger.error(\n\t\t\t`Passing referenceId into a subscription action isn't allowed if subscription.authorizeReference isn't defined in your paystack plugin config and matches no organization membership.`,\n\t\t);\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage:\n \"Passing referenceId isn't allowed without subscription.authorizeReference or valid organization membership.\",\n\t\t});\n\t});\n","import { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { defineErrorCodes } from \"@better-auth/core/utils\";\nimport { HIDE_METADATA } from \"better-auth\";\nimport {\n\tAPIError,\n\tgetSessionFromCtx,\n\toriginCheck,\n\tsessionMiddleware,\n} from \"better-auth/api\";\nimport * as z from \"zod/v4\";\nimport type { GenericEndpointContext } from \"better-auth\";\n\nimport type { InputPaystackTransaction, InputPaystackProduct, InputSubscription, PaystackOptions, PaystackTransaction, Subscription, Organization, Member, User, PaystackClientLike, PaystackWebhookPayload } from \"./types\";\nimport {\n\tsyncProductQuantityFromPaystack,\n\tgetPlanByName,\n\tgetPlans,\n\tgetProductByName,\n\tgetProducts,\n\tvalidateMinAmount,\n\tgetNextPeriodEnd,\n} from \"./utils\";\nimport type { PaystackPlan, PaystackProduct } from \"./types\";\nimport { referenceMiddleware } from \"./middleware\";\nimport { getPaystackOps, unwrapSdkResult } from \"./paystack-sdk\";\n\ntype AnyPaystackOptions = PaystackOptions<PaystackClientLike>;\n\nconst PAYSTACK_ERROR_CODES = defineErrorCodes({\n\tSUBSCRIPTION_NOT_FOUND: \"Subscription not found\",\n\tSUBSCRIPTION_PLAN_NOT_FOUND: \"Subscription plan not found\",\n\tUNABLE_TO_CREATE_CUSTOMER: \"Unable to create customer\",\n\tFAILED_TO_INITIALIZE_TRANSACTION: \"Failed to initialize transaction\",\n\tFAILED_TO_VERIFY_TRANSACTION: \"Failed to verify transaction\",\n\tFAILED_TO_DISABLE_SUBSCRIPTION: \"Failed to disable subscription\",\n\tFAILED_TO_ENABLE_SUBSCRIPTION: \"Failed to enable subscription\",\n\tEMAIL_VERIFICATION_REQUIRED:\n\t\t\"Email verification is required before you can subscribe to a plan\",\n});\n\nasync function hmacSha512Hex(secret: string, message: string): Promise<string> {\n\tconst encoder = new TextEncoder();\n\tconst keyData = encoder.encode(secret);\n\tconst msgData = encoder.encode(message);\n\n\tconst crypto = globalThis.crypto;\n\tif (crypto !== undefined && crypto !== null && \"subtle\" in crypto) {\n\t\tconst subtle = crypto.subtle;\n\t\tconst key = await subtle.importKey(\n\t\t\t\"raw\",\n\t\t\tkeyData,\n\t\t\t{ name: \"HMAC\", hash: \"SHA-512\" },\n\t\t\tfalse,\n\t\t\t[\"sign\"],\n\t\t);\n\t\tconst signature = await subtle.sign(\"HMAC\", key, msgData);\n\t\treturn Array.from(new Uint8Array(signature))\n\t\t\t.map((b) => b.toString(16).padStart(2, \"0\"))\n\t\t\t.join(\"\");\n\t}\n\n\tconst { createHmac } = await import(\"node:crypto\");\n\treturn createHmac(\"sha512\", secret).update(message).digest(\"hex\");\n}\n\nexport const paystackWebhook = (options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/webhook\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"handlePaystackWebhook\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tcloneRequest: true,\n\t\t\tdisableBody: true,\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst request = (ctx as GenericEndpointContext & { requestClone?: Request }).requestClone ?? ctx.request;\n\t\t\tif (!request) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Request object is missing from context\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst payload = await request.text();\n\t\t\tconst headers = (ctx as GenericEndpointContext & { headers?: Headers }).headers ?? (ctx.request as unknown as { headers: Headers })?.headers;\n\t\t\tconst signature = headers?.get(\"x-paystack-signature\") as\n\t\t\t\t| string\n\t\t\t\t| null\n\t\t\t\t| undefined;\n\n\t\t\tif (signature === undefined || signature === null || signature === \"\") {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Missing x-paystack-signature header\",\n\t\t\t\t\tstatus: 401,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst expected = await hmacSha512Hex(options.paystackWebhookSecret, payload);\n\t\t\tif (expected !== signature) {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Invalid Paystack webhook signature\",\n\t\t\t\t\tstatus: 401,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst event = JSON.parse(payload) as PaystackWebhookPayload;\n\t\t\tconst eventName = event.event;\n\t\t\tconst data = event.data;\n\n\t\t\t// Core Transaction Status Sync (Applies to both one-time and recurring)\n\t\t\tif (eventName === \"charge.success\") {\n\t\t\t\tconst reference = (data as Record<string, unknown> | undefined)?.reference as string | undefined;\n\t\t\t\tconst paystackId = (data as Record<string, unknown> | undefined)?.id !== undefined && (data as Record<string, unknown> | undefined)?.id !== null ? String((data).id) : undefined;\n\t\t\t\tif (reference !== undefined && reference !== null && reference !== \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\t\t\t\tpaystackId,\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t// Transaction record might not exist yet (e.g. webhook arrives before local record)\n\t\t\t\t\t\tctx.context.logger.warn(\"Failed to update transaction status for charge.success\", e);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Sync product quantity from Paystack after successful charge\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst transaction = await ctx.context.adapter.findOne<PaystackTransaction>({\n\t\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (transaction?.product) {\n\t\t\t\t\t\t\tawait syncProductQuantityFromPaystack(ctx as GenericEndpointContext, transaction.product, options.paystackClient);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tctx.context.logger.warn(\"Failed to sync product quantity\", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (eventName === \"charge.failure\") {\n\t\t\t\tconst reference = (data as Record<string, unknown> | undefined)?.reference as string | undefined;\n\t\t\t\tif (reference !== undefined && reference !== null && reference !== \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tctx.context.logger.warn(\"Failed to update transaction status for charge.failure\", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Best-effort local state sync for subscription lifecycle.\n\t\t\tif (options.subscription?.enabled === true) {\n\t\t\t\ttry {\n\n\t\t\t\t\tif (eventName === \"subscription.create\") {\n\t\t\t\t\t\tconst payloadData = data as any;\n\t\t\t\t\t\tconst subscriptionCode =\n\t\t\t\t\t\t\tpayloadData?.subscription_code ??\n\t\t\t\t\t\t\tpayloadData?.subscription?.subscription_code ??\n\t\t\t\t\t\t\tpayloadData?.code;\n\t\t\t\t\t\tconst customerCode =\n\t\t\t\t\t\t\tpayloadData?.customer?.customer_code ??\n\t\t\t\t\t\t\tpayloadData?.customer_code ??\n\t\t\t\t\t\t\tpayloadData?.customer?.code;\n\t\t\t\t\t\tconst planCode =\n\t\t\t\t\t\t\tpayloadData?.plan?.plan_code ?? payloadData?.plan_code ?? payloadData?.plan;\n\n\t\t\t\t\t\tlet metadata: unknown = payloadData?.metadata;\n\t\t\t\t\t\tif (typeof metadata === \"string\") {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tmetadata = JSON.parse(metadata);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// ignore\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst referenceIdFromMetadata =\n\t\t\t\t\t\t\ttypeof metadata === \"object\" && metadata !== null\n\t\t\t\t\t\t\t\t? ((metadata as Record<string, unknown>).referenceId as string | undefined)\n\t\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\t\tlet planNameFromMetadata =\n\t\t\t\t\t\t\ttypeof metadata === \"object\" && metadata !== null\n\t\t\t\t\t\t\t\t? ((metadata as Record<string, unknown>).plan as string | undefined)\n\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\tif (typeof planNameFromMetadata === \"string\") {\n\t\t\t\t\t\t\tplanNameFromMetadata = planNameFromMetadata.toLowerCase();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst plans = await getPlans(options.subscription);\n\t\t\t\t\t\tconst planFromCode = (planCode !== undefined && planCode !== null && planCode !== \"\")\n\t\t\t\t\t\t\t? plans.find((p) => p.planCode !== undefined && p.planCode !== null && p.planCode === planCode)\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\tconst planPart = planFromCode?.name ?? planNameFromMetadata;\n\t\t\t\t\t\tconst planName = planPart !== undefined && planPart !== null && planPart !== \"\" ? planPart.toLowerCase() : undefined;\n\n\t\t\t\t\t\tif (subscriptionCode !== undefined && subscriptionCode !== null && subscriptionCode !== \"\") {\n\t\t\t\t\t\t\tconst where: { field: string; value: string | number | boolean | null }[] = [];\n\t\t\t\t\t\t\tif (referenceIdFromMetadata !== undefined && referenceIdFromMetadata !== null && referenceIdFromMetadata !== \"\") {\n\t\t\t\t\t\t\t\twhere.push({ field: \"referenceId\", value: referenceIdFromMetadata });\n\t\t\t\t\t\t\t} else if (customerCode !== undefined && customerCode !== null && customerCode !== \"\") {\n\t\t\t\t\t\t\t\twhere.push({ field: \"paystackCustomerCode\", value: customerCode });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (planName !== undefined && planName !== null && planName !== \"\") {\n\t\t\t\t\t\t\t\twhere.push({ field: \"plan\", value: planName });\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (where.length > 0) {\n\t\t\t\t\t\t\t\tconst matches = await ctx.context.adapter.findMany<Subscription>({\n\t\t\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\t\t\twhere: where as { field: string; value: string | number | boolean | null }[],\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tconst subscription = (matches !== undefined && matches !== null) ? matches[0] : undefined;\n\t\t\t\t\t\t\t\tif (subscription !== undefined && subscription !== null) {\n\t\t\t\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\t\t\t\tpaystackSubscriptionCode: subscriptionCode,\n\t\t\t\t\t\t\t\t\t\t\tstatus: \"active\",\n\t\t\t\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t\t\t\t\tperiodEnd: (payloadData?.next_payment_date !== undefined && payloadData?.next_payment_date !== null && payloadData?.next_payment_date !== \"\") ? new Date(payloadData.next_payment_date) : undefined,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: subscription.id }],\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\tconst plan = planFromCode ?? (planName !== undefined && planName !== null && planName !== \"\" ? await getPlanByName(options, planName) : undefined);\n\t\t\t\t\t\t\t\t\tif (plan !== undefined && plan !== null) {\n\t\t\t\t\t\t\t\t\t\tawait options.subscription.onSubscriptionComplete?.(\n\t\t\t\t\t\t\t\t\t\t\t{ event, subscription: { ...subscription, paystackSubscriptionCode: subscriptionCode, status: \"active\" }, plan },\n\t\t\t\t\t\t\t\t\t\t\tctx as GenericEndpointContext,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t// Also call onSubscriptionCreated for subscriptions created outside of checkout\n\t\t\t\t\t\t\t\t\t\tawait options.subscription.onSubscriptionCreated?.(\n\t\t\t\t\t\t\t\t\t\t\t{ event, subscription: { ...subscription, paystackSubscriptionCode: subscriptionCode, status: \"active\" }, plan },\n\t\t\t\t\t\t\t\t\t\t\tctx as GenericEndpointContext,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (eventName === \"subscription.disable\" || eventName === \"subscription.not_renew\") {\n\t\t\t\t\t\tconst payloadData = data as any;\n\t\t\t\t\t\tconst subscriptionCode =\n\t\t\t\t\t\t\tpayloadData?.subscription_code ??\n\t\t\t\t\t\t\tpayloadData?.subscription?.subscription_code ??\n\t\t\t\t\t\t\tpayloadData?.code;\n\t\t\t\t\t\tif (subscriptionCode !== undefined && subscriptionCode !== null && subscriptionCode !== \"\") {\n\t\t\t\t\t\t\t// Find the subscription first to get full data for the hook\n\t\t\t\t\t\t\tconst existing = await ctx.context.adapter.findOne<Subscription>({\n\t\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\t\twhere: [{ field: \"paystackSubscriptionCode\", value: subscriptionCode }],\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tlet newStatus = \"canceled\";\n\t\t\t\t\t\t\tconst nextPaymentDate = (data)?.next_payment_date as string | undefined;\n\t\t\t\t\t\t\tconst periodEnd = nextPaymentDate ? new Date(nextPaymentDate) : (existing?.periodEnd ? new Date(existing.periodEnd) : undefined);\n\n\t\t\t\t\t\t\tif (periodEnd && periodEnd > new Date()) {\n\t\t\t\t\t\t\t\tnewStatus = \"active\";\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\t\tstatus: newStatus,\n\t\t\t\t\t\t\t\t\tcancelAtPeriodEnd: true,\n\t\t\t\t\t\t\t\t\t...(periodEnd ? { periodEnd } : {}),\n\t\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{ field: \"paystackSubscriptionCode\", value: subscriptionCode },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (existing) {\n\t\t\t\t\t\t\t\tawait options.subscription.onSubscriptionCancel?.(\n\t\t\t\t\t\t\t\t\t{ event, subscription: { ...existing, status: \"canceled\" } },\n\t\t\t\t\t\t\t\t\tctx as GenericEndpointContext,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (_e: unknown) {\n\t\t\t\t\tctx.context.logger.error(\"Failed to sync Paystack webhook event\", _e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait options.onEvent?.(event);\n\t\t\treturn ctx.json({ received: true });\n\t\t},\n\t);\n};\n\n\nconst initializeTransactionBodySchema = z.object({\n\tplan: z.string().optional(),\n\tproduct: z.string().optional(),\n\tamount: z.number().int().positive().optional(), // Amount in smallest currency unit (e.g., kobo)\n\tcurrency: z.string().optional(),\n\temail: z.string().optional(),\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n\treferenceId: z.string().optional(),\n\tcallbackURL: z.string().optional(),\n\tquantity: z.number().int().positive().optional(),\n});\n\nexport const initializeTransaction = <P extends string = \"/paystack/initialize-transaction\">(options: AnyPaystackOptions, path: P = \"/paystack/initialize-transaction\" as P) => {\n\tconst subscriptionOptions = options.subscription;\n\t// However, for one-time payments, we might not strictly need subscription middleware\n\t// checking for existing subs, but let's keep it consistent for now.\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"initialize-transaction\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: initializeTransactionBodySchema,\n\t\t\tuse: useMiddlewares,\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\tconst { plan: planName, product: productName, amount: bodyAmount, currency, email, metadata: extraMetadata, callbackURL, quantity } = ctx.body;\n\n\t\t\t// 1. Validate Callback URL validation (same as before)\n\t\t\tif (callbackURL !== undefined && callbackURL !== null && callbackURL !== \"\") {\n\t\t\t\tconst checkTrusted = () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!callbackURL) return false;\n\t\t\t\t\t\tif (callbackURL.startsWith(\"/\")) return true;\n\t\t\t\t\t\tconst baseUrl =\n\t\t\t\t\t\t\t((ctx.context as Record<string, unknown>)?.baseURL as string | undefined) ??\n\t\t\t\t\t\t\t((ctx.request as unknown as { url?: string })?.url) ??\n\t\t\t\t\t\t\t\"\";\n\t\t\t\t\t\tif (!baseUrl) return false;\n\t\t\t\t\t\tconst baseOrigin = new URL(baseUrl).origin;\n\t\t\t\t\t\treturn new URL(callbackURL).origin === baseOrigin;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tif (!checkTrusted()) {\n\t\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\t\tmessage: \"callbackURL is not a trusted origin.\",\n\t\t\t\t\t\tstatus: 403,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 2. Get User & Session\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\t\t\tconst user = session.user;\n\n\t\t\t// 3. Email Verification Check (only if subscription options enforce it)\n\t\t\tif (subscriptionOptions?.enabled === true && subscriptionOptions.requireEmailVerification === true && !user.emailVerified) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tcode: \"EMAIL_VERIFICATION_REQUIRED\",\n\t\t\t\t\tmessage: PAYSTACK_ERROR_CODES.EMAIL_VERIFICATION_REQUIRED,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// 4. Determine Payment Mode: Subscription (Plan) vs Product vs One-Time (Amount)\n\t\t\tlet plan: PaystackPlan | null | undefined;\n\t\t\tlet product: PaystackProduct | InputPaystackProduct | undefined;\n\n\t\t\tif (planName !== undefined && planName !== null && planName !== \"\") {\n\t\t\t\tif (subscriptionOptions?.enabled !== true) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", { message: \"Subscriptions are not enabled.\" });\n\t\t\t\t}\n\t\t\t\tplan = await getPlanByName(options, planName) ?? undefined;\n\t\t\t\tif (!plan) {\n\t\t\t\t\t// Fallback: Check database for synced plans\n\t\t\t\t\tconst nativePlan = await ctx.context.adapter.findOne<PaystackPlan>({\n\t\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t\t\twhere: [{ field: \"name\", value: planName }],\n\t\t\t\t\t});\n\t\t\t\t\tif (nativePlan) {\n\t\t\t\t\t\tplan = nativePlan;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Try checking by planCode as well\n\t\t\t\t\t\tconst nativePlanByCode = await ctx.context.adapter.findOne<PaystackPlan>({\n\t\t\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t\t\t\twhere: [{ field: \"planCode\", value: planName }],\n\t\t\t\t\t\t});\n\t\t\t\t\t\tplan = nativePlanByCode ?? undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!plan) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tcode: \"SUBSCRIPTION_PLAN_NOT_FOUND\",\n\t\t\t\t\t\tmessage: PAYSTACK_ERROR_CODES.SUBSCRIPTION_PLAN_NOT_FOUND,\n\t\t\t\t\t\tstatus: 400\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (productName !== undefined && productName !== null && productName !== \"\") {\n\t\t\t\tif (typeof productName === 'string') {\n\t\t\t\t\tproduct ??= await getProductByName(options, productName) ?? undefined;\n\t\t\t\t\t// Fallback: Check database for synced products\n\t\t\t\t\tproduct ??= await ctx.context.adapter.findOne<PaystackProduct>({\n\t\t\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\t\t\twhere: [{ field: \"name\", value: productName }],\n\t\t\t\t\t}) ?? undefined;\n\t\t\t\t}\n\t\t\t\tif (!product) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: `Product '${productName}' not found.`,\n\t\t\t\t\t\tstatus: 400\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (bodyAmount === undefined || bodyAmount === null || bodyAmount === 0) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Either 'plan', 'product', or 'amount' is required to initialize a transaction.\",\n\t\t\t\t\tstatus: 400\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst amount = bodyAmount ?? product?.price;\n\t\t\tconst finalCurrency = currency ?? product?.currency ?? plan?.currency ?? \"NGN\";\n\n\t\t\tlet url: string | undefined;\n\t\t\tlet reference: string | undefined;\n\t\t\tlet accessCode: string | undefined;\n\n\t\t\t// 5. Prepare Payload\n\n\t\t\tconst referenceIdFromCtx = (ctx.context as Record<string, unknown>).referenceId as string | undefined;\n\t\t\tconst referenceId = (ctx.body.referenceId !== undefined && ctx.body.referenceId !== null && ctx.body.referenceId !== \"\")\n\t\t\t\t? ctx.body.referenceId\n\t\t\t\t: (referenceIdFromCtx !== undefined && referenceIdFromCtx !== null && referenceIdFromCtx !== \"\")\n\t\t\t\t\t? referenceIdFromCtx\n\t\t\t\t\t: (session.user as unknown as { id: string }).id;\n\n\t\t\t// Check trial eligibility - prevent trial abuse\n\t\t\tlet trialStart: Date | undefined;\n\t\t\tlet trialEnd: Date | undefined;\n\t\t\tif (plan?.freeTrial?.days !== undefined && plan.freeTrial.days !== null && plan.freeTrial.days > 0) {\n\t\t\t\t// Check if user/referenceId has ever had a trial\n\t\t\t\tconst previousTrials = await ctx.context.adapter.findMany<Subscription>({\n\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\twhere: [{ field: \"referenceId\", value: referenceId }],\n\t\t\t\t});\n\t\t\t\tconst hadTrial = previousTrials?.some(\n\t\t\t\t\t(sub) => (sub.trialStart !== undefined && sub.trialStart !== null) || (sub.trialEnd !== undefined && sub.trialEnd !== null) || sub.status === \"trialing\"\n\t\t\t\t);\n\n\t\t\t\tif (!hadTrial) {\n\t\t\t\t\ttrialStart = new Date();\n\t\t\t\t\ttrialEnd = new Date();\n\t\t\t\t\ttrialEnd.setDate(trialEnd.getDate() + plan.freeTrial.days);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\t// Determine Customer Email & Code (Organization support)\n\t\t\t\tlet targetEmail = (email !== undefined && email !== null && email !== \"\") ? email : user.email;\n\t\t\t\tlet paystackCustomerCode = (user as unknown as { paystackCustomerCode?: string }).paystackCustomerCode;\n\n\t\t\t\tif (options.organization?.enabled === true && referenceId !== undefined && referenceId !== null && referenceId !== \"\" && referenceId !== user.id) {\n\t\t\t\t\tconst org = await ctx.context.adapter.findOne<Organization>({\n\t\t\t\t\t\tmodel: \"organization\",\n\t\t\t\t\t\twhere: [{ field: \"id\", value: referenceId }],\n\t\t\t\t\t});\n\t\t\t\t\tif (org !== undefined && org !== null) {\n\t\t\t\t\t\t// Prefer organization's existing Paystack customer code\n\t\t\t\t\t\tif (org.paystackCustomerCode !== undefined && org.paystackCustomerCode !== null && org.paystackCustomerCode !== \"\") {\n\t\t\t\t\t\t\tpaystackCustomerCode = org.paystackCustomerCode;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (org.email !== undefined && org.email !== null && org.email !== \"\") {\n\t\t\t\t\t\t\ttargetEmail = org.email;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Fallback: Use Organization Owner Email\n\t\t\t\t\t\t\tconst ownerMember = await ctx.context.adapter.findOne<Member>({\n\t\t\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{ field: \"organizationId\", value: referenceId },\n\t\t\t\t\t\t\t\t\t{ field: \"role\", value: \"owner\" }\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (ownerMember) {\n\t\t\t\t\t\t\t\tconst ownerUser = await ctx.context.adapter.findOne<User>({\n\t\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: ownerMember.userId }]\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tif (ownerUser?.email !== undefined && ownerUser?.email !== null && ownerUser?.email !== \"\") {\n\t\t\t\t\t\t\t\t\ttargetEmail = ownerUser.email;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Construct Metadata\n\t\t\t\tconst metadata = JSON.stringify({\n\t\t\t\t\treferenceId,\n\t\t\t\t\tuserId: user.id,\n\t\t\t\t\tplan: plan?.name.toLowerCase(), // Undefined for one-time\n\t\t\t\t\tproduct: product?.name.toLowerCase(),\n\t\t\t\t\tisTrial: !!trialStart,\n\t\t\t\t\ttrialEnd: trialEnd?.toISOString(),\n\t\t\t\t\t...extraMetadata,\n\t\t\t\t});\n\n\t\t\t\tconst initBody: Record<string, unknown> & { email?: string; amount?: number; plan?: string; invoice_limit?: number } = {\n\t\t\t\t\temail: targetEmail,\n\t\t\t\t\tcallback_url: callbackURL,\n\t\t\t\t\tmetadata,\n\t\t\t\t\t// If plan/product exists, use its currency; otherwise fallback to provided or default\n\t\t\t\t\tcurrency: finalCurrency,\n\t\t\t\t\tquantity,\n\t\t\t\t};\n\n\t\t\t\t// Sync/Update Customer: ensure email matches if code exists\n\t\t\t\tif (paystackCustomerCode !== undefined && paystackCustomerCode !== null && paystackCustomerCode !== \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst ops = getPaystackOps(options.paystackClient);\n\t\t\t\t\t\t// Only update if email is present\n\t\t\t\t\t\tif (initBody.email !== undefined && initBody.email !== null && initBody.email !== \"\") {\n\t\t\t\t\t\t\tawait ops.customerUpdate(paystackCustomerCode, { email: initBody.email });\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (_e: unknown) {\n\t\t\t\t\t\t// Ignore sync errors\n\t\t\t\t\t}\n\t\t\t\t}\n\n\n\t\t\t\tif (plan) {\n\t\t\t\t\t// Subscription Flow\n\t\t\t\t\tif (trialStart) {\n\t\t\t\t\t\t// Trial Flow: Authorize card with minimum amount, don't start sub yet\n\t\t\t\t\t\tinitBody.amount = 5000; // 50 NGN (minimum allowed)\n\t\t\t\t\t\t// Do NOT set initBody.plan\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Standard Flow\n\t\t\t\t\t\tinitBody.plan = plan.planCode;\n\t\t\t\t\t\tinitBody.invoice_limit = plan.invoiceLimit;\n\t\t\t\t\t\t// Paystack requires amount even with planCode (it uses plan's stored amount)\n\t\t\t\t\t\t// For local plans without planCode, use finalAmount; for planCode plans, use plan.amount or minimum\n\t\t\t\t\t\tconst planAmount = amount ?? plan.amount ?? 50000; // 500 NGN minimum fallback\n\t\t\t\t\t\tinitBody.amount = Math.max(Math.round(planAmount), 50000);\n\t\t\t\t\t\tif (quantity !== undefined && quantity !== null && quantity > 0) {\n\t\t\t\t\t\t\tinitBody.amount = initBody.amount * quantity;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// One-Time Payment Flow\n\t\t\t\t\tif (amount === undefined || amount === null || amount === 0) throw new APIError(\"BAD_REQUEST\", { message: \"Amount is required for one-time payments\" });\n\t\t\t\t\tinitBody.amount = Math.round(amount);\n\t\t\t\t}\n\n\t\t\t\tconst initRaw = await paystack.transactionInitialize(initBody as unknown as Parameters<typeof paystack.transactionInitialize>[0]);\n\t\t\t\tconst initRes = unwrapSdkResult<Record<string, unknown>>(initRaw);\n\t\t\t\tlet data =\n\t\t\t\t\t(initRes !== undefined && initRes !== null && typeof initRes === \"object\" && \"status\" in initRes && \"data\" in initRes)\n\t\t\t\t\t\t? (initRes).data\n\t\t\t\t\t\t: (initRes as Record<string, unknown> | undefined)?.data ?? initRes;\n\n\t\t\t\tif (data !== undefined && data !== null && typeof data === \"object\" && \"status\" in data && \"data\" in data) {\n\t\t\t\t\tdata = (data as Record<string, unknown>).data;\n\t\t\t\t}\n\t\t\t\turl = (data as Record<string, unknown>)?.authorization_url as string | undefined;\n\t\t\t\treference = (data as Record<string, unknown>)?.reference as string | undefined;\n\t\t\t\taccessCode = (data as Record<string, unknown>)?.access_code as string | undefined;\n\t\t\t} catch (error: unknown) {\n\t\t\t\t(ctx as unknown as { context: { logger: { error: (msg: string, err: unknown) => void } } }).context.logger.error(\"Failed to initialize Paystack transaction\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tcode: \"FAILED_TO_INITIALIZE_TRANSACTION\",\n\t\t\t\t\tmessage: (error as Error)?.message ?? PAYSTACK_ERROR_CODES.FAILED_TO_INITIALIZE_TRANSACTION,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// 6. Record Transaction & Subscription\n\t\t\tawait ctx.context.adapter.create<InputPaystackTransaction, PaystackTransaction>({\n\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\tdata: {\n\t\t\t\t\treference: reference!,\n\t\t\t\t\treferenceId,\n\t\t\t\t\tuserId: user.id,\n\t\t\t\t\tamount: amount ?? 0,\n\t\t\t\t\tcurrency: plan?.currency ?? currency ?? \"NGN\",\n\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\tplan: plan?.name.toLowerCase(),\n\t\t\t\t\tproduct: product?.name.toLowerCase(),\n\t\t\t\t\tmetadata: (extraMetadata !== undefined && extraMetadata !== null) ? JSON.stringify(extraMetadata) : undefined,\n\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (plan !== undefined && plan !== null) {\n\t\t\t\t// Re-fetch customer code if it wasn't available before (though we didn't force-create it here)\n\t\t\t\t// For now, use what we have (user's or org's)\n\t\t\t\tlet storedCustomerCode = (user as unknown as { paystackCustomerCode?: string }).paystackCustomerCode;\n\t\t\t\tif (options.organization?.enabled === true && referenceId !== user.id) {\n\t\t\t\t\tconst org = await ctx.context.adapter.findOne<Organization>({\n\t\t\t\t\t\tmodel: \"organization\",\n\t\t\t\t\t\twhere: [{ field: \"id\", value: referenceId }],\n\t\t\t\t\t});\n\t\t\t\t\tif (org?.paystackCustomerCode !== undefined && org?.paystackCustomerCode !== null && org.paystackCustomerCode !== \"\") {\n\t\t\t\t\t\tstoredCustomerCode = org.paystackCustomerCode;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst newSubscription = await ctx.context.adapter.create<InputSubscription, Subscription>({\n\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tplan: plan.name.toLowerCase(),\n\t\t\t\t\t\treferenceId,\n\t\t\t\t\t\tpaystackCustomerCode: storedCustomerCode,\n\t\t\t\t\t\tpaystackTransactionReference: reference,\n\t\t\t\t\t\tstatus: (trialStart !== undefined && trialStart !== null) ? \"trialing\" : \"incomplete\",\n\t\t\t\t\t\tseats: quantity,\n\t\t\t\t\t\ttrialStart,\n\t\t\t\t\t\ttrialEnd,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\t// Call trial start hook if trial was granted\n\t\t\t\tif ((trialStart !== undefined && trialStart !== null) && newSubscription !== null && plan.freeTrial?.onTrialStart !== undefined && plan.freeTrial?.onTrialStart !== null) {\n\t\t\t\t\tawait plan.freeTrial.onTrialStart(newSubscription);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ctx.json({\n\t\t\t\turl,\n\t\t\t\treference,\n\t\t\t\taccessCode,\n\t\t\t\tredirect: true,\n\t\t\t});\n\t\t},\n\t);\n};\n\n// Aliases for Client DX Parity\nexport const createSubscription = (options: AnyPaystackOptions) =>\n\tinitializeTransaction(options, \"/paystack/create-subscription\");\nexport const upgradeSubscription = (options: AnyPaystackOptions) =>\n\tinitializeTransaction(options, \"/paystack/upgrade-subscription\");\nexport const restoreSubscription = (options: AnyPaystackOptions) => {\n\t// Alias for enable\n\treturn enablePaystackSubscription(options, \"/paystack/restore-subscription\");\n};\nexport const cancelSubscription = (options: AnyPaystackOptions) => {\n\t// Alias for disable\n\treturn disablePaystackSubscription(options, \"/paystack/cancel-subscription\");\n};\n\n\nexport const verifyTransaction = <P extends string = \"/paystack/verify-transaction\">(options: AnyPaystackOptions, path: P = \"/paystack/verify-transaction\" as P) => {\n\tconst verifyBodySchema = z.object({\n\t\treference: z.string(),\n\t});\n\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"verify-transaction\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: verifyBodySchema,\n\t\t\tuse: useMiddlewares,\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\tlet verifyRes: unknown;\n\t\t\ttry {\n\t\t\t\tconst verifyRaw = await paystack.transactionVerify(ctx.body.reference);\n\t\t\t\tverifyRes = unwrapSdkResult<Record<string, unknown>>(verifyRaw);\n\t\t\t} catch (error: unknown) {\n\t\t\t\tctx.context.logger.error(\"Failed to verify Paystack transaction\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tcode: \"FAILED_TO_VERIFY_TRANSACTION\",\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t(error as Error)?.message ?? PAYSTACK_ERROR_CODES.FAILED_TO_VERIFY_TRANSACTION,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst data = unwrapSdkResult<Record<string, unknown>>(verifyRes);\n\t\t\tconst status = (data)?.status as string | undefined;\n\t\t\tconst reference = ((data)?.reference as string | undefined) ?? ctx.body.reference;\n\t\t\tconst paystackId = (data)?.id !== undefined && (data)?.id !== null ? String((data as { id: string | number }).id) : undefined;\n\t\t\tconst authorizationCode = ((data)?.authorization as Record<string, unknown>)?.authorization_code as string | undefined;\n\n\t\t\tif (status === \"success\") {\n\t\t\t\tconst session = await getSessionFromCtx(ctx);\n\n\t\t\t\t// Get the local transaction record to know the intended referenceId (Org or User)\n\t\t\t\tconst txRecord = await ctx.context.adapter.findOne<Record<string, unknown> & { referenceId?: string }>({\n\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t});\n\n\t\t\t\t// Trust the referenceId from the record, fallback to session user if missing\n\t\t\t\tconst referenceId = txRecord?.referenceId ?? (session?.user as unknown as { id: string })?.id;\n\n\t\t\t\t// Authorization check: ensure the current user has access to this referenceId\n\t\t\t\tif (session !== null && session !== undefined && referenceId !== session.user.id) {\n\t\t\t\t\tconst authRef = (subscriptionOptions as unknown as { authorizeReference: (data: unknown, ctx: unknown) => Promise<boolean> })?.authorizeReference;\n\t\t\t\t\tlet authorized = false;\n\t\t\t\t\tif (authRef !== undefined && authRef !== null) {\n\t\t\t\t\t\tauthorized = await authRef({\n\t\t\t\t\t\t\tuser: session.user,\n\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\treferenceId,\n\t\t\t\t\t\t\taction: \"verify-transaction\"\n\t\t\t\t\t\t}, ctx);\n\t\t\t\t\t} else if (options.organization?.enabled === true) {\n\t\t\t\t\t\tconst member = await ctx.context.adapter.findOne({\n\t\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"userId\", value: session.user.id },\n\t\t\t\t\t\t\t\t{ field: \"organizationId\", value: referenceId }\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (member !== null && member !== undefined) authorized = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!authorized) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ttry {\n\n\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\t\t\tpaystackId,\n\t\t\t\t\t\t\t// Update with actual amount/currency from Paystack (for planCode subscriptions)\n\t\t\t\t\t\t\t...((data)?.amount !== undefined && (data)?.amount !== null ? { amount: (data).amount } : {}),\n\t\t\t\t\t\t\t...((data)?.currency !== undefined && (data)?.currency !== null ? { currency: (data).currency } : {}),\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t});\n\n\t\t\t\t\tconst customer = (data)?.customer;\n\t\t\t\t\tconst paystackCustomerCodeFromPaystack = (customer !== undefined && customer !== null && typeof customer === \"object\")\n\t\t\t\t\t\t? (customer as Record<string, unknown>).customer_code as string | undefined\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tif (paystackCustomerCodeFromPaystack !== undefined && paystackCustomerCodeFromPaystack !== null && paystackCustomerCodeFromPaystack !== \"\" && referenceId !== undefined && referenceId !== null && referenceId !== \"\") {\n\t\t\t\t\t\tconst isOrg = options.organization?.enabled === true && ((referenceId.startsWith(\"org_\")) || (await ctx.context.adapter.findOne({ model: \"organization\", where: [{ field: \"id\", value: referenceId }] }) !== null));\n\n\t\t\t\t\t\tif (isOrg === true) {\n\t\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\t\tmodel: \"organization\",\n\t\t\t\t\t\t\t\tupdate: { paystackCustomerCode: paystackCustomerCodeFromPaystack },\n\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: referenceId }],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\tupdate: { paystackCustomerCode: paystackCustomerCodeFromPaystack },\n\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: referenceId }],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Decrement product quantity if applicable\n\t\t\t\t\tconst transaction = await ctx.context.adapter.findOne<PaystackTransaction>({\n\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t});\n\t\t\t\t\tif (transaction?.product) {\n\t\t\t\t\t\tawait syncProductQuantityFromPaystack(ctx as GenericEndpointContext, transaction.product, options.paystackClient);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check for trial activation\n\t\t\t\t\tlet isTrial = false;\n\t\t\t\t\tlet trialEnd: string | undefined;\n\t\t\t\t\tlet targetPlan: string | undefined;\n\n\t\t\t\t\tif ((data)?.metadata !== undefined && (data)?.metadata !== null) {\n\t\t\t\t\t\tconst metaRaw = (data).metadata;\n\t\t\t\t\t\tconst meta = typeof metaRaw === \"string\" ? JSON.parse(metaRaw) : metaRaw as Record<string, unknown>;\n\t\t\t\t\t\tisTrial = meta.isTrial === true || meta.isTrial === \"true\";\n\n\t\t\t\t\t\ttrialEnd = meta.trialEnd as string | undefined;\n\n\t\t\t\t\t\ttargetPlan = meta.plan as string | undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet paystackSubscriptionCode: string | undefined;\n\n\t\t\t\t\tif (isTrial === true && (targetPlan !== undefined && targetPlan !== null && targetPlan !== \"\") && (trialEnd !== undefined && trialEnd !== null && trialEnd !== \"\")) {\n\t\t\t\t\t\t// Trial Flow: Create subscription with future start date using auth code\n\t\t\t\t\t\tconst email = ((data)?.customer as Record<string, unknown>)?.email as string | undefined;\n\n\t\t\t\t\t\t// We need the planCode. We have the plan NAME in metadata (lowercased).\n\t\t\t\t\t\tconst plans = await getPlans(subscriptionOptions);\n\t\t\t\t\t\tconst planConfig = plans.find(p => p.name.toLowerCase() === targetPlan?.toLowerCase());\n\n\t\t\t\t\t\t// For local plans (no planCode), generate a local subscription code\n\t\t\t\t\t\tif (planConfig !== undefined && (planConfig.planCode === undefined || planConfig.planCode === null || planConfig.planCode === \"\")) {\n\t\t\t\t\t\t\tpaystackSubscriptionCode = `LOC_${reference}`;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ((authorizationCode !== undefined && authorizationCode !== null && authorizationCode !== \"\") && (email !== undefined && email !== null && email !== \"\") && (planConfig?.planCode !== undefined && planConfig?.planCode !== null && planConfig?.planCode !== \"\")) {\n\t\t\t\t\t\t\tconst subRes = await paystack.subscriptionCreate({\n\t\t\t\t\t\t\t\tcustomer: email,\n\t\t\t\t\t\t\t\tplan: planConfig.planCode,\n\t\t\t\t\t\t\t\tauthorization: authorizationCode,\n\t\t\t\t\t\t\t\tstart_date: trialEnd\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst subData = unwrapSdkResult<Record<string, unknown>>(subRes);\n\t\t\t\t\t\t\tconst cleanSubData = (subData as { data?: Record<string, unknown> })?.data ?? subData;\n\n\t\t\t\t\t\t\tpaystackSubscriptionCode = (cleanSubData)?.subscription_code as string | undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (isTrial !== true) {\n\t\t\t\t\t\tconst planFromPaystack = (data)?.plan as Record<string, unknown> | undefined;\n\t\t\t\t\t\tconst planCodeFromPaystack = planFromPaystack?.plan_code as string | undefined;\n\n\t\t\t\t\t\tif (planCodeFromPaystack === undefined || planCodeFromPaystack === null || planCodeFromPaystack === \"\") {\n\t\t\t\t\t\t\t// Local Plan\n\t\t\t\t\t\t\tpaystackSubscriptionCode = `LOC_${reference}`;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Native Paystack subscription (if created during charge)\n\t\t\t\t\t\t\tpaystackSubscriptionCode = ((data)?.subscription as Record<string, unknown> | undefined)?.subscription_code as string | undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\n\t\t\t\t\tconst existingSubs = await ctx.context.adapter.findMany<Subscription>({\n\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\twhere: [{ field: \"paystackTransactionReference\", value: reference }],\n\t\t\t\t\t});\n\t\t\t\t\tlet targetSub: Subscription | undefined;\n\t\t\t\t\tif (existingSubs && existingSubs.length > 0) {\n\t\t\t\t\t\ttargetSub = existingSubs.find(s =>\n\t\t\t\t\t\t\t!(referenceId !== undefined && referenceId !== null && referenceId !== \"\") || s.referenceId === referenceId\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tlet updatedSubscription: Subscription | null = null;\n\t\t\t\t\tif (targetSub !== undefined && targetSub !== null) {\n\t\t\t\t\t\tupdatedSubscription = await ctx.context.adapter.update<Subscription>({\n\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tstatus: isTrial === true ? \"trialing\" : \"active\",\n\t\t\t\t\t\t\t\tperiodStart: new Date(),\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t\t...(isTrial === true && (trialEnd !== undefined && trialEnd !== null && trialEnd !== \"\") ? {\n\t\t\t\t\t\t\t\t\ttrialStart: new Date(),\n\t\t\t\t\t\t\t\t\ttrialEnd: new Date(trialEnd),\n\t\t\t\t\t\t\t\t\tperiodEnd: new Date(trialEnd),\n\t\t\t\t\t\t\t\t} : {}),\n\t\t\t\t\t\t\t\t...(paystackSubscriptionCode !== undefined && paystackSubscriptionCode !== null && paystackSubscriptionCode !== \"\" ? { paystackSubscriptionCode } : {}),\n\t\t\t\t\t\t\t\t...(authorizationCode !== undefined && authorizationCode !== null && authorizationCode !== \"\" ? { paystackAuthorizationCode: authorizationCode } : {}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\twhere: [{ field: \"id\", value: targetSub.id }],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (updatedSubscription && subscriptionOptions?.enabled === true && \"onSubscriptionComplete\" in subscriptionOptions && typeof (subscriptionOptions as unknown as Record<string, unknown>).onSubscriptionComplete === \"function\") {\n\t\t\t\t\t\tconst subOpts = subscriptionOptions;\n\t\t\t\t\t\tconst plans = await getPlans(subOpts);\n\t\t\t\t\t\tconst plan = plans.find(p => p.name.toLowerCase() === updatedSubscription.plan.toLowerCase());\n\t\t\t\t\t\tif (plan) {\n\t\t\t\t\t\t\tawait (subscriptionOptions as unknown as { onSubscriptionComplete: (data: unknown, ctx: unknown) => Promise<void> }).onSubscriptionComplete({\n\t\t\t\t\t\t\t\tevent: data,\n\t\t\t\t\t\t\t\tsubscription: updatedSubscription,\n\t\t\t\t\t\t\t\tplan\n\t\t\t\t\t\t\t}, ctx);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (e: unknown) {\n\t\t\t\t\tctx.context.logger.error(\n\t\t\t\t\t\t\"Failed to update transaction/subscription after verification\",\n\t\t\t\t\t\te,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (status === \"failed\" || status === \"abandoned\") {\n\t\t\t\ttry {\n\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tstatus,\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t});\n\t\t\t\t} catch (e: unknown) {\n\t\t\t\t\tctx.context.logger.error(\"Failed to update transaction status\", e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ctx.json({\n\t\t\t\tstatus,\n\t\t\t\treference,\n\t\t\t\tdata,\n\t\t\t});\n\t\t},\n\t);\n};\n\nexport const listSubscriptions = (options: AnyPaystackOptions) => {\n\tconst listQuerySchema = z.object({\n\t\treferenceId: z.string().optional(),\n\t});\n\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"list-subscriptions\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\t\"/paystack/list-subscriptions\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: listQuerySchema,\n\t\t\tuse: useMiddlewares,\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tif (subscriptionOptions?.enabled !== true) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Subscriptions are not enabled in the Paystack options.\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\t\t\tconst referenceIdPart = (ctx.context as Record<string, unknown>).referenceId as string | undefined;\n\t\t\tconst queryRefId = ctx.query?.referenceId;\n\t\t\tconst referenceId = (referenceIdPart !== undefined && referenceIdPart !== null && referenceIdPart !== \"\")\n\t\t\t\t? referenceIdPart\n\t\t\t\t: (queryRefId !== undefined && queryRefId !== null && queryRefId !== \"\")\n\t\t\t\t\t? queryRefId\n\t\t\t\t\t: (session.user as unknown as { id: string }).id;\n\t\t\tconst res = await ctx.context.adapter.findMany<Subscription>({\n\t\t\t\tmodel: \"subscription\",\n\t\t\t\twhere: [{ field: \"referenceId\", value: referenceId }],\n\t\t\t});\n\t\t\treturn ctx.json({ subscriptions: res });\n\t\t},\n\t);\n};\n\nexport const listTransactions = <P extends string = \"/paystack/list-transactions\">(options: AnyPaystackOptions, path: P = \"/paystack/list-transactions\" as P) => {\n\tconst listQuerySchema = z.object({\n\t\treferenceId: z.string().optional(),\n\t});\n\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"list-transactions\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: listQuerySchema,\n\t\t\tuse: useMiddlewares,\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\t\t\tconst referenceId =\n\t\t\t\t((ctx.context as Record<string, unknown>).referenceId as string | undefined) ??\n\t\t\t\t(ctx.query?.referenceId) ??\n\t\t\t\t((session.user as unknown as { id: string }).id);\n\t\t\tconst res = await ctx.context.adapter.findMany<PaystackTransaction>({\n\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\twhere: [{ field: \"referenceId\", value: referenceId }],\n\t\t\t});\n\t\t\t// Sort by createdAt desc locally if adapter doesn't support it well, \n\t\t\t// but Better Auth adapters usually return in insertion order.\n\t\t\t// Let's sort to be sure.\n\t\t\tconst sorted = res.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n\t\t\treturn ctx.json({ transactions: sorted });\n\t\t},\n\t);\n};\n\nconst enableDisableBodySchema = z.object({\n\treferenceId: z.string().optional(),\n\tsubscriptionCode: z.string(),\n\temailToken: z.string().optional(),\n});\n\nfunction decodeBase64UrlToString(value: string): string {\n\tconst normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n\tconst padded = normalized + \"===\".slice((normalized.length + 3) % 4);\n\tif (typeof (globalThis as unknown as { atob: unknown }).atob === \"function\") {\n\t\treturn ((globalThis as unknown as { atob: (v: string) => string }).atob)(padded);\n\t}\n\t// eslint-disable-next-line no-restricted-globals\n\treturn Buffer.from(padded, \"base64\").toString(\"utf8\");\n}\n\nfunction tryGetEmailTokenFromSubscriptionManageLink(link: string): string | undefined {\n\ttry {\n\t\tconst url = new URL(link);\n\t\tconst subscriptionToken = url.searchParams.get(\"subscription_token\");\n\t\tif (subscriptionToken === undefined || subscriptionToken === null || subscriptionToken === \"\") return undefined;\n\t\tconst parts = subscriptionToken.split(\".\");\n\t\tif (parts.length < 2) return undefined;\n\t\tconst payloadJson = decodeBase64UrlToString(parts[1]);\n\t\tconst payload = JSON.parse(payloadJson);\n\t\treturn typeof payload?.email_token === \"string\" ? payload.email_token : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport const disablePaystackSubscription = <P extends string = \"/paystack/disable-subscription\">(options: AnyPaystackOptions, path: P = \"/paystack/disable-subscription\" as P) => {\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"disable-subscription\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{ method: \"POST\", body: enableDisableBodySchema, use: useMiddlewares },\n\t\tasync (ctx) => {\n\t\t\tconst { subscriptionCode } = ctx.body;\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\ttry {\n\t\t\t\tif (subscriptionCode.startsWith(\"LOC_\")) {\n\t\t\t\t\tconst sub = await ctx.context.adapter.findOne<Subscription>({\n\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\twhere: [{ field: \"paystackSubscriptionCode\", value: subscriptionCode }],\n\t\t\t\t\t});\n\n\t\t\t\t\tif (sub) {\n\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tstatus: \"active\",\n\t\t\t\t\t\t\t\tcancelAtPeriodEnd: true,\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\twhere: [{ field: \"id\", value: sub.id }],\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn ctx.json({ status: \"success\" });\n\t\t\t\t\t}\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", { message: \"Subscription not found\" });\n\t\t\t\t}\n\n\t\t\t\tlet emailToken = ctx.body.emailToken;\n\t\t\t\tlet nextPaymentDate: string | undefined;\n\n\t\t\t\t// Always fetch subscription to get next_payment_date even if we have emailToken (unless passed? no, next_payment_date comes from paystack)\n\t\t\t\t// We need next_payment_date for cancelAtPeriodEnd logic\n\t\t\t\ttry {\n\t\t\t\t\tconst raw = await paystack.subscriptionFetch(subscriptionCode);\n\t\t\t\t\tconst fetchRes = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t\tconst data =\n\t\t\t\t\t\tfetchRes !== null && fetchRes !== undefined && typeof fetchRes === \"object\" && \"status\" in fetchRes && \"data\" in fetchRes\n\t\t\t\t\t\t\t? (fetchRes).data\n\t\t\t\t\t\t\t: fetchRes?.data !== undefined ? fetchRes.data : fetchRes;\n\n\t\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\t\temailToken = (data as Record<string, unknown>)?.email_token as string | undefined;\n\t\t\t\t\t}\n\t\t\t\t\tnextPaymentDate = (data as Record<string, unknown>)?.next_payment_date as string | undefined;\n\t\t\t\t} catch {\n\t\t\t\t\t// ignore fetch failure? If we can't fetch, we might miss next_payment_date.\n\t\t\t\t}\n\n\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst raw = await paystack.subscriptionManageLink(subscriptionCode);\n\t\t\t\t\t\tconst linkRes = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t\t\tconst data =\n\t\t\t\t\t\t\tlinkRes !== null && linkRes !== undefined && typeof linkRes === \"object\" && \"status\" in linkRes && \"data\" in linkRes\n\t\t\t\t\t\t\t\t? (linkRes).data\n\t\t\t\t\t\t\t\t: linkRes?.data !== undefined ? linkRes.data : linkRes;\n\t\t\t\t\t\tconst link = typeof data === \"string\" ? data : (data as Record<string, unknown>)?.link as string | undefined;\n\n\t\t\t\t\t\tif (link !== undefined && link !== null && link !== \"\") {\n\t\t\t\t\t\t\temailToken = tryGetEmailTokenFromSubscriptionManageLink(link);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\tthrow new Error(\"Could not retrieve email_token for subscription disable.\");\n\t\t\t\t}\n\n\t\t\t\tawait paystack.subscriptionDisable({ code: subscriptionCode, token: emailToken });\n\n\t\t\t\t// Implement Cancel at Period End logic\n\t\t\t\t// Paystack \"disable\" stops future charges.\n\t\t\t\t// We keep status as \"active\" but set cancelAtPeriodEnd = true\n\n\t\t\t\t// Duplicate removed\n\n\t\t\t\tconst periodEnd = (nextPaymentDate !== undefined && nextPaymentDate !== null && nextPaymentDate !== \"\") ? new Date(nextPaymentDate) : undefined;\n\n\t\t\t\tconst sub = await ctx.context.adapter.findOne<Subscription>({\n\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\twhere: [{ field: \"paystackSubscriptionCode\", value: subscriptionCode }],\n\t\t\t\t});\n\n\t\t\t\tif (sub) {\n\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tstatus: \"active\", // Keep active until period end\n\t\t\t\t\t\t\tcancelAtPeriodEnd: true,\n\t\t\t\t\t\t\tperiodEnd,\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\twhere: [{ field: \"id\", value: sub.id }],\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t// This is unexpected if we are disabling a subscription that should exist\n\t\t\t\t\tctx.context.logger.warn(`Could not find subscription with code ${subscriptionCode} to disable`);\n\t\t\t\t}\n\n\t\t\t\treturn ctx.json({ status: \"success\" });\n\t\t\t} catch (error: unknown) {\n\t\t\t\t(ctx as unknown as { context: { logger: { error: (msg: string, err: unknown) => void } } }).context.logger.error(\"Failed to disable subscription\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tcode: \"FAILED_TO_DISABLE_SUBSCRIPTION\",\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t(error as Error)?.message ?? PAYSTACK_ERROR_CODES.FAILED_TO_DISABLE_SUBSCRIPTION,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n};\n\nexport const enablePaystackSubscription = <P extends string = \"/paystack/enable-subscription\">(options: AnyPaystackOptions, path: P = \"/paystack/enable-subscription\" as P) => {\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"enable-subscription\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{ method: \"POST\", body: enableDisableBodySchema, use: useMiddlewares },\n\t\tasync (ctx) => {\n\t\t\tconst { subscriptionCode } = ctx.body;\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\ttry {\n\t\t\t\tlet emailToken = ctx.body.emailToken;\n\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst raw = await paystack.subscriptionFetch(subscriptionCode);\n\t\t\t\t\t\tconst fetchRes = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t\t\tconst data =\n\t\t\t\t\t\t\tfetchRes !== null && fetchRes !== undefined && typeof fetchRes === \"object\" && \"status\" in fetchRes && \"data\" in fetchRes\n\t\t\t\t\t\t\t\t? (fetchRes).data\n\t\t\t\t\t\t\t\t: fetchRes?.data !== undefined ? fetchRes.data : fetchRes;\n\t\t\t\t\t\temailToken = (data as Record<string, unknown>)?.email_token as string | undefined;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore; try manage-link fallback below\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst raw = await paystack.subscriptionManageLink(subscriptionCode);\n\t\t\t\t\t\tconst linkRes = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t\t\tconst data =\n\t\t\t\t\t\t\tlinkRes !== null && linkRes !== undefined && \"status\" in linkRes && \"data\" in linkRes\n\t\t\t\t\t\t\t\t? (linkRes).data\n\t\t\t\t\t\t\t\t: linkRes?.data !== undefined ? linkRes.data : linkRes;\n\t\t\t\t\t\tconst link = typeof data === \"string\" ? data : (data as Record<string, unknown>)?.link as string | undefined;\n\n\t\t\t\t\t\tif (link !== undefined && link !== null && link !== \"\") {\n\t\t\t\t\t\t\temailToken = tryGetEmailTokenFromSubscriptionManageLink(link);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", { message: \"Could not retrieve email_token for subscription enable.\" });\n\t\t\t\t}\n\n\t\t\t\tawait paystack.subscriptionEnable({ code: subscriptionCode, token: emailToken });\n\n\t\t\t\t// Update local status immediately\n\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tstatus: \"active\",\n\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t},\n\t\t\t\t\twhere: [{ field: \"paystackSubscriptionCode\", value: subscriptionCode }],\n\t\t\t\t});\n\n\t\t\t\treturn ctx.json({ status: \"success\" });\n\t\t\t} catch (error: unknown) {\n\t\t\t\tctx.context.logger.error(\"Failed to enable subscription\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tcode: \"FAILED_TO_ENABLE_SUBSCRIPTION\",\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t(error as Error)?.message ?? PAYSTACK_ERROR_CODES.FAILED_TO_ENABLE_SUBSCRIPTION,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n};\n\nexport const getSubscriptionManageLink = <P extends string = \"/paystack/get-subscription-manage-link\">(options: AnyPaystackOptions, path: P = \"/paystack/get-subscription-manage-link\" as P) => {\n\tconst manageLinkQuerySchema = z.object({\n\t\tsubscriptionCode: z.string(),\n\t});\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"get-subscription-manage-link\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\tconst handler = async (ctx: GenericEndpointContext) => {\n\t\tconst { subscriptionCode } = ctx.query;\n\n\t\t// If it's a local mock subscription, return null link instead of error\n\t\tif (subscriptionCode.startsWith(\"LOC_\") || subscriptionCode.startsWith(\"sub_local_\")) {\n\t\t\treturn ctx.json({ link: null, message: \"Local subscriptions cannot be managed on Paystack\" });\n\t\t}\n\n\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\ttry {\n\t\t\tconst raw = await paystack.subscriptionManageLink(subscriptionCode);\n\t\t\tconst res = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\tconst data =\n\t\t\t\t(res !== null && res !== undefined && typeof res === \"object\" && \"status\" in res && \"data\" in res)\n\t\t\t\t\t? (res).data\n\t\t\t\t\t: res?.data !== undefined ? res.data : res;\n\n\t\t\tconst link = typeof data === \"string\" ? data : (data as Record<string, unknown>)?.link as string | undefined;\n\n\t\t\treturn ctx.json({ link });\n\t\t} catch (error: unknown) {\n\t\t\tctx.context.logger.error(\"Failed to get subscription manage link\", error);\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: (error as Error)?.message ?? \"Failed to get subscription manage link\",\n\t\t\t});\n\t\t}\n\t};\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: manageLinkQuerySchema,\n\t\t\tuse: useMiddlewares,\n\t\t},\n\t\thandler,\n\t);\n};\n\nexport const syncProducts = (options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/sync-products\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t},\n\t\t\tdisableBody: true,\n\t\t\tuse: [sessionMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconsole.error(\"DEBUG: syncProducts endpoint hit!\");\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\ttry {\n\t\t\t\tconst raw = await paystack.productList();\n\t\t\t\tconst res = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\tconst productsData = (res !== null && typeof res === \"object\" && \"status\" in res && \"data\" in res) ? (res as Record<string, any>).data : (res as Record<string, any>)?.data ?? res;\n\n\t\t\t\tif (!Array.isArray(productsData)) {\n\t\t\t\t\treturn ctx.json({ status: \"success\", count: 0 });\n\t\t\t\t}\n\n\t\t\t\tfor (const product of productsData) {\n\t\t\t\t\tconst paystackId = String(product.id);\n\t\t\t\t\tconst existing = await ctx.context.adapter.findOne<PaystackProduct>({\n\t\t\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\t\t\twhere: [{ field: \"paystackId\", value: paystackId }],\n\t\t\t\t\t});\n\n\t\t\t\t\tconst productData = {\n\t\t\t\t\t\tname: product.name,\n\t\t\t\t\t\tdescription: product.description,\n\t\t\t\t\t\tprice: product.price,\n\t\t\t\t\t\tcurrency: product.currency,\n\t\t\t\t\t\tquantity: product.quantity,\n\t\t\t\t\t\tunlimited: product.unlimited,\n\t\t\t\t\t\tpaystackId,\n\t\t\t\t\t\tslug: product.slug ?? product.name.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t\t\t\tmetadata: product.metadata ? JSON.stringify(product.metadata) : undefined,\n\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t};\n\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\t\t\t\tupdate: productData,\n\t\t\t\t\t\t\twhere: [{ field: \"id\", value: existing.id }],\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t...productData,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ctx.json({ status: \"success\", count: productsData.length });\n\t\t\t} catch (error: unknown) {\n\t\t\t\tctx.context.logger.error(\"Failed to sync products\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: (error as Error)?.message ?? \"Failed to sync products\",\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n};\n\nexport const listProducts = (_options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/list-products\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"listPaystackProducts\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst res = await ctx.context.adapter.findMany<PaystackProduct>({\n\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t});\n\t\t\tconst sorted = res.sort((a, b) => a.name.localeCompare(b.name));\n\t\t\treturn ctx.json({ products: sorted });\n\t\t}\n\t);\n};\n\nexport const syncPlans = (options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/sync-plans\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t},\n\t\t\tdisableBody: true,\n\t\t\tuse: [sessionMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\ttry {\n\t\t\t\tconst raw = await paystack.planList();\n\t\t\t\tconst res = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\tconst plansData = (res !== null && typeof res === \"object\" && \"status\" in res && \"data\" in res) ? (res as Record<string, any>).data : (res as Record<string, any>)?.data ?? res;\n\n\t\t\t\tif (!Array.isArray(plansData)) {\n\t\t\t\t\treturn ctx.json({ status: \"success\", count: 0 });\n\t\t\t\t}\n\n\t\t\t\tfor (const plan of plansData) {\n\t\t\t\t\tconst paystackId = String(plan.id);\n\t\t\t\t\tconst existing = await ctx.context.adapter.findOne<any>({\n\t\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t\t\twhere: [{ field: \"paystackId\", value: paystackId }],\n\t\t\t\t\t});\n\n\t\t\t\t\tconst planData = {\n\t\t\t\t\t\tname: plan.name,\n\t\t\t\t\t\tdescription: plan.description,\n\t\t\t\t\t\tamount: plan.amount,\n\t\t\t\t\t\tcurrency: plan.currency,\n\t\t\t\t\t\tinterval: plan.interval,\n\t\t\t\t\t\tplanCode: plan.plan_code,\n\t\t\t\t\t\tpaystackId,\n\t\t\t\t\t\tmetadata: plan.metadata ? JSON.stringify(plan.metadata) : undefined,\n\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t};\n\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t\t\t\tupdate: planData,\n\t\t\t\t\t\t\twhere: [{ field: \"id\", value: existing.id }],\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait ctx.context.adapter.create({\n\t\t\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t...planData,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ctx.json({ status: \"success\", count: plansData.length });\n\t\t\t} catch (error: unknown) {\n\t\t\t\tctx.context.logger.error(\"Failed to sync plans\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: (error as Error)?.message ?? \"Failed to sync plans\",\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n};\n\nexport const listPlans = (_options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/list-plans\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t},\n\t\t\tuse: [sessionMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\ttry {\n\t\t\t\tconst plans = await ctx.context.adapter.findMany<any>({\n\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t});\n\t\t\t\treturn ctx.json({ plans });\n\t\t\t} catch (error: unknown) {\n\t\t\t\tctx.context.logger.error(\"Failed to list plans\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: (error as Error)?.message ?? \"Failed to list plans\",\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n};\n\nexport const getConfig = (options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/get-config\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"getPaystackConfig\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst plans = options.subscription?.enabled === true\n\t\t\t\t? await getPlans(options.subscription)\n\t\t\t\t: [];\n\t\t\tconst products = await getProducts(options.products);\n\t\t\treturn ctx.json({\n\t\t\t\tplans,\n\t\t\t\tproducts,\n\t\t\t});\n\t\t}\n\t);\n};\n\nexport { PAYSTACK_ERROR_CODES };\nexport const chargeRecurringSubscription = (options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/charge-recurring\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: z.object({\n\t\t\t\tsubscriptionId: z.string(),\n\t\t\t\tamount: z.number().optional(),\n\t\t\t}),\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst { subscriptionId, amount: bodyAmount } = ctx.body;\n\t\t\tconst subscription = await ctx.context.adapter.findOne<Subscription>({\n\t\t\t\tmodel: \"subscription\",\n\t\t\t\twhere: [{ field: \"id\", value: subscriptionId }],\n\t\t\t});\n\n\t\t\tif (subscription === null || subscription === undefined) {\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", { message: \"Subscription not found\" });\n\t\t\t}\n\n\t\t\tif (subscription.paystackAuthorizationCode === undefined || subscription.paystackAuthorizationCode === null || subscription.paystackAuthorizationCode === \"\") {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", { message: \"No authorization code found for this subscription\" });\n\t\t\t}\n\n\t\t\tconst plans = await getPlans(options.subscription);\n\t\t\tconst plan = plans.find((p) => p.name.toLowerCase() === subscription.plan.toLowerCase());\n\n\t\t\tif (plan === undefined || plan === null) {\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", { message: \"Plan not found\" });\n\t\t\t}\n\n\t\t\tconst amount = bodyAmount ?? plan.amount;\n\t\t\tif (amount === undefined || amount === null) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", { message: \"Plan amount is not defined\" });\n\t\t\t}\n\n\t\t\tlet email: string | null | undefined;\n\t\t\tif (subscription.referenceId !== undefined && subscription.referenceId !== null && subscription.referenceId !== \"\") {\n\t\t\t\t// Try to find user or org\n\t\t\t\tconst user = await ctx.context.adapter.findOne<User>({\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\twhere: [{ field: \"id\", value: subscription.referenceId }],\n\t\t\t\t});\n\t\t\t\tif (user !== undefined && user !== null) {\n\t\t\t\t\temail = user.email;\n\t\t\t\t} else if (options.organization?.enabled === true) {\n\t\t\t\t\t// Check org owner email if referenceId is organizationId\n\t\t\t\t\tconst ownerMember = await ctx.context.adapter.findOne<Member>({\n\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"organizationId\", value: subscription.referenceId },\n\t\t\t\t\t\t\t{ field: \"role\", value: \"owner\" },\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\t\t\t\t\tif (ownerMember !== undefined && ownerMember !== null) {\n\t\t\t\t\t\tconst ownerUser = await ctx.context.adapter.findOne<User>({\n\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\twhere: [{ field: \"id\", value: ownerMember.userId }],\n\t\t\t\t\t\t});\n\t\t\t\t\t\temail = ownerUser?.email;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// No fallback needed since referenceId is required and handled above\n\t\t\tif (email === undefined || email === null || email === \"\") {\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", { message: \"User email not found\" });\n\t\t\t}\n\n\t\t\tconst finalCurrency = plan.currency ?? \"NGN\";\n\t\t\tif (!validateMinAmount(amount, finalCurrency)) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: `Amount ${amount} is less than the minimum required for ${finalCurrency}.`,\n\t\t\t\t\tstatus: 400\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\tconst chargeRes = await paystack.transactionChargeAuthorization({\n\t\t\t\temail,\n\t\t\t\tamount,\n\t\t\t\tauthorization_code: subscription.paystackAuthorizationCode,\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\tcurrency: plan.currency as any,\n\t\t\t\tmetadata: {\n\t\t\t\t\tsubscriptionId,\n\t\t\t\t\treferenceId: subscription.referenceId,\n\t\t\t\t\tplan: plan.name,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst data = unwrapSdkResult<Record<string, unknown>>(chargeRes);\n\t\t\tconst chargeData = (data as { data?: Record<string, unknown> })?.data ?? data;\n\n\t\t\tif (chargeData?.status === \"success\") {\n\t\t\t\tconst now = new Date();\n\t\t\t\tconst nextPeriodEnd = getNextPeriodEnd(now, plan.interval ?? \"monthly\");\n\n\t\t\t\tawait ctx.context.adapter.update({\n\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tperiodStart: now,\n\t\t\t\t\t\tperiodEnd: nextPeriodEnd,\n\t\t\t\t\t\tupdatedAt: now,\n\t\t\t\t\t\t// Record the last transaction reference if available\n\t\t\t\t\t\tpaystackTransactionReference: chargeData.reference as string | undefined,\n\t\t\t\t\t},\n\t\t\t\t\twhere: [{ field: \"id\", value: subscription.id }],\n\t\t\t\t});\n\n\t\t\t\treturn ctx.json({ status: \"success\", data: chargeData });\n\t\t\t}\n\n\t\t\treturn ctx.json({ status: \"failed\", data: chargeData }, { status: 400 });\n\t\t},\n\t);\n};\n","import type { BetterAuthPluginDBSchema } from \"@better-auth/core/db\";\nimport { mergeSchema } from \"better-auth/db\";\n\nimport type { PaystackClientLike, PaystackOptions } from \"./types\";\n\nexport const transactions = {\n\tpaystackTransaction: {\n\t\tfields: {\n\t\t\treference: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tpaystackId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\treferenceId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tamount: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tcurrency: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tstatus: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tplan: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tproduct: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tmetadata: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tupdatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\nexport const subscriptions = {\n\tsubscription: {\n\t\tfields: {\n\t\t\tplan: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\treferenceId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tpaystackCustomerCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tpaystackSubscriptionCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tpaystackTransactionReference: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tpaystackAuthorizationCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tpaystackEmailToken: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tstatus: {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdefaultValue: \"incomplete\",\n\t\t\t},\n\t\t\tperiodStart: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tperiodEnd: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\ttrialStart: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\ttrialEnd: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tcancelAtPeriodEnd: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\trequired: false,\n\t\t\t\tdefaultValue: false,\n\t\t\t},\n\t\t\tgroupId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tseats: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\nexport const user = {\n\tuser: {\n\t\tfields: {\n\t\t\tpaystackCustomerCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\nexport const organization = {\n\torganization: {\n\t\tfields: {\n\t\t\tpaystackCustomerCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\temail: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\nexport const products = {\n\tpaystackProduct: {\n\t\tfields: {\n\t\t\tname: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tdescription: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tprice: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tcurrency: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tquantity: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: false,\n\t\t\t\tdefaultValue: 0,\n\t\t\t},\n\t\t\tunlimited: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\trequired: false,\n\t\t\t\tdefaultValue: true,\n\t\t\t},\n\t\t\tpaystackId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tslug: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tmetadata: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tupdatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\nexport const plans = {\n\tpaystackPlan: {\n\t\tfields: {\n\t\t\tname: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tdescription: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tamount: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tcurrency: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tinterval: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tplanCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tpaystackId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tmetadata: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tupdatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const getSchema = (options: PaystackOptions<PaystackClientLike, any, any>) => {\n\tlet baseSchema: BetterAuthPluginDBSchema;\n\n\tif (options.subscription?.enabled === true) {\n\t\tbaseSchema = {\n\t\t\t...subscriptions,\n\t\t\t...transactions,\n\t\t\t...user,\n\t\t\t...products,\n\t\t\t...plans,\n\t\t};\n\t} else {\n\t\tbaseSchema = {\n\t\t\t...user,\n\t\t\t...transactions,\n\t\t\t...products,\n\t\t\t...plans,\n\t\t};\n\t}\n\n\t// Add organization schema if organization support is enabled\n\tif (options.organization?.enabled === true) {\n\t\tbaseSchema = {\n\t\t\t...baseSchema,\n\t\t\t...organization,\n\t\t};\n\t}\n\n\tif (\n\t\toptions.schema !== undefined &&\n options.subscription?.enabled !== true &&\n \"subscription\" in options.schema\n\t) {\n\t\tconst { subscription: _subscription, ...restSchema } = options.schema as Record<string, unknown>;\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\treturn mergeSchema(baseSchema, restSchema as any);\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\treturn mergeSchema(baseSchema, options.schema as any);\n};\n","import type { GenericEndpointContext } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\n\nimport type { Subscription } from \"./types\";\n\nexport const getOrganizationSubscription = async (\n\tctx: GenericEndpointContext,\n\torganizationId: string\n): Promise<Subscription | null> => {\n\tconst subscription = await ctx.context.adapter.findOne<Subscription>({\n\t\tmodel: \"subscription\",\n\t\twhere: [{ field: \"referenceId\", value: organizationId }],\n\t});\n\treturn subscription;\n};\n\nexport const checkSeatLimit = async (\n\tctx: GenericEndpointContext,\n\torganizationId: string,\n\tseatsToAdd = 1\n) => {\n\tconst subscription = await getOrganizationSubscription(ctx, organizationId);\n \n\tif (subscription?.seats === undefined || subscription.seats === null) {\n\t\treturn true; // No explicit seat limit found\n\t}\n\n\tconst members = await ctx.context.adapter.findMany({\n\t\tmodel: \"member\",\n\t\twhere: [{ field: \"organizationId\", value: organizationId }],\n\t});\n\n\tif (members.length + seatsToAdd > subscription.seats) {\n\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\tmessage: `Organization member limit reached. Used: ${members.length}, Max: ${subscription.seats}`\n\t\t});\n\t}\n\n\treturn true;\n};\n\nexport const checkTeamLimit = async (\n\tctx: GenericEndpointContext,\n\torganizationId: string,\n\tmaxTeams: number\n) => {\n\tconst teams = await ctx.context.adapter.findMany({\n\t\tmodel: \"team\",\n\t\twhere: [{ field: \"organizationId\", value: organizationId }],\n\t});\n\n\tif (teams.length >= maxTeams) {\n\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\tmessage: `Organization team limit reached. Max teams: ${maxTeams}`\n\t\t});\n\t}\n\n\treturn true;\n};\n","import { defineErrorCodes } from \"@better-auth/core/utils\";\nimport type { AuthContext, GenericEndpointContext } from \"better-auth\";\nimport { defu } from \"defu\";\n\nimport {\n\tdisablePaystackSubscription,\n\tenablePaystackSubscription,\n\tinitializeTransaction,\n\tlistSubscriptions,\n\tlistTransactions,\n\tpaystackWebhook,\n\tverifyTransaction,\n\tgetConfig,\n\tgetSubscriptionManageLink,\n\tPAYSTACK_ERROR_CODES,\n\tcreateSubscription,\n\tupgradeSubscription,\n\tcancelSubscription,\n\trestoreSubscription,\n\tchargeRecurringSubscription,\n\tsyncProducts,\n\tlistProducts,\n\tsyncPlans,\n\tlistPlans,\n} from \"./routes\";\nimport { getSchema } from \"./schema\";\nimport { checkSeatLimit, checkTeamLimit, getOrganizationSubscription } from \"./limits\";\nimport { getPlanByName } from \"./utils\";\nimport type {\n\tPaystackNodeClient,\n\tPaystackClientLike,\n\tPaystackOptions,\n\tPaystackPlan,\n\tSubscription,\n\tSubscriptionOptions,\n\tPaystackProduct,\n\tMember,\n\tUser,\n\tPaystackCustomerResponse,\n} from \"./types\";\nimport { getPaystackOps, unwrapSdkResult } from \"./paystack-sdk\";\n\nconst INTERNAL_ERROR_CODES = defineErrorCodes({\n\t...PAYSTACK_ERROR_CODES,\n});\n\nexport const paystack = <\n\tTPaystackClient extends PaystackClientLike = PaystackNodeClient,\n\tTMetadata = Record<string, unknown>,\n\tTLimits = Record<string, unknown>,\n\tO extends PaystackOptions<TPaystackClient, TMetadata, TLimits> = PaystackOptions<TPaystackClient, TMetadata, TLimits>,\n>(\n\t\toptions: O,\n\t) => {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tconst routeOptions = options as any;\n\tconst res = {\n\t\tid: \"paystack\",\n\t\tendpoints: {\n\t\t\tinitializeTransaction: initializeTransaction(routeOptions),\n\t\t\tverifyTransaction: verifyTransaction(routeOptions),\n\t\t\tlistSubscriptions: listSubscriptions(routeOptions),\n\t\t\tpaystackWebhook: paystackWebhook(routeOptions),\n\t\t\tlistTransactions: listTransactions(routeOptions),\n\t\t\tgetConfig: getConfig(routeOptions),\n\t\t\tdisableSubscription: disablePaystackSubscription(routeOptions),\n\t\t\tenableSubscription: enablePaystackSubscription(routeOptions),\n\t\t\tgetSubscriptionManageLink: getSubscriptionManageLink(routeOptions),\n\t\t\tsubscriptionManageLink: getSubscriptionManageLink(routeOptions, \"/paystack/subscription/manage-link\"), // Historical alias\n\t\t\tcreateSubscription: createSubscription(routeOptions),\n\t\t\tupgradeSubscription: upgradeSubscription(routeOptions),\n\t\t\tcancelSubscription: cancelSubscription(routeOptions),\n\t\t\trestoreSubscription: restoreSubscription(routeOptions),\n\t\t\tchargeRecurringSubscription: chargeRecurringSubscription(routeOptions),\n\t\t\tsyncProducts: syncProducts(routeOptions),\n\t\t\tlistProducts: listProducts(routeOptions),\n\t\t\tsyncPlans: syncPlans(routeOptions),\n\t\t\tlistPlans: listPlans(routeOptions),\n\t\t},\n\t\tschema: getSchema(options),\n\t\tinit: (ctx: AuthContext) => {\n\t\t\treturn {\n\t\t\t\toptions: {\n\t\t\t\t\tdatabaseHooks: {\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\t\tasync after(user: { id: string; email: string; name?: string | null }, hookCtx?: GenericEndpointContext | null) {\n\t\t\t\t\t\t\t\t\tif (hookCtx === undefined || hookCtx === null || options.createCustomerOnSignUp !== true) return;\n\n\t\t\t\t\t\t\t\t\tconst paystackOps = getPaystackOps(options.paystackClient as PaystackClientLike);\n\t\t\t\t\t\t\t\t\tconst raw = await paystackOps.customerCreate({\n\t\t\t\t\t\t\t\t\t\temail: user.email,\n\t\t\t\t\t\t\t\t\t\tfirst_name: user.name ?? undefined,\n\t\t\t\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\t\t\t\t\t} as Record<string, unknown>,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tconst sdkRes = unwrapSdkResult<PaystackCustomerResponse>(raw);\n\t\t\t\t\t\t\t\t\tconst customerCode = (sdkRes?.customer_code as string | undefined)\n\t\t\t\t\t\t\t\t\t\t?? (sdkRes?.data as Record<string, unknown>)?.customer_code as string | undefined;\n\n\t\t\t\t\t\t\t\t\tif (customerCode === undefined || customerCode === null) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tawait ctx.adapter.update({\n\t\t\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: user.id }],\n\t\t\t\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\t\t\t\tpaystackCustomerCode: customerCode,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\torganization: options.organization?.enabled === true\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\t\t\tasync after(org: { id: string; name: string; email?: string | null }, hookCtx: GenericEndpointContext | null) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tconst extraCreateParams = options.organization?.getCustomerCreateParams\n\t\t\t\t\t\t\t\t\t\t\t\t? await options.organization.getCustomerCreateParams(org, hookCtx!)\n\t\t\t\t\t\t\t\t\t\t\t\t: {};\n\n\t\t\t\t\t\t\t\t\t\t\tlet targetEmail = org.email;\n\t\t\t\t\t\t\t\t\t\t\tif (targetEmail === undefined || targetEmail === null) {\n\t\t\t\t\t\t\t\t\t\t\t\tconst ownerMember = await ctx.adapter.findOne<Member>({\n\t\t\t\t\t\t\t\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ field: \"organizationId\", value: org.id },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ field: \"role\", value: \"owner\" }\n\t\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\tif (ownerMember !== null && ownerMember !== undefined) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst ownerUser = await ctx.adapter.findOne<User>({\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: ownerMember.userId }]\n\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\t\ttargetEmail = ownerUser?.email;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tif (targetEmail === undefined || targetEmail === null) return;\n\n\t\t\t\t\t\t\t\t\t\t\tconst params = defu(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\temail: targetEmail,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfirst_name: org.name,\n\t\t\t\t\t\t\t\t\t\t\t\t\tmetadata: { organizationId: org.id },\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\textraCreateParams,\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\tconst paystackOps = getPaystackOps(options.paystackClient as PaystackClientLike);\n\t\t\t\t\t\t\t\t\t\t\tconst raw = await paystackOps.customerCreate(params as unknown as Parameters<typeof paystackOps.customerCreate>[0]);\n\t\t\t\t\t\t\t\t\t\t\tconst sdkRes = unwrapSdkResult<PaystackCustomerResponse>(raw);\n\t\t\t\t\t\t\t\t\t\t\tconst customerCode = (sdkRes?.customer_code as string | undefined)\n\t\t\t\t\t\t\t\t\t\t\t\t?? (sdkRes?.data as Record<string, unknown>)?.customer_code as string | undefined;\n\n\t\t\t\t\t\t\t\t\t\t\tif (customerCode === undefined || customerCode === null) return;\n\n\t\t\t\t\t\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\t\t\t\t\t\t\t\tawait (ctx.internalAdapter as any).updateOrganization(org.id, {\n\t\t\t\t\t\t\t\t\t\t\t\tpaystackCustomerCode: customerCode,\n\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\tawait options.organization?.onCustomerCreate?.(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tpaystackCustomer: sdkRes as unknown as PaystackCustomerResponse,\n\t\t\t\t\t\t\t\t\t\t\t\t\torganization: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t...org,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tpaystackCustomerCode: customerCode,\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\thookCtx!,\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\t\t\t\t\t\t(ctx as unknown as AuthContext).logger.error(\"Failed to create Paystack customer for organization\", error);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t},\n\t\t\t\t\tmember: {\n\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\tbefore: async (member: { organizationId: string }, ctx: GenericEndpointContext | null | undefined) => {\n\t\t\t\t\t\t\t\tif (options.subscription?.enabled === true && member.organizationId && ctx !== null && ctx !== undefined) {\n\t\t\t\t\t\t\t\t\tawait checkSeatLimit(ctx, member.organizationId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tinvitation: {\n\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\tbefore: async (invitation: { organizationId: string }, ctx: GenericEndpointContext | null | undefined) => {\n\t\t\t\t\t\t\t\tif (options.subscription?.enabled === true && invitation.organizationId && ctx !== null && ctx !== undefined) {\n\t\t\t\t\t\t\t\t\tawait checkSeatLimit(ctx, invitation.organizationId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tteam: {\n\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\tbefore: async (team: { organizationId: string }, ctx: GenericEndpointContext | null | undefined) => {\n\t\t\t\t\t\t\t\tif (options.subscription?.enabled === true && team.organizationId && ctx !== null && ctx !== undefined) {\n\t\t\t\t\t\t\t\t\tconst subscription = await getOrganizationSubscription(ctx, team.organizationId);\n\t\t\t\t\t\t\t\t\tif (subscription !== null && subscription !== undefined) {\n\t\t\t\t\t\t\t\t\t\tconst plan = await getPlanByName(options, subscription.plan);\n\t\t\t\t\t\t\t\t\t\tconst limits = plan?.limits;\n\t\t\t\t\t\t\t\t\t\tconst maxTeams = limits?.teams as number | undefined;\n\n\t\t\t\t\t\t\t\t\t\tif (typeof maxTeams === \"number\") {\n\t\t\t\t\t\t\t\t\t\t\tawait checkTeamLimit(ctx, team.organizationId, maxTeams);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t$ERROR_CODES: INTERNAL_ERROR_CODES,\n\t};\n\n\treturn res;\n};\n\nexport type PaystackPlugin<\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tO extends PaystackOptions<PaystackClientLike, any, any> = PaystackOptions,\n> = ReturnType<\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\ttypeof paystack<PaystackClientLike, any, any, O>\n>;\n\nexport type { Subscription, SubscriptionOptions, PaystackPlan, PaystackOptions, PaystackProduct };\n"],"mappings":"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CN,UAAU;EACV;CACD,YAAY;EACX,MAAM;EACN,UAAU;EACV;CACD,UAAU;EACT,MAAM;EACN,UAAU;EACV;CACD,mBAAmB;EAClB,MAAM;EACN,UAAU;EACV,cAAc;EACd;CACD,SAAS;EACR,MAAM;EACN,UAAU;EACV;CACD,OAAO;EACN,MAAM;EACN,UAAU;EACV;CACD,EACD,EACD;AAED,MAAa,OAAO,EACnB,MAAM,EACL,QAAQ,EACP,sBAAsB;CACrB,MAAM;CACN,UAAU;CACV,OAAO;CACP,EACD,EACD,EACD;AAED,MAAa,eAAe,EAC3B,cAAc,EACb,QAAQ;CACP,sBAAsB;EACrB,MAAM;EACN,UAAU;EACV,OAAO;EACP;CACD,OAAO;EACN,MAAM;EACN,UAAU;EACV;CACD,EACD,EACD;AAED,MAAa,WAAW,EACvB,iBAAiB,EAChB,QAAQ;CACP,MAAM;EACL,MAAM;EACN,UAAU;EACV;CACD,aAAa;EACZ,MAAM;EACN,UAAU;EACV;CACD,OAAO;EACN,MAAM;EACN,UAAU;EACV;CACD,UAAU;EACT,MAAM;EACN,UAAU;EACV;CACD,UAAU;EACT,MAAM;EACN,UAAU;EACV,cAAc;EACd;CACD,WAAW;EACV,MAAM;EACN,UAAU;EACV,cAAc;EACd;CACD,YAAY;EACX,MAAM;EACN,UAAU;EACV,QAAQ;EACR;CACD,MAAM;EACL,MAAM;EACN,UAAU;EACV,QAAQ;EACR;CACD,UAAU;EACT,MAAM;EACN,UAAU;EACV;CACD,WAAW;EACV,MAAM;EACN,UAAU;EACV;CACD,WAAW;EACV,MAAM;EACN,UAAU;EACV;CACD,EACD,EACD;AAED,MAAa,QAAQ,EACpB,cAAc,EACb,QAAQ;CACP,MAAM;EACL,MAAM;EACN,UAAU;EACV;CACD,aAAa;EACZ,MAAM;EACN,UAAU;EACV;CACD,QAAQ;EACP,MAAM;EACN,UAAU;EACV;CACD,UAAU;EACT,MAAM;EACN,UAAU;EACV;CACD,UAAU;EACT,MAAM;EACN,UAAU;EACV;CACD,UAAU;EACT,MAAM;EACN,UAAU;EACV,QAAQ;EACR;CACD,YAAY;EACX,M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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/paystack-sdk.ts","../src/utils.ts","../src/middleware.ts","../src/limits.ts","../src/routes.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["import type {\n\tPaystackClientLike,\n\tPaystackCustomerCreateInput,\n\tPaystackCustomerUpdateInput,\n\tPaystackNodeClient,\n\tPaystackOpenApiFetchResponse,\n\tPaystackSubscriptionFetchInit,\n\tPaystackSubscriptionCreateInput,\n\tPaystackSubscriptionToggleInput,\n\tPaystackTransactionInitializeInput,\n\tPaystackTransactionChargeAuthorizationInput,\n} from \"./types\";\n\nfunction isOpenApiFetchResponse(\n\tvalue: unknown,\n): value is PaystackOpenApiFetchResponse {\n\treturn (\n\t\tvalue !== null &&\n\t\tvalue !== undefined &&\n\t\ttypeof value === \"object\" &&\n\t\t(\"data\" in value || \"error\" in value || \"response\" in value)\n\t);\n}\n\nexport function unwrapSdkResult<T = unknown>(result: unknown): T {\n\tif (isOpenApiFetchResponse(result)) {\n\t\tif (result.error !== undefined && result.error !== null) {\n\t\t\tthrow new Error(typeof result.error === \"string\" ? result.error : JSON.stringify(result.error));\n\t\t}\n\t\treturn (result.data as T) ?? (result as T);\n\t}\n\tif (result !== null && result !== undefined && typeof result === \"object\" && \"data\" in result) {\n\t\tconst data = (result as { data: unknown }).data;\n\t\t// If data is also an object with a data property, unwrap it (legacy SDK style)\n\t\tif (data !== null && typeof data === \"object\" && \"data\" in data) {\n\t\t\treturn (data as { data: T }).data;\n\t\t}\n\t\treturn data as T;\n\t}\n\treturn result as T;\n}\n\n\n\n\n\ntype TransactionInitializeBody = Parameters<PaystackNodeClient[\"transaction_initialize\"]>[0] extends {\n\tbody?: infer B;\n}\n\t? B\n\t: never;\n\nexport function getPaystackOps(\n\tpaystackClient: PaystackClientLike,\n) {\n\treturn {\n\t\tcustomerCreate: (params: PaystackCustomerCreateInput) => {\n\t\t\tif (paystackClient?.customer_create !== undefined) {\n\t\t\t\treturn paystackClient.customer_create({ body: params as unknown as NonNullable<Parameters<PaystackNodeClient[\"customer_create\"]>[0]>[\"body\"] });\n\t\t\t}\n\t\t\treturn paystackClient?.customer?.create?.(params);\n\t\t},\n\t\tcustomerUpdate: (code: string, params: PaystackCustomerUpdateInput) => {\n\t\t\tif (paystackClient?.customer_update !== undefined) {\n\t\t\t\treturn paystackClient.customer_update({\n\t\t\t\t\tparams: { path: { code } },\n\t\t\t\t\tbody: params as unknown as NonNullable<Parameters<PaystackNodeClient[\"customer_update\"]>[0]>[\"body\"],\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.customer?.update?.(code, params);\n\t\t},\n\t\ttransactionInitialize: (body: PaystackTransactionInitializeInput) => {\n\t\t\tif (paystackClient?.transaction_initialize !== undefined) {\n\t\t\t\treturn paystackClient.transaction_initialize({\n\t\t\t\t\tbody: body as TransactionInitializeBody,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.transaction?.initialize?.(body);\n\t\t},\n\t\ttransactionVerify: (reference: string) => {\n\t\t\tif (paystackClient?.transaction_verify !== undefined) {\n\t\t\t\treturn paystackClient.transaction_verify({\n\t\t\t\t\tparams: { path: { reference } },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.transaction?.verify?.(reference);\n\t\t},\n\t\tsubscriptionCreate: (body: PaystackSubscriptionCreateInput) => {\n\t\t\tif (paystackClient?.subscription_create !== undefined) {\n\t\t\t\treturn paystackClient.subscription_create({ body });\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.create?.(body);\n\t\t},\n\t\tsubscriptionDisable: (body: PaystackSubscriptionToggleInput) => {\n\t\t\tif (paystackClient?.subscription_disable !== undefined) {\n\t\t\t\treturn paystackClient.subscription_disable({ body });\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.disable?.(body);\n\t\t},\n\t\tsubscriptionEnable: (body: PaystackSubscriptionToggleInput) => {\n\t\t\tif (paystackClient?.subscription_enable !== undefined) {\n\t\t\t\treturn paystackClient.subscription_enable({ body });\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.enable?.(body);\n\t\t},\n\t\tsubscriptionFetch: async (idOrCode: string) => {\n\t\t\tif (paystackClient?.subscription_fetch !== undefined) {\n\t\t\t\ttry {\n\t\t\t\t\treturn await paystackClient.subscription_fetch({\n\t\t\t\t\t\tparams: { path: { code: idOrCode } },\n\t\t\t\t\t});\n\t\t\t\t} catch {\n\t\t\t\t\tconst compatFetch = paystackClient.subscription_fetch as unknown as (\n\t\t\t\t\t\tinit: PaystackSubscriptionFetchInit,\n\t\t\t\t\t) => Promise<unknown>;\n\t\t\t\t\treturn compatFetch({\n\t\t\t\t\t\tparams: { path: { id_or_code: idOrCode } },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.fetch?.(idOrCode);\n\t\t},\n\t\tsubscriptionManageLink: (code: string) => {\n\t\t\tif (paystackClient?.subscription_manageLink !== undefined) {\n\t\t\t\treturn paystackClient.subscription_manageLink({\n\t\t\t\t\tparams: { path: { code } },\n\t\t\t\t});\n\t\t\t}\n\t\t\t// Fallback for snake_case if older SDK version or different generator\n\t\t\tif (paystackClient?.subscription_manage_link !== undefined) {\n\t\t\t\treturn paystackClient.subscription_manage_link({\n\t\t\t\t\tparams: { path: { code } },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.manage?.link?.(code);\n\t\t},\n\t\tsubscriptionManageEmail: (code: string, email: string) => {\n\t\t\tif (paystackClient?.subscription_manageEmail !== undefined) {\n\t\t\t\treturn paystackClient.subscription_manageEmail({\n\t\t\t\t\tparams: { path: { code } },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.subscription?.manage?.email?.(code, email);\n\t\t},\n\t\tsubscriptionUpdate: (params: { code: string; plan?: string; authorization?: string; amount?: number }) => {\n\t\t\tif (paystackClient?.subscription_update !== undefined) {\n\t\t\t\treturn (paystackClient.subscription_update as any)({\n\t\t\t\t\tparams: { path: { code: params.code } },\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tplan: params.plan,\n\t\t\t\t\t\tauthorization: params.authorization,\n\t\t\t\t\t\tamount: params.amount,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\treturn (paystackClient as any)?.subscription?.update?.(params.code, params);\n\t\t},\n\t\ttransactionChargeAuthorization: (body: PaystackTransactionChargeAuthorizationInput) => {\n\t\t\tif (paystackClient?.transaction_chargeAuthorization !== undefined) {\n\t\t\t\treturn paystackClient.transaction_chargeAuthorization({\n\n\t\t\t\t\t// casting to avoid deep type issues with metadata\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\t\tbody: body as any, // casting to avoid deep type issues with metadata\n\t\t\t\t});\n\t\t\t}\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\treturn paystackClient?.transaction?.chargeAuthorization?.(body as any);\n\t\t},\n\t\tproductList: () => {\n\t\t\tif (paystackClient?.product_list !== undefined) {\n\t\t\t\treturn paystackClient.product_list();\n\t\t\t}\n\t\t\treturn paystackClient?.product?.list?.();\n\t\t},\n\t\tproductFetch: (idOrCode: string) => {\n\t\t\tif (paystackClient?.product_fetch !== undefined) {\n\t\t\t\treturn paystackClient.product_fetch({\n\t\t\t\t\tparams: { path: { id_or_code: idOrCode } },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.product?.fetch?.(idOrCode);\n\t\t},\n\t\tproductCreate: (params: Record<string, unknown>) => {\n\t\t\tif (paystackClient?.product_create !== undefined) {\n\t\t\t\treturn paystackClient.product_create({ body: params });\n\t\t\t}\n\t\t\treturn paystackClient?.product?.create?.(params);\n\t\t},\n\t\tproductUpdate: (idOrCode: string, params: Record<string, unknown>) => {\n\t\t\tif (paystackClient?.product_update !== undefined) {\n\t\t\t\treturn paystackClient.product_update({\n\t\t\t\t\tparams: { path: { id_or_code: idOrCode } },\n\t\t\t\t\tbody: params,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.product?.update?.(idOrCode, params);\n\t\t},\n\t\tproductDelete: (idOrCode: string) => {\n\t\t\tif (paystackClient?.product_delete !== undefined) {\n\t\t\t\treturn paystackClient.product_delete({\n\t\t\t\t\tparams: { path: { id_or_code: idOrCode } },\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn paystackClient?.product?.delete?.(idOrCode);\n\t\t},\n\t\tplanList: () => {\n\t\t\tif (paystackClient?.plan_list !== undefined) {\n\t\t\t\treturn paystackClient.plan_list();\n\t\t\t}\n\t\t\treturn paystackClient?.plan?.list?.();\n\t\t},\n\t};\n}\n","import type { PaystackClientLike, PaystackOptions, PaystackProduct } from \"./types\";\nimport { getPaystackOps, unwrapSdkResult } from \"./paystack-sdk\";\n\nexport async function getPlans(subscriptionOptions: PaystackOptions[\"subscription\"]) {\n\tif (subscriptionOptions?.enabled === true) {\n\t\treturn typeof subscriptionOptions.plans === \"function\"\n\t\t\t? subscriptionOptions.plans()\n\t\t\t: subscriptionOptions.plans;\n\t}\n\tthrow new Error(\"Subscriptions are not enabled in the Paystack options.\");\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const getPlan = async (options: PaystackOptions<PaystackClientLike, any, any>, planId: string) => {\n\tif (options.subscription?.enabled === true) {\n\t\tconst plans = await getPlans(options.subscription);\n\t\treturn plans.find((plan) => plan.name === planId) ?? null;\n\t}\n\treturn null;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function getPlanByName(options: PaystackOptions<PaystackClientLike, any, any>, name: string) {\n\tif (options.subscription?.enabled === true) {\n\t\tconst plans = await getPlans(options.subscription);\n\t\treturn plans.find(\n\t\t\t(plan) => plan.name.toLowerCase() === name.toLowerCase(),\n\t\t) ?? null;\n\t}\n\treturn null;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function getPlanByPriceId(options: PaystackOptions<PaystackClientLike, any, any>, priceId: string) {\n\tif (options.subscription?.enabled === true) {\n\t\tconst plans = await getPlans(options.subscription);\n\t\treturn plans.find((plan) => plan.name === priceId) ?? null;\n\t}\n\treturn null;\n}\n\n\nexport async function getProducts(productOptions: PaystackOptions[\"products\"]) {\n\tif (productOptions?.products) {\n\t\treturn typeof productOptions.products === \"function\"\n\t\t\t? await productOptions.products()\n\t\t\t: productOptions.products;\n\t}\n\treturn [];\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function getProductByName(options: PaystackOptions<PaystackClientLike, any, any>, name: string) {\n\treturn await getProducts(options.products).then((products) =>\n\t\tproducts?.find((product) => product.name.toLowerCase() === name.toLowerCase()) ?? null,\n\t);\n}\n\nexport function getNextPeriodEnd(startDate: Date, interval: string): Date {\n\tconst date = new Date(startDate);\n\tswitch (interval) {\n\tcase \"daily\":\n\t\tdate.setDate(date.getDate() + 1);\n\t\tbreak;\n\tcase \"weekly\":\n\t\tdate.setDate(date.getDate() + 7);\n\t\tbreak;\n\tcase \"monthly\":\n\t\tdate.setMonth(date.getMonth() + 1);\n\t\tbreak;\n\tcase \"quarterly\":\n\t\tdate.setMonth(date.getMonth() + 3);\n\t\tbreak;\n\tcase \"biannually\":\n\t\tdate.setMonth(date.getMonth() + 6);\n\t\tbreak;\n\tcase \"annually\":\n\t\tdate.setFullYear(date.getFullYear() + 1);\n\t\tbreak;\n\tdefault:\n\t\t// Default to monthly if unknown\n\t\tdate.setMonth(date.getMonth() + 1);\n\t}\n\treturn date;\n}\n\n/**\n * Validates if the amount meets Paystack's minimum transaction requirements.\n * Amounts should be in the smallest currency unit (e.g., kobo, cents).\n */\nexport function validateMinAmount(amount: number, currency: string): boolean {\n\tconst minAmounts: Record<string, number> = {\n\t\tNGN: 5000, // 50.00\n\t\tGHS: 10, // 0.10\n\t\tZAR: 100, // 1.00\n\t\tKES: 300, // 3.00\n\t\tUSD: 200, // 2.00\n\t\tXOF: 100, // 1.00\n\t};\n\tconst min = minAmounts[currency.toUpperCase()];\n\treturn min !== undefined ? amount >= min : true;\n}\n\nexport async function syncProductQuantityFromPaystack(\n\tctx: any,\n\tproductName: string,\n\tpaystackClient: PaystackClientLike,\n): Promise<void> {\n\t// Find the local product record (by name or slug)\n\tlet localProduct = await (ctx.context.adapter).findOne({\n\t\tmodel: \"paystackProduct\",\n\t\twhere: [{ field: \"name\", value: productName }],\n\t}) as PaystackProduct | null;\n\n\tlocalProduct ??= await (ctx.context.adapter).findOne({\n\t\tmodel: \"paystackProduct\",\n\t\twhere: [{ field: \"slug\", value: productName.toLowerCase().replace(/\\s+/g, \"-\") }],\n\t}) as PaystackProduct | null;\n\n\tif (localProduct?.paystackId === undefined || localProduct?.paystackId === null || localProduct?.paystackId === \"\") {\n\t\t// No local record with a Paystack ID — fall back to local decrement\n\t\tif (localProduct && (localProduct as any).unlimited !== true && (localProduct as any).quantity !== undefined && (localProduct as any).quantity > 0) {\n\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\tupdate: { quantity: (localProduct as any).quantity - 1, updatedAt: new Date() },\n\t\t\t\twhere: [{ field: \"id\", value: (localProduct as any).id }],\n\t\t\t});\n\t\t}\n\t\treturn;\n\t}\n\n\t// Fetch the latest quantity from Paystack\n\ttry {\n\t\tconst ops = getPaystackOps(paystackClient);\n\t\tconst raw = await ops.productFetch(localProduct.paystackId);\n\t\tconst data = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\tconst remoteQuantity = data?.quantity as number | undefined;\n\n\t\tif (remoteQuantity !== undefined) {\n\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\tupdate: { quantity: remoteQuantity, updatedAt: new Date() },\n\t\t\t\twhere: [{ field: \"id\", value: (localProduct as any).id }],\n\t\t\t});\n\t\t}\n\t} catch {\n\t\t// If API call fails, fall back to local decrement\n\t\tif ((localProduct as any).unlimited !== true && (localProduct as any).quantity !== undefined && (localProduct as any).quantity > 0) {\n\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\tupdate: { quantity: (localProduct as any).quantity - 1, updatedAt: new Date() },\n\t\t\t\twhere: [{ field: \"id\", value: (localProduct as any).id }],\n\t\t\t});\n\t\t}\n\t}\n}\n\n/** @deprecated Use syncProductQuantityFromPaystack instead */\nexport async function decrementProductQuantity(ctx: any, productName: string) {\n\tlet product = await (ctx.context.adapter).findOne({\n\t\tmodel: \"paystackProduct\",\n\t\twhere: [{ field: \"name\", value: productName }],\n\t}) as PaystackProduct | null;\n\n\tproduct ??= await (ctx.context.adapter).findOne({\n\t\tmodel: \"paystackProduct\",\n\t\twhere: [{ field: \"slug\", value: productName.toLowerCase().replace(/\\s+/g, \"-\") }],\n\t}) as PaystackProduct | null;\n\n\tif (product) {\n\t\tif (product.unlimited !== true && product.quantity !== undefined && product.quantity > 0) {\n\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\tupdate: {\n\t\t\t\t\tquantity: (product as any).quantity - 1,\n\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t},\n\t\t\t\twhere: [{ field: \"id\", value: (product as any).id }],\n\t\t\t});\n\t\t}\n\t}\n}\n\nexport async function syncSubscriptionSeats(\n\tctx: any,\n\torganizationId: string,\n\toptions: PaystackOptions<PaystackClientLike, any, any>,\n): Promise<void> {\n\tif (options.subscription?.enabled !== true) return;\n\n\tconst adapter = ctx.context?.adapter ?? ctx.adapter;\n\tconst subscription = await (adapter).findOne({\n\t\tmodel: \"subscription\",\n\t\twhere: [{ field: \"referenceId\", value: organizationId }],\n\t});\n\n\tif (subscription === null || subscription.paystackSubscriptionCode === undefined || subscription.paystackSubscriptionCode === null) return;\n\tconst plan = await getPlanByName(options, subscription.plan);\n\tif (plan === null) return;\n\tif (plan.seatAmount === undefined && plan.seatPlanCode === undefined) return;\n\n\tconst members = await (adapter).findMany({\n\t\tmodel: \"member\",\n\t\twhere: [{ field: \"organizationId\", value: organizationId }],\n\t});\n\n\tconst quantity = members.length;\n\tlet totalAmount = plan.amount ?? 0;\n\n\tif (plan.seatAmount !== undefined && plan.seatAmount !== null) {\n\t\ttotalAmount += (quantity * plan.seatAmount);\n\t}\n\n\tconst ops = getPaystackOps(options.paystackClient);\n\ttry {\n\t\t// Paystack subscription update doesn't natively support quantity in the same way as Stripe\n\t\t// but we can update the amount or the plan.\n\t\tawait ops.subscriptionUpdate({\n\t\t\tcode: subscription.paystackSubscriptionCode,\n\t\t\tamount: totalAmount,\n\t\t});\n\n\t\t// Update local DB to reflect current seat count\n\t\tawait (adapter).update({\n\t\t\tmodel: \"subscription\",\n\t\t\twhere: [{ field: \"id\", value: subscription.id }],\n\t\t\tupdate: {\n\t\t\t\tseats: quantity,\n\t\t\t\tupdatedAt: new Date(),\n\t\t\t},\n\t\t});\n\t} catch (e: unknown) {\n\t\tconst log = ctx.context?.logger ?? ctx.logger;\n\t\tif (log !== undefined && log !== null) {\n\t\t\tlog.error(\"Failed to sync subscription seats with Paystack\", e);\n\t\t}\n\t}\n}\n","import { createAuthMiddleware } from \"@better-auth/core/api\";\nimport { logger } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\n\n\nimport type { PaystackClientLike, PaystackOptions, Session, User } from \"./types\";\n\nexport const referenceMiddleware = (\n\toptions: PaystackOptions<PaystackClientLike>,\n\taction:\n | \"initialize-transaction\"\n | \"verify-transaction\"\n | \"list-subscriptions\"\n | \"list-transactions\"\n | \"disable-subscription\"\n | \"enable-subscription\"\n | \"get-subscription-manage-link\",\n) =>\n\tcreateAuthMiddleware(async (ctx) => {\n\t\tconst session = ctx.context.session as {\n\t\t\tuser: User;\n\t\t\tsession: Session;\n\t\t} | null;\n\n\t\tif (session === null || session === undefined) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t}\n\t\tconst body = (ctx.body ?? {}) as Record<string, unknown>;\n\t\tconst query = (ctx.query ?? {}) as Record<string, unknown>;\n\t\tconst referenceId =\n (body.referenceId as string | undefined) ?? (query.referenceId as string | undefined) ?? session.user.id;\n \n\t\tconst subscriptionOptions = options.subscription;\n\n\n\n\t\tif (referenceId === session.user.id) {\n\t\t\treturn {\n\t\t\t\treferenceId,\n\t\t\t};\n\t\t}\n\n\n \n\t\t// 1. Try custom authorization first if provided\n\t\tif (subscriptionOptions?.enabled === true && 'authorizeReference' in subscriptionOptions && subscriptionOptions.authorizeReference) {\n\t\t\tconst authorized = await subscriptionOptions.authorizeReference(\n\t\t\t\t{\n\t\t\t\t\tuser: session.user,\n\t\t\t\t\tsession: session.session,\n\t\t\t\t\treferenceId,\n\t\t\t\t\taction,\n\t\t\t\t},\n\t\t\t\tctx,\n\t\t\t);\n\t\t\tif (authorized === true) {\n\t\t\t\treturn {\n\t\t\t\t\treferenceId,\n\t\t\t\t};\n\t\t\t}\n\t\t\t// If explicit authorizeReference returns false, do we fail immediately?\n\t\t\t// Usually yes, but maybe we fallback to org check?\n\t\t\t// Let's assume authorizeReference overrides everything.\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t}\n\n\t\t// 2. Fallback: Organization Check\n\t\tif (options.organization?.enabled === true) {\n\t\t\t// Check if referenceId indicates an organization the user is a member of\n\t\t\tconst member = await (ctx.context.adapter as any).findOne({\n\t\t\t\tmodel: \"member\",\n\t\t\t\twhere: [\n\t\t\t\t\t{ field: \"userId\", value: session.user.id },\n\t\t\t\t\t{ field: \"organizationId\", value: referenceId }\n\t\t\t\t]\n\t\t\t});\n \n\t\t\tif (member !== null && member !== undefined) {\n\t\t\t\tlogger.debug(\"DEBUG MIDDLEWARE MEMBER FOUND:\", member);\n\t\t\t\t// User is a member of the organization.\n\t\t\t\t// We could check roles here, but for now allow any member.\n\t\t\t\treturn {\n\t\t\t\t\treferenceId,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tlogger.error(\n\t\t\t`Passing referenceId into a subscription action isn't allowed if subscription.authorizeReference isn't defined in your paystack plugin config and matches no organization membership.`,\n\t\t);\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage:\n \"Passing referenceId isn't allowed without subscription.authorizeReference or valid organization membership.\",\n\t\t});\n\t});\n","import type { GenericEndpointContext } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\n\nimport type { Subscription } from \"./types\";\n\nexport const getOrganizationSubscription = async (\n\tctx: GenericEndpointContext,\n\torganizationId: string\n): Promise<Subscription | null> => {\n\tconst subscription = await (ctx.context.adapter as any).findOne({\n\t\tmodel: \"subscription\",\n\t\twhere: [{ field: \"referenceId\", value: organizationId }],\n\t});\n\treturn subscription;\n};\n\nexport const checkSeatLimit = async (\n\tctx: GenericEndpointContext,\n\torganizationId: string,\n\tseatsToAdd = 1\n) => {\n\tconst subscription = await getOrganizationSubscription(ctx, organizationId);\n \n\tif (subscription?.seats === undefined || subscription.seats === null) {\n\t\treturn true; // No explicit seat limit found\n\t}\n\n\tconst members = await ctx.context.adapter.findMany({\n\t\tmodel: \"member\",\n\t\twhere: [{ field: \"organizationId\", value: organizationId }],\n\t});\n\n\tif (members.length + seatsToAdd > subscription.seats) {\n\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\tmessage: `Organization member limit reached. Used: ${members.length}, Max: ${subscription.seats}`\n\t\t});\n\t}\n\n\treturn true;\n};\n\nexport const checkTeamLimit = async (\n\tctx: GenericEndpointContext,\n\torganizationId: string,\n\tmaxTeams: number\n) => {\n\tconst teams = await ctx.context.adapter.findMany({\n\t\tmodel: \"team\",\n\t\twhere: [{ field: \"organizationId\", value: organizationId }],\n\t});\n\n\tif (teams.length >= maxTeams) {\n\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\tmessage: `Organization team limit reached. Max teams: ${maxTeams}`\n\t\t});\n\t}\n\n\treturn true;\n};\n","import { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { defineErrorCodes } from \"@better-auth/core/utils/error-codes\";\nimport { HIDE_METADATA } from \"better-auth\";\nimport {\n\tAPIError,\n\tgetSessionFromCtx,\n\toriginCheck,\n\tsessionMiddleware,\n} from \"better-auth/api\";\nimport * as z from \"zod/v4\";\nimport type { GenericEndpointContext } from \"better-auth\";\n\nimport type { InputPaystackProduct, PaystackOptions, PaystackTransaction, Subscription, Member, User, PaystackClientLike, PaystackWebhookPayload, PaystackProduct } from \"./types\";\nimport {\n\tsyncProductQuantityFromPaystack,\n\tgetPlanByName,\n\tgetPlans,\n\tgetProductByName,\n\tgetProducts,\n\tvalidateMinAmount,\n\tgetNextPeriodEnd,\n} from \"./utils\";\nimport type { PaystackPlan } from \"./types\";\nimport { referenceMiddleware } from \"./middleware\";\nimport { getPaystackOps, unwrapSdkResult } from \"./paystack-sdk\";\nimport { getOrganizationSubscription } from \"./limits\";\n\ntype AnyPaystackOptions = PaystackOptions<PaystackClientLike>;\n\nconst PAYSTACK_ERROR_CODES = defineErrorCodes({\n\tSUBSCRIPTION_NOT_FOUND: \"Subscription not found\",\n\tSUBSCRIPTION_PLAN_NOT_FOUND: \"Subscription plan not found\",\n\tUNABLE_TO_CREATE_CUSTOMER: \"Unable to create customer\",\n\tFAILED_TO_INITIALIZE_TRANSACTION: \"Failed to initialize transaction\",\n\tFAILED_TO_VERIFY_TRANSACTION: \"Failed to verify transaction\",\n\tFAILED_TO_DISABLE_SUBSCRIPTION: \"Failed to disable subscription\",\n\tFAILED_TO_ENABLE_SUBSCRIPTION: \"Failed to enable subscription\",\n\tEMAIL_VERIFICATION_REQUIRED:\n\t\t\"Email verification is required before you can subscribe to a plan\",\n});\n\nasync function hmacSha512Hex(secret: string, message: string): Promise<string> {\n\tconst encoder = new TextEncoder();\n\tconst keyData = encoder.encode(secret);\n\tconst msgData = encoder.encode(message);\n\n\tconst crypto = globalThis.crypto;\n\tif (crypto !== undefined && crypto !== null && \"subtle\" in crypto) {\n\t\tconst subtle = crypto.subtle;\n\t\tconst key = await subtle.importKey(\n\t\t\t\"raw\",\n\t\t\tkeyData,\n\t\t\t{ name: \"HMAC\", hash: \"SHA-512\" },\n\t\t\tfalse,\n\t\t\t[\"sign\"],\n\t\t);\n\t\tconst signature = await subtle.sign(\"HMAC\", key, msgData);\n\t\treturn Array.from(new Uint8Array(signature))\n\t\t\t.map((b) => b.toString(16).padStart(2, \"0\"))\n\t\t\t.join(\"\");\n\t}\n\n\tconst { createHmac } = await import(\"node:crypto\");\n\treturn createHmac(\"sha512\", secret).update(message).digest(\"hex\");\n}\n\nexport const paystackWebhook = (options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/webhook\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"handlePaystackWebhook\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tcloneRequest: true,\n\t\t\tdisableBody: true,\n\t\t},\n\t\tasync (ctx: any) => {\n\t\t\tconst request = (ctx as GenericEndpointContext & { requestClone?: Request }).requestClone ?? ctx.request;\n\t\t\tif (!request) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Request object is missing from context\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst payload = await request.text();\n\t\t\tconst headers = (ctx as GenericEndpointContext & { headers?: Headers }).headers ?? (ctx.request as unknown as { headers: Headers })?.headers;\n\t\t\tconst signature = headers?.get(\"x-paystack-signature\") as\n\t\t\t\t| string\n\t\t\t\t| null\n\t\t\t\t| undefined;\n\n\t\t\tif (signature === undefined || signature === null || signature === \"\") {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Missing x-paystack-signature header\",\n\t\t\t\t\tstatus: 401,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst expected = await hmacSha512Hex(options.paystackWebhookSecret, payload);\n\t\t\tif (expected !== signature) {\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Invalid Paystack webhook signature\",\n\t\t\t\t\tstatus: 401,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst event = JSON.parse(payload) as PaystackWebhookPayload;\n\t\t\tconst eventName = event.event;\n\t\t\tconst data = event.data;\n\n\t\t\t// Core Transaction Status Sync (Applies to both one-time and recurring)\n\t\t\tif (eventName === \"charge.success\") {\n\t\t\t\tconst reference = (data as Record<string, unknown> | undefined)?.reference as string | undefined;\n\t\t\t\tconst paystackId = (data as Record<string, unknown> | undefined)?.id !== undefined && (data as Record<string, unknown> | undefined)?.id !== null ? String((data).id) : undefined;\n\t\t\t\tif (reference !== undefined && reference !== null && reference !== \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\t\t\t\tpaystackId,\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t// Transaction record might not exist yet (e.g. webhook arrives before local record)\n\t\t\t\t\t\tctx.context.logger.warn(\"Failed to update transaction status for charge.success\", e);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Sync product quantity from Paystack after successful charge\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst transaction = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t\t}) as PaystackTransaction | null;\n\t\t\t\t\t\tif (transaction?.product) {\n\t\t\t\t\t\t\tawait syncProductQuantityFromPaystack(ctx, transaction.product, options.paystackClient);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tctx.context.logger.warn(\"Failed to sync product quantity\", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (eventName === \"charge.failure\") {\n\t\t\t\tconst reference = (data as Record<string, unknown> | undefined)?.reference as string | undefined;\n\t\t\t\tif (reference !== undefined && reference !== null && reference !== \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tctx.context.logger.warn(\"Failed to update transaction status for charge.failure\", e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Best-effort local state sync for subscription lifecycle.\n\t\t\tif (options.subscription?.enabled === true) {\n\t\t\t\ttry {\n\n\t\t\t\t\tif (eventName === \"subscription.create\") {\n\t\t\t\t\t\tconst payloadData = data as any;\n\t\t\t\t\t\tconst subscriptionCode =\n\t\t\t\t\t\t\tpayloadData?.subscription_code ??\n\t\t\t\t\t\t\tpayloadData?.subscription?.subscription_code ??\n\t\t\t\t\t\t\tpayloadData?.code;\n\t\t\t\t\t\tconst customerCode =\n\t\t\t\t\t\t\tpayloadData?.customer?.customer_code ??\n\t\t\t\t\t\t\tpayloadData?.customer_code ??\n\t\t\t\t\t\t\tpayloadData?.customer?.code;\n\t\t\t\t\t\tconst planCode =\n\t\t\t\t\t\t\tpayloadData?.plan?.plan_code ?? payloadData?.plan_code ?? payloadData?.plan;\n\n\t\t\t\t\t\tlet metadata: unknown = payloadData?.metadata;\n\t\t\t\t\t\tif (typeof metadata === \"string\") {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tmetadata = JSON.parse(metadata);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t// ignore\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst referenceIdFromMetadata =\n\t\t\t\t\t\t\ttypeof metadata === \"object\" && metadata !== null\n\t\t\t\t\t\t\t\t? ((metadata as Record<string, unknown>).referenceId as string | undefined)\n\t\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\t\tlet planNameFromMetadata =\n\t\t\t\t\t\t\ttypeof metadata === \"object\" && metadata !== null\n\t\t\t\t\t\t\t\t? ((metadata as Record<string, unknown>).plan as string | undefined)\n\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\tif (typeof planNameFromMetadata === \"string\") {\n\t\t\t\t\t\t\tplanNameFromMetadata = planNameFromMetadata.toLowerCase();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst plans = await getPlans(options.subscription);\n\t\t\t\t\t\tconst planFromCode = (planCode !== undefined && planCode !== null && planCode !== \"\")\n\t\t\t\t\t\t\t? plans.find((p) => p.planCode !== undefined && p.planCode !== null && p.planCode === planCode)\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\tconst planPart = planFromCode?.name ?? planNameFromMetadata;\n\t\t\t\t\t\tconst planName = planPart !== undefined && planPart !== null && planPart !== \"\" ? planPart.toLowerCase() : undefined;\n\n\t\t\t\t\t\tif (subscriptionCode !== undefined && subscriptionCode !== null && subscriptionCode !== \"\") {\n\t\t\t\t\t\t\tconst where: { field: string; value: string | number | boolean | null }[] = [];\n\t\t\t\t\t\t\tif (referenceIdFromMetadata !== undefined && referenceIdFromMetadata !== null && referenceIdFromMetadata !== \"\") {\n\t\t\t\t\t\t\t\twhere.push({ field: \"referenceId\", value: referenceIdFromMetadata });\n\t\t\t\t\t\t\t} else if (customerCode !== undefined && customerCode !== null && customerCode !== \"\") {\n\t\t\t\t\t\t\t\twhere.push({ field: \"paystackCustomerCode\", value: customerCode });\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (planName !== undefined && planName !== null && planName !== \"\") {\n\t\t\t\t\t\t\t\twhere.push({ field: \"plan\", value: planName });\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (where.length > 0) {\n\t\t\t\t\t\t\t\tconst matches = await (ctx.context.adapter).findMany({\n\t\t\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\t\t\twhere: where as { field: string; value: string | number | boolean | null }[],\n\t\t\t\t\t\t\t\t}) as Subscription[];\n\t\t\t\t\t\t\t\tconst subscription = (matches !== undefined && matches !== null) ? matches[0] : undefined;\n\t\t\t\t\t\t\t\tif (subscription !== undefined && subscription !== null) {\n\t\t\t\t\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\t\t\t\tpaystackSubscriptionCode: subscriptionCode,\n\t\t\t\t\t\t\t\t\t\t\tstatus: \"active\",\n\t\t\t\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t\t\t\t\tperiodEnd: (payloadData?.next_payment_date !== undefined && payloadData?.next_payment_date !== null && payloadData?.next_payment_date !== \"\") ? new Date(payloadData.next_payment_date) : undefined,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: subscription.id }],\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\tconst plan = planFromCode ?? (planName !== undefined && planName !== null && planName !== \"\" ? await getPlanByName(options, planName) : undefined);\n\t\t\t\t\t\t\t\t\tif (plan !== undefined && plan !== null) {\n\t\t\t\t\t\t\t\t\t\tawait options.subscription.onSubscriptionComplete?.(\n\t\t\t\t\t\t\t\t\t\t\t{ event, subscription: { ...subscription, paystackSubscriptionCode: subscriptionCode, status: \"active\" }, plan },\n\t\t\t\t\t\t\t\t\t\t\tctx as GenericEndpointContext,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t// Also call onSubscriptionCreated for subscriptions created outside of checkout\n\t\t\t\t\t\t\t\t\t\tawait options.subscription.onSubscriptionCreated?.(\n\t\t\t\t\t\t\t\t\t\t\t{ event, subscription: { ...subscription, paystackSubscriptionCode: subscriptionCode, status: \"active\" }, plan },\n\t\t\t\t\t\t\t\t\t\t\tctx as GenericEndpointContext,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (eventName === \"subscription.disable\" || eventName === \"subscription.not_renew\") {\n\t\t\t\t\t\tconst payloadData = data as any;\n\t\t\t\t\t\tconst subscriptionCode =\n\t\t\t\t\t\t\tpayloadData?.subscription_code ??\n\t\t\t\t\t\t\tpayloadData?.subscription?.subscription_code ??\n\t\t\t\t\t\t\tpayloadData?.code;\n\t\t\t\t\t\tif (subscriptionCode !== undefined && subscriptionCode !== null && subscriptionCode !== \"\") {\n\t\t\t\t\t\t\t// Find the subscription first to get full data for the hook\n\t\t\t\t\t\t\tconst existing = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\t\twhere: [{ field: \"paystackSubscriptionCode\", value: subscriptionCode }],\n\t\t\t\t\t\t\t}) as Subscription | null;\n\n\t\t\t\t\t\t\tlet newStatus = \"canceled\";\n\t\t\t\t\t\t\tconst nextPaymentDate = (data)?.next_payment_date as string | undefined;\n\t\t\t\t\t\t\tconst periodEnd = nextPaymentDate ? new Date(nextPaymentDate) : (existing?.periodEnd ? new Date(existing.periodEnd) : undefined);\n\n\t\t\t\t\t\t\tif (periodEnd && periodEnd > new Date()) {\n\t\t\t\t\t\t\t\tnewStatus = \"active\";\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\t\tstatus: newStatus,\n\t\t\t\t\t\t\t\t\tcancelAtPeriodEnd: true,\n\t\t\t\t\t\t\t\t\t...(periodEnd ? { periodEnd } : {}),\n\t\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{ field: \"paystackSubscriptionCode\", value: subscriptionCode },\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (existing) {\n\t\t\t\t\t\t\t\tawait options.subscription.onSubscriptionCancel?.(\n\t\t\t\t\t\t\t\t\t{ event, subscription: { ...existing, status: \"canceled\" } },\n\t\t\t\t\t\t\t\t\tctx as GenericEndpointContext,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Handle plan changes on renewal\n\t\t\t\t\tif (eventName === \"charge.success\" || eventName === \"invoice.update\") {\n\t\t\t\t\t\tconst payloadData = data as any;\n\t\t\t\t\t\tconst subscriptionCode = payloadData?.subscription?.subscription_code ?? payloadData?.subscription_code;\n\n\t\t\t\t\t\tif (subscriptionCode) {\n\t\t\t\t\t\t\tconst existingSub = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\t\twhere: [{ field: \"paystackSubscriptionCode\", value: subscriptionCode }],\n\t\t\t\t\t\t\t}) as Subscription | null;\n\n\t\t\t\t\t\t\tif (existingSub?.pendingPlan) {\n\t\t\t\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\t\t\tplan: existingSub.pendingPlan,\n\t\t\t\t\t\t\t\t\t\tpendingPlan: null,\n\t\t\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: existingSub.id }],\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (_e: unknown) {\n\t\t\t\t\tctx.context.logger.error(\"Failed to sync Paystack webhook event\", _e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait options.onEvent?.(event);\n\t\t\treturn ctx.json({ received: true });\n\t\t},\n\t);\n};\n\nconst initializeTransactionBodySchema = z.object({\n\tplan: z.string().optional(),\n\tproduct: z.string().optional(),\n\tamount: z.number().int().positive().optional(),\n\tcurrency: z.string().optional(),\n\temail: z.string().optional(),\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n\treferenceId: z.string().optional(),\n\tcallbackURL: z.string().optional(),\n\tquantity: z.number().int().positive().optional(),\n\tscheduleAtPeriodEnd: z.boolean().optional(),\n\tcancelAtPeriodEnd: z.boolean().optional(),\n\tprorateAndCharge: z.boolean().optional(),\n});\n\nexport const initializeTransaction = <P extends string = \"/paystack/initialize-transaction\">(options: AnyPaystackOptions, path: P = \"/paystack/initialize-transaction\" as P) => {\n\tconst subscriptionOptions = options.subscription;\n\t// However, for one-time payments, we might not strictly need subscription middleware\n\t// checking for existing subs, but let's keep it consistent for now.\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"initialize-transaction\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: initializeTransactionBodySchema,\n\t\t\tuse: useMiddlewares,\n\t\t},\n\t\tasync (ctx: any) => {\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\tconst { plan: planName, product: productName, amount: bodyAmount, currency, email, metadata: extraMetadata, callbackURL, quantity, scheduleAtPeriodEnd, cancelAtPeriodEnd, prorateAndCharge } = ctx.body;\n\n\t\t\t// 1. Validate Callback URL validation (same as before)\n\t\t\tif (callbackURL !== undefined && callbackURL !== null && callbackURL !== \"\") {\n\t\t\t\tconst checkTrusted = () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!callbackURL) return false;\n\t\t\t\t\t\tif (callbackURL.startsWith(\"/\")) return true;\n\t\t\t\t\t\tconst baseUrl =\n\t\t\t\t\t\t\t((ctx.context as Record<string, unknown>)?.baseURL as string | undefined) ??\n\t\t\t\t\t\t\t((ctx.request as unknown as { url?: string })?.url) ??\n\t\t\t\t\t\t\t\"\";\n\t\t\t\t\t\tif (!baseUrl) return false;\n\t\t\t\t\t\tconst baseOrigin = new URL(baseUrl).origin;\n\t\t\t\t\t\treturn new URL(callbackURL).origin === baseOrigin;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tif (!checkTrusted()) {\n\t\t\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\t\t\tmessage: \"callbackURL is not a trusted origin.\",\n\t\t\t\t\t\tstatus: 403,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 2. Get User & Session\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\t\t\tconst user = session.user;\n\n\t\t\t// 3. Email Verification Check (only if subscription options enforce it)\n\t\t\tif (subscriptionOptions?.enabled === true && subscriptionOptions.requireEmailVerification === true && !user.emailVerified) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tcode: \"EMAIL_VERIFICATION_REQUIRED\",\n\t\t\t\t\tmessage: PAYSTACK_ERROR_CODES.EMAIL_VERIFICATION_REQUIRED.message,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// 4. Determine Payment Mode: Subscription (Plan) vs Product vs One-Time (Amount)\n\t\t\tlet plan: PaystackPlan | null | undefined;\n\t\t\tlet product: PaystackProduct | InputPaystackProduct | undefined;\n\n\t\t\tif (planName !== undefined && planName !== null && planName !== \"\") {\n\t\t\t\tif (subscriptionOptions?.enabled !== true) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", { message: \"Subscriptions are not enabled.\" });\n\t\t\t\t}\n\t\t\t\tplan = await getPlanByName(options, planName) ?? undefined;\n\t\t\t\tif (!plan) {\n\t\t\t\t\t// Fallback: Check database for synced plans\n\t\t\t\t\tconst nativePlan = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t\t\twhere: [{ field: \"name\", value: planName }],\n\t\t\t\t\t}) as PaystackPlan | null;\n\t\t\t\t\tif (nativePlan) {\n\t\t\t\t\t\tplan = nativePlan;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Try checking by planCode as well\n\t\t\t\t\t\tconst nativePlanByCode = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t\t\t\twhere: [{ field: \"planCode\", value: planName }],\n\t\t\t\t\t\t}) as PaystackPlan | null;\n\t\t\t\t\t\tplan = nativePlanByCode ?? undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!plan) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tcode: \"SUBSCRIPTION_PLAN_NOT_FOUND\",\n\t\t\t\t\t\tmessage: PAYSTACK_ERROR_CODES.SUBSCRIPTION_PLAN_NOT_FOUND.message,\n\t\t\t\t\t\tstatus: 400\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (productName !== undefined && productName !== null && productName !== \"\") {\n\t\t\t\tif (typeof productName === 'string') {\n\t\t\t\t\tproduct ??= await getProductByName(options, productName) ?? undefined;\n\t\t\t\t\t// Fallback: Check database for synced products\n\t\t\t\t\tproduct ??= (await (ctx.context.adapter).findOne({\n\t\t\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\t\t\twhere: [{ field: \"name\", value: productName }],\n\t\t\t\t\t}) as PaystackProduct | null) ?? undefined;\n\t\t\t\t}\n\t\t\t\tif (!product) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: `Product '${productName}' not found.`,\n\t\t\t\t\t\tstatus: 400\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (bodyAmount === undefined || bodyAmount === null || bodyAmount === 0) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Either 'plan', 'product', or 'amount' is required to initialize a transaction.\",\n\t\t\t\t\tstatus: 400\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tlet amount = bodyAmount ?? (product as PaystackProduct | undefined)?.price;\n\t\t\tconst finalCurrency = currency ?? (product as PaystackProduct | undefined)?.currency ?? plan?.currency ?? \"NGN\";\n\n\t\t\tconst referenceIdFromCtx = (ctx.context as Record<string, unknown>).referenceId as string | undefined;\n\t\t\tconst referenceId = (ctx.body.referenceId !== undefined && ctx.body.referenceId !== null && ctx.body.referenceId !== \"\")\n\t\t\t\t? ctx.body.referenceId\n\t\t\t\t: (referenceIdFromCtx !== undefined && referenceIdFromCtx !== null && referenceIdFromCtx !== \"\")\n\t\t\t\t\t? referenceIdFromCtx\n\t\t\t\t\t: (session.user as unknown as { id: string }).id;\n\n\t\t\t// Handle scheduleAtPeriodEnd for existing subscriptions\n\t\t\tif (plan && scheduleAtPeriodEnd === true) {\n\t\t\t\tconst existingSub = await getOrganizationSubscription(ctx, referenceId);\n\t\t\t\tif (existingSub?.status === \"active\") {\n\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\twhere: [{ field: \"id\", value: existingSub.id }],\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tpendingPlan: plan.name,\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\t\tmessage: \"Plan change scheduled at period end.\",\n\t\t\t\t\t\tscheduled: true,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle cancelAtPeriodEnd for existing subscriptions\n\t\t\tif (cancelAtPeriodEnd === true) {\n\t\t\t\tconst existingSub = await getOrganizationSubscription(ctx, referenceId);\n\t\t\t\tif (existingSub?.status === \"active\") {\n\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\twhere: [{ field: \"id\", value: existingSub.id }],\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tcancelAtPeriodEnd: true,\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\t\tmessage: \"Subscription cancellation scheduled at period end.\",\n\t\t\t\t\t\tscheduled: true,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Calculate final amount considering seats if applicable\n\t\t\tif (plan && (plan.seatAmount !== undefined || (plan as any).seatPriceId !== undefined)) {\n\t\t\t\tconst members = await (ctx.context.adapter).findMany({\n\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\twhere: [{ field: \"organizationId\", value: referenceId }],\n\t\t\t\t});\n\t\t\t\tconst seatCount = members.length > 0 ? members.length : 1;\n\t\t\t\tconst quantityToUse = quantity ?? seatCount;\n\t\t\t\tamount = (plan.amount ?? 0) + (quantityToUse * (plan.seatAmount ?? (plan as any).seatPriceId ?? 0));\n\t\t\t}\n\n\t\t\tlet url: string | undefined;\n\t\t\tlet reference: string | undefined;\n\t\t\tlet accessCode: string | undefined;\n\n\t\t\t// Check trial eligibility - prevent trial abuse\n\t\t\tlet trialStart: Date | undefined;\n\t\t\tlet trialEnd: Date | undefined;\n\t\t\tif (plan?.freeTrial?.days !== undefined && plan.freeTrial.days !== null && plan.freeTrial.days > 0) {\n\t\t\t\t// Check if user/referenceId has ever had a trial\n\t\t\t\tconst previousTrials = await (ctx.context.adapter).findMany({\n\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\twhere: [{ field: \"referenceId\", value: referenceId }],\n\t\t\t\t}) as Subscription[];\n\t\t\t\tconst hadTrial = previousTrials?.some(\n\t\t\t\t\t(sub) => (sub.trialStart !== undefined && sub.trialStart !== null) || (sub.trialEnd !== undefined && sub.trialEnd !== null) || sub.status === \"trialing\"\n\t\t\t\t);\n\n\t\t\t\tif (!hadTrial) {\n\t\t\t\t\ttrialStart = new Date();\n\t\t\t\t\ttrialEnd = new Date();\n\t\t\t\t\ttrialEnd.setDate(trialEnd.getDate() + plan.freeTrial.days);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\t// Determine Customer Email & Code (Organization support)\n\t\t\t\tlet targetEmail = (email !== undefined && email !== null && email !== \"\") ? email : user.email;\n\t\t\t\tlet paystackCustomerCode = (user as unknown as { paystackCustomerCode?: string }).paystackCustomerCode;\n\n\t\t\t\tif (options.organization?.enabled === true && referenceId !== undefined && referenceId !== null && referenceId !== \"\" && referenceId !== user.id) {\n\t\t\t\t\tconst org = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\tmodel: \"organization\",\n\t\t\t\t\t\twhere: [{ field: \"id\", value: referenceId }],\n\t\t\t\t\t});\n\t\t\t\t\tif (org !== undefined && org !== null) {\n\t\t\t\t\t\t// Prefer organization's existing Paystack customer code\n\t\t\t\t\t\tif (org.paystackCustomerCode !== undefined && org.paystackCustomerCode !== null && org.paystackCustomerCode !== \"\") {\n\t\t\t\t\t\t\tpaystackCustomerCode = org.paystackCustomerCode;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (org.email !== undefined && org.email !== null && org.email !== \"\") {\n\t\t\t\t\t\t\ttargetEmail = org.email;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Fallback: Use Organization Owner Email\n\t\t\t\t\t\t\tconst ownerMember = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t{ field: \"organizationId\", value: referenceId },\n\t\t\t\t\t\t\t\t\t{ field: \"role\", value: \"owner\" }\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}) as Member | null;\n\n\t\t\t\t\t\t\tif (ownerMember) {\n\t\t\t\t\t\t\t\tconst ownerUser = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: ownerMember.userId }]\n\t\t\t\t\t\t\t\t}) as User | null;\n\n\t\t\t\t\t\t\t\tif (ownerUser?.email !== undefined && ownerUser?.email !== null && ownerUser?.email !== \"\") {\n\t\t\t\t\t\t\t\t\ttargetEmail = ownerUser.email;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Construct Metadata\n\t\t\t\tconst metadata = JSON.stringify({\n\t\t\t\t\treferenceId,\n\t\t\t\t\tuserId: user.id,\n\t\t\t\t\tplan: plan?.name.toLowerCase(), // Undefined for one-time\n\t\t\t\t\tproduct: product?.name.toLowerCase(),\n\t\t\t\t\tisTrial: !!trialStart,\n\t\t\t\t\ttrialEnd: trialEnd?.toISOString(),\n\t\t\t\t\t...extraMetadata,\n\t\t\t\t});\n\n\t\t\t\tconst initBody: Record<string, unknown> & { email?: string; amount?: number; plan?: string; invoice_limit?: number } = {\n\t\t\t\t\temail: targetEmail,\n\t\t\t\t\tcallback_url: callbackURL,\n\t\t\t\t\tmetadata,\n\t\t\t\t\t// If plan/product exists, use its currency; otherwise fallback to provided or default\n\t\t\t\t\tcurrency: finalCurrency,\n\t\t\t\t\tquantity,\n\t\t\t\t};\n\n\t\t\t\t// Sync/Update Customer: ensure email matches if code exists\n\t\t\t\tif (paystackCustomerCode !== undefined && paystackCustomerCode !== null && paystackCustomerCode !== \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst ops = getPaystackOps(options.paystackClient);\n\t\t\t\t\t\t// Only update if email is present\n\t\t\t\t\t\tif (initBody.email !== undefined && initBody.email !== null && initBody.email !== \"\") {\n\t\t\t\t\t\t\tawait ops.customerUpdate(paystackCustomerCode, { email: initBody.email });\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (_e: unknown) {\n\t\t\t\t\t\t// Ignore sync errors\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Handle prorateAndCharge for existing active subscriptions\n\t\t\t\tif (plan && prorateAndCharge === true) {\n\t\t\t\t\tconst existingSub = await getOrganizationSubscription(ctx, referenceId);\n\t\t\t\t\tif (existingSub?.status === \"active\" && existingSub.paystackAuthorizationCode !== null && existingSub.paystackAuthorizationCode !== undefined && existingSub.paystackSubscriptionCode !== null && existingSub.paystackSubscriptionCode !== undefined) {\n\t\t\t\t\t\t// 1. Calculate remaining days\n\t\t\t\t\t\tconst now = new Date();\n\t\t\t\t\t\tconst periodEndLocal = existingSub.periodEnd ? new Date(existingSub.periodEnd) : new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000); // fallback 30 days\n\t\t\t\t\t\tconst periodStartLocal = existingSub.periodStart ? new Date(existingSub.periodStart) : now;\n\n\t\t\t\t\t\tconst totalDays = Math.max(1, Math.ceil((periodEndLocal.getTime() - periodStartLocal.getTime()) / (1000 * 60 * 60 * 24)));\n\t\t\t\t\t\tconst remainingDays = Math.max(0, Math.ceil((periodEndLocal.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)));\n\n\t\t\t\t\t\t// 2. Fetch old plan/amount\n\t\t\t\t\t\tlet oldAmount = 0;\n\t\t\t\t\t\tif (existingSub.plan) {\n\t\t\t\t\t\t\tconst oldPlan = (await getPlanByName(options, existingSub.plan)) ?? (await (ctx.context.adapter).findOne({ model: \"paystackPlan\", where: [{ field: \"name\", value: existingSub.plan }] }) as PaystackPlan | null);\n\t\t\t\t\t\t\tif (oldPlan) {\n\t\t\t\t\t\t\t\tconst oldSeatCount = existingSub.seats ?? 1;\n\t\t\t\t\t\t\t\toldAmount = (oldPlan.amount ?? 0) + (oldSeatCount * (oldPlan.seatAmount ?? (oldPlan as any).seatPriceId ?? 0));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// 3. Calculate new total amount\n\t\t\t\t\t\tlet membersCount = 1;\n\t\t\t\t\t\tif (plan.seatAmount !== undefined || (plan as any).seatPriceId !== undefined) {\n\t\t\t\t\t\t\tconst members = await (ctx.context.adapter).findMany({\n\t\t\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\t\t\twhere: [{ field: \"organizationId\", value: referenceId }],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tmembersCount = members.length > 0 ? members.length : 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst newSeatCount = quantity ?? existingSub.seats ?? membersCount;\n\t\t\t\t\t\tconst newAmount = (plan.amount ?? 0) + (newSeatCount * (plan.seatAmount ?? (plan as any).seatPriceId ?? 0));\n\n\t\t\t\t\t\t// 4. Calculate Difference & Charge\n\t\t\t\t\t\tconst costDifference = newAmount - oldAmount;\n\t\t\t\t\t\tif (costDifference > 0 && remainingDays > 0) {\n\t\t\t\t\t\t\tconst proratedAmount = Math.round((costDifference / totalDays) * remainingDays);\n\t\t\t\t\t\t\t// Ensure minimum Paystack charge limit is met (50 NGN -> 5000)\n\t\t\t\t\t\t\tif (proratedAmount >= 5000) {\n\t\t\t\t\t\t\t\tconst ops = getPaystackOps(options.paystackClient);\n\t\t\t\t\t\t\t\tconst chargeResRaw = await ops.transactionChargeAuthorization({\n\t\t\t\t\t\t\t\t\temail: targetEmail,\n\t\t\t\t\t\t\t\t\tamount: proratedAmount,\n\t\t\t\t\t\t\t\t\tauthorization_code: existingSub.paystackAuthorizationCode,\n\t\t\t\t\t\t\t\t\treference: `prorate_${Date.now()}_${Math.random().toString(36).substring(7)}`,\n\t\t\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\t\t\ttype: \"proration\",\n\t\t\t\t\t\t\t\t\t\treferenceId,\n\t\t\t\t\t\t\t\t\t\tnewPlan: plan.name,\n\t\t\t\t\t\t\t\t\t\toldPlan: existingSub.plan,\n\t\t\t\t\t\t\t\t\t\tremainingDays,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tconst chargeRes = unwrapSdkResult<Record<string, unknown>>(chargeResRaw);\n\n\t\t\t\t\t\t\t\tconst chargeData = chargeRes as any;\n\t\t\t\t\t\t\t\tconst actualStatus = chargeData?.data?.status ?? chargeData?.status;\n\n\t\t\t\t\t\t\t\tif (actualStatus !== \"success\") {\n\t\t\t\t\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", { message: \"Failed to process prorated charge via saved authorization.\" });\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// 5. Update Subscription Future Cycle in Paystack\n\t\t\t\t\t\tconst ops = getPaystackOps(options.paystackClient);\n\t\t\t\t\t\tawait ops.subscriptionUpdate({\n\t\t\t\t\t\t\tcode: existingSub.paystackSubscriptionCode,\n\t\t\t\t\t\t\tamount: newAmount,\n\t\t\t\t\t\t\tplan: plan.planCode,\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// 6. Update Local DB\n\t\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\twhere: [{ field: \"id\", value: existingSub.id }],\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tplan: plan.name,\n\t\t\t\t\t\t\t\tseats: newSeatCount,\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\t\t\tmessage: \"Subscription successfully upgraded with prorated charge.\",\n\t\t\t\t\t\t\tprorated: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (plan) {\n\t\t\t\t\t// Subscription Flow\n\t\t\t\t\tif (trialStart) {\n\t\t\t\t\t\t// Trial Flow: Authorize card with minimum amount, don't start sub yet\n\t\t\t\t\t\tinitBody.amount = 5000; // 50 NGN (minimum allowed)\n\t\t\t\t\t\t// Do NOT set initBody.plan\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Standard Flow\n\t\t\t\t\t\tinitBody.plan = plan.planCode;\n\t\t\t\t\t\tinitBody.invoice_limit = plan.invoiceLimit;\n\t\t\t\t\t\t// Paystack requires amount even with planCode (it uses plan's stored amount)\n\t\t\t\t\t\t// For local plans without planCode, use finalAmount; for planCode plans, use plan.amount or override\n\t\t\t\t\t\tlet finalAmount: number;\n\t\t\t\t\t\tif (amount !== undefined && amount !== null) {\n\t\t\t\t\t\t\t// amount was calculated via seat-based logic or provided as override\n\t\t\t\t\t\t\tfinalAmount = amount;\n\t\t\t\t\t\t\t// We force quantity to 1 in the Paystack call because our amount already includes the quantity multiplier\n\t\t\t\t\t\t\tinitBody.quantity = 1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Standard Flow: Plan Price * Quantity\n\t\t\t\t\t\t\tfinalAmount = (plan.amount ?? 50000) * (quantity ?? 1);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tinitBody.amount = Math.max(Math.round(finalAmount), 50000);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// One-Time Payment Flow\n\t\t\t\t\tif (amount === undefined || amount === null || amount === 0) throw new APIError(\"BAD_REQUEST\", { message: \"Amount is required for one-time payments\" });\n\t\t\t\t\tinitBody.amount = Math.round(amount);\n\t\t\t\t}\n\n\t\t\t\tconst initRaw = await paystack.transactionInitialize(initBody as unknown as Parameters<typeof paystack.transactionInitialize>[0]);\n\t\t\t\tconst initRes = unwrapSdkResult<Record<string, unknown>>(initRaw);\n\t\t\t\tlet data =\n\t\t\t\t\t(initRes !== undefined && initRes !== null && typeof initRes === \"object\" && \"status\" in initRes && \"data\" in initRes)\n\t\t\t\t\t\t? (initRes).data\n\t\t\t\t\t\t: (initRes as Record<string, unknown> | undefined)?.data ?? initRes;\n\n\t\t\t\tif (data !== undefined && data !== null && typeof data === \"object\" && \"status\" in data && \"data\" in data) {\n\t\t\t\t\tdata = (data as Record<string, unknown>).data;\n\t\t\t\t}\n\t\t\t\turl = (data as Record<string, unknown>)?.authorization_url as string | undefined;\n\t\t\t\treference = (data as Record<string, unknown>)?.reference as string | undefined;\n\t\t\t\taccessCode = (data as Record<string, unknown>)?.access_code as string | undefined;\n\t\t\t} catch (error: unknown) {\n\t\t\t\t(ctx as unknown as { context: { logger: { error: (msg: string, err: unknown) => void } } }).context.logger.error(\"Failed to initialize Paystack transaction\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tcode: \"FAILED_TO_INITIALIZE_TRANSACTION\",\n\t\t\t\t\tmessage: (error as Error)?.message ?? PAYSTACK_ERROR_CODES.FAILED_TO_INITIALIZE_TRANSACTION.message,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// 6. Record Transaction & Subscription\n\t\t\tawait (ctx.context.adapter).create({\n\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\tdata: {\n\t\t\t\t\treference: reference!,\n\t\t\t\t\treferenceId,\n\t\t\t\t\tuserId: user.id,\n\t\t\t\t\tamount: amount ?? 0,\n\t\t\t\t\tcurrency: plan?.currency ?? currency ?? \"NGN\",\n\t\t\t\t\tstatus: \"pending\",\n\t\t\t\t\tplan: plan?.name.toLowerCase(),\n\t\t\t\t\tproduct: product?.name.toLowerCase(),\n\t\t\t\t\tmetadata: (extraMetadata !== undefined && extraMetadata !== null) ? JSON.stringify(extraMetadata) : undefined,\n\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (plan !== undefined && plan !== null) {\n\t\t\t\t// Re-fetch customer code if it wasn't available before (though we didn't force-create it here)\n\t\t\t\t// For now, use what we have (user's or org's)\n\t\t\t\tlet storedCustomerCode = (user as unknown as { paystackCustomerCode?: string }).paystackCustomerCode;\n\t\t\t\tif (options.organization?.enabled === true && referenceId !== user.id) {\n\t\t\t\t\tconst org = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\tmodel: \"organization\",\n\t\t\t\t\t\twhere: [{ field: \"id\", value: referenceId }],\n\t\t\t\t\t});\n\t\t\t\t\tif (org?.paystackCustomerCode !== undefined && org?.paystackCustomerCode !== null && org.paystackCustomerCode !== \"\") {\n\t\t\t\t\t\tstoredCustomerCode = org.paystackCustomerCode;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst newSubscription = await (ctx.context.adapter).create({\n\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tplan: plan.name.toLowerCase(),\n\t\t\t\t\t\treferenceId,\n\t\t\t\t\t\tpaystackCustomerCode: storedCustomerCode,\n\t\t\t\t\t\tpaystackTransactionReference: reference,\n\t\t\t\t\t\tstatus: (trialStart !== undefined && trialStart !== null) ? \"trialing\" : \"incomplete\",\n\t\t\t\t\t\tseats: quantity,\n\t\t\t\t\t\ttrialStart,\n\t\t\t\t\t\ttrialEnd,\n\t\t\t\t\t},\n\t\t\t\t}) as Subscription | null;\n\n\t\t\t\t// Call trial start hook if trial was granted\n\t\t\t\tif ((trialStart !== undefined && trialStart !== null) && newSubscription !== null && plan.freeTrial?.onTrialStart !== undefined && plan.freeTrial?.onTrialStart !== null) {\n\t\t\t\t\tawait plan.freeTrial.onTrialStart(newSubscription);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ctx.json({\n\t\t\t\turl,\n\t\t\t\treference,\n\t\t\t\taccessCode,\n\t\t\t\tredirect: true,\n\t\t\t});\n\t\t},\n\t);\n};\n\n// Aliases for Client DX Parity\nexport const createSubscription = (options: AnyPaystackOptions) =>\n\tinitializeTransaction(options, \"/paystack/create-subscription\");\nexport const upgradeSubscription = (options: AnyPaystackOptions) =>\n\tinitializeTransaction(options, \"/paystack/upgrade-subscription\");\nexport const restoreSubscription = (options: AnyPaystackOptions) => {\n\t// Alias for enable\n\treturn enablePaystackSubscription(options, \"/paystack/restore-subscription\");\n};\nexport const cancelSubscription = (options: AnyPaystackOptions) => {\n\t// Alias for disable\n\treturn disablePaystackSubscription(options, \"/paystack/cancel-subscription\");\n};\n\n\nexport const verifyTransaction = <P extends string = \"/paystack/verify-transaction\">(options: AnyPaystackOptions, path: P = \"/paystack/verify-transaction\" as P) => {\n\tconst verifyBodySchema = z.object({\n\t\treference: z.string(),\n\t});\n\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"verify-transaction\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: verifyBodySchema,\n\t\t\tuse: useMiddlewares,\n\t\t},\n\t\tasync (ctx: any) => {\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\tlet verifyRes: unknown;\n\t\t\ttry {\n\t\t\t\tconst verifyRaw = await paystack.transactionVerify(ctx.body.reference);\n\t\t\t\tverifyRes = unwrapSdkResult<Record<string, unknown>>(verifyRaw);\n\t\t\t} catch (error: unknown) {\n\t\t\t\tctx.context.logger.error(\"Failed to verify Paystack transaction\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tcode: \"FAILED_TO_VERIFY_TRANSACTION\",\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t(error as Error)?.message ?? PAYSTACK_ERROR_CODES.FAILED_TO_VERIFY_TRANSACTION.message,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst data = unwrapSdkResult<Record<string, unknown>>(verifyRes);\n\t\t\tconst status = (data)?.status as string | undefined;\n\t\t\tconst reference = ((data)?.reference as string | undefined) ?? ctx.body.reference;\n\t\t\tconst paystackId = (data)?.id !== undefined && (data)?.id !== null ? String((data as { id: string | number }).id) : undefined;\n\t\t\tconst authorizationCode = ((data)?.authorization as Record<string, unknown>)?.authorization_code as string | undefined;\n\n\t\t\tif (status === \"success\") {\n\t\t\t\tconst session = await getSessionFromCtx(ctx);\n\n\t\t\t\t// Get the local transaction record to know the intended referenceId (Org or User)\n\t\t\t\tconst txRecord = await (ctx.context.adapter).findOne({\n\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t}) as (Record<string, unknown> & { referenceId?: string }) | null;\n\n\t\t\t\t// Trust the referenceId from the record, fallback to session user if missing\n\t\t\t\tconst referenceId = txRecord?.referenceId ?? (session?.user as unknown as { id: string })?.id;\n\n\t\t\t\t// Authorization check: ensure the current user has access to this referenceId\n\t\t\t\tif (session !== null && session !== undefined && referenceId !== session.user.id) {\n\t\t\t\t\tconst authRef = (subscriptionOptions as unknown as { authorizeReference: (data: unknown, ctx: unknown) => Promise<boolean> })?.authorizeReference;\n\t\t\t\t\tlet authorized = false;\n\t\t\t\t\tif (authRef !== undefined && authRef !== null) {\n\t\t\t\t\t\tauthorized = await authRef({\n\t\t\t\t\t\t\tuser: session.user,\n\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\treferenceId,\n\t\t\t\t\t\t\taction: \"verify-transaction\"\n\t\t\t\t\t\t}, ctx);\n\t\t\t\t\t} else if (options.organization?.enabled === true) {\n\t\t\t\t\t\tconst member = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t{ field: \"userId\", value: session.user.id },\n\t\t\t\t\t\t\t\t{ field: \"organizationId\", value: referenceId }\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}) as Member | null;\n\t\t\t\t\t\tif (member !== null && member !== undefined) authorized = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!authorized) {\n\t\t\t\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\ttry {\n\n\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\t\t\tpaystackId,\n\t\t\t\t\t\t\t// Update with actual amount/currency from Paystack (for planCode subscriptions)\n\t\t\t\t\t\t\t...((data)?.amount !== undefined && (data)?.amount !== null ? { amount: (data).amount } : {}),\n\t\t\t\t\t\t\t...((data)?.currency !== undefined && (data)?.currency !== null ? { currency: (data).currency } : {}),\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t});\n\n\t\t\t\t\tconst customer = (data)?.customer;\n\t\t\t\t\tconst paystackCustomerCodeFromPaystack = (customer !== undefined && customer !== null && typeof customer === \"object\")\n\t\t\t\t\t\t? (customer as Record<string, unknown>).customer_code as string | undefined\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\tif (paystackCustomerCodeFromPaystack !== undefined && paystackCustomerCodeFromPaystack !== null && paystackCustomerCodeFromPaystack !== \"\" && referenceId !== undefined && referenceId !== null && referenceId !== \"\") {\n\t\t\t\t\t\tconst isOrg = options.organization?.enabled === true && ((referenceId.startsWith(\"org_\")) || (await ctx.context.adapter.findOne({ model: \"organization\", where: [{ field: \"id\", value: referenceId }] }) !== null));\n\n\t\t\t\t\t\tif (isOrg === true) {\n\t\t\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\t\t\tmodel: \"organization\",\n\t\t\t\t\t\t\t\tupdate: { paystackCustomerCode: paystackCustomerCodeFromPaystack },\n\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: referenceId }],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\tupdate: { paystackCustomerCode: paystackCustomerCodeFromPaystack },\n\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: referenceId }],\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Decrement product quantity if applicable\n\t\t\t\t\tconst transaction = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t}) as PaystackTransaction | null;\n\t\t\t\t\tif (transaction?.product) {\n\t\t\t\t\t\tawait syncProductQuantityFromPaystack(ctx, transaction.product, options.paystackClient);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Check for trial activation\n\t\t\t\t\tlet isTrial = false;\n\t\t\t\t\tlet trialEnd: string | undefined;\n\t\t\t\t\tlet targetPlan: string | undefined;\n\n\t\t\t\t\tif ((data)?.metadata !== undefined && (data)?.metadata !== null) {\n\t\t\t\t\t\tconst metaRaw = (data).metadata;\n\t\t\t\t\t\tconst meta = typeof metaRaw === \"string\" ? JSON.parse(metaRaw) : metaRaw as Record<string, unknown>;\n\t\t\t\t\t\tisTrial = meta.isTrial === true || meta.isTrial === \"true\";\n\n\t\t\t\t\t\ttrialEnd = meta.trialEnd as string | undefined;\n\n\t\t\t\t\t\ttargetPlan = meta.plan as string | undefined;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet paystackSubscriptionCode: string | undefined;\n\n\t\t\t\t\tif (isTrial === true && (targetPlan !== undefined && targetPlan !== null && targetPlan !== \"\") && (trialEnd !== undefined && trialEnd !== null && trialEnd !== \"\")) {\n\t\t\t\t\t\t// Trial Flow: Create subscription with future start date using auth code\n\t\t\t\t\t\tconst email = ((data)?.customer as Record<string, unknown>)?.email as string | undefined;\n\n\t\t\t\t\t\t// We need the planCode. We have the plan NAME in metadata (lowercased).\n\t\t\t\t\t\tconst plans = await getPlans(subscriptionOptions);\n\t\t\t\t\t\tconst planConfig = plans.find(p => p.name.toLowerCase() === targetPlan?.toLowerCase());\n\n\t\t\t\t\t\t// For local plans (no planCode), generate a local subscription code\n\t\t\t\t\t\tif (planConfig !== undefined && (planConfig.planCode === undefined || planConfig.planCode === null || planConfig.planCode === \"\")) {\n\t\t\t\t\t\t\tpaystackSubscriptionCode = `LOC_${reference}`;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ((authorizationCode !== undefined && authorizationCode !== null && authorizationCode !== \"\") && (email !== undefined && email !== null && email !== \"\") && (planConfig?.planCode !== undefined && planConfig?.planCode !== null && planConfig?.planCode !== \"\")) {\n\t\t\t\t\t\t\tconst subRes = await paystack.subscriptionCreate({\n\t\t\t\t\t\t\t\tcustomer: email,\n\t\t\t\t\t\t\t\tplan: planConfig.planCode,\n\t\t\t\t\t\t\t\tauthorization: authorizationCode,\n\t\t\t\t\t\t\t\tstart_date: trialEnd\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst subData = unwrapSdkResult<Record<string, unknown>>(subRes);\n\t\t\t\t\t\t\tconst cleanSubData = (subData as { data?: Record<string, unknown> })?.data ?? subData;\n\n\t\t\t\t\t\t\tpaystackSubscriptionCode = (cleanSubData)?.subscription_code as string | undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (isTrial !== true) {\n\t\t\t\t\t\tconst planFromPaystack = (data)?.plan as Record<string, unknown> | undefined;\n\t\t\t\t\t\tconst planCodeFromPaystack = planFromPaystack?.plan_code as string | undefined;\n\n\t\t\t\t\t\tif (planCodeFromPaystack === undefined || planCodeFromPaystack === null || planCodeFromPaystack === \"\") {\n\t\t\t\t\t\t\t// Local Plan\n\t\t\t\t\t\t\tpaystackSubscriptionCode = `LOC_${reference}`;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Native Paystack subscription (if created during charge)\n\t\t\t\t\t\t\tpaystackSubscriptionCode = ((data)?.subscription as Record<string, unknown> | undefined)?.subscription_code as string | undefined;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\n\t\t\t\t\tconst existingSubs = await (ctx.context.adapter).findMany({\n\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\twhere: [{ field: \"paystackTransactionReference\", value: reference }],\n\t\t\t\t\t}) as Subscription[];\n\t\t\t\t\tlet targetSub: Subscription | undefined;\n\t\t\t\t\tif (existingSubs && existingSubs.length > 0) {\n\t\t\t\t\t\ttargetSub = existingSubs.find(s =>\n\t\t\t\t\t\t\t!(referenceId !== undefined && referenceId !== null && referenceId !== \"\") || s.referenceId === referenceId\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tlet updatedSubscription: Subscription | null = null;\n\t\t\t\t\tif (targetSub !== undefined && targetSub !== null) {\n\t\t\t\t\t\tupdatedSubscription = await (ctx.context.adapter).update({\n\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tstatus: isTrial === true ? \"trialing\" : \"active\",\n\t\t\t\t\t\t\t\tperiodStart: new Date(),\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t\t...(isTrial === true && (trialEnd !== undefined && trialEnd !== null && trialEnd !== \"\") ? {\n\t\t\t\t\t\t\t\t\ttrialStart: new Date(),\n\t\t\t\t\t\t\t\t\ttrialEnd: new Date(trialEnd),\n\t\t\t\t\t\t\t\t\tperiodEnd: new Date(trialEnd),\n\t\t\t\t\t\t\t\t} : {}),\n\t\t\t\t\t\t\t\t...(paystackSubscriptionCode !== undefined && paystackSubscriptionCode !== null && paystackSubscriptionCode !== \"\" ? { paystackSubscriptionCode } : {}),\n\t\t\t\t\t\t\t\t...(authorizationCode !== undefined && authorizationCode !== null && authorizationCode !== \"\" ? { paystackAuthorizationCode: authorizationCode } : {}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\twhere: [{ field: \"id\", value: targetSub.id }],\n\t\t\t\t\t\t}) as Subscription | null;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (updatedSubscription && subscriptionOptions?.enabled === true && \"onSubscriptionComplete\" in subscriptionOptions && typeof (subscriptionOptions as unknown as Record<string, unknown>).onSubscriptionComplete === \"function\") {\n\t\t\t\t\t\tconst subOpts = subscriptionOptions;\n\t\t\t\t\t\tconst plans = await getPlans(subOpts);\n\t\t\t\t\t\tconst plan = plans.find(p => p.name.toLowerCase() === updatedSubscription.plan.toLowerCase());\n\t\t\t\t\t\tif (plan) {\n\t\t\t\t\t\t\tawait (subscriptionOptions as unknown as { onSubscriptionComplete: (data: unknown, ctx: unknown) => Promise<void> }).onSubscriptionComplete({\n\t\t\t\t\t\t\t\tevent: data,\n\t\t\t\t\t\t\t\tsubscription: updatedSubscription,\n\t\t\t\t\t\t\t\tplan\n\t\t\t\t\t\t\t}, ctx);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (e: unknown) {\n\t\t\t\t\tctx.context.logger.error(\n\t\t\t\t\t\t\"Failed to update transaction/subscription after verification\",\n\t\t\t\t\t\te,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (status === \"failed\" || status === \"abandoned\") {\n\t\t\t\ttry {\n\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tstatus,\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\twhere: [{ field: \"reference\", value: reference }],\n\t\t\t\t\t});\n\t\t\t\t} catch (e: unknown) {\n\t\t\t\t\tctx.context.logger.error(\"Failed to update transaction status\", e);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn ctx.json({\n\t\t\t\tstatus,\n\t\t\t\treference,\n\t\t\t\tdata,\n\t\t\t});\n\t\t},\n\t);\n};\n\nexport const listSubscriptions = (options: AnyPaystackOptions) => {\n\tconst listQuerySchema = z.object({\n\t\treferenceId: z.string().optional(),\n\t});\n\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"list-subscriptions\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\t\"/paystack/list-subscriptions\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: listQuerySchema,\n\t\t\tuse: useMiddlewares,\n\t\t},\n\t\tasync (ctx: any) => {\n\t\t\tif (subscriptionOptions?.enabled !== true) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Subscriptions are not enabled in the Paystack options.\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\t\t\tconst referenceIdPart = (ctx.context as Record<string, unknown>).referenceId as string | undefined;\n\t\t\tconst queryRefId = ctx.query?.referenceId;\n\t\t\tconst referenceId = (referenceIdPart !== undefined && referenceIdPart !== null && referenceIdPart !== \"\")\n\t\t\t\t? referenceIdPart\n\t\t\t\t: (queryRefId !== undefined && queryRefId !== null && queryRefId !== \"\")\n\t\t\t\t\t? queryRefId\n\t\t\t\t\t: (session.user as unknown as { id: string }).id;\n\t\t\tconst res = await (ctx.context.adapter).findMany({\n\t\t\t\tmodel: \"subscription\",\n\t\t\t\twhere: [{ field: \"referenceId\", value: referenceId }],\n\t\t\t}) as Subscription[];\n\t\t\treturn ctx.json({ subscriptions: res });\n\t\t},\n\t);\n};\n\nexport const listTransactions = <P extends string = \"/paystack/list-transactions\">(options: AnyPaystackOptions, path: P = \"/paystack/list-transactions\" as P) => {\n\tconst listQuerySchema = z.object({\n\t\treferenceId: z.string().optional(),\n\t});\n\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"list-transactions\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: listQuerySchema,\n\t\t\tuse: useMiddlewares,\n\t\t},\n\t\tasync (ctx: any) => {\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tif (!session) throw new APIError(\"UNAUTHORIZED\");\n\t\t\tconst referenceId =\n\t\t\t\t((ctx.context as Record<string, unknown>).referenceId as string | undefined) ??\n\t\t\t\t(ctx.query?.referenceId) ??\n\t\t\t\t((session.user as unknown as { id: string }).id);\n\t\t\tconst res = await (ctx.context.adapter).findMany({\n\t\t\t\tmodel: \"paystackTransaction\",\n\t\t\t\twhere: [{ field: \"referenceId\", value: referenceId }],\n\t\t\t}) as PaystackTransaction[];\n\t\t\t// Sort by createdAt desc locally if adapter doesn't support it well, \n\t\t\t// but Better Auth adapters usually return in insertion order.\n\t\t\t// Let's sort to be sure.\n\t\t\tconst sorted = res.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());\n\t\t\treturn ctx.json({ transactions: sorted });\n\t\t},\n\t);\n};\n\nconst enableDisableBodySchema = z.object({\n\treferenceId: z.string().optional(),\n\tsubscriptionCode: z.string(),\n\temailToken: z.string().optional(),\n\tatPeriodEnd: z.boolean().optional(),\n});\n\nfunction decodeBase64UrlToString(value: string): string {\n\tconst normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n\tconst padded = normalized + \"===\".slice((normalized.length + 3) % 4);\n\tif (typeof (globalThis as unknown as { atob: unknown }).atob === \"function\") {\n\t\treturn ((globalThis as unknown as { atob: (v: string) => string }).atob)(padded);\n\t}\n\t// eslint-disable-next-line no-restricted-globals\n\treturn Buffer.from(padded, \"base64\").toString(\"utf8\");\n}\n\nfunction tryGetEmailTokenFromSubscriptionManageLink(link: string): string | undefined {\n\ttry {\n\t\tconst url = new URL(link);\n\t\tconst subscriptionToken = url.searchParams.get(\"subscription_token\");\n\t\tif (subscriptionToken === undefined || subscriptionToken === null || subscriptionToken === \"\") return undefined;\n\t\tconst parts = subscriptionToken.split(\".\");\n\t\tif (parts.length < 2) return undefined;\n\t\tconst payloadJson = decodeBase64UrlToString(parts[1]);\n\t\tconst payload = JSON.parse(payloadJson);\n\t\treturn typeof payload?.email_token === \"string\" ? payload.email_token : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport const disablePaystackSubscription = <P extends string = \"/paystack/disable-subscription\">(options: AnyPaystackOptions, path: P = \"/paystack/disable-subscription\" as P) => {\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"disable-subscription\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{ method: \"POST\", body: enableDisableBodySchema, use: useMiddlewares },\n\t\tasync (ctx: any) => {\n\t\t\tconst { subscriptionCode, atPeriodEnd } = ctx.body;\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\ttry {\n\t\t\t\tif (subscriptionCode.startsWith(\"LOC_\")) {\n\t\t\t\t\tconst sub = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\twhere: [{ field: \"paystackSubscriptionCode\", value: subscriptionCode }],\n\t\t\t\t\t}) as Subscription | null;\n\n\t\t\t\t\tif (sub) {\n\t\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tstatus: atPeriodEnd === false ? \"canceled\" : \"active\",\n\t\t\t\t\t\t\t\tcancelAtPeriodEnd: atPeriodEnd !== false,\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\twhere: [{ field: \"id\", value: sub.id }],\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn ctx.json({ status: \"success\" });\n\t\t\t\t\t}\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", { message: \"Subscription not found\" });\n\t\t\t\t}\n\n\t\t\t\tlet emailToken = ctx.body.emailToken;\n\t\t\t\tlet nextPaymentDate: string | undefined;\n\n\t\t\t\t// Always fetch subscription to get next_payment_date even if we have emailToken (unless passed? no, next_payment_date comes from paystack)\n\t\t\t\t// We need next_payment_date for cancelAtPeriodEnd logic\n\t\t\t\ttry {\n\t\t\t\t\tconst raw = await paystack.subscriptionFetch(subscriptionCode);\n\t\t\t\t\tconst fetchRes = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t\tconst data =\n\t\t\t\t\t\tfetchRes !== null && fetchRes !== undefined && typeof fetchRes === \"object\" && \"status\" in fetchRes && \"data\" in fetchRes\n\t\t\t\t\t\t\t? (fetchRes).data\n\t\t\t\t\t\t\t: fetchRes?.data !== undefined ? fetchRes.data : fetchRes;\n\n\t\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\t\temailToken = (data as Record<string, unknown>)?.email_token as string | undefined;\n\t\t\t\t\t}\n\t\t\t\t\tnextPaymentDate = (data as Record<string, unknown>)?.next_payment_date as string | undefined;\n\t\t\t\t} catch {\n\t\t\t\t\t// ignore fetch failure? If we can't fetch, we might miss next_payment_date.\n\t\t\t\t}\n\n\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst raw = await paystack.subscriptionManageLink(subscriptionCode);\n\t\t\t\t\t\tconst linkRes = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t\t\tconst data =\n\t\t\t\t\t\t\tlinkRes !== null && linkRes !== undefined && typeof linkRes === \"object\" && \"status\" in linkRes && \"data\" in linkRes\n\t\t\t\t\t\t\t\t? (linkRes).data\n\t\t\t\t\t\t\t\t: linkRes?.data !== undefined ? linkRes.data : linkRes;\n\t\t\t\t\t\tconst link = typeof data === \"string\" ? data : (data as Record<string, unknown>)?.link as string | undefined;\n\n\t\t\t\t\t\tif (link !== undefined && link !== null && link !== \"\") {\n\t\t\t\t\t\t\temailToken = tryGetEmailTokenFromSubscriptionManageLink(link);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\tthrow new Error(\"Could not retrieve email_token for subscription disable.\");\n\t\t\t\t}\n\n\t\t\t\tawait paystack.subscriptionDisable({ code: subscriptionCode, token: emailToken });\n\n\t\t\t\t// Implement Cancel at Period End logic\n\t\t\t\t// Paystack \"disable\" stops future charges.\n\t\t\t\t// We keep status as \"active\" but set cancelAtPeriodEnd = true\n\n\t\t\t\t// Duplicate removed\n\n\t\t\t\tconst periodEnd = (nextPaymentDate !== undefined && nextPaymentDate !== null && nextPaymentDate !== \"\") ? new Date(nextPaymentDate) : undefined;\n\n\t\t\t\tconst sub = await (ctx.context.adapter).findOne({\n\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\twhere: [{ field: \"paystackSubscriptionCode\", value: subscriptionCode }],\n\t\t\t\t}) as Subscription | null;\n\n\t\t\t\tif (sub) {\n\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tstatus: atPeriodEnd === false ? \"canceled\" : \"active\",\n\t\t\t\t\t\t\tcancelAtPeriodEnd: atPeriodEnd !== false,\n\t\t\t\t\t\t\tperiodEnd,\n\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t},\n\t\t\t\t\t\twhere: [{ field: \"id\", value: sub.id }],\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t// This is unexpected if we are disabling a subscription that should exist\n\t\t\t\t\tctx.context.logger.warn(`Could not find subscription with code ${subscriptionCode} to disable`);\n\t\t\t\t}\n\n\t\t\t\treturn ctx.json({ status: \"success\" });\n\t\t\t} catch (error: unknown) {\n\t\t\t\t(ctx as unknown as { context: { logger: { error: (msg: string, err: unknown) => void } } }).context.logger.error(\"Failed to disable subscription\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tcode: \"FAILED_TO_DISABLE_SUBSCRIPTION\",\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t(error as Error)?.message ?? PAYSTACK_ERROR_CODES.FAILED_TO_DISABLE_SUBSCRIPTION.message,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n};\n\nexport const enablePaystackSubscription = <P extends string = \"/paystack/enable-subscription\">(options: AnyPaystackOptions, path: P = \"/paystack/enable-subscription\" as P) => {\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"enable-subscription\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{ method: \"POST\", body: enableDisableBodySchema, use: useMiddlewares },\n\t\tasync (ctx: any) => {\n\t\t\tconst { subscriptionCode } = ctx.body;\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\ttry {\n\t\t\t\tlet emailToken = ctx.body.emailToken;\n\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst raw = await paystack.subscriptionFetch(subscriptionCode);\n\t\t\t\t\t\tconst fetchRes = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t\t\tconst data =\n\t\t\t\t\t\t\tfetchRes !== null && fetchRes !== undefined && typeof fetchRes === \"object\" && \"status\" in fetchRes && \"data\" in fetchRes\n\t\t\t\t\t\t\t\t? (fetchRes).data\n\t\t\t\t\t\t\t\t: fetchRes?.data !== undefined ? fetchRes.data : fetchRes;\n\t\t\t\t\t\temailToken = (data as Record<string, unknown>)?.email_token as string | undefined;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore; try manage-link fallback below\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst raw = await paystack.subscriptionManageLink(subscriptionCode);\n\t\t\t\t\t\tconst linkRes = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t\t\tconst data =\n\t\t\t\t\t\t\tlinkRes !== null && linkRes !== undefined && \"status\" in linkRes && \"data\" in linkRes\n\t\t\t\t\t\t\t\t? (linkRes).data\n\t\t\t\t\t\t\t\t: linkRes?.data !== undefined ? linkRes.data : linkRes;\n\t\t\t\t\t\tconst link = typeof data === \"string\" ? data : (data as Record<string, unknown>)?.link as string | undefined;\n\n\t\t\t\t\t\tif (link !== undefined && link !== null && link !== \"\") {\n\t\t\t\t\t\t\temailToken = tryGetEmailTokenFromSubscriptionManageLink(link);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// ignore\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (emailToken === undefined || emailToken === null || emailToken === \"\") {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", { message: \"Could not retrieve email_token for subscription enable.\" });\n\t\t\t\t}\n\n\t\t\t\tawait paystack.subscriptionEnable({ code: subscriptionCode, token: emailToken });\n\n\t\t\t\t// Update local status immediately\n\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tstatus: \"active\",\n\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t},\n\t\t\t\t\twhere: [{ field: \"paystackSubscriptionCode\", value: subscriptionCode }],\n\t\t\t\t});\n\n\t\t\t\treturn ctx.json({ status: \"success\" });\n\t\t\t} catch (error: unknown) {\n\t\t\t\tctx.context.logger.error(\"Failed to enable subscription\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tcode: \"FAILED_TO_ENABLE_SUBSCRIPTION\",\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t(error as Error)?.message ?? PAYSTACK_ERROR_CODES.FAILED_TO_ENABLE_SUBSCRIPTION.message,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n};\n\nexport const getSubscriptionManageLink = <P extends string = \"/paystack/get-subscription-manage-link\">(options: AnyPaystackOptions, path: P = \"/paystack/get-subscription-manage-link\" as P) => {\n\tconst manageLinkQuerySchema = z.object({\n\t\tsubscriptionCode: z.string(),\n\t});\n\tconst subscriptionOptions = options.subscription;\n\tconst useMiddlewares = subscriptionOptions?.enabled === true\n\t\t? [sessionMiddleware, originCheck, referenceMiddleware(options, \"get-subscription-manage-link\")]\n\t\t: [sessionMiddleware, originCheck];\n\n\tconst handler = async (ctx: any) => {\n\t\tconst { subscriptionCode } = ctx.query;\n\n\t\t// If it's a local mock subscription, return null link instead of error\n\t\tif (subscriptionCode.startsWith(\"LOC_\") || subscriptionCode.startsWith(\"sub_local_\")) {\n\t\t\treturn ctx.json({ link: null, message: \"Local subscriptions cannot be managed on Paystack\" });\n\t\t}\n\n\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\ttry {\n\t\t\tconst raw = await paystack.subscriptionManageLink(subscriptionCode);\n\t\t\tconst res = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\tconst data =\n\t\t\t\t(res !== null && res !== undefined && typeof res === \"object\" && \"status\" in res && \"data\" in res)\n\t\t\t\t\t? (res).data\n\t\t\t\t\t: res?.data !== undefined ? res.data : res;\n\n\t\t\tconst link = typeof data === \"string\" ? data : (data as Record<string, unknown>)?.link as string | undefined;\n\n\t\t\treturn ctx.json({ link });\n\t\t} catch (error: unknown) {\n\t\t\tctx.context.logger.error(\"Failed to get subscription manage link\", error);\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: (error as Error)?.message ?? \"Failed to get subscription manage link\",\n\t\t\t});\n\t\t}\n\t};\n\n\treturn createAuthEndpoint(\n\t\tpath,\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tquery: manageLinkQuerySchema,\n\t\t\tuse: useMiddlewares,\n\t\t},\n\t\thandler,\n\t);\n};\n\nexport const syncProducts = (options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/sync-products\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t},\n\t\t\tdisableBody: true,\n\t\t\tuse: [sessionMiddleware],\n\t\t},\n\t\tasync (ctx: any) => {\n\t\t\tconsole.error(\"DEBUG: syncProducts endpoint hit!\");\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\ttry {\n\t\t\t\tconst raw = await paystack.productList();\n\t\t\t\tconst res = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\tconst productsData = (res !== null && typeof res === \"object\" && \"status\" in res && \"data\" in res) ? (res as Record<string, any>).data : (res as Record<string, any>)?.data ?? res;\n\n\t\t\t\tif (!Array.isArray(productsData)) {\n\t\t\t\t\treturn ctx.json({ status: \"success\", count: 0 });\n\t\t\t\t}\n\n\t\t\t\tfor (const product of productsData) {\n\t\t\t\t\tconst paystackId = String(product.id);\n\t\t\t\t\tconst existing = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\t\t\twhere: [{ field: \"paystackId\", value: paystackId }],\n\t\t\t\t\t}) as PaystackProduct | null;\n\n\t\t\t\t\tconst productData = {\n\t\t\t\t\t\tname: product.name,\n\t\t\t\t\t\tdescription: product.description,\n\t\t\t\t\t\tprice: product.price,\n\t\t\t\t\t\tcurrency: product.currency,\n\t\t\t\t\t\tquantity: product.quantity,\n\t\t\t\t\t\tunlimited: product.unlimited,\n\t\t\t\t\t\tpaystackId,\n\t\t\t\t\t\tslug: product.slug ?? product.name.toLowerCase().replace(/\\s+/g, \"-\"),\n\t\t\t\t\t\tmetadata: product.metadata ? JSON.stringify(product.metadata) : undefined,\n\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t};\n\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\t\t\t\tupdate: productData,\n\t\t\t\t\t\t\twhere: [{ field: \"id\", value: existing.id }],\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait (ctx.context.adapter).create({\n\t\t\t\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t...productData,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ctx.json({ status: \"success\", count: productsData.length });\n\t\t\t} catch (error: unknown) {\n\t\t\t\tctx.context.logger.error(\"Failed to sync products\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: (error as Error)?.message ?? \"Failed to sync products\",\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n};\n\nexport const listProducts = (_options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/list-products\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"listPaystackProducts\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx: any) => {\n\t\t\tconst res = await (ctx.context.adapter).findMany({\n\t\t\t\tmodel: \"paystackProduct\",\n\t\t\t}) as PaystackProduct[];\n\t\t\tconst sorted = res.sort((a, b) => a.name.localeCompare(b.name));\n\t\t\treturn ctx.json({ products: sorted });\n\t\t}\n\t);\n};\n\nexport const syncPlans = (options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/sync-plans\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t},\n\t\t\tdisableBody: true,\n\t\t\tuse: [sessionMiddleware],\n\t\t},\n\t\tasync (ctx: any) => {\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\ttry {\n\t\t\t\tconst raw = await paystack.planList();\n\t\t\t\tconst res = unwrapSdkResult<Record<string, unknown>>(raw);\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\tconst plansData = (res !== null && typeof res === \"object\" && \"status\" in res && \"data\" in res) ? (res as Record<string, any>).data : (res as Record<string, any>)?.data ?? res;\n\n\t\t\t\tif (!Array.isArray(plansData)) {\n\t\t\t\t\treturn ctx.json({ status: \"success\", count: 0 });\n\t\t\t\t}\n\n\t\t\t\tfor (const plan of plansData) {\n\t\t\t\t\tconst paystackId = String(plan.id);\n\t\t\t\t\tconst existing = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t\t\twhere: [{ field: \"paystackId\", value: paystackId }],\n\t\t\t\t\t});\n\n\t\t\t\t\tconst planData = {\n\t\t\t\t\t\tname: plan.name,\n\t\t\t\t\t\tdescription: plan.description,\n\t\t\t\t\t\tamount: plan.amount,\n\t\t\t\t\t\tcurrency: plan.currency,\n\t\t\t\t\t\tinterval: plan.interval,\n\t\t\t\t\t\tplanCode: plan.plan_code,\n\t\t\t\t\t\tpaystackId,\n\t\t\t\t\t\tmetadata: plan.metadata ? JSON.stringify(plan.metadata) : undefined,\n\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t};\n\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t\t\t\tupdate: planData,\n\t\t\t\t\t\t\twhere: [{ field: \"id\", value: existing.id }],\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tawait (ctx.context.adapter).create({\n\t\t\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\t...planData,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn ctx.json({ status: \"success\", count: plansData.length });\n\t\t\t} catch (error: unknown) {\n\t\t\t\tctx.context.logger.error(\"Failed to sync plans\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: (error as Error)?.message ?? \"Failed to sync plans\",\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n};\n\nexport const listPlans = (_options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/list-plans\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tmetadata: {\n\t\t\t\t...HIDE_METADATA,\n\t\t\t},\n\t\t\tuse: [sessionMiddleware],\n\t\t},\n\t\tasync (ctx: any) => {\n\t\t\ttry {\n\t\t\t\tconst plans = await (ctx.context.adapter).findMany({\n\t\t\t\t\tmodel: \"paystackPlan\",\n\t\t\t\t}) as any[];\n\t\t\t\treturn ctx.json({ plans });\n\t\t\t} catch (error: unknown) {\n\t\t\t\tctx.context.logger.error(\"Failed to list plans\", error);\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: (error as Error)?.message ?? \"Failed to list plans\",\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n};\n\nexport const getConfig = (options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/get-config\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"getPaystackConfig\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tasync (ctx: any) => {\n\t\t\tconst plans = options.subscription?.enabled === true\n\t\t\t\t? await getPlans(options.subscription)\n\t\t\t\t: [];\n\t\t\tconst products = await getProducts(options.products);\n\t\t\treturn ctx.json({\n\t\t\t\tplans,\n\t\t\t\tproducts,\n\t\t\t});\n\t\t}\n\t);\n};\n\nexport { PAYSTACK_ERROR_CODES };\nexport const chargeRecurringSubscription = (options: AnyPaystackOptions) => {\n\treturn createAuthEndpoint(\n\t\t\"/paystack/charge-recurring\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: z.object({\n\t\t\t\tsubscriptionId: z.string(),\n\t\t\t\tamount: z.number().optional(),\n\t\t\t}),\n\t\t},\n\t\tasync (ctx: any) => {\n\t\t\tconst { subscriptionId, amount: bodyAmount } = ctx.body;\n\t\t\tconst subscription = await (ctx.context.adapter).findOne({\n\t\t\t\tmodel: \"subscription\",\n\t\t\t\twhere: [{ field: \"id\", value: subscriptionId }],\n\t\t\t}) as Subscription | null;\n\n\t\t\tif (subscription === null || subscription === undefined) {\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", { message: \"Subscription not found\" });\n\t\t\t}\n\n\t\t\tif (subscription.paystackAuthorizationCode === undefined || subscription.paystackAuthorizationCode === null || subscription.paystackAuthorizationCode === \"\") {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", { message: \"No authorization code found for this subscription\" });\n\t\t\t}\n\n\t\t\tconst plans = await getPlans(options.subscription);\n\t\t\tconst plan = plans.find((p) => p.name.toLowerCase() === subscription.plan.toLowerCase());\n\n\t\t\tif (plan === undefined || plan === null) {\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", { message: \"Plan not found\" });\n\t\t\t}\n\n\t\t\tconst amount = bodyAmount ?? plan.amount;\n\t\t\tif (amount === undefined || amount === null) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", { message: \"Plan amount is not defined\" });\n\t\t\t}\n\n\t\t\tlet email: string | null | undefined;\n\t\t\tif (subscription.referenceId !== undefined && subscription.referenceId !== null && subscription.referenceId !== \"\") {\n\t\t\t\t// Try to find user or org\n\t\t\t\tconst user = await (ctx.context.adapter).findOne({\n\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\twhere: [{ field: \"id\", value: subscription.referenceId }],\n\t\t\t\t}) as User | null;\n\t\t\t\tif (user !== undefined && user !== null) {\n\t\t\t\t\temail = user.email;\n\t\t\t\t} else if (options.organization?.enabled === true) {\n\t\t\t\t\t// Check org owner email if referenceId is organizationId\n\t\t\t\t\tconst ownerMember = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t{ field: \"organizationId\", value: subscription.referenceId },\n\t\t\t\t\t\t\t{ field: \"role\", value: \"owner\" },\n\t\t\t\t\t\t],\n\t\t\t\t\t}) as Member | null;\n\t\t\t\t\tif (ownerMember !== undefined && ownerMember !== null) {\n\t\t\t\t\t\tconst ownerUser = await (ctx.context.adapter).findOne({\n\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\twhere: [{ field: \"id\", value: ownerMember.userId }],\n\t\t\t\t\t\t}) as User | null;\n\t\t\t\t\t\temail = ownerUser?.email;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// No fallback needed since referenceId is required and handled above\n\t\t\tif (email === undefined || email === null || email === \"\") {\n\t\t\t\tthrow new APIError(\"NOT_FOUND\", { message: \"User email not found\" });\n\t\t\t}\n\n\t\t\tconst finalCurrency = plan.currency ?? \"NGN\";\n\t\t\tif (!validateMinAmount(amount, finalCurrency)) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: `Amount ${amount} is less than the minimum required for ${finalCurrency}.`,\n\t\t\t\t\tstatus: 400\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst paystack = getPaystackOps(options.paystackClient);\n\t\t\tconst chargeRes = await paystack.transactionChargeAuthorization({\n\t\t\t\temail,\n\t\t\t\tamount,\n\t\t\t\tauthorization_code: subscription.paystackAuthorizationCode,\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\tcurrency: plan.currency as any,\n\t\t\t\tmetadata: {\n\t\t\t\t\tsubscriptionId,\n\t\t\t\t\treferenceId: subscription.referenceId,\n\t\t\t\t\tplan: plan.name,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst data = unwrapSdkResult<Record<string, unknown>>(chargeRes);\n\t\t\tconst chargeData = (data as { data?: Record<string, unknown> })?.data ?? data;\n\n\t\t\tif (chargeData?.status === \"success\") {\n\t\t\t\tconst now = new Date();\n\t\t\t\tconst nextPeriodEnd = getNextPeriodEnd(now, plan.interval ?? \"monthly\");\n\n\t\t\t\tawait (ctx.context.adapter).update({\n\t\t\t\t\tmodel: \"subscription\",\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tperiodStart: now,\n\t\t\t\t\t\tperiodEnd: nextPeriodEnd,\n\t\t\t\t\t\tupdatedAt: now,\n\t\t\t\t\t\t// Record the last transaction reference if available\n\t\t\t\t\t\tpaystackTransactionReference: chargeData.reference as string | undefined,\n\t\t\t\t\t},\n\t\t\t\t\twhere: [{ field: \"id\", value: subscription.id }],\n\t\t\t\t});\n\n\t\t\t\treturn ctx.json({ status: \"success\", data: chargeData });\n\t\t\t}\n\n\t\t\treturn ctx.json({ status: \"failed\", data: chargeData }, { status: 400 });\n\t\t},\n\t);\n};\n","import type { BetterAuthPluginDBSchema } from \"@better-auth/core/db\";\nimport { mergeSchema } from \"better-auth/db\";\n\nimport type { PaystackClientLike, PaystackOptions } from \"./types\";\n\nexport const transactions = {\n\tpaystackTransaction: {\n\t\tfields: {\n\t\t\treference: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tpaystackId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\treferenceId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tuserId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tamount: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tcurrency: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tstatus: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tplan: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tproduct: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tmetadata: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tupdatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\nexport const subscriptions = {\n\tsubscription: {\n\t\tfields: {\n\t\t\tplan: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\treferenceId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tpaystackCustomerCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tpaystackSubscriptionCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tpaystackTransactionReference: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\tpaystackAuthorizationCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tpaystackEmailToken: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tstatus: {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdefaultValue: \"incomplete\",\n\t\t\t},\n\t\t\tperiodStart: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tperiodEnd: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\ttrialStart: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\ttrialEnd: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tcancelAtPeriodEnd: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\trequired: false,\n\t\t\t\tdefaultValue: false,\n\t\t\t},\n\t\t\tgroupId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tseats: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tpendingPlan: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\nexport const user = {\n\tuser: {\n\t\tfields: {\n\t\t\tpaystackCustomerCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\nexport const organization = {\n\torganization: {\n\t\tfields: {\n\t\t\tpaystackCustomerCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tindex: true,\n\t\t\t},\n\t\t\temail: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\nexport const products = {\n\tpaystackProduct: {\n\t\tfields: {\n\t\t\tname: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tdescription: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tprice: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tcurrency: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tquantity: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: false,\n\t\t\t\tdefaultValue: 0,\n\t\t\t},\n\t\t\tunlimited: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\trequired: false,\n\t\t\t\tdefaultValue: true,\n\t\t\t},\n\t\t\tpaystackId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tslug: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tmetadata: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tupdatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\nexport const plans = {\n\tpaystackPlan: {\n\t\tfields: {\n\t\t\tname: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tdescription: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tamount: {\n\t\t\t\ttype: \"number\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tcurrency: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tinterval: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tplanCode: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tpaystackId: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: true,\n\t\t\t\tunique: true,\n\t\t\t},\n\t\t\tmetadata: {\n\t\t\t\ttype: \"string\",\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t\tcreatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\tupdatedAt: {\n\t\t\t\ttype: \"date\",\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t},\n\t},\n} satisfies BetterAuthPluginDBSchema;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport const getSchema = (options: PaystackOptions<PaystackClientLike, any, any>) => {\n\tlet baseSchema: BetterAuthPluginDBSchema;\n\n\tif (options.subscription?.enabled === true) {\n\t\tbaseSchema = {\n\t\t\t...subscriptions,\n\t\t\t...transactions,\n\t\t\t...user,\n\t\t\t...products,\n\t\t\t...plans,\n\t\t};\n\t} else {\n\t\tbaseSchema = {\n\t\t\t...user,\n\t\t\t...transactions,\n\t\t\t...products,\n\t\t\t...plans,\n\t\t};\n\t}\n\n\t// Add organization schema if organization support is enabled\n\tif (options.organization?.enabled === true) {\n\t\tbaseSchema = {\n\t\t\t...baseSchema,\n\t\t\t...organization,\n\t\t};\n\t}\n\n\tif (\n\t\toptions.schema !== undefined &&\n\t\toptions.subscription?.enabled !== true &&\n\t\t\"subscription\" in options.schema\n\t) {\n\t\tconst { subscription: _subscription, ...restSchema } = options.schema as Record<string, unknown>;\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\treturn mergeSchema(baseSchema, restSchema as any);\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\treturn mergeSchema(baseSchema, options.schema as any);\n};\n","import { defineErrorCodes } from \"@better-auth/core/utils/error-codes\";\nimport type { AuthContext, GenericEndpointContext } from \"better-auth\";\nimport { defu } from \"defu\";\n\nimport {\n\tdisablePaystackSubscription,\n\tenablePaystackSubscription,\n\tinitializeTransaction,\n\tlistSubscriptions,\n\tlistTransactions,\n\tpaystackWebhook,\n\tverifyTransaction,\n\tgetConfig,\n\tgetSubscriptionManageLink,\n\tPAYSTACK_ERROR_CODES,\n\tcreateSubscription,\n\tupgradeSubscription,\n\tcancelSubscription,\n\trestoreSubscription,\n\tchargeRecurringSubscription,\n\tsyncProducts,\n\tlistProducts,\n\tsyncPlans,\n\tlistPlans,\n} from \"./routes\";\nimport { getSchema } from \"./schema\";\nimport { checkSeatLimit, checkTeamLimit, getOrganizationSubscription } from \"./limits\";\nimport { getPlanByName, syncSubscriptionSeats } from \"./utils\";\nimport type {\n\tPaystackNodeClient,\n\tPaystackClientLike,\n\tPaystackOptions,\n\tPaystackPlan,\n\tSubscription,\n\tSubscriptionOptions,\n\tPaystackProduct,\n\tPaystackCustomerResponse,\n} from \"./types\";\nimport { getPaystackOps, unwrapSdkResult } from \"./paystack-sdk\";\n\nconst INTERNAL_ERROR_CODES = defineErrorCodes({\n\t...Object.fromEntries(\n\t\tObject.entries(PAYSTACK_ERROR_CODES).map(([key, value]) => [\n\t\t\tkey,\n\t\t\ttypeof value === \"string\" ? value : (value as { message: string }).message,\n\t\t]),\n\t),\n});\n\nexport const paystack = <\n\tTPaystackClient extends PaystackClientLike = PaystackNodeClient,\n\tTMetadata = Record<string, unknown>,\n\tTLimits = Record<string, unknown>,\n\tO extends PaystackOptions<TPaystackClient, TMetadata, TLimits> = PaystackOptions<TPaystackClient, TMetadata, TLimits>,\n>(\n\t\toptions: O,\n\t) => {\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tconst routeOptions = options as any;\n\tconst res = {\n\t\tid: \"paystack\",\n\t\tendpoints: {\n\t\t\tinitializeTransaction: initializeTransaction(routeOptions),\n\t\t\tverifyTransaction: verifyTransaction(routeOptions),\n\t\t\tlistSubscriptions: listSubscriptions(routeOptions),\n\t\t\tpaystackWebhook: paystackWebhook(routeOptions),\n\t\t\tlistTransactions: listTransactions(routeOptions),\n\t\t\tgetConfig: getConfig(routeOptions),\n\t\t\tdisableSubscription: disablePaystackSubscription(routeOptions),\n\t\t\tenableSubscription: enablePaystackSubscription(routeOptions),\n\t\t\tgetSubscriptionManageLink: getSubscriptionManageLink(routeOptions),\n\t\t\tsubscriptionManageLink: getSubscriptionManageLink(routeOptions, \"/paystack/subscription/manage-link\"), // Historical alias\n\t\t\tcreateSubscription: createSubscription(routeOptions),\n\t\t\tupgradeSubscription: upgradeSubscription(routeOptions),\n\t\t\tcancelSubscription: cancelSubscription(routeOptions),\n\t\t\trestoreSubscription: restoreSubscription(routeOptions),\n\t\t\tchargeRecurringSubscription: chargeRecurringSubscription(routeOptions),\n\t\t\tsyncProducts: syncProducts(routeOptions),\n\t\t\tlistProducts: listProducts(routeOptions),\n\t\t\tsyncPlans: syncPlans(routeOptions),\n\t\t\tlistPlans: listPlans(routeOptions),\n\t\t},\n\t\tschema: getSchema(options),\n\t\tinit: (ctx: AuthContext) => {\n\t\t\treturn {\n\t\t\t\toptions: {\n\t\t\t\t\tdatabaseHooks: {\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\t\tasync after(user: { id: string; email: string; name?: string | null }, hookCtx?: GenericEndpointContext | null) {\n\t\t\t\t\t\t\t\t\tif (hookCtx === undefined || hookCtx === null || options.createCustomerOnSignUp !== true) return;\n\n\t\t\t\t\t\t\t\t\tconst paystackOps = getPaystackOps(options.paystackClient as PaystackClientLike);\n\t\t\t\t\t\t\t\t\tconst raw = await paystackOps.customerCreate({\n\t\t\t\t\t\t\t\t\t\temail: user.email,\n\t\t\t\t\t\t\t\t\t\tfirst_name: user.name ?? undefined,\n\t\t\t\t\t\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\t\t\t\t\tuserId: user.id,\n\t\t\t\t\t\t\t\t\t\t} as Record<string, unknown>,\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\tconst sdkRes = unwrapSdkResult<PaystackCustomerResponse>(raw);\n\t\t\t\t\t\t\t\t\tconst customerCode = (sdkRes?.customer_code as string | undefined)\n\t\t\t\t\t\t\t\t\t\t?? (sdkRes?.data as Record<string, unknown>)?.customer_code as string | undefined;\n\n\t\t\t\t\t\t\t\t\tif (customerCode === undefined || customerCode === null) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tawait (ctx.adapter as any).update({\n\t\t\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: user.id }],\n\t\t\t\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\t\t\t\tpaystackCustomerCode: customerCode,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\torganization: options.organization?.enabled === true\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\t\t\tasync after(org: { id: string; name: string; email?: string | null }, hookCtx: GenericEndpointContext | null) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tconst extraCreateParams = options.organization?.getCustomerCreateParams\n\t\t\t\t\t\t\t\t\t\t\t\t? await options.organization.getCustomerCreateParams(org, hookCtx!)\n\t\t\t\t\t\t\t\t\t\t\t\t: {};\n\n\t\t\t\t\t\t\t\t\t\t\tlet targetEmail = org.email;\n\t\t\t\t\t\t\t\t\t\t\tif (targetEmail === undefined || targetEmail === null) {\n\t\t\t\t\t\t\t\t\t\t\t\tconst ownerMember = await (ctx.adapter as any).findOne({\n\t\t\t\t\t\t\t\t\t\t\t\t\tmodel: \"member\",\n\t\t\t\t\t\t\t\t\t\t\t\t\twhere: [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ field: \"organizationId\", value: org.id },\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t{ field: \"role\", value: \"owner\" }\n\t\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\tif (ownerMember !== null && ownerMember !== undefined) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst ownerUser = await (ctx.adapter as any).findOne({\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmodel: \"user\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\twhere: [{ field: \"id\", value: ownerMember.userId }]\n\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\t\ttargetEmail = ownerUser?.email;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tif (targetEmail === undefined || targetEmail === null) return;\n\n\t\t\t\t\t\t\t\t\t\t\tconst params = defu(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\temail: targetEmail,\n\t\t\t\t\t\t\t\t\t\t\t\t\tfirst_name: org.name,\n\t\t\t\t\t\t\t\t\t\t\t\t\tmetadata: { organizationId: org.id },\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\textraCreateParams,\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t\tconst paystackOps = getPaystackOps(options.paystackClient as PaystackClientLike);\n\t\t\t\t\t\t\t\t\t\t\tconst raw = await paystackOps.customerCreate(params as unknown as Parameters<typeof paystackOps.customerCreate>[0]);\n\t\t\t\t\t\t\t\t\t\t\tconst sdkRes = unwrapSdkResult<PaystackCustomerResponse>(raw);\n\t\t\t\t\t\t\t\t\t\t\tconst customerCode = (sdkRes?.customer_code as string | undefined)\n\t\t\t\t\t\t\t\t\t\t\t\t?? (sdkRes?.data as Record<string, unknown>)?.customer_code as string | undefined;\n\n\t\t\t\t\t\t\t\t\t\t\tif (customerCode === undefined || customerCode === null) return;\n\n\t\t\t\t\t\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\t\t\t\t\t\t\t\tawait (ctx.internalAdapter as any).updateOrganization(org.id, {\n\t\t\t\t\t\t\t\t\t\t\t\tpaystackCustomerCode: customerCode,\n\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\tawait options.organization?.onCustomerCreate?.(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tpaystackCustomer: sdkRes as unknown as PaystackCustomerResponse,\n\t\t\t\t\t\t\t\t\t\t\t\t\torganization: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t...org,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tpaystackCustomerCode: customerCode,\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\thookCtx!,\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t\t\t\t\t\t\t(ctx as unknown as AuthContext).logger.error(\"Failed to create Paystack customer for organization\", error);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t},\n\t\t\t\t\tmember: {\n\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\tbefore: async (member: { organizationId: string }, ctx: GenericEndpointContext | null | undefined) => {\n\t\t\t\t\t\t\t\tif (options.subscription?.enabled === true && member.organizationId && ctx !== null && ctx !== undefined) {\n\t\t\t\t\t\t\t\t\tawait checkSeatLimit(ctx, member.organizationId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tafter: async (member: { organizationId: string | undefined }, ctx: GenericEndpointContext | null | undefined) => {\n\t\t\t\t\t\t\t\tif (options.subscription?.enabled === true && (member?.organizationId !== undefined && member?.organizationId !== null) && (ctx !== undefined && ctx !== null)) {\n\t\t\t\t\t\t\t\t\tawait syncSubscriptionSeats(ctx, member.organizationId, options);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdelete: {\n\t\t\t\t\t\t\tafter: async (member: { organizationId: string | undefined }, ctx: GenericEndpointContext | null | undefined) => {\n\t\t\t\t\t\t\t\tif (options.subscription?.enabled === true && (member?.organizationId !== undefined && member?.organizationId !== null) && (ctx !== undefined && ctx !== null)) {\n\t\t\t\t\t\t\t\t\tawait syncSubscriptionSeats(ctx, member.organizationId, options);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tinvitation: {\n\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\tbefore: async (invitation: { organizationId: string }, ctx: GenericEndpointContext | null | undefined) => {\n\t\t\t\t\t\t\t\tif (options.subscription?.enabled === true && invitation.organizationId && ctx !== null && ctx !== undefined) {\n\t\t\t\t\t\t\t\t\tawait checkSeatLimit(ctx, invitation.organizationId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tafter: async (invitation: { organizationId: string | undefined }, ctx: GenericEndpointContext | null | undefined) => {\n\t\t\t\t\t\t\t\tif (options.subscription?.enabled === true && (invitation?.organizationId !== undefined && invitation?.organizationId !== null) && (ctx !== undefined && ctx !== null)) {\n\t\t\t\t\t\t\t\t\tawait syncSubscriptionSeats(ctx, invitation.organizationId, options);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdelete: {\n\t\t\t\t\t\t\tafter: async (invitation: { organizationId: string | undefined }, ctx: GenericEndpointContext | null | undefined) => {\n\t\t\t\t\t\t\t\tif (options.subscription?.enabled === true && (invitation?.organizationId !== undefined && invitation?.organizationId !== null) && (ctx !== undefined && ctx !== null)) {\n\t\t\t\t\t\t\t\t\tawait syncSubscriptionSeats(ctx, invitation.organizationId, options);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tteam: {\n\t\t\t\t\t\tcreate: {\n\t\t\t\t\t\t\tbefore: async (team: { organizationId: string }, ctx: GenericEndpointContext | null | undefined) => {\n\t\t\t\t\t\t\t\tif (options.subscription?.enabled === true && team.organizationId && ctx !== null && ctx !== undefined) {\n\t\t\t\t\t\t\t\t\tconst subscription = await getOrganizationSubscription(ctx, team.organizationId);\n\t\t\t\t\t\t\t\t\tif (subscription !== null && subscription !== undefined) {\n\t\t\t\t\t\t\t\t\t\tconst plan = await getPlanByName(options, subscription.plan);\n\t\t\t\t\t\t\t\t\t\tconst limits = plan?.limits;\n\t\t\t\t\t\t\t\t\t\tconst maxTeams = limits?.teams as number | undefined;\n\n\t\t\t\t\t\t\t\t\t\tif (typeof maxTeams === \"number\") {\n\t\t\t\t\t\t\t\t\t\t\tawait checkTeamLimit(ctx, team.organizationId, maxTeams);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\t$ERROR_CODES: INTERNAL_ERROR_CODES,\n\t};\n\n\treturn res;\n};\n\nexport type PaystackPlugin<\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tO extends PaystackOptions<PaystackClientLike, any, any> = PaystackOptions,\n> = ReturnType<\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\ttypeof paystack<PaystackClientLike, any, any, O>\n>;\n\nexport type { Subscription, SubscriptionOptions, PaystackPlan, PaystackOptions, PaystackProduct };\n"],"mappings":"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M;EACN,UAAU;EACV;CACD,EACD,EACD;AAED,MAAa,gBAAgB,EAC5B,cAAc,EACb,QAAQ;CACP,MAAM;EACL,MAAM;EACN,UAAU;EACV,OAAO;EACP;CACD,aAAa;EACZ,MAAM;EACN,UAAU;EACV,OAAO;EACP;CACD,sBAAsB;EACrB,MAAM;EACN,UAAU;EACV,OAAO;EACP;CACD,0BAA0B;EACzB,MAAM;EACN,UAAU;EACV,QAAQ;EACR;CACD,8BAA8B;EAC7B,MAAM;EACN,UAAU;EACV,OAAO;EACP;CACD,2BAA2B;EAC1B,MAAM;EACN,UAAU;EACV;CACD,oBAAoB;EACnB,MAAM;EACN,UAAU;EACV;CACD,QAAQ;EACP,MAAM;EACN,cAAc;EACd;CACD,aAAa;EACZ,MAAM;EACN,UAAU;EACV;CACD,WAAW;EACV,MAAM;EACN,UAAU;EACV;CACD,YAAY;EACX,MAAM;EACN,UAAU;EACV;CACD,UAAU;EACT,MAAM;EACN,UAAU;EACV;CACD,mBAAmB;EAClB,MAAM;EACN,UAAU;EACV,cAAc;EACd;CACD,SAAS;EACR,MAAM;EACN,UAAU;EACV;CACD,OAAO;EACN,MAAM;EACN,UAAU;EACV;CACD,aAAa;EACZ,MAAM;EACN,UAAU;EACV;CACD,EACD,EACD;AAED,MAAa,OAAO,EACnB,MAAM,EACL,QAAQ,EACP,sBAAsB;CACrB,MAAM;CACN,UAAU;CACV,OAAO;CACP,EACD,EACD,EACD;AAED,MAAa,eAAe,EAC3B,cAAc,EACb,QAAQ;CACP,sBAAsB;EACrB,MAAM;EACN,UAAU;EACV,OAAO;EACP;CACD,OAAO;EACN,MAAM;EACN,UAAU;EACV;CACD,EACD,EACD;AAED,MAAa,WAAW,EACvB,iBAAiB,EAChB,QAAQ;CACP,MAAM;EACL,MAAM;EACN,UAAU;EACV;CACD,aAAa;EACZ,MAAM;EACN,UAAU;EACV;CACD,OAAO;EACN,MAAM;EACN,UAAU;EACV;CACD,UAAU;EACT,MAAM;EACN,UAAU;EACV;CACD,UAAU;EACT,MAAM;EACN,UAAU;EACV,cAAc;EACd;CACD,WAAW;EACV,MAAM;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"}
|