better-auth-payu 0.1.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 +722 -0
- package/dist/client-fGPaKb7O.d.ts +48 -0
- package/dist/client-fGPaKb7O.d.ts.map +1 -0
- package/dist/client.js +39 -0
- package/dist/client.js.map +1 -0
- package/dist/error-codes-CZKuS8SB.js +46 -0
- package/dist/error-codes-CZKuS8SB.js.map +1 -0
- package/dist/index-B1s85S1-.d.ts +828 -0
- package/dist/index-B1s85S1-.d.ts.map +1 -0
- package/dist/index-Dnld5Msn.d.ts +2 -0
- package/dist/index.js +1814 -0
- package/dist/index.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../node_modules/@better-auth/core/dist/context/global.mjs","../node_modules/@better-auth/core/dist/async_hooks/index.mjs","../node_modules/@better-auth/core/dist/context/endpoint-context.mjs","../node_modules/@better-auth/core/dist/api/index.mjs","../src/metadata.ts","../src/hooks.ts","../src/utils.ts","../src/middleware.ts","../src/routes.ts","../src/schema.ts","../src/index.ts"],"sourcesContent":["//#region src/context/global.ts\nconst symbol = Symbol.for(\"better-auth:global\");\nlet bind = null;\nconst __context = {};\nconst __betterAuthVersion = \"1.4.18\";\n/**\n* We store context instance in the globalThis.\n*\n* The reason we do this is that some bundlers, web framework, or package managers might\n* create multiple copies of BetterAuth in the same process intentionally or unintentionally.\n*\n* For example, yarn v1, Next.js, SSR, Vite...\n*\n* @internal\n*/\nfunction __getBetterAuthGlobal() {\n\tif (!globalThis[symbol]) {\n\t\tglobalThis[symbol] = {\n\t\t\tversion: __betterAuthVersion,\n\t\t\tepoch: 1,\n\t\t\tcontext: __context\n\t\t};\n\t\tbind = globalThis[symbol];\n\t}\n\tbind = globalThis[symbol];\n\tif (bind.version !== __betterAuthVersion) {\n\t\tbind.version = __betterAuthVersion;\n\t\tbind.epoch++;\n\t}\n\treturn globalThis[symbol];\n}\nfunction getBetterAuthVersion() {\n\treturn __getBetterAuthGlobal().version;\n}\n\n//#endregion\nexport { __getBetterAuthGlobal, getBetterAuthVersion };\n//# sourceMappingURL=global.mjs.map","//#region src/async_hooks/index.ts\nconst AsyncLocalStoragePromise = import(\n\t/* @vite-ignore */\n\t/* webpackIgnore: true */\n\t\"node:async_hooks\"\n).then((mod) => mod.AsyncLocalStorage).catch((err) => {\n\tif (\"AsyncLocalStorage\" in globalThis) return globalThis.AsyncLocalStorage;\n\tif (typeof window !== \"undefined\") return null;\n\tconsole.warn(\"[better-auth] Warning: AsyncLocalStorage is not available in this environment. Some features may not work as expected.\");\n\tconsole.warn(\"[better-auth] Please read more about this warning at https://better-auth.com/docs/installation#mount-handler\");\n\tconsole.warn(\"[better-auth] If you are using Cloudflare Workers, please see: https://developers.cloudflare.com/workers/configuration/compatibility-flags/#nodejs-compatibility-flag\");\n\tthrow err;\n});\nasync function getAsyncLocalStorage() {\n\tconst mod = await AsyncLocalStoragePromise;\n\tif (mod === null) throw new Error(\"getAsyncLocalStorage is only available in server code\");\n\telse return mod;\n}\n\n//#endregion\nexport { getAsyncLocalStorage };\n//# sourceMappingURL=index.mjs.map","import { __getBetterAuthGlobal } from \"./global.mjs\";\nimport { getAsyncLocalStorage } from \"@better-auth/core/async_hooks\";\n\n//#region src/context/endpoint-context.ts\nconst ensureAsyncStorage = async () => {\n\tconst betterAuthGlobal = __getBetterAuthGlobal();\n\tif (!betterAuthGlobal.context.endpointContextAsyncStorage) {\n\t\tconst AsyncLocalStorage$1 = await getAsyncLocalStorage();\n\t\tbetterAuthGlobal.context.endpointContextAsyncStorage = new AsyncLocalStorage$1();\n\t}\n\treturn betterAuthGlobal.context.endpointContextAsyncStorage;\n};\n/**\n* This is for internal use only. Most users should use `getCurrentAuthContext` instead.\n*\n* It is exposed for advanced use cases where you need direct access to the AsyncLocalStorage instance.\n*/\nasync function getCurrentAuthContextAsyncLocalStorage() {\n\treturn ensureAsyncStorage();\n}\nasync function getCurrentAuthContext() {\n\tconst context = (await ensureAsyncStorage()).getStore();\n\tif (!context) throw new Error(\"No auth context found. Please make sure you are calling this function within a `runWithEndpointContext` callback.\");\n\treturn context;\n}\nasync function runWithEndpointContext(context, fn) {\n\treturn (await ensureAsyncStorage()).run(context, fn);\n}\n\n//#endregion\nexport { getCurrentAuthContext, getCurrentAuthContextAsyncLocalStorage, runWithEndpointContext };\n//# sourceMappingURL=endpoint-context.mjs.map","import { runWithEndpointContext } from \"../context/endpoint-context.mjs\";\nimport \"../context/index.mjs\";\nimport { createEndpoint, createMiddleware } from \"better-call\";\n\n//#region src/api/index.ts\nconst optionsMiddleware = createMiddleware(async () => {\n\t/**\n\t* This will be passed on the instance of\n\t* the context. Used to infer the type\n\t* here.\n\t*/\n\treturn {};\n});\nconst createAuthMiddleware = createMiddleware.create({ use: [optionsMiddleware, createMiddleware(async () => {\n\treturn {};\n})] });\nconst use = [optionsMiddleware];\nfunction createAuthEndpoint(pathOrOptions, handlerOrOptions, handlerOrNever) {\n\tconst path = typeof pathOrOptions === \"string\" ? pathOrOptions : void 0;\n\tconst options = typeof handlerOrOptions === \"object\" ? handlerOrOptions : pathOrOptions;\n\tconst handler = typeof handlerOrOptions === \"function\" ? handlerOrOptions : handlerOrNever;\n\tif (path) return createEndpoint(path, {\n\t\t...options,\n\t\tuse: [...options?.use || [], ...use]\n\t}, async (ctx) => runWithEndpointContext(ctx, () => handler(ctx)));\n\treturn createEndpoint({\n\t\t...options,\n\t\tuse: [...options?.use || [], ...use]\n\t}, async (ctx) => runWithEndpointContext(ctx, () => handler(ctx)));\n}\n\n//#endregion\nexport { createAuthEndpoint, createAuthMiddleware, optionsMiddleware };\n//# sourceMappingURL=index.mjs.map","import { defu } from \"defu\";\n\n// ─── PayU Notes (UDF Fields) ─────────────────────────────────────────────────\n// PayU uses User Defined Fields (udf1-udf10) instead of Razorpay's notes object.\n// We reserve:\n// udf1 → customerType (\"user\" | \"organization\")\n// udf2 → userId\n// udf3 → organizationId (if applicable)\n// udf4 → subscriptionId\n// udf5 → referenceId\n// udf6-udf10 → user-provided metadata\n\ntype PayUUdf = Record<string, string | undefined>;\n\ntype CustomerInternalUdf =\n | { customerType: \"user\"; userId: string }\n | { customerType: \"organization\"; organizationId: string };\n\ntype SubscriptionInternalUdf = {\n userId: string;\n subscriptionId: string;\n referenceId: string;\n};\n\n// ─── Customer UDF Helpers ────────────────────────────────────────────────────\n\nexport const customerUdf = {\n /** Internal keys used for customer tracking */\n keys: [\"customerType\", \"userId\", \"organizationId\"] as const,\n\n /**\n * Set customer UDFs by mapping internal fields to udf slots.\n * Internal fields take priority over user-provided values.\n */\n set(internalFields: CustomerInternalUdf, userUdf?: PayUUdf): PayUUdf {\n const internal: PayUUdf = {\n udf1: internalFields.customerType,\n udf2: \"userId\" in internalFields ? internalFields.userId : undefined,\n udf3:\n \"organizationId\" in internalFields\n ? internalFields.organizationId\n : undefined,\n };\n return defu(internal, userUdf || {}) as PayUUdf;\n },\n\n /**\n * Extract customer-specific fields from UDF values.\n */\n get(udf: PayUUdf | null | undefined) {\n if (!udf) {\n return {\n userId: undefined,\n organizationId: undefined,\n customerType: undefined as\n | CustomerInternalUdf[\"customerType\"]\n | undefined,\n };\n }\n return {\n userId: udf.udf2,\n organizationId: udf.udf3,\n customerType: udf.udf1 as CustomerInternalUdf[\"customerType\"] | undefined,\n };\n },\n};\n\n// ─── Subscription UDF Helpers ────────────────────────────────────────────────\n\nexport const subscriptionUdf = {\n /** Internal keys used for subscription tracking */\n keys: [\"userId\", \"subscriptionId\", \"referenceId\"] as const,\n\n /**\n * Set subscription UDFs by mapping internal fields to udf slots.\n * Internal fields take priority over user-provided values.\n */\n set(internalFields: SubscriptionInternalUdf, userUdf?: PayUUdf): PayUUdf {\n const internal: PayUUdf = {\n udf2: internalFields.userId,\n udf4: internalFields.subscriptionId,\n udf5: internalFields.referenceId,\n };\n return defu(internal, userUdf || {}) as PayUUdf;\n },\n\n /**\n * Extract subscription-specific fields from UDF values.\n */\n get(udf: PayUUdf | null | undefined) {\n if (!udf) {\n return {\n userId: undefined,\n subscriptionId: undefined,\n referenceId: undefined,\n };\n }\n return {\n userId: udf.udf2,\n subscriptionId: udf.udf4,\n referenceId: udf.udf5,\n };\n },\n};\n\n// ─── UDF Serialization ──────────────────────────────────────────────────────\n\n/**\n * Convert a PayUUdf object to individual udf params for API calls.\n */\nexport function udfToParams(udf: PayUUdf): Record<string, string> {\n const params: Record<string, string> = {};\n for (let i = 1; i <= 10; i++) {\n const key = `udf${i}`;\n if (udf[key]) {\n params[key] = udf[key]!;\n }\n }\n return params;\n}\n\n/**\n * Extract UDF fields from a PayU response/webhook into a PayUUdf object.\n */\nexport function paramsToUdf(\n params: Record<string, string | undefined>,\n): PayUUdf {\n const udf: PayUUdf = {};\n for (let i = 1; i <= 10; i++) {\n const key = `udf${i}`;\n if (params[key]) {\n udf[key] = params[key];\n }\n }\n return udf;\n}\n","import { paramsToUdf, subscriptionUdf } from \"./metadata\";\nimport type {\n PayUOptions,\n PayUSubscriptionStatus,\n PayUWebhookEvent,\n Subscription,\n} from \"./types\";\n\ntype Adapter = {\n // biome-ignore lint/suspicious/noExplicitAny: adapter args vary by method\n findOne: (args: any) => Promise<any>;\n // biome-ignore lint/suspicious/noExplicitAny: adapter args vary by method\n create: (args: any) => Promise<any>;\n // biome-ignore lint/suspicious/noExplicitAny: adapter args vary by method\n update: (args: any) => Promise<any>;\n};\n\ntype HookContext = {\n context: {\n adapter: Adapter;\n logger: {\n warn: (msg: string) => void;\n error: (msg: string) => void;\n info: (msg: string) => void;\n };\n };\n};\n\n// ─── Helper: Find subscription by PayU txnid ─────────────────────────────────\n\nasync function findSubscriptionByTxnId(\n adapter: Adapter,\n txnid: string,\n): Promise<Subscription | null> {\n const result = await adapter.findOne({\n model: \"subscription\",\n where: [{ field: \"payuTransactionId\", value: txnid }],\n });\n return result as Subscription | null;\n}\n\nasync function findSubscriptionByUdf(\n adapter: Adapter,\n event: PayUWebhookEvent,\n): Promise<Subscription | null> {\n const udf = paramsToUdf(event as unknown as Record<string, string>);\n const subUdf = subscriptionUdf.get(udf);\n\n if (subUdf.subscriptionId) {\n const result = await adapter.findOne({\n model: \"subscription\",\n where: [{ field: \"id\", value: subUdf.subscriptionId }],\n });\n return result as Subscription | null;\n }\n\n return null;\n}\n\nasync function findSubscription(\n adapter: Adapter,\n event: PayUWebhookEvent,\n): Promise<Subscription | null> {\n // First try by txnid, then by UDF subscription ID\n const byTxn = await findSubscriptionByTxnId(adapter, event.txnid);\n if (byTxn) return byTxn;\n return findSubscriptionByUdf(adapter, event);\n}\n\n// ─── Webhook Handlers ────────────────────────────────────────────────────────\n\nexport async function onPaymentSuccess(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n if (!event.txnid) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n status: \"active\" as PayUSubscriptionStatus,\n payuMihpayid: event.mihpayid,\n paidCount: (sub.paidCount || 0) + 1,\n remainingCount:\n sub.totalCount != null\n ? Math.max((sub.totalCount || 0) - ((sub.paidCount || 0) + 1), 0)\n : null,\n updatedAt: new Date(),\n },\n });\n\n const plan = options.subscription.plans\n ? (typeof options.subscription.plans === \"function\"\n ? await options.subscription.plans()\n : options.subscription.plans\n ).find((p) => p.name === sub.plan)\n : undefined;\n\n await options.subscription.onPaymentSuccess?.({\n subscription: sub,\n plan,\n event,\n });\n } else {\n ctx.context.logger.warn(\n `PayU: payment success for txnid ${event.txnid} but subscription not found`,\n );\n }\n } catch (err) {\n ctx.context.logger.error(\n `PayU onPaymentSuccess error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport async function onPaymentFailure(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n status: \"pending\" as PayUSubscriptionStatus,\n updatedAt: new Date(),\n },\n });\n }\n\n await options.subscription.onPaymentFailure?.({\n event,\n error: event.error || event.field9 || \"Payment failed\",\n });\n } catch (err) {\n ctx.context.logger.error(\n `PayU onPaymentFailure error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport async function onSubscriptionActivated(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n if (!event.txnid) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n status: \"active\" as PayUSubscriptionStatus,\n payuMihpayid: event.mihpayid,\n currentStart: new Date(),\n updatedAt: new Date(),\n },\n });\n\n const plan = options.subscription.plans\n ? (typeof options.subscription.plans === \"function\"\n ? await options.subscription.plans()\n : options.subscription.plans\n ).find((p) => p.name === sub.plan)\n : undefined;\n\n await options.subscription.onSubscriptionActivated?.({\n subscription: sub,\n plan,\n event,\n });\n } else {\n ctx.context.logger.warn(\n `PayU: subscription activated for txnid ${event.txnid} but subscription not found`,\n );\n }\n } catch (err) {\n ctx.context.logger.error(\n `PayU onSubscriptionActivated error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport async function onSubscriptionCharged(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n if (!event.txnid) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n const newPaidCount = (sub.paidCount || 0) + 1;\n const newRemainingCount =\n sub.totalCount != null\n ? Math.max((sub.totalCount || 0) - newPaidCount, 0)\n : null;\n\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n status: \"active\" as PayUSubscriptionStatus,\n paidCount: newPaidCount,\n remainingCount: newRemainingCount,\n payuMihpayid: event.mihpayid,\n updatedAt: new Date(),\n },\n });\n\n const plan = options.subscription.plans\n ? (typeof options.subscription.plans === \"function\"\n ? await options.subscription.plans()\n : options.subscription.plans\n ).find((p) => p.name === sub.plan)\n : undefined;\n\n await options.subscription.onSubscriptionCharged?.({\n subscription: sub,\n plan,\n event,\n });\n } else {\n ctx.context.logger.warn(\n `PayU: subscription charged for txnid ${event.txnid} but subscription not found`,\n );\n }\n } catch (err) {\n ctx.context.logger.error(\n `PayU onSubscriptionCharged error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport async function onSubscriptionPending(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n status: \"pending\" as PayUSubscriptionStatus,\n updatedAt: new Date(),\n },\n });\n\n const plan = options.subscription.plans\n ? (typeof options.subscription.plans === \"function\"\n ? await options.subscription.plans()\n : options.subscription.plans\n ).find((p) => p.name === sub.plan)\n : undefined;\n\n await options.subscription.onSubscriptionPending?.({\n subscription: sub,\n plan,\n event,\n });\n }\n } catch (err) {\n ctx.context.logger.error(\n `PayU onSubscriptionPending error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport async function onSubscriptionHalted(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n status: \"halted\" as PayUSubscriptionStatus,\n updatedAt: new Date(),\n },\n });\n\n const plan = options.subscription.plans\n ? (typeof options.subscription.plans === \"function\"\n ? await options.subscription.plans()\n : options.subscription.plans\n ).find((p) => p.name === sub.plan)\n : undefined;\n\n await options.subscription.onSubscriptionHalted?.({\n subscription: sub,\n plan,\n event,\n });\n }\n } catch (err) {\n ctx.context.logger.error(\n `PayU onSubscriptionHalted error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport async function onSubscriptionCompleted(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n status: \"completed\" as PayUSubscriptionStatus,\n endedAt: new Date(),\n remainingCount: 0,\n updatedAt: new Date(),\n },\n });\n\n const plan = options.subscription.plans\n ? (typeof options.subscription.plans === \"function\"\n ? await options.subscription.plans()\n : options.subscription.plans\n ).find((p) => p.name === sub.plan)\n : undefined;\n\n await options.subscription.onSubscriptionCompleted?.({\n subscription: sub,\n plan,\n event,\n });\n }\n } catch (err) {\n ctx.context.logger.error(\n `PayU onSubscriptionCompleted error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport async function onSubscriptionCancelled(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n status: \"cancelled\" as PayUSubscriptionStatus,\n cancelledAt: new Date(),\n endedAt: new Date(),\n updatedAt: new Date(),\n },\n });\n\n const plan = options.subscription.plans\n ? (typeof options.subscription.plans === \"function\"\n ? await options.subscription.plans()\n : options.subscription.plans\n ).find((p) => p.name === sub.plan)\n : undefined;\n\n await options.subscription.onSubscriptionCancelled?.({\n subscription: sub,\n plan,\n event,\n });\n } else {\n ctx.context.logger.warn(\n `PayU: subscription cancelled for txnid ${event.txnid} but subscription not found`,\n );\n }\n } catch (err) {\n ctx.context.logger.error(\n `PayU onSubscriptionCancelled error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport async function onSubscriptionPaused(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n status: \"paused\" as PayUSubscriptionStatus,\n pausedAt: new Date(),\n updatedAt: new Date(),\n },\n });\n\n const plan = options.subscription.plans\n ? (typeof options.subscription.plans === \"function\"\n ? await options.subscription.plans()\n : options.subscription.plans\n ).find((p) => p.name === sub.plan)\n : undefined;\n\n await options.subscription.onSubscriptionPaused?.({\n subscription: sub,\n plan,\n event,\n });\n }\n } catch (err) {\n ctx.context.logger.error(\n `PayU onSubscriptionPaused error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport async function onSubscriptionResumed(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n status: \"active\" as PayUSubscriptionStatus,\n pausedAt: null,\n updatedAt: new Date(),\n },\n });\n\n const plan = options.subscription.plans\n ? (typeof options.subscription.plans === \"function\"\n ? await options.subscription.plans()\n : options.subscription.plans\n ).find((p) => p.name === sub.plan)\n : undefined;\n\n await options.subscription.onSubscriptionResumed?.({\n subscription: sub,\n plan,\n event,\n });\n }\n } catch (err) {\n ctx.context.logger.error(\n `PayU onSubscriptionResumed error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport async function onMandateRevoked(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n status: \"cancelled\" as PayUSubscriptionStatus,\n cancelledAt: new Date(),\n endedAt: new Date(),\n updatedAt: new Date(),\n },\n });\n\n const plan = options.subscription.plans\n ? (typeof options.subscription.plans === \"function\"\n ? await options.subscription.plans()\n : options.subscription.plans\n ).find((p) => p.name === sub.plan)\n : undefined;\n\n await options.subscription.onMandateRevoked?.({\n subscription: sub,\n plan,\n event,\n });\n }\n } catch (err) {\n ctx.context.logger.error(\n `PayU onMandateRevoked error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\nexport async function onMandateModified(\n ctx: HookContext,\n options: PayUOptions,\n event: PayUWebhookEvent,\n): Promise<void> {\n if (!options.subscription?.enabled) return;\n\n try {\n const sub = await findSubscription(ctx.context.adapter, event);\n\n if (sub) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: sub.id }],\n update: {\n updatedAt: new Date(),\n },\n });\n\n const plan = options.subscription.plans\n ? (typeof options.subscription.plans === \"function\"\n ? await options.subscription.plans()\n : options.subscription.plans\n ).find((p) => p.name === sub.plan)\n : undefined;\n\n await options.subscription.onMandateModified?.({\n subscription: sub,\n plan,\n event,\n });\n }\n } catch (err) {\n ctx.context.logger.error(\n `PayU onMandateModified error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n","import { APIError } from \"better-call\";\nimport { createHmac } from \"crypto\";\nimport type {\n PayUOptions,\n PayUPlan,\n PayUSubscriptionStatus,\n Subscription,\n} from \"./types\";\n\n// ─── API Error Helper ────────────────────────────────────────────────────────\n\nexport function createAPIError(\n status: ConstructorParameters<typeof APIError>[0],\n message: string,\n): APIError {\n return new APIError(status, { body: { message, code: message } });\n}\n\n// ─── Hash Generation ─────────────────────────────────────────────────────────\n\n/**\n * Generate PayU hash using HMAC-SHA256 with merchant salt.\n * Hash formula: sha512(key|txnid|amount|productinfo|firstname|email|udf1|...|udf10||salt)\n */\nexport function generatePayUHash(\n params: {\n key: string;\n txnid: string;\n amount: string;\n productinfo: string;\n firstname: string;\n email: string;\n udf1?: string;\n udf2?: string;\n udf3?: string;\n udf4?: string;\n udf5?: string;\n udf6?: string;\n udf7?: string;\n udf8?: string;\n udf9?: string;\n udf10?: string;\n },\n salt: string,\n): string {\n const hashString = [\n params.key,\n params.txnid,\n params.amount,\n params.productinfo,\n params.firstname,\n params.email,\n params.udf1 || \"\",\n params.udf2 || \"\",\n params.udf3 || \"\",\n params.udf4 || \"\",\n params.udf5 || \"\",\n params.udf6 || \"\",\n params.udf7 || \"\",\n params.udf8 || \"\",\n params.udf9 || \"\",\n params.udf10 || \"\",\n salt,\n ].join(\"|\");\n\n return createHmac(\"sha512\", \"\").update(hashString).digest(\"hex\");\n}\n\n/**\n * Verify PayU webhook/response hash.\n * Reverse hash: sha512(salt|status||||||||||udf10|udf9|...|udf1|email|firstname|productinfo|amount|txnid|key)\n */\nexport function verifyPayUHash(\n params: {\n key: string;\n txnid: string;\n amount: string;\n productinfo: string;\n firstname: string;\n email: string;\n status: string;\n udf1?: string;\n udf2?: string;\n udf3?: string;\n udf4?: string;\n udf5?: string;\n udf6?: string;\n udf7?: string;\n udf8?: string;\n udf9?: string;\n udf10?: string;\n },\n salt: string,\n receivedHash: string,\n): boolean {\n const reverseHashString = [\n salt,\n params.status,\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n params.udf10 || \"\",\n params.udf9 || \"\",\n params.udf8 || \"\",\n params.udf7 || \"\",\n params.udf6 || \"\",\n params.udf5 || \"\",\n params.udf4 || \"\",\n params.udf3 || \"\",\n params.udf2 || \"\",\n params.udf1 || \"\",\n params.email,\n params.firstname,\n params.productinfo,\n params.amount,\n params.txnid,\n params.key,\n ].join(\"|\");\n\n const computedHash = createHmac(\"sha512\", \"\")\n .update(reverseHashString)\n .digest(\"hex\");\n\n return computedHash === receivedHash;\n}\n\n// ─── Plan Lookup Helpers ─────────────────────────────────────────────────────\n\nexport async function getPlans(\n subscriptionOptions: PayUOptions[\"subscription\"],\n): Promise<PayUPlan[]> {\n if (subscriptionOptions?.enabled) {\n return typeof subscriptionOptions.plans === \"function\"\n ? await subscriptionOptions.plans()\n : subscriptionOptions.plans || [];\n }\n throw new Error(\"Subscriptions are not enabled in the PayU options.\");\n}\n\nexport async function getPlanByName(\n options: PayUOptions,\n name: string,\n): Promise<PayUPlan | undefined> {\n return await getPlans(options.subscription).then((res) =>\n res.find((plan) => plan.name.toLowerCase() === name.toLowerCase()),\n );\n}\n\nexport async function getPlanByPlanId(\n options: PayUOptions,\n planId: string,\n): Promise<PayUPlan | undefined> {\n return await getPlans(options.subscription).then((res) =>\n res.find((plan) => plan.planId === planId || plan.annualPlanId === planId),\n );\n}\n\n// ─── Status Checkers ─────────────────────────────────────────────────────────\n\nexport function isActive(sub: Subscription | { status: string }): boolean {\n return sub.status === \"active\";\n}\n\nexport function isAuthenticated(\n sub: Subscription | { status: string },\n): boolean {\n return sub.status === \"authenticated\";\n}\n\nexport function isPaused(sub: Subscription | { status: string }): boolean {\n return sub.status === \"paused\";\n}\n\nexport function isCancelled(sub: Subscription | { status: string }): boolean {\n return sub.status === \"cancelled\";\n}\n\nexport function isTerminal(sub: Subscription | { status: string }): boolean {\n return (\n sub.status === \"cancelled\" ||\n sub.status === \"completed\" ||\n sub.status === \"expired\"\n );\n}\n\nexport function isUsable(sub: Subscription | { status: string }): boolean {\n return sub.status === \"active\" || sub.status === \"authenticated\";\n}\n\nexport function hasPaymentIssue(\n sub: Subscription | { status: string },\n): boolean {\n return sub.status === \"pending\" || sub.status === \"halted\";\n}\n\n// ─── Date Helpers ────────────────────────────────────────────────────────────\n\nexport function timestampToDate(\n timestamp: number | null | undefined,\n): Date | undefined {\n return timestamp ? new Date(timestamp * 1000) : undefined;\n}\n\nexport function dateStringToDate(\n dateStr: string | null | undefined,\n): Date | undefined {\n if (!dateStr) return undefined;\n const d = new Date(dateStr);\n return isNaN(d.getTime()) ? undefined : d;\n}\n\n// ─── Status Mapper ───────────────────────────────────────────────────────────\n\nexport function toSubscriptionStatus(status: string): PayUSubscriptionStatus {\n const validStatuses: PayUSubscriptionStatus[] = [\n \"created\",\n \"authenticated\",\n \"active\",\n \"pending\",\n \"halted\",\n \"cancelled\",\n \"completed\",\n \"expired\",\n \"paused\",\n ];\n if (validStatuses.includes(status as PayUSubscriptionStatus)) {\n return status as PayUSubscriptionStatus;\n }\n return \"created\";\n}\n\n// ─── PayU API Command Hash ───────────────────────────────────────────────────\n\n/**\n * Generate hash for PayU API commands (verify_payment, cancel_refund, etc.)\n * Hash formula: sha512(key|command|var1|salt)\n */\nexport function generateCommandHash(\n key: string,\n command: string,\n var1: string,\n salt: string,\n): string {\n const hashString = `${key}|${command}|${var1}|${salt}`;\n return createHmac(\"sha512\", \"\").update(hashString).digest(\"hex\");\n}\n","import { PAYU_ERROR_CODES } from \"./error-codes\";\nimport type { PayUOptions } from \"./types\";\nimport { createAPIError } from \"./utils\";\n\ntype Context = {\n context: {\n session?: {\n user?: { id: string };\n } | null;\n };\n query?: Record<string, string>;\n body?: Record<string, unknown>;\n};\n\n/**\n * Middleware to extract and validate the authenticated session.\n * Returns the user from the session or throws UNAUTHORIZED.\n */\nexport function payuSessionMiddleware(ctx: Context) {\n const user = ctx.context.session?.user;\n if (!user) {\n throw createAPIError(\"UNAUTHORIZED\", PAYU_ERROR_CODES.UNAUTHORIZED);\n }\n return user;\n}\n\n/**\n * Middleware factory to authorize a reference (user or organization) for\n * subscription actions. Supports org-based subscriptions.\n */\nexport function referenceMiddleware(options: PayUOptions) {\n return async (ctx: Context) => {\n const user = payuSessionMiddleware(ctx);\n const referenceId =\n (ctx.body as Record<string, string>)?.referenceId ??\n ctx.query?.referenceId ??\n user.id;\n\n // If referenceId matches the user, it's a user-level subscription\n if (referenceId === user.id) {\n return { referenceId, type: \"user\" as const, userId: user.id };\n }\n\n // If organizations are enabled, check authorization\n if (options.organization?.enabled) {\n const authorizeReference = options.organization.authorizeReference;\n\n if (authorizeReference) {\n const allowed = await authorizeReference({\n action: \"list-subscriptions\",\n organizationId: referenceId,\n userId: user.id,\n role: undefined,\n });\n\n if (!allowed) {\n throw createAPIError(\n \"FORBIDDEN\",\n PAYU_ERROR_CODES.REFERENCE_ID_NOT_ALLOWED,\n );\n }\n }\n\n return {\n referenceId,\n type: \"organization\" as const,\n userId: user.id,\n };\n }\n\n // referenceId doesn't match user and orgs are disabled\n throw createAPIError(\n \"FORBIDDEN\",\n PAYU_ERROR_CODES.REFERENCE_ID_NOT_ALLOWED,\n );\n };\n}\n","import { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { z } from \"zod\";\nimport { PAYU_ERROR_CODES } from \"./error-codes\";\nimport {\n onMandateModified,\n onMandateRevoked,\n onPaymentFailure,\n onPaymentSuccess,\n onSubscriptionActivated,\n onSubscriptionCancelled,\n onSubscriptionCompleted,\n onSubscriptionHalted,\n onSubscriptionPaused,\n onSubscriptionPending,\n onSubscriptionResumed,\n} from \"./hooks\";\nimport { subscriptionUdf } from \"./metadata\";\nimport { payuSessionMiddleware, referenceMiddleware } from \"./middleware\";\nimport type { PayUOptions, PayUWebhookEvent, Subscription } from \"./types\";\nimport {\n createAPIError,\n generateCommandHash,\n generatePayUHash,\n getPlanByName,\n getPlanByPlanId,\n getPlans,\n isActive,\n isCancelled,\n isPaused,\n isTerminal,\n verifyPayUHash,\n} from \"./utils\";\n\n// ─── Zod Schemas ─────────────────────────────────────────────────────────────\n\nconst createSubscriptionBodySchema = z.object({\n plan: z.string(),\n referenceId: z.string().optional(),\n customerType: z.enum([\"user\", \"organization\"]).optional(),\n mandateType: z.enum([\"card\", \"upi\", \"netbanking\"]).optional(),\n});\n\nconst cancelSubscriptionBodySchema = z.object({\n referenceId: z.string().optional(),\n customerType: z.enum([\"user\", \"organization\"]).optional(),\n cancelAtCycleEnd: z.boolean().optional(),\n});\n\nconst pauseSubscriptionBodySchema = z.object({\n referenceId: z.string().optional(),\n customerType: z.enum([\"user\", \"organization\"]).optional(),\n});\n\nconst resumeSubscriptionBodySchema = z.object({\n referenceId: z.string().optional(),\n customerType: z.enum([\"user\", \"organization\"]).optional(),\n});\n\nconst listSubscriptionsQuerySchema = z.object({\n referenceId: z.string().optional(),\n customerType: z.enum([\"user\", \"organization\"]).optional(),\n});\n\nconst updateSubscriptionBodySchema = z.object({\n referenceId: z.string().optional(),\n customerType: z.enum([\"user\", \"organization\"]).optional(),\n plan: z.string().optional(),\n quantity: z.number().optional(),\n});\n\nconst chargeSubscriptionBodySchema = z.object({\n subscriptionId: z.string(),\n amount: z.string(),\n txnid: z.string(),\n});\n\nconst preDebitNotifyBodySchema = z.object({\n subscriptionId: z.string(),\n amount: z.string(),\n txnid: z.string(),\n debitDate: z.string(),\n});\n\nconst fetchSubscriptionQuerySchema = z.object({\n subscriptionId: z.string(),\n});\n\nconst mandateStatusQuerySchema = z.object({\n subscriptionId: z.string(),\n mandateType: z.enum([\"card\", \"upi\", \"netbanking\"]).optional(),\n});\n\nconst mandateModifyBodySchema = z.object({\n subscriptionId: z.string(),\n amount: z.string(),\n mandateType: z.enum([\"card\", \"upi\", \"netbanking\"]).optional(),\n});\n\nconst initiatePaymentBodySchema = z.object({\n txnid: z.string(),\n amount: z.string(),\n productinfo: z.string(),\n firstname: z.string(),\n email: z.string(),\n phone: z.string(),\n referenceId: z.string().optional(),\n});\n\nconst verifyPaymentBodySchema = z.object({\n txnid: z.string(),\n});\n\nconst initiateRefundBodySchema = z.object({\n mihpayid: z.string(),\n amount: z.string(),\n tokenId: z.string(),\n});\n\nconst refundStatusQuerySchema = z.object({\n requestId: z.string().optional(),\n mihpayid: z.string().optional(),\n});\n\nconst transactionInfoQuerySchema = z.object({\n txnid: z.string(),\n});\n\nconst transactionDetailsQuerySchema = z.object({\n startDate: z.string(),\n endDate: z.string(),\n});\n\nconst validateVpaBodySchema = z.object({\n vpa: z.string(),\n});\n\nconst updateSIBodySchema = z.object({\n subscriptionId: z.string(),\n billingAmount: z.string().optional(),\n billingCycle: z.string().optional(),\n billingInterval: z.number().optional(),\n paymentEndDate: z.string().optional(),\n});\n\nconst fetchPlanQuerySchema = z.object({\n planId: z.string(),\n});\n\nconst payAndSubscribeBodySchema = z.object({\n plan: z.string(),\n referenceId: z.string().optional(),\n customerType: z.enum([\"user\", \"organization\"]).optional(),\n mandateType: z.enum([\"card\", \"upi\", \"netbanking\"]).optional(),\n initialAmount: z.string().optional(),\n});\n\n// ─── Route Factory ───────────────────────────────────────────────────────────\n\nexport function createRoutes(options: PayUOptions) {\n const getReference = referenceMiddleware(options);\n\n return {\n // ─── Subscription: Create ──────────────────────────────────────────\n createSubscription: createAuthEndpoint(\n \"/payu/subscription/create\",\n {\n method: \"POST\",\n body: createSubscriptionBodySchema,\n },\n async (ctx) => {\n const user = payuSessionMiddleware(ctx);\n const ref = await getReference(ctx);\n const body = ctx.body;\n\n if (!options.subscription?.enabled) {\n throw createAPIError(\n \"BAD_REQUEST\",\n PAYU_ERROR_CODES.INVALID_REQUEST_BODY,\n );\n }\n\n const plan = await getPlanByName(options, body.plan);\n if (!plan) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_PLAN_NOT_FOUND,\n );\n }\n\n // Check for existing active subscription\n const existing = (await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [\n { field: \"referenceId\", value: ref.referenceId },\n {\n field: \"status\",\n operator: \"in\",\n value: [\"active\", \"authenticated\"],\n },\n ],\n })) as Subscription | null;\n\n if (existing && existing.plan === body.plan) {\n throw createAPIError(\n \"CONFLICT\",\n PAYU_ERROR_CODES.ALREADY_SUBSCRIBED_PLAN,\n );\n }\n\n // Create subscription record\n const subscription = await ctx.context.adapter.create({\n model: \"subscription\",\n data: {\n plan: plan.name,\n referenceId: ref.referenceId,\n payuCustomerId: null,\n payuSubscriptionId: `payu_sub_${Date.now()}`,\n payuMandateType: body.mandateType || \"card\",\n payuTransactionId: null,\n payuMihpayid: null,\n status: \"created\",\n currentStart: null,\n currentEnd: null,\n endedAt: null,\n quantity: 1,\n totalCount: plan.totalCount,\n paidCount: 0,\n remainingCount: plan.totalCount,\n cancelledAt: null,\n pausedAt: null,\n cancelAtCycleEnd: false,\n billingPeriod: plan.billingCycle,\n seats: null,\n trialStart: null,\n trialEnd: null,\n metadata: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n },\n });\n\n // Generate hash for PayU payment form\n const txnid = `txn_${Date.now()}_${(subscription as Record<string, unknown>).id}`;\n const hash = generatePayUHash(\n {\n key: options.merchantKey,\n txnid,\n amount: plan.amount,\n productinfo: plan.name,\n firstname: user.id,\n email: \"\",\n ...subscriptionUdf.set({\n userId: user.id,\n subscriptionId: (subscription as Record<string, unknown>)\n .id as string,\n referenceId: ref.referenceId,\n }),\n },\n options.merchantSalt,\n );\n\n return ctx.json({\n subscription,\n paymentParams: {\n key: options.merchantKey,\n txnid,\n amount: plan.amount,\n productinfo: plan.name,\n hash,\n mandateType: body.mandateType || \"card\",\n },\n });\n },\n ),\n\n // ─── Subscription: Pay and Subscribe ────────────────────────────────\n payAndSubscribe: createAuthEndpoint(\n \"/payu/subscription/pay-and-subscribe\",\n {\n method: \"POST\",\n body: payAndSubscribeBodySchema,\n },\n async (ctx) => {\n const user = payuSessionMiddleware(ctx);\n const ref = await getReference(ctx);\n const body = ctx.body;\n\n if (!options.subscription?.enabled) {\n throw createAPIError(\n \"BAD_REQUEST\",\n PAYU_ERROR_CODES.INVALID_REQUEST_BODY,\n );\n }\n\n const plan = await getPlanByName(options, body.plan);\n if (!plan) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_PLAN_NOT_FOUND,\n );\n }\n\n const subscription = await ctx.context.adapter.create({\n model: \"subscription\",\n data: {\n plan: plan.name,\n referenceId: ref.referenceId,\n payuSubscriptionId: `payu_sub_${Date.now()}`,\n payuMandateType: body.mandateType || \"card\",\n status: \"created\",\n quantity: 1,\n totalCount: plan.totalCount,\n paidCount: 0,\n remainingCount: plan.totalCount,\n billingPeriod: plan.billingCycle,\n createdAt: new Date(),\n updatedAt: new Date(),\n },\n });\n\n const txnid = `txn_${Date.now()}_${(subscription as Record<string, unknown>).id}`;\n const initialAmount = body.initialAmount || plan.amount;\n const hash = generatePayUHash(\n {\n key: options.merchantKey,\n txnid,\n amount: initialAmount,\n productinfo: plan.name,\n firstname: user.id,\n email: \"\",\n },\n options.merchantSalt,\n );\n\n return ctx.json({\n subscription,\n paymentParams: {\n key: options.merchantKey,\n txnid,\n amount: initialAmount,\n productinfo: plan.name,\n hash,\n mandateType: body.mandateType || \"card\",\n },\n });\n },\n ),\n\n // ─── Subscription: Cancel ──────────────────────────────────────────\n cancelSubscription: createAuthEndpoint(\n \"/payu/subscription/cancel\",\n {\n method: \"POST\",\n body: cancelSubscriptionBodySchema,\n },\n async (ctx) => {\n const ref = await getReference(ctx);\n\n const subscription = (await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [\n { field: \"referenceId\", value: ref.referenceId },\n {\n field: \"status\",\n operator: \"in\",\n value: [\"active\", \"authenticated\"],\n },\n ],\n })) as Subscription | null;\n\n if (!subscription) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,\n );\n }\n\n if (isCancelled(subscription)) {\n throw createAPIError(\n \"BAD_REQUEST\",\n PAYU_ERROR_CODES.SUBSCRIPTION_ALREADY_CANCELLED,\n );\n }\n\n if (isTerminal(subscription)) {\n throw createAPIError(\n \"BAD_REQUEST\",\n PAYU_ERROR_CODES.SUBSCRIPTION_IN_TERMINAL_STATE,\n );\n }\n\n // For cancel at cycle end, just mark it\n if (ctx.body.cancelAtCycleEnd) {\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: subscription.id }],\n update: {\n cancelAtCycleEnd: true,\n updatedAt: new Date(),\n },\n });\n return ctx.json({ success: true, cancelAtCycleEnd: true });\n }\n\n // Call PayU mandate revoke API based on mandate type\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const command =\n subscription.payuMandateType === \"upi\"\n ? \"upi_mandate_revoke\"\n : \"mandate_revoke\";\n\n const hash = generateCommandHash(\n options.merchantKey,\n command,\n subscription.payuTransactionId || \"\",\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/${command}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command,\n var1: subscription.payuTransactionId || \"\",\n hash,\n }),\n });\n\n const result = await response.json();\n\n if (result.status === 0 || result.error) {\n throw createAPIError(\n \"INTERNAL_SERVER_ERROR\",\n PAYU_ERROR_CODES.MANDATE_REVOKE_FAILED,\n );\n }\n\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: subscription.id }],\n update: {\n status: \"cancelled\",\n cancelledAt: new Date(),\n endedAt: new Date(),\n updatedAt: new Date(),\n },\n });\n\n return ctx.json({ success: true });\n },\n ),\n\n // ─── Subscription: Pause ────────────────────────────────────────────\n pauseSubscription: createAuthEndpoint(\n \"/payu/subscription/pause\",\n {\n method: \"POST\",\n body: pauseSubscriptionBodySchema,\n },\n async (ctx) => {\n const ref = await getReference(ctx);\n\n const subscription = (await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [\n { field: \"referenceId\", value: ref.referenceId },\n { field: \"status\", value: \"active\" },\n ],\n })) as Subscription | null;\n\n if (!subscription) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,\n );\n }\n\n if (!isActive(subscription)) {\n throw createAPIError(\n \"BAD_REQUEST\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_ACTIVE,\n );\n }\n\n if (isPaused(subscription)) {\n throw createAPIError(\n \"BAD_REQUEST\",\n PAYU_ERROR_CODES.SUBSCRIPTION_ALREADY_PAUSED,\n );\n }\n\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: subscription.id }],\n update: {\n status: \"paused\",\n pausedAt: new Date(),\n updatedAt: new Date(),\n },\n });\n\n return ctx.json({ success: true });\n },\n ),\n\n // ─── Subscription: Resume ───────────────────────────────────────────\n resumeSubscription: createAuthEndpoint(\n \"/payu/subscription/resume\",\n {\n method: \"POST\",\n body: resumeSubscriptionBodySchema,\n },\n async (ctx) => {\n const ref = await getReference(ctx);\n\n const subscription = (await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [\n { field: \"referenceId\", value: ref.referenceId },\n { field: \"status\", value: \"paused\" },\n ],\n })) as Subscription | null;\n\n if (!subscription) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,\n );\n }\n\n if (!isPaused(subscription)) {\n throw createAPIError(\n \"BAD_REQUEST\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_PAUSED,\n );\n }\n\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: subscription.id }],\n update: {\n status: \"active\",\n pausedAt: null,\n updatedAt: new Date(),\n },\n });\n\n return ctx.json({ success: true });\n },\n ),\n\n // ─── Subscription: List ─────────────────────────────────────────────\n listSubscriptions: createAuthEndpoint(\n \"/payu/subscription/list\",\n {\n method: \"GET\",\n query: listSubscriptionsQuerySchema,\n },\n async (ctx) => {\n const ref = await getReference(ctx);\n\n const subscriptions = await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [{ field: \"referenceId\", value: ref.referenceId }],\n });\n\n return ctx.json({\n subscriptions: subscriptions ? [subscriptions] : [],\n });\n },\n ),\n\n // ─── Subscription: Get ──────────────────────────────────────────────\n getSubscription: createAuthEndpoint(\n \"/payu/subscription/get\",\n {\n method: \"GET\",\n query: fetchSubscriptionQuerySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const { subscriptionId } = ctx.query;\n\n const subscription = await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [{ field: \"id\", value: subscriptionId }],\n });\n\n if (!subscription) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,\n );\n }\n\n return ctx.json({ subscription });\n },\n ),\n\n // ─── Subscription: Update ───────────────────────────────────────────\n updateSubscription: createAuthEndpoint(\n \"/payu/subscription/update\",\n {\n method: \"POST\",\n body: updateSubscriptionBodySchema,\n },\n async (ctx) => {\n const ref = await getReference(ctx);\n const body = ctx.body;\n\n const subscription = (await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [\n { field: \"referenceId\", value: ref.referenceId },\n {\n field: \"status\",\n operator: \"in\",\n value: [\"active\", \"authenticated\"],\n },\n ],\n })) as Subscription | null;\n\n if (!subscription) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,\n );\n }\n\n const updateData: Record<string, unknown> = { updatedAt: new Date() };\n\n if (body.plan) {\n const plan = await getPlanByName(options, body.plan);\n if (!plan) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_PLAN_NOT_FOUND,\n );\n }\n updateData.plan = plan.name;\n updateData.billingPeriod = plan.billingCycle;\n updateData.totalCount = plan.totalCount;\n }\n\n if (body.quantity !== undefined) {\n updateData.quantity = body.quantity;\n }\n\n await ctx.context.adapter.update({\n model: \"subscription\",\n where: [{ field: \"id\", value: subscription.id }],\n update: updateData,\n });\n\n return ctx.json({ success: true });\n },\n ),\n\n // ─── Pre-Debit Notification ─────────────────────────────────────────\n preDebitNotify: createAuthEndpoint(\n \"/payu/subscription/pre-debit-notify\",\n {\n method: \"POST\",\n body: preDebitNotifyBodySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const body = ctx.body;\n\n const subscription = (await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [{ field: \"id\", value: body.subscriptionId }],\n })) as Subscription | null;\n\n if (!subscription) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,\n );\n }\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const hash = generateCommandHash(\n options.merchantKey,\n \"pre_debit_SI\",\n body.txnid,\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/pre_debit_SI`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command: \"pre_debit_SI\",\n var1: body.txnid,\n var2: body.amount,\n var3: body.debitDate,\n hash,\n }),\n });\n\n const result = await response.json();\n\n if (result.status === 0 || result.error) {\n throw createAPIError(\n \"INTERNAL_SERVER_ERROR\",\n PAYU_ERROR_CODES.PRE_DEBIT_NOTIFICATION_FAILED,\n );\n }\n\n return ctx.json({ success: true, result });\n },\n ),\n\n // ─── Subscription: Charge (Recurring Payment) ───────────────────────\n chargeSubscription: createAuthEndpoint(\n \"/payu/subscription/charge\",\n {\n method: \"POST\",\n body: chargeSubscriptionBodySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const body = ctx.body;\n\n const subscription = (await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [{ field: \"id\", value: body.subscriptionId }],\n })) as Subscription | null;\n\n if (!subscription) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,\n );\n }\n\n if (!isActive(subscription)) {\n throw createAPIError(\n \"BAD_REQUEST\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_ACTIVE,\n );\n }\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const hash = generateCommandHash(\n options.merchantKey,\n \"si_transaction\",\n body.txnid,\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/si_transaction`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command: \"si_transaction\",\n var1: body.txnid,\n var2: body.amount,\n hash,\n }),\n });\n\n const result = await response.json();\n\n if (result.status === 0 || result.error) {\n throw createAPIError(\n \"INTERNAL_SERVER_ERROR\",\n PAYU_ERROR_CODES.PAYMENT_INITIATION_FAILED,\n );\n }\n\n return ctx.json({ success: true, result });\n },\n ),\n\n // ─── Update Standing Instruction ────────────────────────────────────\n updateSI: createAuthEndpoint(\n \"/payu/subscription/update-si\",\n {\n method: \"POST\",\n body: updateSIBodySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const body = ctx.body;\n\n const subscription = (await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [{ field: \"id\", value: body.subscriptionId }],\n })) as Subscription | null;\n\n if (!subscription) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,\n );\n }\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const hash = generateCommandHash(\n options.merchantKey,\n \"update_si\",\n subscription.payuTransactionId || \"\",\n options.merchantSalt,\n );\n\n const params: Record<string, string> = {\n key: options.merchantKey,\n command: \"update_si\",\n var1: subscription.payuTransactionId || \"\",\n hash,\n };\n\n if (body.billingAmount) params.var2 = body.billingAmount;\n if (body.billingCycle) params.var3 = body.billingCycle;\n if (body.billingInterval !== undefined)\n params.var4 = String(body.billingInterval);\n if (body.paymentEndDate) params.var5 = body.paymentEndDate;\n\n const response = await fetch(`${apiUrl}/merchant/update_si`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams(params),\n });\n\n const result = await response.json();\n\n if (result.status === 0 || result.error) {\n throw createAPIError(\n \"INTERNAL_SERVER_ERROR\",\n PAYU_ERROR_CODES.SI_UPDATE_FAILED,\n );\n }\n\n return ctx.json({ success: true, result });\n },\n ),\n\n // ─── Mandate: Status ────────────────────────────────────────────────\n mandateStatus: createAuthEndpoint(\n \"/payu/mandate/status\",\n {\n method: \"GET\",\n query: mandateStatusQuerySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const { subscriptionId, mandateType } = ctx.query;\n\n const subscription = (await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [{ field: \"id\", value: subscriptionId }],\n })) as Subscription | null;\n\n if (!subscription) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,\n );\n }\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const mType = mandateType || subscription.payuMandateType || \"card\";\n let command: string;\n\n if (mType === \"upi\") {\n command = \"upi_mandate_status\";\n } else if (mType === \"netbanking\") {\n command = \"net_banking_mandate_status\";\n } else {\n command = \"check_mandate_status\";\n }\n\n const hash = generateCommandHash(\n options.merchantKey,\n command,\n subscription.payuTransactionId || \"\",\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/${command}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command,\n var1: subscription.payuTransactionId || \"\",\n hash,\n }),\n });\n\n const result = await response.json();\n\n if (result.status === 0 || result.error) {\n throw createAPIError(\n \"INTERNAL_SERVER_ERROR\",\n PAYU_ERROR_CODES.MANDATE_STATUS_CHECK_FAILED,\n );\n }\n\n return ctx.json({ mandate: result });\n },\n ),\n\n // ─── Mandate: Modify ────────────────────────────────────────────────\n mandateModify: createAuthEndpoint(\n \"/payu/mandate/modify\",\n {\n method: \"POST\",\n body: mandateModifyBodySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const body = ctx.body;\n\n const subscription = (await ctx.context.adapter.findOne({\n model: \"subscription\",\n where: [{ field: \"id\", value: body.subscriptionId }],\n })) as Subscription | null;\n\n if (!subscription) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_NOT_FOUND,\n );\n }\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const mType =\n body.mandateType || subscription.payuMandateType || \"card\";\n let command: string;\n\n if (mType === \"upi\") {\n command = \"upi_mandate_modify\";\n } else {\n command = \"mandate_modify\";\n }\n\n const hash = generateCommandHash(\n options.merchantKey,\n command,\n subscription.payuTransactionId || \"\",\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/${command}`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command,\n var1: subscription.payuTransactionId || \"\",\n var2: body.amount,\n hash,\n }),\n });\n\n const result = await response.json();\n\n if (result.status === 0 || result.error) {\n throw createAPIError(\n \"INTERNAL_SERVER_ERROR\",\n PAYU_ERROR_CODES.MANDATE_MODIFY_FAILED,\n );\n }\n\n return ctx.json({ success: true, result });\n },\n ),\n\n // ─── Payment: Initiate ──────────────────────────────────────────────\n initiatePayment: createAuthEndpoint(\n \"/payu/payment/initiate\",\n {\n method: \"POST\",\n body: initiatePaymentBodySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const body = ctx.body;\n\n const hash = generatePayUHash(\n {\n key: options.merchantKey,\n txnid: body.txnid,\n amount: body.amount,\n productinfo: body.productinfo,\n firstname: body.firstname,\n email: body.email,\n },\n options.merchantSalt,\n );\n\n return ctx.json({\n paymentParams: {\n key: options.merchantKey,\n txnid: body.txnid,\n amount: body.amount,\n productinfo: body.productinfo,\n firstname: body.firstname,\n email: body.email,\n phone: body.phone,\n hash,\n surl: `${options.apiBaseUrl || \"\"}/payu/webhook`,\n furl: `${options.apiBaseUrl || \"\"}/payu/webhook`,\n },\n });\n },\n ),\n\n // ─── Payment: Verify ────────────────────────────────────────────────\n verifyPayment: createAuthEndpoint(\n \"/payu/payment/verify\",\n {\n method: \"POST\",\n body: verifyPaymentBodySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const { txnid } = ctx.body;\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const hash = generateCommandHash(\n options.merchantKey,\n \"verify_payment\",\n txnid,\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/postservice?form=2`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command: \"verify_payment\",\n var1: txnid,\n hash,\n }),\n });\n\n const result = await response.json();\n\n if (result.status === 0 || result.error) {\n throw createAPIError(\n \"INTERNAL_SERVER_ERROR\",\n PAYU_ERROR_CODES.PAYMENT_VERIFICATION_FAILED,\n );\n }\n\n return ctx.json({ transaction: result });\n },\n ),\n\n // ─── Payment: Check ─────────────────────────────────────────────────\n checkPayment: createAuthEndpoint(\n \"/payu/payment/check\",\n {\n method: \"POST\",\n body: z.object({ mihpayid: z.string() }),\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const { mihpayid } = ctx.body;\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const hash = generateCommandHash(\n options.merchantKey,\n \"check_payment\",\n mihpayid,\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/postservice?form=2`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command: \"check_payment\",\n var1: mihpayid,\n hash,\n }),\n });\n\n const result = await response.json();\n\n return ctx.json({ transaction: result });\n },\n ),\n\n // ─── Refund: Initiate ───────────────────────────────────────────────\n initiateRefund: createAuthEndpoint(\n \"/payu/refund/initiate\",\n {\n method: \"POST\",\n body: initiateRefundBodySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const body = ctx.body;\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const hash = generateCommandHash(\n options.merchantKey,\n \"cancel_refund_transaction\",\n body.mihpayid,\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/postservice?form=2`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command: \"cancel_refund_transaction\",\n var1: body.mihpayid,\n var2: body.tokenId,\n var3: body.amount,\n hash,\n }),\n });\n\n const result = await response.json();\n\n if (result.status === 0 || result.error) {\n throw createAPIError(\n \"INTERNAL_SERVER_ERROR\",\n PAYU_ERROR_CODES.REFUND_INITIATION_FAILED,\n );\n }\n\n return ctx.json({ success: true, refund: result });\n },\n ),\n\n // ─── Refund: Status ─────────────────────────────────────────────────\n refundStatus: createAuthEndpoint(\n \"/payu/refund/status\",\n {\n method: \"GET\",\n query: refundStatusQuerySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const { requestId, mihpayid } = ctx.query;\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n let command: string;\n let var1: string;\n\n if (requestId) {\n command = \"check_action_status\";\n var1 = requestId;\n } else if (mihpayid) {\n command = \"check_action_status\";\n var1 = mihpayid;\n } else {\n throw createAPIError(\n \"BAD_REQUEST\",\n PAYU_ERROR_CODES.INVALID_REQUEST_BODY,\n );\n }\n\n const hash = generateCommandHash(\n options.merchantKey,\n command,\n var1,\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/postservice?form=2`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command,\n var1,\n hash,\n }),\n });\n\n const result = await response.json();\n\n return ctx.json({ refundStatus: result });\n },\n ),\n\n // ─── Refund: List ───────────────────────────────────────────────────\n listRefunds: createAuthEndpoint(\n \"/payu/refund/list\",\n {\n method: \"POST\",\n body: z.object({ mihpayids: z.array(z.string()) }),\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const { mihpayids } = ctx.body;\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const var1 = mihpayids.join(\"|\");\n const hash = generateCommandHash(\n options.merchantKey,\n \"get_all_refunds_from_transaction_ids\",\n var1,\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/postservice?form=2`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command: \"get_all_refunds_from_transaction_ids\",\n var1,\n hash,\n }),\n });\n\n const result = await response.json();\n\n return ctx.json({ refunds: result });\n },\n ),\n\n // ─── Transaction: Info ──────────────────────────────────────────────\n transactionInfo: createAuthEndpoint(\n \"/payu/transaction/info\",\n {\n method: \"GET\",\n query: transactionInfoQuerySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const { txnid } = ctx.query;\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const hash = generateCommandHash(\n options.merchantKey,\n \"get_transaction_info\",\n txnid,\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/postservice?form=2`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command: \"get_transaction_info\",\n var1: txnid,\n hash,\n }),\n });\n\n const result = await response.json();\n\n return ctx.json({ transaction: result });\n },\n ),\n\n // ─── Transaction: Details ───────────────────────────────────────────\n transactionDetails: createAuthEndpoint(\n \"/payu/transaction/details\",\n {\n method: \"GET\",\n query: transactionDetailsQuerySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const { startDate, endDate } = ctx.query;\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const hash = generateCommandHash(\n options.merchantKey,\n \"get_Transaction_Details\",\n startDate,\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/postservice?form=2`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command: \"get_Transaction_Details\",\n var1: startDate,\n var2: endDate,\n hash,\n }),\n });\n\n const result = await response.json();\n\n return ctx.json({ transactions: result });\n },\n ),\n\n // ─── VPA: Validate ──────────────────────────────────────────────────\n validateVpa: createAuthEndpoint(\n \"/payu/upi/validate-vpa\",\n {\n method: \"POST\",\n body: validateVpaBodySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const { vpa } = ctx.body;\n\n const apiUrl = options.apiBaseUrl || \"https://info.payu.in\";\n const hash = generateCommandHash(\n options.merchantKey,\n \"validateVPA\",\n vpa,\n options.merchantSalt,\n );\n\n const response = await fetch(`${apiUrl}/merchant/postservice?form=2`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n key: options.merchantKey,\n command: \"validateVPA\",\n var1: vpa,\n hash,\n }),\n });\n\n const result = await response.json();\n\n if (result.status === 0 || result.isVPAValid === 0) {\n throw createAPIError(\"BAD_REQUEST\", PAYU_ERROR_CODES.INVALID_VPA);\n }\n\n return ctx.json({ valid: true, result });\n },\n ),\n\n // ─── Plan: List ─────────────────────────────────────────────────────\n listPlans: createAuthEndpoint(\n \"/payu/plan/list\",\n {\n method: \"GET\",\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n\n if (!options.subscription?.enabled) {\n return ctx.json({ plans: [] });\n }\n\n const plans = await getPlans(options.subscription);\n return ctx.json({ plans });\n },\n ),\n\n // ─── Plan: Get ──────────────────────────────────────────────────────\n getPlan: createAuthEndpoint(\n \"/payu/plan/get\",\n {\n method: \"GET\",\n query: fetchPlanQuerySchema,\n },\n async (ctx) => {\n payuSessionMiddleware(ctx);\n const { planId } = ctx.query;\n\n const plan = await getPlanByPlanId(options, planId);\n if (!plan) {\n throw createAPIError(\n \"NOT_FOUND\",\n PAYU_ERROR_CODES.SUBSCRIPTION_PLAN_NOT_FOUND,\n );\n }\n\n return ctx.json({ plan });\n },\n ),\n\n // ─── Webhook ────────────────────────────────────────────────────────\n webhook: createAuthEndpoint(\n \"/payu/webhook\",\n {\n method: \"POST\",\n },\n async (ctx) => {\n const body = ctx.body as Record<string, string>;\n\n if (!body || !body.hash) {\n throw createAPIError(\n \"BAD_REQUEST\",\n PAYU_ERROR_CODES.WEBHOOK_HASH_NOT_FOUND,\n );\n }\n\n // Verify hash\n const isValid = verifyPayUHash(\n {\n key: body.key || options.merchantKey,\n txnid: body.txnid || \"\",\n amount: body.amount || \"\",\n productinfo: body.productinfo || \"\",\n firstname: body.firstname || \"\",\n email: body.email || \"\",\n status: body.status || \"\",\n udf1: body.udf1,\n udf2: body.udf2,\n udf3: body.udf3,\n udf4: body.udf4,\n udf5: body.udf5,\n udf6: body.udf6,\n udf7: body.udf7,\n udf8: body.udf8,\n udf9: body.udf9,\n udf10: body.udf10,\n },\n options.merchantSalt,\n body.hash,\n );\n\n if (!isValid) {\n throw createAPIError(\n \"UNAUTHORIZED\",\n PAYU_ERROR_CODES.FAILED_TO_VERIFY_WEBHOOK,\n );\n }\n\n const event: PayUWebhookEvent = {\n mihpayid: body.mihpayid || \"\",\n status: body.status || \"\",\n txnid: body.txnid || \"\",\n amount: body.amount || \"\",\n productinfo: body.productinfo || \"\",\n firstname: body.firstname || \"\",\n email: body.email || \"\",\n phone: body.phone || \"\",\n hash: body.hash,\n key: body.key || \"\",\n mode: body.mode || \"\",\n unmappedstatus: body.unmappedstatus || \"\",\n field9: body.field9 || \"\",\n error: body.error_Message || body.error || \"\",\n bank_ref_num: body.bank_ref_num || \"\",\n addedon: body.addedon || \"\",\n payment_source: body.payment_source || \"\",\n udf1: body.udf1,\n udf2: body.udf2,\n udf3: body.udf3,\n udf4: body.udf4,\n udf5: body.udf5,\n udf6: body.udf6,\n udf7: body.udf7,\n udf8: body.udf8,\n udf9: body.udf9,\n udf10: body.udf10,\n notificationType: body.notificationType,\n };\n\n // Route based on status and notification type\n const status = body.status?.toLowerCase();\n const notifType = body.notificationType?.toLowerCase();\n\n if (notifType === \"mandate_revoked\" || notifType === \"si_cancelled\") {\n await onMandateRevoked(ctx, options, event);\n } else if (\n notifType === \"mandate_modified\" ||\n notifType === \"si_modified\"\n ) {\n await onMandateModified(ctx, options, event);\n } else if (status === \"success\" || status === \"captured\") {\n await onPaymentSuccess(ctx, options, event);\n await onSubscriptionActivated(ctx, options, event);\n } else if (status === \"failure\" || status === \"failed\") {\n await onPaymentFailure(ctx, options, event);\n } else if (status === \"pending\") {\n await onSubscriptionPending(ctx, options, event);\n } else if (status === \"cancelled\") {\n await onSubscriptionCancelled(ctx, options, event);\n } else if (status === \"halted\") {\n await onSubscriptionHalted(ctx, options, event);\n } else if (status === \"completed\") {\n await onSubscriptionCompleted(ctx, options, event);\n } else if (status === \"paused\") {\n await onSubscriptionPaused(ctx, options, event);\n } else if (status === \"resumed\" || status === \"active\") {\n await onSubscriptionResumed(ctx, options, event);\n }\n\n return ctx.json({ success: true });\n },\n ),\n };\n}\n","import type { BetterAuthPluginDBSchema } from \"@better-auth/core/db\";\nimport { mergeSchema } from \"better-auth/db\";\nimport type { PayUOptions } from \"./types\";\n\nexport const subscriptions = {\n subscription: {\n fields: {\n plan: {\n type: \"string\",\n required: true,\n },\n referenceId: {\n type: \"string\",\n required: true,\n },\n payuCustomerId: {\n type: \"string\",\n required: false,\n },\n payuSubscriptionId: {\n type: \"string\",\n required: false,\n },\n payuMandateType: {\n type: \"string\",\n required: false,\n },\n payuTransactionId: {\n type: \"string\",\n required: false,\n },\n payuMihpayid: {\n type: \"string\",\n required: false,\n },\n status: {\n type: \"string\",\n defaultValue: \"created\",\n },\n currentStart: {\n type: \"date\",\n required: false,\n },\n currentEnd: {\n type: \"date\",\n required: false,\n },\n endedAt: {\n type: \"date\",\n required: false,\n },\n quantity: {\n type: \"number\",\n required: false,\n defaultValue: 1,\n },\n totalCount: {\n type: \"number\",\n required: false,\n },\n paidCount: {\n type: \"number\",\n required: false,\n defaultValue: 0,\n },\n remainingCount: {\n type: \"number\",\n required: false,\n },\n cancelledAt: {\n type: \"date\",\n required: false,\n },\n pausedAt: {\n type: \"date\",\n required: false,\n },\n cancelAtCycleEnd: {\n type: \"boolean\",\n required: false,\n defaultValue: false,\n },\n billingPeriod: {\n type: \"string\",\n required: false,\n },\n seats: {\n type: \"number\",\n required: false,\n },\n trialStart: {\n type: \"date\",\n required: false,\n },\n trialEnd: {\n type: \"date\",\n required: false,\n },\n metadata: {\n type: \"string\",\n required: false,\n },\n },\n },\n} satisfies BetterAuthPluginDBSchema;\n\nexport const user = {\n user: {\n fields: {\n payuCustomerId: {\n type: \"string\",\n required: false,\n },\n },\n },\n} satisfies BetterAuthPluginDBSchema;\n\nexport const organization = {\n organization: {\n fields: {\n payuCustomerId: {\n type: \"string\",\n required: false,\n },\n },\n },\n} satisfies BetterAuthPluginDBSchema;\n\ntype GetSchemaResult<O extends PayUOptions> = typeof user &\n (O[\"subscription\"] extends { enabled: true } ? typeof subscriptions : {}) &\n (O[\"organization\"] extends { enabled: true } ? typeof organization : {});\n\nexport const getSchema = <O extends PayUOptions>(\n options: O,\n): GetSchemaResult<O> => {\n let baseSchema: BetterAuthPluginDBSchema = {};\n\n if (options.subscription?.enabled) {\n baseSchema = {\n ...subscriptions,\n ...user,\n };\n } else {\n baseSchema = {\n ...user,\n };\n }\n\n if (options.organization?.enabled) {\n baseSchema = {\n ...baseSchema,\n ...organization,\n };\n }\n\n if (\n options.schema &&\n !options.subscription?.enabled &&\n \"subscription\" in options.schema\n ) {\n const { subscription: _subscription, ...restSchema } = options.schema;\n return mergeSchema(baseSchema, restSchema) as GetSchemaResult<O>;\n }\n\n return mergeSchema(baseSchema, options.schema) as GetSchemaResult<O>;\n};\n","import type { BetterAuthPlugin } from \"better-auth\";\nimport type { Organization } from \"better-auth/plugins/organization\";\nimport { PAYU_ERROR_CODES } from \"./error-codes\";\nimport { createRoutes } from \"./routes\";\nimport { getSchema } from \"./schema\";\nimport type { PayUOptions, Subscription } from \"./types\";\nimport { createAPIError, isActive } from \"./utils\";\n\ndeclare module \"@better-auth/core\" {\n interface BetterAuthPluginRegistry<AuthOptions, Options> {\n payu: {\n creator: typeof payu;\n };\n }\n}\n\nexport const payu = <O extends PayUOptions>(options: O) => {\n const routes = createRoutes(options);\n\n const subscriptionEndpoints = {\n payuCreateSubscription: routes.createSubscription,\n payuPayAndSubscribe: routes.payAndSubscribe,\n payuCancelSubscription: routes.cancelSubscription,\n payuPauseSubscription: routes.pauseSubscription,\n payuResumeSubscription: routes.resumeSubscription,\n payuListSubscriptions: routes.listSubscriptions,\n payuGetSubscription: routes.getSubscription,\n payuUpdateSubscription: routes.updateSubscription,\n payuPreDebitNotify: routes.preDebitNotify,\n payuChargeSubscription: routes.chargeSubscription,\n payuUpdateSI: routes.updateSI,\n };\n\n const mandateEndpoints = {\n payuMandateStatus: routes.mandateStatus,\n payuMandateModify: routes.mandateModify,\n };\n\n const paymentEndpoints = {\n payuInitiatePayment: routes.initiatePayment,\n payuVerifyPayment: routes.verifyPayment,\n payuCheckPayment: routes.checkPayment,\n };\n\n const refundEndpoints = {\n payuInitiateRefund: routes.initiateRefund,\n payuRefundStatus: routes.refundStatus,\n payuListRefunds: routes.listRefunds,\n };\n\n const transactionEndpoints = {\n payuTransactionInfo: routes.transactionInfo,\n payuTransactionDetails: routes.transactionDetails,\n };\n\n const utilityEndpoints = {\n payuValidateVpa: routes.validateVpa,\n payuListPlans: routes.listPlans,\n payuGetPlan: routes.getPlan,\n };\n\n return {\n id: \"payu\",\n endpoints: {\n payuWebhook: routes.webhook,\n ...paymentEndpoints,\n ...refundEndpoints,\n ...transactionEndpoints,\n ...utilityEndpoints,\n ...mandateEndpoints,\n ...((options.subscription?.enabled\n ? subscriptionEndpoints\n : {}) as O[\"subscription\"] extends {\n enabled: true;\n }\n ? typeof subscriptionEndpoints\n : {}),\n },\n init(ctx) {\n if (options.organization?.enabled) {\n const orgPlugin = ctx.getPlugin(\"organization\");\n if (!orgPlugin) {\n ctx.logger.error(`Organization plugin not found`);\n return;\n }\n\n const existingHooks = orgPlugin.options?.organizationHooks ?? {};\n\n /**\n * Block organization deletion when there's an active subscription\n */\n const beforeDeletePayUOrg = async (data: {\n organization: Organization;\n }) => {\n const subscription = (await ctx.adapter.findOne({\n model: \"subscription\",\n where: [\n {\n field: \"referenceId\",\n value: data.organization.id,\n },\n ],\n })) as Subscription | null;\n\n if (subscription && isActive(subscription)) {\n throw createAPIError(\n \"BAD_REQUEST\",\n PAYU_ERROR_CODES.ORGANIZATION_ON_ACTIVE_SUBSCRIPTION,\n );\n }\n };\n\n orgPlugin.options = {\n ...orgPlugin.options,\n organizationHooks: {\n ...existingHooks,\n beforeDeleteOrganization: async (data: {\n organization: Organization;\n }) => {\n if (existingHooks.beforeDeleteOrganization) {\n await existingHooks.beforeDeleteOrganization(data);\n }\n await beforeDeletePayUOrg(data);\n },\n },\n };\n }\n },\n schema: getSchema(options),\n hooks: {\n after: [\n {\n matcher(context) {\n return context.path === \"/user/update\";\n },\n async handler(ctx) {\n // Sync user updates if needed\n },\n },\n ],\n },\n } satisfies BetterAuthPlugin;\n};\n\n// Export types and utilities\nexport { PAYU_ERROR_CODES } from \"./error-codes\";\nexport {\n customerUdf,\n paramsToUdf,\n subscriptionUdf,\n udfToParams,\n} from \"./metadata\";\nexport type {\n PayUTransactionResponse,\n PayUWebhookEvent,\n Subscription,\n SubscriptionCallbackData,\n SubscriptionOptions,\n} from \"./types\";\nexport {\n dateStringToDate,\n generateCommandHash,\n generatePayUHash,\n hasPaymentIssue,\n isActive,\n isAuthenticated,\n isCancelled,\n isPaused,\n isTerminal,\n isUsable,\n timestampToDate,\n toSubscriptionStatus,\n verifyPayUHash,\n} from \"./utils\";\n"],"x_google_ignoreList":[0,1,2,3],"mappings":";;;;;;;;AACA,MAAM,SAAS,OAAO,IAAI,qBAAqB;AAC/C,IAAI,OAAO;AACX,MAAM,YAAY,EAAE;AACpB,MAAM,sBAAsB;;;;;;;;;;;AAW5B,SAAS,wBAAwB;AAChC,KAAI,CAAC,WAAW,SAAS;AACxB,aAAW,UAAU;GACpB,SAAS;GACT,OAAO;GACP,SAAS;GACT;AACD,SAAO,WAAW;;AAEnB,QAAO,WAAW;AAClB,KAAI,KAAK,YAAY,qBAAqB;AACzC,OAAK,UAAU;AACf,OAAK;;AAEN,QAAO,WAAW;;;;;AC5BnB,MAAM,2BAA2B;;;CAGhC;EACC,MAAM,QAAQ,IAAI,kBAAkB,CAAC,OAAO,QAAQ;AACrD,KAAI,uBAAuB,WAAY,QAAO,WAAW;AACzD,KAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,SAAQ,KAAK,yHAAyH;AACtI,SAAQ,KAAK,+GAA+G;AAC5H,SAAQ,KAAK,wKAAwK;AACrL,OAAM;EACL;AACF,eAAe,uBAAuB;CACrC,MAAM,MAAM,MAAM;AAClB,KAAI,QAAQ,KAAM,OAAM,IAAI,MAAM,wDAAwD;KACrF,QAAO;;;;;ACZb,MAAM,qBAAqB,YAAY;CACtC,MAAM,mBAAmB,uBAAuB;AAChD,KAAI,CAAC,iBAAiB,QAAQ,6BAA6B;EAC1D,MAAM,sBAAsB,MAAM,sBAAsB;AACxD,mBAAiB,QAAQ,8BAA8B,IAAI,qBAAqB;;AAEjF,QAAO,iBAAiB,QAAQ;;AAejC,eAAe,uBAAuB,SAAS,IAAI;AAClD,SAAQ,MAAM,oBAAoB,EAAE,IAAI,SAAS,GAAG;;;;;ACrBrD,MAAM,oBAAoB,iBAAiB,YAAY;;;;;;AAMtD,QAAO,EAAE;EACR;AACF,MAAM,uBAAuB,iBAAiB,OAAO,EAAE,KAAK,CAAC,mBAAmB,iBAAiB,YAAY;AAC5G,QAAO,EAAE;EACR,CAAC,EAAE,CAAC;AACN,MAAM,MAAM,CAAC,kBAAkB;AAC/B,SAAS,mBAAmB,eAAe,kBAAkB,gBAAgB;CAC5E,MAAM,OAAO,OAAO,kBAAkB,WAAW,gBAAgB,KAAK;CACtE,MAAM,UAAU,OAAO,qBAAqB,WAAW,mBAAmB;CAC1E,MAAM,UAAU,OAAO,qBAAqB,aAAa,mBAAmB;AAC5E,KAAI,KAAM,QAAO,eAAe,MAAM;EACrC,GAAG;EACH,KAAK,CAAC,GAAG,SAAS,OAAO,EAAE,EAAE,GAAG,IAAI;EACpC,EAAE,OAAO,QAAQ,uBAAuB,WAAW,QAAQ,IAAI,CAAC,CAAC;AAClE,QAAO,eAAe;EACrB,GAAG;EACH,KAAK,CAAC,GAAG,SAAS,OAAO,EAAE,EAAE,GAAG,IAAI;EACpC,EAAE,OAAO,QAAQ,uBAAuB,WAAW,QAAQ,IAAI,CAAC,CAAC;;;;;ACFnE,MAAa,cAAc;CAEzB,MAAM;EAAC;EAAgB;EAAU;EAAiB;CAMlD,IAAI,gBAAqC,SAA4B;AASnE,SAAO,KARmB;GACxB,MAAM,eAAe;GACrB,MAAM,YAAY,iBAAiB,eAAe,SAAS;GAC3D,MACE,oBAAoB,iBAChB,eAAe,iBACf;GACP,EACqB,WAAW,EAAE,CAAC;;CAMtC,IAAI,KAAiC;AACnC,MAAI,CAAC,IACH,QAAO;GACL,QAAQ;GACR,gBAAgB;GAChB,cAAc;GAGf;AAEH,SAAO;GACL,QAAQ,IAAI;GACZ,gBAAgB,IAAI;GACpB,cAAc,IAAI;GACnB;;CAEJ;AAID,MAAa,kBAAkB;CAE7B,MAAM;EAAC;EAAU;EAAkB;EAAc;CAMjD,IAAI,gBAAyC,SAA4B;AAMvE,SAAO,KALmB;GACxB,MAAM,eAAe;GACrB,MAAM,eAAe;GACrB,MAAM,eAAe;GACtB,EACqB,WAAW,EAAE,CAAC;;CAMtC,IAAI,KAAiC;AACnC,MAAI,CAAC,IACH,QAAO;GACL,QAAQ;GACR,gBAAgB;GAChB,aAAa;GACd;AAEH,SAAO;GACL,QAAQ,IAAI;GACZ,gBAAgB,IAAI;GACpB,aAAa,IAAI;GAClB;;CAEJ;;;;AAOD,SAAgB,YAAY,KAAsC;CAChE,MAAM,SAAiC,EAAE;AACzC,MAAK,IAAI,IAAI,GAAG,KAAK,IAAI,KAAK;EAC5B,MAAM,MAAM,MAAM;AAClB,MAAI,IAAI,KACN,QAAO,OAAO,IAAI;;AAGtB,QAAO;;;;;AAMT,SAAgB,YACd,QACS;CACT,MAAM,MAAe,EAAE;AACvB,MAAK,IAAI,IAAI,GAAG,KAAK,IAAI,KAAK;EAC5B,MAAM,MAAM,MAAM;AAClB,MAAI,OAAO,KACT,KAAI,OAAO,OAAO;;AAGtB,QAAO;;;;;ACxGT,eAAe,wBACb,SACA,OAC8B;AAK9B,QAJe,MAAM,QAAQ,QAAQ;EACnC,OAAO;EACP,OAAO,CAAC;GAAE,OAAO;GAAqB,OAAO;GAAO,CAAC;EACtD,CAAC;;AAIJ,eAAe,sBACb,SACA,OAC8B;CAC9B,MAAM,MAAM,YAAY,MAA2C;CACnE,MAAM,SAAS,gBAAgB,IAAI,IAAI;AAEvC,KAAI,OAAO,eAKT,QAJe,MAAM,QAAQ,QAAQ;EACnC,OAAO;EACP,OAAO,CAAC;GAAE,OAAO;GAAM,OAAO,OAAO;GAAgB,CAAC;EACvD,CAAC;AAIJ,QAAO;;AAGT,eAAe,iBACb,SACA,OAC8B;CAE9B,MAAM,QAAQ,MAAM,wBAAwB,SAAS,MAAM,MAAM;AACjE,KAAI,MAAO,QAAO;AAClB,QAAO,sBAAsB,SAAS,MAAM;;AAK9C,eAAsB,iBACpB,KACA,SACA,OACe;AACf,KAAI,CAAC,QAAQ,cAAc,QAAS;AACpC,KAAI,CAAC,MAAM,MAAO;AAElB,KAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,IAAI,QAAQ,SAAS,MAAM;AAE9D,MAAI,KAAK;AACP,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,IAAI;KAAI,CAAC;IACvC,QAAQ;KACN,QAAQ;KACR,cAAc,MAAM;KACpB,YAAY,IAAI,aAAa,KAAK;KAClC,gBACE,IAAI,cAAc,OACd,KAAK,KAAK,IAAI,cAAc,OAAO,IAAI,aAAa,KAAK,IAAI,EAAE,GAC/D;KACN,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;GAEF,MAAM,OAAO,QAAQ,aAAa,SAC7B,OAAO,QAAQ,aAAa,UAAU,aACnC,MAAM,QAAQ,aAAa,OAAO,GAClC,QAAQ,aAAa,OACvB,MAAM,MAAM,EAAE,SAAS,IAAI,KAAK,GAClC;AAEJ,SAAM,QAAQ,aAAa,mBAAmB;IAC5C,cAAc;IACd;IACA;IACD,CAAC;QAEF,KAAI,QAAQ,OAAO,KACjB,mCAAmC,MAAM,MAAM,6BAChD;UAEI,KAAK;AACZ,MAAI,QAAQ,OAAO,MACjB,gCAAgC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACjF;;;AAIL,eAAsB,iBACpB,KACA,SACA,OACe;AACf,KAAI,CAAC,QAAQ,cAAc,QAAS;AAEpC,KAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,IAAI,QAAQ,SAAS,MAAM;AAE9D,MAAI,IACF,OAAM,IAAI,QAAQ,QAAQ,OAAO;GAC/B,OAAO;GACP,OAAO,CAAC;IAAE,OAAO;IAAM,OAAO,IAAI;IAAI,CAAC;GACvC,QAAQ;IACN,QAAQ;IACR,2BAAW,IAAI,MAAM;IACtB;GACF,CAAC;AAGJ,QAAM,QAAQ,aAAa,mBAAmB;GAC5C;GACA,OAAO,MAAM,SAAS,MAAM,UAAU;GACvC,CAAC;UACK,KAAK;AACZ,MAAI,QAAQ,OAAO,MACjB,gCAAgC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACjF;;;AAIL,eAAsB,wBACpB,KACA,SACA,OACe;AACf,KAAI,CAAC,QAAQ,cAAc,QAAS;AACpC,KAAI,CAAC,MAAM,MAAO;AAElB,KAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,IAAI,QAAQ,SAAS,MAAM;AAE9D,MAAI,KAAK;AACP,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,IAAI;KAAI,CAAC;IACvC,QAAQ;KACN,QAAQ;KACR,cAAc,MAAM;KACpB,8BAAc,IAAI,MAAM;KACxB,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;GAEF,MAAM,OAAO,QAAQ,aAAa,SAC7B,OAAO,QAAQ,aAAa,UAAU,aACnC,MAAM,QAAQ,aAAa,OAAO,GAClC,QAAQ,aAAa,OACvB,MAAM,MAAM,EAAE,SAAS,IAAI,KAAK,GAClC;AAEJ,SAAM,QAAQ,aAAa,0BAA0B;IACnD,cAAc;IACd;IACA;IACD,CAAC;QAEF,KAAI,QAAQ,OAAO,KACjB,0CAA0C,MAAM,MAAM,6BACvD;UAEI,KAAK;AACZ,MAAI,QAAQ,OAAO,MACjB,uCAAuC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACxF;;;AA0DL,eAAsB,sBACpB,KACA,SACA,OACe;AACf,KAAI,CAAC,QAAQ,cAAc,QAAS;AAEpC,KAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,IAAI,QAAQ,SAAS,MAAM;AAE9D,MAAI,KAAK;AACP,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,IAAI;KAAI,CAAC;IACvC,QAAQ;KACN,QAAQ;KACR,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;GAEF,MAAM,OAAO,QAAQ,aAAa,SAC7B,OAAO,QAAQ,aAAa,UAAU,aACnC,MAAM,QAAQ,aAAa,OAAO,GAClC,QAAQ,aAAa,OACvB,MAAM,MAAM,EAAE,SAAS,IAAI,KAAK,GAClC;AAEJ,SAAM,QAAQ,aAAa,wBAAwB;IACjD,cAAc;IACd;IACA;IACD,CAAC;;UAEG,KAAK;AACZ,MAAI,QAAQ,OAAO,MACjB,qCAAqC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACtF;;;AAIL,eAAsB,qBACpB,KACA,SACA,OACe;AACf,KAAI,CAAC,QAAQ,cAAc,QAAS;AAEpC,KAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,IAAI,QAAQ,SAAS,MAAM;AAE9D,MAAI,KAAK;AACP,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,IAAI;KAAI,CAAC;IACvC,QAAQ;KACN,QAAQ;KACR,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;GAEF,MAAM,OAAO,QAAQ,aAAa,SAC7B,OAAO,QAAQ,aAAa,UAAU,aACnC,MAAM,QAAQ,aAAa,OAAO,GAClC,QAAQ,aAAa,OACvB,MAAM,MAAM,EAAE,SAAS,IAAI,KAAK,GAClC;AAEJ,SAAM,QAAQ,aAAa,uBAAuB;IAChD,cAAc;IACd;IACA;IACD,CAAC;;UAEG,KAAK;AACZ,MAAI,QAAQ,OAAO,MACjB,oCAAoC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACrF;;;AAIL,eAAsB,wBACpB,KACA,SACA,OACe;AACf,KAAI,CAAC,QAAQ,cAAc,QAAS;AAEpC,KAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,IAAI,QAAQ,SAAS,MAAM;AAE9D,MAAI,KAAK;AACP,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,IAAI;KAAI,CAAC;IACvC,QAAQ;KACN,QAAQ;KACR,yBAAS,IAAI,MAAM;KACnB,gBAAgB;KAChB,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;GAEF,MAAM,OAAO,QAAQ,aAAa,SAC7B,OAAO,QAAQ,aAAa,UAAU,aACnC,MAAM,QAAQ,aAAa,OAAO,GAClC,QAAQ,aAAa,OACvB,MAAM,MAAM,EAAE,SAAS,IAAI,KAAK,GAClC;AAEJ,SAAM,QAAQ,aAAa,0BAA0B;IACnD,cAAc;IACd;IACA;IACD,CAAC;;UAEG,KAAK;AACZ,MAAI,QAAQ,OAAO,MACjB,uCAAuC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACxF;;;AAIL,eAAsB,wBACpB,KACA,SACA,OACe;AACf,KAAI,CAAC,QAAQ,cAAc,QAAS;AAEpC,KAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,IAAI,QAAQ,SAAS,MAAM;AAE9D,MAAI,KAAK;AACP,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,IAAI;KAAI,CAAC;IACvC,QAAQ;KACN,QAAQ;KACR,6BAAa,IAAI,MAAM;KACvB,yBAAS,IAAI,MAAM;KACnB,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;GAEF,MAAM,OAAO,QAAQ,aAAa,SAC7B,OAAO,QAAQ,aAAa,UAAU,aACnC,MAAM,QAAQ,aAAa,OAAO,GAClC,QAAQ,aAAa,OACvB,MAAM,MAAM,EAAE,SAAS,IAAI,KAAK,GAClC;AAEJ,SAAM,QAAQ,aAAa,0BAA0B;IACnD,cAAc;IACd;IACA;IACD,CAAC;QAEF,KAAI,QAAQ,OAAO,KACjB,0CAA0C,MAAM,MAAM,6BACvD;UAEI,KAAK;AACZ,MAAI,QAAQ,OAAO,MACjB,uCAAuC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACxF;;;AAIL,eAAsB,qBACpB,KACA,SACA,OACe;AACf,KAAI,CAAC,QAAQ,cAAc,QAAS;AAEpC,KAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,IAAI,QAAQ,SAAS,MAAM;AAE9D,MAAI,KAAK;AACP,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,IAAI;KAAI,CAAC;IACvC,QAAQ;KACN,QAAQ;KACR,0BAAU,IAAI,MAAM;KACpB,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;GAEF,MAAM,OAAO,QAAQ,aAAa,SAC7B,OAAO,QAAQ,aAAa,UAAU,aACnC,MAAM,QAAQ,aAAa,OAAO,GAClC,QAAQ,aAAa,OACvB,MAAM,MAAM,EAAE,SAAS,IAAI,KAAK,GAClC;AAEJ,SAAM,QAAQ,aAAa,uBAAuB;IAChD,cAAc;IACd;IACA;IACD,CAAC;;UAEG,KAAK;AACZ,MAAI,QAAQ,OAAO,MACjB,oCAAoC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACrF;;;AAIL,eAAsB,sBACpB,KACA,SACA,OACe;AACf,KAAI,CAAC,QAAQ,cAAc,QAAS;AAEpC,KAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,IAAI,QAAQ,SAAS,MAAM;AAE9D,MAAI,KAAK;AACP,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,IAAI;KAAI,CAAC;IACvC,QAAQ;KACN,QAAQ;KACR,UAAU;KACV,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;GAEF,MAAM,OAAO,QAAQ,aAAa,SAC7B,OAAO,QAAQ,aAAa,UAAU,aACnC,MAAM,QAAQ,aAAa,OAAO,GAClC,QAAQ,aAAa,OACvB,MAAM,MAAM,EAAE,SAAS,IAAI,KAAK,GAClC;AAEJ,SAAM,QAAQ,aAAa,wBAAwB;IACjD,cAAc;IACd;IACA;IACD,CAAC;;UAEG,KAAK;AACZ,MAAI,QAAQ,OAAO,MACjB,qCAAqC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACtF;;;AAIL,eAAsB,iBACpB,KACA,SACA,OACe;AACf,KAAI,CAAC,QAAQ,cAAc,QAAS;AAEpC,KAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,IAAI,QAAQ,SAAS,MAAM;AAE9D,MAAI,KAAK;AACP,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,IAAI;KAAI,CAAC;IACvC,QAAQ;KACN,QAAQ;KACR,6BAAa,IAAI,MAAM;KACvB,yBAAS,IAAI,MAAM;KACnB,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;GAEF,MAAM,OAAO,QAAQ,aAAa,SAC7B,OAAO,QAAQ,aAAa,UAAU,aACnC,MAAM,QAAQ,aAAa,OAAO,GAClC,QAAQ,aAAa,OACvB,MAAM,MAAM,EAAE,SAAS,IAAI,KAAK,GAClC;AAEJ,SAAM,QAAQ,aAAa,mBAAmB;IAC5C,cAAc;IACd;IACA;IACD,CAAC;;UAEG,KAAK;AACZ,MAAI,QAAQ,OAAO,MACjB,gCAAgC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GACjF;;;AAIL,eAAsB,kBACpB,KACA,SACA,OACe;AACf,KAAI,CAAC,QAAQ,cAAc,QAAS;AAEpC,KAAI;EACF,MAAM,MAAM,MAAM,iBAAiB,IAAI,QAAQ,SAAS,MAAM;AAE9D,MAAI,KAAK;AACP,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,IAAI;KAAI,CAAC;IACvC,QAAQ,EACN,2BAAW,IAAI,MAAM,EACtB;IACF,CAAC;GAEF,MAAM,OAAO,QAAQ,aAAa,SAC7B,OAAO,QAAQ,aAAa,UAAU,aACnC,MAAM,QAAQ,aAAa,OAAO,GAClC,QAAQ,aAAa,OACvB,MAAM,MAAM,EAAE,SAAS,IAAI,KAAK,GAClC;AAEJ,SAAM,QAAQ,aAAa,oBAAoB;IAC7C,cAAc;IACd;IACA;IACD,CAAC;;UAEG,KAAK;AACZ,MAAI,QAAQ,OAAO,MACjB,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,GAClF;;;;;;AC3jBL,SAAgB,eACd,QACA,SACU;AACV,QAAO,IAAI,SAAS,QAAQ,EAAE,MAAM;EAAE;EAAS,MAAM;EAAS,EAAE,CAAC;;;;;;AASnE,SAAgB,iBACd,QAkBA,MACQ;CACR,MAAM,aAAa;EACjB,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,SAAS;EAChB;EACD,CAAC,KAAK,IAAI;AAEX,QAAO,WAAW,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,OAAO,MAAM;;;;;;AAOlE,SAAgB,eACd,QAmBA,MACA,cACS;CACT,MAAM,oBAAoB;EACxB;EACA,OAAO;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,OAAO,SAAS;EAChB,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACR,CAAC,KAAK,IAAI;AAMX,QAJqB,WAAW,UAAU,GAAG,CAC1C,OAAO,kBAAkB,CACzB,OAAO,MAAM,KAEQ;;AAK1B,eAAsB,SACpB,qBACqB;AACrB,KAAI,qBAAqB,QACvB,QAAO,OAAO,oBAAoB,UAAU,aACxC,MAAM,oBAAoB,OAAO,GACjC,oBAAoB,SAAS,EAAE;AAErC,OAAM,IAAI,MAAM,qDAAqD;;AAGvE,eAAsB,cACpB,SACA,MAC+B;AAC/B,QAAO,MAAM,SAAS,QAAQ,aAAa,CAAC,MAAM,QAChD,IAAI,MAAM,SAAS,KAAK,KAAK,aAAa,KAAK,KAAK,aAAa,CAAC,CACnE;;AAGH,eAAsB,gBACpB,SACA,QAC+B;AAC/B,QAAO,MAAM,SAAS,QAAQ,aAAa,CAAC,MAAM,QAChD,IAAI,MAAM,SAAS,KAAK,WAAW,UAAU,KAAK,iBAAiB,OAAO,CAC3E;;AAKH,SAAgB,SAAS,KAAiD;AACxE,QAAO,IAAI,WAAW;;AAGxB,SAAgB,gBACd,KACS;AACT,QAAO,IAAI,WAAW;;AAGxB,SAAgB,SAAS,KAAiD;AACxE,QAAO,IAAI,WAAW;;AAGxB,SAAgB,YAAY,KAAiD;AAC3E,QAAO,IAAI,WAAW;;AAGxB,SAAgB,WAAW,KAAiD;AAC1E,QACE,IAAI,WAAW,eACf,IAAI,WAAW,eACf,IAAI,WAAW;;AAInB,SAAgB,SAAS,KAAiD;AACxE,QAAO,IAAI,WAAW,YAAY,IAAI,WAAW;;AAGnD,SAAgB,gBACd,KACS;AACT,QAAO,IAAI,WAAW,aAAa,IAAI,WAAW;;AAKpD,SAAgB,gBACd,WACkB;AAClB,QAAO,4BAAY,IAAI,KAAK,YAAY,IAAK,GAAG;;AAGlD,SAAgB,iBACd,SACkB;AAClB,KAAI,CAAC,QAAS,QAAO;CACrB,MAAM,IAAI,IAAI,KAAK,QAAQ;AAC3B,QAAO,MAAM,EAAE,SAAS,CAAC,GAAG,SAAY;;AAK1C,SAAgB,qBAAqB,QAAwC;AAY3E,KAXgD;EAC9C;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACiB,SAAS,OAAiC,CAC1D,QAAO;AAET,QAAO;;;;;;AAST,SAAgB,oBACd,KACA,SACA,MACA,MACQ;CACR,MAAM,aAAa,GAAG,IAAI,GAAG,QAAQ,GAAG,KAAK,GAAG;AAChD,QAAO,WAAW,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,OAAO,MAAM;;;;;;;;;ACxOlE,SAAgB,sBAAsB,KAAc;CAClD,MAAM,OAAO,IAAI,QAAQ,SAAS;AAClC,KAAI,CAAC,KACH,OAAM,eAAe,gBAAgB,iBAAiB,aAAa;AAErE,QAAO;;;;;;AAOT,SAAgB,oBAAoB,SAAsB;AACxD,QAAO,OAAO,QAAiB;EAC7B,MAAM,OAAO,sBAAsB,IAAI;EACvC,MAAM,cACH,IAAI,MAAiC,eACtC,IAAI,OAAO,eACX,KAAK;AAGP,MAAI,gBAAgB,KAAK,GACvB,QAAO;GAAE;GAAa,MAAM;GAAiB,QAAQ,KAAK;GAAI;AAIhE,MAAI,QAAQ,cAAc,SAAS;GACjC,MAAM,qBAAqB,QAAQ,aAAa;AAEhD,OAAI,oBAQF;QAAI,CAPY,MAAM,mBAAmB;KACvC,QAAQ;KACR,gBAAgB;KAChB,QAAQ,KAAK;KACb,MAAM;KACP,CAAC,CAGA,OAAM,eACJ,aACA,iBAAiB,yBAClB;;AAIL,UAAO;IACL;IACA,MAAM;IACN,QAAQ,KAAK;IACd;;AAIH,QAAM,eACJ,aACA,iBAAiB,yBAClB;;;;;;ACvCL,MAAM,+BAA+B,EAAE,OAAO;CAC5C,MAAM,EAAE,QAAQ;CAChB,aAAa,EAAE,QAAQ,CAAC,UAAU;CAClC,cAAc,EAAE,KAAK,CAAC,QAAQ,eAAe,CAAC,CAAC,UAAU;CACzD,aAAa,EAAE,KAAK;EAAC;EAAQ;EAAO;EAAa,CAAC,CAAC,UAAU;CAC9D,CAAC;AAEF,MAAM,+BAA+B,EAAE,OAAO;CAC5C,aAAa,EAAE,QAAQ,CAAC,UAAU;CAClC,cAAc,EAAE,KAAK,CAAC,QAAQ,eAAe,CAAC,CAAC,UAAU;CACzD,kBAAkB,EAAE,SAAS,CAAC,UAAU;CACzC,CAAC;AAEF,MAAM,8BAA8B,EAAE,OAAO;CAC3C,aAAa,EAAE,QAAQ,CAAC,UAAU;CAClC,cAAc,EAAE,KAAK,CAAC,QAAQ,eAAe,CAAC,CAAC,UAAU;CAC1D,CAAC;AAEF,MAAM,+BAA+B,EAAE,OAAO;CAC5C,aAAa,EAAE,QAAQ,CAAC,UAAU;CAClC,cAAc,EAAE,KAAK,CAAC,QAAQ,eAAe,CAAC,CAAC,UAAU;CAC1D,CAAC;AAEF,MAAM,+BAA+B,EAAE,OAAO;CAC5C,aAAa,EAAE,QAAQ,CAAC,UAAU;CAClC,cAAc,EAAE,KAAK,CAAC,QAAQ,eAAe,CAAC,CAAC,UAAU;CAC1D,CAAC;AAEF,MAAM,+BAA+B,EAAE,OAAO;CAC5C,aAAa,EAAE,QAAQ,CAAC,UAAU;CAClC,cAAc,EAAE,KAAK,CAAC,QAAQ,eAAe,CAAC,CAAC,UAAU;CACzD,MAAM,EAAE,QAAQ,CAAC,UAAU;CAC3B,UAAU,EAAE,QAAQ,CAAC,UAAU;CAChC,CAAC;AAEF,MAAM,+BAA+B,EAAE,OAAO;CAC5C,gBAAgB,EAAE,QAAQ;CAC1B,QAAQ,EAAE,QAAQ;CAClB,OAAO,EAAE,QAAQ;CAClB,CAAC;AAEF,MAAM,2BAA2B,EAAE,OAAO;CACxC,gBAAgB,EAAE,QAAQ;CAC1B,QAAQ,EAAE,QAAQ;CAClB,OAAO,EAAE,QAAQ;CACjB,WAAW,EAAE,QAAQ;CACtB,CAAC;AAEF,MAAM,+BAA+B,EAAE,OAAO,EAC5C,gBAAgB,EAAE,QAAQ,EAC3B,CAAC;AAEF,MAAM,2BAA2B,EAAE,OAAO;CACxC,gBAAgB,EAAE,QAAQ;CAC1B,aAAa,EAAE,KAAK;EAAC;EAAQ;EAAO;EAAa,CAAC,CAAC,UAAU;CAC9D,CAAC;AAEF,MAAM,0BAA0B,EAAE,OAAO;CACvC,gBAAgB,EAAE,QAAQ;CAC1B,QAAQ,EAAE,QAAQ;CAClB,aAAa,EAAE,KAAK;EAAC;EAAQ;EAAO;EAAa,CAAC,CAAC,UAAU;CAC9D,CAAC;AAEF,MAAM,4BAA4B,EAAE,OAAO;CACzC,OAAO,EAAE,QAAQ;CACjB,QAAQ,EAAE,QAAQ;CAClB,aAAa,EAAE,QAAQ;CACvB,WAAW,EAAE,QAAQ;CACrB,OAAO,EAAE,QAAQ;CACjB,OAAO,EAAE,QAAQ;CACjB,aAAa,EAAE,QAAQ,CAAC,UAAU;CACnC,CAAC;AAEF,MAAM,0BAA0B,EAAE,OAAO,EACvC,OAAO,EAAE,QAAQ,EAClB,CAAC;AAEF,MAAM,2BAA2B,EAAE,OAAO;CACxC,UAAU,EAAE,QAAQ;CACpB,QAAQ,EAAE,QAAQ;CAClB,SAAS,EAAE,QAAQ;CACpB,CAAC;AAEF,MAAM,0BAA0B,EAAE,OAAO;CACvC,WAAW,EAAE,QAAQ,CAAC,UAAU;CAChC,UAAU,EAAE,QAAQ,CAAC,UAAU;CAChC,CAAC;AAEF,MAAM,6BAA6B,EAAE,OAAO,EAC1C,OAAO,EAAE,QAAQ,EAClB,CAAC;AAEF,MAAM,gCAAgC,EAAE,OAAO;CAC7C,WAAW,EAAE,QAAQ;CACrB,SAAS,EAAE,QAAQ;CACpB,CAAC;AAEF,MAAM,wBAAwB,EAAE,OAAO,EACrC,KAAK,EAAE,QAAQ,EAChB,CAAC;AAEF,MAAM,qBAAqB,EAAE,OAAO;CAClC,gBAAgB,EAAE,QAAQ;CAC1B,eAAe,EAAE,QAAQ,CAAC,UAAU;CACpC,cAAc,EAAE,QAAQ,CAAC,UAAU;CACnC,iBAAiB,EAAE,QAAQ,CAAC,UAAU;CACtC,gBAAgB,EAAE,QAAQ,CAAC,UAAU;CACtC,CAAC;AAEF,MAAM,uBAAuB,EAAE,OAAO,EACpC,QAAQ,EAAE,QAAQ,EACnB,CAAC;AAEF,MAAM,4BAA4B,EAAE,OAAO;CACzC,MAAM,EAAE,QAAQ;CAChB,aAAa,EAAE,QAAQ,CAAC,UAAU;CAClC,cAAc,EAAE,KAAK,CAAC,QAAQ,eAAe,CAAC,CAAC,UAAU;CACzD,aAAa,EAAE,KAAK;EAAC;EAAQ;EAAO;EAAa,CAAC,CAAC,UAAU;CAC7D,eAAe,EAAE,QAAQ,CAAC,UAAU;CACrC,CAAC;AAIF,SAAgB,aAAa,SAAsB;CACjD,MAAM,eAAe,oBAAoB,QAAQ;AAEjD,QAAO;EAEL,oBAAoB,mBAClB,6BACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;GACb,MAAM,OAAO,sBAAsB,IAAI;GACvC,MAAM,MAAM,MAAM,aAAa,IAAI;GACnC,MAAM,OAAO,IAAI;AAEjB,OAAI,CAAC,QAAQ,cAAc,QACzB,OAAM,eACJ,eACA,iBAAiB,qBAClB;GAGH,MAAM,OAAO,MAAM,cAAc,SAAS,KAAK,KAAK;AACpD,OAAI,CAAC,KACH,OAAM,eACJ,aACA,iBAAiB,4BAClB;GAIH,MAAM,WAAY,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IAClD,OAAO;IACP,OAAO,CACL;KAAE,OAAO;KAAe,OAAO,IAAI;KAAa,EAChD;KACE,OAAO;KACP,UAAU;KACV,OAAO,CAAC,UAAU,gBAAgB;KACnC,CACF;IACF,CAAC;AAEF,OAAI,YAAY,SAAS,SAAS,KAAK,KACrC,OAAM,eACJ,YACA,iBAAiB,wBAClB;GAIH,MAAM,eAAe,MAAM,IAAI,QAAQ,QAAQ,OAAO;IACpD,OAAO;IACP,MAAM;KACJ,MAAM,KAAK;KACX,aAAa,IAAI;KACjB,gBAAgB;KAChB,oBAAoB,YAAY,KAAK,KAAK;KAC1C,iBAAiB,KAAK,eAAe;KACrC,mBAAmB;KACnB,cAAc;KACd,QAAQ;KACR,cAAc;KACd,YAAY;KACZ,SAAS;KACT,UAAU;KACV,YAAY,KAAK;KACjB,WAAW;KACX,gBAAgB,KAAK;KACrB,aAAa;KACb,UAAU;KACV,kBAAkB;KAClB,eAAe,KAAK;KACpB,OAAO;KACP,YAAY;KACZ,UAAU;KACV,UAAU;KACV,2BAAW,IAAI,MAAM;KACrB,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;GAGF,MAAM,QAAQ,OAAO,KAAK,KAAK,CAAC,GAAI,aAAyC;GAC7E,MAAM,OAAO,iBACX;IACE,KAAK,QAAQ;IACb;IACA,QAAQ,KAAK;IACb,aAAa,KAAK;IAClB,WAAW,KAAK;IAChB,OAAO;IACP,GAAG,gBAAgB,IAAI;KACrB,QAAQ,KAAK;KACb,gBAAiB,aACd;KACH,aAAa,IAAI;KAClB,CAAC;IACH,EACD,QAAQ,aACT;AAED,UAAO,IAAI,KAAK;IACd;IACA,eAAe;KACb,KAAK,QAAQ;KACb;KACA,QAAQ,KAAK;KACb,aAAa,KAAK;KAClB;KACA,aAAa,KAAK,eAAe;KAClC;IACF,CAAC;IAEL;EAGD,iBAAiB,mBACf,wCACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;GACb,MAAM,OAAO,sBAAsB,IAAI;GACvC,MAAM,MAAM,MAAM,aAAa,IAAI;GACnC,MAAM,OAAO,IAAI;AAEjB,OAAI,CAAC,QAAQ,cAAc,QACzB,OAAM,eACJ,eACA,iBAAiB,qBAClB;GAGH,MAAM,OAAO,MAAM,cAAc,SAAS,KAAK,KAAK;AACpD,OAAI,CAAC,KACH,OAAM,eACJ,aACA,iBAAiB,4BAClB;GAGH,MAAM,eAAe,MAAM,IAAI,QAAQ,QAAQ,OAAO;IACpD,OAAO;IACP,MAAM;KACJ,MAAM,KAAK;KACX,aAAa,IAAI;KACjB,oBAAoB,YAAY,KAAK,KAAK;KAC1C,iBAAiB,KAAK,eAAe;KACrC,QAAQ;KACR,UAAU;KACV,YAAY,KAAK;KACjB,WAAW;KACX,gBAAgB,KAAK;KACrB,eAAe,KAAK;KACpB,2BAAW,IAAI,MAAM;KACrB,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;GAEF,MAAM,QAAQ,OAAO,KAAK,KAAK,CAAC,GAAI,aAAyC;GAC7E,MAAM,gBAAgB,KAAK,iBAAiB,KAAK;GACjD,MAAM,OAAO,iBACX;IACE,KAAK,QAAQ;IACb;IACA,QAAQ;IACR,aAAa,KAAK;IAClB,WAAW,KAAK;IAChB,OAAO;IACR,EACD,QAAQ,aACT;AAED,UAAO,IAAI,KAAK;IACd;IACA,eAAe;KACb,KAAK,QAAQ;KACb;KACA,QAAQ;KACR,aAAa,KAAK;KAClB;KACA,aAAa,KAAK,eAAe;KAClC;IACF,CAAC;IAEL;EAGD,oBAAoB,mBAClB,6BACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;GACb,MAAM,MAAM,MAAM,aAAa,IAAI;GAEnC,MAAM,eAAgB,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACtD,OAAO;IACP,OAAO,CACL;KAAE,OAAO;KAAe,OAAO,IAAI;KAAa,EAChD;KACE,OAAO;KACP,UAAU;KACV,OAAO,CAAC,UAAU,gBAAgB;KACnC,CACF;IACF,CAAC;AAEF,OAAI,CAAC,aACH,OAAM,eACJ,aACA,iBAAiB,uBAClB;AAGH,OAAI,YAAY,aAAa,CAC3B,OAAM,eACJ,eACA,iBAAiB,+BAClB;AAGH,OAAI,WAAW,aAAa,CAC1B,OAAM,eACJ,eACA,iBAAiB,+BAClB;AAIH,OAAI,IAAI,KAAK,kBAAkB;AAC7B,UAAM,IAAI,QAAQ,QAAQ,OAAO;KAC/B,OAAO;KACP,OAAO,CAAC;MAAE,OAAO;MAAM,OAAO,aAAa;MAAI,CAAC;KAChD,QAAQ;MACN,kBAAkB;MAClB,2BAAW,IAAI,MAAM;MACtB;KACF,CAAC;AACF,WAAO,IAAI,KAAK;KAAE,SAAS;KAAM,kBAAkB;KAAM,CAAC;;GAI5D,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,UACJ,aAAa,oBAAoB,QAC7B,uBACA;GAEN,MAAM,OAAO,oBACX,QAAQ,aACR,SACA,aAAa,qBAAqB,IAClC,QAAQ,aACT;GAaD,MAAM,SAAS,OAXE,MAAM,MAAM,GAAG,OAAO,YAAY,WAAW;IAC5D,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb;KACA,MAAM,aAAa,qBAAqB;KACxC;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,OAAI,OAAO,WAAW,KAAK,OAAO,MAChC,OAAM,eACJ,yBACA,iBAAiB,sBAClB;AAGH,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,aAAa;KAAI,CAAC;IAChD,QAAQ;KACN,QAAQ;KACR,6BAAa,IAAI,MAAM;KACvB,yBAAS,IAAI,MAAM;KACnB,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;AAEF,UAAO,IAAI,KAAK,EAAE,SAAS,MAAM,CAAC;IAErC;EAGD,mBAAmB,mBACjB,4BACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;GACb,MAAM,MAAM,MAAM,aAAa,IAAI;GAEnC,MAAM,eAAgB,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACtD,OAAO;IACP,OAAO,CACL;KAAE,OAAO;KAAe,OAAO,IAAI;KAAa,EAChD;KAAE,OAAO;KAAU,OAAO;KAAU,CACrC;IACF,CAAC;AAEF,OAAI,CAAC,aACH,OAAM,eACJ,aACA,iBAAiB,uBAClB;AAGH,OAAI,CAAC,SAAS,aAAa,CACzB,OAAM,eACJ,eACA,iBAAiB,wBAClB;AAGH,OAAI,SAAS,aAAa,CACxB,OAAM,eACJ,eACA,iBAAiB,4BAClB;AAGH,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,aAAa;KAAI,CAAC;IAChD,QAAQ;KACN,QAAQ;KACR,0BAAU,IAAI,MAAM;KACpB,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;AAEF,UAAO,IAAI,KAAK,EAAE,SAAS,MAAM,CAAC;IAErC;EAGD,oBAAoB,mBAClB,6BACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;GACb,MAAM,MAAM,MAAM,aAAa,IAAI;GAEnC,MAAM,eAAgB,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACtD,OAAO;IACP,OAAO,CACL;KAAE,OAAO;KAAe,OAAO,IAAI;KAAa,EAChD;KAAE,OAAO;KAAU,OAAO;KAAU,CACrC;IACF,CAAC;AAEF,OAAI,CAAC,aACH,OAAM,eACJ,aACA,iBAAiB,uBAClB;AAGH,OAAI,CAAC,SAAS,aAAa,CACzB,OAAM,eACJ,eACA,iBAAiB,wBAClB;AAGH,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,aAAa;KAAI,CAAC;IAChD,QAAQ;KACN,QAAQ;KACR,UAAU;KACV,2BAAW,IAAI,MAAM;KACtB;IACF,CAAC;AAEF,UAAO,IAAI,KAAK,EAAE,SAAS,MAAM,CAAC;IAErC;EAGD,mBAAmB,mBACjB,2BACA;GACE,QAAQ;GACR,OAAO;GACR,EACD,OAAO,QAAQ;GACb,MAAM,MAAM,MAAM,aAAa,IAAI;GAEnC,MAAM,gBAAgB,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACtD,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAe,OAAO,IAAI;KAAa,CAAC;IAC1D,CAAC;AAEF,UAAO,IAAI,KAAK,EACd,eAAe,gBAAgB,CAAC,cAAc,GAAG,EAAE,EACpD,CAAC;IAEL;EAGD,iBAAiB,mBACf,0BACA;GACE,QAAQ;GACR,OAAO;GACR,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,EAAE,mBAAmB,IAAI;GAE/B,MAAM,eAAe,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACrD,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO;KAAgB,CAAC;IAChD,CAAC;AAEF,OAAI,CAAC,aACH,OAAM,eACJ,aACA,iBAAiB,uBAClB;AAGH,UAAO,IAAI,KAAK,EAAE,cAAc,CAAC;IAEpC;EAGD,oBAAoB,mBAClB,6BACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;GACb,MAAM,MAAM,MAAM,aAAa,IAAI;GACnC,MAAM,OAAO,IAAI;GAEjB,MAAM,eAAgB,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACtD,OAAO;IACP,OAAO,CACL;KAAE,OAAO;KAAe,OAAO,IAAI;KAAa,EAChD;KACE,OAAO;KACP,UAAU;KACV,OAAO,CAAC,UAAU,gBAAgB;KACnC,CACF;IACF,CAAC;AAEF,OAAI,CAAC,aACH,OAAM,eACJ,aACA,iBAAiB,uBAClB;GAGH,MAAM,aAAsC,EAAE,2BAAW,IAAI,MAAM,EAAE;AAErE,OAAI,KAAK,MAAM;IACb,MAAM,OAAO,MAAM,cAAc,SAAS,KAAK,KAAK;AACpD,QAAI,CAAC,KACH,OAAM,eACJ,aACA,iBAAiB,4BAClB;AAEH,eAAW,OAAO,KAAK;AACvB,eAAW,gBAAgB,KAAK;AAChC,eAAW,aAAa,KAAK;;AAG/B,OAAI,KAAK,aAAa,OACpB,YAAW,WAAW,KAAK;AAG7B,SAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,aAAa;KAAI,CAAC;IAChD,QAAQ;IACT,CAAC;AAEF,UAAO,IAAI,KAAK,EAAE,SAAS,MAAM,CAAC;IAErC;EAGD,gBAAgB,mBACd,uCACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,OAAO,IAAI;AAOjB,OAAI,CALkB,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACtD,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,KAAK;KAAgB,CAAC;IACrD,CAAC,CAGA,OAAM,eACJ,aACA,iBAAiB,uBAClB;GAGH,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,OAAO,oBACX,QAAQ,aACR,gBACA,KAAK,OACL,QAAQ,aACT;GAeD,MAAM,SAAS,OAbE,MAAM,MAAM,GAAG,OAAO,yBAAyB;IAC9D,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb,SAAS;KACT,MAAM,KAAK;KACX,MAAM,KAAK;KACX,MAAM,KAAK;KACX;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,OAAI,OAAO,WAAW,KAAK,OAAO,MAChC,OAAM,eACJ,yBACA,iBAAiB,8BAClB;AAGH,UAAO,IAAI,KAAK;IAAE,SAAS;IAAM;IAAQ,CAAC;IAE7C;EAGD,oBAAoB,mBAClB,6BACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,OAAO,IAAI;GAEjB,MAAM,eAAgB,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACtD,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,KAAK;KAAgB,CAAC;IACrD,CAAC;AAEF,OAAI,CAAC,aACH,OAAM,eACJ,aACA,iBAAiB,uBAClB;AAGH,OAAI,CAAC,SAAS,aAAa,CACzB,OAAM,eACJ,eACA,iBAAiB,wBAClB;GAGH,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,OAAO,oBACX,QAAQ,aACR,kBACA,KAAK,OACL,QAAQ,aACT;GAcD,MAAM,SAAS,OAZE,MAAM,MAAM,GAAG,OAAO,2BAA2B;IAChE,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb,SAAS;KACT,MAAM,KAAK;KACX,MAAM,KAAK;KACX;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,OAAI,OAAO,WAAW,KAAK,OAAO,MAChC,OAAM,eACJ,yBACA,iBAAiB,0BAClB;AAGH,UAAO,IAAI,KAAK;IAAE,SAAS;IAAM;IAAQ,CAAC;IAE7C;EAGD,UAAU,mBACR,gCACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,OAAO,IAAI;GAEjB,MAAM,eAAgB,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACtD,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,KAAK;KAAgB,CAAC;IACrD,CAAC;AAEF,OAAI,CAAC,aACH,OAAM,eACJ,aACA,iBAAiB,uBAClB;GAGH,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,OAAO,oBACX,QAAQ,aACR,aACA,aAAa,qBAAqB,IAClC,QAAQ,aACT;GAED,MAAM,SAAiC;IACrC,KAAK,QAAQ;IACb,SAAS;IACT,MAAM,aAAa,qBAAqB;IACxC;IACD;AAED,OAAI,KAAK,cAAe,QAAO,OAAO,KAAK;AAC3C,OAAI,KAAK,aAAc,QAAO,OAAO,KAAK;AAC1C,OAAI,KAAK,oBAAoB,OAC3B,QAAO,OAAO,OAAO,KAAK,gBAAgB;AAC5C,OAAI,KAAK,eAAgB,QAAO,OAAO,KAAK;GAQ5C,MAAM,SAAS,OANE,MAAM,MAAM,GAAG,OAAO,sBAAsB;IAC3D,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB,OAAO;IAClC,CAAC,EAE4B,MAAM;AAEpC,OAAI,OAAO,WAAW,KAAK,OAAO,MAChC,OAAM,eACJ,yBACA,iBAAiB,iBAClB;AAGH,UAAO,IAAI,KAAK;IAAE,SAAS;IAAM;IAAQ,CAAC;IAE7C;EAGD,eAAe,mBACb,wBACA;GACE,QAAQ;GACR,OAAO;GACR,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,EAAE,gBAAgB,gBAAgB,IAAI;GAE5C,MAAM,eAAgB,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACtD,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO;KAAgB,CAAC;IAChD,CAAC;AAEF,OAAI,CAAC,aACH,OAAM,eACJ,aACA,iBAAiB,uBAClB;GAGH,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,QAAQ,eAAe,aAAa,mBAAmB;GAC7D,IAAI;AAEJ,OAAI,UAAU,MACZ,WAAU;YACD,UAAU,aACnB,WAAU;OAEV,WAAU;GAGZ,MAAM,OAAO,oBACX,QAAQ,aACR,SACA,aAAa,qBAAqB,IAClC,QAAQ,aACT;GAaD,MAAM,SAAS,OAXE,MAAM,MAAM,GAAG,OAAO,YAAY,WAAW;IAC5D,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb;KACA,MAAM,aAAa,qBAAqB;KACxC;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,OAAI,OAAO,WAAW,KAAK,OAAO,MAChC,OAAM,eACJ,yBACA,iBAAiB,4BAClB;AAGH,UAAO,IAAI,KAAK,EAAE,SAAS,QAAQ,CAAC;IAEvC;EAGD,eAAe,mBACb,wBACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,OAAO,IAAI;GAEjB,MAAM,eAAgB,MAAM,IAAI,QAAQ,QAAQ,QAAQ;IACtD,OAAO;IACP,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,KAAK;KAAgB,CAAC;IACrD,CAAC;AAEF,OAAI,CAAC,aACH,OAAM,eACJ,aACA,iBAAiB,uBAClB;GAGH,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,QACJ,KAAK,eAAe,aAAa,mBAAmB;GACtD,IAAI;AAEJ,OAAI,UAAU,MACZ,WAAU;OAEV,WAAU;GAGZ,MAAM,OAAO,oBACX,QAAQ,aACR,SACA,aAAa,qBAAqB,IAClC,QAAQ,aACT;GAcD,MAAM,SAAS,OAZE,MAAM,MAAM,GAAG,OAAO,YAAY,WAAW;IAC5D,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb;KACA,MAAM,aAAa,qBAAqB;KACxC,MAAM,KAAK;KACX;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,OAAI,OAAO,WAAW,KAAK,OAAO,MAChC,OAAM,eACJ,yBACA,iBAAiB,sBAClB;AAGH,UAAO,IAAI,KAAK;IAAE,SAAS;IAAM;IAAQ,CAAC;IAE7C;EAGD,iBAAiB,mBACf,0BACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,OAAO,IAAI;GAEjB,MAAM,OAAO,iBACX;IACE,KAAK,QAAQ;IACb,OAAO,KAAK;IACZ,QAAQ,KAAK;IACb,aAAa,KAAK;IAClB,WAAW,KAAK;IAChB,OAAO,KAAK;IACb,EACD,QAAQ,aACT;AAED,UAAO,IAAI,KAAK,EACd,eAAe;IACb,KAAK,QAAQ;IACb,OAAO,KAAK;IACZ,QAAQ,KAAK;IACb,aAAa,KAAK;IAClB,WAAW,KAAK;IAChB,OAAO,KAAK;IACZ,OAAO,KAAK;IACZ;IACA,MAAM,GAAG,QAAQ,cAAc,GAAG;IAClC,MAAM,GAAG,QAAQ,cAAc,GAAG;IACnC,EACF,CAAC;IAEL;EAGD,eAAe,mBACb,wBACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,EAAE,UAAU,IAAI;GAEtB,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,OAAO,oBACX,QAAQ,aACR,kBACA,OACA,QAAQ,aACT;GAaD,MAAM,SAAS,OAXE,MAAM,MAAM,GAAG,OAAO,+BAA+B;IACpE,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb,SAAS;KACT,MAAM;KACN;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,OAAI,OAAO,WAAW,KAAK,OAAO,MAChC,OAAM,eACJ,yBACA,iBAAiB,4BAClB;AAGH,UAAO,IAAI,KAAK,EAAE,aAAa,QAAQ,CAAC;IAE3C;EAGD,cAAc,mBACZ,uBACA;GACE,QAAQ;GACR,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;GACzC,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,EAAE,aAAa,IAAI;GAEzB,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,OAAO,oBACX,QAAQ,aACR,iBACA,UACA,QAAQ,aACT;GAaD,MAAM,SAAS,OAXE,MAAM,MAAM,GAAG,OAAO,+BAA+B;IACpE,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb,SAAS;KACT,MAAM;KACN;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,UAAO,IAAI,KAAK,EAAE,aAAa,QAAQ,CAAC;IAE3C;EAGD,gBAAgB,mBACd,yBACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,OAAO,IAAI;GAEjB,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,OAAO,oBACX,QAAQ,aACR,6BACA,KAAK,UACL,QAAQ,aACT;GAeD,MAAM,SAAS,OAbE,MAAM,MAAM,GAAG,OAAO,+BAA+B;IACpE,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb,SAAS;KACT,MAAM,KAAK;KACX,MAAM,KAAK;KACX,MAAM,KAAK;KACX;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,OAAI,OAAO,WAAW,KAAK,OAAO,MAChC,OAAM,eACJ,yBACA,iBAAiB,yBAClB;AAGH,UAAO,IAAI,KAAK;IAAE,SAAS;IAAM,QAAQ;IAAQ,CAAC;IAErD;EAGD,cAAc,mBACZ,uBACA;GACE,QAAQ;GACR,OAAO;GACR,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,EAAE,WAAW,aAAa,IAAI;GAEpC,MAAM,SAAS,QAAQ,cAAc;GACrC,IAAI;GACJ,IAAI;AAEJ,OAAI,WAAW;AACb,cAAU;AACV,WAAO;cACE,UAAU;AACnB,cAAU;AACV,WAAO;SAEP,OAAM,eACJ,eACA,iBAAiB,qBAClB;GAGH,MAAM,OAAO,oBACX,QAAQ,aACR,SACA,MACA,QAAQ,aACT;GAaD,MAAM,SAAS,OAXE,MAAM,MAAM,GAAG,OAAO,+BAA+B;IACpE,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb;KACA;KACA;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,UAAO,IAAI,KAAK,EAAE,cAAc,QAAQ,CAAC;IAE5C;EAGD,aAAa,mBACX,qBACA;GACE,QAAQ;GACR,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;GACnD,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,EAAE,cAAc,IAAI;GAE1B,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,OAAO,UAAU,KAAK,IAAI;GAChC,MAAM,OAAO,oBACX,QAAQ,aACR,wCACA,MACA,QAAQ,aACT;GAaD,MAAM,SAAS,OAXE,MAAM,MAAM,GAAG,OAAO,+BAA+B;IACpE,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb,SAAS;KACT;KACA;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,UAAO,IAAI,KAAK,EAAE,SAAS,QAAQ,CAAC;IAEvC;EAGD,iBAAiB,mBACf,0BACA;GACE,QAAQ;GACR,OAAO;GACR,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,EAAE,UAAU,IAAI;GAEtB,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,OAAO,oBACX,QAAQ,aACR,wBACA,OACA,QAAQ,aACT;GAaD,MAAM,SAAS,OAXE,MAAM,MAAM,GAAG,OAAO,+BAA+B;IACpE,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb,SAAS;KACT,MAAM;KACN;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,UAAO,IAAI,KAAK,EAAE,aAAa,QAAQ,CAAC;IAE3C;EAGD,oBAAoB,mBAClB,6BACA;GACE,QAAQ;GACR,OAAO;GACR,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,EAAE,WAAW,YAAY,IAAI;GAEnC,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,OAAO,oBACX,QAAQ,aACR,2BACA,WACA,QAAQ,aACT;GAcD,MAAM,SAAS,OAZE,MAAM,MAAM,GAAG,OAAO,+BAA+B;IACpE,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb,SAAS;KACT,MAAM;KACN,MAAM;KACN;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,UAAO,IAAI,KAAK,EAAE,cAAc,QAAQ,CAAC;IAE5C;EAGD,aAAa,mBACX,0BACA;GACE,QAAQ;GACR,MAAM;GACP,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,EAAE,QAAQ,IAAI;GAEpB,MAAM,SAAS,QAAQ,cAAc;GACrC,MAAM,OAAO,oBACX,QAAQ,aACR,eACA,KACA,QAAQ,aACT;GAaD,MAAM,SAAS,OAXE,MAAM,MAAM,GAAG,OAAO,+BAA+B;IACpE,QAAQ;IACR,SAAS,EAAE,gBAAgB,qCAAqC;IAChE,MAAM,IAAI,gBAAgB;KACxB,KAAK,QAAQ;KACb,SAAS;KACT,MAAM;KACN;KACD,CAAC;IACH,CAAC,EAE4B,MAAM;AAEpC,OAAI,OAAO,WAAW,KAAK,OAAO,eAAe,EAC/C,OAAM,eAAe,eAAe,iBAAiB,YAAY;AAGnE,UAAO,IAAI,KAAK;IAAE,OAAO;IAAM;IAAQ,CAAC;IAE3C;EAGD,WAAW,mBACT,mBACA,EACE,QAAQ,OACT,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;AAE1B,OAAI,CAAC,QAAQ,cAAc,QACzB,QAAO,IAAI,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;GAGhC,MAAM,QAAQ,MAAM,SAAS,QAAQ,aAAa;AAClD,UAAO,IAAI,KAAK,EAAE,OAAO,CAAC;IAE7B;EAGD,SAAS,mBACP,kBACA;GACE,QAAQ;GACR,OAAO;GACR,EACD,OAAO,QAAQ;AACb,yBAAsB,IAAI;GAC1B,MAAM,EAAE,WAAW,IAAI;GAEvB,MAAM,OAAO,MAAM,gBAAgB,SAAS,OAAO;AACnD,OAAI,CAAC,KACH,OAAM,eACJ,aACA,iBAAiB,4BAClB;AAGH,UAAO,IAAI,KAAK,EAAE,MAAM,CAAC;IAE5B;EAGD,SAAS,mBACP,iBACA,EACE,QAAQ,QACT,EACD,OAAO,QAAQ;GACb,MAAM,OAAO,IAAI;AAEjB,OAAI,CAAC,QAAQ,CAAC,KAAK,KACjB,OAAM,eACJ,eACA,iBAAiB,uBAClB;AA4BH,OAAI,CAxBY,eACd;IACE,KAAK,KAAK,OAAO,QAAQ;IACzB,OAAO,KAAK,SAAS;IACrB,QAAQ,KAAK,UAAU;IACvB,aAAa,KAAK,eAAe;IACjC,WAAW,KAAK,aAAa;IAC7B,OAAO,KAAK,SAAS;IACrB,QAAQ,KAAK,UAAU;IACvB,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,OAAO,KAAK;IACb,EACD,QAAQ,cACR,KAAK,KACN,CAGC,OAAM,eACJ,gBACA,iBAAiB,yBAClB;GAGH,MAAM,QAA0B;IAC9B,UAAU,KAAK,YAAY;IAC3B,QAAQ,KAAK,UAAU;IACvB,OAAO,KAAK,SAAS;IACrB,QAAQ,KAAK,UAAU;IACvB,aAAa,KAAK,eAAe;IACjC,WAAW,KAAK,aAAa;IAC7B,OAAO,KAAK,SAAS;IACrB,OAAO,KAAK,SAAS;IACrB,MAAM,KAAK;IACX,KAAK,KAAK,OAAO;IACjB,MAAM,KAAK,QAAQ;IACnB,gBAAgB,KAAK,kBAAkB;IACvC,QAAQ,KAAK,UAAU;IACvB,OAAO,KAAK,iBAAiB,KAAK,SAAS;IAC3C,cAAc,KAAK,gBAAgB;IACnC,SAAS,KAAK,WAAW;IACzB,gBAAgB,KAAK,kBAAkB;IACvC,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,MAAM,KAAK;IACX,OAAO,KAAK;IACZ,kBAAkB,KAAK;IACxB;GAGD,MAAM,SAAS,KAAK,QAAQ,aAAa;GACzC,MAAM,YAAY,KAAK,kBAAkB,aAAa;AAEtD,OAAI,cAAc,qBAAqB,cAAc,eACnD,OAAM,iBAAiB,KAAK,SAAS,MAAM;YAE3C,cAAc,sBACd,cAAc,cAEd,OAAM,kBAAkB,KAAK,SAAS,MAAM;YACnC,WAAW,aAAa,WAAW,YAAY;AACxD,UAAM,iBAAiB,KAAK,SAAS,MAAM;AAC3C,UAAM,wBAAwB,KAAK,SAAS,MAAM;cACzC,WAAW,aAAa,WAAW,SAC5C,OAAM,iBAAiB,KAAK,SAAS,MAAM;YAClC,WAAW,UACpB,OAAM,sBAAsB,KAAK,SAAS,MAAM;YACvC,WAAW,YACpB,OAAM,wBAAwB,KAAK,SAAS,MAAM;YACzC,WAAW,SACpB,OAAM,qBAAqB,KAAK,SAAS,MAAM;YACtC,WAAW,YACpB,OAAM,wBAAwB,KAAK,SAAS,MAAM;YACzC,WAAW,SACpB,OAAM,qBAAqB,KAAK,SAAS,MAAM;YACtC,WAAW,aAAa,WAAW,SAC5C,OAAM,sBAAsB,KAAK,SAAS,MAAM;AAGlD,UAAO,IAAI,KAAK,EAAE,SAAS,MAAM,CAAC;IAErC;EACF;;;;;ACj9CH,MAAa,gBAAgB,EAC3B,cAAc,EACZ,QAAQ;CACN,MAAM;EACJ,MAAM;EACN,UAAU;EACX;CACD,aAAa;EACX,MAAM;EACN,UAAU;EACX;CACD,gBAAgB;EACd,MAAM;EACN,UAAU;EACX;CACD,oBAAoB;EAClB,MAAM;EACN,UAAU;EACX;CACD,iBAAiB;EACf,MAAM;EACN,UAAU;EACX;CACD,mBAAmB;EACjB,MAAM;EACN,UAAU;EACX;CACD,cAAc;EACZ,MAAM;EACN,UAAU;EACX;CACD,QAAQ;EACN,MAAM;EACN,cAAc;EACf;CACD,cAAc;EACZ,MAAM;EACN,UAAU;EACX;CACD,YAAY;EACV,MAAM;EACN,UAAU;EACX;CACD,SAAS;EACP,MAAM;EACN,UAAU;EACX;CACD,UAAU;EACR,MAAM;EACN,UAAU;EACV,cAAc;EACf;CACD,YAAY;EACV,MAAM;EACN,UAAU;EACX;CACD,WAAW;EACT,MAAM;EACN,UAAU;EACV,cAAc;EACf;CACD,gBAAgB;EACd,MAAM;EACN,UAAU;EACX;CACD,aAAa;EACX,MAAM;EACN,UAAU;EACX;CACD,UAAU;EACR,MAAM;EACN,UAAU;EACX;CACD,kBAAkB;EAChB,MAAM;EACN,UAAU;EACV,cAAc;EACf;CACD,eAAe;EACb,MAAM;EACN,UAAU;EACX;CACD,OAAO;EACL,MAAM;EACN,UAAU;EACX;CACD,YAAY;EACV,MAAM;EACN,UAAU;EACX;CACD,UAAU;EACR,MAAM;EACN,UAAU;EACX;CACD,UAAU;EACR,MAAM;EACN,UAAU;EACX;CACF,EACF,EACF;AAED,MAAa,OAAO,EAClB,MAAM,EACJ,QAAQ,EACN,gBAAgB;CACd,MAAM;CACN,UAAU;CACX,EACF,EACF,EACF;AAED,MAAa,eAAe,EAC1B,cAAc,EACZ,QAAQ,EACN,gBAAgB;CACd,MAAM;CACN,UAAU;CACX,EACF,EACF,EACF;AAMD,MAAa,aACX,YACuB;CACvB,IAAI,aAAuC,EAAE;AAE7C,KAAI,QAAQ,cAAc,QACxB,cAAa;EACX,GAAG;EACH,GAAG;EACJ;KAED,cAAa,EACX,GAAG,MACJ;AAGH,KAAI,QAAQ,cAAc,QACxB,cAAa;EACX,GAAG;EACH,GAAG;EACJ;AAGH,KACE,QAAQ,UACR,CAAC,QAAQ,cAAc,WACvB,kBAAkB,QAAQ,QAC1B;EACA,MAAM,EAAE,cAAc,eAAe,GAAG,eAAe,QAAQ;AAC/D,SAAO,YAAY,YAAY,WAAW;;AAG5C,QAAO,YAAY,YAAY,QAAQ,OAAO;;;;;ACpJhD,MAAa,QAA+B,YAAe;CACzD,MAAM,SAAS,aAAa,QAAQ;CAEpC,MAAM,wBAAwB;EAC5B,wBAAwB,OAAO;EAC/B,qBAAqB,OAAO;EAC5B,wBAAwB,OAAO;EAC/B,uBAAuB,OAAO;EAC9B,wBAAwB,OAAO;EAC/B,uBAAuB,OAAO;EAC9B,qBAAqB,OAAO;EAC5B,wBAAwB,OAAO;EAC/B,oBAAoB,OAAO;EAC3B,wBAAwB,OAAO;EAC/B,cAAc,OAAO;EACtB;CAED,MAAM,mBAAmB;EACvB,mBAAmB,OAAO;EAC1B,mBAAmB,OAAO;EAC3B;CAED,MAAM,mBAAmB;EACvB,qBAAqB,OAAO;EAC5B,mBAAmB,OAAO;EAC1B,kBAAkB,OAAO;EAC1B;CAED,MAAM,kBAAkB;EACtB,oBAAoB,OAAO;EAC3B,kBAAkB,OAAO;EACzB,iBAAiB,OAAO;EACzB;CAED,MAAM,uBAAuB;EAC3B,qBAAqB,OAAO;EAC5B,wBAAwB,OAAO;EAChC;CAED,MAAM,mBAAmB;EACvB,iBAAiB,OAAO;EACxB,eAAe,OAAO;EACtB,aAAa,OAAO;EACrB;AAED,QAAO;EACL,IAAI;EACJ,WAAW;GACT,aAAa,OAAO;GACpB,GAAG;GACH,GAAG;GACH,GAAG;GACH,GAAG;GACH,GAAG;GACH,GAAK,QAAQ,cAAc,UACvB,wBACA,EAAE;GAKP;EACD,KAAK,KAAK;AACR,OAAI,QAAQ,cAAc,SAAS;IACjC,MAAM,YAAY,IAAI,UAAU,eAAe;AAC/C,QAAI,CAAC,WAAW;AACd,SAAI,OAAO,MAAM,gCAAgC;AACjD;;IAGF,MAAM,gBAAgB,UAAU,SAAS,qBAAqB,EAAE;;;;IAKhE,MAAM,sBAAsB,OAAO,SAE7B;KACJ,MAAM,eAAgB,MAAM,IAAI,QAAQ,QAAQ;MAC9C,OAAO;MACP,OAAO,CACL;OACE,OAAO;OACP,OAAO,KAAK,aAAa;OAC1B,CACF;MACF,CAAC;AAEF,SAAI,gBAAgB,SAAS,aAAa,CACxC,OAAM,eACJ,eACA,iBAAiB,oCAClB;;AAIL,cAAU,UAAU;KAClB,GAAG,UAAU;KACb,mBAAmB;MACjB,GAAG;MACH,0BAA0B,OAAO,SAE3B;AACJ,WAAI,cAAc,yBAChB,OAAM,cAAc,yBAAyB,KAAK;AAEpD,aAAM,oBAAoB,KAAK;;MAElC;KACF;;;EAGL,QAAQ,UAAU,QAAQ;EAC1B,OAAO,EACL,OAAO,CACL;GACE,QAAQ,SAAS;AACf,WAAO,QAAQ,SAAS;;GAE1B,MAAM,QAAQ,KAAK;GAGpB,CACF,EACF;EACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "better-auth-payu",
|
|
3
|
+
"author": "",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.mts",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"payu",
|
|
11
|
+
"auth",
|
|
12
|
+
"subscription",
|
|
13
|
+
"better-auth",
|
|
14
|
+
"standing-instructions",
|
|
15
|
+
"recurring-payments"
|
|
16
|
+
],
|
|
17
|
+
"module": "dist/index.mjs",
|
|
18
|
+
"description": "PayU plugin for Better Auth",
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "vitest",
|
|
21
|
+
"coverage": "vitest run --coverage --coverage.provider=istanbul",
|
|
22
|
+
"build": "tsdown",
|
|
23
|
+
"dev": "tsdown --watch",
|
|
24
|
+
"typecheck": "tsc --project tsconfig.json"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"dev-source": "./src/index.ts",
|
|
35
|
+
"types": "./dist/index.d.mts",
|
|
36
|
+
"default": "./dist/index.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./client": {
|
|
39
|
+
"dev-source": "./src/client.ts",
|
|
40
|
+
"types": "./dist/client.d.mts",
|
|
41
|
+
"default": "./dist/client.mjs"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"typesVersions": {
|
|
45
|
+
"*": {
|
|
46
|
+
"*": [
|
|
47
|
+
"./dist/index.d.mts"
|
|
48
|
+
],
|
|
49
|
+
"client": [
|
|
50
|
+
"./dist/client.d.mts"
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"defu": "^6.1.4",
|
|
56
|
+
"zod": "^4.3.6"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"better-auth": "*"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/node": "^25.2.3",
|
|
63
|
+
"better-auth": "^1.2.10",
|
|
64
|
+
"better-call": "^1.0.10",
|
|
65
|
+
"tsdown": "^0.12.4",
|
|
66
|
+
"typescript": "^5.8.3",
|
|
67
|
+
"vitest": "^4.0.18"
|
|
68
|
+
}
|
|
69
|
+
}
|