better-auth-paystack
Version:
Production-ready Paystack billing plugin for Better Auth. Supports subscriptions, one-time payments, organization billing, secure webhooks and more
1 lines • 329 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","names":["NodeBuffer","z","getAllowedSubscriptionChannels","subCode"],"sources":["../src/models.ts","../src/billing-store.ts","../src/paystack-sdk.ts","../src/customer.ts","../src/utils.ts","../src/limits.ts","../src/credential-crypto.ts","../src/payment-credentials.ts","../src/reference-access.ts","../src/subscription-fulfillment.ts","../src/reconciliation.ts","../src/reference-middleware.ts","../src/route-modules/callback-url.ts","../src/route-modules/catalog.ts","../src/route-modules/checkout.ts","../src/route-modules/shared.ts","../src/route-modules/subscriptions.ts","../src/route-modules/webhook.ts","../src/subscription-lifecycle.ts","../src/routes.ts","../src/schema.ts","../src/operations.ts","../src/migrations.ts","../src/index.ts"],"sourcesContent":["/** Provider-owned Better Auth model names. Keep these centralized so a provider\n * model cannot accidentally fall back to Better Auth's generic billing tables. */\nexport const PAYSTACK_MODELS = {\n customer: \"paystackCustomer\",\n paymentCredential: \"paystackPaymentCredential\",\n subscription: \"paystackSubscription\",\n transaction: \"paystackTransaction\",\n product: \"paystackProduct\",\n plan: \"paystackPlan\",\n webhookEvent: \"paystackWebhookEvent\",\n} as const;\n\nexport const LEGACY_PAYSTACK_MODELS = {\n subscription: \"subscription\",\n} as const;\n","import type { GenericEndpointContext } from \"better-auth\";\n\nimport { PAYSTACK_MODELS } from \"./models.ts\";\nimport type {\n Member,\n PaystackCustomer,\n PaystackOrganization,\n PaystackPlan,\n PaystackProduct,\n PaystackTransaction,\n PaystackWebhookEventRecord,\n Subscription,\n User,\n} from \"./types.ts\";\n\nexport type BillingStoreAdapter = Pick<\n GenericEndpointContext[\"context\"][\"adapter\"],\n \"create\" | \"delete\" | \"deleteMany\" | \"findMany\" | \"findOne\" | \"update\" | \"updateMany\"\n>;\ntype Adapter = BillingStoreAdapter;\ntype WhereValue = string | number | boolean | null;\ntype WhereClause = { field: string; value: WhereValue }[];\n\nexport interface BillingStore {\n findSubscriptionById(id: string): Promise<Subscription | null>;\n findSubscriptionByCode(subscriptionCode: string): Promise<Subscription | null>;\n findSubscriptionsByReference(referenceId: string): Promise<Subscription[]>;\n findCurrentSubscription(\n referenceId: string,\n groupId?: string | null,\n ): Promise<Subscription | null>;\n retireCompetingSubscriptions(\n referenceId: string,\n groupId: string | null,\n exceptId: string,\n ): Promise<void>;\n findSubscriptionsByTransactionReference(reference: string): Promise<Subscription[]>;\n createSubscription(data: Partial<Subscription> & Record<string, unknown>): Promise<Subscription>;\n updateSubscription(\n id: string,\n update: Partial<Subscription> & Record<string, unknown>,\n ): Promise<Subscription | null>;\n updateSubscriptionByCode(\n subscriptionCode: string,\n update: Partial<Subscription> & Record<string, unknown>,\n ): Promise<Subscription | null>;\n findCustomerByReference(\n referenceType: \"user\" | \"organization\",\n referenceId: string,\n ): Promise<PaystackCustomer | null>;\n findCustomerByCode(customerCode: string): Promise<PaystackCustomer | null>;\n saveCustomer(\n referenceType: \"user\" | \"organization\",\n referenceId: string,\n customerCode: string,\n email?: string | null,\n ): Promise<PaystackCustomer>;\n createTransaction(\n data: Partial<PaystackTransaction> & Record<string, unknown>,\n ): Promise<PaystackTransaction>;\n findTransactionByReference(reference: string): Promise<PaystackTransaction | null>;\n updateTransactionByReference(\n reference: string,\n update: Partial<PaystackTransaction> & Record<string, unknown>,\n ): Promise<PaystackTransaction | null>;\n createWebhookEvent(\n data: Omit<PaystackWebhookEventRecord, \"id\">,\n ): Promise<PaystackWebhookEventRecord>;\n findWebhookEvent(eventId: string): Promise<PaystackWebhookEventRecord | null>;\n updateWebhookEvent(\n eventId: string,\n update: Partial<PaystackWebhookEventRecord> & Record<string, unknown>,\n ): Promise<PaystackWebhookEventRecord | null>;\n listTransactions(referenceId: string): Promise<PaystackTransaction[]>;\n listProducts(): Promise<PaystackProduct[]>;\n findProductByName(name: string): Promise<PaystackProduct | null>;\n findProductBySlug(slug: string): Promise<PaystackProduct | null>;\n updateProduct(\n id: string,\n update: Partial<PaystackProduct> & Record<string, unknown>,\n ): Promise<void>;\n upsertProductByPaystackId(\n paystackId: string,\n data: Partial<PaystackProduct> & Record<string, unknown>,\n ): Promise<void>;\n listPlans(): Promise<PaystackPlan[]>;\n findPlanByName(name: string): Promise<PaystackPlan | null>;\n findPlanByCode(planCode: string): Promise<PaystackPlan | null>;\n upsertPlanByPaystackId(\n paystackId: string,\n data: Partial<PaystackPlan> & Record<string, unknown>,\n ): Promise<void>;\n findUser(id: string): Promise<User | null>;\n findOrganization(id: string): Promise<PaystackOrganization | null>;\n findOrganizationOwner(organizationId: string): Promise<Member | null>;\n listMembers(organizationId: string): Promise<Member[]>;\n listTeams(organizationId: string): Promise<unknown[]>;\n saveCustomerCode(\n referenceId: string,\n customerCode: string,\n isOrganization: boolean,\n email?: string | null,\n ): Promise<void>;\n}\n\nfunction sortSubscriptionsForCurrent(subscriptions: Subscription[]): Subscription[] {\n const statusRank = new Map([\n [\"active\", 0],\n [\"trialing\", 1],\n [\"incomplete\", 2],\n [\"past_due\", 3],\n [\"canceled\", 4],\n ]);\n\n return [...subscriptions].sort((a, b) => {\n const rankA = statusRank.get(a.status) ?? 99;\n const rankB = statusRank.get(b.status) ?? 99;\n if (rankA !== rankB) return rankA - rankB;\n return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();\n });\n}\n\nexport function createBillingStore(ctx: GenericEndpointContext): BillingStore {\n return createBillingStoreFromAdapter(ctx.context.adapter);\n}\n\nexport function createBillingStoreFromAdapter(adapter: Adapter): BillingStore {\n const findOne = async <T>(model: string, where: WhereClause): Promise<T | null> => {\n try {\n return (await adapter.findOne<T>({ model, where })) ?? null;\n } catch {\n // Adapters such as the in-memory adapter create provider tables lazily.\n return null;\n }\n };\n\n const findMany = async <T>(model: string, where?: WhereClause): Promise<T[]> => {\n try {\n return (await adapter.findMany<T>({ model, ...(where ? { where } : {}) })) ?? [];\n } catch {\n return [];\n }\n };\n\n return {\n findSubscriptionById: (id) =>\n findOne<Subscription>(PAYSTACK_MODELS.subscription, [{ field: \"id\", value: id }]),\n findSubscriptionByCode: (subscriptionCode) =>\n findOne<Subscription>(PAYSTACK_MODELS.subscription, [\n { field: \"subscriptionCode\", value: subscriptionCode },\n ]),\n findSubscriptionsByReference: (referenceId) =>\n findMany<Subscription>(PAYSTACK_MODELS.subscription, [\n { field: \"referenceId\", value: referenceId },\n ]),\n async findCurrentSubscription(referenceId, groupId) {\n const subscriptions = await this.findSubscriptionsByReference(referenceId);\n const scoped =\n groupId === undefined\n ? subscriptions\n : subscriptions.filter((subscription) =>\n groupId === null\n ? subscription.groupId === undefined ||\n subscription.groupId === null ||\n subscription.groupId === \"\"\n : subscription.groupId === groupId,\n );\n return sortSubscriptionsForCurrent(scoped)[0] ?? null;\n },\n async retireCompetingSubscriptions(referenceId, groupId, exceptId) {\n const subscriptions = await this.findSubscriptionsByReference(referenceId);\n const selected = subscriptions.find((subscription) => subscription.id === exceptId);\n const competitors = subscriptions.filter(\n (subscription) =>\n subscription.id !== exceptId &&\n (selected === undefined ||\n new Date(subscription.createdAt).getTime() <= new Date(selected.createdAt).getTime()) &&\n (subscription.status === \"active\" || subscription.status === \"trialing\") &&\n (groupId === null\n ? subscription.groupId === undefined ||\n subscription.groupId === null ||\n subscription.groupId === \"\"\n : subscription.groupId === groupId),\n );\n const now = new Date();\n for (const subscription of competitors) {\n await this.updateSubscription(subscription.id, {\n status: \"canceled\",\n cancelAtPeriodEnd: false,\n canceledAt: now,\n endedAt: now,\n updatedAt: now,\n });\n }\n },\n findSubscriptionsByTransactionReference: (reference) =>\n findMany<Subscription>(PAYSTACK_MODELS.subscription, [\n { field: \"transactionReference\", value: reference },\n ]),\n createSubscription: async (data) =>\n await adapter.create({\n model: PAYSTACK_MODELS.subscription,\n data: data as Omit<Subscription, \"id\">,\n }),\n updateSubscription: (id, update) =>\n adapter.update<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n update,\n where: [{ field: \"id\", value: id }],\n }),\n updateSubscriptionByCode: (subscriptionCode, update) =>\n adapter.update<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n update,\n where: [{ field: \"subscriptionCode\", value: subscriptionCode }],\n }),\n createTransaction: async (data) =>\n await adapter.create({\n model: PAYSTACK_MODELS.transaction,\n data: data as Omit<PaystackTransaction, \"id\">,\n }),\n findTransactionByReference: (reference) =>\n findOne<PaystackTransaction>(PAYSTACK_MODELS.transaction, [\n { field: \"reference\", value: reference },\n ]),\n updateTransactionByReference: (reference, update) =>\n adapter.update<PaystackTransaction>({\n model: PAYSTACK_MODELS.transaction,\n update,\n where: [{ field: \"reference\", value: reference }],\n }),\n createWebhookEvent: (data) =>\n adapter.create({\n model: PAYSTACK_MODELS.webhookEvent,\n data,\n }),\n findWebhookEvent: (eventId) =>\n adapter.findOne<PaystackWebhookEventRecord>({\n model: PAYSTACK_MODELS.webhookEvent,\n where: [{ field: \"eventId\", value: eventId }],\n }),\n updateWebhookEvent: (eventId, update) =>\n adapter.update<PaystackWebhookEventRecord>({\n model: PAYSTACK_MODELS.webhookEvent,\n update,\n where: [{ field: \"eventId\", value: eventId }],\n }),\n async listTransactions(referenceId) {\n const transactions = await findMany<PaystackTransaction>(PAYSTACK_MODELS.transaction, [\n { field: \"referenceId\", value: referenceId },\n ]);\n return transactions.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n },\n async listProducts() {\n const products = await findMany<PaystackProduct>(PAYSTACK_MODELS.product);\n return products.sort((a, b) => a.name.localeCompare(b.name));\n },\n findProductByName: (name) =>\n findOne<PaystackProduct>(PAYSTACK_MODELS.product, [{ field: \"name\", value: name }]),\n findProductBySlug: (slug) =>\n findOne<PaystackProduct>(PAYSTACK_MODELS.product, [{ field: \"slug\", value: slug }]),\n async updateProduct(id, update) {\n await adapter.update({\n model: PAYSTACK_MODELS.product,\n update,\n where: [{ field: \"id\", value: id }],\n });\n },\n async upsertProductByPaystackId(paystackId, data) {\n const existing = await findOne<PaystackProduct>(PAYSTACK_MODELS.product, [\n { field: \"paystackId\", value: paystackId },\n ]);\n if (existing?.id !== undefined) {\n const { createdAt: _createdAt, ...update } = data;\n await adapter.update({\n model: PAYSTACK_MODELS.product,\n update,\n where: [{ field: \"id\", value: String(existing.id) }],\n });\n return;\n }\n await adapter.create({ model: PAYSTACK_MODELS.product, data });\n },\n listPlans: () => findMany<PaystackPlan>(PAYSTACK_MODELS.plan),\n findPlanByName: (name) =>\n findOne<PaystackPlan>(PAYSTACK_MODELS.plan, [{ field: \"name\", value: name }]),\n findPlanByCode: (planCode) =>\n findOne<PaystackPlan>(PAYSTACK_MODELS.plan, [{ field: \"planCode\", value: planCode }]),\n async upsertPlanByPaystackId(paystackId, data) {\n const existing = await findOne<PaystackPlan>(PAYSTACK_MODELS.plan, [\n { field: \"paystackId\", value: paystackId },\n ]);\n if (existing?.id !== undefined) {\n const { createdAt: _createdAt, ...update } = data;\n await adapter.update({\n model: PAYSTACK_MODELS.plan,\n update,\n where: [{ field: \"id\", value: existing.id }],\n });\n return;\n }\n await adapter.create({ model: PAYSTACK_MODELS.plan, data });\n },\n findUser: (id) => findOne<User>(\"user\", [{ field: \"id\", value: id }]),\n findOrganization: (id) =>\n findOne<PaystackOrganization>(\"organization\", [{ field: \"id\", value: id }]),\n findOrganizationOwner: (organizationId) =>\n findOne<Member>(\"member\", [\n { field: \"organizationId\", value: organizationId },\n { field: \"role\", value: \"owner\" },\n ]),\n listMembers: (organizationId) =>\n findMany<Member>(\"member\", [{ field: \"organizationId\", value: organizationId }]),\n listTeams: (organizationId) =>\n findMany(\"team\", [{ field: \"organizationId\", value: organizationId }]),\n findCustomerByReference: (referenceType, referenceId) =>\n findOne<PaystackCustomer>(PAYSTACK_MODELS.customer, [\n { field: \"referenceKey\", value: `${referenceType}:${referenceId}` },\n ]),\n findCustomerByCode: (customerCode) =>\n findOne<PaystackCustomer>(PAYSTACK_MODELS.customer, [\n { field: \"customerCode\", value: customerCode },\n ]),\n async saveCustomer(referenceType, referenceId, customerCode, email) {\n const referenceKey = `${referenceType}:${referenceId}`;\n const existing = await findOne<PaystackCustomer>(PAYSTACK_MODELS.customer, [\n { field: \"referenceKey\", value: referenceKey },\n ]);\n const now = new Date();\n const hasEmail = email !== undefined && email !== null && email !== \"\";\n if (existing) {\n const updated = await adapter.update<PaystackCustomer>({\n model: PAYSTACK_MODELS.customer,\n update: { customerCode, ...(hasEmail ? { email } : {}), updatedAt: now },\n where: [{ field: \"id\", value: existing.id }],\n });\n return (\n updated ?? { ...existing, customerCode, email: email ?? existing.email, updatedAt: now }\n );\n }\n return adapter.create({\n model: PAYSTACK_MODELS.customer,\n data: {\n referenceType,\n referenceId,\n referenceKey,\n customerCode,\n ...(hasEmail ? { email } : {}),\n createdAt: now,\n updatedAt: now,\n },\n });\n },\n async saveCustomerCode(referenceId, customerCode, isOrganization, email) {\n await this.saveCustomer(\n isOrganization ? \"organization\" : \"user\",\n referenceId,\n customerCode,\n email,\n );\n },\n };\n}\n","import {\n PaystackError,\n PaystackResponse,\n type CustomerCreatePayload,\n type CustomerUpdatePayload,\n} from \"@alexasomba/paystack-node\";\nimport type { components } from \"@alexasomba/paystack-node\";\nimport { APIError } from \"better-auth/api\";\n\nimport type { PaystackClientLike } from \"./types.ts\";\n\n/**\n * Interface for checking if a result is a PaystackResponse from the SDK v1.9.1+\n */\nfunction IsPaystackResponse(value: unknown): value is PaystackResponse<unknown> {\n return value instanceof PaystackResponse;\n}\n\n/**\n * Unwraps a Paystack SDK result, extracting the data or throwing an APIError if the request failed.\n * Leverages the native .unwrap() method in SDK v1.9.1+ if available.\n */\nexport function unwrapSdkResult<T = unknown>(result: unknown): T {\n if (IsPaystackResponse(result)) {\n try {\n return result.unwrap() as T;\n } catch (e: unknown) {\n if (e instanceof PaystackError) {\n throw new APIError(e.status === 404 ? \"NOT_FOUND\" : \"BAD_REQUEST\", {\n message: e.message,\n status: e.status,\n });\n }\n\n throw new APIError(\"BAD_REQUEST\", {\n message: (e as Error)?.message ?? \"Paystack API error\",\n });\n }\n }\n\n // Fallback for custom or legacy structures (e.g. from mocks in tests)\n let current = result;\n\n // Handle nested { data: { data: ... } } or { status: true, data: ... }\n while (current !== null && current !== undefined && typeof current === \"object\") {\n const body = current as Record<string, unknown>;\n\n // Check for Paystack Error shape\n if (body.status === false) {\n throw new APIError(\"BAD_REQUEST\", {\n message: (body.message as string | undefined) ?? \"Paystack API error\",\n });\n }\n\n // Stop if we have found the actual transaction/subscription payload properties\n if (\"authorization_url\" in body || \"reference\" in body || \"customer_code\" in body) {\n break;\n }\n\n // If there's a data property, unwrap it and continue checking\n if (\n \"data\" in body &&\n body.data !== undefined &&\n body.data !== null &&\n typeof body.data === \"object\"\n ) {\n current = body.data;\n continue;\n }\n break;\n }\n\n return current as T;\n}\n\n/**\n * Returns the operations object from a Paystack client.\n * For v1.9.1+, the client itself uses the grouped structure.\n */\nexport function getPaystackOps(client?: PaystackClientLike): PaystackClientLike | undefined {\n return client;\n}\n\ninterface ChargeAuthorizationPayload {\n email: string;\n amount: number;\n authorization_code: string;\n reference: string;\n metadata?: string;\n}\n\ninterface CreateSubscriptionPayload {\n customer: string;\n plan: string;\n authorization?: string;\n start_date?: string;\n}\n\nexport interface PaystackAdapter {\n initializeTransaction(\n body: components[\"schemas\"][\"TransactionInitialize\"],\n ): Promise<components[\"schemas\"][\"TransactionInitializeResponse\"][\"data\"]>;\n verifyTransaction(reference: string): Promise<unknown>;\n chargeAuthorization(body: ChargeAuthorizationPayload): Promise<unknown>;\n createCustomer(body: CustomerCreatePayload): Promise<unknown>;\n fetchCustomer(emailOrCode: string): Promise<unknown>;\n updateCustomer(\n emailOrCode: string,\n body: CustomerUpdatePayload & { email?: string },\n ): Promise<unknown>;\n listProducts(): Promise<components[\"schemas\"][\"ProductListsResponseArray\"][]>;\n fetchProduct(productId: number): Promise<unknown>;\n listPlans(): Promise<components[\"schemas\"][\"PlanListResponseArray\"][]>;\n createSubscription(body: CreateSubscriptionPayload): Promise<unknown>;\n fetchSubscription(subscriptionCode: string): Promise<unknown>;\n disableSubscription(body: { code: string; token: string }): Promise<unknown>;\n enableSubscription(body: { code: string; token: string }): Promise<unknown>;\n manageSubscriptionLink(subscriptionCode: string): Promise<{ link: string }>;\n}\n\nexport function createPaystackAdapter(client?: PaystackClientLike): PaystackAdapter {\n const requireClient = (): PaystackClientLike => {\n if (client === undefined || client === null) {\n throw new APIError(\"BAD_REQUEST\", { message: \"Paystack client is not configured\" });\n }\n return client;\n };\n\n return {\n async initializeTransaction(\n body: components[\"schemas\"][\"TransactionInitialize\"],\n ): Promise<components[\"schemas\"][\"TransactionInitializeResponse\"][\"data\"]> {\n const raw = await requireClient().transaction?.initialize({ body });\n return unwrapSdkResult<components[\"schemas\"][\"TransactionInitializeResponse\"][\"data\"]>(raw);\n },\n async verifyTransaction(reference: string): Promise<unknown> {\n const raw = await requireClient().transaction?.verify(reference);\n return unwrapSdkResult(raw);\n },\n async chargeAuthorization(body: ChargeAuthorizationPayload): Promise<unknown> {\n const raw = await requireClient().transaction?.chargeAuthorization({ body });\n return unwrapSdkResult(raw);\n },\n async createCustomer(body: CustomerCreatePayload): Promise<unknown> {\n const raw = await requireClient().customer?.create({ body });\n return unwrapSdkResult(raw);\n },\n async fetchCustomer(emailOrCode: string): Promise<unknown> {\n const raw = await requireClient().customer?.fetch(emailOrCode);\n return unwrapSdkResult(raw);\n },\n async updateCustomer(\n emailOrCode: string,\n body: CustomerUpdatePayload & { email?: string },\n ): Promise<unknown> {\n const raw = await requireClient().customer?.update(emailOrCode, {\n body: body,\n });\n return unwrapSdkResult(raw);\n },\n async listProducts(): Promise<components[\"schemas\"][\"ProductListsResponseArray\"][]> {\n const raw = await requireClient().product?.list({});\n return unwrapSdkResult<components[\"schemas\"][\"ProductListsResponseArray\"][]>(raw);\n },\n async fetchProduct(productId: number): Promise<unknown> {\n const raw = await requireClient().product?.fetch(productId);\n return unwrapSdkResult(raw);\n },\n async listPlans(): Promise<components[\"schemas\"][\"PlanListResponseArray\"][]> {\n const raw = await requireClient().plan?.list();\n return unwrapSdkResult<components[\"schemas\"][\"PlanListResponseArray\"][]>(raw);\n },\n async createSubscription(body: CreateSubscriptionPayload): Promise<unknown> {\n const raw = await requireClient().subscription?.create({ body });\n return unwrapSdkResult(raw);\n },\n async fetchSubscription(subscriptionCode: string): Promise<unknown> {\n const raw = await requireClient().subscription?.fetch(subscriptionCode);\n return unwrapSdkResult(raw);\n },\n async disableSubscription(body: { code: string; token: string }): Promise<unknown> {\n const raw = await requireClient().subscription?.disable({ body });\n return unwrapSdkResult(raw);\n },\n async enableSubscription(body: { code: string; token: string }): Promise<unknown> {\n const raw = await requireClient().subscription?.enable({ body });\n return unwrapSdkResult(raw);\n },\n async manageSubscriptionLink(subscriptionCode: string): Promise<{ link: string }> {\n const raw = await requireClient().subscription?.manageLink(subscriptionCode);\n return unwrapSdkResult<{ link: string }>(raw);\n },\n };\n}\n","import { createBillingStoreFromAdapter } from \"./billing-store.ts\";\nimport { parsePaystackMetadata, stringifyPaystackMetadata } from \"./metadata.ts\";\nimport { createPaystackAdapter } from \"./paystack-sdk.ts\";\nimport type { PaystackClientLike, PaystackCustomerResponse } from \"./types.ts\";\n\ninterface Logger {\n error(message: string, error?: unknown): void;\n}\ntype Adapter = Parameters<typeof createBillingStoreFromAdapter>[0];\n\ninterface BillingReference {\n id: string;\n type: \"user\" | \"organization\";\n email: string;\n name?: string | null;\n emailVerified?: boolean;\n paystackCustomerCode?: string | null;\n}\n\nfunction isNotFound(error: unknown): boolean {\n if (error === null || typeof error !== \"object\") return false;\n const candidate = error as Record<string, unknown>;\n return candidate.status === 404 || candidate.statusCode === 404;\n}\n\nfunction customerCode(customer: unknown): string | undefined {\n if (customer === null || typeof customer !== \"object\") return undefined;\n const code = (customer as Record<string, unknown>).customer_code;\n return typeof code === \"string\" && code !== \"\" ? code : undefined;\n}\n\nfunction ownsCustomer(customer: unknown, reference: BillingReference): boolean {\n if (customer === null || typeof customer !== \"object\") return false;\n const metadata = parsePaystackMetadata((customer as Record<string, unknown>).metadata);\n const expectedIdKey = reference.type === \"user\" ? \"userId\" : \"organizationId\";\n const otherIdKey = reference.type === \"user\" ? \"organizationId\" : \"userId\";\n return (\n metadata[expectedIdKey] === reference.id &&\n metadata[otherIdKey] === undefined &&\n (metadata.customerType === undefined || metadata.customerType === reference.type)\n );\n}\n\nfunction hasOwner(customer: unknown): boolean {\n if (customer === null || typeof customer !== \"object\") return false;\n const metadata = parsePaystackMetadata((customer as Record<string, unknown>).metadata);\n return (\n typeof metadata.userId === \"string\" ||\n typeof metadata.organizationId === \"string\" ||\n typeof metadata.customerType === \"string\"\n );\n}\n\nfunction ownershipMetadata(reference: BillingReference, existing?: unknown): string | undefined {\n return stringifyPaystackMetadata({\n ...parsePaystackMetadata(existing),\n customerType: reference.type,\n ...(reference.type === \"user\" ? { userId: reference.id } : { organizationId: reference.id }),\n });\n}\n\nexport async function resolvePaystackCustomer(input: {\n adapter: Adapter;\n client: PaystackClientLike;\n logger: Logger;\n reference: BillingReference;\n createParams?: Record<string, unknown>;\n}): Promise<{ customer: PaystackCustomerResponse; created: boolean } | null> {\n const { adapter, client, logger, reference } = input;\n const store = createBillingStoreFromAdapter(adapter);\n const persisted = await store.findCustomerByReference(reference.type, reference.id);\n let legacyCode: string | undefined;\n try {\n const legacy = await adapter.findOne<{ paystackCustomerCode?: string | null }>({\n model: reference.type,\n where: [{ field: \"id\", value: reference.id }],\n select: [\"paystackCustomerCode\"],\n });\n legacyCode = legacy?.paystackCustomerCode ?? undefined;\n } catch {\n // The legacy column is optional after the v4 schema migration.\n }\n const existingCode = reference.paystackCustomerCode ?? persisted?.customerCode ?? legacyCode;\n if (typeof existingCode === \"string\" && existingCode !== \"\") {\n if (persisted === null) {\n await store.saveCustomer(reference.type, reference.id, existingCode, reference.email);\n }\n return null;\n }\n\n const sdk = createPaystackAdapter(client);\n let existing: PaystackCustomerResponse | null = null;\n if (typeof client.customer?.fetch === \"function\") {\n try {\n existing =\n ((await sdk.fetchCustomer(reference.email)) as PaystackCustomerResponse | undefined) ??\n null;\n } catch (error: unknown) {\n if (!isNotFound(error)) {\n logger.error(\"Failed to look up Paystack customer; customer creation was skipped\", error);\n return null;\n }\n }\n }\n\n if (existing !== null) {\n const code = customerCode(existing);\n if (code === undefined) {\n logger.error(\"Paystack customer lookup returned no customer code\");\n return null;\n }\n\n const owned = ownsCustomer(existing, reference);\n const canClaimLegacy =\n reference.type === \"user\" && reference.emailVerified === true && !hasOwner(existing);\n if (!owned && !canClaimLegacy) {\n logger.error(\"Paystack customer belongs to another billing reference\");\n return null;\n }\n\n const existingMetadata = (existing as unknown as Record<string, unknown>).metadata;\n if (canClaimLegacy || parsePaystackMetadata(existingMetadata).customerType !== reference.type) {\n await sdk.updateCustomer(code, {\n metadata: ownershipMetadata(reference, existingMetadata),\n });\n }\n await store.saveCustomer(reference.type, reference.id, code, reference.email);\n return { customer: existing, created: false };\n }\n\n const customer = (await sdk.createCustomer({\n ...input.createParams,\n email: reference.email,\n first_name: reference.name ?? undefined,\n metadata: ownershipMetadata(reference),\n })) as PaystackCustomerResponse;\n const code = customerCode(customer);\n if (code === undefined) return null;\n await store.saveCustomer(reference.type, reference.id, code, reference.email);\n return { customer, created: true };\n}\n","import type { GenericEndpointContext } from \"better-auth\";\n\nimport { createBillingStore } from \"./billing-store.ts\";\nimport { createPaystackAdapter } from \"./paystack-sdk.ts\";\nimport type {\n AnyPaystackOptions,\n PaystackClientLike,\n PaystackPlan,\n PaystackProduct,\n Subscription,\n PaystackProductResponse,\n} from \"./types.ts\";\n\nexport function getPlanSeatAmount(plan: PaystackPlan): number | undefined {\n if (plan.seatAmount !== undefined) {\n if (typeof plan.seatAmount === \"number\" && Number.isFinite(plan.seatAmount)) {\n return plan.seatAmount;\n }\n throw new Error(`Invalid seatAmount for plan '${plan.name}'. Expected a finite number.`);\n }\n\n if (plan.seatPriceId === undefined || plan.seatPriceId === null || plan.seatPriceId === \"\") {\n return undefined;\n }\n\n const parsed = typeof plan.seatPriceId === \"string\" ? Number(plan.seatPriceId) : plan.seatPriceId;\n if (typeof parsed === \"number\" && Number.isFinite(parsed)) {\n return parsed;\n }\n\n throw new Error(\n `Invalid seatPriceId for plan '${plan.name}'. Expected a numeric amount in the smallest currency unit.`,\n );\n}\n\nexport function calculatePlanAmount(plan: PaystackPlan, quantity: number): number {\n return (plan.amount ?? 0) + quantity * (getPlanSeatAmount(plan) ?? 0);\n}\n\nexport function normalizeSubscriptionGroup(group: string | undefined | null): string | null {\n const normalized = group?.trim().toLowerCase();\n return normalized === undefined || normalized === \"\" ? null : normalized;\n}\n\nexport function isLocalSubscriptionCode(subscriptionCode: string | undefined | null): boolean {\n return (\n typeof subscriptionCode === \"string\" &&\n (subscriptionCode.startsWith(\"LOC_\") || subscriptionCode.startsWith(\"sub_local_\"))\n );\n}\n\nexport function isLocallyManagedSubscription(\n subscription: Pick<Subscription, \"subscriptionCode\" | \"planCode\">,\n): boolean {\n if (isLocalSubscriptionCode(subscription.subscriptionCode)) {\n return true;\n }\n\n if (typeof subscription.subscriptionCode === \"string\" && subscription.subscriptionCode !== \"\") {\n return false;\n }\n\n return (\n subscription.planCode === undefined ||\n subscription.planCode === null ||\n subscription.planCode === \"\"\n );\n}\n\nexport function assertLocallyManagedSubscription(\n subscription: Pick<Subscription, \"subscriptionCode\" | \"planCode\">,\n action: string,\n): void {\n if (!isLocallyManagedSubscription(subscription)) {\n throw new Error(\n `Paystack-managed subscriptions do not support ${action}. Use local billing for seat-based or prorated subscription changes.`,\n );\n }\n}\n\nexport async function getPlans(\n subscriptionOptions: AnyPaystackOptions[\"subscription\"],\n): Promise<PaystackPlan[]> {\n if (subscriptionOptions?.enabled === true) {\n return typeof subscriptionOptions.plans === \"function\"\n ? subscriptionOptions.plans()\n : subscriptionOptions.plans;\n }\n throw new Error(\"Subscriptions are not enabled in the Paystack options.\");\n}\n\nexport const getPlan: (\n options: AnyPaystackOptions,\n planId: string,\n) => Promise<PaystackPlan | null> = async (options, planId) => {\n if (options.subscription?.enabled === true) {\n const plans = await getPlans(options.subscription);\n return plans.find((plan) => plan.name === planId) ?? null;\n }\n return null;\n};\n\nexport async function getPlanByName(\n options: AnyPaystackOptions,\n name: string,\n): Promise<PaystackPlan | null> {\n if (typeof name !== \"string\" || name.trim() === \"\") {\n return null;\n }\n if (options.subscription?.enabled === true) {\n const plans = await getPlans(options.subscription);\n const normalizedName = name.toLowerCase();\n return (\n plans.find(\n (plan) => typeof plan.name === \"string\" && plan.name.toLowerCase() === normalizedName,\n ) ?? null\n );\n }\n return null;\n}\n\nexport async function getPlanByPriceId(\n options: AnyPaystackOptions,\n priceId: string,\n): Promise<PaystackPlan | null> {\n if (options.subscription?.enabled === true) {\n const plans = await getPlans(options.subscription);\n return plans.find((plan) => plan.name === priceId) ?? null;\n }\n return null;\n}\n\nexport async function getProducts(\n productOptions: AnyPaystackOptions[\"products\"],\n): Promise<PaystackProduct[]> {\n if (productOptions?.products) {\n return typeof productOptions.products === \"function\"\n ? await productOptions.products()\n : productOptions.products;\n }\n return [];\n}\n\nexport async function getProductByName(\n options: AnyPaystackOptions,\n name: string,\n): Promise<PaystackProduct | null> {\n return await getProducts(options.products).then((products) =>\n products !== undefined && products !== null\n ? (products.find((product) => product.name.toLowerCase() === name.toLowerCase()) ?? null)\n : null,\n );\n}\n\nexport function getNextPeriodEnd(startDate: Date, interval: string): Date {\n const date = new Date(startDate);\n switch (interval) {\n case \"daily\":\n date.setDate(date.getDate() + 1);\n break;\n case \"weekly\":\n date.setDate(date.getDate() + 7);\n break;\n case \"monthly\":\n date.setMonth(date.getMonth() + 1);\n break;\n case \"quarterly\":\n date.setMonth(date.getMonth() + 3);\n break;\n case \"biannually\":\n date.setMonth(date.getMonth() + 6);\n break;\n case \"annually\":\n date.setFullYear(date.getFullYear() + 1);\n break;\n default:\n // Default to monthly if unknown\n date.setMonth(date.getMonth() + 1);\n }\n return date;\n}\n\n/**\n * Validates if the amount meets Paystack's minimum transaction requirements.\n * Amounts should be in the smallest currency unit (e.g., kobo, cents).\n */\nexport function validateMinAmount(amount: number, currency: string): boolean {\n const minAmounts: Record<string, number> = {\n NGN: 5000, // 50.00\n GHS: 10, // 0.10\n ZAR: 100, // 1.00\n KES: 300, // 3.00\n USD: 200, // 2.00\n XOF: 100, // 1.00\n };\n const min = minAmounts[currency.toUpperCase()];\n return min !== undefined ? amount >= min : true;\n}\n\nexport async function syncProductQuantityFromPaystack(\n ctx: GenericEndpointContext,\n productName: string,\n paystackClient: PaystackClientLike,\n): Promise<void> {\n const store = createBillingStore(ctx);\n // Find the local product record (by name or slug)\n let localProduct = await store.findProductByName(productName);\n\n localProduct ??= await store.findProductBySlug(productName.toLowerCase().replace(/\\s+/g, \"-\"));\n\n if (\n localProduct?.paystackId === undefined ||\n localProduct.paystackId === null ||\n localProduct.paystackId === \"\"\n ) {\n // No local record with a Paystack ID - fall back to local decrement\n if (\n localProduct?.id !== undefined &&\n localProduct.unlimited !== true &&\n typeof localProduct.quantity === \"number\" &&\n localProduct.quantity > 0\n ) {\n await store.updateProduct(localProduct.id, {\n quantity: localProduct.quantity - 1,\n updatedAt: new Date(),\n });\n }\n return;\n }\n\n // Fetch the latest quantity from Paystack\n try {\n const paystackProductId = Number(localProduct.paystackId);\n if (!Number.isFinite(paystackProductId)) {\n return;\n }\n const sdkRes = (await createPaystackAdapter(paystackClient).fetchProduct(\n paystackProductId,\n )) as PaystackProductResponse;\n const remoteQuantity = sdkRes?.quantity;\n\n if (remoteQuantity !== undefined && localProduct.id !== undefined) {\n await store.updateProduct(localProduct.id, {\n quantity: remoteQuantity,\n updatedAt: new Date(),\n });\n }\n } catch {\n // If API call fails, fall back to local decrement\n if (\n localProduct?.id !== undefined &&\n localProduct.unlimited !== true &&\n typeof localProduct.quantity === \"number\" &&\n localProduct.quantity > 0\n ) {\n await store.updateProduct(localProduct.id, {\n quantity: localProduct.quantity - 1,\n updatedAt: new Date(),\n });\n }\n }\n}\n\nexport async function decrementProductQuantity(\n ctx: GenericEndpointContext,\n productName: string,\n): Promise<void> {\n const store = createBillingStore(ctx);\n let product = await store.findProductByName(productName);\n\n product ??= await store.findProductBySlug(productName.toLowerCase().replace(/\\s+/g, \"-\"));\n\n if (product !== undefined && product !== null) {\n if (\n product.unlimited !== true &&\n typeof product.quantity === \"number\" &&\n product.quantity > 0 &&\n product.id !== undefined\n ) {\n await store.updateProduct(product.id, {\n quantity: product.quantity - 1,\n updatedAt: new Date(),\n });\n }\n }\n}\n\nexport async function syncSubscriptionSeats(\n ctx: GenericEndpointContext,\n organizationId: string,\n options: AnyPaystackOptions,\n): Promise<void> {\n if (options.subscription?.enabled !== true) return;\n\n const store = createBillingStore(ctx);\n const subscriptions = (await store.findSubscriptionsByReference(organizationId)).filter(\n (subscription) => subscription.status === \"active\" || subscription.status === \"trialing\",\n );\n const seatSubscriptions: Subscription[] = [];\n for (const candidate of subscriptions) {\n const candidatePlan = await getPlanByName(options, candidate.plan);\n if (candidatePlan !== null && getPlanSeatAmount(candidatePlan) !== undefined) {\n seatSubscriptions.push(candidate);\n }\n }\n const members = await store.listMembers(organizationId);\n const quantity = members.length;\n for (const subscription of seatSubscriptions) {\n if (\n subscription.subscriptionCode === undefined ||\n subscription.subscriptionCode === null ||\n subscription.subscriptionCode === \"\"\n )\n continue;\n try {\n assertLocallyManagedSubscription(subscription, \"automatic seat sync\");\n\n // Locally managed subscriptions renew via saved authorizations, so seat count lives in our DB.\n await store.updateSubscription(subscription.id, {\n seats: quantity,\n updatedAt: new Date(),\n });\n } catch (e: unknown) {\n ctx.context.logger.error(\"Failed to sync subscription seats\", e);\n }\n }\n}\n","import type { GenericEndpointContext } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\n\nimport { createBillingStore } from \"./billing-store.ts\";\nimport type { AnyPaystackOptions, Subscription } from \"./types.ts\";\nimport { getPlanByName } from \"./utils.ts\";\n\nexport const getOrganizationSubscription = async (\n ctx: GenericEndpointContext,\n organizationId: string,\n groupId?: string | null,\n): Promise<Subscription | null> => {\n return createBillingStore(ctx).findCurrentSubscription(organizationId, groupId);\n};\n\nexport const checkSeatLimit = async (\n ctx: GenericEndpointContext,\n organizationId: string,\n seatsToAdd = 1,\n): Promise<boolean> => {\n const store = createBillingStore(ctx);\n const subscriptions = (await store.findSubscriptionsByReference(organizationId)).filter(\n (subscription) => subscription.status === \"active\" || subscription.status === \"trialing\",\n );\n const seatLimit = subscriptions.reduce<number | undefined>(\n (maximum, subscription) =>\n typeof subscription.seats === \"number\"\n ? Math.max(maximum ?? subscription.seats, subscription.seats)\n : maximum,\n undefined,\n );\n const members = await store.listMembers(organizationId);\n\n if (seatLimit === undefined) {\n return true; // No subscription, no specific limit enforcement here (or maybe allow depending on config)\n }\n\n if (members.length + seatsToAdd > seatLimit) {\n throw new APIError(\"FORBIDDEN\", {\n message: `Organization member limit reached. Used: ${members.length}, Max: ${seatLimit}`,\n });\n }\n\n return true;\n};\n\nexport async function getOrganizationEntitlements(\n ctx: GenericEndpointContext,\n organizationId: string,\n options: AnyPaystackOptions,\n): Promise<{ limits: Record<string, number>; features: string[] }> {\n const subscriptions = (\n await createBillingStore(ctx).findSubscriptionsByReference(organizationId)\n ).filter(\n (subscription) => subscription.status === \"active\" || subscription.status === \"trialing\",\n );\n const limits: Record<string, number> = {};\n const features = new Set<string>();\n for (const subscription of subscriptions) {\n const plan = await getPlanByName(options, subscription.plan);\n for (const [name, value] of Object.entries(plan?.limits ?? {})) {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n limits[name] = Math.max(limits[name] ?? value, value);\n }\n }\n for (const feature of plan?.features ?? []) features.add(feature);\n }\n return { limits, features: [...features] };\n}\n\nexport const checkTeamLimit = async (\n ctx: GenericEndpointContext,\n organizationId: string,\n maxTeams: number,\n): Promise<boolean> => {\n const teams = await createBillingStore(ctx).listTeams(organizationId);\n\n if (teams.length >= maxTeams) {\n throw new APIError(\"FORBIDDEN\", {\n message: `Organization team limit reached. Max teams: ${maxTeams}`,\n });\n }\n\n return true;\n};\n","import { Buffer as NodeBuffer } from \"node:buffer\";\nimport { createCipheriv, createDecipheriv, createHash, randomBytes } from \"node:crypto\";\n\nconst ALGORITHM = \"aes-256-gcm\";\nconst VERSION = \"v1\";\nconst IV_LENGTH = 12;\n\nfunction deriveKey(secret: string): Uint8Array {\n if (typeof secret !== \"string\" || secret.trim() === \"\") {\n throw new Error(\"A non-empty credential encryption key is required\");\n }\n return createHash(\"sha256\").update(secret, \"utf8\").digest();\n}\n\nexport function encryptPaystackCredential(value: string, secret: string): string {\n if (value === \"\") throw new Error(\"Cannot encrypt an empty Paystack credential\");\n const iv = randomBytes(IV_LENGTH);\n const cipher = createCipheriv(ALGORITHM, deriveKey(secret), iv);\n const ciphertext = NodeBuffer.concat([cipher.update(value, \"utf8\"), cipher.final()]);\n const authTag = cipher.getAuthTag();\n return [VERSION, iv.toString(\"hex\"), authTag.toString(\"hex\"), ciphertext.toString(\"hex\")].join(\n \":\",\n );\n}\n\nexport function decryptPaystackCredential(encrypted: string, secret: string): string {\n const parts = encrypted.split(\":\");\n if (parts.length !== 4 || parts[0] !== VERSION) {\n throw new Error(\"Invalid Paystack credential ciphertext\");\n }\n const [, ivHex, authTagHex, ciphertextHex] = parts;\n const iv = NodeBuffer.from(ivHex, \"hex\");\n const authTag = NodeBuffer.from(authTagHex, \"hex\");\n const ciphertext = NodeBuffer.from(ciphertextHex, \"hex\");\n if (iv.length !== IV_LENGTH || authTag.length !== 16 || ciphertext.length === 0) {\n throw new Error(\"Invalid Paystack credential ciphertext\");\n }\n const decipher = createDecipheriv(ALGORITHM, deriveKey(secret), iv);\n decipher.setAuthTag(authTag);\n return NodeBuffer.concat([decipher.update(ciphertext), decipher.final()]).toString(\"utf8\");\n}\n\nexport function resolveCredentialEncryptionKey(options: {\n secretKey: string;\n credentialEncryptionKey?: string;\n}): string {\n const key = options.credentialEncryptionKey ?? options.secretKey;\n if (typeof key !== \"string\" || key.trim() === \"\") {\n throw new Error(\"credentialEncryptionKey or secretKey must be a non-empty string\");\n }\n return key;\n}\n","import type { createBillingStoreFromAdapter } from \"./billing-store.ts\";\nimport {\n decryptPaystackCredential,\n encryptPaystackCredential,\n resolveCredentialEncryptionKey,\n} from \"./credential-crypto.ts\";\nimport { PAYSTACK_MODELS } from \"./models.ts\";\nimport type { PaystackOptions } from \"./types.ts\";\n\ntype Adapter = Parameters<typeof createBillingStoreFromAdapter>[0];\n\ninterface StoredPaymentCredential {\n id: string;\n subscriptionId: string;\n authorizationCodeEncrypted?: string | null;\n emailTokenEncrypted?: string | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface PaystackPaymentCredentialValues {\n authorizationCode?: string | null;\n emailToken?: string | null;\n}\n\nexport async function readPaystackPaymentCredentials(\n adapter: Adapter,\n options: PaystackOptions,\n subscriptionId: string,\n): Promise<PaystackPaymentCredentialValues | null> {\n let row: StoredPaymentCredential | null;\n try {\n row = await adapter.findOne<StoredPaymentCredential>({\n model: PAYSTACK_MODELS.paymentCredential,\n where: [{ field: \"subscriptionId\", value: subscriptionId }],\n });\n } catch {\n return null;\n }\n if (!row) return null;\n const key = resolveCredentialEncryptionKey(options);\n const authorizationCodeEncrypted = row.authorizationCodeEncrypted;\n const emailTokenEncrypted = row.emailTokenEncrypted;\n return {\n authorizationCode:\n typeof authorizationCodeEncrypted === \"string\" && authorizationCodeEncrypted !== \"\"\n ? decryptPaystackCredential(authorizationCodeEncrypted, key)\n : undefined,\n emailToken:\n typeof emailTokenEncrypted === \"string\" && emailTokenEncrypted !== \"\"\n ? decryptPaystackCredential(emailTokenEncrypted, key)\n : undefined,\n };\n}\n\nexport async function savePaystackPaymentCredentials(\n adapter: Adapter,\n options: PaystackOptions,\n subscriptionId: string,\n values: PaystackPaymentCredentialValues,\n): Promise<void> {\n const authorizationCode = values.authorizationCode ?? undefined;\n const emailToken = values.emailToken ?? undefined;\n if (authorizationCode === undefined && emailToken === undefined) return;\n const key = resolveCredentialEncryptionKey(options);\n const now = new Date();\n let existing: StoredPaymentCredential | null = null;\n try {\n existing = await adapter.findOne<StoredPaymentCredential>({\n model: PAYSTACK_MODELS.paymentCredential,\n where: [{ field: \"subscriptionId\", value: subscriptionId }],\n });\n } catch {\n // Some adapters create provider tables lazily on first write.\n }\n const update = {\n ...(authorizationCode !== undefined\n ? { authorizationCodeEncrypted: encryptPaystackCredential(authorizationCode, key) }\n : {}),\n ...(emailToken !== undefined\n ? { emailTokenEncrypted: encryptPaystackCredential(emailToken, key) }\n : {}),\n updatedAt: now,\n };\n if (existing !== null) {\n await adapter.update({\n model: PAYSTACK_MODELS.paymentCredential,\n update,\n where: [{ field: \"id\", value: existing.id }],\n });\n return;\n }\n await adapter.create({\n model: PAYSTACK_MODELS.paymentCredential,\n data: {\n subscriptionId,\n ...update,\n createdAt: now,\n },\n });\n}\n\nexport async function findStoredPaystackPaymentCredential(\n adapter: Adapter,\n subscriptionId: string,\n): Promise<StoredPaymentCredential | null> {\n try {\n return (\n (await adapter.findOne<StoredPaymentCredential>({\n model: PAYSTACK_MODELS.paymentCredential,\n where: [{ field: \"subscriptionId\", value: subscriptionId }],\n })) ?? null\n );\n } catch {\n return null;\n }\n}\n","import type { GenericEndpointContext } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\n\nimport type { AnyPaystackOptions, Session, User } from \"./types.ts\";\n\nexport type BillingReferenceAction =\n | \"initialize-transaction\"\n | \"verify-transaction\"\n | \"list-subscriptions\"\n | \"list-transactions\"\n | \"disable-subscription\"\n | \"enable-subscription\"\n | \"get-subscription-manage-link\";\n\nconst DEFAULT_BILLING_ORG_ROLES = [\"owner\", \"admin\"] as const;\n\nfunction normalizeBillingRoles(roles: readonly string[]): Set<string> {\n return new Set(roles.map((value) => value.trim()).filter((value) => value !== \"\"));\n}\n\nexport function getBillingRoles(options: AnyPaystackOptions): readonly string[] {\n return options.organization?.billingRoles ?? DEFAULT_BILLING_ORG_ROLES;\n}\n\nexport function hasBillingRole(\n role: unknown,\n billingRoles: readonly string[] = DEFAULT_BILLING_ORG_ROLES,\n): boolean {\n const allowedRoles = normalizeBillingRoles(billingRoles);\n if (Array.isArray(role)) {\n return role.some((value) => hasBillingRole(value, billingRoles));\n }\n if (typeof role !== \"string\") {\n return false;\n }\n return role\n .split(\",\")\n .map((value) => value.trim())\n .some((value) => allowedRoles.has(value));\n}\n\nexport function resolveBillingReferenceId(input: {\n body?: unknown;\n query?: unknown;\n requestUrl?: string;\n fallbackUserId: string;\n}): string {\n const body = (input.body ?? {}) as Record<string, unknown>;\n const query = (input.query ?? {}) as Record<string, unknown>;\n const requestQueryReferenceId =\n typeof input.requestUrl === \"string\"\n ? (new URL(input.requestUrl).searchParams.get(\"referenceId\") ?? undefined)\n : undefined;\n\n return (\n (body.referenceId as string | undefined) ??\n (query.referenceId as string | undefined) ??\n requestQueryReferenceId ??\n input.fallbackUserId\n );\n}\n\nexport async function authorizeBillingReference(\n ctx: GenericEndpointContext,\n options: AnyPaystackOptions,\n data: {\n user: User;\n session: Session;\n referenceId: string;\n action: BillingReferenceAction;\n },\n): Promise<void> {\n if (data.referenceId === data.user.id) return;\n\n if (\n options.subscription?.enabled === true &&\n typeof options.subscription.authorizeReference === \"function\"\n ) {\n const authorized = await options.subscription.authorizeReference(\n {\n user: data.user,\n session: data.session,\n referenceId: data.referenceId,\n action: data.action,\n },\n ctx,\n );\n if (authorized === true) return;\n throw new APIError(\"UNAUTHORIZED\");\n }\n\n if (options.organization?.enabled === true) {\n const member = await ctx.context.adapter.findOne({\n model: \"member\",\n where: [\n { field: \"userId\", value: data.user.id },\n { field: \"organizationId\", value: data.referenceId },\n ],\n });\n\n if (\n member !== null &&\n member !== undefined &&\n hasBillingRole((member as { role?: unknown }).role, getBillingRoles(options))\n ) {\n return;\n }\n }\n\n throw new APIError(\"UNAUTHORIZED\");\n}\n","import { createHash, randomUUID } from \"node:crypto\";\n\nimport type { GenericEndpointContext } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\nimport * as z from \"zod/v4\";\n\nimport { createBillingStore } from \"./billing-store.ts\";\nimport { PAYSTACK_MODELS } from \"./models.ts\";\nimport type {\n AnyPaystackOptions,\n PaystackPlan,\n PaystackWebhookPayload,\n PaystackWebhookEventRecord,\n Subscription,\n} from \"./types.ts\";\n\nconst progressSchema = z.object({\n version: z.literal(1),\n completed: z.array(z.enum([\"complete\", \"update\", \"trialStart\"])),\n remoteCreationSubmitted: z.boolean().optional(),\n remoteSubscriptionCode: z.string().optional(),\n});\ninterface Claim {\n eventId: string;\n status: string;\n progress: z.infer<typeof progressSchema>;\n}\nconst unavailable = () =>\n new APIError(\"SERVICE_UNAVAILABLE\", {\n message: \"Subscription fulfillment is pending. Retry verification.\",\n });\n\n/** Persist delivery intent before activation, sharing one lease across verification transports. */\nexport async function claimSubscriptionFulfillment(\n ctx: GenericEndpointContext,\n reference: string,\n subscription: Subscription,\n phase = \"subscription-fulfillment\",\n): Promise<Claim | null> {\n const store = createBillingStore(ctx);\n const eventId = `${phase}:${createHash(\"sha256\")\n .update(JSON.stringify([reference, subscription.id]))\n .digest(\"hex\")}`;\n const findRecord = () =>\n ctx.context.adapter.findOne<PaystackWebhookEventRecord>({\n model: PAYSTACK_MODELS.webhookEvent,\n where: [{ field: \"eventId\", value: eventId }],\n });\n let record = await findRecord();\n if (record === null) {\n // Existing entitlements predate this delivery journal; do not replay historical callbacks.\n if (subscription.status !== \"incomplete\") return null;\n try {\n record = await store.createWebhookEvent({\n eventId,\n eventType: \"subscription.fulfillment\",\n reference,\n status: \"pending\",\n payload: JSON.stringify({ version: 1, completed: [] }),\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n } catch (error) {\n record = await findRecord();\n if (record === null) throw error;\n }\n }\n if (record.status === \"processed\") return null;\n if (\n record.status.startsWith(\"processing:\") &&\n Date.now() - new Date(record.updatedAt).getTime() < 300_000\n )\n throw unavailable();\n const progress = progressSchema.parse(JSON.parse(record.payload));\n const status = `processing:${randomUUID()}`;\n const claimed = await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.webhookEvent,\n where: [\n { field: \"eventId\", value: eventId },\n { field: \"status\", value: record.status },\n { field: \"updatedAt\", value: record.updatedAt },\n ],\n update: { status, updatedAt: new Date() },\n });\n if (claimed === null) throw unavailable();\n return { eventId, status, progress };\n}\n\nexport async function deliverTrialStart(\n ctx: GenericEndpointContext,\n claim: Claim,\n subscription: Subscription,\n plan: PaystackPlan | undefined,\n): Promise<void> {\n if (!claim.progress.completed.includes(\"trialStart\")) {\n await checkpoint(ctx, claim);\n await plan?.freeTrial?.onTrialStart?.(subscription);\n claim.progress.completed.push(\"trialStart\");\n await checkpoint(ctx, claim);\n }\n await checkpoint(ctx, claim, true);\n}\n\nexport async function reserveRemoteTrialSubscription(\n ctx: GenericEndpointContext,\n claim: Claim,\n create: () => Promise<string | undefined>,\n): Promise<string> {\n if (claim.progress.remoteSubscriptionCode !== undefined)\n return claim.progress.remoteSubscriptionCode;\n if (claim.progress.remoteCreationSubmitted === true)\n throw new APIError(\"SERVICE_UNAVAILABLE\", {\n message:\n \"Remote trial subscription creation is unresolved. Reconcile the existing provider subscription before retrying.\",\n });\n claim.progress.remoteCreationSubmitted = true;\n await checkpoint(ctx, claim);\n const code = await create();\n if (code === undefined || code === \"\") throw unavailable();\n claim.progress.remoteSubscriptionCode = code;\n await checkpoint(ctx, claim);\n return code;\n}\n\nasync function checkpoint(\n ctx: GenericEndpointContext,\n claim: Claim,\n processed = false,\n): Promise<void> {\n const updated = await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.webhookEvent,\n where: [\n { field: \"eventId\", value: claim.eventId },\n { field: \"status\", value: claim.status },\n ],\n update: {\n payload: JSON.stringify(claim.progress),\n updatedAt: new Date(),\n ...(processed ? { status: \"processed\", processedAt: new Date() } : {}),\n },\n });\n if (updated === null) throw unavailable();\n}\n\nexport async function deliverSubscriptionFulfillment(\n ctx: GenericEndpointContext,\n options: AnyPaystackOptions,\n claim: Claim,\n subscription: Subscription,\n plan: PaystackPlan | undefined,\n event: PaystackWebhookPayload,\n): Promise<void> {\n if (plan !== undefined) {\n const callbacks = {\n complete: options.subscription?.onSubscriptionComplete,\n update: options.subscription?.onSubscriptionUpdate,\n };\n for (const name of [\"complete\", \"update\"] as const) {\n if (claim.progress.completed.includes(name)) continue;\n // Refresh ownership before invoking application code. Hooks must still be idempotent:\n // a process can stop after its side effect and before this journal checkpoint.\n await checkpoint(ctx, claim);\n await callbacks[name]?.({ event, subscription, plan }, ctx);\n claim.progress.completed.push(name);\n await checkpoint(ctx, claim);\n }\n }\n await checkpoint(ctx, claim, true);\n}\n\nexport async function releaseSubscriptionFulfillment(\n ctx: GenericEndpointContext,\n claim: Claim,\n): Promise<void> {\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.webhookEvent,\n where: [\n { field: \"eventId\", value: claim.eventId },\n { field: \"status\", value: claim.status },\n ],\n update: { status: \"pending\", updatedAt: new Date() },\n });\n}\n","import type { components } from \"@alexasomba/paystack-node\";\nimport type { GenericEndpointContext } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\n\nimport { createBillingStore } from \"./billing-store.ts\";\nimport {\n getMetadataBoolean,\n getMetadataNumber,\n getMetadataString,\n parsePaystackMetadata,\n} from \"./metadata.ts\";\nimport { PAYSTACK_MODELS } from \"./models.ts\";\nimport { savePaystackPaymentCredentials } from \"./payment-credentials.ts\";\nimport { getPaystackOps, unwrapSdkResult } from \"./paystack-sdk.ts\";\nimport { authorizeBillingReference } from \"./reference-access.ts\";\nimport {\n claimSubscriptionFulfillment,\n deliverSubscriptionFulfillment,\n releaseSubscriptionFulfillment,\n reserveRemoteTrialSubscription,\n} from \"./subscription-fulfillment.ts\";\nimport type {\n AnyPaystackOptions,\n PaystackCheckoutChannel,\n PaystackTransaction,\n PaystackTransactionResponse,\n PaystackWebhookPayload,\n Session,\n Subscription,\n User,\n} from \"./types.ts\";\nimport { getPlans, syncProductQuantityFromPaystack } from \"./utils.ts\";\n\nexport type PaystackReconciliationSource = \"webhook\" | \"queue\" | \"admin\" | \"server\" | \"browser\";\n\nexport interface ReconcilePaystackTransactionInput {\n reference: string;\n source?: PaystackReconciliationSource;\n referenceId?: string;\n actor?: {\n user: User;\n session: Session;\n };\n throwOnError?: boolean;\n}\n\nexport interface PaystackReconciliationError {\n code: string;\n message: string;\n status?: number;\n}\n\nexport interface PaystackReconciliationSummary {\n transaction: {\n found: boolean;\n updated: boolean;\n referenceId?: string;\n previousStatus?: string;\n status?: string;\n };\n subscription: {\n found: boolean;\n updated: boolean;\n id?: string;\n status?: string;\n prorationApplied: boolean;\n };\n customer: {\n saved: boolean;\n referenceId?: string;\n customerCode?: string;\n model?: \"user\" | \"organization\";\n };\n product: {\n synced: boolean;\n name?: string;\n };\n}\n\nexport interface ReconcilePaystackTransactionSuccess extends PaystackReconciliationSummary {\n ok: true;\n source: PaystackReconciliationSource;\n status: string;\n reference: string;\n data: PaystackTransactionResponse;\n error?: undefined;\n}\n\nexport interface ReconcilePaystackTransactionFailure extends PaystackReconciliationSummary {\n ok: false;\n source: PaystackReconciliationSource;\n status: string;\n reference: string;\n data: PaystackTransactionResponse | null;\n error: PaystackReconciliationError;\n}\n\nexport type ReconcilePaystackTransactionResult =\n | ReconcilePaystackTransactionSuccess\n | ReconcilePaystackTransactionFailure;\n\nfunction getAllowedSubscriptionChannels(\n options: AnyPaystackOptions,\n): PaystackCheckoutChannel[] | undefined {\n const channels = options.subscription?.allowedPaymentChannels;\n return Array.isArray(channels) && channels.length > 0 ? channels : undefined;\n}\n\nfunction isAllowedSubscriptionChannel(\n channel: string | null | undefined,\n allowedChannels: readonly PaystackCheckoutChannel[] | undefined,\n): boolean {\n if (allowedChannels === undefined) return true;\n return channel !== undefined && channel !== null && allowedChannels.includes(channel as never);\n}\n\nfunction createSummary(): PaystackReconciliationSummary {\n return {\n transaction: {\n found: false,\n updated: false,\n },\n subscription: {\n found: false,\n updated: false,\n prorationApplied: false,\n },\n customer: {\n saved: false,\n },\n product: {\n synced: false,\n },\n };\n}\n\nfunction getErrorMessage(error: unknown, fallback: string): string {\n return error instanceof Error && error.message !== \"\" ? error.message : fallback;\n}\n\nfunction createFailureResult(input: {\n source: PaystackReconciliationSource;\n status: string;\n reference: string;\n data: PaystackTransactionResponse | null;\n summary: PaystackReconciliationSummary;\n error: PaystackReconciliationError;\n}): ReconcilePaystackTransactionFailure {\n return {\n ok: false,\n source: input.source,\n status: input.status,\n reference: input.reference,\n data: input.data,\n error: input.error,\n ...input.summary,\n };\n}\n\nfunction throwOrReturnFailure(\n input: {\n throwOnError: boolean;\n apiStatus: \"BAD_REQUEST\" | \"UNAUTHORIZED\";\n } & Parameters<typeof createFailureResult>[0],\n): ReconcilePaystackTransactionFailure {\n if (input.throwOnError) {\n throw new APIError(input.apiStatus, {\n code: input.error.code,\n message: input.error.message,\n status: input.error.status,\n });\n }\n\n return createFailureResult(input);\n}\n\nfunction hasReferenceMismatch(input: {\n expectedReferenceId?: string;\n transactionReferenceId?: string | null;\n}): boolean {\n return (\n input.expectedReferenceId !== undefined &&\n input.expectedReferenceId !== \"\" &&\n input.transactionReferenceId !== undefined &&\n input.transactionReferenceId !== null &&\n input.transactionReferenceId !== \"\" &&\n input.expectedReferenceId !== input.transactionReferenceId\n );\n}\n\nfunction getNonEmptyString(value: unknown): string | undefined {\n return typeof value === \"string\" && value !== \"\" ? value : undefined;\n}\n\nexport async function reconcilePaystackTransaction(\n ctx: GenericEndpointContext,\n options: AnyPaystackOptions,\n input: ReconcilePaystackTransactionInput,\n): Promise<ReconcilePaystackTransactionResult> {\n const source = input.source ?? \"server\";\n const throwOnError = input.throwOnError === true;\n const summary = createSummary();\n const paystack = getPaystackOps(options.paystackClient);\n let data: PaystackTransactionResponse | undefined;\n\n try {\n const verifyRaw = await paystack?.transaction?.verify(input.reference);\n data = unwrapSdkResult<PaystackTransactionResponse>(verifyRaw);\n } catch (error: unknown) {\n ctx.context.logger.error(\"Failed to verify Paystack transaction\", error);\n return throwOrReturnFailure({\n throwOnError,\n apiStatus: \"BAD_REQUEST\",\n source,\n status: \"error\",\n reference: input.reference,\n data: null,\n summary,\n error: {\n code: \"FAILED_TO_VERIFY_TRANSACTION\",\n message: getErrorMessage(error, \"Failed to verify transaction\"),\n status: 400,\n },\n });\n }\n\n if (data === undefined || data === null) {\n return throwOrReturnFailure({\n throwOnError,\n apiStatus: \"BAD_REQUEST\",\n source,\n status: \"error\",\n reference: input.reference,\n data: null,\n summary,\n error: {\n code: \"FAILED_TO_VERIFY_TRANSACTION\",\n message: \"Failed to fetch transaction data from Paystack.\",\n status: 400,\n },\n });\n }\n\n const status = data.status ?? \"failed\";\n const reference = input.reference;\n const paystackIdRaw = (data as { id?: number | string | null }).id;\n const paystackId =\n paystackIdRaw !== undefined && paystackIdRaw !== null ? String(paystackIdRaw) : undefined;\n const authorizationCode = (data.authorization as { authorization_code?: string | null } | null)\n ?.authorization_code;\n const store = createBillingStore(ctx);\n const txRecord = await store.findTransactionByReference(reference);\n summary.transaction.found = txRecord !== null;\n summary.transaction.previousStatus = txRecord?.status;\n\n if (\n hasReferenceMismatch({\n expectedReferenceId: input.referenceId,\n transactionReferenceId: txRecord?.referenceId,\n })\n ) {\n return throwOrReturnFailure({\n throwOnError,\n apiStatus: \"UNAUTHORIZED\",\n source,\n status,\n reference,\n data,\n summary,\n error: {\n code: \"REFERENCE_ID_MISMATCH\",\n message: \"Transaction reference does not belong to the expected billing reference.\",\n status: 401,\n },\n });\n }\n\n const referenceId =\n input.referenceId ??\n getNonEmptyString(txRecord?.referenceId) ??\n getNonEmptyString(input.actor?.user.id);\n summary.transaction.referenceId = referenceId;\n\n if (\n input.actor !== undefined &&\n referenceId !== undefined &&\n referenceId !== input.actor.user.id\n ) {\n try {\n await authorizeBillingReference(ctx, options, {\n user: input.actor.user,\n session: input.actor.session,\n referenceId,\n action: \"verify-transaction\",\n });\n } catch (error: unknown) {\n return throwOrReturnFailure({\n throwOnError,\n apiStatus: \"UNAUTHORIZED\",\n source,\n status,\n reference,\n data,\n summary,\n error: {\n code: \"UNAUTHORIZED\",\n message: getErrorMessage(error, \"Not authorized to reconcile this transaction.\"),\n status: 401,\n },\n });\n }\n }\n\n if (\n data.reference !== reference ||\n (txRecord !== null && typeof txRecord.amount === \"number\" && txRecord.amount !== data.amount) ||\n (txRecord !== null &&\n typeof txRecord.currency === \"string\" &&\n txRecord.currency !== data.currency)\n ) {\n return throwOrReturnFailure({\n throwOnError,\n apiStatus: \"BAD_REQUEST\",\n source,\n status,\n reference,\n data,\n summary,\n error: {\n code: \"PAYMENT_INTENT_MISMATCH\",\n message: \"Verified payment does not match the stored reference, amount, and currency.\",\n status: 400,\n },\n });\n }\n\n const transactionUpdate: Partial<PaystackTransaction> & Record<string, unknown> = {\n status,\n paystackId,\n amount: data.amount,\n currency: data.currency,\n updatedAt: new Date(),\n };\n const updatedTransaction = await store.updateTransactionByReference(reference, transactionUpdate);\n summary.transaction.updated = updatedTransaction !== null;\n summary.transaction.status = status;\n\n if (status !== \"success\") {\n return {\n ok: true,\n source,\n status,\n reference,\n data,\n ...summary,\n };\n }\n\n const allowedSubscriptionChannels = getAllowedSubscriptionChannels(options);\n const isSubscriptionFlow =\n (txRecord?.plan !== undefined && txRecord.plan !== null && txRecord.plan !== \"\") ||\n Boolean((data as { plan?: unknown }).plan);\n\n if (\n isSubscriptionFlow &&\n isAllowedSubscriptionChannel(data.channel ?? undefined, allowedSubscriptionChannels) === false\n ) {\n await store.updateTransactionByReference(reference, {\n ...transactionUpdate,\n status: \"failed\",\n });\n summary.transaction.updated = true;\n summary.transaction.status = \"failed\";\n\n return throwOrReturnFailure({\n throwOnError,\n apiStatus: \"BAD_REQUEST\",\n source,\n status: \"failed\",\n reference,\n data,\n summary,\n error: {\n code: \"SUBSCRIPTION_PAYMENT_CHANNEL_NOT_ALLOWED\",\n message: `This subscription requires one of: ${allowedSubscriptionChannels?.join(\", \") ?? \"allowed channels\"}.`,\n status: 400,\n },\n });\n }\n\n const paystackCustomerCodeFromPaystack = data.customer?.customer_code;\n if (\n paystackCustomerCodeFromPaystack !== undefined &&\n paystackCustomerCodeFromPaystack !== null &&\n paystackCustomerCodeFromPaystack !== \"\" &&\n referenceId !== undefined &&\n referenceId !== \"\"\n ) {\n let isOrganization =\n options.organization?.enabled === true &&\n typeof referenceId === \"string\" &&\n referenceId.startsWith(\"org_\");\n if (isOrganization === false && options.organization?.enabled === true) {\n const organization = await store.findOrganization(referenceId);\n isOrganization = organization !== null;\n }\n\n await store.saveCustomerCode(\n referenceId,\n paystackCustomerCodeFromPaystack,\n isOrganization,\n data.customer?.email,\n );\n summary.customer.saved = true;\n summary.customer.referenceId = referenceId;\n summary.customer.customerCode = paystackCustomerCodeFromPaystack;\n summary.customer.model = isOrganization ? \"organization\" : \"user\";\n }\n\n const transaction = updatedTransaction ?? (await store.findTransactionByReference(reference));\n if (\n transaction !== undefined &&\n transaction !== null &&\n transaction.product !== undefined &&\n transaction.product !== null &&\n transaction.product !== \"\" &&\n options.paystackClient !== undefined &&\n options.paystackClient !== null\n ) {\n await syncProductQuantityFromPaystack(ctx, transaction.product, options.paystackClient);\n summary.product.synced = true;\n summary.product.name = transaction.product;\n }\n\n if (options.subscription?.enabled !== true) {\n return {\n ok: true,\n source,\n status,\n reference,\n data,\n ...summary,\n };\n }\n\n const metadataObj = parsePaystackMetadata(data.metadata);\n const isTrial = getMetadataBoolean(metadataObj, \"isTrial\");\n const trialEnd = getMetadataString(metadataObj, \"trialEnd\");\n const targetPlan = getMetadataString(metadataObj, \"plan\");\n\n if (metadataObj.type === \"proration\") {\n const subscriptionId = getMetadataString(metadataObj, \"subscriptionId\");\n const newPlan = getMetadataString(metadataObj, \"newPlan\");\n const newSeatCount = getMetadataNumber(metadataObj, \"newSeatCount\");\n\n if (\n subscriptionId !== undefined &&\n subscriptionId !== \"\" &&\n newPlan !== undefined &&\n newPlan !== \"\"\n ) {\n const originalSubscription = await store.findSubscriptionById(subscriptionId);\n if (\n !originalSubscription ||\n originalSubscription.status === \"canceled\" ||\n originalSubscription.transactionReference === reference\n )\n return { ok: true, source, status, reference, data, ...summary };\n const updatedSubscription = await store.updateSubscription(subscriptionId, {\n plan: newPlan,\n ...(typeof newSeatCount === \"number\" ? { seats: newSeatCount } : {}),\n transactionReference: reference,\n updatedAt: new Date(),\n });\n summary.subscription.found = updatedSubscription !== null;\n summary.subscription.updated = updatedSubscription !== null;\n summary.subscription.id = updatedSubscription?.id ?? subscriptionId;\n summary.subscription.status = updatedSubscription?.status;\n summary.subscription.prorationApplied = updatedSubscription !== null;\n if (\n updatedSubscription !== null &&\n authorizationCode !== undefined &&\n authorizationCode !== null &&\n authorizationCode !== \"\"\n ) {\n await savePaystackPaymentCredentials(ctx.context.adapter, options, updatedSubscription.id, {\n authorizationCode,\n });\n }\n }\n\n return {\n ok: true,\n source,\n status,\n reference,\n data,\n ...summary,\n };\n }\n\n let subscriptionCode: string | undefined;\n const existingSubs = await store.findSubscriptionsByTransactionReference(reference);\n const targetSub = existingSubs.find(\n (subscription) =>\n referenceId === undefined || referenceId === \"\" || subscription.referenceId === referenceId,\n );\n summary.subscription.found = targetSub !== undefined;\n summary.subscription.id = targetSub?.id;\n summary.subscription.status = targetSub?.status;\n\n // Terminal entitlements are never reactivated by a payment replay.\n if (!targetSub || ![\"incomplete\", \"active\", \"trialing\"].includes(targetSub.status)) {\n return { ok: true, source, status, reference, data, ...summary };\n }\n const claim = await claimSubscriptionFulfillment(ctx, reference, targetSub);\n if (claim === null) return { ok: true, source, status, reference, data, ...summary };\n try {\n if (targetSub.status !== \"incomplete\") {\n if (\n authorizationCode !== undefined &&\n authorizationCode !== null &&\n authorizationCode !== \"\"\n ) {\n await savePaystackPaymentCredentials(ctx.context.adapter, options, targetSub.id, {\n authorizationCode,\n });\n }\n await store.retireCompetingSubscriptions(\n targetSub.referenceId,\n targetSub.groupId ?? null,\n targetSub.id,\n );\n const plans = await getPlans(options.subscription);\n const plan = plans.find(\n (candidate) => candidate.name.toLowerCase() === targetSub.plan.toLowerCase(),\n );\n await deliverSubscriptionFulfillment(\n ctx,\n options,\n claim,\n targetSub,\n plan,\n data as unknown as PaystackWebhookPayload,\n );\n return { ok: true, source, status, reference, data, ...summary };\n }\n\n if (isTrial && targetPlan !== undefined && trialEnd !== undefined) {\n const email = data.customer?.email;\n const plans = await getPlans(options.subscription);\n const planConfig = plans.find((plan) => plan.name.toLowerCase() === targetPlan.toLowerCase());\n\n if (\n planConfig !== undefined &&\n planConfig !== null &&\n (planConfig.planCode === undefined ||\n planConfig.planCode === null ||\n planConfig.planCode === \"\")\n ) {\n subscriptionCode = `LOC_${reference}`;\n } else if (\n targetSub?.subscriptionCode !== undefined &&\n targetSub.subscriptionCode !== null &&\n targetSub.subscriptionCode !== \"\"\n ) {\n subscriptionCode = targetSub.subscriptionCode;\n } else if (\n authorizationCode !== undefined &&\n authorizationCode !== null &&\n email !== undefined &&\n email !== null &&\n email !== \"\" &&\n planConfig?.planCode !== undefined &&\n planConfig.planCode !== null &&\n planConfig.planCode !== \"\"\n ) {\n const planCode = planConfig.planCode;\n subscriptionCode = await reserveRemoteTrialSubscription(ctx, claim, async () => {\n const subResRaw = await paystack?.subscription?.create({\n body: {\n customer: email,\n plan: planCode,\n authorization: authorizationCode,\n start_date: trialEnd,\n },\n });\n const subRes =\n unwrapSdkResult<components[\"schemas\"][\"SubscriptionListResponseArray\"]>(subResRaw);\n return subRes?.subscription_code;\n });\n }\n } else if (isTrial === false) {\n const planCodeFromPaystack = (data as { plan?: { plan_code?: string | null } }).plan\n ?.plan_code;\n if (\n planCodeFromPaystack === undefined ||\n planCodeFromPaystack === null ||\n planCodeFromPaystack === \"\"\n ) {\n subscriptionCode = `LOC_${reference}`;\n } else {\n subscriptionCode =\n (data as { subscription?: { subscription_code?: string | null } }).subscription\n ?.subscription_code ?? undefined;\n }\n }\n\n let updatedSubscription: Subscription | null = null;\n if (targetSub !== undefined && targetSub !== null) {\n const plans = await getPlans(options.subscription);\n const resolvedPlan = plans.find(\n (candidate) => candidate.name.toLowerCase() === targetSub.plan.toLowerCase(),\n );\n updatedSubscription = await ctx.context.adapter.update<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n where: [\n { field: \"id\", value: targetSub.id },\n { field: \"status\", value: \"incomplete\" },\n { field: \"transactionReference\", value: reference },\n ],\n update: {\n status: isTrial ? \"trialing\" : \"active\",\n billingInterval: resolvedPlan?.interval ?? targetSub.billingInterval ?? null,\n periodStart: new Date(),\n updatedAt: new Date(),\n ...(isTrial && trialEnd !== undefined\n ? {\n trialStart: new Date(),\n trialEnd: new Date(trialEnd),\n periodEnd: new Date(trialEnd),\n }\n : {}),\n ...(subscriptionCode !== undefined ? { subscriptionCode } : {}),\n },\n });\n summary.subscription.updated = updatedSubscription !== null;\n summary.subscription.id = updatedSubscription?.id ?? targetSub.id;\n summary.subscription.status = updatedSubscription?.status ?? targetSub.status;\n if (\n authorizationCode !== undefined &&\n authorizationCode !== null &&\n authorizationCode !== \"\" &&\n updatedSubscription !== null\n ) {\n await savePaystackPaymentCredentials(ctx.context.adapter, options, updatedSubscription.id, {\n authorizationCode,\n });\n }\n if (\n updatedSubscription !== null &&\n (updatedSubscription.status === \"active\" || updatedSubscription.status === \"trialing\")\n ) {\n await store.retireCompetingSubscriptions(\n updatedSubscription.referenceId,\n updatedSubscription.groupId ?? null,\n updatedSubscription.id,\n );\n }\n }\n\n if (updatedSubscription !== undefined && updatedSubscription !== null) {\n const plans = await getPlans(options.subscription);\n const plan = plans.find(\n (candidate) => candidate.name.toLowerCase() === updatedSubscription.plan.toLowerCase(),\n );\n await deliverSubscriptionFulfillment(\n ctx,\n options,\n claim,\n updatedSubscription,\n plan,\n data as unknown as PaystackWebhookPayload,\n );\n } else {\n throw new APIError(\"SERVICE_UNAVAILABLE\", {\n message: \"Subscription activation is pending. Retry verification.\",\n });\n }\n\n return {\n ok: true,\n source,\n status,\n reference,\n data,\n ...summary,\n };\n } catch (error) {\n await releaseSubscriptionFulfillment(ctx, claim);\n throw error;\n }\n}\n","import { APIError, createAuthMiddleware, type AuthMiddleware } from \"better-auth/api\";\n\nimport {\n authorizeBillingReference,\n type BillingReferenceAction,\n resolveBillingReferenceId,\n} from \"./reference-access.ts\";\nimport type { PaystackOptions } from \"./types.ts\";\n\nexport { hasBillingRole } from \"./reference-access.ts\";\n\nexport const referenceMiddleware = (\n options: PaystackOptions,\n action: BillingReferenceAction,\n): AuthMiddleware =>\n createAuthMiddleware(async (ctx) => {\n const session = ctx.context.session;\n\n if (session === null || session === undefined) {\n throw new APIError(\"UNAUTHORIZED\");\n }\n const referenceId = resolveBillingReferenceId({\n body: ctx.body,\n query: ctx.query,\n requestUrl: ctx.request?.url,\n fallbackUserId: session.user.id,\n });\n\n await authorizeBillingReference(ctx, options, {\n user: session.user,\n session: session.session,\n referenceId,\n action,\n });\n\n return {\n context: {\n ...ctx.context,\n referenceId,\n },\n };\n });\n","/** Accept only absolute HTTP(S) URLs or root-relative paths on the Better Auth origin. */\nfunction hasControlCharacters(value: string): boolean {\n for (const character of value) {\n const codePoint = character.codePointAt(0);\n if (\n codePoint !== undefined &&\n (codePoint <= 0x1f || (codePoint >= 0x7f && codePoint <= 0x9f))\n ) {\n return true;\n }\n }\n return false;\n}\n\nexport function isTrustedCallbackURL(callbackURL: string, baseURL: string): boolean {\n if (\n callbackURL.startsWith(\"//\") ||\n callbackURL.includes(\"\\\\\") ||\n hasControlCharacters(callbackURL)\n ) {\n return false;\n }\n try {\n const base = new URL(baseURL);\n const isAbsoluteHttpURL = /^https?:\\/\\//i.test(callbackURL);\n if (!isAbsoluteHttpURL && !callbackURL.startsWith(\"/\")) return false;\n const callback = new URL(callbackURL, base);\n return (\n (callback.protocol === \"http:\" || callback.protocol === \"https:\") &&\n callback.origin === base.origin &&\n callback.username === \"\" &&\n callback.password === \"\"\n );\n } catch {\n return false;\n }\n}\n","import type { GenericEndpointContext } from \"better-auth\";\n\nimport { createBillingStore } from \"../billing-store.ts\";\nimport type { AnyPaystackOptions, PaystackPlan, PaystackProduct } from \"../types.ts\";\nimport { getPlans, getProducts } from \"../utils.ts\";\n\nexport async function listStoredProducts(ctx: GenericEndpointContext): Promise<PaystackProduct[]> {\n return createBillingStore(ctx).listProducts();\n}\n\nexport async function listStoredPlans(ctx: GenericEndpointContext): Promise<PaystackPlan[]> {\n return createBillingStore(ctx).listPlans();\n}\n\nexport async function getConfiguredCatalog(options: AnyPaystackOptions): Promise<{\n plans: PaystackPlan[];\n products: PaystackProduct[];\n}> {\n const plans = options.subscription?.enabled === true ? await getPlans(options.subscription) : [];\n const products = await getProducts(options.products);\n return { plans, products };\n}\n","/* oxlint-disable no-restricted-imports */\nimport { z } from \"zod\";\n\nexport const initializeTransactionBodySchema: z.ZodObject<{\n plan: z.ZodOptional<z.ZodString>;\n product: z.ZodOptional<z.ZodString>;\n amount: z.ZodOptional<z.ZodNumber>;\n currency: z.ZodOptional<z.ZodString>;\n email: z.ZodOptional<z.ZodString>;\n metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;\n referenceId: z.ZodOptional<z.ZodString>;\n subscriptionId: z.ZodOptional<z.ZodString>;\n callbackURL: z.ZodOptional<z.ZodString>;\n quantity: z.ZodOptional<z.ZodNumber>;\n scheduleAtPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n cancelAtPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n prorateAndCharge: z.ZodOptional<z.ZodBoolean>;\n confirmTrialTokenizationCharge: z.ZodOptional<z.ZodBoolean>;\n}> = z.object({\n plan: z.string().optional(),\n product: z.string().optional(),\n amount: z.number().int().positive().optional(),\n currency: z.string().optional(),\n email: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n referenceId: z.string().optional(),\n subscriptionId: z.string().optional(),\n callbackURL: z.string().optional(),\n quantity: z.number().int().positive().optional(),\n scheduleAtPeriodEnd: z.boolean().optional(),\n cancelAtPeriodEnd: z.boolean().optional(),\n prorateAndCharge: z.boolean().optional(),\n confirmTrialTokenizationCharge: z.boolean().optional(),\n});\n","import { defineErrorCodes } from \"better-auth\";\nimport type { RawError } from \"better-auth\";\n\nimport type { AnyPaystackOptions, PaystackCheckoutChannel } from \"../types.ts\";\n\nexport const PAYSTACK_ERROR_CODES: {\n SUBSCRIPTION_NOT_FOUND: RawError<\"SUBSCRIPTION_NOT_FOUND\">;\n SUBSCRIPTION_PLAN_NOT_FOUND: RawError<\"SUBSCRIPTION_PLAN_NOT_FOUND\">;\n UNABLE_TO_CREATE_CUSTOMER: RawError<\"UNABLE_TO_CREATE_CUSTOMER\">;\n FAILED_TO_INITIALIZE_TRANSACTION: RawError<\"FAILED_TO_INITIALIZE_TRANSACTION\">;\n FAILED_TO_VERIFY_TRANSACTION: RawError<\"FAILED_TO_VERIFY_TRANSACTION\">;\n FAILED_TO_DISABLE_SUBSCRIPTION: RawError<\"FAILED_TO_DISABLE_SUBSCRIPTION\">;\n FAILED_TO_ENABLE_SUBSCRIPTION: RawError<\"FAILED_TO_ENABLE_SUBSCRIPTION\">;\n EMAIL_VERIFICATION_REQUIRED: RawError<\"EMAIL_VERIFICATION_REQUIRED\">;\n SUBSCRIPTION_PAYMENT_CHANNEL_NOT_ALLOWED: RawError<\"SUBSCRIPTION_PAYMENT_CHANNEL_NOT_ALLOWED\">;\n} = defineErrorCodes({\n SUBSCRIPTION_NOT_FOUND: \"Subscription not found\",\n SUBSCRIPTION_PLAN_NOT_FOUND: \"Subscription plan not found\",\n UNABLE_TO_CREATE_CUSTOMER: \"Unable to create customer\",\n FAILED_TO_INITIALIZE_TRANSACTION: \"Failed to initialize transaction\",\n FAILED_TO_VERIFY_TRANSACTION: \"Failed to verify transaction\",\n FAILED_TO_DISABLE_SUBSCRIPTION: \"Failed to disable subscription\",\n FAILED_TO_ENABLE_SUBSCRIPTION: \"Failed to enable subscription\",\n EMAIL_VERIFICATION_REQUIRED: \"Email verification is required before you can subscribe to a plan\",\n SUBSCRIPTION_PAYMENT_CHANNEL_NOT_ALLOWED:\n \"This subscription only supports specific payment channels\",\n});\n\nexport function getAllowedSubscriptionChannels(\n options: AnyPaystackOptions,\n): PaystackCheckoutChannel[] | undefined {\n const channels = options.subscription?.allowedPaymentChannels;\n return Array.isArray(channels) && channels.length > 0 ? channels : undefined;\n}\n\nexport async function hmacSha512Hex(secret: string, message: string): Promise<string> {\n const encoder = new TextEncoder();\n const keyData = encoder.encode(secret);\n const msgData = encoder.encode(message);\n\n const crypto = globalThis.crypto;\n if (crypto !== undefined && crypto !== null && \"subtle\" in crypto) {\n const subtle = crypto.subtle;\n const key = await subtle.importKey(\"raw\", keyData, { name: \"HMAC\", hash: \"SHA-512\" }, false, [\n \"sign\",\n ]);\n const signature = await subtle.sign(\"HMAC\", key, msgData);\n return Array.from(new Uint8Array(signature))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n const { createHmac } = await import(\"node:crypto\");\n return createHmac(\"sha512\", secret).update(message).digest(\"hex\");\n}\n","/* oxlint-disable no-restricted-imports */\nimport { z } from \"zod\";\n\nexport const enableDisableBodySchema: z.ZodObject<{\n referenceId: z.ZodOptional<z.ZodString>;\n subscriptionCode: z.ZodString;\n emailToken: z.ZodOptional<z.ZodString>;\n atPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n}> = z.object({\n referenceId: z.string().optional(),\n subscriptionCode: z.string(),\n emailToken: z.string().optional(),\n atPeriodEnd: z.boolean().optional(),\n});\n\nexport function decodeBase64UrlToString(value: string): string {\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized + \"===\".slice((normalized.length + 3) % 4);\n const binaryString = atob(padded);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n return new TextDecoder().decode(bytes);\n}\n\nexport function tryGetEmailTokenFromSubscriptionManageLink(link: string): string | undefined {\n try {\n const url = new URL(link);\n const subscriptionToken = url.searchParams.get(\"subscription_token\");\n if (subscriptionToken === undefined || subscriptionToken === null || subscriptionToken === \"\")\n return undefined;\n const parts = subscriptionToken.split(\".\");\n if (parts.length < 2) return undefined;\n const payloadJson = decodeBase64UrlToString(parts[1] ?? \"\");\n const payload = JSON.parse(payloadJson) as Record<string, unknown>;\n return typeof payload.email_token === \"string\" ? payload.email_token : undefined;\n } catch {\n return undefined;\n }\n}\n","import type { GenericEndpointContext } from \"better-auth\";\n\nexport function getWebhookRequest(ctx: GenericEndpointContext): Request | undefined {\n return (\n (ctx as unknown as { requestClone?: Request }).requestClone ??\n (ctx as { request?: Request }).request\n );\n}\n\nexport function getWebhookHeaders(ctx: GenericEndpointContext): Headers | undefined {\n return (\n (ctx as GenericEndpointContext & { headers?: Headers }).headers ??\n (ctx.request as unknown as { headers?: Headers })?.headers\n );\n}\n\nexport function getWebhookClientIP(\n ctx: GenericEndpointContext,\n headers: Headers | undefined,\n): string | undefined {\n return (\n headers?.get(\"x-forwarded-for\")?.split(\",\")[0]?.trim() ??\n headers?.get(\"x-real-ip\") ??\n (ctx.request as unknown as { ip?: string }).ip\n );\n}\n","import type { components } from \"@alexasomba/paystack-node\";\nimport type { GenericEndpointContext } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\n\nimport { createBillingStore } from \"./billing-store.ts\";\nimport { getOrganizationSubscription } from \"./limits.ts\";\nimport { createProrationMetadata, stringifyPaystackMetadata } from \"./metadata.ts\";\nimport { PAYSTACK_MODELS } from \"./models.ts\";\nimport { readPaystackPaymentCredentials } from \"./payment-credentials.ts\";\nimport { createPaystackAdapter } from \"./paystack-sdk.ts\";\nimport type {\n AnyPaystackOptions,\n PaystackChargeAuthorizationResponse,\n PaystackCheckoutChannel,\n PaystackInitializeResult,\n PaystackPlan,\n Subscription,\n User,\n PaystackSubscriptionOperation,\n PaystackSubscriptionOperationPhase,\n} from \"./types.ts\";\nimport {\n assertLocallyManagedSubscription,\n calculatePlanAmount,\n getPlanByName,\n getPlanSeatAmount,\n normalizeSubscriptionGroup,\n} from \"./utils.ts\";\n\n/** Keep reservation context invocation-local, including concurrent requests through one plugin. */\nexport async function runSubscriptionOperation<TResult extends PaystackInitializeResult>(\n ctx: GenericEndpointContext,\n options: AnyPaystackOptions | undefined,\n operation: PaystackSubscriptionOperation,\n run: (\n providerReference: string | undefined,\n setPhase: (phase: PaystackSubscriptionOperationPhase) => void,\n ) => Promise<TResult>,\n): Promise<TResult> {\n const hooks = options?.subscription?.operationHooks;\n if (hooks === undefined) return run(undefined, () => undefined);\n const decision = await hooks.before(operation, ctx);\n if (decision.kind === \"replay\") {\n const validKind =\n operation.kind === \"schedule\"\n ? decision.result.kind === \"scheduled\"\n : operation.kind === \"initialize\"\n ? decision.result.kind === \"checkout\"\n : operation.kind === \"local-change\"\n ? decision.result.kind === \"prorated\"\n : decision.result.kind === \"checkout\" || decision.result.kind === \"prorated\";\n if (!validKind)\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Operation replay does not match the validated operation kind.\",\n });\n return decision.result as TResult;\n }\n if (decision.kind === \"block\") {\n throw new APIError(\"CONFLICT\", {\n message: decision.message ?? \"Subscription operation is blocked.\",\n });\n }\n if (\n decision.kind !== \"proceed\" ||\n typeof decision.providerReference !== \"string\" ||\n decision.providerReference.trim() === \"\"\n ) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Operation hook must reserve a provider reference.\",\n });\n }\n const invocation = {\n ...operation,\n providerReference: decision.providerReference,\n context: decision.context,\n };\n let phase: PaystackSubscriptionOperationPhase =\n operation.kind === \"schedule\" || operation.kind === \"local-change\" ? \"persistence\" : \"provider\";\n try {\n const result = await run(decision.providerReference, (next) => {\n phase = next;\n });\n phase = \"completion\";\n await hooks.after?.({ ...invocation, result }, ctx);\n return result;\n } catch (error: unknown) {\n try {\n await hooks.onError?.({ ...invocation, phase, error }, ctx);\n } catch {\n ctx.context.logger.error(\"Paystack operation error hook failed\", { phase });\n }\n throw error;\n }\n}\n\nexport type ProratedUpgradeOutcome =\n | Extract<PaystackInitializeResult, { kind: \"prorated\" }>\n | {\n kind: \"checkout\";\n url: string | undefined;\n reference: string | undefined;\n accessCode: string | undefined;\n redirect: true;\n };\n\nexport interface TrialLifecycleDecision {\n trialStart?: Date;\n trialEnd?: Date;\n requestedDays: number;\n requested: boolean;\n granted: boolean;\n deniedReason?: \"already_used\";\n}\n\nexport async function scheduleSubscriptionLifecycleChange(\n ctx: GenericEndpointContext,\n input: {\n userId?: string;\n referenceId: string;\n subscriptionId?: string;\n plan?: PaystackPlan;\n scheduleAtPeriodEnd?: boolean;\n cancelAtPeriodEnd?: boolean;\n },\n options?: AnyPaystackOptions,\n): Promise<Extract<PaystackInitializeResult, { kind: \"scheduled\" }> | null> {\n const groupId = normalizeSubscriptionGroup(input.plan?.group);\n if (input.plan !== undefined && input.scheduleAtPeriodEnd === true) {\n const existingSub =\n input.subscriptionId === undefined\n ? await getOrganizationSubscription(ctx, input.referenceId, groupId)\n : await createBillingStore(ctx).findSubscriptionById(input.subscriptionId);\n if (existingSub?.status === \"active\") {\n return runSubscriptionOperation<Extract<PaystackInitializeResult, { kind: \"scheduled\" }>>(\n ctx,\n options,\n {\n actor: { id: input.userId ?? existingSub.userId },\n referenceId: input.referenceId,\n kind: \"schedule\",\n subscription: existingSub,\n intent: {\n plan: input.plan?.name ?? existingSub.plan,\n interval: input.plan?.interval ?? existingSub.billingInterval ?? undefined,\n groupId,\n scheduleAtPeriodEnd: input.scheduleAtPeriodEnd,\n cancelAtPeriodEnd: input.cancelAtPeriodEnd,\n },\n },\n async () => {\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"id\", value: existingSub.id }],\n update: {\n pendingPlan: input.plan?.name,\n updatedAt: new Date(),\n },\n });\n return {\n kind: \"scheduled\",\n status: \"success\",\n message: \"Plan change scheduled at period end.\",\n scheduled: true,\n };\n },\n );\n }\n }\n\n if (input.cancelAtPeriodEnd === true) {\n const existingSub =\n input.subscriptionId === undefined\n ? await getOrganizationSubscription(\n ctx,\n input.referenceId,\n input.plan === undefined ? undefined : groupId,\n )\n : await createBillingStore(ctx).findSubscriptionById(input.subscriptionId);\n if (existingSub?.status === \"active\") {\n return runSubscriptionOperation<Extract<PaystackInitializeResult, { kind: \"scheduled\" }>>(\n ctx,\n options,\n {\n actor: { id: input.userId ?? existingSub.userId },\n referenceId: input.referenceId,\n kind: \"schedule\",\n subscription: existingSub,\n intent: {\n plan: input.plan?.name ?? existingSub.plan,\n interval: input.plan?.interval ?? existingSub.billingInterval ?? undefined,\n groupId,\n scheduleAtPeriodEnd: input.scheduleAtPeriodEnd,\n cancelAtPeriodEnd: input.cancelAtPeriodEnd,\n },\n },\n async () => {\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"id\", value: existingSub.id }],\n update: {\n cancelAtPeriodEnd: true,\n cancelAt: existingSub.periodEnd ?? null,\n canceledAt: new Date(),\n updatedAt: new Date(),\n },\n });\n\n return {\n kind: \"scheduled\",\n status: \"success\",\n message: \"Subscription cancellation scheduled at period end.\",\n scheduled: true,\n };\n },\n );\n }\n }\n\n return null;\n}\n\nexport async function resolveTrialLifecycle(\n ctx: GenericEndpointContext,\n input: {\n referenceId: string;\n plan?: PaystackPlan;\n },\n): Promise<TrialLifecycleDecision> {\n const requestedDays =\n input.plan?.freeTrial?.days !== undefined && input.plan.freeTrial.days > 0\n ? input.plan.freeTrial.days\n : 0;\n const requested = requestedDays > 0;\n if (!requested) {\n return {\n requestedDays,\n requested: false,\n granted: false,\n };\n }\n\n const previousTrials = await ctx.context.adapter.findMany<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"referenceId\", value: input.referenceId }],\n });\n const hadTrial = previousTrials?.some(\n (subscription) =>\n (subscription.trialStart !== undefined && subscription.trialStart !== null) ||\n (subscription.trialEnd !== undefined && subscription.trialEnd !== null) ||\n subscription.status === \"trialing\",\n );\n\n if (hadTrial === true) {\n return {\n requestedDays,\n requested,\n granted: false,\n deniedReason: \"already_used\",\n };\n }\n\n const trialStart = new Date();\n const trialEnd = new Date();\n trialEnd.setDate(trialEnd.getDate() + requestedDays);\n\n return {\n trialStart,\n trialEnd,\n requestedDays,\n requested,\n granted: true,\n };\n}\n\nexport async function resolveCheckoutTargetEmail(\n ctx: GenericEndpointContext,\n options: AnyPaystackOptions,\n input: {\n email?: string;\n referenceId: string;\n user: User;\n },\n): Promise<string> {\n const targetEmail = input.email ?? input.user.email;\n\n if (\n options.organization?.enabled !== true ||\n input.referenceId === input.user.id ||\n input.referenceId === \"\"\n ) {\n return targetEmail;\n }\n\n const org = await ctx.context.adapter.findOne({\n model: \"organization\",\n where: [{ field: \"id\", value: input.referenceId }],\n });\n if (org === undefined || org === null) {\n return targetEmail;\n }\n\n const orgWithEmail = org as { email?: string | null };\n if (\n orgWithEmail.email !== undefined &&\n orgWithEmail.email !== null &&\n orgWithEmail.email !== \"\"\n ) {\n return orgWithEmail.email;\n }\n\n const ownerMember = await ctx.context.adapter.findOne({\n model: \"member\",\n where: [\n { field: \"organizationId\", value: input.referenceId },\n { field: \"role\", value: \"owner\" },\n ],\n });\n\n if (ownerMember === undefined || ownerMember === null) {\n return targetEmail;\n }\n\n const ownerUser = await ctx.context.adapter.findOne<User>({\n model: \"user\",\n where: [{ field: \"id\", value: (ownerMember as { userId: string }).userId }],\n });\n\n return ownerUser?.email !== undefined && ownerUser.email !== \"\" ? ownerUser.email : targetEmail;\n}\n\nexport async function handleProratedUpgrade(\n ctx: GenericEndpointContext,\n options: AnyPaystackOptions,\n input: {\n plan: PaystackPlan;\n referenceId: string;\n subscriptionId?: string;\n quantity?: number;\n targetEmail: string;\n userId: string;\n finalCurrency: string;\n callbackURL?: string;\n allowedSubscriptionChannels?: PaystackCheckoutChannel[];\n },\n): Promise<ProratedUpgradeOutcome | null> {\n const store = createBillingStore(ctx);\n const existingSub =\n input.subscriptionId === undefined\n ? await store.findCurrentSubscription(\n input.referenceId,\n normalizeSubscriptionGroup(input.plan.group),\n )\n : await store.findSubscriptionById(input.subscriptionId);\n if (\n existingSub?.status !== \"active\" ||\n existingSub.subscriptionCode === undefined ||\n existingSub.subscriptionCode === null ||\n existingSub.subscriptionCode === \"\" ||\n existingSub.periodEnd === undefined ||\n existingSub.periodEnd === null ||\n existingSub.periodStart === undefined ||\n existingSub.periodStart === null\n ) {\n return null;\n }\n\n const now = new Date();\n const periodEnd = new Date(existingSub.periodEnd);\n const periodStart = new Date(existingSub.periodStart);\n\n const totalDays = Math.max(\n 1,\n Math.ceil((periodEnd.getTime() - periodStart.getTime()) / (1000 * 60 * 60 * 24)),\n );\n const remainingDays = Math.max(\n 0,\n Math.ceil((periodEnd.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)),\n );\n\n let oldAmount = 0;\n if (existingSub.plan !== \"\") {\n const oldPlan =\n (await getPlanByName(options, existingSub.plan)) ??\n (await store.findPlanByName(existingSub.plan));\n if (oldPlan !== undefined && oldPlan !== null) {\n oldAmount = calculatePlanAmount(oldPlan, existingSub.seats ?? 1);\n }\n }\n\n let membersCount = 1;\n let newSeatCount: number;\n let newAmount: number;\n try {\n assertLocallyManagedSubscription(existingSub, \"plan or seat changes\");\n if (getPlanSeatAmount(input.plan) !== undefined) {\n const members = await store.listMembers(input.referenceId);\n membersCount = members.length > 0 ? members.length : 1;\n }\n newSeatCount = input.quantity ?? existingSub.seats ?? membersCount;\n newAmount = calculatePlanAmount(input.plan, newSeatCount);\n } catch (error: unknown) {\n throw new APIError(\"BAD_REQUEST\", {\n message: error instanceof Error ? error.message : \"Invalid seat configuration for plan.\",\n });\n }\n\n const costDifference = newAmount - oldAmount;\n const prorationMetadata = createProrationMetadata({\n subscriptionId: existingSub.id,\n referenceId: input.referenceId,\n newPlan: input.plan.name.toLowerCase(),\n oldPlan: existingSub.plan,\n newSeatCount,\n remainingDays,\n });\n const serializedProrationMetadata = stringifyPaystackMetadata(prorationMetadata);\n const proratedAmount = Math.round((costDifference / totalDays) * remainingDays);\n const hasCharge = costDifference > 0 && remainingDays > 0;\n if (hasCharge && proratedAmount < 5000) {\n throw new APIError(\"BAD_REQUEST\", {\n message:\n \"Prorated upgrade amount is below Paystack's minimum charge. Schedule the change for period end instead.\",\n status: 400,\n });\n }\n const credentials = hasCharge\n ? await readPaystackPaymentCredentials(ctx.context.adapter, options, existingSub.id)\n : null;\n const hasAuthorization =\n credentials?.authorizationCode !== undefined &&\n credentials.authorizationCode !== null &&\n credentials.authorizationCode !== \"\";\n return runSubscriptionOperation<Exclude<PaystackInitializeResult, { kind: \"scheduled\" }>>(\n ctx,\n options,\n {\n actor: { id: input.userId ?? existingSub.userId },\n referenceId: input.referenceId,\n kind: hasCharge\n ? hasAuthorization\n ? \"proration-charge\"\n : \"proration-initialize\"\n : \"local-change\",\n subscription: existingSub,\n intent: {\n plan: input.plan.name.toLowerCase(),\n amount: hasCharge ? proratedAmount : 0,\n currency: input.finalCurrency,\n interval: input.plan.interval,\n quantity: newSeatCount,\n groupId: normalizeSubscriptionGroup(input.plan.group),\n callbackURL: input.callbackURL,\n },\n },\n async (providerReference, setPhase) => {\n let completedProrationReference: string | undefined;\n\n if (costDifference > 0 && remainingDays > 0) {\n const paystack = createPaystackAdapter(options.paystackClient);\n if (\n credentials?.authorizationCode !== undefined &&\n credentials.authorizationCode !== null &&\n credentials.authorizationCode !== \"\"\n ) {\n const sdkRes = (await paystack.chargeAuthorization({\n email: input.targetEmail,\n amount: proratedAmount,\n authorization_code: credentials.authorizationCode,\n reference:\n providerReference ??\n `upg_${existingSub.id}_${Date.now()}_${Math.random().toString(36).substring(7)}`,\n metadata: serializedProrationMetadata,\n })) as PaystackChargeAuthorizationResponse;\n\n if (providerReference !== undefined && sdkRes?.reference !== providerReference) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Provider reference does not match reserved operation.\",\n });\n }\n if (sdkRes?.status !== \"success\") {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Failed to process prorated charge via saved authorization.\",\n });\n }\n\n setPhase(\"persistence\");\n await store.createTransaction({\n reference: sdkRes.reference ?? \"\",\n paystackId:\n sdkRes.id !== undefined && sdkRes.id !== null ? String(sdkRes.id) : undefined,\n referenceId: input.referenceId,\n userId: input.userId,\n amount: sdkRes.amount ?? proratedAmount,\n currency: sdkRes.currency ?? input.finalCurrency,\n status: \"success\",\n plan: input.plan.name.toLowerCase(),\n metadata: serializedProrationMetadata,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n completedProrationReference = sdkRes.reference ?? undefined;\n } else {\n const initRes = await paystack.initializeTransaction({\n ...(providerReference !== undefined ? { reference: providerReference } : {}),\n email: input.targetEmail,\n amount: proratedAmount,\n currency: input.finalCurrency,\n callback_url: input.callbackURL ?? undefined,\n metadata: serializedProrationMetadata,\n ...(input.allowedSubscriptionChannels !== undefined\n ? { channels: input.allowedSubscriptionChannels }\n : {}),\n } as components[\"schemas\"][\"TransactionInitialize\"]);\n\n if (providerReference !== undefined && initRes?.reference !== providerReference) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Provider reference does not match reserved operation.\",\n });\n }\n setPhase(\"persistence\");\n await store.createTransaction({\n reference: initRes?.reference ?? \"\",\n referenceId: input.referenceId,\n userId: input.userId,\n amount: proratedAmount,\n currency: input.finalCurrency,\n status: \"pending\",\n plan: input.plan.name.toLowerCase(),\n metadata: serializedProrationMetadata,\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n\n return {\n kind: \"checkout\",\n url: initRes?.authorization_url,\n reference: initRes?.reference,\n accessCode: initRes?.access_code,\n redirect: true,\n };\n }\n }\n\n setPhase(\"persistence\");\n await store.updateSubscription(existingSub.id, {\n plan: input.plan.name,\n seats: newSeatCount,\n ...(completedProrationReference !== undefined\n ? { transactionReference: completedProrationReference }\n : {}),\n updatedAt: new Date(),\n });\n\n return {\n kind: \"prorated\",\n status: \"success\",\n message: \"Subscription successfully upgraded with prorated charge.\",\n prorated: true,\n };\n },\n );\n}\n","import { randomUUID, createHash } from \"node:crypto\";\n\nimport type { components } from \"@alexasomba/paystack-node\";\nimport { HIDE_METADATA } from \"better-auth\";\nimport type { GenericEndpointContext, StrictEndpoint } from \"better-auth\";\nimport {\n APIError,\n getSessionFromCtx,\n type AuthMiddleware,\n originCheckMiddleware,\n sessionMiddleware,\n} from \"better-auth/api\";\nimport { createAuthEndpoint } from \"better-auth/api\";\n/* oxlint-disable no-restricted-imports */\nimport { z } from \"zod\";\n\nimport { createBillingStore } from \"./billing-store.ts\";\nimport {\n createCheckoutMetadata,\n hasPaystackMetadata,\n parsePaystackMetadata,\n stringifyPaystackMetadata,\n} from \"./metadata.ts\";\nimport { PAYSTACK_MODELS } from \"./models.ts\";\nimport {\n readPaystackPaymentCredentials,\n savePaystackPaymentCredentials,\n} from \"./payment-credentials.ts\";\nimport { getPaystackOps, unwrapSdkResult } from \"./paystack-sdk.ts\";\nimport { reconcilePaystackTransaction } from \"./reconciliation.ts\";\nimport { authorizeBillingReference } from \"./reference-access.ts\";\nimport { referenceMiddleware } from \"./reference-middleware.ts\";\nimport { isTrustedCallbackURL } from \"./route-modules/callback-url.ts\";\nimport {\n getConfiguredCatalog,\n listStoredPlans,\n listStoredProducts,\n} from \"./route-modules/catalog.ts\";\nimport { initializeTransactionBodySchema } from \"./route-modules/checkout.ts\";\nimport {\n getAllowedSubscriptionChannels,\n hmacSha512Hex,\n PAYSTACK_ERROR_CODES,\n} from \"./route-modules/shared.ts\";\nimport {\n enableDisableBodySchema,\n tryGetEmailTokenFromSubscriptionManageLink,\n} from \"./route-modules/subscriptions.ts\";\nimport {\n getWebhookClientIP,\n getWebhookHeaders,\n getWebhookRequest,\n} from \"./route-modules/webhook.ts\";\nimport {\n claimSubscriptionFulfillment,\n deliverTrialStart,\n releaseSubscriptionFulfillment,\n} from \"./subscription-fulfillment.ts\";\nimport {\n handleProratedUpgrade,\n resolveCheckoutTargetEmail,\n resolveTrialLifecycle,\n scheduleSubscriptionLifecycleChange,\n runSubscriptionOperation,\n} from \"./subscription-lifecycle.ts\";\nimport type {\n InputPaystackProduct,\n PaystackTransaction,\n AnyPaystackOptions,\n PaystackProduct,\n Subscription,\n Member,\n PaystackPlan,\n PaystackWebhookPayload,\n User,\n PaystackCheckoutChannel,\n PaystackInitializeResult,\n} from \"./types.ts\";\nimport {\n syncProductQuantityFromPaystack,\n getPlanByName,\n getPlans,\n getProductByName,\n getPlanSeatAmount,\n calculatePlanAmount,\n isLocalSubscriptionCode,\n normalizeSubscriptionGroup,\n} from \"./utils.ts\";\n\nexport const paystackWebhook = <P extends string = \"/webhook\">(\n options: AnyPaystackOptions,\n path: P = \"/webhook\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"POST\";\n metadata: {\n openapi: {\n operationId: string;\n };\n scope: \"server\";\n };\n cloneRequest: true;\n disableBody: true;\n },\n {\n received: boolean;\n }\n> => {\n return createAuthEndpoint(\n path,\n {\n method: \"POST\",\n metadata: {\n ...HIDE_METADATA,\n openapi: {\n operationId: \"handlePaystackWebhook\",\n },\n },\n cloneRequest: true,\n disableBody: true,\n },\n async (ctx) => {\n const request = getWebhookRequest(ctx as GenericEndpointContext);\n if (request === undefined || request === null) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Request object is missing from context\",\n });\n }\n const payload = await request.text();\n const headers = getWebhookHeaders(ctx as GenericEndpointContext);\n const signature = headers?.get(\"x-paystack-signature\");\n\n if (options.webhook?.verifyIP === true) {\n const trustedIPs = options.webhook.trustedIPs ?? [\n \"52.31.139.75\",\n \"52.49.173.169\",\n \"52.214.14.220\",\n ];\n const clientIP = getWebhookClientIP(ctx as GenericEndpointContext, headers);\n\n if (\n clientIP !== undefined &&\n clientIP !== null &&\n trustedIPs.includes(clientIP) === false\n ) {\n throw new APIError(\"UNAUTHORIZED\", {\n message: `Forbidden IP: ${clientIP}`,\n status: 401,\n });\n }\n }\n\n if (signature === undefined || signature === null || signature === \"\") {\n throw new APIError(\"UNAUTHORIZED\", {\n message: \"Missing x-paystack-signature header\",\n status: 401,\n });\n }\n\n const expected = await hmacSha512Hex(options.secretKey, payload);\n if (expected !== signature) {\n throw new APIError(\"UNAUTHORIZED\", {\n message: \"Invalid Paystack webhook signature\",\n status: 401,\n });\n }\n\n const event = JSON.parse(payload) as PaystackWebhookPayload;\n const eventName = event.event;\n const data = event.data;\n const reference = (data as { reference?: string | null })?.reference;\n const eventId = createHash(\"sha256\").update(payload).digest(\"hex\");\n const store = createBillingStore(ctx);\n let claimStatus: string | undefined;\n try {\n let existingEvent = await store.findWebhookEvent(eventId);\n if (existingEvent?.status === \"processed\") return ctx.json({ received: true });\n if (existingEvent === null) {\n try {\n existingEvent = await store.createWebhookEvent({\n eventId,\n eventType: eventName,\n reference: reference ?? null,\n payload,\n status: \"pending\",\n createdAt: new Date(),\n updatedAt: new Date(),\n });\n } catch (error) {\n existingEvent = await store.findWebhookEvent(eventId);\n if (!existingEvent) throw error;\n }\n }\n if (existingEvent.status === \"processed\") return ctx.json({ received: true });\n if (\n existingEvent.status.startsWith(\"processing:\") &&\n new Date(existingEvent.updatedAt).getTime() > Date.now() - 5 * 60_000\n )\n throw new Error(\"Webhook is already processing; retry later.\");\n claimStatus = `processing:${randomUUID()}`;\n const claimed = await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.webhookEvent,\n where: [\n { field: \"eventId\", value: eventId },\n { field: \"status\", value: existingEvent.status },\n { field: \"updatedAt\", value: existingEvent.updatedAt },\n ],\n update: { status: claimStatus, updatedAt: new Date() },\n });\n if (claimed === null) throw new Error(\"Webhook claim was lost; retry later.\");\n\n // Core Transaction Status Sync (Applies to both one-time and recurring)\n if (eventName === \"charge.success\") {\n const reference = (data as { reference?: string | null })?.reference;\n const paystackIdRaw = (data as { id?: number | string | null })?.id;\n const paystackId =\n paystackIdRaw !== undefined && paystackIdRaw !== null\n ? String(paystackIdRaw)\n : undefined;\n\n if (reference !== undefined && reference !== null && reference !== \"\") {\n try {\n await ctx.context.adapter.update({\n model: \"paystackTransaction\",\n update: {\n status: \"success\",\n paystackId,\n updatedAt: new Date(),\n },\n where: [{ field: \"reference\", value: reference }],\n });\n } catch (e) {\n ctx.context.logger.warn(\"Failed to update transaction status for charge.success\", e);\n throw e;\n }\n\n if (options.subscription?.enabled === true) {\n const pendingTrial = await ctx.context.adapter.findOne<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"transactionReference\", value: reference }],\n });\n if (\n pendingTrial !== null &&\n [\"incomplete\", \"trialing\"].includes(pendingTrial.status) &&\n pendingTrial.trialStart !== undefined &&\n pendingTrial.trialStart !== null\n ) {\n const trialClaim = await claimSubscriptionFulfillment(\n ctx,\n reference,\n pendingTrial,\n \"trial-start\",\n );\n if (trialClaim !== null) {\n try {\n const startedTrial =\n pendingTrial.status === \"trialing\"\n ? pendingTrial\n : await ctx.context.adapter.update<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n where: [\n { field: \"id\", value: pendingTrial.id },\n { field: \"status\", value: \"incomplete\" },\n { field: \"transactionReference\", value: reference },\n ],\n update: { status: \"trialing\", updatedAt: new Date() },\n });\n if (startedTrial === null)\n throw new Error(\"Trial activation changed concurrently; retry later.\");\n const trialPlan = await getPlanByName(options, pendingTrial.plan);\n await deliverTrialStart(ctx, trialClaim, startedTrial, trialPlan ?? undefined);\n } catch (error) {\n await releaseSubscriptionFulfillment(ctx, trialClaim);\n throw error;\n }\n }\n }\n }\n\n // Sync product quantity from Paystack after successful charge\n try {\n const transaction = await ctx.context.adapter.findOne<PaystackTransaction>({\n model: \"paystackTransaction\",\n where: [{ field: \"reference\", value: reference }],\n });\n if (\n transaction !== undefined &&\n transaction !== null &&\n transaction.product !== undefined &&\n transaction.product !== null &&\n transaction.product !== \"\"\n ) {\n if (options.paystackClient !== undefined && options.paystackClient !== null) {\n await syncProductQuantityFromPaystack(\n ctx,\n transaction.product,\n options.paystackClient,\n );\n }\n }\n } catch (e) {\n ctx.context.logger.warn(\"Failed to sync product quantity\", e);\n throw e;\n }\n }\n }\n\n if ((eventName as string) === \"charge.failure\") {\n const reference = (data as { reference?: string })?.reference;\n if (reference !== undefined && reference !== null && reference !== \"\") {\n try {\n await ctx.context.adapter.update({\n model: \"paystackTransaction\",\n update: {\n status: \"failed\",\n updatedAt: new Date(),\n },\n where: [{ field: \"reference\", value: reference }],\n });\n } catch (e) {\n ctx.context.logger.warn(\"Failed to update transaction status for charge.failure\", e);\n throw e;\n }\n if (options.subscription?.enabled === true) {\n const pendingTrial = await ctx.context.adapter.findOne<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"transactionReference\", value: reference }],\n });\n if (\n pendingTrial?.status === \"incomplete\" &&\n pendingTrial.trialStart !== undefined &&\n pendingTrial.trialStart !== null\n ) {\n const endedAt = new Date();\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"id\", value: pendingTrial.id }],\n update: { status: \"canceled\", endedAt, updatedAt: endedAt },\n });\n }\n }\n }\n }\n\n if ((eventName as string) === \"invoice.payment_failed\") {\n const invoice = data as {\n subscription?: { subscription_code?: string | null };\n subscription_code?: string | null;\n };\n const subscriptionCode =\n invoice.subscription?.subscription_code ?? invoice.subscription_code;\n if (\n subscriptionCode !== null &&\n subscriptionCode !== undefined &&\n subscriptionCode !== \"\"\n ) {\n const existing = await ctx.context.adapter.findOne<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"subscriptionCode\", value: subscriptionCode }],\n });\n if (existing && existing.status !== \"canceled\" && existing.status !== \"past_due\") {\n const pastDue = { ...existing, status: \"past_due\", updatedAt: new Date() };\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"id\", value: existing.id }],\n update: { status: pastDue.status, updatedAt: pastDue.updatedAt },\n });\n const plan = await getPlanByName(options, existing.plan);\n if (plan) {\n await options.subscription?.onSubscriptionUpdate?.(\n { event, subscription: pastDue, plan },\n ctx as GenericEndpointContext,\n );\n }\n }\n }\n }\n\n // Best-effort local state sync for subscription lifecycle.\n if (options.subscription?.enabled === true) {\n try {\n if (eventName === \"subscription.create\") {\n const subscriptionData =\n data as unknown as components[\"schemas\"][\"SubscriptionListResponseArray\"];\n const subscriptionCode = subscriptionData.subscription_code ?? \"\";\n const customerCode = (\n subscriptionData.customer as { customer_code?: string | null } | undefined\n )?.customer_code;\n const planCode = (subscriptionData.plan as { plan_code?: string | null } | undefined)\n ?.plan_code;\n\n const metadataObj = parsePaystackMetadata(\n (subscriptionData as unknown as { metadata?: unknown }).metadata,\n );\n const referenceIdFromMetadata =\n typeof metadataObj.referenceId === \"string\" ? metadataObj.referenceId : undefined;\n let planNameFromMetadata =\n typeof metadataObj.plan === \"string\" ? metadataObj.plan : undefined;\n if (typeof planNameFromMetadata === \"string\") {\n planNameFromMetadata = planNameFromMetadata.toLowerCase();\n }\n\n const plans = await getPlans(options.subscription);\n const planFromCode =\n planCode !== undefined && planCode !== null && planCode !== \"\"\n ? plans.find((p) => p.planCode === planCode)\n : undefined;\n const groupIdFromMetadata =\n typeof metadataObj.groupId === \"string\"\n ? normalizeSubscriptionGroup(metadataObj.groupId)\n : normalizeSubscriptionGroup(planFromCode?.group);\n const planPart = planFromCode?.name ?? planNameFromMetadata;\n const planName =\n planPart !== undefined && planPart !== null && planPart !== \"\"\n ? planPart.toLowerCase()\n : undefined;\n\n if (\n subscriptionCode !== undefined &&\n subscriptionCode !== null &&\n subscriptionCode !== \"\"\n ) {\n const where: { field: string; value: string | number | boolean | null }[] = [];\n if (\n referenceIdFromMetadata !== undefined &&\n referenceIdFromMetadata !== null &&\n referenceIdFromMetadata !== \"\"\n ) {\n where.push({ field: \"referenceId\", value: referenceIdFromMetadata });\n } else if (\n customerCode !== undefined &&\n customerCode !== null &&\n customerCode !== \"\"\n ) {\n where.push({ field: \"customerCode\", value: customerCode });\n }\n if (planName !== undefined && planName !== null && planName !== \"\") {\n where.push({ field: \"plan\", value: planName });\n }\n\n if (where.length > 0) {\n const matches = await ctx.context.adapter.findMany<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n where: where,\n });\n const subscription = matches?.find((candidate) =>\n candidate.status !== \"canceled\" &&\n (candidate.subscriptionCode === subscriptionCode ||\n candidate.status === \"incomplete\" ||\n (candidate.status === \"trialing\" &&\n (candidate.subscriptionCode === undefined ||\n candidate.subscriptionCode === null ||\n candidate.subscriptionCode === \"\"))) &&\n groupIdFromMetadata === null\n ? candidate.groupId === undefined ||\n candidate.groupId === null ||\n candidate.groupId === \"\"\n : candidate.groupId === groupIdFromMetadata,\n );\n if (subscription !== undefined && subscription !== null) {\n const plan =\n planFromCode ??\n (planName !== undefined && planName !== null && planName !== \"\"\n ? await getPlanByName(options, planName)\n : undefined);\n const now = new Date();\n const persistedSubscription: Subscription = {\n ...subscription,\n subscriptionCode,\n status: \"active\",\n billingInterval: plan?.interval ?? subscription.billingInterval ?? null,\n periodEnd:\n subscriptionData.next_payment_date !== undefined &&\n subscriptionData.next_payment_date !== null\n ? new Date(subscriptionData.next_payment_date)\n : subscription.periodEnd,\n updatedAt: now,\n };\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.subscription,\n update: {\n subscriptionCode: persistedSubscription.subscriptionCode,\n status: persistedSubscription.status,\n billingInterval: persistedSubscription.billingInterval,\n periodEnd: persistedSubscription.periodEnd,\n updatedAt: persistedSubscription.updatedAt,\n },\n where: [{ field: \"id\", value: subscription.id }],\n });\n await createBillingStore(ctx).retireCompetingSubscriptions(\n subscription.referenceId,\n subscription.groupId ?? null,\n subscription.id,\n );\n\n if (plan !== undefined && plan !== null) {\n const callbackData = { event, subscription: persistedSubscription, plan };\n for (const callback of [\n options.subscription.onSubscriptionComplete,\n options.subscription.onSubscriptionCreated,\n options.subscription.onSubscriptionUpdate,\n ]) {\n try {\n await callback?.(callbackData, ctx as GenericEndpointContext);\n } catch (error) {\n ctx.context.logger.error(\"Paystack subscription callback failed\", error);\n throw error;\n }\n }\n if (subscription.status === \"trialing\") {\n try {\n await plan.freeTrial?.onTrialEnd?.(persistedSubscription);\n } catch (error) {\n ctx.context.logger.error(\"Paystack trial end callback failed\", error);\n throw error;\n }\n }\n }\n }\n }\n }\n }\n\n if (eventName === \"subscription.disable\" || eventName === \"subscription.not_renew\") {\n const subscriptionData =\n data as unknown as components[\"schemas\"][\"SubscriptionListResponseArray\"];\n const subscriptionCode = subscriptionData.subscription_code ?? \"\";\n if (subscriptionCode !== \"\") {\n const existing = await ctx.context.adapter.findOne<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"subscriptionCode\", value: subscriptionCode }],\n });\n\n let newStatus = \"canceled\";\n const nextPaymentDate = subscriptionData.next_payment_date;\n const periodEnd =\n nextPaymentDate !== undefined &&\n nextPaymentDate !== null &&\n nextPaymentDate !== \"\"\n ? new Date(nextPaymentDate)\n : existing?.periodEnd !== undefined && existing.periodEnd !== null\n ? new Date(existing.periodEnd)\n : undefined;\n\n if (periodEnd !== undefined && periodEnd.getTime() > Date.now()) {\n newStatus = \"active\";\n }\n\n const now = new Date();\n const persistedSubscription =\n existing === null || existing === undefined\n ? undefined\n : ({\n ...existing,\n status: newStatus,\n cancelAtPeriodEnd: newStatus === \"active\",\n cancelAt: newStatus === \"active\" ? (periodEnd ?? null) : null,\n canceledAt: now,\n endedAt: newStatus === \"canceled\" ? now : null,\n ...(periodEnd ? { periodEnd } : {}),\n updatedAt: now,\n } as Subscription);\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.subscription,\n update: {\n status: newStatus,\n cancelAtPeriodEnd: newStatus === \"active\",\n cancelAt: newStatus === \"active\" ? (periodEnd ?? null) : null,\n canceledAt: now,\n endedAt: newStatus === \"canceled\" ? now : null,\n ...(periodEnd ? { periodEnd } : {}),\n updatedAt: now,\n },\n where: [{ field: \"subscriptionCode\", value: subscriptionCode }],\n });\n\n if (persistedSubscription !== undefined) {\n try {\n await options.subscription.onSubscriptionCancel?.(\n { event, subscription: persistedSubscription },\n ctx as GenericEndpointContext,\n );\n } catch (error) {\n ctx.context.logger.error(\"Paystack subscription cancel callback failed\", error);\n }\n const plan = await getPlanByName(options, persistedSubscription.plan);\n if (plan !== undefined && plan !== null) {\n try {\n await options.subscription.onSubscriptionUpdate?.(\n { event, subscription: persistedSubscription, plan },\n ctx as GenericEndpointContext,\n );\n } catch (error) {\n ctx.context.logger.error(\n \"Paystack subscription update callback failed\",\n error,\n );\n }\n if (existing?.status === \"trialing\" && newStatus === \"canceled\") {\n try {\n await plan.freeTrial?.onTrialExpired?.(persistedSubscription);\n } catch (error) {\n ctx.context.logger.error(\"Paystack trial expiry callback failed\", error);\n }\n }\n }\n }\n }\n }\n\n // Handle plan changes on renewal\n if (eventName === \"charge.success\" || eventName === \"invoice.update\") {\n const subData = (data as { subscription?: { subscription_code?: string | null } })\n ?.subscription;\n const subscriptionCodeRaw =\n subData?.subscription_code ??\n (data as { subscription_code?: string | null })?.subscription_code;\n const subscriptionCode =\n subscriptionCodeRaw !== undefined &&\n subscriptionCodeRaw !== null &&\n subscriptionCodeRaw !== \"\"\n ? subscriptionCodeRaw\n : undefined;\n\n if (subscriptionCode !== undefined) {\n const existingSub = await ctx.context.adapter.findOne<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"subscriptionCode\", value: subscriptionCode }],\n });\n\n if (existingSub?.status === \"past_due\") {\n const recovered = { ...existingSub, status: \"active\", updatedAt: new Date() };\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.subscription,\n update: { status: recovered.status, updatedAt: recovered.updatedAt },\n where: [{ field: \"id\", value: existingSub.id }],\n });\n const plan = await getPlanByName(options, existingSub.plan);\n if (plan) {\n await options.subscription.onSubscriptionUpdate?.(\n { event, subscription: recovered, plan },\n ctx as GenericEndpointContext,\n );\n }\n }\n\n if (\n existingSub !== undefined &&\n existingSub !== null &&\n existingSub.pendingPlan !== undefined &&\n existingSub.pendingPlan !== null &&\n existingSub.pendingPlan !== \"\"\n ) {\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.subscription,\n update: {\n plan: existingSub.pendingPlan,\n pendingPlan: null,\n updatedAt: new Date(),\n },\n where: [{ field: \"id\", value: existingSub.id }],\n });\n }\n }\n }\n } catch (_e: unknown) {\n ctx.context.logger.error(\"Failed to sync Paystack webhook event\", _e);\n throw _e;\n }\n }\n\n await options.onEvent?.(event);\n const completed = await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.webhookEvent,\n where: [\n { field: \"eventId\", value: eventId },\n { field: \"status\", value: claimStatus },\n ],\n update: { status: \"processed\", processedAt: new Date(), updatedAt: new Date() },\n });\n if (completed === null) throw new Error(\"Webhook processing lease was lost.\");\n return ctx.json({ received: true });\n } catch (error) {\n if (claimStatus !== undefined)\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.webhookEvent,\n where: [\n { field: \"eventId\", value: eventId },\n { field: \"status\", value: claimStatus },\n ],\n update: { status: \"pending\", updatedAt: new Date() },\n });\n ctx.context.logger.error(\n \"Paystack webhook processing failed; delivery must be retried\",\n error,\n );\n throw new APIError(\"SERVICE_UNAVAILABLE\", {\n message: \"Webhook processing failed; retry delivery.\",\n });\n }\n },\n );\n};\n\nexport const initializeTransaction = <P extends string = \"/initialize-transaction\">(\n options: AnyPaystackOptions,\n path: P = \"/initialize-transaction\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"POST\";\n body: z.ZodObject<\n {\n plan: z.ZodOptional<z.ZodString>;\n product: z.ZodOptional<z.ZodString>;\n amount: z.ZodOptional<z.ZodNumber>;\n currency: z.ZodOptional<z.ZodString>;\n email: z.ZodOptional<z.ZodString>;\n metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;\n referenceId: z.ZodOptional<z.ZodString>;\n subscriptionId: z.ZodOptional<z.ZodString>;\n callbackURL: z.ZodOptional<z.ZodString>;\n quantity: z.ZodOptional<z.ZodNumber>;\n scheduleAtPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n cancelAtPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n prorateAndCharge: z.ZodOptional<z.ZodBoolean>;\n confirmTrialTokenizationCharge: z.ZodOptional<z.ZodBoolean>;\n },\n z.core.$strip\n >;\n use: AuthMiddleware[];\n },\n PaystackInitializeResult | undefined\n> => {\n const subscriptionOptions = options.subscription;\n const useMiddlewares: AuthMiddleware[] =\n subscriptionOptions?.enabled === true\n ? [\n sessionMiddleware,\n originCheckMiddleware,\n referenceMiddleware(options, \"initialize-transaction\"),\n ]\n : [sessionMiddleware, originCheckMiddleware];\n\n return createAuthEndpoint(\n path,\n {\n method: \"POST\",\n body: initializeTransactionBodySchema,\n use: useMiddlewares,\n },\n async (ctx) => {\n const paystack = getPaystackOps(options.paystackClient);\n const {\n plan: planName,\n product: productName,\n amount: bodyAmount,\n currency,\n email,\n metadata: extraMetadata,\n callbackURL,\n quantity,\n scheduleAtPeriodEnd,\n cancelAtPeriodEnd,\n prorateAndCharge,\n subscriptionId,\n confirmTrialTokenizationCharge,\n } = ctx.body;\n\n // 1. Validate Callback URL validation (same as before)\n if (callbackURL !== undefined && callbackURL !== null && callbackURL !== \"\") {\n const baseUrl =\n ((ctx.context as Record<string, unknown>)?.baseURL as string | undefined) ??\n (ctx.request as unknown as { url?: string })?.url ??\n \"\";\n if (!isTrustedCallbackURL(callbackURL, baseUrl)) {\n throw new APIError(\"FORBIDDEN\", {\n message: \"callbackURL is not a trusted origin.\",\n status: 403,\n });\n }\n }\n\n // 2. Get User & Session\n const session = await getSessionFromCtx(ctx);\n if (session === undefined || session === null) throw new APIError(\"UNAUTHORIZED\");\n const user = session.user;\n\n // 3. Email Verification Check (only if subscription options enforce it)\n if (\n subscriptionOptions?.enabled === true &&\n subscriptionOptions.requireEmailVerification === true &&\n user.emailVerified !== true\n ) {\n throw new APIError(\"BAD_REQUEST\", {\n code: \"EMAIL_VERIFICATION_REQUIRED\",\n message: PAYSTACK_ERROR_CODES.EMAIL_VERIFICATION_REQUIRED.message,\n });\n }\n\n // 4. Determine Payment Mode: Subscription (Plan) vs Product vs One-Time (Amount)\n let plan: PaystackPlan | undefined;\n let product: PaystackProduct | InputPaystackProduct | undefined;\n\n if (planName !== undefined && planName !== null && planName !== \"\") {\n if (subscriptionOptions?.enabled !== true) {\n throw new APIError(\"BAD_REQUEST\", { message: \"Subscriptions are not enabled.\" });\n }\n plan = (await getPlanByName(options, planName)) ?? undefined;\n if (plan === undefined || plan === null) {\n try {\n // Fallback: Check database for synced plans when that model exists.\n const nativePlan = await ctx.context.adapter.findOne<PaystackPlan>({\n model: \"paystackPlan\",\n where: [{ field: \"name\", value: planName }],\n });\n if (nativePlan !== undefined && nativePlan !== null) {\n plan = nativePlan;\n } else {\n const nativePlanByCode = await ctx.context.adapter.findOne<PaystackPlan>({\n model: \"paystackPlan\",\n where: [{ field: \"planCode\", value: planName }],\n });\n plan = nativePlanByCode ?? undefined;\n }\n } catch {\n plan = undefined;\n }\n }\n if (plan === undefined || plan === null) {\n throw new APIError(\"BAD_REQUEST\", {\n code: \"SUBSCRIPTION_PLAN_NOT_FOUND\",\n message: PAYSTACK_ERROR_CODES.SUBSCRIPTION_PLAN_NOT_FOUND.message,\n status: 400,\n });\n }\n } else if (productName !== undefined && productName !== null && productName !== \"\") {\n if (typeof productName === \"string\") {\n product = (await getProductByName(options, productName)) ?? undefined;\n // Fallback: Check database for synced products\n product ??=\n (await ctx.context.adapter.findOne<PaystackProduct>({\n model: \"paystackProduct\",\n where: [{ field: \"name\", value: productName }],\n })) ?? undefined;\n }\n if (product === undefined || product === null) {\n throw new APIError(\"BAD_REQUEST\", {\n message: `Product '${productName}' not found.`,\n status: 400,\n });\n }\n } else if (bodyAmount === undefined || bodyAmount === null) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Either 'plan', 'product', or 'amount' is required to initialize a transaction.\",\n status: 400,\n });\n }\n\n let amount =\n plan !== undefined\n ? plan.amount\n : product\n ? ((product as PaystackProduct).price ?? (product as InputPaystackProduct).amount)\n : bodyAmount;\n const finalCurrency =\n plan !== undefined || product\n ? ((product as PaystackProduct)?.currency ??\n (product as InputPaystackProduct)?.currency ??\n plan?.currency ??\n \"NGN\")\n : (currency ?? \"NGN\");\n\n const referenceIdFromCtx = (ctx.context as Record<string, unknown>).referenceId as\n | string\n | undefined;\n const referenceId =\n ctx.body.referenceId ?? referenceIdFromCtx ?? (session.user as { id: string }).id;\n const groupId = normalizeSubscriptionGroup(plan?.group);\n if (subscriptionId !== undefined) {\n const selectedSubscription =\n await createBillingStore(ctx).findSubscriptionById(subscriptionId);\n if (\n selectedSubscription === null ||\n selectedSubscription.referenceId !== referenceId ||\n normalizeSubscriptionGroup(selectedSubscription.groupId) !== groupId\n ) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Subscription does not belong to the authorized reference and plan group.\",\n });\n }\n }\n\n const scheduledChange = await scheduleSubscriptionLifecycleChange(\n ctx,\n {\n userId: user.id,\n referenceId,\n subscriptionId,\n plan,\n scheduleAtPeriodEnd,\n cancelAtPeriodEnd,\n },\n options,\n );\n if (scheduledChange !== null) {\n return ctx.json(scheduledChange);\n }\n\n let validatedQuantity = quantity ?? 1;\n if (product && amount !== undefined) amount *= quantity ?? 1;\n if (amount !== undefined && (!Number.isSafeInteger(amount) || amount <= 0))\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Catalog amount must be a positive safe integer.\",\n });\n\n // Calculate final amount considering seats if applicable\n if (plan !== undefined) {\n try {\n if (getPlanSeatAmount(plan) !== undefined) {\n const members = await ctx.context.adapter.findMany<Member>({\n model: \"member\",\n where: [{ field: \"organizationId\", value: referenceId }],\n });\n const seatCount = members.length > 0 ? members.length : 1;\n const quantityToUse = quantity ?? seatCount;\n validatedQuantity = quantityToUse;\n amount = calculatePlanAmount(plan, quantityToUse);\n }\n } catch (error: unknown) {\n throw new APIError(\"BAD_REQUEST\", {\n message:\n error instanceof Error ? error.message : \"Invalid seat configuration for plan.\",\n });\n }\n }\n\n let url: string | undefined;\n let reference: string | undefined;\n let accessCode: string | undefined;\n\n const trial = await resolveTrialLifecycle(ctx, { referenceId, plan });\n const { trialStart, trialEnd } = trial;\n const trialTokenizationCharge = trial.granted\n ? getTrialTokenizationCharge(plan, finalCurrency)\n : undefined;\n if (trial.granted && confirmTrialTokenizationCharge !== true) {\n throw new APIError(\"BAD_REQUEST\", {\n code: \"TRIAL_TOKENIZATION_CHARGE_CONFIRMATION_REQUIRED\",\n message: `This Paystack trial requires a one-time tokenization charge of ${trialTokenizationCharge} minor units in ${finalCurrency}. Tell the customer the exact charge and retry with confirmTrialTokenizationCharge: true after they accept it.`,\n });\n }\n\n const normalizeInitializationError = (error: unknown): APIError => {\n ctx.context.logger.error(\"Failed to initialize Paystack transaction\", error);\n return new APIError(\"BAD_REQUEST\", {\n code: \"FAILED_TO_INITIALIZE_TRANSACTION\",\n message:\n error instanceof Error\n ? error.message\n : PAYSTACK_ERROR_CODES.FAILED_TO_INITIALIZE_TRANSACTION.message,\n });\n };\n const prepared = await (async () => {\n const targetEmail = await resolveCheckoutTargetEmail(ctx, options, {\n email,\n referenceId,\n user: user as User,\n });\n\n const allowedSubscriptionChannels = plan\n ? getAllowedSubscriptionChannels(options)\n : undefined;\n\n // Construct Metadata\n const metadata = stringifyPaystackMetadata(\n createCheckoutMetadata({\n referenceId,\n userId: user.id,\n plan: plan !== undefined ? plan.name.toLowerCase() : undefined,\n groupId,\n product: product !== undefined ? product.name.toLowerCase() : undefined,\n extra: extraMetadata,\n trial: {\n isTrial: trialStart !== undefined,\n requested: trial.requested,\n granted: trial.granted,\n deniedReason: trial.deniedReason,\n endsAt: trialEnd,\n },\n }),\n );\n\n const initBody: {\n email: string;\n callback_url?: string;\n metadata?: string;\n currency: string;\n quantity?: number;\n amount?: number;\n plan?: string;\n channels?: PaystackCheckoutChannel[];\n [key: string]: unknown;\n } = {\n email: targetEmail,\n callback_url: callbackURL ?? undefined,\n metadata,\n // If plan/product exists, use its currency; otherwise fallback to provided or default\n currency: finalCurrency,\n quantity,\n };\n\n if (allowedSubscriptionChannels !== undefined) {\n initBody.channels = allowedSubscriptionChannels;\n }\n\n // Handle prorateAndCharge for existing active subscriptions\n if (plan !== undefined && prorateAndCharge === true) {\n const proration = await handleProratedUpgrade(ctx, options, {\n plan,\n referenceId,\n subscriptionId,\n quantity,\n targetEmail,\n userId: user.id,\n finalCurrency,\n callbackURL,\n allowedSubscriptionChannels,\n });\n\n if (proration?.kind === \"checkout\") {\n return {\n earlyResult: {\n kind: \"checkout\",\n url: proration.url ?? \"\",\n reference: proration.reference ?? \"\",\n accessCode: proration.accessCode ?? \"\",\n redirect: proration.redirect,\n } satisfies PaystackInitializeResult,\n };\n }\n\n if (proration?.kind === \"prorated\") {\n return {\n earlyResult: {\n kind: \"prorated\",\n status: proration.status,\n message: proration.message,\n prorated: proration.prorated,\n } satisfies PaystackInitializeResult,\n };\n }\n }\n\n if (plan !== undefined) {\n // Subscription Flow\n if (trialStart !== undefined) {\n // Paystack requires a small paid transaction to tokenize authorization before a local trial.\n initBody.amount = trialTokenizationCharge;\n } else {\n // Standard Flow\n initBody.plan = plan.planCode;\n // SDK might use different field names, but keeping DX consistency\n (initBody as Record<string, unknown>).invoice_limit = plan.invoiceLimit;\n\n let finalAmount: number;\n if (amount !== undefined && amount !== null) {\n finalAmount = amount;\n initBody.quantity = 1;\n } else {\n finalAmount = (plan.amount ?? 0) * (quantity ?? 1);\n }\n initBody.amount = Math.max(Math.round(finalAmount), 5000);\n }\n } else {\n // One-Time Payment Flow\n if (amount === undefined || amount === null)\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Amount is required for one-time payments\",\n });\n initBody.amount = Math.round(amount);\n }\n\n return { initBody };\n })().catch((error: unknown) => {\n if (options.subscription?.operationHooks === undefined)\n throw normalizeInitializationError(error);\n throw error;\n });\n if (prepared.earlyResult !== undefined) return ctx.json(prepared.earlyResult);\n const initBody = prepared.initBody;\n const operation =\n plan !== undefined && options.subscription?.operationHooks !== undefined\n ? {\n actor: { id: user.id },\n referenceId,\n kind: \"initialize\" as const,\n subscription:\n subscriptionId !== undefined\n ? await createBillingStore(ctx).findSubscriptionById(subscriptionId)\n : await createBillingStore(ctx).findCurrentSubscription(referenceId, groupId),\n intent: {\n plan: plan.name.toLowerCase(),\n amount: initBody.amount,\n currency: finalCurrency,\n interval: plan.interval,\n quantity: validatedQuantity,\n groupId,\n callbackURL,\n trialStart,\n trialEnd,\n },\n }\n : undefined;\n const execute = async (\n providerReference: string | undefined,\n setPhase: (phase: \"provider\" | \"persistence\" | \"completion\") => void,\n ): Promise<PaystackInitializeResult> => {\n if (providerReference !== undefined) initBody.reference = providerReference;\n try {\n const initRaw = await paystack?.transaction?.initialize({\n body: initBody as components[\"schemas\"][\"TransactionInitialize\"],\n });\n const sdkRes =\n unwrapSdkResult<components[\"schemas\"][\"TransactionInitializeResponse\"][\"data\"]>(\n initRaw,\n );\n\n if (providerReference !== undefined && sdkRes?.reference !== providerReference) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Provider reference does not match reserved operation.\",\n });\n }\n url = sdkRes?.authorization_url;\n reference = sdkRes?.reference;\n accessCode = sdkRes?.access_code;\n } catch (error: unknown) {\n throw normalizeInitializationError(error);\n }\n setPhase(\"persistence\");\n // 6. Record Transaction & Subscription\n await ctx.context.adapter.create({\n model: PAYSTACK_MODELS.transaction,\n data: {\n reference: reference ?? \"\",\n referenceId,\n userId: user.id,\n amount: initBody.amount ?? 0,\n currency: finalCurrency,\n status: \"pending\",\n plan: plan !== undefined ? plan.name.toLowerCase() : undefined,\n product: product !== undefined ? product.name.toLowerCase() : undefined,\n metadata: hasPaystackMetadata(extraMetadata)\n ? stringifyPaystackMetadata(extraMetadata)\n : undefined,\n createdAt: new Date(),\n updatedAt: new Date(),\n },\n });\n\n if (plan !== undefined) {\n const store = createBillingStore(ctx);\n const customer = await store.findCustomerByReference(\n referenceId === user.id ? \"user\" : \"organization\",\n referenceId,\n );\n let customerCode = customer?.customerCode;\n if (customerCode === undefined) {\n try {\n const legacy = await ctx.context.adapter.findOne<{\n paystackCustomerCode?: string | null;\n }>({\n model: referenceId === user.id ? \"user\" : \"organization\",\n where: [{ field: \"id\", value: referenceId }],\n select: [\"paystackCustomerCode\"],\n });\n customerCode = legacy?.paystackCustomerCode ?? undefined;\n if (customerCode !== undefined && customerCode !== null && customerCode !== \"\") {\n await store.saveCustomer(\n referenceId === user.id ? \"user\" : \"organization\",\n referenceId,\n customerCode,\n );\n }\n } catch {\n // Legacy customer columns are optional after the migration.\n }\n }\n\n await ctx.context.adapter.create<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n data: {\n plan: plan.name.toLowerCase(),\n groupId,\n referenceId,\n userId: user.id,\n customerCode,\n subscriptionCode: undefined,\n planCode: plan.planCode,\n transactionReference: reference ?? \"\",\n // Access remains incomplete until the tokenization charge succeeds.\n status: \"incomplete\",\n billingInterval: plan.interval ?? null,\n seats: quantity ?? 1,\n periodStart: new Date(),\n periodEnd: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // Default 30 days\n cancelAtPeriodEnd: false,\n trialStart,\n trialEnd,\n createdAt: new Date(),\n updatedAt: new Date(),\n },\n });\n }\n\n return ctx.json({\n kind: \"checkout\",\n url: url ?? \"\",\n reference: reference ?? \"\",\n accessCode: accessCode ?? \"\",\n redirect: true,\n ...(trial.granted && trialTokenizationCharge !== undefined\n ? {\n trial: {\n days: trial.requestedDays,\n tokenizationCharge: { amount: trialTokenizationCharge, currency: finalCurrency },\n },\n }\n : {}),\n } satisfies PaystackInitializeResult);\n };\n return operation !== undefined\n ? runSubscriptionOperation(ctx, options, operation, execute)\n : execute(undefined, () => undefined);\n },\n );\n};\n\nfunction getTrialTokenizationCharge(plan: PaystackPlan | undefined, currency: string): number {\n const configured = plan?.freeTrial?.tokenizationCharge;\n if (configured !== undefined) {\n if (!Number.isSafeInteger(configured) || configured <= 0) {\n throw new APIError(\"BAD_REQUEST\", {\n code: \"INVALID_TRIAL_TOKENIZATION_CHARGE\",\n message: \"freeTrial.tokenizationCharge must be a positive safe integer in minor units.\",\n });\n }\n return configured;\n }\n const documentedMinimums: Record<string, number> = {\n NGN: 5_000,\n GHS: 10,\n ZAR: 100,\n KES: 300,\n USD: 200,\n };\n const amount = documentedMinimums[currency.toUpperCase()];\n if (amount === undefined) {\n throw new APIError(\"BAD_REQUEST\", {\n code: \"TRIAL_TOKENIZATION_CHARGE_REQUIRED\",\n message: `Configure freeTrial.tokenizationCharge in minor units for ${currency}.`,\n });\n }\n return amount;\n}\n\n// Aliases for Client DX Parity\nexport const createSubscription = <P extends string = \"/create-subscription\">(\n options: AnyPaystackOptions,\n path: P = \"/create-subscription\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"POST\";\n body: z.ZodObject<\n {\n plan: z.ZodOptional<z.ZodString>;\n product: z.ZodOptional<z.ZodString>;\n amount: z.ZodOptional<z.ZodNumber>;\n currency: z.ZodOptional<z.ZodString>;\n email: z.ZodOptional<z.ZodString>;\n metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;\n referenceId: z.ZodOptional<z.ZodString>;\n subscriptionId: z.ZodOptional<z.ZodString>;\n callbackURL: z.ZodOptional<z.ZodString>;\n quantity: z.ZodOptional<z.ZodNumber>;\n scheduleAtPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n cancelAtPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n prorateAndCharge: z.ZodOptional<z.ZodBoolean>;\n confirmTrialTokenizationCharge: z.ZodOptional<z.ZodBoolean>;\n },\n z.core.$strip\n >;\n use: AuthMiddleware[];\n },\n PaystackInitializeResult | undefined\n> => initializeTransaction(options, path);\n\nexport const upgradeSubscription = <P extends string = \"/upgrade-subscription\">(\n options: AnyPaystackOptions,\n path: P = \"/upgrade-subscription\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"POST\";\n body: z.ZodObject<\n {\n plan: z.ZodOptional<z.ZodString>;\n product: z.ZodOptional<z.ZodString>;\n amount: z.ZodOptional<z.ZodNumber>;\n currency: z.ZodOptional<z.ZodString>;\n email: z.ZodOptional<z.ZodString>;\n metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;\n referenceId: z.ZodOptional<z.ZodString>;\n subscriptionId: z.ZodOptional<z.ZodString>;\n callbackURL: z.ZodOptional<z.ZodString>;\n quantity: z.ZodOptional<z.ZodNumber>;\n scheduleAtPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n cancelAtPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n prorateAndCharge: z.ZodOptional<z.ZodBoolean>;\n confirmTrialTokenizationCharge: z.ZodOptional<z.ZodBoolean>;\n },\n z.core.$strip\n >;\n use: AuthMiddleware[];\n },\n PaystackInitializeResult | undefined\n> => initializeTransaction(options, path);\n\nexport const cancelSubscription = <P extends string = \"/cancel-subscription\">(\n options: AnyPaystackOptions,\n path: P = \"/cancel-subscription\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"POST\";\n body: z.ZodObject<\n {\n referenceId: z.ZodOptional<z.ZodString>;\n subscriptionCode: z.ZodString;\n emailToken: z.ZodOptional<z.ZodString>;\n atPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n },\n z.core.$strip\n >;\n use: AuthMiddleware[];\n },\n {\n status: string;\n }\n> => disablePaystackSubscription(options, path);\n\nexport const restoreSubscription = <P extends string = \"/restore-subscription\">(\n options: AnyPaystackOptions,\n path: P = \"/restore-subscription\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"POST\";\n body: z.ZodObject<\n {\n referenceId: z.ZodOptional<z.ZodString>;\n subscriptionCode: z.ZodString;\n emailToken: z.ZodOptional<z.ZodString>;\n atPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n },\n z.core.$strip\n >;\n use: AuthMiddleware[];\n },\n {\n status: string;\n }\n> => enablePaystackSubscription(options, path);\n\nexport const verifyTransaction = <P extends string = \"/verify-transaction\">(\n options: AnyPaystackOptions,\n path: P = \"/verify-transaction\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"POST\";\n body: z.ZodObject<\n {\n reference: z.ZodString;\n },\n z.core.$strip\n >;\n use: AuthMiddleware[];\n },\n {\n status: string;\n reference: string;\n data: {\n id: number;\n domain: string;\n status: string;\n reference: string;\n receipt_number: string | null;\n amount: number;\n message: string | null;\n gateway_response: string;\n channel: string;\n currency: string;\n ip_address: string | null;\n metadata: (string | Record<string, never> | number) | null;\n log: {\n start_time: number;\n time_spent: number;\n attempts: number;\n errors: number;\n success: boolean;\n mobile: boolean;\n input: unknown[];\n history: {\n type: string;\n message: string;\n time: number;\n }[];\n } | null;\n fees: number | null;\n fees_split: unknown;\n authorization: {\n authorization_code?: string;\n bin?: string | null;\n last4?: string;\n exp_month?: string;\n exp_year?: string;\n channel?: string;\n card_type?: string;\n bank?: string;\n country_code?: string;\n brand?: string;\n reusable?: boolean;\n signature?: string;\n account_name?: string | null;\n receiver_bank_account_number?: string | null;\n receiver_bank?: string | null;\n };\n customer: {\n id: number;\n first_name: string | null;\n last_name: string | null;\n email: string;\n customer_code: string;\n phone: string | null;\n metadata: Record<string, never> | null;\n risk_action: string;\n international_format_phone?: string | null;\n };\n plan: (string | Record<string, never>) | null;\n split: Record<string, never> | null;\n order_id: unknown;\n paidAt: string | null;\n createdAt: string;\n requested_amount: number;\n pos_transaction_data: unknown;\n source: unknown;\n fees_breakdown: unknown;\n connect: unknown;\n transaction_date: string;\n plan_object: {\n id?: number;\n name?: string;\n plan_code?: string;\n description?: unknown;\n amount?: number;\n interval?: string;\n send_invoices?: boolean;\n send_sms?: boolean;\n currency?: string;\n };\n subaccount: Record<string, never> | null;\n };\n }\n> => {\n const verifyBodySchema = z.object({\n reference: z.string(),\n });\n\n const subscriptionOptions = options.subscription;\n const useMiddlewares: AuthMiddleware[] =\n subscriptionOptions?.enabled === true\n ? [\n sessionMiddleware,\n originCheckMiddleware,\n referenceMiddleware(options, \"verify-transaction\"),\n ]\n : [sessionMiddleware, originCheckMiddleware];\n\n return createAuthEndpoint(\n path,\n {\n method: \"POST\",\n body: verifyBodySchema,\n use: useMiddlewares,\n },\n async (ctx) => {\n const session = await getSessionFromCtx(ctx);\n const result = await reconcilePaystackTransaction(ctx as GenericEndpointContext, options, {\n reference: ctx.body.reference,\n source: \"browser\",\n actor:\n session !== undefined && session !== null\n ? {\n user: session.user as User,\n session: session.session,\n }\n : undefined,\n throwOnError: true,\n });\n\n if (!result.ok || result.data === null) {\n throw new APIError(\"BAD_REQUEST\", {\n code: result.error?.code ?? \"FAILED_TO_VERIFY_TRANSACTION\",\n message:\n result.error?.message ?? PAYSTACK_ERROR_CODES.FAILED_TO_VERIFY_TRANSACTION.message,\n status: result.error?.status,\n });\n }\n\n return ctx.json({\n status: result.status,\n reference: result.reference,\n data: result.data,\n });\n },\n );\n};\n\nexport const listSubscriptions = <P extends string = \"/list-subscriptions\">(\n options: AnyPaystackOptions,\n path: P = \"/list-subscriptions\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"GET\";\n query: z.ZodObject<\n {\n referenceId: z.ZodOptional<z.ZodString>;\n },\n z.core.$strip\n >;\n use: AuthMiddleware[];\n },\n {\n subscriptions: Subscription[];\n }\n> => {\n const listQuerySchema = z.object({\n referenceId: z.string().optional(),\n });\n\n const subscriptionOptions = options.subscription;\n const useMiddlewares: AuthMiddleware[] =\n subscriptionOptions?.enabled === true\n ? [\n sessionMiddleware,\n originCheckMiddleware,\n referenceMiddleware(options, \"list-subscriptions\"),\n ]\n : [sessionMiddleware, originCheckMiddleware];\n\n return createAuthEndpoint(\n path,\n {\n method: \"GET\",\n query: listQuerySchema,\n use: useMiddlewares,\n },\n async (ctx) => {\n if (subscriptionOptions?.enabled !== true) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Subscriptions are not enabled in the Paystack options.\",\n });\n }\n const session = await getSessionFromCtx(ctx);\n if (session === undefined || session === null) throw new APIError(\"UNAUTHORIZED\");\n const store = createBillingStore(ctx);\n const referenceIdPart = (ctx.context as Record<string, unknown>).referenceId as\n | string\n | undefined;\n const queryRefId =\n ctx.query?.referenceId ??\n (typeof ctx.request?.url === \"string\"\n ? (new URL(ctx.request.url).searchParams.get(\"referenceId\") ?? undefined)\n : undefined);\n const userId = (session.user as { id: string }).id;\n if (queryRefId !== undefined && queryRefId !== userId && referenceIdPart !== queryRefId) {\n await authorizeBillingReference(ctx, options, {\n user: session.user as User,\n session: session.session,\n referenceId: queryRefId,\n action: \"list-subscriptions\",\n });\n }\n const referenceId = queryRefId ?? referenceIdPart ?? userId;\n const res = await store.findSubscriptionsByReference(referenceId);\n return ctx.json({ subscriptions: res });\n },\n );\n};\n\nexport const listTransactions = <P extends string = \"/list-transactions\">(\n options: AnyPaystackOptions,\n path: P = \"/list-transactions\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"GET\";\n query: z.ZodObject<\n {\n referenceId: z.ZodOptional<z.ZodString>;\n },\n z.core.$strip\n >;\n use: AuthMiddleware[];\n },\n {\n transactions: PaystackTransaction[];\n }\n> => {\n const listQuerySchema = z.object({\n referenceId: z.string().optional(),\n });\n\n const subscriptionOptions = options.subscription;\n const useMiddlewares: AuthMiddleware[] =\n subscriptionOptions?.enabled === true\n ? [\n sessionMiddleware,\n originCheckMiddleware,\n referenceMiddleware(options, \"list-transactions\"),\n ]\n : [sessionMiddleware, originCheckMiddleware];\n\n return createAuthEndpoint(\n path,\n {\n method: \"GET\",\n query: listQuerySchema,\n use: useMiddlewares,\n },\n async (ctx) => {\n const session = await getSessionFromCtx(ctx);\n if (session === undefined || session === null) throw new APIError(\"UNAUTHORIZED\");\n const store = createBillingStore(ctx);\n const referenceIdPart = (ctx.context as Record<string, unknown>).referenceId as\n | string\n | undefined;\n const queryRefId =\n ctx.query?.referenceId ??\n (typeof ctx.request?.url === \"string\"\n ? (new URL(ctx.request.url).searchParams.get(\"referenceId\") ?? undefined)\n : undefined);\n const userId = (session.user as { id: string }).id;\n if (queryRefId !== undefined && queryRefId !== userId && referenceIdPart !== queryRefId) {\n await authorizeBillingReference(ctx, options, {\n user: session.user as User,\n session: session.session,\n referenceId: queryRefId,\n action: \"list-transactions\",\n });\n }\n const referenceId = queryRefId ?? referenceIdPart ?? userId;\n const transactions = await store.listTransactions(referenceId);\n return ctx.json({ transactions });\n },\n );\n};\n\nexport const disablePaystackSubscription = <P extends string = \"/disable-subscription\">(\n options: AnyPaystackOptions,\n path: P = \"/disable-subscription\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"POST\";\n body: z.ZodObject<\n {\n referenceId: z.ZodOptional<z.ZodString>;\n subscriptionCode: z.ZodString;\n emailToken: z.ZodOptional<z.ZodString>;\n atPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n },\n z.core.$strip\n >;\n use: AuthMiddleware[];\n },\n {\n status: string;\n }\n> => {\n const subscriptionOptions = options.subscription;\n const useMiddlewares: AuthMiddleware[] =\n subscriptionOptions?.enabled === true\n ? [\n sessionMiddleware,\n originCheckMiddleware,\n referenceMiddleware(options, \"disable-subscription\"),\n ]\n : [sessionMiddleware, originCheckMiddleware];\n\n return createAuthEndpoint(\n path,\n { method: \"POST\", body: enableDisableBodySchema, use: useMiddlewares },\n async (ctx) => {\n const { subscriptionCode, atPeriodEnd } = ctx.body;\n const paystack = getPaystackOps(options.paystackClient);\n try {\n const subCode = subscriptionCode;\n if (isLocalSubscriptionCode(subCode)) {\n const sub = await ctx.context.adapter.findOne<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"subscriptionCode\", value: subscriptionCode }],\n });\n\n if (sub !== null && sub !== undefined) {\n const now = new Date();\n const immediate = atPeriodEnd === false;\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.subscription,\n update: {\n status: immediate ? \"canceled\" : \"active\",\n cancelAtPeriodEnd: !immediate,\n cancelAt: immediate ? null : (sub.periodEnd ?? null),\n canceledAt: now,\n endedAt: immediate ? now : null,\n updatedAt: now,\n },\n where: [{ field: \"id\", value: sub.id }],\n });\n return ctx.json({ status: \"success\" });\n }\n throw new APIError(\"BAD_REQUEST\", { message: \"Subscription not found\" });\n }\n\n const storedSubscription =\n await createBillingStore(ctx).findSubscriptionByCode(subscriptionCode);\n const storedCredentials = storedSubscription\n ? await readPaystackPaymentCredentials(\n ctx.context.adapter,\n options,\n storedSubscription.id,\n )\n : null;\n let emailToken = ctx.body.emailToken ?? storedCredentials?.emailToken;\n let nextPaymentDate: string | undefined;\n\n try {\n const raw = await paystack?.subscription?.fetch(subscriptionCode);\n const fetchRes =\n unwrapSdkResult<components[\"schemas\"][\"SubscriptionListResponseArray\"]>(raw);\n\n if (fetchRes !== undefined && fetchRes !== null) {\n emailToken ??= fetchRes.email_token ?? undefined;\n nextPaymentDate = fetchRes.next_payment_date ?? undefined;\n }\n } catch {\n // ignore fetch failure\n }\n\n if (emailToken === undefined || emailToken === null || emailToken === \"\") {\n try {\n const raw = await paystack?.subscription?.manageLink(subscriptionCode);\n const linkRes = unwrapSdkResult<{ link: string }>(raw);\n const link = linkRes?.link;\n if (link !== undefined && link !== null && link !== \"\") {\n emailToken = tryGetEmailTokenFromSubscriptionManageLink(link);\n }\n } catch {\n // ignore\n }\n }\n\n if (emailToken === undefined || emailToken === null || emailToken === \"\") {\n throw new Error(\"Could not retrieve email_token for subscription disable.\");\n }\n\n if (storedSubscription) {\n await savePaystackPaymentCredentials(\n ctx.context.adapter,\n options,\n storedSubscription.id,\n {\n emailToken,\n },\n );\n }\n\n await paystack?.subscription?.disable({\n body: { code: subscriptionCode, token: emailToken },\n });\n\n const periodEnd =\n nextPaymentDate !== undefined && nextPaymentDate !== null && nextPaymentDate !== \"\"\n ? new Date(nextPaymentDate)\n : undefined;\n\n const sub = await ctx.context.adapter.findOne<Subscription>({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"subscriptionCode\", value: subscriptionCode }],\n });\n\n if (sub !== undefined && sub !== null) {\n const now = new Date();\n const immediate = atPeriodEnd === false;\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.subscription,\n update: {\n status: immediate ? \"canceled\" : \"active\",\n cancelAtPeriodEnd: !immediate,\n cancelAt: immediate ? null : (periodEnd ?? sub.periodEnd ?? null),\n canceledAt: now,\n endedAt: immediate ? now : null,\n periodEnd,\n updatedAt: now,\n },\n where: [{ field: \"id\", value: sub.id }],\n });\n } else {\n ctx.context.logger.warn(\n `Could not find subscription with code ${subscriptionCode} to disable`,\n );\n }\n\n return ctx.json({ status: \"success\" });\n } catch (error: unknown) {\n ctx.context.logger.error(\"Failed to disable subscription\", error);\n const errorMessage =\n error instanceof Error\n ? error.message\n : PAYSTACK_ERROR_CODES.FAILED_TO_DISABLE_SUBSCRIPTION.message;\n throw new APIError(\"BAD_REQUEST\", {\n code: \"FAILED_TO_DISABLE_SUBSCRIPTION\",\n message: errorMessage,\n });\n }\n },\n );\n};\n\nexport const enablePaystackSubscription = <P extends string = \"/enable-subscription\">(\n options: AnyPaystackOptions,\n path: P = \"/enable-subscription\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"POST\";\n body: z.ZodObject<\n {\n referenceId: z.ZodOptional<z.ZodString>;\n subscriptionCode: z.ZodString;\n emailToken: z.ZodOptional<z.ZodString>;\n atPeriodEnd: z.ZodOptional<z.ZodBoolean>;\n },\n z.core.$strip\n >;\n use: AuthMiddleware[];\n },\n {\n status: string;\n }\n> => {\n const subscriptionOptions = options.subscription;\n const useMiddlewares: AuthMiddleware[] =\n subscriptionOptions?.enabled === true\n ? [\n sessionMiddleware,\n originCheckMiddleware,\n referenceMiddleware(options, \"enable-subscription\"),\n ]\n : [sessionMiddleware, originCheckMiddleware];\n\n return createAuthEndpoint(\n path,\n { method: \"POST\", body: enableDisableBodySchema, use: useMiddlewares },\n async (ctx) => {\n const { subscriptionCode } = ctx.body;\n const paystack = getPaystackOps(options.paystackClient);\n try {\n const storedSubscription =\n await createBillingStore(ctx).findSubscriptionByCode(subscriptionCode);\n const storedCredentials = storedSubscription\n ? await readPaystackPaymentCredentials(\n ctx.context.adapter,\n options,\n storedSubscription.id,\n )\n : null;\n let emailToken = ctx.body.emailToken ?? storedCredentials?.emailToken;\n if (emailToken === undefined || emailToken === null || emailToken === \"\") {\n try {\n const raw = await paystack?.subscription?.fetch(subscriptionCode);\n const fetchRes =\n unwrapSdkResult<components[\"schemas\"][\"SubscriptionListResponseArray\"]>(raw);\n if (fetchRes !== undefined && fetchRes !== null) {\n emailToken = fetchRes.email_token ?? undefined;\n }\n } catch {\n // ignore\n }\n }\n\n if (emailToken === undefined || emailToken === null || emailToken === \"\") {\n try {\n const raw = await paystack?.subscription?.manageLink(subscriptionCode);\n const linkRes = unwrapSdkResult<{ link: string }>(raw);\n const link = linkRes?.link;\n if (link !== undefined && link !== null && link !== \"\") {\n emailToken = tryGetEmailTokenFromSubscriptionManageLink(link);\n }\n } catch {\n // ignore\n }\n }\n\n if (emailToken === undefined || emailToken === null || emailToken === \"\") {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"Could not retrieve email_token for subscription enable.\",\n });\n }\n\n if (storedSubscription) {\n await savePaystackPaymentCredentials(\n ctx.context.adapter,\n options,\n storedSubscription.id,\n {\n emailToken,\n },\n );\n }\n\n await paystack?.subscription?.enable({\n body: { code: subscriptionCode, token: emailToken },\n });\n\n // Update local status immediately\n await ctx.context.adapter.update({\n model: PAYSTACK_MODELS.subscription,\n update: {\n status: \"active\",\n cancelAtPeriodEnd: false,\n cancelAt: null,\n canceledAt: null,\n endedAt: null,\n updatedAt: new Date(),\n },\n where: [{ field: \"subscriptionCode\", value: subscriptionCode }],\n });\n\n return ctx.json({ status: \"success\" });\n } catch (error: unknown) {\n ctx.context.logger.error(\"Failed to enable subscription\", error);\n const errorMessage =\n error instanceof Error\n ? error.message\n : PAYSTACK_ERROR_CODES.FAILED_TO_ENABLE_SUBSCRIPTION.message;\n throw new APIError(\"BAD_REQUEST\", {\n code: \"FAILED_TO_ENABLE_SUBSCRIPTION\",\n message: errorMessage,\n });\n }\n },\n );\n};\n\nexport const getSubscriptionManageLink = <P extends string = \"/subscription-manage-link\">(\n options: AnyPaystackOptions,\n path: P = \"/subscription-manage-link\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"GET\";\n query: z.ZodObject<\n {\n subscriptionCode: z.ZodString;\n },\n z.core.$strip\n >;\n use: AuthMiddleware[];\n },\n {\n link: string | null;\n }\n> => {\n const manageLinkQuerySchema = z.object({\n subscriptionCode: z.string(),\n });\n const subscriptionOptions = options.subscription;\n const useMiddlewares: AuthMiddleware[] =\n subscriptionOptions?.enabled === true\n ? [\n sessionMiddleware,\n originCheckMiddleware,\n referenceMiddleware(options, \"get-subscription-manage-link\"),\n ]\n : [sessionMiddleware, originCheckMiddleware];\n\n const handler = async (ctx: GenericEndpointContext) => {\n const { subscriptionCode } = ctx.query;\n\n if (isLocalSubscriptionCode(subscriptionCode as string)) {\n return ctx.json({ link: null, message: \"Local subscriptions cannot be managed on Paystack\" });\n }\n\n const paystack = getPaystackOps(options.paystackClient);\n try {\n const raw = await paystack?.subscription?.manageLink(subscriptionCode as string);\n const res = unwrapSdkResult<{ link: string }>(raw);\n return ctx.json({ link: res?.link || null });\n } catch (error: unknown) {\n ctx.context.logger.error(\"Failed to get subscription manage link\", error);\n const errorMessage =\n error instanceof Error ? error.message : \"Failed to get subscription manage link\";\n throw new APIError(\"BAD_REQUEST\", {\n message: errorMessage,\n });\n }\n };\n\n return createAuthEndpoint(\n path,\n {\n method: \"GET\",\n query: manageLinkQuerySchema,\n use: useMiddlewares,\n },\n handler,\n );\n};\n\nexport const listProducts = <P extends string = \"/list-products\">(\n _options: AnyPaystackOptions,\n path: P = \"/list-products\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"GET\";\n metadata: {\n openapi: {\n operationId: string;\n };\n };\n },\n {\n products: PaystackProduct[];\n }\n> => {\n return createAuthEndpoint(\n path,\n {\n method: \"GET\",\n metadata: {\n openapi: {\n operationId: \"listPaystackProducts\",\n },\n },\n },\n async (ctx) => {\n const products = await listStoredProducts(ctx);\n return ctx.json({ products });\n },\n );\n};\n\nexport const listPlans = <P extends string = \"/list-plans\">(\n _options: AnyPaystackOptions,\n path: P = \"/list-plans\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"GET\";\n metadata: {\n scope: \"server\";\n };\n use: AuthMiddleware[];\n },\n {\n plans: PaystackPlan[];\n }\n> => {\n return createAuthEndpoint(\n path,\n {\n method: \"GET\",\n metadata: { ...HIDE_METADATA },\n use: [sessionMiddleware],\n },\n async (ctx) => {\n try {\n const plans = await listStoredPlans(ctx);\n return ctx.json({ plans });\n } catch (error: unknown) {\n ctx.context.logger.error(\"Failed to list plans\", error);\n const errorMessage = error instanceof Error ? error.message : \"Failed to list plans\";\n throw new APIError(\"BAD_REQUEST\", {\n message: errorMessage,\n });\n }\n },\n );\n};\n\nexport const getConfig = <P extends string = \"/get-config\">(\n options: AnyPaystackOptions,\n path: P = \"/get-config\" as P,\n): StrictEndpoint<\n P,\n {\n method: \"GET\";\n metadata: {\n openapi: {\n operationId: string;\n };\n };\n },\n {\n plans: PaystackPlan[];\n products: PaystackProduct[];\n }\n> => {\n return createAuthEndpoint(\n path,\n {\n method: \"GET\",\n metadata: {\n openapi: {\n operationId: \"getPaystackConfig\",\n },\n },\n },\n async (ctx: GenericEndpointContext) => {\n return ctx.json(await getConfiguredCatalog(options));\n },\n );\n};\n\nexport { PAYSTACK_ERROR_CODES };\n","import { mergeSchema, type BetterAuthPluginDBSchema, type DBFieldAttribute } from \"better-auth/db\";\n\nimport type { PaystackOptions } from \"./types.ts\";\n\ntype PluginSchemaTable<TableName extends string, FieldName extends string> = Record<\n TableName,\n {\n fields: Record<FieldName, DBFieldAttribute>;\n disableMigration?: boolean;\n modelName?: string;\n }\n>;\n\ntype TransactionsSchema = PluginSchemaTable<\n \"paystackTransaction\",\n | \"reference\"\n | \"paystackId\"\n | \"referenceId\"\n | \"userId\"\n | \"amount\"\n | \"currency\"\n | \"status\"\n | \"plan\"\n | \"product\"\n | \"metadata\"\n | \"createdAt\"\n | \"updatedAt\"\n>;\n\ntype WebhookEventsSchema = PluginSchemaTable<\n \"paystackWebhookEvent\",\n | \"eventId\"\n | \"eventType\"\n | \"reference\"\n | \"payload\"\n | \"status\"\n | \"processedAt\"\n | \"createdAt\"\n | \"updatedAt\"\n>;\n\ntype SubscriptionsSchema = PluginSchemaTable<\n \"paystackSubscription\",\n | \"plan\"\n | \"referenceId\"\n | \"userId\"\n | \"customerCode\"\n | \"subscriptionCode\"\n | \"transactionReference\"\n | \"planCode\"\n | \"status\"\n | \"periodStart\"\n | \"periodEnd\"\n | \"trialStart\"\n | \"trialEnd\"\n | \"cancelAtPeriodEnd\"\n | \"cancelAt\"\n | \"canceledAt\"\n | \"endedAt\"\n | \"billingInterval\"\n | \"groupId\"\n | \"seats\"\n | \"pendingPlan\"\n | \"createdAt\"\n | \"updatedAt\"\n>;\n\ntype CustomerSchema = PluginSchemaTable<\n \"paystackCustomer\",\n | \"referenceType\"\n | \"referenceId\"\n | \"referenceKey\"\n | \"customerCode\"\n | \"email\"\n | \"createdAt\"\n | \"updatedAt\"\n>;\n\ntype PaymentCredentialsSchema = PluginSchemaTable<\n \"paystackPaymentCredential\",\n | \"subscriptionId\"\n | \"authorizationCodeEncrypted\"\n | \"emailTokenEncrypted\"\n | \"createdAt\"\n | \"updatedAt\"\n>;\n\ntype UserSchema = PluginSchemaTable<\"user\", never>;\n\ntype OrganizationSchema = PluginSchemaTable<\"organization\", \"email\">;\n\ntype ProductsSchema = PluginSchemaTable<\n \"paystackProduct\",\n | \"name\"\n | \"description\"\n | \"price\"\n | \"currency\"\n | \"quantity\"\n | \"unlimited\"\n | \"paystackId\"\n | \"slug\"\n | \"metadata\"\n | \"createdAt\"\n | \"updatedAt\"\n>;\n\ntype PlansSchema = PluginSchemaTable<\n \"paystackPlan\",\n | \"name\"\n | \"description\"\n | \"amount\"\n | \"currency\"\n | \"interval\"\n | \"group\"\n | \"planCode\"\n | \"paystackId\"\n | \"metadata\"\n | \"createdAt\"\n | \"updatedAt\"\n>;\n\nexport type PaystackPluginSchema = SubscriptionsSchema &\n TransactionsSchema &\n CustomerSchema &\n PaymentCredentialsSchema &\n UserSchema &\n OrganizationSchema &\n ProductsSchema &\n PlansSchema &\n WebhookEventsSchema;\n\nconst transactionsSchema: TransactionsSchema = {\n paystackTransaction: {\n fields: {\n reference: {\n type: \"string\",\n required: true,\n unique: true,\n },\n paystackId: {\n type: \"string\",\n required: false,\n },\n referenceId: {\n type: \"string\",\n required: true,\n index: true,\n },\n userId: {\n type: \"string\",\n required: true,\n index: true,\n },\n amount: {\n type: \"number\",\n required: true,\n },\n currency: {\n type: \"string\",\n required: true,\n },\n status: {\n type: \"string\",\n required: true,\n },\n plan: {\n type: \"string\",\n required: false,\n },\n product: {\n type: \"string\",\n required: false,\n },\n metadata: {\n type: \"string\",\n required: false,\n },\n createdAt: {\n type: \"date\",\n required: true,\n },\n updatedAt: {\n type: \"date\",\n required: true,\n },\n },\n },\n} satisfies BetterAuthPluginDBSchema;\n\nexport const transactions: typeof transactionsSchema = transactionsSchema;\n\nconst subscriptionsSchema: SubscriptionsSchema = {\n paystackSubscription: {\n fields: {\n plan: {\n type: \"string\",\n required: true,\n index: true,\n },\n referenceId: {\n type: \"string\",\n required: true,\n index: true,\n },\n userId: {\n type: \"string\",\n required: true,\n index: true,\n },\n customerCode: {\n type: \"string\",\n required: false,\n index: true,\n },\n subscriptionCode: {\n type: \"string\",\n required: false,\n unique: true,\n },\n transactionReference: {\n type: \"string\",\n required: false,\n index: true,\n },\n planCode: {\n type: \"string\",\n required: false,\n },\n status: {\n type: \"string\",\n defaultValue: \"incomplete\",\n },\n periodStart: {\n type: \"date\",\n required: false,\n },\n periodEnd: {\n type: \"date\",\n required: false,\n },\n trialStart: {\n type: \"date\",\n required: false,\n },\n trialEnd: {\n type: \"date\",\n required: false,\n },\n cancelAtPeriodEnd: {\n type: \"boolean\",\n required: false,\n defaultValue: false,\n },\n cancelAt: {\n type: \"date\",\n required: false,\n },\n canceledAt: {\n type: \"date\",\n required: false,\n },\n endedAt: {\n type: \"date\",\n required: false,\n },\n billingInterval: {\n type: \"string\",\n required: false,\n },\n groupId: {\n type: \"string\",\n required: false,\n },\n seats: {\n type: \"number\",\n required: false,\n },\n pendingPlan: {\n type: \"string\",\n required: false,\n },\n createdAt: {\n type: \"date\",\n required: true,\n },\n updatedAt: {\n type: \"date\",\n required: true,\n },\n },\n },\n} satisfies BetterAuthPluginDBSchema;\n\nexport const subscriptions: typeof subscriptionsSchema = subscriptionsSchema;\n\nconst customersSchema: CustomerSchema = {\n paystackCustomer: {\n fields: {\n referenceType: { type: \"string\", required: true },\n referenceId: { type: \"string\", required: true, index: true },\n // Better Auth schema generation cannot express a portable composite unique\n // index, so this provider-owned key enforces (type, id) uniqueness.\n referenceKey: { type: \"string\", required: true, unique: true },\n customerCode: { type: \"string\", required: true, unique: true },\n email: { type: \"string\", required: false },\n createdAt: { type: \"date\", required: true },\n updatedAt: { type: \"date\", required: true },\n },\n },\n} satisfies BetterAuthPluginDBSchema;\n\nexport const customers: typeof customersSchema = customersSchema;\n\nconst paymentCredentialsSchema: PaymentCredentialsSchema = {\n paystackPaymentCredential: {\n fields: {\n subscriptionId: { type: \"string\", required: true, unique: true, index: true },\n authorizationCodeEncrypted: { type: \"string\", required: false },\n emailTokenEncrypted: { type: \"string\", required: false },\n createdAt: { type: \"date\", required: true },\n updatedAt: { type: \"date\", required: true },\n },\n },\n} satisfies BetterAuthPluginDBSchema;\n\nexport const paymentCredentials: typeof paymentCredentialsSchema = paymentCredentialsSchema;\n\nconst userSchema: UserSchema = {\n user: {\n fields: {},\n },\n} satisfies BetterAuthPluginDBSchema;\n\nexport const user: typeof userSchema = userSchema;\n\nconst organizationSchema: OrganizationSchema = {\n organization: {\n fields: {\n email: {\n type: \"string\",\n required: false,\n },\n },\n },\n} satisfies BetterAuthPluginDBSchema;\n\nexport const organization: typeof organizationSchema = organizationSchema;\n\nconst productsSchema: ProductsSchema = {\n paystackProduct: {\n fields: {\n name: {\n type: \"string\",\n required: true,\n },\n description: {\n type: \"string\",\n required: false,\n },\n price: {\n type: \"number\",\n required: true,\n },\n currency: {\n type: \"string\",\n required: true,\n },\n quantity: {\n type: \"number\",\n required: false,\n defaultValue: 0,\n },\n unlimited: {\n type: \"boolean\",\n required: false,\n defaultValue: true,\n },\n paystackId: {\n type: \"string\",\n required: false,\n unique: true,\n },\n slug: {\n type: \"string\",\n required: true,\n unique: true,\n },\n metadata: {\n type: \"string\",\n required: false,\n },\n createdAt: {\n type: \"date\",\n required: true,\n },\n updatedAt: {\n type: \"date\",\n required: true,\n },\n },\n },\n} satisfies BetterAuthPluginDBSchema;\n\nexport const products: typeof productsSchema = productsSchema;\n\nconst plansSchema: PlansSchema = {\n paystackPlan: {\n fields: {\n name: {\n type: \"string\",\n required: true,\n },\n description: {\n type: \"string\",\n required: false,\n },\n amount: {\n type: \"number\",\n required: true,\n },\n currency: {\n type: \"string\",\n required: true,\n },\n interval: {\n type: \"string\",\n required: true,\n },\n group: {\n type: \"string\",\n required: false,\n },\n planCode: {\n type: \"string\",\n required: true,\n unique: true,\n },\n paystackId: {\n type: \"string\",\n required: true,\n unique: true,\n },\n metadata: {\n type: \"string\",\n required: false,\n },\n createdAt: {\n type: \"date\",\n required: true,\n },\n updatedAt: {\n type: \"date\",\n required: true,\n },\n },\n },\n} satisfies BetterAuthPluginDBSchema;\n\nexport const plans: typeof plansSchema = plansSchema;\n\nconst webhookEventsSchema: WebhookEventsSchema = {\n paystackWebhookEvent: {\n fields: {\n eventId: {\n type: \"string\",\n required: true,\n unique: true,\n },\n eventType: {\n type: \"string\",\n required: true,\n index: true,\n },\n reference: {\n type: \"string\",\n required: false,\n index: true,\n },\n payload: {\n type: \"string\",\n required: true,\n },\n status: {\n type: \"string\",\n required: true,\n defaultValue: \"pending\",\n index: true,\n },\n processedAt: {\n type: \"date\",\n required: false,\n },\n createdAt: {\n type: \"date\",\n required: true,\n },\n updatedAt: {\n type: \"date\",\n required: true,\n },\n },\n },\n} satisfies BetterAuthPluginDBSchema;\n\nexport const webhookEvents: typeof webhookEventsSchema = webhookEventsSchema;\n\nconst paystackPluginSchemaDefinition: PaystackPluginSchema = {\n ...subscriptions,\n ...transactions,\n ...customers,\n ...paymentCredentials,\n ...user,\n ...organization,\n ...products,\n ...plans,\n ...webhookEvents,\n} satisfies BetterAuthPluginDBSchema;\n\nexport const paystackPluginSchema: typeof paystackPluginSchemaDefinition =\n paystackPluginSchemaDefinition;\n\nexport const getSchema = (options: PaystackOptions): BetterAuthPluginDBSchema => {\n let baseSchema: BetterAuthPluginDBSchema;\n const optionSchema = options.schema as Parameters<typeof mergeSchema>[1];\n\n if (options.subscription?.enabled === true) {\n baseSchema = {\n ...subscriptions,\n ...transactions,\n ...customers,\n ...paymentCredentials,\n ...user,\n ...products,\n ...plans,\n ...webhookEvents,\n };\n } else {\n baseSchema = {\n ...user,\n ...transactions,\n ...customers,\n ...paymentCredentials,\n ...products,\n ...plans,\n ...webhookEvents,\n };\n }\n\n // Add organization schema if organization support is enabled\n if (options.organization?.enabled === true) {\n baseSchema = {\n ...baseSchema,\n ...organization,\n };\n }\n\n if (options.schema !== undefined && \"subscription\" in options.schema) {\n const { subscription: _subscription, ...restSchema } = optionSchema ?? {};\n return mergeSchema(baseSchema, restSchema);\n }\n\n return mergeSchema(baseSchema, optionSchema);\n};\n","import type { GenericEndpointContext } from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\n\nimport { createBillingStore } from \"./billing-store.ts\";\nimport { createRenewalMetadata, stringifyPaystackMetadata } from \"./metadata.ts\";\nimport { readPaystackPaymentCredentials } from \"./payment-credentials.ts\";\nimport { createPaystackAdapter } from \"./paystack-sdk.ts\";\nimport type {\n AnyPaystackOptions,\n ChargeRecurringSubscriptionInput,\n ChargeRecurringSubscriptionResult,\n PaystackSyncResult,\n PaystackChargeAuthorizationResponse,\n} from \"./types.ts\";\nimport { calculatePlanAmount } from \"./utils.ts\";\nimport { getNextPeriodEnd, getPlans, validateMinAmount } from \"./utils.ts\";\n\nexport async function syncPaystackProducts(\n ctx: GenericEndpointContext,\n options: AnyPaystackOptions,\n): Promise<PaystackSyncResult> {\n const paystack = createPaystackAdapter(options.paystackClient);\n const store = createBillingStore(ctx);\n try {\n const productsData = await paystack.listProducts();\n\n if (!Array.isArray(productsData)) {\n return { status: \"success\", count: 0 };\n }\n\n for (const product of productsData) {\n const paystackId = String(product.id);\n const productFields = {\n name: product.name ?? \"\",\n description: product.description ?? \"\",\n price: product.price ?? 0,\n currency: product.currency ?? \"\",\n quantity: product.quantity ?? 0,\n unlimited:\n product.unlimited !== undefined &&\n product.unlimited !== null &&\n product.unlimited !== false,\n paystackId,\n slug:\n (product as { slug?: string }).slug ??\n product.name?.toLowerCase().replace(/\\s+/g, \"-\") ??\n \"\",\n metadata: stringifyPaystackMetadata((product as { metadata?: unknown }).metadata),\n updatedAt: new Date(),\n };\n\n await store.upsertProductByPaystackId(paystackId, {\n ...productFields,\n createdAt: new Date(),\n });\n }\n\n return { status: \"success\", count: productsData.length };\n } catch (error: unknown) {\n ctx.context.logger.error(\"Failed to sync products\", error);\n const errorMessage = error instanceof Error ? error.message : \"Failed to sync products\";\n throw new APIError(\"BAD_REQUEST\", {\n message: errorMessage,\n });\n }\n}\n\nexport async function syncPaystackPlans(\n ctx: GenericEndpointContext,\n options: AnyPaystackOptions,\n): Promise<PaystackSyncResult> {\n const paystack = createPaystackAdapter(options.paystackClient);\n const store = createBillingStore(ctx);\n try {\n const plansData = await paystack.listPlans();\n\n if (!Array.isArray(plansData)) {\n return { status: \"success\", count: 0 };\n }\n\n for (const plan of plansData) {\n const paystackId = String(plan.id);\n const planData = {\n name: plan.name ?? \"\",\n description: typeof plan.description === \"string\" ? plan.description : \"\",\n amount: plan.amount ?? 0,\n currency: plan.currency ?? \"\",\n interval: plan.interval ?? \"\",\n planCode: plan.plan_code ?? \"\",\n paystackId,\n metadata: stringifyPaystackMetadata((plan as { metadata?: unknown }).metadata),\n updatedAt: new Date(),\n };\n\n await store.upsertPlanByPaystackId(paystackId, {\n ...planData,\n createdAt: new Date(),\n });\n }\n\n return { status: \"success\", count: plansData.length };\n } catch (error: unknown) {\n ctx.context.logger.error(\"Failed to sync plans\", error);\n const errorMessage = error instanceof Error ? error.message : \"Failed to sync plans\";\n throw new APIError(\"BAD_REQUEST\", {\n message: errorMessage,\n });\n }\n}\n\nexport async function chargeSubscriptionRenewal(\n ctx: GenericEndpointContext,\n options: AnyPaystackOptions,\n input: ChargeRecurringSubscriptionInput,\n): Promise<ChargeRecurringSubscriptionResult> {\n const { subscriptionId } = input;\n const store = createBillingStore(ctx);\n const subscription = await store.findSubscriptionById(subscriptionId);\n\n if (subscription === undefined || subscription === null) {\n throw new APIError(\"NOT_FOUND\", { message: \"Subscription not found\" });\n }\n\n const credentials = await readPaystackPaymentCredentials(\n ctx.context.adapter,\n options,\n subscription.id,\n );\n if (\n credentials?.authorizationCode === undefined ||\n credentials.authorizationCode === null ||\n credentials.authorizationCode === \"\"\n ) {\n throw new APIError(\"BAD_REQUEST\", {\n message: \"No authorization code found for this subscription\",\n });\n }\n\n const plans = await getPlans(options.subscription);\n const plan = plans.find(\n (candidate) => candidate.name.toLowerCase() === subscription.plan.toLowerCase(),\n );\n\n if (plan === undefined || plan === null) {\n throw new APIError(\"NOT_FOUND\", { message: \"Plan not found\" });\n }\n\n const amount = calculatePlanAmount(plan, subscription.seats ?? 1);\n if (amount === undefined || amount === null) {\n throw new APIError(\"BAD_REQUEST\", { message: \"Plan amount is not defined\" });\n }\n\n let email: string | undefined;\n let billingUserId = subscription.userId;\n const referenceId = subscription.referenceId;\n if (referenceId !== undefined && referenceId !== null && referenceId !== \"\") {\n const user = await store.findUser(referenceId);\n if (user !== undefined && user !== null) {\n email = user.email;\n billingUserId = user.id;\n } else if (options.organization?.enabled === true) {\n const ownerMember = await store.findOrganizationOwner(referenceId);\n if (ownerMember !== undefined && ownerMember !== null) {\n const ownerUser = await store.findUser(ownerMember.userId);\n email = ownerUser?.email;\n billingUserId = ownerUser?.id ?? ownerMember.userId;\n }\n }\n }\n\n if (email === undefined || email === null || email === \"\") {\n throw new APIError(\"NOT_FOUND\", { message: \"User email not found\" });\n }\n\n const finalCurrency = plan.currency ?? \"NGN\";\n if (!validateMinAmount(amount, finalCurrency)) {\n throw new APIError(\"BAD_REQUEST\", {\n message: `Amount ${amount} is less than the minimum required for ${finalCurrency}.`,\n status: 400,\n });\n }\n\n const paystack = createPaystackAdapter(options.paystackClient);\n const renewalMetadata = createRenewalMetadata({\n subscriptionId,\n referenceId,\n });\n const serializedRenewalMetadata = stringifyPaystackMetadata(renewalMetadata);\n\n const chargeData = await paystack.chargeAuthorization({\n email,\n amount,\n authorization_code: credentials.authorizationCode,\n reference: `rec_${subscription.id}_${Date.now()}`,\n metadata: serializedRenewalMetadata,\n });\n\n const typedChargeData = chargeData as PaystackChargeAuthorizationResponse;\n if (typedChargeData?.status === \"success\" && typedChargeData.reference !== undefined) {\n const now = new Date();\n const nextPeriodEnd = getNextPeriodEnd(now, plan.interval ?? \"monthly\");\n\n await store.createTransaction({\n reference: typedChargeData.reference,\n paystackId:\n typedChargeData.id !== undefined && typedChargeData.id !== null\n ? String(typedChargeData.id)\n : undefined,\n referenceId,\n userId: billingUserId,\n amount: typedChargeData.amount,\n currency: typedChargeData.currency,\n status: \"success\",\n plan: plan.name.toLowerCase(),\n metadata: serializedRenewalMetadata,\n createdAt: now,\n updatedAt: now,\n });\n\n await store.updateSubscription(subscription.id, {\n periodStart: now,\n periodEnd: nextPeriodEnd,\n updatedAt: now,\n transactionReference: typedChargeData.reference,\n });\n\n return { status: \"success\", data: typedChargeData };\n }\n\n return { status: \"failed\", data: typedChargeData };\n}\n","import type { GenericEndpointContext } from \"better-auth\";\n\nimport type { createBillingStoreFromAdapter } from \"./billing-store.ts\";\nimport { LEGACY_PAYSTACK_MODELS, PAYSTACK_MODELS } from \"./models.ts\";\nimport { savePaystackPaymentCredentials } from \"./payment-credentials.ts\";\nimport type { AnyPaystackOptions } from \"./types.ts\";\n\ntype Adapter = Parameters<typeof createBillingStoreFromAdapter>[0];\ntype LegacyRecord = Record<string, unknown> & { id?: string | number };\n\nexport interface PaystackSchemaMigrationFailure {\n kind: \"subscription\" | \"customer\" | \"credential\";\n id: string;\n message: string;\n}\n\nexport interface PaystackSchemaMigrationReport {\n status: \"complete\" | \"partial\";\n subscriptions: { migrated: number; skipped: number; failed: number };\n customers: { migrated: number; skipped: number; failed: number };\n credentials: { migrated: number; skipped: number; failed: number };\n skipped: number;\n failures: PaystackSchemaMigrationFailure[];\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === \"string\" && value !== \"\" ? value : undefined;\n}\n\nfunction asIdentifier(value: unknown): string | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) return String(value);\n return asString(value);\n}\n\nfunction asDate(value: unknown, fallback: Date): Date {\n if (value instanceof Date) return value;\n if (typeof value === \"string\" || typeof value === \"number\") {\n const date = new Date(value);\n if (!Number.isNaN(date.getTime())) return date;\n }\n return fallback;\n}\n\nfunction asOptionalDate(value: unknown): Date | null | undefined {\n if (value === null) return null;\n if (value === undefined) return undefined;\n if (value instanceof Date) return value;\n if (typeof value === \"string\" || typeof value === \"number\") {\n const date = new Date(value);\n if (!Number.isNaN(date.getTime())) return date;\n }\n return undefined;\n}\n\nasync function findManySafely(adapter: Adapter, model: string): Promise<LegacyRecord[]> {\n try {\n return (await adapter.findMany<LegacyRecord>({ model })) ?? [];\n } catch {\n // The legacy table may already have been removed in a fresh installation.\n return [];\n }\n}\n\nfunction migrationData(legacy: LegacyRecord): Record<string, unknown> {\n const now = new Date();\n const referenceId = asIdentifier(legacy.referenceId) ?? asIdentifier(legacy.userId) ?? \"\";\n const id = asIdentifier(legacy.id);\n return {\n ...(id !== undefined ? { id } : {}),\n plan: asString(legacy.plan) ?? \"\",\n referenceId,\n userId: asIdentifier(legacy.userId) ?? referenceId,\n customerCode:\n asString(legacy.customerCode) ?? asString(legacy.paystackCustomerCode) ?? undefined,\n subscriptionCode:\n asString(legacy.subscriptionCode) ?? asString(legacy.paystackSubscriptionCode) ?? undefined,\n transactionReference:\n asString(legacy.transactionReference) ??\n asString(legacy.paystackTransactionReference) ??\n undefined,\n planCode: asString(legacy.planCode) ?? asString(legacy.paystackPlanCode) ?? undefined,\n status: asString(legacy.status) ?? \"incomplete\",\n periodStart: asDate(legacy.periodStart, now),\n periodEnd: asOptionalDate(legacy.periodEnd),\n trialStart: asOptionalDate(legacy.trialStart),\n trialEnd: asOptionalDate(legacy.trialEnd),\n cancelAtPeriodEnd: legacy.cancelAtPeriodEnd === true,\n cancelAt: asOptionalDate(legacy.cancelAt),\n canceledAt: asOptionalDate(legacy.canceledAt),\n endedAt: asOptionalDate(legacy.endedAt),\n billingInterval: asString(legacy.billingInterval) ?? undefined,\n groupId: asString(legacy.groupId) ?? undefined,\n seats: typeof legacy.seats === \"number\" ? legacy.seats : undefined,\n pendingPlan: asString(legacy.pendingPlan) ?? undefined,\n createdAt: asDate(legacy.createdAt, now),\n updatedAt: asDate(legacy.updatedAt, now),\n };\n}\n\nasync function migrateCustomer(\n adapter: Adapter,\n referenceType: \"user\" | \"organization\",\n legacy: LegacyRecord,\n report: PaystackSchemaMigrationReport,\n): Promise<void> {\n const customerCode = asString(legacy.paystackCustomerCode) ?? asString(legacy.customerCode);\n const referenceId = asIdentifier(legacy.id);\n if (customerCode === undefined || referenceId === undefined) return;\n const referenceKey = `${referenceType}:${referenceId}`;\n try {\n const existing = await adapter.findOne<LegacyRecord>({\n model: PAYSTACK_MODELS.customer,\n where: [{ field: \"referenceKey\", value: referenceKey }],\n });\n if (existing) {\n report.customers.skipped += 1;\n report.skipped += 1;\n return;\n }\n const now = new Date();\n const email = asString(legacy.email);\n await adapter.create({\n model: PAYSTACK_MODELS.customer,\n data: {\n referenceType,\n referenceId,\n referenceKey,\n customerCode,\n ...(email !== undefined ? { email } : {}),\n createdAt: asDate(legacy.createdAt, now),\n updatedAt: asDate(legacy.updatedAt, now),\n },\n });\n report.customers.migrated += 1;\n } catch (error) {\n report.customers.failed += 1;\n report.failures.push({\n kind: \"customer\",\n id: referenceKey,\n message: error instanceof Error ? error.message : \"Failed to migrate customer\",\n });\n }\n}\n\nexport async function migratePaystackSubscriptionSchema(\n ctx: GenericEndpointContext,\n options: AnyPaystackOptions,\n): Promise<PaystackSchemaMigrationReport> {\n const adapter = ctx.context.adapter;\n const report: PaystackSchemaMigrationReport = {\n status: \"complete\",\n subscriptions: { migrated: 0, skipped: 0, failed: 0 },\n customers: { migrated: 0, skipped: 0, failed: 0 },\n credentials: { migrated: 0, skipped: 0, failed: 0 },\n skipped: 0,\n failures: [],\n };\n\n for (const referenceType of [\"user\", \"organization\"] as const) {\n const records = await findManySafely(adapter, referenceType);\n for (const record of records) await migrateCustomer(adapter, referenceType, record, report);\n }\n\n const legacySubscriptions = await findManySafely(adapter, LEGACY_PAYSTACK_MODELS.subscription);\n for (const legacy of legacySubscriptions) {\n const id = asIdentifier(legacy.id);\n if (id === undefined) continue;\n try {\n const existing = await adapter.findOne<LegacyRecord>({\n model: PAYSTACK_MODELS.subscription,\n where: [{ field: \"id\", value: id }],\n });\n if (existing) {\n report.subscriptions.skipped += 1;\n report.skipped += 1;\n } else {\n await adapter.create({\n model: PAYSTACK_MODELS.subscription,\n data: migrationData(legacy),\n forceAllowId: true,\n });\n report.subscriptions.migrated += 1;\n }\n } catch (error) {\n report.subscriptions.failed += 1;\n report.failures.push({\n kind: \"subscription\",\n id,\n message: error instanceof Error ? error.message : \"Failed to migrate subscription\",\n });\n }\n\n const authorizationCode =\n asString(legacy.authorizationCode) ?? asString(legacy.paystackAuthorizationCode);\n const emailToken = asString(legacy.emailToken) ?? asString(legacy.paystackEmailToken);\n if (authorizationCode !== undefined || emailToken !== undefined) {\n try {\n const existingCredential = await adapter.findOne<LegacyRecord>({\n model: PAYSTACK_MODELS.paymentCredential,\n where: [{ field: \"subscriptionId\", value: id }],\n });\n if (existingCredential) {\n report.credentials.skipped += 1;\n report.skipped += 1;\n } else {\n await savePaystackPaymentCredentials(adapter, options, id, {\n authorizationCode,\n emailToken,\n });\n report.credentials.migrated += 1;\n }\n } catch (error) {\n report.credentials.failed += 1;\n report.failures.push({\n kind: \"credential\",\n id,\n message: error instanceof Error ? error.message : \"Failed to migrate credential\",\n });\n }\n }\n }\n\n report.status = report.failures.length > 0 ? \"partial\" : \"complete\";\n return report;\n}\n","import {\n defineErrorCodes,\n type AuthContext,\n type BetterAuthPlugin,\n type GenericEndpointContext,\n} from \"better-auth\";\nimport { APIError } from \"better-auth/api\";\nimport { defu } from \"defu\";\n\nimport { createBillingStoreFromAdapter, type BillingStoreAdapter } from \"./billing-store.ts\";\nimport { resolvePaystackCustomer } from \"./customer.ts\";\nimport { checkSeatLimit, checkTeamLimit, getOrganizationEntitlements } from \"./limits.ts\";\nimport { createPaystackAdapter } from \"./paystack-sdk.ts\";\nimport {\n disablePaystackSubscription,\n enablePaystackSubscription,\n initializeTransaction,\n listSubscriptions,\n listTransactions,\n paystackWebhook,\n verifyTransaction,\n getConfig,\n getSubscriptionManageLink,\n PAYSTACK_ERROR_CODES,\n createSubscription,\n upgradeSubscription,\n cancelSubscription,\n restoreSubscription,\n listProducts,\n listPlans,\n} from \"./routes.ts\";\nimport { getSchema } from \"./schema.ts\";\nimport type { PaystackClientLike, PaystackOptions, AnyPaystackOptions, User } from \"./types.ts\";\nimport { syncSubscriptionSeats } from \"./utils.ts\";\nimport { PACKAGE_VERSION } from \"./version.ts\";\n\nexport {\n createCheckoutMetadata,\n createProrationMetadata,\n createRenewalMetadata,\n getMetadataBoolean,\n getMetadataNumber,\n getMetadataString,\n hasPaystackMetadata,\n parsePaystackMetadata,\n stringifyPaystackMetadata,\n} from \"./metadata.ts\";\nexport type { PaystackMetadata } from \"./metadata.ts\";\nexport type { PaystackInitializeResult } from \"./types.ts\";\n\ndeclare module \"better-auth\" {\n interface BetterAuthPluginRegistry<AuthOptions, Options> {\n paystack: {\n creator: typeof paystack;\n };\n }\n}\n\nconst INTERNAL_ERROR_CODES: ReturnType<typeof defineErrorCodes> = defineErrorCodes(\n Object.fromEntries(\n Object.entries(PAYSTACK_ERROR_CODES).map(([key, value]) => [\n key,\n typeof value === \"string\" ? value : (value as { message: string }).message,\n ]),\n ),\n);\n\n/**\n * Must stay a `type` rather than an `interface`.\n *\n * `BetterAuthPlugin[\"endpoints\"]` is `{ [key: string]: Endpoint }`, and only object literal\n * *type aliases* get TypeScript's implicit index signature — interfaces do not. Declaring\n * this as `interface ... extends Record<string, Endpoint>` satisfies that constraint but\n * gives the plugin a real string index signature. Better Auth merges every plugin's\n * endpoints into `auth.api`, so that signature spreads across the whole API surface and,\n * under `noUncheckedIndexedAccess`, makes *every* `auth.api.*` call possibly `undefined`.\n */\n// oxlint-disable-next-line typescript/consistent-type-definitions\ntype PaystackPluginEndpoints = {\n initializeTransaction: ReturnType<typeof initializeTransaction>;\n verifyTransaction: ReturnType<typeof verifyTransaction>;\n listSubscriptions: ReturnType<typeof listSubscriptions>;\n paystackWebhook: ReturnType<typeof paystackWebhook>;\n listTransactions: ReturnType<typeof listTransactions>;\n getConfig: ReturnType<typeof getConfig>;\n disableSubscription: ReturnType<typeof disablePaystackSubscription>;\n enableSubscription: ReturnType<typeof enablePaystackSubscription>;\n getSubscriptionManageLink: ReturnType<typeof getSubscriptionManageLink>;\n subscriptionManageLink: ReturnType<typeof getSubscriptionManageLink>;\n createSubscription: ReturnType<typeof createSubscription>;\n upgradeSubscription: ReturnType<typeof upgradeSubscription>;\n cancelSubscription: ReturnType<typeof cancelSubscription>;\n restoreSubscription: ReturnType<typeof restoreSubscription>;\n listProducts: ReturnType<typeof listProducts>;\n listPlans: ReturnType<typeof listPlans>;\n};\n\ntype PaystackHookHandler = (...args: unknown[]) => unknown;\n\ninterface PaystackPluginInitResult {\n options: {\n databaseHooks: Record<string, unknown> & {\n organization: {\n create: {\n after: PaystackHookHandler;\n };\n };\n };\n };\n}\n\ntype PaystackPluginInitContext = Pick<AuthContext, \"hasPlugin\" | \"logger\"> & {\n adapter: BillingStoreAdapter;\n};\n\ntype PaystackPluginInit = ((ctx: PaystackPluginInitContext) => PaystackPluginInitResult) &\n NonNullable<BetterAuthPlugin[\"init\"]>;\n\ntype PaystackPluginInstance<O extends AnyPaystackOptions> = Omit<\n BetterAuthPlugin,\n \"id\" | \"version\" | \"endpoints\" | \"schema\" | \"init\" | \"$ERROR_CODES\" | \"options\"\n> & {\n id: \"paystack\";\n version: typeof PACKAGE_VERSION;\n endpoints: PaystackPluginEndpoints;\n schema: ReturnType<typeof getSchema>;\n init: PaystackPluginInit;\n $ERROR_CODES: typeof INTERNAL_ERROR_CODES;\n options: NoInfer<O>;\n};\n\nconst createPaystackPlugin = <\n TPaystackClient extends PaystackClientLike = PaystackClientLike,\n O extends PaystackOptions<TPaystackClient> = PaystackOptions<TPaystackClient>,\n>(\n options: O,\n): PaystackPluginInstance<O> => {\n const routeOptions = {\n ...(options as unknown as AnyPaystackOptions),\n webhook: options.webhook,\n } satisfies AnyPaystackOptions;\n return {\n id: \"paystack\",\n version: PACKAGE_VERSION as typeof PACKAGE_VERSION,\n endpoints: {\n initializeTransaction: initializeTransaction(\n routeOptions,\n \"/paystack/initialize-transaction\",\n ),\n verifyTransaction: verifyTransaction(routeOptions, \"/paystack/verify-transaction\"),\n listSubscriptions: listSubscriptions(routeOptions, \"/paystack/list-subscriptions\"),\n paystackWebhook: paystackWebhook(routeOptions, \"/paystack/webhook\"),\n listTransactions: listTransactions(routeOptions, \"/paystack/list-transactions\"),\n getConfig: getConfig(routeOptions, \"/paystack/config\"),\n disableSubscription: disablePaystackSubscription(\n routeOptions,\n \"/paystack/disable-subscription\",\n ),\n enableSubscription: enablePaystackSubscription(routeOptions, \"/paystack/enable-subscription\"),\n getSubscriptionManageLink: getSubscriptionManageLink(\n routeOptions,\n \"/paystack/subscription-manage-link\",\n ),\n subscriptionManageLink: getSubscriptionManageLink(\n routeOptions,\n \"/paystack/subscription/manage-link\",\n ),\n createSubscription: createSubscription(routeOptions, \"/paystack/create-subscription\"),\n upgradeSubscription: upgradeSubscription(routeOptions, \"/paystack/upgrade-subscription\"),\n cancelSubscription: cancelSubscription(routeOptions, \"/paystack/cancel-subscription\"),\n restoreSubscription: restoreSubscription(routeOptions, \"/paystack/restore-subscription\"),\n listProducts: listProducts(routeOptions, \"/paystack/list-products\"),\n listPlans: listPlans(routeOptions, \"/paystack/list-plans\"),\n },\n schema: getSchema(options),\n init: ((ctx: PaystackPluginInitContext) => {\n const organizationPluginAvailable = ctx.hasPlugin(\"organization\");\n if (options.organization?.enabled === true && !organizationPluginAvailable) {\n ctx.logger.error(\n \"Paystack organization billing is enabled, but the Better Auth organization plugin was not found. Organization billing hooks will be skipped.\",\n );\n }\n\n return {\n options: {\n databaseHooks: {\n user: {\n create: {\n async after(\n user: {\n id: string;\n email?: string | null;\n name?: string | null;\n emailVerified?: boolean;\n },\n hookCtx?: GenericEndpointContext | null,\n ) {\n if (\n !hookCtx ||\n options.createCustomerOnSignUp !== true ||\n user.email === null ||\n user.email === undefined ||\n user.email === \"\"\n )\n return;\n\n try {\n const result = await resolvePaystackCustomer({\n adapter: ctx.adapter,\n client: options.paystackClient as PaystackClientLike,\n logger: ctx.logger,\n reference: {\n id: user.id,\n type: \"user\",\n email: user.email,\n name: user.name,\n emailVerified: user.emailVerified,\n paystackCustomerCode: (user as Record<string, unknown>)\n .paystackCustomerCode as string | null | undefined,\n },\n });\n const customerCode = result?.customer.customer_code;\n\n if (\n result?.created === true &&\n typeof customerCode === \"string\" &&\n typeof options.onCustomerCreate === \"function\"\n ) {\n await options.onCustomerCreate(\n {\n paystackCustomer: result.customer,\n user: {\n ...(user as User),\n paystackCustomerCode: customerCode,\n },\n },\n hookCtx,\n );\n }\n } catch (error: unknown) {\n ctx.logger.error(\"Failed to create Paystack customer for user\", error);\n }\n },\n },\n update: {\n async after(user: { id: string; email?: string | null }) {\n const customerCode = (\n await createBillingStoreFromAdapter(ctx.adapter).findCustomerByReference(\n \"user\",\n user.id,\n )\n )?.customerCode;\n if (\n typeof customerCode !== \"string\" ||\n customerCode === \"\" ||\n typeof user.email !== \"string\" ||\n user.email === \"\"\n )\n return;\n try {\n await createPaystackAdapter(options.paystackClient).updateCustomer(\n customerCode,\n { email: user.email },\n );\n } catch (error: unknown) {\n ctx.logger.error(\"Failed to synchronize Paystack customer email\", error);\n }\n },\n },\n },\n organization:\n options.organization?.enabled === true && organizationPluginAvailable\n ? {\n create: {\n async after(\n org: { id: string; name: string; email?: string | null },\n hookCtx: GenericEndpointContext | null,\n ) {\n try {\n const extraCreateParams =\n typeof options.organization?.getCustomerCreateParams === \"function\"\n ? await (\n options.organization.getCustomerCreateParams as (\n org: Record<string, unknown>,\n hookCtx: GenericEndpointContext,\n ) => Promise<Record<string, unknown>>\n )(org, hookCtx!)\n : {};\n\n let targetEmail = org.email;\n if (targetEmail === undefined || targetEmail === null) {\n const store = createBillingStoreFromAdapter(ctx.adapter);\n const ownerMember = await store.findOrganizationOwner(org.id);\n if (ownerMember !== null && ownerMember !== undefined) {\n const ownerUser = await store.findUser(ownerMember.userId);\n targetEmail = ownerUser?.email;\n }\n }\n\n if (targetEmail === undefined || targetEmail === null) return;\n\n const result = await resolvePaystackCustomer({\n adapter: ctx.adapter,\n client: options.paystackClient as PaystackClientLike,\n logger: ctx.logger,\n reference: {\n id: org.id,\n type: \"organization\",\n email: targetEmail,\n name: org.name,\n paystackCustomerCode: (\n org as { paystackCustomerCode?: string | null }\n ).paystackCustomerCode,\n },\n createParams: defu({}, extraCreateParams),\n });\n const customerCode = result?.customer.customer_code;\n\n if (\n result?.created === true &&\n typeof customerCode === \"string\" &&\n typeof options.organization?.onCustomerCreate === \"function\"\n ) {\n await options.organization.onCustomerCreate(\n {\n paystackCustomer: result.customer,\n organization: {\n ...org,\n paystackCustomerCode: customerCode,\n },\n },\n hookCtx!,\n );\n }\n } catch (error: unknown) {\n ctx.logger.error(\n \"Failed to create Paystack customer for organization\",\n error,\n );\n }\n },\n },\n update: {\n async after(\n org: {\n id: string;\n name?: string | null;\n email?: string | null;\n },\n hookCtx?: GenericEndpointContext | null,\n ) {\n const persisted = await createBillingStoreFromAdapter(\n ctx.adapter,\n ).findOrganization(org.id);\n const customerCode = (\n await createBillingStoreFromAdapter(ctx.adapter).findCustomerByReference(\n \"organization\",\n org.id,\n )\n )?.customerCode;\n if (typeof customerCode !== \"string\" || customerCode === \"\") return;\n try {\n const configured =\n typeof options.organization?.getCustomerCreateParams === \"function\" &&\n hookCtx\n ? await options.organization.getCustomerCreateParams(\n {\n id: org.id,\n name: org.name ?? persisted?.name ?? \"\",\n email:\n org.email ??\n (persisted as typeof persisted & { email?: string | null })\n ?.email,\n },\n hookCtx,\n )\n : {};\n const configuredEmail =\n typeof configured.email === \"string\" && configured.email !== \"\"\n ? configured.email\n : undefined;\n await createPaystackAdapter(options.paystackClient).updateCustomer(\n customerCode,\n {\n ...(configuredEmail !== undefined ||\n (typeof org.email === \"string\" && org.email !== \"\")\n ? { email: configuredEmail ?? org.email ?? undefined }\n : {}),\n ...(typeof org.name === \"string\" && org.name !== \"\"\n ? { first_name: org.name }\n : {}),\n },\n );\n } catch (error: unknown) {\n ctx.logger.error(\n \"Failed to synchronize Paystack organization customer\",\n error,\n );\n }\n },\n },\n delete: {\n async before(org: { id: string }) {\n const store = createBillingStoreFromAdapter(ctx.adapter);\n const subscriptions = await store.findSubscriptionsByReference(org.id);\n if (\n subscriptions.some(\n (subscription) =>\n subscription.status === \"active\" ||\n subscription.status === \"trialing\",\n )\n ) {\n throw new APIError(\"BAD_REQUEST\", {\n message:\n \"Organization cannot be deleted while it has an active subscription\",\n });\n }\n\n const customerCode = (\n await store.findCustomerByReference(\"organization\", org.id)\n )?.customerCode;\n if (typeof customerCode !== \"string\" || customerCode === \"\") return;\n try {\n const customer = (await createPaystackAdapter(\n options.paystackClient,\n ).fetchCustomer(customerCode)) as {\n subscriptions?: { status?: string }[];\n };\n if (\n customer.subscriptions?.some(\n (subscription) =>\n subscription.status === \"active\" ||\n subscription.status === \"trialing\",\n ) === true\n ) {\n throw new APIError(\"BAD_REQUEST\", {\n message:\n \"Organization cannot be deleted while it has an active subscription\",\n });\n }\n } catch (error: unknown) {\n if (error instanceof APIError) throw error;\n ctx.logger.error(\n \"Failed to check Paystack subscriptions before organization deletion\",\n error,\n );\n throw new APIError(\"BAD_REQUEST\", {\n message:\n \"Organization deletion could not verify its Paystack subscriptions\",\n });\n }\n },\n },\n }\n : undefined,\n member: organizationPluginAvailable\n ? {\n create: {\n before: async (\n member: { organizationId: string },\n ctx: GenericEndpointContext | null | undefined,\n ) => {\n if (\n options.subscription?.enabled === true &&\n member.organizationId &&\n ctx !== null &&\n ctx !== undefined\n ) {\n await checkSeatLimit(ctx, member.organizationId);\n }\n },\n after: async (\n member: { organizationId: string | undefined },\n ctx: GenericEndpointContext | null | undefined,\n ) => {\n if (\n options.subscription?.enabled === true &&\n typeof member?.organizationId === \"string\" &&\n ctx\n ) {\n await syncSubscriptionSeats(ctx, member.organizationId, routeOptions);\n }\n },\n },\n delete: {\n after: async (\n member: { organizationId: string | undefined },\n ctx: GenericEndpointContext | null | undefined,\n ) => {\n if (\n options.subscription?.enabled === true &&\n typeof member?.organizationId === \"string\" &&\n ctx\n ) {\n await syncSubscriptionSeats(ctx, member.organizationId, routeOptions);\n }\n },\n },\n }\n : undefined,\n invitation: organizationPluginAvailable\n ? {\n create: {\n before: async (\n invitation: { organizationId: string },\n ctx: GenericEndpointContext | null | undefined,\n ) => {\n if (\n options.subscription?.enabled === true &&\n invitation.organizationId &&\n ctx !== null &&\n ctx !== undefined\n ) {\n await checkSeatLimit(ctx, invitation.organizationId);\n }\n },\n after: async (\n invitation: { organizationId: string | undefined },\n ctx: GenericEndpointContext | null | undefined,\n ) => {\n if (\n options.subscription?.enabled === true &&\n typeof invitation?.organizationId === \"string\" &&\n ctx\n ) {\n await syncSubscriptionSeats(ctx, invitation.organizationId, routeOptions);\n }\n },\n },\n delete: {\n after: async (\n invitation: { organizationId: string | undefined },\n ctx: GenericEndpointContext | null | undefined,\n ) => {\n if (\n options.subscription?.enabled === true &&\n typeof invitation?.organizationId === \"string\" &&\n ctx\n ) {\n await syncSubscriptionSeats(ctx, invitation.organizationId, routeOptions);\n }\n },\n },\n }\n : undefined,\n team: organizationPluginAvailable\n ? {\n create: {\n before: async (\n team: { organizationId: string },\n ctx: GenericEndpointContext | null | undefined,\n ) => {\n if (options.subscription?.enabled === true && team.organizationId && ctx) {\n const entitlements = await getOrganizationEntitlements(\n ctx,\n team.organizationId,\n routeOptions,\n );\n const maxTeams = entitlements.limits.teams;\n if (typeof maxTeams === \"number\") {\n await checkTeamLimit(ctx, team.organizationId, maxTeams);\n }\n }\n },\n },\n }\n : undefined,\n },\n },\n };\n }) as PaystackPluginInit,\n $ERROR_CODES: INTERNAL_ERROR_CODES,\n options: options,\n } satisfies BetterAuthPlugin;\n};\n\nexport const paystack: typeof createPaystackPlugin = createPaystackPlugin;\n\nexport type PaystackPlugin<\n TPaystackClient extends PaystackClientLike = PaystackClientLike,\n O extends PaystackOptions<TPaystackClient> = PaystackOptions<TPaystackClient>,\n> = ReturnType<typeof paystack<TPaystackClient, O>>;\n\nexport {\n chargeSubscriptionRenewal,\n syncPaystackPlans,\n syncPaystackProducts,\n} from \"./operations.ts\";\nexport { getOrganizationEntitlements } from \"./limits.ts\";\nexport { reconcilePaystackTransaction } from \"./reconciliation.ts\";\nexport { migratePaystackSubscriptionSchema } from \"./migrations.ts\";\nexport type {\n PaystackReconciliationError,\n PaystackReconciliationSource,\n PaystackReconciliationSummary,\n ReconcilePaystackTransactionFailure,\n ReconcilePaystackTransactionInput,\n ReconcilePaystackTransactionResult,\n ReconcilePaystackTransactionSuccess,\n} from \"./reconciliation.ts\";\nexport type {\n Subscription,\n PaystackSubscription,\n PaystackCustomer,\n PaystackPaymentCredential,\n SubscriptionOptions,\n PaystackSubscriptionOperation,\n PaystackSubscriptionOperationDecision,\n PaystackSubscriptionOperationPhase,\n PaystackSubscriptionOperationHooks,\n PaystackPlan,\n PaystackOptions,\n PaystackProduct,\n PaystackTransaction,\n PaystackTransactionResponse,\n PaystackClientLike,\n ChargeRecurringSubscriptionResult,\n PaystackSyncResult,\n PaystackWebhookEventRecord,\n} from \"./types.ts\";\nexport type {\n PaystackSchemaMigrationFailure,\n PaystackSchemaMigrationReport,\n} from \"./migrations.ts\";\n"],"mappings":";;;;;;;;;;;;;AAEA,MAAa,kBAAkB;CAC7B,UAAU;CACV,mBAAmB;CACnB,cAAc;CACd,aAAa;CACb,SAAS;CACT,MAAM;CACN,cAAc;AAChB;AAEA,MAAa,yBAAyB,EACpC,cAAc,eAChB;;;AC2FA,SAAS,4BAA4B,eAA+C;CAClF,MAAM,6BAAa,IAAI,IAAI;EACzB,CAAC,UAAU,CAAC;EACZ,CAAC,YAAY,CAAC;EACd,CAAC,cAAc,CAAC;EAChB,CAAC,YAAY,CAAC;EACd,CAAC,YAAY,CAAC;CAChB,CAAC;CAED,OAAO,CAAC,GAAG,aAAa,CAAC,CAAC,MAAM,GAAG,MAAM;EACvC,MAAM,QAAQ,WAAW,IAAI,EAAE,MAAM,KAAK;EAC1C,MAAM,QAAQ,WAAW,IAAI,EAAE,MAAM,KAAK;EAC1C,IAAI,UAAU,OAAO,OAAO,QAAQ;EACpC,OAAO,IAAI,KAAK,EAAE,SAAS,CAAC,CAAC,QAAQ,IAAI,IAAI,KAAK,EAAE,SAAS,CAAC,CAAC,QAAQ;CACzE,CAAC;AACH;AAEA,SAAgB,mBAAmB,KAA2C;CAC5E,OAAO,8BAA8B,IAAI,QAAQ,OAAO;AAC1D;AAEA,SAAgB,8BAA8B,SAAgC;CAC5E,MAAM,UAAU,OAAU,OAAe,UAA0C;EACjF,IAAI;GACF,OAAQ,MAAM,QAAQ,QAAW;IAAE;IAAO;GAAM,CAAC,KAAM;EACzD,QAAQ;GAEN,OAAO;EACT;CACF;CAEA,MAAM,WAAW,OAAU,OAAe,UAAsC;EAC9E,IAAI;GACF,OAAQ,MAAM,QAAQ,SAAY;IAAE;IAAO,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;GAAG,CAAC,KAAM,CAAC;EACjF,QAAQ;GACN,OAAO,CAAC;EACV;CACF;CAEA,OAAO;EACL,uBAAuB,OACrB,QAAsB,gBAAgB,cAAc,CAAC;GAAE,OAAO;GAAM,OAAO;EAAG,CAAC,CAAC;EAClF,yBAAyB,qBACvB,QAAsB,gBAAgB,cAAc,CAClD;GAAE,OAAO;GAAoB,OAAO;EAAiB,CACvD,CAAC;EACH,+BAA+B,gBAC7B,SAAuB,gBAAgB,cAAc,CACnD;GAAE,OAAO;GAAe,OAAO;EAAY,CAC7C,CAAC;EACH,MAAM,wBAAwB,aAAa,SAAS;GAClD,MAAM,gBAAgB,MAAM,KAAK,6BAA6B,WAAW;GAWzE,OAAO,4BATL,YAAY,KAAA,IACR,gBACA,cAAc,QAAQ,iBACpB,YAAY,OACR,aAAa,YAAY,KAAA,KACzB,aAAa,YAAY,QACzB,aAAa,YAAY,KACzB,aAAa,YAAY,OAC/B,CACmC,CAAC,CAAC,MAAM;EACnD;EACA,MAAM,6BAA6B,aAAa,SAAS,UAAU;GACjE,MAAM,gBAAgB,MAAM,KAAK,6BAA6B,WAAW;GACzE,MAAM,WAAW,cAAc,MAAM,iBAAiB,aAAa,OAAO,QAAQ;GAClF,MAAM,cAAc,cAAc,QAC/B,iBACC,aAAa,OAAO,aACnB,aAAa,KAAA,KACZ,IAAI,KAAK,aAAa,SAAS,CAAC,CAAC,QAAQ,KAAK,IAAI,KAAK,SAAS,SAAS,CAAC,CAAC,QAAQ,OACpF,aAAa,WAAW,YAAY,aAAa,WAAW,gBAC5D,YAAY,OACT,aAAa,YAAY,KAAA,KACzB,aAAa,YAAY,QACzB,aAAa,YAAY,KACzB,aAAa,YAAY,QACjC;GACA,MAAM,sBAAM,IAAI,KAAK;GACrB,KAAK,MAAM,gBAAgB,aACzB,MAAM,KAAK,mBAAmB,aAAa,IAAI;IAC7C,QAAQ;IACR,mBAAmB;IACnB,YAAY;IACZ,SAAS;IACT,WAAW;GACb,CAAC;EAEL;EACA,0CAA0C,cACxC,SAAuB,gBAAgB,cAAc,CACnD;GAAE,OAAO;GAAwB,OAAO;EAAU,CACpD,CAAC;EACH,oBAAoB,OAAO,SACzB,MAAM,QAAQ,OAAO;GACnB,OAAO,gBAAgB;GACjB;EACR,CAAC;EACH,qBAAqB,IAAI,WACvB,QAAQ,OAAqB;GAC3B,OAAO,gBAAgB;GACvB;GACA,OAAO,CAAC;IAAE,OAAO;IAAM,OAAO;GAAG,CAAC;EACpC,CAAC;EACH,2BAA2B,kBAAkB,WAC3C,QAAQ,OAAqB;GAC3B,OAAO,gBAAgB;GACvB;GACA,OAAO,CAAC;IAAE,OAAO;IAAoB,OAAO;GAAiB,CAAC;EAChE,CAAC;EACH,mBAAmB,OAAO,SACxB,MAAM,QAAQ,OAAO;GACnB,OAAO,gBAAgB;GACjB;EACR,CAAC;EACH,6BAA6B,cAC3B,QAA6B,gBAAgB,aAAa,CACxD;GAAE,OAAO;GAAa,OAAO;EAAU,CACzC,CAAC;EACH,+BAA+B,WAAW,WACxC,QAAQ,OAA4B;GAClC,OAAO,gBAAgB;GACvB;GACA,OAAO,CAAC;IAAE,OAAO;IAAa,OAAO;GAAU,CAAC;EAClD,CAAC;EACH,qBAAqB,SACnB,QAAQ,OAAO;GACb,OAAO,gBAAgB;GACvB;EACF,CAAC;EACH,mBAAmB,YACjB,QAAQ,QAAoC;GAC1C,OAAO,gBAAgB;GACvB,OAAO,CAAC;IAAE,OAAO;IAAW,OAAO;GAAQ,CAAC;EAC9C,CAAC;EACH,qBAAqB,SAAS,WAC5B,QAAQ,OAAmC;GACzC,OAAO,gBAAgB;GACvB;GACA,OAAO,CAAC;IAAE,OAAO;IAAW,OAAO;GAAQ,CAAC;EAC9C,CAAC;EACH,MAAM,iBAAiB,aAAa;GAIlC,QAAO,MAHoB,SAA8B,gBAAgB,aAAa,CACpF;IAAE,OAAO;IAAe,OAAO;GAAY,CAC7C,CAAC,EAAA,CACmB,MAAM,GAAG,MAAM,EAAE,UAAU,QAAQ,IAAI,EAAE,UAAU,QAAQ,CAAC;EAClF;EACA,MAAM,eAAe;GAEnB,QAAO,MADgB,SAA0B,gBAAgB,OAAO,EAAA,CACxD,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;EAC7D;EACA,oBAAoB,SAClB,QAAyB,gBAAgB,SAAS,CAAC;GAAE,OAAO;GAAQ,OAAO;EAAK,CAAC,CAAC;EACpF,oBAAoB,SAClB,QAAyB,gBAAgB,SAAS,CAAC;GAAE,OAAO;GAAQ,OAAO;EAAK,CAAC,CAAC;EACpF,MAAM,cAAc,IAAI,QAAQ;GAC9B,MAAM,QAAQ,OAAO;IACnB,OAAO,gBAAgB;IACvB;IACA,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO;IAAG,CAAC;GACpC,CAAC;EACH;EACA,MAAM,0BAA0B,YAAY,MAAM;GAChD,MAAM,WAAW,MAAM,QAAyB,gBAAgB,SAAS,CACvE;IAAE,OAAO;IAAc,OAAO;GAAW,CAC3C,CAAC;GACD,IAAI,UAAU,OAAO,KAAA,GAAW;IAC9B,MAAM,EAAE,WAAW,YAAY,GAAG,WAAW;IAC7C,MAAM,QAAQ,OAAO;KACnB,OAAO,gBAAgB;KACvB;KACA,OAAO,CAAC;MAAE,OAAO;MAAM,OAAO,OAAO,SAAS,EAAE;KAAE,CAAC;IACrD,CAAC;IACD;GACF;GACA,MAAM,QAAQ,OAAO;IAAE,OAAO,gBAAgB;IAAS;GAAK,CAAC;EAC/D;EACA,iBAAiB,SAAuB,gBAAgB,IAAI;EAC5D,iBAAiB,SACf,QAAsB,gBAAgB,MAAM,CAAC;GAAE,OAAO;GAAQ,OAAO;EAAK,CAAC,CAAC;EAC9E,iBAAiB,aACf,QAAsB,gBAAgB,MAAM,CAAC;GAAE,OAAO;GAAY,OAAO;EAAS,CAAC,CAAC;EACtF,MAAM,uBAAuB,YAAY,MAAM;GAC7C,MAAM,WAAW,MAAM,QAAsB,gBAAgB,MAAM,CACjE;IAAE,OAAO;IAAc,OAAO;GAAW,CAC3C,CAAC;GACD,IAAI,UAAU,OAAO,KAAA,GAAW;IAC9B,MAAM,EAAE,WAAW,YAAY,GAAG,WAAW;IAC7C,MAAM,QAAQ,OAAO;KACnB,OAAO,gBAAgB;KACvB;KACA,OAAO,CAAC;MAAE,OAAO;MAAM,OAAO,SAAS;KAAG,CAAC;IAC7C,CAAC;IACD;GACF;GACA,MAAM,QAAQ,OAAO;IAAE,OAAO,gBAAgB;IAAM;GAAK,CAAC;EAC5D;EACA,WAAW,OAAO,QAAc,QAAQ,CAAC;GAAE,OAAO;GAAM,OAAO;EAAG,CAAC,CAAC;EACpE,mBAAmB,OACjB,QAA8B,gBAAgB,CAAC;GAAE,OAAO;GAAM,OAAO;EAAG,CAAC,CAAC;EAC5E,wBAAwB,mBACtB,QAAgB,UAAU,CACxB;GAAE,OAAO;GAAkB,OAAO;EAAe,GACjD;GAAE,OAAO;GAAQ,OAAO;EAAQ,CAClC,CAAC;EACH,cAAc,mBACZ,SAAiB,UAAU,CAAC;GAAE,OAAO;GAAkB,OAAO;EAAe,CAAC,CAAC;EACjF,YAAY,mBACV,SAAS,QAAQ,CAAC;GAAE,OAAO;GAAkB,OAAO;EAAe,CAAC,CAAC;EACvE,0BAA0B,eAAe,gBACvC,QAA0B,gBAAgB,UAAU,CAClD;GAAE,OAAO;GAAgB,OAAO,GAAG,cAAc,GAAG;EAAc,CACpE,CAAC;EACH,qBAAqB,iBACnB,QAA0B,gBAAgB,UAAU,CAClD;GAAE,OAAO;GAAgB,OAAO;EAAa,CAC/C,CAAC;EACH,MAAM,aAAa,eAAe,aAAa,cAAc,OAAO;GAClE,MAAM,eAAe,GAAG,cAAc,GAAG;GACzC,MAAM,WAAW,MAAM,QAA0B,gBAAgB,UAAU,CACzE;IAAE,OAAO;IAAgB,OAAO;GAAa,CAC/C,CAAC;GACD,MAAM,sBAAM,IAAI,KAAK;GACrB,MAAM,WAAW,UAAU,KAAA,KAAa,UAAU,QAAQ,UAAU;GACpE,IAAI,UAMF,OACE,MANoB,QAAQ,OAAyB;IACrD,OAAO,gBAAgB;IACvB,QAAQ;KAAE;KAAc,GAAI,WAAW,EAAE,MAAM,IAAI,CAAC;KAAI,WAAW;IAAI;IACvE,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,SAAS;IAAG,CAAC;GAC7C,CAAC,KAEY;IAAE,GAAG;IAAU;IAAc,OAAO,SAAS,SAAS;IAAO,WAAW;GAAI;GAG3F,OAAO,QAAQ,OAAO;IACpB,OAAO,gBAAgB;IACvB,MAAM;KACJ;KACA;KACA;KACA;KACA,GAAI,WAAW,EAAE,MAAM,IAAI,CAAC;KAC5B,WAAW;KACX,WAAW;IACb;GACF,CAAC;EACH;EACA,MAAM,iBAAiB,aAAa,cAAc,gBAAgB,OAAO;GACvE,MAAM,KAAK,aACT,iBAAiB,iBAAiB,QAClC,aACA,cACA,KACF;EACF;CACF;AACF;;;;;;AC5VA,SAAS,mBAAmB,OAAoD;CAC9E,OAAO,iBAAiB;AAC1B;;;;;AAMA,SAAgB,gBAA6B,QAAoB;CAC/D,IAAI,mBAAmB,MAAM,GAC3B,IAAI;EACF,OAAO,OAAO,OAAO;CACvB,SAAS,GAAY;EACnB,IAAI,aAAa,eACf,MAAM,IAAI,SAAS,EAAE,WAAW,MAAM,cAAc,eAAe;GACjE,SAAS,EAAE;GACX,QAAQ,EAAE;EACZ,CAAC;EAGH,MAAM,IAAI,SAAS,eAAe,EAChC,SAAU,GAAa,WAAW,qBACpC,CAAC;CACH;CAIF,IAAI,UAAU;CAGd,OAAO,YAAY,QAAQ,YAAY,KAAA,KAAa,OAAO,YAAY,UAAU;EAC/E,MAAM,OAAO;EAGb,IAAI,KAAK,WAAW,OAClB,MAAM,IAAI,SAAS,eAAe,EAChC,SAAU,KAAK,WAAkC,qBACnD,CAAC;EAIH,IAAI,uBAAuB,QAAQ,eAAe,QAAQ,mBAAmB,MAC3E;EAIF,IACE,UAAU,QACV,KAAK,SAAS,KAAA,KACd,KAAK,SAAS,QACd,OAAO,KAAK,SAAS,UACrB;GACA,UAAU,KAAK;GACf;EACF;EACA;CACF;CAEA,OAAO;AACT;;;;;AAMA,SAAgB,eAAe,QAA6D;CAC1F,OAAO;AACT;AAuCA,SAAgB,sBAAsB,QAA8C;CAClF,MAAM,sBAA0C;EAC9C,IAAI,WAAW,KAAA,KAAa,WAAW,MACrC,MAAM,IAAI,SAAS,eAAe,EAAE,SAAS,oCAAoC,CAAC;EAEpF,OAAO;CACT;CAEA,OAAO;EACL,MAAM,sBACJ,MACyE;GAEzE,OAAO,gBAAgF,MADrE,cAAc,CAAC,CAAC,aAAa,WAAW,EAAE,KAAK,CAAC,CACwB;EAC5F;EACA,MAAM,kBAAkB,WAAqC;GAE3D,OAAO,gBAAgB,MADL,cAAc,CAAC,CAAC,aAAa,OAAO,SAAS,CACrC;EAC5B;EACA,MAAM,oBAAoB,MAAoD;GAE5E,OAAO,gBAAgB,MADL,cAAc,CAAC,CAAC,aAAa,oBAAoB,EAAE,KAAK,CAAC,CACjD;EAC5B;EACA,MAAM,eAAe,MAA+C;GAElE,OAAO,gBAAgB,MADL,cAAc,CAAC,CAAC,UAAU,OAAO,EAAE,KAAK,CAAC,CACjC;EAC5B;EACA,MAAM,cAAc,aAAuC;GAEzD,OAAO,gBAAgB,MADL,cAAc,CAAC,CAAC,UAAU,MAAM,WAAW,CACnC;EAC5B;EACA,MAAM,eACJ,aACA,MACkB;GAIlB,OAAO,gBAAgB,MAHL,cAAc,CAAC,CAAC,UAAU,OAAO,aAAa,EACxD,KACR,CAAC,CACyB;EAC5B;EACA,MAAM,eAA8E;GAElF,OAAO,gBAAsE,MAD3D,cAAc,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAC8B;EAClF;EACA,MAAM,aAAa,WAAqC;GAEtD,OAAO,gBAAgB,MADL,cAAc,CAAC,CAAC,SAAS,MAAM,SAAS,CAChC;EAC5B;EACA,MAAM,YAAuE;GAE3E,OAAO,gBAAkE,MADvD,cAAc,CAAC,CAAC,MAAM,KAAK,CAC+B;EAC9E;EACA,MAAM,mBAAmB,MAAmD;GAE1E,OAAO,gBAAgB,MADL,cAAc,CAAC,CAAC,cAAc,OAAO,EAAE,KAAK,CAAC,CACrC;EAC5B;EACA,MAAM,kBAAkB,kBAA4C;GAElE,OAAO,gBAAgB,MADL,cAAc,CAAC,CAAC,cAAc,MAAM,gBAAgB,CAC5C;EAC5B;EACA,MAAM,oBAAoB,MAAyD;GAEjF,OAAO,gBAAgB,MADL,cAAc,CAAC,CAAC,cAAc,QAAQ,EAAE,KAAK,CAAC,CACtC;EAC5B;EACA,MAAM,mBAAmB,MAAyD;GAEhF,OAAO,gBAAgB,MADL,cAAc,CAAC,CAAC,cAAc,OAAO,EAAE,KAAK,CAAC,CACrC;EAC5B;EACA,MAAM,uBAAuB,kBAAqD;GAEhF,OAAO,gBAAkC,MADvB,cAAc,CAAC,CAAC,cAAc,WAAW,gBAAgB,CAC/B;EAC9C;CACF;AACF;;;AC9KA,SAAS,WAAW,OAAyB;CAC3C,IAAI,UAAU,QAAQ,OAAO,UAAU,UAAU,OAAO;CACxD,MAAM,YAAY;CAClB,OAAO,UAAU,WAAW,OAAO,UAAU,eAAe;AAC9D;AAEA,SAAS,aAAa,UAAuC;CAC3D,IAAI,aAAa,QAAQ,OAAO,aAAa,UAAU,OAAO,KAAA;CAC9D,MAAM,OAAQ,SAAqC;CACnD,OAAO,OAAO,SAAS,YAAY,SAAS,KAAK,OAAO,KAAA;AAC1D;AAEA,SAAS,aAAa,UAAmB,WAAsC;CAC7E,IAAI,aAAa,QAAQ,OAAO,aAAa,UAAU,OAAO;CAC9D,MAAM,WAAW,sBAAuB,SAAqC,QAAQ;CACrF,MAAM,gBAAgB,UAAU,SAAS,SAAS,WAAW;CAC7D,MAAM,aAAa,UAAU,SAAS,SAAS,mBAAmB;CAClE,OACE,SAAS,mBAAmB,UAAU,MACtC,SAAS,gBAAgB,KAAA,MACxB,SAAS,iBAAiB,KAAA,KAAa,SAAS,iBAAiB,UAAU;AAEhF;AAEA,SAAS,SAAS,UAA4B;CAC5C,IAAI,aAAa,QAAQ,OAAO,aAAa,UAAU,OAAO;CAC9D,MAAM,WAAW,sBAAuB,SAAqC,QAAQ;CACrF,OACE,OAAO,SAAS,WAAW,YAC3B,OAAO,SAAS,mBAAmB,YACnC,OAAO,SAAS,iBAAiB;AAErC;AAEA,SAAS,kBAAkB,WAA6B,UAAwC;CAC9F,OAAO,0BAA0B;EAC/B,GAAG,sBAAsB,QAAQ;EACjC,cAAc,UAAU;EACxB,GAAI,UAAU,SAAS,SAAS,EAAE,QAAQ,UAAU,GAAG,IAAI,EAAE,gBAAgB,UAAU,GAAG;CAC5F,CAAC;AACH;AAEA,eAAsB,wBAAwB,OAM+B;CAC3E,MAAM,EAAE,SAAS,QAAQ,QAAQ,cAAc;CAC/C,MAAM,QAAQ,8BAA8B,OAAO;CACnD,MAAM,YAAY,MAAM,MAAM,wBAAwB,UAAU,MAAM,UAAU,EAAE;CAClF,IAAI;CACJ,IAAI;EAMF,cAAa,MALQ,QAAQ,QAAkD;GAC7E,OAAO,UAAU;GACjB,OAAO,CAAC;IAAE,OAAO;IAAM,OAAO,UAAU;GAAG,CAAC;GAC5C,QAAQ,CAAC,sBAAsB;EACjC,CAAC,EAAA,EACoB,wBAAwB,KAAA;CAC/C,QAAQ,CAER;CACA,MAAM,eAAe,UAAU,wBAAwB,WAAW,gBAAgB;CAClF,IAAI,OAAO,iBAAiB,YAAY,iBAAiB,IAAI;EAC3D,IAAI,cAAc,MAChB,MAAM,MAAM,aAAa,UAAU,MAAM,UAAU,IAAI,cAAc,UAAU,KAAK;EAEtF,OAAO;CACT;CAEA,MAAM,MAAM,sBAAsB,MAAM;CACxC,IAAI,WAA4C;CAChD,IAAI,OAAO,OAAO,UAAU,UAAU,YACpC,IAAI;EACF,WACI,MAAM,IAAI,cAAc,UAAU,KAAK,KACzC;CACJ,SAAS,OAAgB;EACvB,IAAI,CAAC,WAAW,KAAK,GAAG;GACtB,OAAO,MAAM,sEAAsE,KAAK;GACxF,OAAO;EACT;CACF;CAGF,IAAI,aAAa,MAAM;EACrB,MAAM,OAAO,aAAa,QAAQ;EAClC,IAAI,SAAS,KAAA,GAAW;GACtB,OAAO,MAAM,oDAAoD;GACjE,OAAO;EACT;EAEA,MAAM,QAAQ,aAAa,UAAU,SAAS;EAC9C,MAAM,iBACJ,UAAU,SAAS,UAAU,UAAU,kBAAkB,QAAQ,CAAC,SAAS,QAAQ;EACrF,IAAI,CAAC,SAAS,CAAC,gBAAgB;GAC7B,OAAO,MAAM,wDAAwD;GACrE,OAAO;EACT;EAEA,MAAM,mBAAoB,SAAgD;EAC1E,IAAI,kBAAkB,sBAAsB,gBAAgB,CAAC,CAAC,iBAAiB,UAAU,MACvF,MAAM,IAAI,eAAe,MAAM,EAC7B,UAAU,kBAAkB,WAAW,gBAAgB,EACzD,CAAC;EAEH,MAAM,MAAM,aAAa,UAAU,MAAM,UAAU,IAAI,MAAM,UAAU,KAAK;EAC5E,OAAO;GAAE,UAAU;GAAU,SAAS;EAAM;CAC9C;CAEA,MAAM,WAAY,MAAM,IAAI,eAAe;EACzC,GAAG,MAAM;EACT,OAAO,UAAU;EACjB,YAAY,UAAU,QAAQ,KAAA;EAC9B,UAAU,kBAAkB,SAAS;CACvC,CAAC;CACD,MAAM,OAAO,aAAa,QAAQ;CAClC,IAAI,SAAS,KAAA,GAAW,OAAO;CAC/B,MAAM,MAAM,aAAa,UAAU,MAAM,UAAU,IAAI,MAAM,UAAU,KAAK;CAC5E,OAAO;EAAE;EAAU,SAAS;CAAK;AACnC;;;AC/HA,SAAgB,kBAAkB,MAAwC;CACxE,IAAI,KAAK,eAAe,KAAA,GAAW;EACjC,IAAI,OAAO,KAAK,eAAe,YAAY,OAAO,SAAS,KAAK,UAAU,GACxE,OAAO,KAAK;EAEd,MAAM,IAAI,MAAM,gCAAgC,KAAK,KAAK,6BAA6B;CACzF;CAEA,IAAI,KAAK,gBAAgB,KAAA,KAAa,KAAK,gBAAgB,QAAQ,KAAK,gBAAgB,IACtF;CAGF,MAAM,SAAS,OAAO,KAAK,gBAAgB,WAAW,OAAO,KAAK,WAAW,IAAI,KAAK;CACtF,IAAI,OAAO,WAAW,YAAY,OAAO,SAAS,MAAM,GACtD,OAAO;CAGT,MAAM,IAAI,MACR,iCAAiC,KAAK,KAAK,4DAC7C;AACF;AAEA,SAAgB,oBAAoB,MAAoB,UAA0B;CAChF,QAAQ,KAAK,UAAU,KAAK,YAAY,kBAAkB,IAAI,KAAK;AACrE;AAEA,SAAgB,2BAA2B,OAAiD;CAC1F,MAAM,aAAa,OAAO,KAAK,CAAC,CAAC,YAAY;CAC7C,OAAO,eAAe,KAAA,KAAa,eAAe,KAAK,OAAO;AAChE;AAEA,SAAgB,wBAAwB,kBAAsD;CAC5F,OACE,OAAO,qBAAqB,aAC3B,iBAAiB,WAAW,MAAM,KAAK,iBAAiB,WAAW,YAAY;AAEpF;AAEA,SAAgB,6BACd,cACS;CACT,IAAI,wBAAwB,aAAa,gBAAgB,GACvD,OAAO;CAGT,IAAI,OAAO,aAAa,qBAAqB,YAAY,aAAa,qBAAqB,IACzF,OAAO;CAGT,OACE,aAAa,aAAa,KAAA,KAC1B,aAAa,aAAa,QAC1B,aAAa,aAAa;AAE9B;AAEA,SAAgB,iCACd,cACA,QACM;CACN,IAAI,CAAC,6BAA6B,YAAY,GAC5C,MAAM,IAAI,MACR,iDAAiD,OAAO,qEAC1D;AAEJ;AAEA,eAAsB,SACpB,qBACyB;CACzB,IAAI,qBAAqB,YAAY,MACnC,OAAO,OAAO,oBAAoB,UAAU,aACxC,oBAAoB,MAAM,IAC1B,oBAAoB;CAE1B,MAAM,IAAI,MAAM,wDAAwD;AAC1E;AAaA,eAAsB,cACpB,SACA,MAC8B;CAC9B,IAAI,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM,IAC9C,OAAO;CAET,IAAI,QAAQ,cAAc,YAAY,MAAM;EAC1C,MAAM,QAAQ,MAAM,SAAS,QAAQ,YAAY;EACjD,MAAM,iBAAiB,KAAK,YAAY;EACxC,OACE,MAAM,MACH,SAAS,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,YAAY,MAAM,cACzE,KAAK;CAET;CACA,OAAO;AACT;AAaA,eAAsB,YACpB,gBAC4B;CAC5B,IAAI,gBAAgB,UAClB,OAAO,OAAO,eAAe,aAAa,aACtC,MAAM,eAAe,SAAS,IAC9B,eAAe;CAErB,OAAO,CAAC;AACV;AAEA,eAAsB,iBACpB,SACA,MACiC;CACjC,OAAO,MAAM,YAAY,QAAQ,QAAQ,CAAC,CAAC,MAAM,aAC/C,aAAa,KAAA,KAAa,aAAa,OAClC,SAAS,MAAM,YAAY,QAAQ,KAAK,YAAY,MAAM,KAAK,YAAY,CAAC,KAAK,OAClF,IACN;AACF;AAEA,SAAgB,iBAAiB,WAAiB,UAAwB;CACxE,MAAM,OAAO,IAAI,KAAK,SAAS;CAC/B,QAAQ,UAAR;EACE,KAAK;GACH,KAAK,QAAQ,KAAK,QAAQ,IAAI,CAAC;GAC/B;EACF,KAAK;GACH,KAAK,QAAQ,KAAK,QAAQ,IAAI,CAAC;GAC/B;EACF,KAAK;GACH,KAAK,SAAS,KAAK,SAAS,IAAI,CAAC;GACjC;EACF,KAAK;GACH,KAAK,SAAS,KAAK,SAAS,IAAI,CAAC;GACjC;EACF,KAAK;GACH,KAAK,SAAS,KAAK,SAAS,IAAI,CAAC;GACjC;EACF,KAAK;GACH,KAAK,YAAY,KAAK,YAAY,IAAI,CAAC;GACvC;EACF,SAEE,KAAK,SAAS,KAAK,SAAS,IAAI,CAAC;CACrC;CACA,OAAO;AACT;;;;;AAMA,SAAgB,kBAAkB,QAAgB,UAA2B;CAS3E,MAAM,MAAM;EAPV,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;CAEc,EAAE,SAAS,YAAY;CAC5C,OAAO,QAAQ,KAAA,IAAY,UAAU,MAAM;AAC7C;AAEA,eAAsB,gCACpB,KACA,aACA,gBACe;CACf,MAAM,QAAQ,mBAAmB,GAAG;CAEpC,IAAI,eAAe,MAAM,MAAM,kBAAkB,WAAW;CAE5D,iBAAiB,MAAM,MAAM,kBAAkB,YAAY,YAAY,CAAC,CAAC,QAAQ,QAAQ,GAAG,CAAC;CAE7F,IACE,cAAc,eAAe,KAAA,KAC7B,aAAa,eAAe,QAC5B,aAAa,eAAe,IAC5B;EAEA,IACE,cAAc,OAAO,KAAA,KACrB,aAAa,cAAc,QAC3B,OAAO,aAAa,aAAa,YACjC,aAAa,WAAW,GAExB,MAAM,MAAM,cAAc,aAAa,IAAI;GACzC,UAAU,aAAa,WAAW;GAClC,2BAAW,IAAI,KAAK;EACtB,CAAC;EAEH;CACF;CAGA,IAAI;EACF,MAAM,oBAAoB,OAAO,aAAa,UAAU;EACxD,IAAI,CAAC,OAAO,SAAS,iBAAiB,GACpC;EAKF,MAAM,kBAAiB,MAHD,sBAAsB,cAAc,CAAC,CAAC,aAC1D,iBACF,EAAA,EAC+B;EAE/B,IAAI,mBAAmB,KAAA,KAAa,aAAa,OAAO,KAAA,GACtD,MAAM,MAAM,cAAc,aAAa,IAAI;GACzC,UAAU;GACV,2BAAW,IAAI,KAAK;EACtB,CAAC;CAEL,QAAQ;EAEN,IACE,cAAc,OAAO,KAAA,KACrB,aAAa,cAAc,QAC3B,OAAO,aAAa,aAAa,YACjC,aAAa,WAAW,GAExB,MAAM,MAAM,cAAc,aAAa,IAAI;GACzC,UAAU,aAAa,WAAW;GAClC,2BAAW,IAAI,KAAK;EACtB,CAAC;CAEL;AACF;AA0BA,eAAsB,sBACpB,KACA,gBACA,SACe;CACf,IAAI,QAAQ,cAAc,YAAY,MAAM;CAE5C,MAAM,QAAQ,mBAAmB,GAAG;CACpC,MAAM,iBAAiB,MAAM,MAAM,6BAA6B,cAAc,EAAA,CAAG,QAC9E,iBAAiB,aAAa,WAAW,YAAY,aAAa,WAAW,UAChF;CACA,MAAM,oBAAoC,CAAC;CAC3C,KAAK,MAAM,aAAa,eAAe;EACrC,MAAM,gBAAgB,MAAM,cAAc,SAAS,UAAU,IAAI;EACjE,IAAI,kBAAkB,QAAQ,kBAAkB,aAAa,MAAM,KAAA,GACjE,kBAAkB,KAAK,SAAS;CAEpC;CAEA,MAAM,YAAW,MADK,MAAM,YAAY,cAAc,EAAA,CAC7B;CACzB,KAAK,MAAM,gBAAgB,mBAAmB;EAC5C,IACE,aAAa,qBAAqB,KAAA,KAClC,aAAa,qBAAqB,QAClC,aAAa,qBAAqB,IAElC;EACF,IAAI;GACF,iCAAiC,cAAc,qBAAqB;GAGpE,MAAM,MAAM,mBAAmB,aAAa,IAAI;IAC9C,OAAO;IACP,2BAAW,IAAI,KAAK;GACtB,CAAC;EACH,SAAS,GAAY;GACnB,IAAI,QAAQ,OAAO,MAAM,qCAAqC,CAAC;EACjE;CACF;AACF;;;AC/TA,MAAa,8BAA8B,OACzC,KACA,gBACA,YACiC;CACjC,OAAO,mBAAmB,GAAG,CAAC,CAAC,wBAAwB,gBAAgB,OAAO;AAChF;AAEA,MAAa,iBAAiB,OAC5B,KACA,gBACA,aAAa,MACQ;CACrB,MAAM,QAAQ,mBAAmB,GAAG;CAIpC,MAAM,aAHiB,MAAM,MAAM,6BAA6B,cAAc,EAAA,CAAG,QAC9E,iBAAiB,aAAa,WAAW,YAAY,aAAa,WAAW,UAElD,CAAC,CAAC,QAC7B,SAAS,iBACR,OAAO,aAAa,UAAU,WAC1B,KAAK,IAAI,WAAW,aAAa,OAAO,aAAa,KAAK,IAC1D,SACN,KAAA,CACF;CACA,MAAM,UAAU,MAAM,MAAM,YAAY,cAAc;CAEtD,IAAI,cAAc,KAAA,GAChB,OAAO;CAGT,IAAI,QAAQ,SAAS,aAAa,WAChC,MAAM,IAAI,SAAS,aAAa,EAC9B,SAAS,4CAA4C,QAAQ,OAAO,SAAS,YAC/E,CAAC;CAGH,OAAO;AACT;AAEA,eAAsB,4BACpB,KACA,gBACA,SACiE;CACjE,MAAM,iBACJ,MAAM,mBAAmB,GAAG,CAAC,CAAC,6BAA6B,cAAc,EAAA,CACzE,QACC,iBAAiB,aAAa,WAAW,YAAY,aAAa,WAAW,UAChF;CACA,MAAM,SAAiC,CAAC;CACxC,MAAM,2BAAW,IAAI,IAAY;CACjC,KAAK,MAAM,gBAAgB,eAAe;EACxC,MAAM,OAAO,MAAM,cAAc,SAAS,aAAa,IAAI;EAC3D,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,MAAM,UAAU,CAAC,CAAC,GAC3D,IAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GACpD,OAAO,QAAQ,KAAK,IAAI,OAAO,SAAS,OAAO,KAAK;EAGxD,KAAK,MAAM,WAAW,MAAM,YAAY,CAAC,GAAG,SAAS,IAAI,OAAO;CAClE;CACA,OAAO;EAAE;EAAQ,UAAU,CAAC,GAAG,QAAQ;CAAE;AAC3C;AAEA,MAAa,iBAAiB,OAC5B,KACA,gBACA,aACqB;CAGrB,KAAI,MAFgB,mBAAmB,GAAG,CAAC,CAAC,UAAU,cAAc,EAAA,CAE1D,UAAU,UAClB,MAAM,IAAI,SAAS,aAAa,EAC9B,SAAS,+CAA+C,WAC1D,CAAC;CAGH,OAAO;AACT;;;ACjFA,MAAM,YAAY;AAClB,MAAM,UAAU;AAChB,MAAM,YAAY;AAElB,SAAS,UAAU,QAA4B;CAC7C,IAAI,OAAO,WAAW,YAAY,OAAO,KAAK,MAAM,IAClD,MAAM,IAAI,MAAM,mDAAmD;CAErE,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,QAAQ,MAAM,CAAC,CAAC,OAAO;AAC5D;AAEA,SAAgB,0BAA0B,OAAe,QAAwB;CAC/E,IAAI,UAAU,IAAI,MAAM,IAAI,MAAM,6CAA6C;CAC/E,MAAM,KAAK,YAAY,SAAS;CAChC,MAAM,SAAS,eAAe,WAAW,UAAU,MAAM,GAAG,EAAE;CAC9D,MAAM,aAAaA,OAAW,OAAO,CAAC,OAAO,OAAO,OAAO,MAAM,GAAG,OAAO,MAAM,CAAC,CAAC;CACnF,MAAM,UAAU,OAAO,WAAW;CAClC,OAAO;EAAC;EAAS,GAAG,SAAS,KAAK;EAAG,QAAQ,SAAS,KAAK;EAAG,WAAW,SAAS,KAAK;CAAC,CAAC,CAAC,KACxF,GACF;AACF;AAEA,SAAgB,0BAA0B,WAAmB,QAAwB;CACnF,MAAM,QAAQ,UAAU,MAAM,GAAG;CACjC,IAAI,MAAM,WAAW,KAAK,MAAM,OAAO,SACrC,MAAM,IAAI,MAAM,wCAAwC;CAE1D,MAAM,GAAG,OAAO,YAAY,iBAAiB;CAC7C,MAAM,KAAKA,OAAW,KAAK,OAAO,KAAK;CACvC,MAAM,UAAUA,OAAW,KAAK,YAAY,KAAK;CACjD,MAAM,aAAaA,OAAW,KAAK,eAAe,KAAK;CACvD,IAAI,GAAG,WAAW,aAAa,QAAQ,WAAW,MAAM,WAAW,WAAW,GAC5E,MAAM,IAAI,MAAM,wCAAwC;CAE1D,MAAM,WAAW,iBAAiB,WAAW,UAAU,MAAM,GAAG,EAAE;CAClE,SAAS,WAAW,OAAO;CAC3B,OAAOA,OAAW,OAAO,CAAC,SAAS,OAAO,UAAU,GAAG,SAAS,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM;AAC3F;AAEA,SAAgB,+BAA+B,SAGpC;CACT,MAAM,MAAM,QAAQ,2BAA2B,QAAQ;CACvD,IAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,MAAM,IAC5C,MAAM,IAAI,MAAM,iEAAiE;CAEnF,OAAO;AACT;;;AC1BA,eAAsB,+BACpB,SACA,SACA,gBACiD;CACjD,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,QAAQ,QAAiC;GACnD,OAAO,gBAAgB;GACvB,OAAO,CAAC;IAAE,OAAO;IAAkB,OAAO;GAAe,CAAC;EAC5D,CAAC;CACH,QAAQ;EACN,OAAO;CACT;CACA,IAAI,CAAC,KAAK,OAAO;CACjB,MAAM,MAAM,+BAA+B,OAAO;CAClD,MAAM,6BAA6B,IAAI;CACvC,MAAM,sBAAsB,IAAI;CAChC,OAAO;EACL,mBACE,OAAO,+BAA+B,YAAY,+BAA+B,KAC7E,0BAA0B,4BAA4B,GAAG,IACzD,KAAA;EACN,YACE,OAAO,wBAAwB,YAAY,wBAAwB,KAC/D,0BAA0B,qBAAqB,GAAG,IAClD,KAAA;CACR;AACF;AAEA,eAAsB,+BACpB,SACA,SACA,gBACA,QACe;CACf,MAAM,oBAAoB,OAAO,qBAAqB,KAAA;CACtD,MAAM,aAAa,OAAO,cAAc,KAAA;CACxC,IAAI,sBAAsB,KAAA,KAAa,eAAe,KAAA,GAAW;CACjE,MAAM,MAAM,+BAA+B,OAAO;CAClD,MAAM,sBAAM,IAAI,KAAK;CACrB,IAAI,WAA2C;CAC/C,IAAI;EACF,WAAW,MAAM,QAAQ,QAAiC;GACxD,OAAO,gBAAgB;GACvB,OAAO,CAAC;IAAE,OAAO;IAAkB,OAAO;GAAe,CAAC;EAC5D,CAAC;CACH,QAAQ,CAER;CACA,MAAM,SAAS;EACb,GAAI,sBAAsB,KAAA,IACtB,EAAE,4BAA4B,0BAA0B,mBAAmB,GAAG,EAAE,IAChF,CAAC;EACL,GAAI,eAAe,KAAA,IACf,EAAE,qBAAqB,0BAA0B,YAAY,GAAG,EAAE,IAClE,CAAC;EACL,WAAW;CACb;CACA,IAAI,aAAa,MAAM;EACrB,MAAM,QAAQ,OAAO;GACnB,OAAO,gBAAgB;GACvB;GACA,OAAO,CAAC;IAAE,OAAO;IAAM,OAAO,SAAS;GAAG,CAAC;EAC7C,CAAC;EACD;CACF;CACA,MAAM,QAAQ,OAAO;EACnB,OAAO,gBAAgB;EACvB,MAAM;GACJ;GACA,GAAG;GACH,WAAW;EACb;CACF,CAAC;AACH;;;ACtFA,MAAM,4BAA4B,CAAC,SAAS,OAAO;AAEnD,SAAS,sBAAsB,OAAuC;CACpE,OAAO,IAAI,IAAI,MAAM,KAAK,UAAU,MAAM,KAAK,CAAC,CAAC,CAAC,QAAQ,UAAU,UAAU,EAAE,CAAC;AACnF;AAEA,SAAgB,gBAAgB,SAAgD;CAC9E,OAAO,QAAQ,cAAc,gBAAgB;AAC/C;AAEA,SAAgB,eACd,MACA,eAAkC,2BACzB;CACT,MAAM,eAAe,sBAAsB,YAAY;CACvD,IAAI,MAAM,QAAQ,IAAI,GACpB,OAAO,KAAK,MAAM,UAAU,eAAe,OAAO,YAAY,CAAC;CAEjE,IAAI,OAAO,SAAS,UAClB,OAAO;CAET,OAAO,KACJ,MAAM,GAAG,CAAC,CACV,KAAK,UAAU,MAAM,KAAK,CAAC,CAAC,CAC5B,MAAM,UAAU,aAAa,IAAI,KAAK,CAAC;AAC5C;AAEA,SAAgB,0BAA0B,OAK/B;CACT,MAAM,OAAQ,MAAM,QAAQ,CAAC;CAC7B,MAAM,QAAS,MAAM,SAAS,CAAC;CAC/B,MAAM,0BACJ,OAAO,MAAM,eAAe,WACvB,IAAI,IAAI,MAAM,UAAU,CAAC,CAAC,aAAa,IAAI,aAAa,KAAK,KAAA,IAC9D,KAAA;CAEN,OACG,KAAK,eACL,MAAM,eACP,2BACA,MAAM;AAEV;AAEA,eAAsB,0BACpB,KACA,SACA,MAMe;CACf,IAAI,KAAK,gBAAgB,KAAK,KAAK,IAAI;CAEvC,IACE,QAAQ,cAAc,YAAY,QAClC,OAAO,QAAQ,aAAa,uBAAuB,YACnD;EAUA,IAAI,MATqB,QAAQ,aAAa,mBAC5C;GACE,MAAM,KAAK;GACX,SAAS,KAAK;GACd,aAAa,KAAK;GAClB,QAAQ,KAAK;EACf,GACA,GACF,MACmB,MAAM;EACzB,MAAM,IAAI,SAAS,cAAc;CACnC;CAEA,IAAI,QAAQ,cAAc,YAAY,MAAM;EAC1C,MAAM,SAAS,MAAM,IAAI,QAAQ,QAAQ,QAAQ;GAC/C,OAAO;GACP,OAAO,CACL;IAAE,OAAO;IAAU,OAAO,KAAK,KAAK;GAAG,GACvC;IAAE,OAAO;IAAkB,OAAO,KAAK;GAAY,CACrD;EACF,CAAC;EAED,IACE,WAAW,QACX,WAAW,KAAA,KACX,eAAgB,OAA8B,MAAM,gBAAgB,OAAO,CAAC,GAE5E;CAEJ;CAEA,MAAM,IAAI,SAAS,cAAc;AACnC;;;AC9FA,MAAM,iBAAiBC,IAAE,OAAO;CAC9B,SAASA,IAAE,QAAQ,CAAC;CACpB,WAAWA,IAAE,MAAMA,IAAE,KAAK;EAAC;EAAY;EAAU;CAAY,CAAC,CAAC;CAC/D,yBAAyBA,IAAE,QAAQ,CAAC,CAAC,SAAS;CAC9C,wBAAwBA,IAAE,OAAO,CAAC,CAAC,SAAS;AAC9C,CAAC;AAMD,MAAM,oBACJ,IAAI,SAAS,uBAAuB,EAClC,SAAS,2DACX,CAAC;;AAGH,eAAsB,6BACpB,KACA,WACA,cACA,QAAQ,4BACe;CACvB,MAAM,QAAQ,mBAAmB,GAAG;CACpC,MAAM,UAAU,GAAG,MAAM,GAAG,WAAW,QAAQ,CAAC,CAC7C,OAAO,KAAK,UAAU,CAAC,WAAW,aAAa,EAAE,CAAC,CAAC,CAAC,CACpD,OAAO,KAAK;CACf,MAAM,mBACJ,IAAI,QAAQ,QAAQ,QAAoC;EACtD,OAAO,gBAAgB;EACvB,OAAO,CAAC;GAAE,OAAO;GAAW,OAAO;EAAQ,CAAC;CAC9C,CAAC;CACH,IAAI,SAAS,MAAM,WAAW;CAC9B,IAAI,WAAW,MAAM;EAEnB,IAAI,aAAa,WAAW,cAAc,OAAO;EACjD,IAAI;GACF,SAAS,MAAM,MAAM,mBAAmB;IACtC;IACA,WAAW;IACX;IACA,QAAQ;IACR,SAAS,KAAK,UAAU;KAAE,SAAS;KAAG,WAAW,CAAC;IAAE,CAAC;IACrD,2BAAW,IAAI,KAAK;IACpB,2BAAW,IAAI,KAAK;GACtB,CAAC;EACH,SAAS,OAAO;GACd,SAAS,MAAM,WAAW;GAC1B,IAAI,WAAW,MAAM,MAAM;EAC7B;CACF;CACA,IAAI,OAAO,WAAW,aAAa,OAAO;CAC1C,IACE,OAAO,OAAO,WAAW,aAAa,KACtC,KAAK,IAAI,IAAI,IAAI,KAAK,OAAO,SAAS,CAAC,CAAC,QAAQ,IAAI,KAEpD,MAAM,YAAY;CACpB,MAAM,WAAW,eAAe,MAAM,KAAK,MAAM,OAAO,OAAO,CAAC;CAChE,MAAM,SAAS,cAAc,WAAW;CAUxC,IAAI,MATkB,IAAI,QAAQ,QAAQ,OAAO;EAC/C,OAAO,gBAAgB;EACvB,OAAO;GACL;IAAE,OAAO;IAAW,OAAO;GAAQ;GACnC;IAAE,OAAO;IAAU,OAAO,OAAO;GAAO;GACxC;IAAE,OAAO;IAAa,OAAO,OAAO;GAAU;EAChD;EACA,QAAQ;GAAE;GAAQ,2BAAW,IAAI,KAAK;EAAE;CAC1C,CAAC,MACe,MAAM,MAAM,YAAY;CACxC,OAAO;EAAE;EAAS;EAAQ;CAAS;AACrC;AAEA,eAAsB,kBACpB,KACA,OACA,cACA,MACe;CACf,IAAI,CAAC,MAAM,SAAS,UAAU,SAAS,YAAY,GAAG;EACpD,MAAM,WAAW,KAAK,KAAK;EAC3B,MAAM,MAAM,WAAW,eAAe,YAAY;EAClD,MAAM,SAAS,UAAU,KAAK,YAAY;EAC1C,MAAM,WAAW,KAAK,KAAK;CAC7B;CACA,MAAM,WAAW,KAAK,OAAO,IAAI;AACnC;AAEA,eAAsB,+BACpB,KACA,OACA,QACiB;CACjB,IAAI,MAAM,SAAS,2BAA2B,KAAA,GAC5C,OAAO,MAAM,SAAS;CACxB,IAAI,MAAM,SAAS,4BAA4B,MAC7C,MAAM,IAAI,SAAS,uBAAuB,EACxC,SACE,kHACJ,CAAC;CACH,MAAM,SAAS,0BAA0B;CACzC,MAAM,WAAW,KAAK,KAAK;CAC3B,MAAM,OAAO,MAAM,OAAO;CAC1B,IAAI,SAAS,KAAA,KAAa,SAAS,IAAI,MAAM,YAAY;CACzD,MAAM,SAAS,yBAAyB;CACxC,MAAM,WAAW,KAAK,KAAK;CAC3B,OAAO;AACT;AAEA,eAAe,WACb,KACA,OACA,YAAY,OACG;CAaf,IAAI,MAZkB,IAAI,QAAQ,QAAQ,OAAO;EAC/C,OAAO,gBAAgB;EACvB,OAAO,CACL;GAAE,OAAO;GAAW,OAAO,MAAM;EAAQ,GACzC;GAAE,OAAO;GAAU,OAAO,MAAM;EAAO,CACzC;EACA,QAAQ;GACN,SAAS,KAAK,UAAU,MAAM,QAAQ;GACtC,2BAAW,IAAI,KAAK;GACpB,GAAI,YAAY;IAAE,QAAQ;IAAa,6BAAa,IAAI,KAAK;GAAE,IAAI,CAAC;EACtE;CACF,CAAC,MACe,MAAM,MAAM,YAAY;AAC1C;AAEA,eAAsB,+BACpB,KACA,SACA,OACA,cACA,MACA,OACe;CACf,IAAI,SAAS,KAAA,GAAW;EACtB,MAAM,YAAY;GAChB,UAAU,QAAQ,cAAc;GAChC,QAAQ,QAAQ,cAAc;EAChC;EACA,KAAK,MAAM,QAAQ,CAAC,YAAY,QAAQ,GAAY;GAClD,IAAI,MAAM,SAAS,UAAU,SAAS,IAAI,GAAG;GAG7C,MAAM,WAAW,KAAK,KAAK;GAC3B,MAAM,UAAU,KAAK,GAAG;IAAE;IAAO;IAAc;GAAK,GAAG,GAAG;GAC1D,MAAM,SAAS,UAAU,KAAK,IAAI;GAClC,MAAM,WAAW,KAAK,KAAK;EAC7B;CACF;CACA,MAAM,WAAW,KAAK,OAAO,IAAI;AACnC;AAEA,eAAsB,+BACpB,KACA,OACe;CACf,MAAM,IAAI,QAAQ,QAAQ,OAAO;EAC/B,OAAO,gBAAgB;EACvB,OAAO,CACL;GAAE,OAAO;GAAW,OAAO,MAAM;EAAQ,GACzC;GAAE,OAAO;GAAU,OAAO,MAAM;EAAO,CACzC;EACA,QAAQ;GAAE,QAAQ;GAAW,2BAAW,IAAI,KAAK;EAAE;CACrD,CAAC;AACH;;;ACjFA,SAASC,iCACP,SACuC;CACvC,MAAM,WAAW,QAAQ,cAAc;CACvC,OAAO,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,IAAI,WAAW,KAAA;AACrE;AAEA,SAAS,6BACP,SACA,iBACS;CACT,IAAI,oBAAoB,KAAA,GAAW,OAAO;CAC1C,OAAO,YAAY,KAAA,KAAa,YAAY,QAAQ,gBAAgB,SAAS,OAAgB;AAC/F;AAEA,SAAS,gBAA+C;CACtD,OAAO;EACL,aAAa;GACX,OAAO;GACP,SAAS;EACX;EACA,cAAc;GACZ,OAAO;GACP,SAAS;GACT,kBAAkB;EACpB;EACA,UAAU,EACR,OAAO,MACT;EACA,SAAS,EACP,QAAQ,MACV;CACF;AACF;AAEA,SAAS,gBAAgB,OAAgB,UAA0B;CACjE,OAAO,iBAAiB,SAAS,MAAM,YAAY,KAAK,MAAM,UAAU;AAC1E;AAEA,SAAS,oBAAoB,OAOW;CACtC,OAAO;EACL,IAAI;EACJ,QAAQ,MAAM;EACd,QAAQ,MAAM;EACd,WAAW,MAAM;EACjB,MAAM,MAAM;EACZ,OAAO,MAAM;EACb,GAAG,MAAM;CACX;AACF;AAEA,SAAS,qBACP,OAIqC;CACrC,IAAI,MAAM,cACR,MAAM,IAAI,SAAS,MAAM,WAAW;EAClC,MAAM,MAAM,MAAM;EAClB,SAAS,MAAM,MAAM;EACrB,QAAQ,MAAM,MAAM;CACtB,CAAC;CAGH,OAAO,oBAAoB,KAAK;AAClC;AAEA,SAAS,qBAAqB,OAGlB;CACV,OACE,MAAM,wBAAwB,KAAA,KAC9B,MAAM,wBAAwB,MAC9B,MAAM,2BAA2B,KAAA,KACjC,MAAM,2BAA2B,QACjC,MAAM,2BAA2B,MACjC,MAAM,wBAAwB,MAAM;AAExC;AAEA,SAAS,kBAAkB,OAAoC;CAC7D,OAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ,KAAA;AAC7D;AAEA,eAAsB,6BACpB,KACA,SACA,OAC6C;CAC7C,MAAM,SAAS,MAAM,UAAU;CAC/B,MAAM,eAAe,MAAM,iBAAiB;CAC5C,MAAM,UAAU,cAAc;CAC9B,MAAM,WAAW,eAAe,QAAQ,cAAc;CACtD,IAAI;CAEJ,IAAI;EAEF,OAAO,gBAA6C,MAD5B,UAAU,aAAa,OAAO,MAAM,SAAS,CACR;CAC/D,SAAS,OAAgB;EACvB,IAAI,QAAQ,OAAO,MAAM,yCAAyC,KAAK;EACvE,OAAO,qBAAqB;GAC1B;GACA,WAAW;GACX;GACA,QAAQ;GACR,WAAW,MAAM;GACjB,MAAM;GACN;GACA,OAAO;IACL,MAAM;IACN,SAAS,gBAAgB,OAAO,8BAA8B;IAC9D,QAAQ;GACV;EACF,CAAC;CACH;CAEA,IAAI,SAAS,KAAA,KAAa,SAAS,MACjC,OAAO,qBAAqB;EAC1B;EACA,WAAW;EACX;EACA,QAAQ;EACR,WAAW,MAAM;EACjB,MAAM;EACN;EACA,OAAO;GACL,MAAM;GACN,SAAS;GACT,QAAQ;EACV;CACF,CAAC;CAGH,MAAM,SAAS,KAAK,UAAU;CAC9B,MAAM,YAAY,MAAM;CACxB,MAAM,gBAAiB,KAAyC;CAChE,MAAM,aACJ,kBAAkB,KAAA,KAAa,kBAAkB,OAAO,OAAO,aAAa,IAAI,KAAA;CAClF,MAAM,oBAAqB,KAAK,eAC5B;CACJ,MAAM,QAAQ,mBAAmB,GAAG;CACpC,MAAM,WAAW,MAAM,MAAM,2BAA2B,SAAS;CACjE,QAAQ,YAAY,QAAQ,aAAa;CACzC,QAAQ,YAAY,iBAAiB,UAAU;CAE/C,IACE,qBAAqB;EACnB,qBAAqB,MAAM;EAC3B,wBAAwB,UAAU;CACpC,CAAC,GAED,OAAO,qBAAqB;EAC1B;EACA,WAAW;EACX;EACA;EACA;EACA;EACA;EACA,OAAO;GACL,MAAM;GACN,SAAS;GACT,QAAQ;EACV;CACF,CAAC;CAGH,MAAM,cACJ,MAAM,eACN,kBAAkB,UAAU,WAAW,KACvC,kBAAkB,MAAM,OAAO,KAAK,EAAE;CACxC,QAAQ,YAAY,cAAc;CAElC,IACE,MAAM,UAAU,KAAA,KAChB,gBAAgB,KAAA,KAChB,gBAAgB,MAAM,MAAM,KAAK,IAEjC,IAAI;EACF,MAAM,0BAA0B,KAAK,SAAS;GAC5C,MAAM,MAAM,MAAM;GAClB,SAAS,MAAM,MAAM;GACrB;GACA,QAAQ;EACV,CAAC;CACH,SAAS,OAAgB;EACvB,OAAO,qBAAqB;GAC1B;GACA,WAAW;GACX;GACA;GACA;GACA;GACA;GACA,OAAO;IACL,MAAM;IACN,SAAS,gBAAgB,OAAO,+CAA+C;IAC/E,QAAQ;GACV;EACF,CAAC;CACH;CAGF,IACE,KAAK,cAAc,aAClB,aAAa,QAAQ,OAAO,SAAS,WAAW,YAAY,SAAS,WAAW,KAAK,UACrF,aAAa,QACZ,OAAO,SAAS,aAAa,YAC7B,SAAS,aAAa,KAAK,UAE7B,OAAO,qBAAqB;EAC1B;EACA,WAAW;EACX;EACA;EACA;EACA;EACA;EACA,OAAO;GACL,MAAM;GACN,SAAS;GACT,QAAQ;EACV;CACF,CAAC;CAGH,MAAM,oBAA4E;EAChF;EACA;EACA,QAAQ,KAAK;EACb,UAAU,KAAK;EACf,2BAAW,IAAI,KAAK;CACtB;CACA,MAAM,qBAAqB,MAAM,MAAM,6BAA6B,WAAW,iBAAiB;CAChG,QAAQ,YAAY,UAAU,uBAAuB;CACrD,QAAQ,YAAY,SAAS;CAE7B,IAAI,WAAW,WACb,OAAO;EACL,IAAI;EACJ;EACA;EACA;EACA;EACA,GAAG;CACL;CAGF,MAAM,8BAA8BA,iCAA+B,OAAO;CAK1E,KAHG,UAAU,SAAS,KAAA,KAAa,SAAS,SAAS,QAAQ,SAAS,SAAS,MAC7E,QAAS,KAA4B,IAAI,MAIzC,6BAA6B,KAAK,WAAW,KAAA,GAAW,2BAA2B,MAAM,OACzF;EACA,MAAM,MAAM,6BAA6B,WAAW;GAClD,GAAG;GACH,QAAQ;EACV,CAAC;EACD,QAAQ,YAAY,UAAU;EAC9B,QAAQ,YAAY,SAAS;EAE7B,OAAO,qBAAqB;GAC1B;GACA,WAAW;GACX;GACA,QAAQ;GACR;GACA;GACA;GACA,OAAO;IACL,MAAM;IACN,SAAS,sCAAsC,6BAA6B,KAAK,IAAI,KAAK,mBAAmB;IAC7G,QAAQ;GACV;EACF,CAAC;CACH;CAEA,MAAM,mCAAmC,KAAK,UAAU;CACxD,IACE,qCAAqC,KAAA,KACrC,qCAAqC,QACrC,qCAAqC,MACrC,gBAAgB,KAAA,KAChB,gBAAgB,IAChB;EACA,IAAI,iBACF,QAAQ,cAAc,YAAY,QAClC,OAAO,gBAAgB,YACvB,YAAY,WAAW,MAAM;EAC/B,IAAI,mBAAmB,SAAS,QAAQ,cAAc,YAAY,MAEhE,iBAAiB,MADU,MAAM,iBAAiB,WAAW,MAC3B;EAGpC,MAAM,MAAM,iBACV,aACA,kCACA,gBACA,KAAK,UAAU,KACjB;EACA,QAAQ,SAAS,QAAQ;EACzB,QAAQ,SAAS,cAAc;EAC/B,QAAQ,SAAS,eAAe;EAChC,QAAQ,SAAS,QAAQ,iBAAiB,iBAAiB;CAC7D;CAEA,MAAM,cAAc,sBAAuB,MAAM,MAAM,2BAA2B,SAAS;CAC3F,IACE,gBAAgB,KAAA,KAChB,gBAAgB,QAChB,YAAY,YAAY,KAAA,KACxB,YAAY,YAAY,QACxB,YAAY,YAAY,MACxB,QAAQ,mBAAmB,KAAA,KAC3B,QAAQ,mBAAmB,MAC3B;EACA,MAAM,gCAAgC,KAAK,YAAY,SAAS,QAAQ,cAAc;EACtF,QAAQ,QAAQ,SAAS;EACzB,QAAQ,QAAQ,OAAO,YAAY;CACrC;CAEA,IAAI,QAAQ,cAAc,YAAY,MACpC,OAAO;EACL,IAAI;EACJ;EACA;EACA;EACA;EACA,GAAG;CACL;CAGF,MAAM,cAAc,sBAAsB,KAAK,QAAQ;CACvD,MAAM,UAAU,mBAAmB,aAAa,SAAS;CACzD,MAAM,WAAW,kBAAkB,aAAa,UAAU;CAC1D,MAAM,aAAa,kBAAkB,aAAa,MAAM;CAExD,IAAI,YAAY,SAAS,aAAa;EACpC,MAAM,iBAAiB,kBAAkB,aAAa,gBAAgB;EACtE,MAAM,UAAU,kBAAkB,aAAa,SAAS;EACxD,MAAM,eAAe,kBAAkB,aAAa,cAAc;EAElE,IACE,mBAAmB,KAAA,KACnB,mBAAmB,MACnB,YAAY,KAAA,KACZ,YAAY,IACZ;GACA,MAAM,uBAAuB,MAAM,MAAM,qBAAqB,cAAc;GAC5E,IACE,CAAC,wBACD,qBAAqB,WAAW,cAChC,qBAAqB,yBAAyB,WAE9C,OAAO;IAAE,IAAI;IAAM;IAAQ;IAAQ;IAAW;IAAM,GAAG;GAAQ;GACjE,MAAM,sBAAsB,MAAM,MAAM,mBAAmB,gBAAgB;IACzE,MAAM;IACN,GAAI,OAAO,iBAAiB,WAAW,EAAE,OAAO,aAAa,IAAI,CAAC;IAClE,sBAAsB;IACtB,2BAAW,IAAI,KAAK;GACtB,CAAC;GACD,QAAQ,aAAa,QAAQ,wBAAwB;GACrD,QAAQ,aAAa,UAAU,wBAAwB;GACvD,QAAQ,aAAa,KAAK,qBAAqB,MAAM;GACrD,QAAQ,aAAa,SAAS,qBAAqB;GACnD,QAAQ,aAAa,mBAAmB,wBAAwB;GAChE,IACE,wBAAwB,QACxB,sBAAsB,KAAA,KACtB,sBAAsB,QACtB,sBAAsB,IAEtB,MAAM,+BAA+B,IAAI,QAAQ,SAAS,SAAS,oBAAoB,IAAI,EACzF,kBACF,CAAC;EAEL;EAEA,OAAO;GACL,IAAI;GACJ;GACA;GACA;GACA;GACA,GAAG;EACL;CACF;CAEA,IAAI;CAEJ,MAAM,aAAY,MADS,MAAM,wCAAwC,SAAS,EAAA,CACnD,MAC5B,iBACC,gBAAgB,KAAA,KAAa,gBAAgB,MAAM,aAAa,gBAAgB,WACpF;CACA,QAAQ,aAAa,QAAQ,cAAc,KAAA;CAC3C,QAAQ,aAAa,KAAK,WAAW;CACrC,QAAQ,aAAa,SAAS,WAAW;CAGzC,IAAI,CAAC,aAAa,CAAC;EAAC;EAAc;EAAU;CAAU,CAAC,CAAC,SAAS,UAAU,MAAM,GAC/E,OAAO;EAAE,IAAI;EAAM;EAAQ;EAAQ;EAAW;EAAM,GAAG;CAAQ;CAEjE,MAAM,QAAQ,MAAM,6BAA6B,KAAK,WAAW,SAAS;CAC1E,IAAI,UAAU,MAAM,OAAO;EAAE,IAAI;EAAM;EAAQ;EAAQ;EAAW;EAAM,GAAG;CAAQ;CACnF,IAAI;EACF,IAAI,UAAU,WAAW,cAAc;GACrC,IACE,sBAAsB,KAAA,KACtB,sBAAsB,QACtB,sBAAsB,IAEtB,MAAM,+BAA+B,IAAI,QAAQ,SAAS,SAAS,UAAU,IAAI,EAC/E,kBACF,CAAC;GAEH,MAAM,MAAM,6BACV,UAAU,aACV,UAAU,WAAW,MACrB,UAAU,EACZ;GAKA,MAAM,+BACJ,KACA,SACA,OACA,YAPW,MADO,SAAS,QAAQ,YAAY,EAAA,CAC9B,MAChB,cAAc,UAAU,KAAK,YAAY,MAAM,UAAU,KAAK,YAAY,CAO3E,GACA,IACF;GACA,OAAO;IAAE,IAAI;IAAM;IAAQ;IAAQ;IAAW;IAAM,GAAG;GAAQ;EACjE;EAEA,IAAI,WAAW,eAAe,KAAA,KAAa,aAAa,KAAA,GAAW;GACjE,MAAM,QAAQ,KAAK,UAAU;GAE7B,MAAM,cAAa,MADC,SAAS,QAAQ,YAAY,EAAA,CACxB,MAAM,SAAS,KAAK,KAAK,YAAY,MAAM,WAAW,YAAY,CAAC;GAE5F,IACE,eAAe,KAAA,KACf,eAAe,SACd,WAAW,aAAa,KAAA,KACvB,WAAW,aAAa,QACxB,WAAW,aAAa,KAE1B,mBAAmB,OAAO;QACrB,IACL,WAAW,qBAAqB,KAAA,KAChC,UAAU,qBAAqB,QAC/B,UAAU,qBAAqB,IAE/B,mBAAmB,UAAU;QACxB,IACL,sBAAsB,KAAA,KACtB,sBAAsB,QACtB,UAAU,KAAA,KACV,UAAU,QACV,UAAU,MACV,YAAY,aAAa,KAAA,KACzB,WAAW,aAAa,QACxB,WAAW,aAAa,IACxB;IACA,MAAM,WAAW,WAAW;IAC5B,mBAAmB,MAAM,+BAA+B,KAAK,OAAO,YAAY;KAW9E,OADE,gBAAwE,MATlD,UAAU,cAAc,OAAO,EACrD,MAAM;MACJ,UAAU;MACV,MAAM;MACN,eAAe;MACf,YAAY;KACd,EACF,CAAC,CAGW,CAAC,EAAE;IACjB,CAAC;GACH;EACF,OAAO,IAAI,YAAY,OAAO;GAC5B,MAAM,uBAAwB,KAAkD,MAC5E;GACJ,IACE,yBAAyB,KAAA,KACzB,yBAAyB,QACzB,yBAAyB,IAEzB,mBAAmB,OAAO;QAE1B,mBACG,KAAkE,cAC/D,qBAAqB,KAAA;EAE/B;EAEA,IAAI,sBAA2C;EAC/C,IAAI,cAAc,KAAA,KAAa,cAAc,MAAM;GAEjD,MAAM,gBAAe,MADD,SAAS,QAAQ,YAAY,EAAA,CACtB,MACxB,cAAc,UAAU,KAAK,YAAY,MAAM,UAAU,KAAK,YAAY,CAC7E;GACA,sBAAsB,MAAM,IAAI,QAAQ,QAAQ,OAAqB;IACnE,OAAO,gBAAgB;IACvB,OAAO;KACL;MAAE,OAAO;MAAM,OAAO,UAAU;KAAG;KACnC;MAAE,OAAO;MAAU,OAAO;KAAa;KACvC;MAAE,OAAO;MAAwB,OAAO;KAAU;IACpD;IACA,QAAQ;KACN,QAAQ,UAAU,aAAa;KAC/B,iBAAiB,cAAc,YAAY,UAAU,mBAAmB;KACxE,6BAAa,IAAI,KAAK;KACtB,2BAAW,IAAI,KAAK;KACpB,GAAI,WAAW,aAAa,KAAA,IACxB;MACE,4BAAY,IAAI,KAAK;MACrB,UAAU,IAAI,KAAK,QAAQ;MAC3B,WAAW,IAAI,KAAK,QAAQ;KAC9B,IACA,CAAC;KACL,GAAI,qBAAqB,KAAA,IAAY,EAAE,iBAAiB,IAAI,CAAC;IAC/D;GACF,CAAC;GACD,QAAQ,aAAa,UAAU,wBAAwB;GACvD,QAAQ,aAAa,KAAK,qBAAqB,MAAM,UAAU;GAC/D,QAAQ,aAAa,SAAS,qBAAqB,UAAU,UAAU;GACvE,IACE,sBAAsB,KAAA,KACtB,sBAAsB,QACtB,sBAAsB,MACtB,wBAAwB,MAExB,MAAM,+BAA+B,IAAI,QAAQ,SAAS,SAAS,oBAAoB,IAAI,EACzF,kBACF,CAAC;GAEH,IACE,wBAAwB,SACvB,oBAAoB,WAAW,YAAY,oBAAoB,WAAW,aAE3E,MAAM,MAAM,6BACV,oBAAoB,aACpB,oBAAoB,WAAW,MAC/B,oBAAoB,EACtB;EAEJ;EAEA,IAAI,wBAAwB,KAAA,KAAa,wBAAwB,MAAM;GAErE,MAAM,QAAO,MADO,SAAS,QAAQ,YAAY,EAAA,CAC9B,MAChB,cAAc,UAAU,KAAK,YAAY,MAAM,oBAAoB,KAAK,YAAY,CACvF;GACA,MAAM,+BACJ,KACA,SACA,OACA,qBACA,MACA,IACF;EACF,OACE,MAAM,IAAI,SAAS,uBAAuB,EACxC,SAAS,0DACX,CAAC;EAGH,OAAO;GACL,IAAI;GACJ;GACA;GACA;GACA;GACA,GAAG;EACL;CACF,SAAS,OAAO;EACd,MAAM,+BAA+B,KAAK,KAAK;EAC/C,MAAM;CACR;AACF;;;ACzqBA,MAAa,uBACX,SACA,WAEA,qBAAqB,OAAO,QAAQ;CAClC,MAAM,UAAU,IAAI,QAAQ;CAE5B,IAAI,YAAY,QAAQ,YAAY,KAAA,GAClC,MAAM,IAAI,SAAS,cAAc;CAEnC,MAAM,cAAc,0BAA0B;EAC5C,MAAM,IAAI;EACV,OAAO,IAAI;EACX,YAAY,IAAI,SAAS;EACzB,gBAAgB,QAAQ,KAAK;CAC/B,CAAC;CAED,MAAM,0BAA0B,KAAK,SAAS;EAC5C,MAAM,QAAQ;EACd,SAAS,QAAQ;EACjB;EACA;CACF,CAAC;CAED,OAAO,EACL,SAAS;EACP,GAAG,IAAI;EACP;CACF,EACF;AACF,CAAC;;;;ACxCH,SAAS,qBAAqB,OAAwB;CACpD,KAAK,MAAM,aAAa,OAAO;EAC7B,MAAM,YAAY,UAAU,YAAY,CAAC;EACzC,IACE,cAAc,KAAA,MACb,aAAa,MAAS,aAAa,OAAQ,aAAa,MAEzD,OAAO;CAEX;CACA,OAAO;AACT;AAEA,SAAgB,qBAAqB,aAAqB,SAA0B;CAClF,IACE,YAAY,WAAW,IAAI,KAC3B,YAAY,SAAS,IAAI,KACzB,qBAAqB,WAAW,GAEhC,OAAO;CAET,IAAI;EACF,MAAM,OAAO,IAAI,IAAI,OAAO;EAE5B,IAAI,CADsB,gBAAgB,KAAK,WAC1B,KAAK,CAAC,YAAY,WAAW,GAAG,GAAG,OAAO;EAC/D,MAAM,WAAW,IAAI,IAAI,aAAa,IAAI;EAC1C,QACG,SAAS,aAAa,WAAW,SAAS,aAAa,aACxD,SAAS,WAAW,KAAK,UACzB,SAAS,aAAa,MACtB,SAAS,aAAa;CAE1B,QAAQ;EACN,OAAO;CACT;AACF;;;AC9BA,eAAsB,mBAAmB,KAAyD;CAChG,OAAO,mBAAmB,GAAG,CAAC,CAAC,aAAa;AAC9C;AAEA,eAAsB,gBAAgB,KAAsD;CAC1F,OAAO,mBAAmB,GAAG,CAAC,CAAC,UAAU;AAC3C;AAEA,eAAsB,qBAAqB,SAGxC;CAGD,OAAO;EAAE,OAFK,QAAQ,cAAc,YAAY,OAAO,MAAM,SAAS,QAAQ,YAAY,IAAI,CAAC;EAE/E,UAAA,MADO,YAAY,QAAQ,QAAQ;CAC1B;AAC3B;;;AClBA,MAAa,kCAeR,EAAE,OAAO;CACZ,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS;CAC1B,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS;CAC7B,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CAC7C,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS;CAC9B,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;CAC3B,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS;CACrD,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS;CACjC,gBAAgB,EAAE,OAAO,CAAC,CAAC,SAAS;CACpC,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS;CACjC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CAC/C,qBAAqB,EAAE,QAAQ,CAAC,CAAC,SAAS;CAC1C,mBAAmB,EAAE,QAAQ,CAAC,CAAC,SAAS;CACxC,kBAAkB,EAAE,QAAQ,CAAC,CAAC,SAAS;CACvC,gCAAgC,EAAE,QAAQ,CAAC,CAAC,SAAS;AACvD,CAAC;;;AC5BD,MAAa,uBAUT,iBAAiB;CACnB,wBAAwB;CACxB,6BAA6B;CAC7B,2BAA2B;CAC3B,kCAAkC;CAClC,8BAA8B;CAC9B,gCAAgC;CAChC,+BAA+B;CAC/B,6BAA6B;CAC7B,0CACE;AACJ,CAAC;AAED,SAAgB,+BACd,SACuC;CACvC,MAAM,WAAW,QAAQ,cAAc;CACvC,OAAO,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,IAAI,WAAW,KAAA;AACrE;AAEA,eAAsB,cAAc,QAAgB,SAAkC;CACpF,MAAM,UAAU,IAAI,YAAY;CAChC,MAAM,UAAU,QAAQ,OAAO,MAAM;CACrC,MAAM,UAAU,QAAQ,OAAO,OAAO;CAEtC,MAAM,SAAS,WAAW;CAC1B,IAAI,WAAW,KAAA,KAAa,WAAW,QAAQ,YAAY,QAAQ;EACjE,MAAM,SAAS,OAAO;EACtB,MAAM,MAAM,MAAM,OAAO,UAAU,OAAO,SAAS;GAAE,MAAM;GAAQ,MAAM;EAAU,GAAG,OAAO,CAC3F,MACF,CAAC;EACD,MAAM,YAAY,MAAM,OAAO,KAAK,QAAQ,KAAK,OAAO;EACxD,OAAO,MAAM,KAAK,IAAI,WAAW,SAAS,CAAC,CAAC,CACzC,KAAK,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAC3C,KAAK,EAAE;CACZ;CAEA,MAAM,EAAE,eAAe,MAAM,OAAO;CACpC,OAAO,WAAW,UAAU,MAAM,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,OAAO,KAAK;AAClE;;;ACnDA,MAAa,0BAKR,EAAE,OAAO;CACZ,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS;CACjC,kBAAkB,EAAE,OAAO;CAC3B,YAAY,EAAE,OAAO,CAAC,CAAC,SAAS;CAChC,aAAa,EAAE,QAAQ,CAAC,CAAC,SAAS;AACpC,CAAC;AAED,SAAgB,wBAAwB,OAAuB;CAC7D,MAAM,aAAa,MAAM,QAAQ,MAAM,GAAG,CAAC,CAAC,QAAQ,MAAM,GAAG;CAC7D,MAAM,SAAS,aAAa,MAAM,OAAO,WAAW,SAAS,KAAK,CAAC;CACnE,MAAM,eAAe,KAAK,MAAM;CAChC,MAAM,QAAQ,IAAI,WAAW,aAAa,MAAM;CAChD,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KACvC,MAAM,KAAK,aAAa,WAAW,CAAC;CAEtC,OAAO,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK;AACvC;AAEA,SAAgB,2CAA2C,MAAkC;CAC3F,IAAI;EAEF,MAAM,oBAAoB,IADV,IAAI,IACQ,CAAC,CAAC,aAAa,IAAI,oBAAoB;EACnE,IAAI,sBAAsB,KAAA,KAAa,sBAAsB,QAAQ,sBAAsB,IACzF,OAAO,KAAA;EACT,MAAM,QAAQ,kBAAkB,MAAM,GAAG;EACzC,IAAI,MAAM,SAAS,GAAG,OAAO,KAAA;EAC7B,MAAM,cAAc,wBAAwB,MAAM,MAAM,EAAE;EAC1D,MAAM,UAAU,KAAK,MAAM,WAAW;EACtC,OAAO,OAAO,QAAQ,gBAAgB,WAAW,QAAQ,cAAc,KAAA;CACzE,QAAQ;EACN;CACF;AACF;;;ACtCA,SAAgB,kBAAkB,KAAkD;CAClF,OACG,IAA8C,gBAC9C,IAA8B;AAEnC;AAEA,SAAgB,kBAAkB,KAAkD;CAClF,OACG,IAAuD,WACvD,IAAI,SAA8C;AAEvD;AAEA,SAAgB,mBACd,KACA,SACoB;CACpB,OACE,SAAS,IAAI,iBAAiB,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,KACrD,SAAS,IAAI,WAAW,KACvB,IAAI,QAAuC;AAEhD;;;;ACKA,eAAsB,yBACpB,KACA,SACA,WACA,KAIkB;CAClB,MAAM,QAAQ,SAAS,cAAc;CACrC,IAAI,UAAU,KAAA,GAAW,OAAO,IAAI,KAAA,SAAiB,KAAA,CAAS;CAC9D,MAAM,WAAW,MAAM,MAAM,OAAO,WAAW,GAAG;CAClD,IAAI,SAAS,SAAS,UAAU;EAS9B,IAAI,EAPF,UAAU,SAAS,aACf,SAAS,OAAO,SAAS,cACzB,UAAU,SAAS,eACjB,SAAS,OAAO,SAAS,aACzB,UAAU,SAAS,iBACjB,SAAS,OAAO,SAAS,aACzB,SAAS,OAAO,SAAS,cAAc,SAAS,OAAO,SAAS,aAExE,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,gEACX,CAAC;EACH,OAAO,SAAS;CAClB;CACA,IAAI,SAAS,SAAS,SACpB,MAAM,IAAI,SAAS,YAAY,EAC7B,SAAS,SAAS,WAAW,qCAC/B,CAAC;CAEH,IACE,SAAS,SAAS,aAClB,OAAO,SAAS,sBAAsB,YACtC,SAAS,kBAAkB,KAAK,MAAM,IAEtC,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,oDACX,CAAC;CAEH,MAAM,aAAa;EACjB,GAAG;EACH,mBAAmB,SAAS;EAC5B,SAAS,SAAS;CACpB;CACA,IAAI,QACF,UAAU,SAAS,cAAc,UAAU,SAAS,iBAAiB,gBAAgB;CACvF,IAAI;EACF,MAAM,SAAS,MAAM,IAAI,SAAS,oBAAoB,SAAS;GAC7D,QAAQ;EACV,CAAC;EACD,QAAQ;EACR,MAAM,MAAM,QAAQ;GAAE,GAAG;GAAY;EAAO,GAAG,GAAG;EAClD,OAAO;CACT,SAAS,OAAgB;EACvB,IAAI;GACF,MAAM,MAAM,UAAU;IAAE,GAAG;IAAY;IAAO;GAAM,GAAG,GAAG;EAC5D,QAAQ;GACN,IAAI,QAAQ,OAAO,MAAM,wCAAwC,EAAE,MAAM,CAAC;EAC5E;EACA,MAAM;CACR;AACF;AAqBA,eAAsB,oCACpB,KACA,OAQA,SAC0E;CAC1E,MAAM,UAAU,2BAA2B,MAAM,MAAM,KAAK;CAC5D,IAAI,MAAM,SAAS,KAAA,KAAa,MAAM,wBAAwB,MAAM;EAClE,MAAM,cACJ,MAAM,mBAAmB,KAAA,IACrB,MAAM,4BAA4B,KAAK,MAAM,aAAa,OAAO,IACjE,MAAM,mBAAmB,GAAG,CAAC,CAAC,qBAAqB,MAAM,cAAc;EAC7E,IAAI,aAAa,WAAW,UAC1B,OAAO,yBACL,KACA,SACA;GACE,OAAO,EAAE,IAAI,MAAM,UAAU,YAAY,OAAO;GAChD,aAAa,MAAM;GACnB,MAAM;GACN,cAAc;GACd,QAAQ;IACN,MAAM,MAAM,MAAM,QAAQ,YAAY;IACtC,UAAU,MAAM,MAAM,YAAY,YAAY,mBAAmB,KAAA;IACjE;IACA,qBAAqB,MAAM;IAC3B,mBAAmB,MAAM;GAC3B;EACF,GACA,YAAY;GACV,MAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO,gBAAgB;IACvB,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,YAAY;IAAG,CAAC;IAC9C,QAAQ;KACN,aAAa,MAAM,MAAM;KACzB,2BAAW,IAAI,KAAK;IACtB;GACF,CAAC;GACD,OAAO;IACL,MAAM;IACN,QAAQ;IACR,SAAS;IACT,WAAW;GACb;EACF,CACF;CAEJ;CAEA,IAAI,MAAM,sBAAsB,MAAM;EACpC,MAAM,cACJ,MAAM,mBAAmB,KAAA,IACrB,MAAM,4BACJ,KACA,MAAM,aACN,MAAM,SAAS,KAAA,IAAY,KAAA,IAAY,OACzC,IACA,MAAM,mBAAmB,GAAG,CAAC,CAAC,qBAAqB,MAAM,cAAc;EAC7E,IAAI,aAAa,WAAW,UAC1B,OAAO,yBACL,KACA,SACA;GACE,OAAO,EAAE,IAAI,MAAM,UAAU,YAAY,OAAO;GAChD,aAAa,MAAM;GACnB,MAAM;GACN,cAAc;GACd,QAAQ;IACN,MAAM,MAAM,MAAM,QAAQ,YAAY;IACtC,UAAU,MAAM,MAAM,YAAY,YAAY,mBAAmB,KAAA;IACjE;IACA,qBAAqB,MAAM;IAC3B,mBAAmB,MAAM;GAC3B;EACF,GACA,YAAY;GACV,MAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO,gBAAgB;IACvB,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO,YAAY;IAAG,CAAC;IAC9C,QAAQ;KACN,mBAAmB;KACnB,UAAU,YAAY,aAAa;KACnC,4BAAY,IAAI,KAAK;KACrB,2BAAW,IAAI,KAAK;IACtB;GACF,CAAC;GAED,OAAO;IACL,MAAM;IACN,QAAQ;IACR,SAAS;IACT,WAAW;GACb;EACF,CACF;CAEJ;CAEA,OAAO;AACT;AAEA,eAAsB,sBACpB,KACA,OAIiC;CACjC,MAAM,gBACJ,MAAM,MAAM,WAAW,SAAS,KAAA,KAAa,MAAM,KAAK,UAAU,OAAO,IACrE,MAAM,KAAK,UAAU,OACrB;CACN,MAAM,YAAY,gBAAgB;CAClC,IAAI,CAAC,WACH,OAAO;EACL;EACA,WAAW;EACX,SAAS;CACX;CAcF,KAPiB,MAJY,IAAI,QAAQ,QAAQ,SAAuB;EACtE,OAAO,gBAAgB;EACvB,OAAO,CAAC;GAAE,OAAO;GAAe,OAAO,MAAM;EAAY,CAAC;CAC5D,CAAC,EAAA,EACgC,MAC9B,iBACE,aAAa,eAAe,KAAA,KAAa,aAAa,eAAe,QACrE,aAAa,aAAa,KAAA,KAAa,aAAa,aAAa,QAClE,aAAa,WAAW,UAC5B,MAEiB,MACf,OAAO;EACL;EACA;EACA,SAAS;EACT,cAAc;CAChB;CAGF,MAAM,6BAAa,IAAI,KAAK;CAC5B,MAAM,2BAAW,IAAI,KAAK;CAC1B,SAAS,QAAQ,SAAS,QAAQ,IAAI,aAAa;CAEnD,OAAO;EACL;EACA;EACA;EACA;EACA,SAAS;CACX;AACF;AAEA,eAAsB,2BACpB,KACA,SACA,OAKiB;CACjB,MAAM,cAAc,MAAM,SAAS,MAAM,KAAK;CAE9C,IACE,QAAQ,cAAc,YAAY,QAClC,MAAM,gBAAgB,MAAM,KAAK,MACjC,MAAM,gBAAgB,IAEtB,OAAO;CAGT,MAAM,MAAM,MAAM,IAAI,QAAQ,QAAQ,QAAQ;EAC5C,OAAO;EACP,OAAO,CAAC;GAAE,OAAO;GAAM,OAAO,MAAM;EAAY,CAAC;CACnD,CAAC;CACD,IAAI,QAAQ,KAAA,KAAa,QAAQ,MAC/B,OAAO;CAGT,MAAM,eAAe;CACrB,IACE,aAAa,UAAU,KAAA,KACvB,aAAa,UAAU,QACvB,aAAa,UAAU,IAEvB,OAAO,aAAa;CAGtB,MAAM,cAAc,MAAM,IAAI,QAAQ,QAAQ,QAAQ;EACpD,OAAO;EACP,OAAO,CACL;GAAE,OAAO;GAAkB,OAAO,MAAM;EAAY,GACpD;GAAE,OAAO;GAAQ,OAAO;EAAQ,CAClC;CACF,CAAC;CAED,IAAI,gBAAgB,KAAA,KAAa,gBAAgB,MAC/C,OAAO;CAGT,MAAM,YAAY,MAAM,IAAI,QAAQ,QAAQ,QAAc;EACxD,OAAO;EACP,OAAO,CAAC;GAAE,OAAO;GAAM,OAAQ,YAAmC;EAAO,CAAC;CAC5E,CAAC;CAED,OAAO,WAAW,UAAU,KAAA,KAAa,UAAU,UAAU,KAAK,UAAU,QAAQ;AACtF;AAEA,eAAsB,sBACpB,KACA,SACA,OAWwC;CACxC,MAAM,QAAQ,mBAAmB,GAAG;CACpC,MAAM,cACJ,MAAM,mBAAmB,KAAA,IACrB,MAAM,MAAM,wBACV,MAAM,aACN,2BAA2B,MAAM,KAAK,KAAK,CAC7C,IACA,MAAM,MAAM,qBAAqB,MAAM,cAAc;CAC3D,IACE,aAAa,WAAW,YACxB,YAAY,qBAAqB,KAAA,KACjC,YAAY,qBAAqB,QACjC,YAAY,qBAAqB,MACjC,YAAY,cAAc,KAAA,KAC1B,YAAY,cAAc,QAC1B,YAAY,gBAAgB,KAAA,KAC5B,YAAY,gBAAgB,MAE5B,OAAO;CAGT,MAAM,sBAAM,IAAI,KAAK;CACrB,MAAM,YAAY,IAAI,KAAK,YAAY,SAAS;CAChD,MAAM,cAAc,IAAI,KAAK,YAAY,WAAW;CAEpD,MAAM,YAAY,KAAK,IACrB,GACA,KAAK,MAAM,UAAU,QAAQ,IAAI,YAAY,QAAQ,KAAM,KAAoB,CACjF;CACA,MAAM,gBAAgB,KAAK,IACzB,GACA,KAAK,MAAM,UAAU,QAAQ,IAAI,IAAI,QAAQ,KAAM,KAAoB,CACzE;CAEA,IAAI,YAAY;CAChB,IAAI,YAAY,SAAS,IAAI;EAC3B,MAAM,UACH,MAAM,cAAc,SAAS,YAAY,IAAI,KAC7C,MAAM,MAAM,eAAe,YAAY,IAAI;EAC9C,IAAI,YAAY,KAAA,KAAa,YAAY,MACvC,YAAY,oBAAoB,SAAS,YAAY,SAAS,CAAC;CAEnE;CAEA,IAAI,eAAe;CACnB,IAAI;CACJ,IAAI;CACJ,IAAI;EACF,iCAAiC,aAAa,sBAAsB;EACpE,IAAI,kBAAkB,MAAM,IAAI,MAAM,KAAA,GAAW;GAC/C,MAAM,UAAU,MAAM,MAAM,YAAY,MAAM,WAAW;GACzD,eAAe,QAAQ,SAAS,IAAI,QAAQ,SAAS;EACvD;EACA,eAAe,MAAM,YAAY,YAAY,SAAS;EACtD,YAAY,oBAAoB,MAAM,MAAM,YAAY;CAC1D,SAAS,OAAgB;EACvB,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,iBAAiB,QAAQ,MAAM,UAAU,uCACpD,CAAC;CACH;CAEA,MAAM,iBAAiB,YAAY;CACnC,MAAM,oBAAoB,wBAAwB;EAChD,gBAAgB,YAAY;EAC5B,aAAa,MAAM;EACnB,SAAS,MAAM,KAAK,KAAK,YAAY;EACrC,SAAS,YAAY;EACrB;EACA;CACF,CAAC;CACD,MAAM,8BAA8B,0BAA0B,iBAAiB;CAC/E,MAAM,iBAAiB,KAAK,MAAO,iBAAiB,YAAa,aAAa;CAC9E,MAAM,YAAY,iBAAiB,KAAK,gBAAgB;CACxD,IAAI,aAAa,iBAAiB,KAChC,MAAM,IAAI,SAAS,eAAe;EAChC,SACE;EACF,QAAQ;CACV,CAAC;CAEH,MAAM,cAAc,YAChB,MAAM,+BAA+B,IAAI,QAAQ,SAAS,SAAS,YAAY,EAAE,IACjF;CACJ,MAAM,mBACJ,aAAa,sBAAsB,KAAA,KACnC,YAAY,sBAAsB,QAClC,YAAY,sBAAsB;CACpC,OAAO,yBACL,KACA,SACA;EACE,OAAO,EAAE,IAAI,MAAM,UAAU,YAAY,OAAO;EAChD,aAAa,MAAM;EACnB,MAAM,YACF,mBACE,qBACA,yBACF;EACJ,cAAc;EACd,QAAQ;GACN,MAAM,MAAM,KAAK,KAAK,YAAY;GAClC,QAAQ,YAAY,iBAAiB;GACrC,UAAU,MAAM;GAChB,UAAU,MAAM,KAAK;GACrB,UAAU;GACV,SAAS,2BAA2B,MAAM,KAAK,KAAK;GACpD,aAAa,MAAM;EACrB;CACF,GACA,OAAO,mBAAmB,aAAa;EACrC,IAAI;EAEJ,IAAI,iBAAiB,KAAK,gBAAgB,GAAG;GAC3C,MAAM,WAAW,sBAAsB,QAAQ,cAAc;GAC7D,IACE,aAAa,sBAAsB,KAAA,KACnC,YAAY,sBAAsB,QAClC,YAAY,sBAAsB,IAClC;IACA,MAAM,SAAU,MAAM,SAAS,oBAAoB;KACjD,OAAO,MAAM;KACb,QAAQ;KACR,oBAAoB,YAAY;KAChC,WACE,qBACA,OAAO,YAAY,GAAG,GAAG,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC;KAC/E,UAAU;IACZ,CAAC;IAED,IAAI,sBAAsB,KAAA,KAAa,QAAQ,cAAc,mBAC3D,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,wDACX,CAAC;IAEH,IAAI,QAAQ,WAAW,WACrB,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,6DACX,CAAC;IAGH,SAAS,aAAa;IACtB,MAAM,MAAM,kBAAkB;KAC5B,WAAW,OAAO,aAAa;KAC/B,YACE,OAAO,OAAO,KAAA,KAAa,OAAO,OAAO,OAAO,OAAO,OAAO,EAAE,IAAI,KAAA;KACtE,aAAa,MAAM;KACnB,QAAQ,MAAM;KACd,QAAQ,OAAO,UAAU;KACzB,UAAU,OAAO,YAAY,MAAM;KACnC,QAAQ;KACR,MAAM,MAAM,KAAK,KAAK,YAAY;KAClC,UAAU;KACV,2BAAW,IAAI,KAAK;KACpB,2BAAW,IAAI,KAAK;IACtB,CAAC;IACD,8BAA8B,OAAO,aAAa,KAAA;GACpD,OAAO;IACL,MAAM,UAAU,MAAM,SAAS,sBAAsB;KACnD,GAAI,sBAAsB,KAAA,IAAY,EAAE,WAAW,kBAAkB,IAAI,CAAC;KAC1E,OAAO,MAAM;KACb,QAAQ;KACR,UAAU,MAAM;KAChB,cAAc,MAAM,eAAe,KAAA;KACnC,UAAU;KACV,GAAI,MAAM,gCAAgC,KAAA,IACtC,EAAE,UAAU,MAAM,4BAA4B,IAC9C,CAAC;IACP,CAAmD;IAEnD,IAAI,sBAAsB,KAAA,KAAa,SAAS,cAAc,mBAC5D,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,wDACX,CAAC;IAEH,SAAS,aAAa;IACtB,MAAM,MAAM,kBAAkB;KAC5B,WAAW,SAAS,aAAa;KACjC,aAAa,MAAM;KACnB,QAAQ,MAAM;KACd,QAAQ;KACR,UAAU,MAAM;KAChB,QAAQ;KACR,MAAM,MAAM,KAAK,KAAK,YAAY;KAClC,UAAU;KACV,2BAAW,IAAI,KAAK;KACpB,2BAAW,IAAI,KAAK;IACtB,CAAC;IAED,OAAO;KACL,MAAM;KACN,KAAK,SAAS;KACd,WAAW,SAAS;KACpB,YAAY,SAAS;KACrB,UAAU;IACZ;GACF;EACF;EAEA,SAAS,aAAa;EACtB,MAAM,MAAM,mBAAmB,YAAY,IAAI;GAC7C,MAAM,MAAM,KAAK;GACjB,OAAO;GACP,GAAI,gCAAgC,KAAA,IAChC,EAAE,sBAAsB,4BAA4B,IACpD,CAAC;GACL,2BAAW,IAAI,KAAK;EACtB,CAAC;EAED,OAAO;GACL,MAAM;GACN,QAAQ;GACR,SAAS;GACT,UAAU;EACZ;CACF,CACF;AACF;;;ACxdA,MAAa,mBACX,SACA,OAAU,eAiBP;CACH,OAAO,mBACL,MACA;EACE,QAAQ;EACR,UAAU;GACR,GAAG;GACH,SAAS,EACP,aAAa,wBACf;EACF;EACA,cAAc;EACd,aAAa;CACf,GACA,OAAO,QAAQ;EACb,MAAM,UAAU,kBAAkB,GAA6B;EAC/D,IAAI,YAAY,KAAA,KAAa,YAAY,MACvC,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,yCACX,CAAC;EAEH,MAAM,UAAU,MAAM,QAAQ,KAAK;EACnC,MAAM,UAAU,kBAAkB,GAA6B;EAC/D,MAAM,YAAY,SAAS,IAAI,sBAAsB;EAErD,IAAI,QAAQ,SAAS,aAAa,MAAM;GACtC,MAAM,aAAa,QAAQ,QAAQ,cAAc;IAC/C;IACA;IACA;GACF;GACA,MAAM,WAAW,mBAAmB,KAA+B,OAAO;GAE1E,IACE,aAAa,KAAA,KACb,aAAa,QACb,WAAW,SAAS,QAAQ,MAAM,OAElC,MAAM,IAAI,SAAS,gBAAgB;IACjC,SAAS,iBAAiB;IAC1B,QAAQ;GACV,CAAC;EAEL;EAEA,IAAI,cAAc,KAAA,KAAa,cAAc,QAAQ,cAAc,IACjE,MAAM,IAAI,SAAS,gBAAgB;GACjC,SAAS;GACT,QAAQ;EACV,CAAC;EAIH,IAAI,MADmB,cAAc,QAAQ,WAAW,OAAO,MAC9C,WACf,MAAM,IAAI,SAAS,gBAAgB;GACjC,SAAS;GACT,QAAQ;EACV,CAAC;EAGH,MAAM,QAAQ,KAAK,MAAM,OAAO;EAChC,MAAM,YAAY,MAAM;EACxB,MAAM,OAAO,MAAM;EACnB,MAAM,YAAa,MAAwC;EAC3D,MAAM,UAAU,WAAW,QAAQ,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,OAAO,KAAK;EACjE,MAAM,QAAQ,mBAAmB,GAAG;EACpC,IAAI;EACJ,IAAI;GACF,IAAI,gBAAgB,MAAM,MAAM,iBAAiB,OAAO;GACxD,IAAI,eAAe,WAAW,aAAa,OAAO,IAAI,KAAK,EAAE,UAAU,KAAK,CAAC;GAC7E,IAAI,kBAAkB,MACpB,IAAI;IACF,gBAAgB,MAAM,MAAM,mBAAmB;KAC7C;KACA,WAAW;KACX,WAAW,aAAa;KACxB;KACA,QAAQ;KACR,2BAAW,IAAI,KAAK;KACpB,2BAAW,IAAI,KAAK;IACtB,CAAC;GACH,SAAS,OAAO;IACd,gBAAgB,MAAM,MAAM,iBAAiB,OAAO;IACpD,IAAI,CAAC,eAAe,MAAM;GAC5B;GAEF,IAAI,cAAc,WAAW,aAAa,OAAO,IAAI,KAAK,EAAE,UAAU,KAAK,CAAC;GAC5E,IACE,cAAc,OAAO,WAAW,aAAa,KAC7C,IAAI,KAAK,cAAc,SAAS,CAAC,CAAC,QAAQ,IAAI,KAAK,IAAI,IAAI,KAE3D,MAAM,IAAI,MAAM,6CAA6C;GAC/D,cAAc,cAAc,WAAW;GAUvC,IAAI,MATkB,IAAI,QAAQ,QAAQ,OAAO;IAC/C,OAAO,gBAAgB;IACvB,OAAO;KACL;MAAE,OAAO;MAAW,OAAO;KAAQ;KACnC;MAAE,OAAO;MAAU,OAAO,cAAc;KAAO;KAC/C;MAAE,OAAO;MAAa,OAAO,cAAc;KAAU;IACvD;IACA,QAAQ;KAAE,QAAQ;KAAa,2BAAW,IAAI,KAAK;IAAE;GACvD,CAAC,MACe,MAAM,MAAM,IAAI,MAAM,sCAAsC;GAG5E,IAAI,cAAc,kBAAkB;IAClC,MAAM,YAAa,MAAwC;IAC3D,MAAM,gBAAiB,MAA0C;IACjE,MAAM,aACJ,kBAAkB,KAAA,KAAa,kBAAkB,OAC7C,OAAO,aAAa,IACpB,KAAA;IAEN,IAAI,cAAc,KAAA,KAAa,cAAc,QAAQ,cAAc,IAAI;KACrE,IAAI;MACF,MAAM,IAAI,QAAQ,QAAQ,OAAO;OAC/B,OAAO;OACP,QAAQ;QACN,QAAQ;QACR;QACA,2BAAW,IAAI,KAAK;OACtB;OACA,OAAO,CAAC;QAAE,OAAO;QAAa,OAAO;OAAU,CAAC;MAClD,CAAC;KACH,SAAS,GAAG;MACV,IAAI,QAAQ,OAAO,KAAK,0DAA0D,CAAC;MACnF,MAAM;KACR;KAEA,IAAI,QAAQ,cAAc,YAAY,MAAM;MAC1C,MAAM,eAAe,MAAM,IAAI,QAAQ,QAAQ,QAAsB;OACnE,OAAO,gBAAgB;OACvB,OAAO,CAAC;QAAE,OAAO;QAAwB,OAAO;OAAU,CAAC;MAC7D,CAAC;MACD,IACE,iBAAiB,QACjB,CAAC,cAAc,UAAU,CAAC,CAAC,SAAS,aAAa,MAAM,KACvD,aAAa,eAAe,KAAA,KAC5B,aAAa,eAAe,MAC5B;OACA,MAAM,aAAa,MAAM,6BACvB,KACA,WACA,cACA,aACF;OACA,IAAI,eAAe,MACjB,IAAI;QACF,MAAM,eACJ,aAAa,WAAW,aACpB,eACA,MAAM,IAAI,QAAQ,QAAQ,OAAqB;SAC7C,OAAO,gBAAgB;SACvB,OAAO;UACL;WAAE,OAAO;WAAM,OAAO,aAAa;UAAG;UACtC;WAAE,OAAO;WAAU,OAAO;UAAa;UACvC;WAAE,OAAO;WAAwB,OAAO;UAAU;SACpD;SACA,QAAQ;UAAE,QAAQ;UAAY,2BAAW,IAAI,KAAK;SAAE;QACtD,CAAC;QACP,IAAI,iBAAiB,MACnB,MAAM,IAAI,MAAM,qDAAqD;QAEvE,MAAM,kBAAkB,KAAK,YAAY,cAAc,MAD/B,cAAc,SAAS,aAAa,IAAI,KACI,KAAA,CAAS;OAC/E,SAAS,OAAO;QACd,MAAM,+BAA+B,KAAK,UAAU;QACpD,MAAM;OACR;MAEJ;KACF;KAGA,IAAI;MACF,MAAM,cAAc,MAAM,IAAI,QAAQ,QAAQ,QAA6B;OACzE,OAAO;OACP,OAAO,CAAC;QAAE,OAAO;QAAa,OAAO;OAAU,CAAC;MAClD,CAAC;MACD,IACE,gBAAgB,KAAA,KAChB,gBAAgB,QAChB,YAAY,YAAY,KAAA,KACxB,YAAY,YAAY,QACxB,YAAY,YAAY,IAEpB;WAAA,QAAQ,mBAAmB,KAAA,KAAa,QAAQ,mBAAmB,MACrE,MAAM,gCACJ,KACA,YAAY,SACZ,QAAQ,cACV;MAAA;KAGN,SAAS,GAAG;MACV,IAAI,QAAQ,OAAO,KAAK,mCAAmC,CAAC;MAC5D,MAAM;KACR;IACF;GACF;GAEA,IAAK,cAAyB,kBAAkB;IAC9C,MAAM,YAAa,MAAiC;IACpD,IAAI,cAAc,KAAA,KAAa,cAAc,QAAQ,cAAc,IAAI;KACrE,IAAI;MACF,MAAM,IAAI,QAAQ,QAAQ,OAAO;OAC/B,OAAO;OACP,QAAQ;QACN,QAAQ;QACR,2BAAW,IAAI,KAAK;OACtB;OACA,OAAO,CAAC;QAAE,OAAO;QAAa,OAAO;OAAU,CAAC;MAClD,CAAC;KACH,SAAS,GAAG;MACV,IAAI,QAAQ,OAAO,KAAK,0DAA0D,CAAC;MACnF,MAAM;KACR;KACA,IAAI,QAAQ,cAAc,YAAY,MAAM;MAC1C,MAAM,eAAe,MAAM,IAAI,QAAQ,QAAQ,QAAsB;OACnE,OAAO,gBAAgB;OACvB,OAAO,CAAC;QAAE,OAAO;QAAwB,OAAO;OAAU,CAAC;MAC7D,CAAC;MACD,IACE,cAAc,WAAW,gBACzB,aAAa,eAAe,KAAA,KAC5B,aAAa,eAAe,MAC5B;OACA,MAAM,0BAAU,IAAI,KAAK;OACzB,MAAM,IAAI,QAAQ,QAAQ,OAAO;QAC/B,OAAO,gBAAgB;QACvB,OAAO,CAAC;SAAE,OAAO;SAAM,OAAO,aAAa;QAAG,CAAC;QAC/C,QAAQ;SAAE,QAAQ;SAAY;SAAS,WAAW;QAAQ;OAC5D,CAAC;MACH;KACF;IACF;GACF;GAEA,IAAK,cAAyB,0BAA0B;IACtD,MAAM,UAAU;IAIhB,MAAM,mBACJ,QAAQ,cAAc,qBAAqB,QAAQ;IACrD,IACE,qBAAqB,QACrB,qBAAqB,KAAA,KACrB,qBAAqB,IACrB;KACA,MAAM,WAAW,MAAM,IAAI,QAAQ,QAAQ,QAAsB;MAC/D,OAAO,gBAAgB;MACvB,OAAO,CAAC;OAAE,OAAO;OAAoB,OAAO;MAAiB,CAAC;KAChE,CAAC;KACD,IAAI,YAAY,SAAS,WAAW,cAAc,SAAS,WAAW,YAAY;MAChF,MAAM,UAAU;OAAE,GAAG;OAAU,QAAQ;OAAY,2BAAW,IAAI,KAAK;MAAE;MACzE,MAAM,IAAI,QAAQ,QAAQ,OAAO;OAC/B,OAAO,gBAAgB;OACvB,OAAO,CAAC;QAAE,OAAO;QAAM,OAAO,SAAS;OAAG,CAAC;OAC3C,QAAQ;QAAE,QAAQ,QAAQ;QAAQ,WAAW,QAAQ;OAAU;MACjE,CAAC;MACD,MAAM,OAAO,MAAM,cAAc,SAAS,SAAS,IAAI;MACvD,IAAI,MACF,MAAM,QAAQ,cAAc,uBAC1B;OAAE;OAAO,cAAc;OAAS;MAAK,GACrC,GACF;KAEJ;IACF;GACF;GAGA,IAAI,QAAQ,cAAc,YAAY,MACpC,IAAI;IACF,IAAI,cAAc,uBAAuB;KACvC,MAAM,mBACJ;KACF,MAAM,mBAAmB,iBAAiB,qBAAqB;KAC/D,MAAM,eACJ,iBAAiB,UAChB;KACH,MAAM,WAAY,iBAAiB,MAC/B;KAEJ,MAAM,cAAc,sBACjB,iBAAuD,QAC1D;KACA,MAAM,0BACJ,OAAO,YAAY,gBAAgB,WAAW,YAAY,cAAc,KAAA;KAC1E,IAAI,uBACF,OAAO,YAAY,SAAS,WAAW,YAAY,OAAO,KAAA;KAC5D,IAAI,OAAO,yBAAyB,UAClC,uBAAuB,qBAAqB,YAAY;KAG1D,MAAM,QAAQ,MAAM,SAAS,QAAQ,YAAY;KACjD,MAAM,eACJ,aAAa,KAAA,KAAa,aAAa,QAAQ,aAAa,KACxD,MAAM,MAAM,MAAM,EAAE,aAAa,QAAQ,IACzC,KAAA;KACN,MAAM,sBACJ,OAAO,YAAY,YAAY,WAC3B,2BAA2B,YAAY,OAAO,IAC9C,2BAA2B,cAAc,KAAK;KACpD,MAAM,WAAW,cAAc,QAAQ;KACvC,MAAM,WACJ,aAAa,KAAA,KAAa,aAAa,QAAQ,aAAa,KACxD,SAAS,YAAY,IACrB,KAAA;KAEN,IACE,qBAAqB,KAAA,KACrB,qBAAqB,QACrB,qBAAqB,IACrB;MACA,MAAM,QAAsE,CAAC;MAC7E,IACE,4BAA4B,KAAA,KAC5B,4BAA4B,QAC5B,4BAA4B,IAE5B,MAAM,KAAK;OAAE,OAAO;OAAe,OAAO;MAAwB,CAAC;WAC9D,IACL,iBAAiB,KAAA,KACjB,iBAAiB,QACjB,iBAAiB,IAEjB,MAAM,KAAK;OAAE,OAAO;OAAgB,OAAO;MAAa,CAAC;MAE3D,IAAI,aAAa,KAAA,KAAa,aAAa,QAAQ,aAAa,IAC9D,MAAM,KAAK;OAAE,OAAO;OAAQ,OAAO;MAAS,CAAC;MAG/C,IAAI,MAAM,SAAS,GAAG;OAKpB,MAAM,gBAAe,MAJC,IAAI,QAAQ,QAAQ,SAAuB;QAC/D,OAAO,gBAAgB;QAChB;OACT,CAAC,EAAA,EAC6B,MAAM,cAClC,UAAU,WAAW,eACpB,UAAU,qBAAqB,oBAC9B,UAAU,WAAW,gBACpB,UAAU,WAAW,eACnB,UAAU,qBAAqB,KAAA,KAC9B,UAAU,qBAAqB,QAC/B,UAAU,qBAAqB,QACrC,wBAAwB,OACpB,UAAU,YAAY,KAAA,KACtB,UAAU,YAAY,QACtB,UAAU,YAAY,KACtB,UAAU,YAAY,mBAC5B;OACA,IAAI,iBAAiB,KAAA,KAAa,iBAAiB,MAAM;QACvD,MAAM,OACJ,iBACC,aAAa,KAAA,KAAa,aAAa,QAAQ,aAAa,KACzD,MAAM,cAAc,SAAS,QAAQ,IACrC,KAAA;QACN,MAAM,sBAAM,IAAI,KAAK;QACrB,MAAM,wBAAsC;SAC1C,GAAG;SACH;SACA,QAAQ;SACR,iBAAiB,MAAM,YAAY,aAAa,mBAAmB;SACnE,WACE,iBAAiB,sBAAsB,KAAA,KACvC,iBAAiB,sBAAsB,OACnC,IAAI,KAAK,iBAAiB,iBAAiB,IAC3C,aAAa;SACnB,WAAW;QACb;QACA,MAAM,IAAI,QAAQ,QAAQ,OAAO;SAC/B,OAAO,gBAAgB;SACvB,QAAQ;UACN,kBAAkB,sBAAsB;UACxC,QAAQ,sBAAsB;UAC9B,iBAAiB,sBAAsB;UACvC,WAAW,sBAAsB;UACjC,WAAW,sBAAsB;SACnC;SACA,OAAO,CAAC;UAAE,OAAO;UAAM,OAAO,aAAa;SAAG,CAAC;QACjD,CAAC;QACD,MAAM,mBAAmB,GAAG,CAAC,CAAC,6BAC5B,aAAa,aACb,aAAa,WAAW,MACxB,aAAa,EACf;QAEA,IAAI,SAAS,KAAA,KAAa,SAAS,MAAM;SACvC,MAAM,eAAe;UAAE;UAAO,cAAc;UAAuB;SAAK;SACxE,KAAK,MAAM,YAAY;UACrB,QAAQ,aAAa;UACrB,QAAQ,aAAa;UACrB,QAAQ,aAAa;SACvB,GACE,IAAI;UACF,MAAM,WAAW,cAAc,GAA6B;SAC9D,SAAS,OAAO;UACd,IAAI,QAAQ,OAAO,MAAM,yCAAyC,KAAK;UACvE,MAAM;SACR;SAEF,IAAI,aAAa,WAAW,YAC1B,IAAI;UACF,MAAM,KAAK,WAAW,aAAa,qBAAqB;SAC1D,SAAS,OAAO;UACd,IAAI,QAAQ,OAAO,MAAM,sCAAsC,KAAK;UACpE,MAAM;SACR;QAEJ;OACF;MACF;KACF;IACF;IAEA,IAAI,cAAc,0BAA0B,cAAc,0BAA0B;KAClF,MAAM,mBACJ;KACF,MAAM,mBAAmB,iBAAiB,qBAAqB;KAC/D,IAAI,qBAAqB,IAAI;MAC3B,MAAM,WAAW,MAAM,IAAI,QAAQ,QAAQ,QAAsB;OAC/D,OAAO,gBAAgB;OACvB,OAAO,CAAC;QAAE,OAAO;QAAoB,OAAO;OAAiB,CAAC;MAChE,CAAC;MAED,IAAI,YAAY;MAChB,MAAM,kBAAkB,iBAAiB;MACzC,MAAM,YACJ,oBAAoB,KAAA,KACpB,oBAAoB,QACpB,oBAAoB,KAChB,IAAI,KAAK,eAAe,IACxB,UAAU,cAAc,KAAA,KAAa,SAAS,cAAc,OAC1D,IAAI,KAAK,SAAS,SAAS,IAC3B,KAAA;MAER,IAAI,cAAc,KAAA,KAAa,UAAU,QAAQ,IAAI,KAAK,IAAI,GAC5D,YAAY;MAGd,MAAM,sBAAM,IAAI,KAAK;MACrB,MAAM,wBACJ,aAAa,QAAQ,aAAa,KAAA,IAC9B,KAAA,IACC;OACC,GAAG;OACH,QAAQ;OACR,mBAAmB,cAAc;OACjC,UAAU,cAAc,WAAY,aAAa,OAAQ;OACzD,YAAY;OACZ,SAAS,cAAc,aAAa,MAAM;OAC1C,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;OACjC,WAAW;MACb;MACN,MAAM,IAAI,QAAQ,QAAQ,OAAO;OAC/B,OAAO,gBAAgB;OACvB,QAAQ;QACN,QAAQ;QACR,mBAAmB,cAAc;QACjC,UAAU,cAAc,WAAY,aAAa,OAAQ;QACzD,YAAY;QACZ,SAAS,cAAc,aAAa,MAAM;QAC1C,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;QACjC,WAAW;OACb;OACA,OAAO,CAAC;QAAE,OAAO;QAAoB,OAAO;OAAiB,CAAC;MAChE,CAAC;MAED,IAAI,0BAA0B,KAAA,GAAW;OACvC,IAAI;QACF,MAAM,QAAQ,aAAa,uBACzB;SAAE;SAAO,cAAc;QAAsB,GAC7C,GACF;OACF,SAAS,OAAO;QACd,IAAI,QAAQ,OAAO,MAAM,gDAAgD,KAAK;OAChF;OACA,MAAM,OAAO,MAAM,cAAc,SAAS,sBAAsB,IAAI;OACpE,IAAI,SAAS,KAAA,KAAa,SAAS,MAAM;QACvC,IAAI;SACF,MAAM,QAAQ,aAAa,uBACzB;UAAE;UAAO,cAAc;UAAuB;SAAK,GACnD,GACF;QACF,SAAS,OAAO;SACd,IAAI,QAAQ,OAAO,MACjB,gDACA,KACF;QACF;QACA,IAAI,UAAU,WAAW,cAAc,cAAc,YACnD,IAAI;SACF,MAAM,KAAK,WAAW,iBAAiB,qBAAqB;QAC9D,SAAS,OAAO;SACd,IAAI,QAAQ,OAAO,MAAM,yCAAyC,KAAK;QACzE;OAEJ;MACF;KACF;IACF;IAGA,IAAI,cAAc,oBAAoB,cAAc,kBAAkB;KAGpE,MAAM,uBAFW,MACb,aAAA,EAEO,qBACR,MAAgD;KACnD,MAAM,mBACJ,wBAAwB,KAAA,KACxB,wBAAwB,QACxB,wBAAwB,KACpB,sBACA,KAAA;KAEN,IAAI,qBAAqB,KAAA,GAAW;MAClC,MAAM,cAAc,MAAM,IAAI,QAAQ,QAAQ,QAAsB;OAClE,OAAO,gBAAgB;OACvB,OAAO,CAAC;QAAE,OAAO;QAAoB,OAAO;OAAiB,CAAC;MAChE,CAAC;MAED,IAAI,aAAa,WAAW,YAAY;OACtC,MAAM,YAAY;QAAE,GAAG;QAAa,QAAQ;QAAU,2BAAW,IAAI,KAAK;OAAE;OAC5E,MAAM,IAAI,QAAQ,QAAQ,OAAO;QAC/B,OAAO,gBAAgB;QACvB,QAAQ;SAAE,QAAQ,UAAU;SAAQ,WAAW,UAAU;QAAU;QACnE,OAAO,CAAC;SAAE,OAAO;SAAM,OAAO,YAAY;QAAG,CAAC;OAChD,CAAC;OACD,MAAM,OAAO,MAAM,cAAc,SAAS,YAAY,IAAI;OAC1D,IAAI,MACF,MAAM,QAAQ,aAAa,uBACzB;QAAE;QAAO,cAAc;QAAW;OAAK,GACvC,GACF;MAEJ;MAEA,IACE,gBAAgB,KAAA,KAChB,gBAAgB,QAChB,YAAY,gBAAgB,KAAA,KAC5B,YAAY,gBAAgB,QAC5B,YAAY,gBAAgB,IAE5B,MAAM,IAAI,QAAQ,QAAQ,OAAO;OAC/B,OAAO,gBAAgB;OACvB,QAAQ;QACN,MAAM,YAAY;QAClB,aAAa;QACb,2BAAW,IAAI,KAAK;OACtB;OACA,OAAO,CAAC;QAAE,OAAO;QAAM,OAAO,YAAY;OAAG,CAAC;MAChD,CAAC;KAEL;IACF;GACF,SAAS,IAAa;IACpB,IAAI,QAAQ,OAAO,MAAM,yCAAyC,EAAE;IACpE,MAAM;GACR;GAGF,MAAM,QAAQ,UAAU,KAAK;GAS7B,IAAI,MARoB,IAAI,QAAQ,QAAQ,OAAO;IACjD,OAAO,gBAAgB;IACvB,OAAO,CACL;KAAE,OAAO;KAAW,OAAO;IAAQ,GACnC;KAAE,OAAO;KAAU,OAAO;IAAY,CACxC;IACA,QAAQ;KAAE,QAAQ;KAAa,6BAAa,IAAI,KAAK;KAAG,2BAAW,IAAI,KAAK;IAAE;GAChF,CAAC,MACiB,MAAM,MAAM,IAAI,MAAM,oCAAoC;GAC5E,OAAO,IAAI,KAAK,EAAE,UAAU,KAAK,CAAC;EACpC,SAAS,OAAO;GACd,IAAI,gBAAgB,KAAA,GAClB,MAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO,gBAAgB;IACvB,OAAO,CACL;KAAE,OAAO;KAAW,OAAO;IAAQ,GACnC;KAAE,OAAO;KAAU,OAAO;IAAY,CACxC;IACA,QAAQ;KAAE,QAAQ;KAAW,2BAAW,IAAI,KAAK;IAAE;GACrD,CAAC;GACH,IAAI,QAAQ,OAAO,MACjB,gEACA,KACF;GACA,MAAM,IAAI,SAAS,uBAAuB,EACxC,SAAS,6CACX,CAAC;EACH;CACF,CACF;AACF;AAEA,MAAa,yBACX,SACA,OAAU,8BA2BP;CACH,MAAM,sBAAsB,QAAQ;CACpC,MAAM,iBACJ,qBAAqB,YAAY,OAC7B;EACE;EACA;EACA,oBAAoB,SAAS,wBAAwB;CACvD,IACA,CAAC,mBAAmB,qBAAqB;CAE/C,OAAO,mBACL,MACA;EACE,QAAQ;EACR,MAAM;EACN,KAAK;CACP,GACA,OAAO,QAAQ;EACb,MAAM,WAAW,eAAe,QAAQ,cAAc;EACtD,MAAM,EACJ,MAAM,UACN,SAAS,aACT,QAAQ,YACR,UACA,OACA,UAAU,eACV,aACA,UACA,qBACA,mBACA,kBACA,gBACA,mCACE,IAAI;EAGR,IAAI,gBAAgB,KAAA,KAAa,gBAAgB,QAAQ,gBAAgB,IAKvE;OAAI,CAAC,qBAAqB,aAHtB,IAAI,SAAqC,WAC1C,IAAI,SAAyC,OAC9C,EAC4C,GAC5C,MAAM,IAAI,SAAS,aAAa;IAC9B,SAAS;IACT,QAAQ;GACV,CAAC;EAAA;EAKL,MAAM,UAAU,MAAM,kBAAkB,GAAG;EAC3C,IAAI,YAAY,KAAA,KAAa,YAAY,MAAM,MAAM,IAAI,SAAS,cAAc;EAChF,MAAM,OAAO,QAAQ;EAGrB,IACE,qBAAqB,YAAY,QACjC,oBAAoB,6BAA6B,QACjD,KAAK,kBAAkB,MAEvB,MAAM,IAAI,SAAS,eAAe;GAChC,MAAM;GACN,SAAS,qBAAqB,4BAA4B;EAC5D,CAAC;EAIH,IAAI;EACJ,IAAI;EAEJ,IAAI,aAAa,KAAA,KAAa,aAAa,QAAQ,aAAa,IAAI;GAClE,IAAI,qBAAqB,YAAY,MACnC,MAAM,IAAI,SAAS,eAAe,EAAE,SAAS,iCAAiC,CAAC;GAEjF,OAAQ,MAAM,cAAc,SAAS,QAAQ,KAAM,KAAA;GACnD,IAAI,SAAS,KAAA,KAAa,SAAS,MACjC,IAAI;IAEF,MAAM,aAAa,MAAM,IAAI,QAAQ,QAAQ,QAAsB;KACjE,OAAO;KACP,OAAO,CAAC;MAAE,OAAO;MAAQ,OAAO;KAAS,CAAC;IAC5C,CAAC;IACD,IAAI,eAAe,KAAA,KAAa,eAAe,MAC7C,OAAO;SAMP,OAAO,MAJwB,IAAI,QAAQ,QAAQ,QAAsB;KACvE,OAAO;KACP,OAAO,CAAC;MAAE,OAAO;MAAY,OAAO;KAAS,CAAC;IAChD,CAAC,KAC0B,KAAA;GAE/B,QAAQ;IACN,OAAO,KAAA;GACT;GAEF,IAAI,SAAS,KAAA,KAAa,SAAS,MACjC,MAAM,IAAI,SAAS,eAAe;IAChC,MAAM;IACN,SAAS,qBAAqB,4BAA4B;IAC1D,QAAQ;GACV,CAAC;EAEL,OAAO,IAAI,gBAAgB,KAAA,KAAa,gBAAgB,QAAQ,gBAAgB,IAAI;GAClF,IAAI,OAAO,gBAAgB,UAAU;IACnC,UAAW,MAAM,iBAAiB,SAAS,WAAW,KAAM,KAAA;IAE5D,YACG,MAAM,IAAI,QAAQ,QAAQ,QAAyB;KAClD,OAAO;KACP,OAAO,CAAC;MAAE,OAAO;MAAQ,OAAO;KAAY,CAAC;IAC/C,CAAC,KAAM,KAAA;GACX;GACA,IAAI,YAAY,KAAA,KAAa,YAAY,MACvC,MAAM,IAAI,SAAS,eAAe;IAChC,SAAS,YAAY,YAAY;IACjC,QAAQ;GACV,CAAC;EAEL,OAAO,IAAI,eAAe,KAAA,KAAa,eAAe,MACpD,MAAM,IAAI,SAAS,eAAe;GAChC,SAAS;GACT,QAAQ;EACV,CAAC;EAGH,IAAI,SACF,SAAS,KAAA,IACL,KAAK,SACL,UACI,QAA4B,SAAU,QAAiC,SACzE;EACR,MAAM,gBACJ,SAAS,KAAA,KAAa,UAChB,SAA6B,YAC9B,SAAkC,YACnC,MAAM,YACN,QACC,YAAY;EAEnB,MAAM,qBAAsB,IAAI,QAAoC;EAGpE,MAAM,cACJ,IAAI,KAAK,eAAe,sBAAuB,QAAQ,KAAwB;EACjF,MAAM,UAAU,2BAA2B,MAAM,KAAK;EACtD,IAAI,mBAAmB,KAAA,GAAW;GAChC,MAAM,uBACJ,MAAM,mBAAmB,GAAG,CAAC,CAAC,qBAAqB,cAAc;GACnE,IACE,yBAAyB,QACzB,qBAAqB,gBAAgB,eACrC,2BAA2B,qBAAqB,OAAO,MAAM,SAE7D,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,2EACX,CAAC;EAEL;EAEA,MAAM,kBAAkB,MAAM,oCAC5B,KACA;GACE,QAAQ,KAAK;GACb;GACA;GACA;GACA;GACA;EACF,GACA,OACF;EACA,IAAI,oBAAoB,MACtB,OAAO,IAAI,KAAK,eAAe;EAGjC,IAAI,oBAAoB,YAAY;EACpC,IAAI,WAAW,WAAW,KAAA,GAAW,UAAU,YAAY;EAC3D,IAAI,WAAW,KAAA,MAAc,CAAC,OAAO,cAAc,MAAM,KAAK,UAAU,IACtE,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,kDACX,CAAC;EAGH,IAAI,SAAS,KAAA,GACX,IAAI;GACF,IAAI,kBAAkB,IAAI,MAAM,KAAA,GAAW;IACzC,MAAM,UAAU,MAAM,IAAI,QAAQ,QAAQ,SAAiB;KACzD,OAAO;KACP,OAAO,CAAC;MAAE,OAAO;MAAkB,OAAO;KAAY,CAAC;IACzD,CAAC;IACD,MAAM,YAAY,QAAQ,SAAS,IAAI,QAAQ,SAAS;IACxD,MAAM,gBAAgB,YAAY;IAClC,oBAAoB;IACpB,SAAS,oBAAoB,MAAM,aAAa;GAClD;EACF,SAAS,OAAgB;GACvB,MAAM,IAAI,SAAS,eAAe,EAChC,SACE,iBAAiB,QAAQ,MAAM,UAAU,uCAC7C,CAAC;EACH;EAGF,IAAI;EACJ,IAAI;EACJ,IAAI;EAEJ,MAAM,QAAQ,MAAM,sBAAsB,KAAK;GAAE;GAAa;EAAK,CAAC;EACpE,MAAM,EAAE,YAAY,aAAa;EACjC,MAAM,0BAA0B,MAAM,UAClC,2BAA2B,MAAM,aAAa,IAC9C,KAAA;EACJ,IAAI,MAAM,WAAW,mCAAmC,MACtD,MAAM,IAAI,SAAS,eAAe;GAChC,MAAM;GACN,SAAS,kEAAkE,wBAAwB,kBAAkB,cAAc;EACrI,CAAC;EAGH,MAAM,gCAAgC,UAA6B;GACjE,IAAI,QAAQ,OAAO,MAAM,6CAA6C,KAAK;GAC3E,OAAO,IAAI,SAAS,eAAe;IACjC,MAAM;IACN,SACE,iBAAiB,QACb,MAAM,UACN,qBAAqB,iCAAiC;GAC9D,CAAC;EACH;EACA,MAAM,WAAW,OAAO,YAAY;GAClC,MAAM,cAAc,MAAM,2BAA2B,KAAK,SAAS;IACjE;IACA;IACM;GACR,CAAC;GAED,MAAM,8BAA8B,OAChC,+BAA+B,OAAO,IACtC,KAAA;GAGJ,MAAM,WAAW,0BACf,uBAAuB;IACrB;IACA,QAAQ,KAAK;IACb,MAAM,SAAS,KAAA,IAAY,KAAK,KAAK,YAAY,IAAI,KAAA;IACrD;IACA,SAAS,YAAY,KAAA,IAAY,QAAQ,KAAK,YAAY,IAAI,KAAA;IAC9D,OAAO;IACP,OAAO;KACL,SAAS,eAAe,KAAA;KACxB,WAAW,MAAM;KACjB,SAAS,MAAM;KACf,cAAc,MAAM;KACpB,QAAQ;IACV;GACF,CAAC,CACH;GAEA,MAAM,WAUF;IACF,OAAO;IACP,cAAc,eAAe,KAAA;IAC7B;IAEA,UAAU;IACV;GACF;GAEA,IAAI,gCAAgC,KAAA,GAClC,SAAS,WAAW;GAItB,IAAI,SAAS,KAAA,KAAa,qBAAqB,MAAM;IACnD,MAAM,YAAY,MAAM,sBAAsB,KAAK,SAAS;KAC1D;KACA;KACA;KACA;KACA;KACA,QAAQ,KAAK;KACb;KACA;KACA;IACF,CAAC;IAED,IAAI,WAAW,SAAS,YACtB,OAAO,EACL,aAAa;KACX,MAAM;KACN,KAAK,UAAU,OAAO;KACtB,WAAW,UAAU,aAAa;KAClC,YAAY,UAAU,cAAc;KACpC,UAAU,UAAU;IACtB,EACF;IAGF,IAAI,WAAW,SAAS,YACtB,OAAO,EACL,aAAa;KACX,MAAM;KACN,QAAQ,UAAU;KAClB,SAAS,UAAU;KACnB,UAAU,UAAU;IACtB,EACF;GAEJ;GAEA,IAAI,SAAS,KAAA,GAAW;IAEtB,IAAI,eAAe,KAAA,GAEjB,SAAS,SAAS;SACb;KAEL,SAAS,OAAO,KAAK;KAErB,SAAsC,gBAAgB,KAAK;KAE3D,IAAI;KACJ,IAAI,WAAW,KAAA,KAAa,WAAW,MAAM;MAC3C,cAAc;MACd,SAAS,WAAW;KACtB,OACE,eAAe,KAAK,UAAU,MAAM,YAAY;KAElD,SAAS,SAAS,KAAK,IAAI,KAAK,MAAM,WAAW,GAAG,GAAI;IAC1D;GACF,OAAO;IAEL,IAAI,WAAW,KAAA,KAAa,WAAW,MACrC,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,2CACX,CAAC;IACH,SAAS,SAAS,KAAK,MAAM,MAAM;GACrC;GAEA,OAAO,EAAE,SAAS;EACpB,EAAA,CAAG,CAAC,CAAC,OAAO,UAAmB;GAC7B,IAAI,QAAQ,cAAc,mBAAmB,KAAA,GAC3C,MAAM,6BAA6B,KAAK;GAC1C,MAAM;EACR,CAAC;EACD,IAAI,SAAS,gBAAgB,KAAA,GAAW,OAAO,IAAI,KAAK,SAAS,WAAW;EAC5E,MAAM,WAAW,SAAS;EAC1B,MAAM,YACJ,SAAS,KAAA,KAAa,QAAQ,cAAc,mBAAmB,KAAA,IAC3D;GACE,OAAO,EAAE,IAAI,KAAK,GAAG;GACrB;GACA,MAAM;GACN,cACE,mBAAmB,KAAA,IACf,MAAM,mBAAmB,GAAG,CAAC,CAAC,qBAAqB,cAAc,IACjE,MAAM,mBAAmB,GAAG,CAAC,CAAC,wBAAwB,aAAa,OAAO;GAChF,QAAQ;IACN,MAAM,KAAK,KAAK,YAAY;IAC5B,QAAQ,SAAS;IACjB,UAAU;IACV,UAAU,KAAK;IACf,UAAU;IACV;IACA;IACA;IACA;GACF;EACF,IACA,KAAA;EACN,MAAM,UAAU,OACd,mBACA,aACsC;GACtC,IAAI,sBAAsB,KAAA,GAAW,SAAS,YAAY;GAC1D,IAAI;IAIF,MAAM,SACJ,gBACE,MALkB,UAAU,aAAa,WAAW,EACtD,MAAM,SACR,CAAC,CAIC;IAEF,IAAI,sBAAsB,KAAA,KAAa,QAAQ,cAAc,mBAC3D,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,wDACX,CAAC;IAEH,MAAM,QAAQ;IACd,YAAY,QAAQ;IACpB,aAAa,QAAQ;GACvB,SAAS,OAAgB;IACvB,MAAM,6BAA6B,KAAK;GAC1C;GACA,SAAS,aAAa;GAEtB,MAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO,gBAAgB;IACvB,MAAM;KACJ,WAAW,aAAa;KACxB;KACA,QAAQ,KAAK;KACb,QAAQ,SAAS,UAAU;KAC3B,UAAU;KACV,QAAQ;KACR,MAAM,SAAS,KAAA,IAAY,KAAK,KAAK,YAAY,IAAI,KAAA;KACrD,SAAS,YAAY,KAAA,IAAY,QAAQ,KAAK,YAAY,IAAI,KAAA;KAC9D,UAAU,oBAAoB,aAAa,IACvC,0BAA0B,aAAa,IACvC,KAAA;KACJ,2BAAW,IAAI,KAAK;KACpB,2BAAW,IAAI,KAAK;IACtB;GACF,CAAC;GAED,IAAI,SAAS,KAAA,GAAW;IACtB,MAAM,QAAQ,mBAAmB,GAAG;IAKpC,IAAI,gBAAe,MAJI,MAAM,wBAC3B,gBAAgB,KAAK,KAAK,SAAS,gBACnC,WACF,EAAA,EAC6B;IAC7B,IAAI,iBAAiB,KAAA,GACnB,IAAI;KAQF,gBAAe,MAPM,IAAI,QAAQ,QAAQ,QAEtC;MACD,OAAO,gBAAgB,KAAK,KAAK,SAAS;MAC1C,OAAO,CAAC;OAAE,OAAO;OAAM,OAAO;MAAY,CAAC;MAC3C,QAAQ,CAAC,sBAAsB;KACjC,CAAC,EAAA,EACsB,wBAAwB,KAAA;KAC/C,IAAI,iBAAiB,KAAA,KAAa,iBAAiB,QAAQ,iBAAiB,IAC1E,MAAM,MAAM,aACV,gBAAgB,KAAK,KAAK,SAAS,gBACnC,aACA,YACF;IAEJ,QAAQ,CAER;IAGF,MAAM,IAAI,QAAQ,QAAQ,OAAqB;KAC7C,OAAO,gBAAgB;KACvB,MAAM;MACJ,MAAM,KAAK,KAAK,YAAY;MAC5B;MACA;MACA,QAAQ,KAAK;MACb;MACA,kBAAkB,KAAA;MAClB,UAAU,KAAK;MACf,sBAAsB,aAAa;MAEnC,QAAQ;MACR,iBAAiB,KAAK,YAAY;MAClC,OAAO,YAAY;MACnB,6BAAa,IAAI,KAAK;MACtB,WAAW,IAAI,KAAK,KAAK,IAAI,IAAI,MAAwB;MACzD,mBAAmB;MACnB;MACA;MACA,2BAAW,IAAI,KAAK;MACpB,2BAAW,IAAI,KAAK;KACtB;IACF,CAAC;GACH;GAEA,OAAO,IAAI,KAAK;IACd,MAAM;IACN,KAAK,OAAO;IACZ,WAAW,aAAa;IACxB,YAAY,cAAc;IAC1B,UAAU;IACV,GAAI,MAAM,WAAW,4BAA4B,KAAA,IAC7C,EACE,OAAO;KACL,MAAM,MAAM;KACZ,oBAAoB;MAAE,QAAQ;MAAyB,UAAU;KAAc;IACjF,EACF,IACA,CAAC;GACP,CAAoC;EACtC;EACA,OAAO,cAAc,KAAA,IACjB,yBAAyB,KAAK,SAAS,WAAW,OAAO,IACzD,QAAQ,KAAA,SAAiB,KAAA,CAAS;CACxC,CACF;AACF;AAEA,SAAS,2BAA2B,MAAgC,UAA0B;CAC5F,MAAM,aAAa,MAAM,WAAW;CACpC,IAAI,eAAe,KAAA,GAAW;EAC5B,IAAI,CAAC,OAAO,cAAc,UAAU,KAAK,cAAc,GACrD,MAAM,IAAI,SAAS,eAAe;GAChC,MAAM;GACN,SAAS;EACX,CAAC;EAEH,OAAO;CACT;CAQA,MAAM,SAAS;EANb,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;CAEyB,EAAE,SAAS,YAAY;CACvD,IAAI,WAAW,KAAA,GACb,MAAM,IAAI,SAAS,eAAe;EAChC,MAAM;EACN,SAAS,6DAA6D,SAAS;CACjF,CAAC;CAEH,OAAO;AACT;AAGA,MAAa,sBACX,SACA,OAAU,2BA2BP,sBAAsB,SAAS,IAAI;AAExC,MAAa,uBACX,SACA,OAAU,4BA2BP,sBAAsB,SAAS,IAAI;AAExC,MAAa,sBACX,SACA,OAAU,2BAmBP,4BAA4B,SAAS,IAAI;AAE9C,MAAa,uBACX,SACA,OAAU,4BAmBP,2BAA2B,SAAS,IAAI;AAE7C,MAAa,qBACX,SACA,OAAU,0BAkGP;CACH,MAAM,mBAAmB,EAAE,OAAO,EAChC,WAAW,EAAE,OAAO,EACtB,CAAC;CAGD,MAAM,iBADsB,QAAQ,cAEb,YAAY,OAC7B;EACE;EACA;EACA,oBAAoB,SAAS,oBAAoB;CACnD,IACA,CAAC,mBAAmB,qBAAqB;CAE/C,OAAO,mBACL,MACA;EACE,QAAQ;EACR,MAAM;EACN,KAAK;CACP,GACA,OAAO,QAAQ;EACb,MAAM,UAAU,MAAM,kBAAkB,GAAG;EAC3C,MAAM,SAAS,MAAM,6BAA6B,KAA+B,SAAS;GACxF,WAAW,IAAI,KAAK;GACpB,QAAQ;GACR,OACE,YAAY,KAAA,KAAa,YAAY,OACjC;IACE,MAAM,QAAQ;IACd,SAAS,QAAQ;GACnB,IACA,KAAA;GACN,cAAc;EAChB,CAAC;EAED,IAAI,CAAC,OAAO,MAAM,OAAO,SAAS,MAChC,MAAM,IAAI,SAAS,eAAe;GAChC,MAAM,OAAO,OAAO,QAAQ;GAC5B,SACE,OAAO,OAAO,WAAW,qBAAqB,6BAA6B;GAC7E,QAAQ,OAAO,OAAO;EACxB,CAAC;EAGH,OAAO,IAAI,KAAK;GACd,QAAQ,OAAO;GACf,WAAW,OAAO;GAClB,MAAM,OAAO;EACf,CAAC;CACH,CACF;AACF;AAEA,MAAa,qBACX,SACA,OAAU,0BAgBP;CACH,MAAM,kBAAkB,EAAE,OAAO,EAC/B,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS,EACnC,CAAC;CAED,MAAM,sBAAsB,QAAQ;CACpC,MAAM,iBACJ,qBAAqB,YAAY,OAC7B;EACE;EACA;EACA,oBAAoB,SAAS,oBAAoB;CACnD,IACA,CAAC,mBAAmB,qBAAqB;CAE/C,OAAO,mBACL,MACA;EACE,QAAQ;EACR,OAAO;EACP,KAAK;CACP,GACA,OAAO,QAAQ;EACb,IAAI,qBAAqB,YAAY,MACnC,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,yDACX,CAAC;EAEH,MAAM,UAAU,MAAM,kBAAkB,GAAG;EAC3C,IAAI,YAAY,KAAA,KAAa,YAAY,MAAM,MAAM,IAAI,SAAS,cAAc;EAChF,MAAM,QAAQ,mBAAmB,GAAG;EACpC,MAAM,kBAAmB,IAAI,QAAoC;EAGjE,MAAM,aACJ,IAAI,OAAO,gBACV,OAAO,IAAI,SAAS,QAAQ,WACxB,IAAI,IAAI,IAAI,QAAQ,GAAG,CAAC,CAAC,aAAa,IAAI,aAAa,KAAK,KAAA,IAC7D,KAAA;EACN,MAAM,SAAU,QAAQ,KAAwB;EAChD,IAAI,eAAe,KAAA,KAAa,eAAe,UAAU,oBAAoB,YAC3E,MAAM,0BAA0B,KAAK,SAAS;GAC5C,MAAM,QAAQ;GACd,SAAS,QAAQ;GACjB,aAAa;GACb,QAAQ;EACV,CAAC;EAEH,MAAM,cAAc,cAAc,mBAAmB;EACrD,MAAM,MAAM,MAAM,MAAM,6BAA6B,WAAW;EAChE,OAAO,IAAI,KAAK,EAAE,eAAe,IAAI,CAAC;CACxC,CACF;AACF;AAEA,MAAa,oBACX,SACA,OAAU,yBAgBP;CACH,MAAM,kBAAkB,EAAE,OAAO,EAC/B,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS,EACnC,CAAC;CAGD,MAAM,iBADsB,QAAQ,cAEb,YAAY,OAC7B;EACE;EACA;EACA,oBAAoB,SAAS,mBAAmB;CAClD,IACA,CAAC,mBAAmB,qBAAqB;CAE/C,OAAO,mBACL,MACA;EACE,QAAQ;EACR,OAAO;EACP,KAAK;CACP,GACA,OAAO,QAAQ;EACb,MAAM,UAAU,MAAM,kBAAkB,GAAG;EAC3C,IAAI,YAAY,KAAA,KAAa,YAAY,MAAM,MAAM,IAAI,SAAS,cAAc;EAChF,MAAM,QAAQ,mBAAmB,GAAG;EACpC,MAAM,kBAAmB,IAAI,QAAoC;EAGjE,MAAM,aACJ,IAAI,OAAO,gBACV,OAAO,IAAI,SAAS,QAAQ,WACxB,IAAI,IAAI,IAAI,QAAQ,GAAG,CAAC,CAAC,aAAa,IAAI,aAAa,KAAK,KAAA,IAC7D,KAAA;EACN,MAAM,SAAU,QAAQ,KAAwB;EAChD,IAAI,eAAe,KAAA,KAAa,eAAe,UAAU,oBAAoB,YAC3E,MAAM,0BAA0B,KAAK,SAAS;GAC5C,MAAM,QAAQ;GACd,SAAS,QAAQ;GACjB,aAAa;GACb,QAAQ;EACV,CAAC;EAEH,MAAM,cAAc,cAAc,mBAAmB;EACrD,MAAM,eAAe,MAAM,MAAM,iBAAiB,WAAW;EAC7D,OAAO,IAAI,KAAK,EAAE,aAAa,CAAC;CAClC,CACF;AACF;AAEA,MAAa,+BACX,SACA,OAAU,4BAmBP;CAEH,MAAM,iBADsB,QAAQ,cAEb,YAAY,OAC7B;EACE;EACA;EACA,oBAAoB,SAAS,sBAAsB;CACrD,IACA,CAAC,mBAAmB,qBAAqB;CAE/C,OAAO,mBACL,MACA;EAAE,QAAQ;EAAQ,MAAM;EAAyB,KAAK;CAAe,GACrE,OAAO,QAAQ;EACb,MAAM,EAAE,kBAAkB,gBAAgB,IAAI;EAC9C,MAAM,WAAW,eAAe,QAAQ,cAAc;EACtD,IAAI;GAEF,IAAI,wBAAwBC,gBAAO,GAAG;IACpC,MAAM,MAAM,MAAM,IAAI,QAAQ,QAAQ,QAAsB;KAC1D,OAAO,gBAAgB;KACvB,OAAO,CAAC;MAAE,OAAO;MAAoB,OAAO;KAAiB,CAAC;IAChE,CAAC;IAED,IAAI,QAAQ,QAAQ,QAAQ,KAAA,GAAW;KACrC,MAAM,sBAAM,IAAI,KAAK;KACrB,MAAM,YAAY,gBAAgB;KAClC,MAAM,IAAI,QAAQ,QAAQ,OAAO;MAC/B,OAAO,gBAAgB;MACvB,QAAQ;OACN,QAAQ,YAAY,aAAa;OACjC,mBAAmB,CAAC;OACpB,UAAU,YAAY,OAAQ,IAAI,aAAa;OAC/C,YAAY;OACZ,SAAS,YAAY,MAAM;OAC3B,WAAW;MACb;MACA,OAAO,CAAC;OAAE,OAAO;OAAM,OAAO,IAAI;MAAG,CAAC;KACxC,CAAC;KACD,OAAO,IAAI,KAAK,EAAE,QAAQ,UAAU,CAAC;IACvC;IACA,MAAM,IAAI,SAAS,eAAe,EAAE,SAAS,yBAAyB,CAAC;GACzE;GAEA,MAAM,qBACJ,MAAM,mBAAmB,GAAG,CAAC,CAAC,uBAAuB,gBAAgB;GACvE,MAAM,oBAAoB,qBACtB,MAAM,+BACJ,IAAI,QAAQ,SACZ,SACA,mBAAmB,EACrB,IACA;GACJ,IAAI,aAAa,IAAI,KAAK,cAAc,mBAAmB;GAC3D,IAAI;GAEJ,IAAI;IAEF,MAAM,WACJ,gBAAwE,MAFxD,UAAU,cAAc,MAAM,gBAAgB,CAEa;IAE7E,IAAI,aAAa,KAAA,KAAa,aAAa,MAAM;KAC/C,eAAe,SAAS,eAAe,KAAA;KACvC,kBAAkB,SAAS,qBAAqB,KAAA;IAClD;GACF,QAAQ,CAER;GAEA,IAAI,eAAe,KAAA,KAAa,eAAe,QAAQ,eAAe,IACpE,IAAI;IAGF,MAAM,OADU,gBAAkC,MADhC,UAAU,cAAc,WAAW,gBAAgB,CAElD,CAAC,EAAE;IACtB,IAAI,SAAS,KAAA,KAAa,SAAS,QAAQ,SAAS,IAClD,aAAa,2CAA2C,IAAI;GAEhE,QAAQ,CAER;GAGF,IAAI,eAAe,KAAA,KAAa,eAAe,QAAQ,eAAe,IACpE,MAAM,IAAI,MAAM,0DAA0D;GAG5E,IAAI,oBACF,MAAM,+BACJ,IAAI,QAAQ,SACZ,SACA,mBAAmB,IACnB,EACE,WACF,CACF;GAGF,MAAM,UAAU,cAAc,QAAQ,EACpC,MAAM;IAAE,MAAM;IAAkB,OAAO;GAAW,EACpD,CAAC;GAED,MAAM,YACJ,oBAAoB,KAAA,KAAa,oBAAoB,QAAQ,oBAAoB,KAC7E,IAAI,KAAK,eAAe,IACxB,KAAA;GAEN,MAAM,MAAM,MAAM,IAAI,QAAQ,QAAQ,QAAsB;IAC1D,OAAO,gBAAgB;IACvB,OAAO,CAAC;KAAE,OAAO;KAAoB,OAAO;IAAiB,CAAC;GAChE,CAAC;GAED,IAAI,QAAQ,KAAA,KAAa,QAAQ,MAAM;IACrC,MAAM,sBAAM,IAAI,KAAK;IACrB,MAAM,YAAY,gBAAgB;IAClC,MAAM,IAAI,QAAQ,QAAQ,OAAO;KAC/B,OAAO,gBAAgB;KACvB,QAAQ;MACN,QAAQ,YAAY,aAAa;MACjC,mBAAmB,CAAC;MACpB,UAAU,YAAY,OAAQ,aAAa,IAAI,aAAa;MAC5D,YAAY;MACZ,SAAS,YAAY,MAAM;MAC3B;MACA,WAAW;KACb;KACA,OAAO,CAAC;MAAE,OAAO;MAAM,OAAO,IAAI;KAAG,CAAC;IACxC,CAAC;GACH,OACE,IAAI,QAAQ,OAAO,KACjB,yCAAyC,iBAAiB,YAC5D;GAGF,OAAO,IAAI,KAAK,EAAE,QAAQ,UAAU,CAAC;EACvC,SAAS,OAAgB;GACvB,IAAI,QAAQ,OAAO,MAAM,kCAAkC,KAAK;GAChE,MAAM,eACJ,iBAAiB,QACb,MAAM,UACN,qBAAqB,+BAA+B;GAC1D,MAAM,IAAI,SAAS,eAAe;IAChC,MAAM;IACN,SAAS;GACX,CAAC;EACH;CACF,CACF;AACF;AAEA,MAAa,8BACX,SACA,OAAU,2BAmBP;CAEH,MAAM,iBADsB,QAAQ,cAEb,YAAY,OAC7B;EACE;EACA;EACA,oBAAoB,SAAS,qBAAqB;CACpD,IACA,CAAC,mBAAmB,qBAAqB;CAE/C,OAAO,mBACL,MACA;EAAE,QAAQ;EAAQ,MAAM;EAAyB,KAAK;CAAe,GACrE,OAAO,QAAQ;EACb,MAAM,EAAE,qBAAqB,IAAI;EACjC,MAAM,WAAW,eAAe,QAAQ,cAAc;EACtD,IAAI;GACF,MAAM,qBACJ,MAAM,mBAAmB,GAAG,CAAC,CAAC,uBAAuB,gBAAgB;GACvE,MAAM,oBAAoB,qBACtB,MAAM,+BACJ,IAAI,QAAQ,SACZ,SACA,mBAAmB,EACrB,IACA;GACJ,IAAI,aAAa,IAAI,KAAK,cAAc,mBAAmB;GAC3D,IAAI,eAAe,KAAA,KAAa,eAAe,QAAQ,eAAe,IACpE,IAAI;IAEF,MAAM,WACJ,gBAAwE,MAFxD,UAAU,cAAc,MAAM,gBAAgB,CAEa;IAC7E,IAAI,aAAa,KAAA,KAAa,aAAa,MACzC,aAAa,SAAS,eAAe,KAAA;GAEzC,QAAQ,CAER;GAGF,IAAI,eAAe,KAAA,KAAa,eAAe,QAAQ,eAAe,IACpE,IAAI;IAGF,MAAM,OADU,gBAAkC,MADhC,UAAU,cAAc,WAAW,gBAAgB,CAElD,CAAC,EAAE;IACtB,IAAI,SAAS,KAAA,KAAa,SAAS,QAAQ,SAAS,IAClD,aAAa,2CAA2C,IAAI;GAEhE,QAAQ,CAER;GAGF,IAAI,eAAe,KAAA,KAAa,eAAe,QAAQ,eAAe,IACpE,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,0DACX,CAAC;GAGH,IAAI,oBACF,MAAM,+BACJ,IAAI,QAAQ,SACZ,SACA,mBAAmB,IACnB,EACE,WACF,CACF;GAGF,MAAM,UAAU,cAAc,OAAO,EACnC,MAAM;IAAE,MAAM;IAAkB,OAAO;GAAW,EACpD,CAAC;GAGD,MAAM,IAAI,QAAQ,QAAQ,OAAO;IAC/B,OAAO,gBAAgB;IACvB,QAAQ;KACN,QAAQ;KACR,mBAAmB;KACnB,UAAU;KACV,YAAY;KACZ,SAAS;KACT,2BAAW,IAAI,KAAK;IACtB;IACA,OAAO,CAAC;KAAE,OAAO;KAAoB,OAAO;IAAiB,CAAC;GAChE,CAAC;GAED,OAAO,IAAI,KAAK,EAAE,QAAQ,UAAU,CAAC;EACvC,SAAS,OAAgB;GACvB,IAAI,QAAQ,OAAO,MAAM,iCAAiC,KAAK;GAC/D,MAAM,eACJ,iBAAiB,QACb,MAAM,UACN,qBAAqB,8BAA8B;GACzD,MAAM,IAAI,SAAS,eAAe;IAChC,MAAM;IACN,SAAS;GACX,CAAC;EACH;CACF,CACF;AACF;AAEA,MAAa,6BACX,SACA,OAAU,gCAgBP;CACH,MAAM,wBAAwB,EAAE,OAAO,EACrC,kBAAkB,EAAE,OAAO,EAC7B,CAAC;CAED,MAAM,iBADsB,QAAQ,cAEb,YAAY,OAC7B;EACE;EACA;EACA,oBAAoB,SAAS,8BAA8B;CAC7D,IACA,CAAC,mBAAmB,qBAAqB;CAE/C,MAAM,UAAU,OAAO,QAAgC;EACrD,MAAM,EAAE,qBAAqB,IAAI;EAEjC,IAAI,wBAAwB,gBAA0B,GACpD,OAAO,IAAI,KAAK;GAAE,MAAM;GAAM,SAAS;EAAoD,CAAC;EAG9F,MAAM,WAAW,eAAe,QAAQ,cAAc;EACtD,IAAI;GAEF,MAAM,MAAM,gBAAkC,MAD5B,UAAU,cAAc,WAAW,gBAA0B,CAC9B;GACjD,OAAO,IAAI,KAAK,EAAE,MAAM,KAAK,QAAQ,KAAK,CAAC;EAC7C,SAAS,OAAgB;GACvB,IAAI,QAAQ,OAAO,MAAM,0CAA0C,KAAK;GACxE,MAAM,eACJ,iBAAiB,QAAQ,MAAM,UAAU;GAC3C,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,aACX,CAAC;EACH;CACF;CAEA,OAAO,mBACL,MACA;EACE,QAAQ;EACR,OAAO;EACP,KAAK;CACP,GACA,OACF;AACF;AAEA,MAAa,gBACX,UACA,OAAU,qBAcP;CACH,OAAO,mBACL,MACA;EACE,QAAQ;EACR,UAAU,EACR,SAAS,EACP,aAAa,uBACf,EACF;CACF,GACA,OAAO,QAAQ;EACb,MAAM,WAAW,MAAM,mBAAmB,GAAG;EAC7C,OAAO,IAAI,KAAK,EAAE,SAAS,CAAC;CAC9B,CACF;AACF;AAEA,MAAa,aACX,UACA,OAAU,kBAaP;CACH,OAAO,mBACL,MACA;EACE,QAAQ;EACR,UAAU,EAAE,GAAG,cAAc;EAC7B,KAAK,CAAC,iBAAiB;CACzB,GACA,OAAO,QAAQ;EACb,IAAI;GACF,MAAM,QAAQ,MAAM,gBAAgB,GAAG;GACvC,OAAO,IAAI,KAAK,EAAE,MAAM,CAAC;EAC3B,SAAS,OAAgB;GACvB,IAAI,QAAQ,OAAO,MAAM,wBAAwB,KAAK;GACtD,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;GAC9D,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,aACX,CAAC;EACH;CACF,CACF;AACF;AAEA,MAAa,aACX,SACA,OAAU,kBAeP;CACH,OAAO,mBACL,MACA;EACE,QAAQ;EACR,UAAU,EACR,SAAS,EACP,aAAa,oBACf,EACF;CACF,GACA,OAAO,QAAgC;EACrC,OAAO,IAAI,KAAK,MAAM,qBAAqB,OAAO,CAAC;CACrD,CACF;AACF;AC75DA,MAAa,eAA0C,EAzDrD,qBAAqB,EACnB,QAAQ;CACN,WAAW;EACT,MAAM;EACN,UAAU;EACV,QAAQ;CACV;CACA,YAAY;EACV,MAAM;EACN,UAAU;CACZ;CACA,aAAa;EACX,MAAM;EACN,UAAU;EACV,OAAO;CACT;CACA,QAAQ;EACN,MAAM;EACN,UAAU;EACV,OAAO;CACT;CACA,QAAQ;EACN,MAAM;EACN,UAAU;CACZ;CACA,UAAU;EACR,MAAM;EACN,UAAU;CACZ;CACA,QAAQ;EACN,MAAM;EACN,UAAU;CACZ;CACA,MAAM;EACJ,MAAM;EACN,UAAU;CACZ;CACA,SAAS;EACP,MAAM;EACN,UAAU;CACZ;CACA,UAAU;EACR,MAAM;EACN,UAAU;CACZ;CACA,WAAW;EACT,MAAM;EACN,UAAU;CACZ;CACA,WAAW;EACT,MAAM;EACN,UAAU;CACZ;AACF,EACF,EAGqD;AAwGvD,MAAa,gBAA4C,EArGvD,sBAAsB,EACpB,QAAQ;CACN,MAAM;EACJ,MAAM;EACN,UAAU;EACV,OAAO;CACT;CACA,aAAa;EACX,MAAM;EACN,UAAU;EACV,OAAO;CACT;CACA,QAAQ;EACN,MAAM;EACN,UAAU;EACV,OAAO;CACT;CACA,cAAc;EACZ,MAAM;EACN,UAAU;EACV,OAAO;CACT;CACA,kBAAkB;EAChB,MAAM;EACN,UAAU;EACV,QAAQ;CACV;CACA,sBAAsB;EACpB,MAAM;EACN,UAAU;EACV,OAAO;CACT;CACA,UAAU;EACR,MAAM;EACN,UAAU;CACZ;CACA,QAAQ;EACN,MAAM;EACN,cAAc;CAChB;CACA,aAAa;EACX,MAAM;EACN,UAAU;CACZ;CACA,WAAW;EACT,MAAM;EACN,UAAU;CACZ;CACA,YAAY;EACV,MAAM;EACN,UAAU;CACZ;CACA,UAAU;EACR,MAAM;EACN,UAAU;CACZ;CACA,mBAAmB;EACjB,MAAM;EACN,UAAU;EACV,cAAc;CAChB;CACA,UAAU;EACR,MAAM;EACN,UAAU;CACZ;CACA,YAAY;EACV,MAAM;EACN,UAAU;CACZ;CACA,SAAS;EACP,MAAM;EACN,UAAU;CACZ;CACA,iBAAiB;EACf,MAAM;EACN,UAAU;CACZ;CACA,SAAS;EACP,MAAM;EACN,UAAU;CACZ;CACA,OAAO;EACL,MAAM;EACN,UAAU;CACZ;CACA,aAAa;EACX,MAAM;EACN,UAAU;CACZ;CACA,WAAW;EACT,MAAM;EACN,UAAU;CACZ;CACA,WAAW;EACT,MAAM;EACN,UAAU;CACZ;AACF,EACF,EAGuD;AAkBzD,MAAa,YAAoC,EAf/C,kBAAkB,EAChB,QAAQ;CACN,eAAe;EAAE,MAAM;EAAU,UAAU;CAAK;CAChD,aAAa;EAAE,MAAM;EAAU,UAAU;EAAM,OAAO;CAAK;CAG3D,cAAc;EAAE,MAAM;EAAU,UAAU;EAAM,QAAQ;CAAK;CAC7D,cAAc;EAAE,MAAM;EAAU,UAAU;EAAM,QAAQ;CAAK;CAC7D,OAAO;EAAE,MAAM;EAAU,UAAU;CAAM;CACzC,WAAW;EAAE,MAAM;EAAQ,UAAU;CAAK;CAC1C,WAAW;EAAE,MAAM;EAAQ,UAAU;CAAK;AAC5C,EACF,EAG+C;AAcjD,MAAa,qBAAsD,EAXjE,2BAA2B,EACzB,QAAQ;CACN,gBAAgB;EAAE,MAAM;EAAU,UAAU;EAAM,QAAQ;EAAM,OAAO;CAAK;CAC5E,4BAA4B;EAAE,MAAM;EAAU,UAAU;CAAM;CAC9D,qBAAqB;EAAE,MAAM;EAAU,UAAU;CAAM;CACvD,WAAW;EAAE,MAAM;EAAQ,UAAU;CAAK;CAC1C,WAAW;EAAE,MAAM;EAAQ,UAAU;CAAK;AAC5C,EACF,EAGiE;AAQnE,MAAa,OAA0B,EALrC,MAAM,EACJ,QAAQ,CAAC,EACX,EAGqC;AAavC,MAAa,eAA0C,EAVrD,cAAc,EACZ,QAAQ,EACN,OAAO;CACL,MAAM;CACN,UAAU;AACZ,EACF,EACF,EAGqD;AAyDvD,MAAa,WAAkC,EAtD7C,iBAAiB,EACf,QAAQ;CACN,MAAM;EACJ,MAAM;EACN,UAAU;CACZ;CACA,aAAa;EACX,MAAM;EACN,UAAU;CACZ;CACA,OAAO;EACL,MAAM;EACN,UAAU;CACZ;CACA,UAAU;EACR,MAAM;EACN,UAAU;CACZ;CACA,UAAU;EACR,MAAM;EACN,UAAU;EACV,cAAc;CAChB;CACA,WAAW;EACT,MAAM;EACN,UAAU;EACV,cAAc;CAChB;CACA,YAAY;EACV,MAAM;EACN,UAAU;EACV,QAAQ;CACV;CACA,MAAM;EACJ,MAAM;EACN,UAAU;EACV,QAAQ;CACV;CACA,UAAU;EACR,MAAM;EACN,UAAU;CACZ;CACA,WAAW;EACT,MAAM;EACN,UAAU;CACZ;CACA,WAAW;EACT,MAAM;EACN,UAAU;CACZ;AACF,EACF,EAG6C;AAuD/C,MAAa,QAA4B,EApDvC,cAAc,EACZ,QAAQ;CACN,MAAM;EACJ,MAAM;EACN,UAAU;CACZ;CACA,aAAa;EACX,MAAM;EACN,UAAU;CACZ;CACA,QAAQ;EACN,MAAM;EACN,UAAU;CACZ;CACA,UAAU;EACR,MAAM;EACN,UAAU;CACZ;CACA,UAAU;EACR,MAAM;EACN,UAAU;CACZ;CACA,OAAO;EACL,MAAM;EACN,UAAU;CACZ;CACA,UAAU;EACR,MAAM;EACN,UAAU;EACV,QAAQ;CACV;CACA,YAAY;EACV,MAAM;EACN,UAAU;EACV,QAAQ;CACV;CACA,UAAU;EACR,MAAM;EACN,UAAU;CACZ;CACA,WAAW;EACT,MAAM;EACN,UAAU;CACZ;CACA,WAAW;EACT,MAAM;EACN,UAAU;CACZ;AACF,EACF,EAGuC;AA8CzC,MAAa,gBAA4C,EA3CvD,sBAAsB,EACpB,QAAQ;CACN,SAAS;EACP,MAAM;EACN,UAAU;EACV,QAAQ;CACV;CACA,WAAW;EACT,MAAM;EACN,UAAU;EACV,OAAO;CACT;CACA,WAAW;EACT,MAAM;EACN,UAAU;EACV,OAAO;CACT;CACA,SAAS;EACP,MAAM;EACN,UAAU;CACZ;CACA,QAAQ;EACN,MAAM;EACN,UAAU;EACV,cAAc;EACd,OAAO;CACT;CACA,aAAa;EACX,MAAM;EACN,UAAU;CACZ;CACA,WAAW;EACT,MAAM;EACN,UAAU;CACZ;CACA,WAAW;EACT,MAAM;EACN,UAAU;CACZ;AACF,EACF,EAGuD;CAEI;CAC3D,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;AACL;AAKA,MAAa,aAAa,YAAuD;CAC/E,IAAI;CACJ,MAAM,eAAe,QAAQ;CAE7B,IAAI,QAAQ,cAAc,YAAY,MACpC,aAAa;EACX,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;CACL;MAEA,aAAa;EACX,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;CACL;CAIF,IAAI,QAAQ,cAAc,YAAY,MACpC,aAAa;EACX,GAAG;EACH,GAAG;CACL;CAGF,IAAI,QAAQ,WAAW,KAAA,KAAa,kBAAkB,QAAQ,QAAQ;EACpE,MAAM,EAAE,cAAc,eAAe,GAAG,eAAe,gBAAgB,CAAC;EACxE,OAAO,YAAY,YAAY,UAAU;CAC3C;CAEA,OAAO,YAAY,YAAY,YAAY;AAC7C;;;ACjiBA,eAAsB,qBACpB,KACA,SAC6B;CAC7B,MAAM,WAAW,sBAAsB,QAAQ,cAAc;CAC7D,MAAM,QAAQ,mBAAmB,GAAG;CACpC,IAAI;EACF,MAAM,eAAe,MAAM,SAAS,aAAa;EAEjD,IAAI,CAAC,MAAM,QAAQ,YAAY,GAC7B,OAAO;GAAE,QAAQ;GAAW,OAAO;EAAE;EAGvC,KAAK,MAAM,WAAW,cAAc;GAClC,MAAM,aAAa,OAAO,QAAQ,EAAE;GACpC,MAAM,gBAAgB;IACpB,MAAM,QAAQ,QAAQ;IACtB,aAAa,QAAQ,eAAe;IACpC,OAAO,QAAQ,SAAS;IACxB,UAAU,QAAQ,YAAY;IAC9B,UAAU,QAAQ,YAAY;IAC9B,WACE,QAAQ,cAAc,KAAA,KACtB,QAAQ,cAAc,QACtB,QAAQ,cAAc;IACxB;IACA,MACG,QAA8B,QAC/B,QAAQ,MAAM,YAAY,CAAC,CAAC,QAAQ,QAAQ,GAAG,KAC/C;IACF,UAAU,0BAA2B,QAAmC,QAAQ;IAChF,2BAAW,IAAI,KAAK;GACtB;GAEA,MAAM,MAAM,0BAA0B,YAAY;IAChD,GAAG;IACH,2BAAW,IAAI,KAAK;GACtB,CAAC;EACH;EAEA,OAAO;GAAE,QAAQ;GAAW,OAAO,aAAa;EAAO;CACzD,SAAS,OAAgB;EACvB,IAAI,QAAQ,OAAO,MAAM,2BAA2B,KAAK;EACzD,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;EAC9D,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,aACX,CAAC;CACH;AACF;AAEA,eAAsB,kBACpB,KACA,SAC6B;CAC7B,MAAM,WAAW,sBAAsB,QAAQ,cAAc;CAC7D,MAAM,QAAQ,mBAAmB,GAAG;CACpC,IAAI;EACF,MAAM,YAAY,MAAM,SAAS,UAAU;EAE3C,IAAI,CAAC,MAAM,QAAQ,SAAS,GAC1B,OAAO;GAAE,QAAQ;GAAW,OAAO;EAAE;EAGvC,KAAK,MAAM,QAAQ,WAAW;GAC5B,MAAM,aAAa,OAAO,KAAK,EAAE;GACjC,MAAM,WAAW;IACf,MAAM,KAAK,QAAQ;IACnB,aAAa,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;IACvE,QAAQ,KAAK,UAAU;IACvB,UAAU,KAAK,YAAY;IAC3B,UAAU,KAAK,YAAY;IAC3B,UAAU,KAAK,aAAa;IAC5B;IACA,UAAU,0BAA2B,KAAgC,QAAQ;IAC7E,2BAAW,IAAI,KAAK;GACtB;GAEA,MAAM,MAAM,uBAAuB,YAAY;IAC7C,GAAG;IACH,2BAAW,IAAI,KAAK;GACtB,CAAC;EACH;EAEA,OAAO;GAAE,QAAQ;GAAW,OAAO,UAAU;EAAO;CACtD,SAAS,OAAgB;EACvB,IAAI,QAAQ,OAAO,MAAM,wBAAwB,KAAK;EACtD,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;EAC9D,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,aACX,CAAC;CACH;AACF;AAEA,eAAsB,0BACpB,KACA,SACA,OAC4C;CAC5C,MAAM,EAAE,mBAAmB;CAC3B,MAAM,QAAQ,mBAAmB,GAAG;CACpC,MAAM,eAAe,MAAM,MAAM,qBAAqB,cAAc;CAEpE,IAAI,iBAAiB,KAAA,KAAa,iBAAiB,MACjD,MAAM,IAAI,SAAS,aAAa,EAAE,SAAS,yBAAyB,CAAC;CAGvE,MAAM,cAAc,MAAM,+BACxB,IAAI,QAAQ,SACZ,SACA,aAAa,EACf;CACA,IACE,aAAa,sBAAsB,KAAA,KACnC,YAAY,sBAAsB,QAClC,YAAY,sBAAsB,IAElC,MAAM,IAAI,SAAS,eAAe,EAChC,SAAS,oDACX,CAAC;CAIH,MAAM,QAAO,MADO,SAAS,QAAQ,YAAY,EAAA,CAC9B,MAChB,cAAc,UAAU,KAAK,YAAY,MAAM,aAAa,KAAK,YAAY,CAChF;CAEA,IAAI,SAAS,KAAA,KAAa,SAAS,MACjC,MAAM,IAAI,SAAS,aAAa,EAAE,SAAS,iBAAiB,CAAC;CAG/D,MAAM,SAAS,oBAAoB,MAAM,aAAa,SAAS,CAAC;CAChE,IAAI,WAAW,KAAA,KAAa,WAAW,MACrC,MAAM,IAAI,SAAS,eAAe,EAAE,SAAS,6BAA6B,CAAC;CAG7E,IAAI;CACJ,IAAI,gBAAgB,aAAa;CACjC,MAAM,cAAc,aAAa;CACjC,IAAI,gBAAgB,KAAA,KAAa,gBAAgB,QAAQ,gBAAgB,IAAI;EAC3E,MAAM,OAAO,MAAM,MAAM,SAAS,WAAW;EAC7C,IAAI,SAAS,KAAA,KAAa,SAAS,MAAM;GACvC,QAAQ,KAAK;GACb,gBAAgB,KAAK;EACvB,OAAO,IAAI,QAAQ,cAAc,YAAY,MAAM;GACjD,MAAM,cAAc,MAAM,MAAM,sBAAsB,WAAW;GACjE,IAAI,gBAAgB,KAAA,KAAa,gBAAgB,MAAM;IACrD,MAAM,YAAY,MAAM,MAAM,SAAS,YAAY,MAAM;IACzD,QAAQ,WAAW;IACnB,gBAAgB,WAAW,MAAM,YAAY;GAC/C;EACF;CACF;CAEA,IAAI,UAAU,KAAA,KAAa,UAAU,QAAQ,UAAU,IACrD,MAAM,IAAI,SAAS,aAAa,EAAE,SAAS,uBAAuB,CAAC;CAGrE,MAAM,gBAAgB,KAAK,YAAY;CACvC,IAAI,CAAC,kBAAkB,QAAQ,aAAa,GAC1C,MAAM,IAAI,SAAS,eAAe;EAChC,SAAS,UAAU,OAAO,yCAAyC,cAAc;EACjF,QAAQ;CACV,CAAC;CAGH,MAAM,WAAW,sBAAsB,QAAQ,cAAc;CAC7D,MAAM,kBAAkB,sBAAsB;EAC5C;EACA;CACF,CAAC;CACD,MAAM,4BAA4B,0BAA0B,eAAe;CAU3E,MAAM,kBAAkB,MARC,SAAS,oBAAoB;EACpD;EACA;EACA,oBAAoB,YAAY;EAChC,WAAW,OAAO,aAAa,GAAG,GAAG,KAAK,IAAI;EAC9C,UAAU;CACZ,CAAC;CAGD,IAAI,iBAAiB,WAAW,aAAa,gBAAgB,cAAc,KAAA,GAAW;EACpF,MAAM,sBAAM,IAAI,KAAK;EACrB,MAAM,gBAAgB,iBAAiB,KAAK,KAAK,YAAY,SAAS;EAEtE,MAAM,MAAM,kBAAkB;GAC5B,WAAW,gBAAgB;GAC3B,YACE,gBAAgB,OAAO,KAAA,KAAa,gBAAgB,OAAO,OACvD,OAAO,gBAAgB,EAAE,IACzB,KAAA;GACN;GACA,QAAQ;GACR,QAAQ,gBAAgB;GACxB,UAAU,gBAAgB;GAC1B,QAAQ;GACR,MAAM,KAAK,KAAK,YAAY;GAC5B,UAAU;GACV,WAAW;GACX,WAAW;EACb,CAAC;EAED,MAAM,MAAM,mBAAmB,aAAa,IAAI;GAC9C,aAAa;GACb,WAAW;GACX,WAAW;GACX,sBAAsB,gBAAgB;EACxC,CAAC;EAED,OAAO;GAAE,QAAQ;GAAW,MAAM;EAAgB;CACpD;CAEA,OAAO;EAAE,QAAQ;EAAU,MAAM;CAAgB;AACnD;;;AC7MA,SAAS,SAAS,OAAoC;CACpD,OAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ,KAAA;AAC7D;AAEA,SAAS,aAAa,OAAoC;CACxD,IAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GAAG,OAAO,OAAO,KAAK;CAC5E,OAAO,SAAS,KAAK;AACvB;AAEA,SAAS,OAAO,OAAgB,UAAsB;CACpD,IAAI,iBAAiB,MAAM,OAAO;CAClC,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;EAC1D,MAAM,OAAO,IAAI,KAAK,KAAK;EAC3B,IAAI,CAAC,OAAO,MAAM,KAAK,QAAQ,CAAC,GAAG,OAAO;CAC5C;CACA,OAAO;AACT;AAEA,SAAS,eAAe,OAAyC;CAC/D,IAAI,UAAU,MAAM,OAAO;CAC3B,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,IAAI,iBAAiB,MAAM,OAAO;CAClC,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;EAC1D,MAAM,OAAO,IAAI,KAAK,KAAK;EAC3B,IAAI,CAAC,OAAO,MAAM,KAAK,QAAQ,CAAC,GAAG,OAAO;CAC5C;AAEF;AAEA,eAAe,eAAe,SAAkB,OAAwC;CACtF,IAAI;EACF,OAAQ,MAAM,QAAQ,SAAuB,EAAE,MAAM,CAAC,KAAM,CAAC;CAC/D,QAAQ;EAEN,OAAO,CAAC;CACV;AACF;AAEA,SAAS,cAAc,QAA+C;CACpE,MAAM,sBAAM,IAAI,KAAK;CACrB,MAAM,cAAc,aAAa,OAAO,WAAW,KAAK,aAAa,OAAO,MAAM,KAAK;CACvF,MAAM,KAAK,aAAa,OAAO,EAAE;CACjC,OAAO;EACL,GAAI,OAAO,KAAA,IAAY,EAAE,GAAG,IAAI,CAAC;EACjC,MAAM,SAAS,OAAO,IAAI,KAAK;EAC/B;EACA,QAAQ,aAAa,OAAO,MAAM,KAAK;EACvC,cACE,SAAS,OAAO,YAAY,KAAK,SAAS,OAAO,oBAAoB,KAAK,KAAA;EAC5E,kBACE,SAAS,OAAO,gBAAgB,KAAK,SAAS,OAAO,wBAAwB,KAAK,KAAA;EACpF,sBACE,SAAS,OAAO,oBAAoB,KACpC,SAAS,OAAO,4BAA4B,KAC5C,KAAA;EACF,UAAU,SAAS,OAAO,QAAQ,KAAK,SAAS,OAAO,gBAAgB,KAAK,KAAA;EAC5E,QAAQ,SAAS,OAAO,MAAM,KAAK;EACnC,aAAa,OAAO,OAAO,aAAa,GAAG;EAC3C,WAAW,eAAe,OAAO,SAAS;EAC1C,YAAY,eAAe,OAAO,UAAU;EAC5C,UAAU,eAAe,OAAO,QAAQ;EACxC,mBAAmB,OAAO,sBAAsB;EAChD,UAAU,eAAe,OAAO,QAAQ;EACxC,YAAY,eAAe,OAAO,UAAU;EAC5C,SAAS,eAAe,OAAO,OAAO;EACtC,iBAAiB,SAAS,OAAO,eAAe,KAAK,KAAA;EACrD,SAAS,SAAS,OAAO,OAAO,KAAK,KAAA;EACrC,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ,KAAA;EACzD,aAAa,SAAS,OAAO,WAAW,KAAK,KAAA;EAC7C,WAAW,OAAO,OAAO,WAAW,GAAG;EACvC,WAAW,OAAO,OAAO,WAAW,GAAG;CACzC;AACF;AAEA,eAAe,gBACb,SACA,eACA,QACA,QACe;CACf,MAAM,eAAe,SAAS,OAAO,oBAAoB,KAAK,SAAS,OAAO,YAAY;CAC1F,MAAM,cAAc,aAAa,OAAO,EAAE;CAC1C,IAAI,iBAAiB,KAAA,KAAa,gBAAgB,KAAA,GAAW;CAC7D,MAAM,eAAe,GAAG,cAAc,GAAG;CACzC,IAAI;EAKF,IAAI,MAJmB,QAAQ,QAAsB;GACnD,OAAO,gBAAgB;GACvB,OAAO,CAAC;IAAE,OAAO;IAAgB,OAAO;GAAa,CAAC;EACxD,CAAC,GACa;GACZ,OAAO,UAAU,WAAW;GAC5B,OAAO,WAAW;GAClB;EACF;EACA,MAAM,sBAAM,IAAI,KAAK;EACrB,MAAM,QAAQ,SAAS,OAAO,KAAK;EACnC,MAAM,QAAQ,OAAO;GACnB,OAAO,gBAAgB;GACvB,MAAM;IACJ;IACA;IACA;IACA;IACA,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;IACvC,WAAW,OAAO,OAAO,WAAW,GAAG;IACvC,WAAW,OAAO,OAAO,WAAW,GAAG;GACzC;EACF,CAAC;EACD,OAAO,UAAU,YAAY;CAC/B,SAAS,OAAO;EACd,OAAO,UAAU,UAAU;EAC3B,OAAO,SAAS,KAAK;GACnB,MAAM;GACN,IAAI;GACJ,SAAS,iBAAiB,QAAQ,MAAM,UAAU;EACpD,CAAC;CACH;AACF;AAEA,eAAsB,kCACpB,KACA,SACwC;CACxC,MAAM,UAAU,IAAI,QAAQ;CAC5B,MAAM,SAAwC;EAC5C,QAAQ;EACR,eAAe;GAAE,UAAU;GAAG,SAAS;GAAG,QAAQ;EAAE;EACpD,WAAW;GAAE,UAAU;GAAG,SAAS;GAAG,QAAQ;EAAE;EAChD,aAAa;GAAE,UAAU;GAAG,SAAS;GAAG,QAAQ;EAAE;EAClD,SAAS;EACT,UAAU,CAAC;CACb;CAEA,KAAK,MAAM,iBAAiB,CAAC,QAAQ,cAAc,GAAY;EAC7D,MAAM,UAAU,MAAM,eAAe,SAAS,aAAa;EAC3D,KAAK,MAAM,UAAU,SAAS,MAAM,gBAAgB,SAAS,eAAe,QAAQ,MAAM;CAC5F;CAEA,MAAM,sBAAsB,MAAM,eAAe,SAAS,uBAAuB,YAAY;CAC7F,KAAK,MAAM,UAAU,qBAAqB;EACxC,MAAM,KAAK,aAAa,OAAO,EAAE;EACjC,IAAI,OAAO,KAAA,GAAW;EACtB,IAAI;GAKF,IAAI,MAJmB,QAAQ,QAAsB;IACnD,OAAO,gBAAgB;IACvB,OAAO,CAAC;KAAE,OAAO;KAAM,OAAO;IAAG,CAAC;GACpC,CAAC,GACa;IACZ,OAAO,cAAc,WAAW;IAChC,OAAO,WAAW;GACpB,OAAO;IACL,MAAM,QAAQ,OAAO;KACnB,OAAO,gBAAgB;KACvB,MAAM,cAAc,MAAM;KAC1B,cAAc;IAChB,CAAC;IACD,OAAO,cAAc,YAAY;GACnC;EACF,SAAS,OAAO;GACd,OAAO,cAAc,UAAU;GAC/B,OAAO,SAAS,KAAK;IACnB,MAAM;IACN;IACA,SAAS,iBAAiB,QAAQ,MAAM,UAAU;GACpD,CAAC;EACH;EAEA,MAAM,oBACJ,SAAS,OAAO,iBAAiB,KAAK,SAAS,OAAO,yBAAyB;EACjF,MAAM,aAAa,SAAS,OAAO,UAAU,KAAK,SAAS,OAAO,kBAAkB;EACpF,IAAI,sBAAsB,KAAA,KAAa,eAAe,KAAA,GACpD,IAAI;GAKF,IAAI,MAJ6B,QAAQ,QAAsB;IAC7D,OAAO,gBAAgB;IACvB,OAAO,CAAC;KAAE,OAAO;KAAkB,OAAO;IAAG,CAAC;GAChD,CAAC,GACuB;IACtB,OAAO,YAAY,WAAW;IAC9B,OAAO,WAAW;GACpB,OAAO;IACL,MAAM,+BAA+B,SAAS,SAAS,IAAI;KACzD;KACA;IACF,CAAC;IACD,OAAO,YAAY,YAAY;GACjC;EACF,SAAS,OAAO;GACd,OAAO,YAAY,UAAU;GAC7B,OAAO,SAAS,KAAK;IACnB,MAAM;IACN;IACA,SAAS,iBAAiB,QAAQ,MAAM,UAAU;GACpD,CAAC;EACH;CAEJ;CAEA,OAAO,SAAS,OAAO,SAAS,SAAS,IAAI,YAAY;CACzD,OAAO;AACT;;;ACtKA,MAAM,uBAA4D,iBAChE,OAAO,YACL,OAAO,QAAQ,oBAAoB,CAAC,CAAC,KAAK,CAAC,KAAK,WAAW,CACzD,KACA,OAAO,UAAU,WAAW,QAAS,MAA8B,OACrE,CAAC,CACH,CACF;AAkEA,MAAM,wBAIJ,YAC8B;CAC9B,MAAM,eAAe;EACnB,GAAI;EACJ,SAAS,QAAQ;CACnB;CACA,OAAO;EACL,IAAI;EACJ,SAAS;EACT,WAAW;GACT,uBAAuB,sBACrB,cACA,kCACF;GACA,mBAAmB,kBAAkB,cAAc,8BAA8B;GACjF,mBAAmB,kBAAkB,cAAc,8BAA8B;GACjF,iBAAiB,gBAAgB,cAAc,mBAAmB;GAClE,kBAAkB,iBAAiB,cAAc,6BAA6B;GAC9E,WAAW,UAAU,cAAc,kBAAkB;GACrD,qBAAqB,4BACnB,cACA,gCACF;GACA,oBAAoB,2BAA2B,cAAc,+BAA+B;GAC5F,2BAA2B,0BACzB,cACA,oCACF;GACA,wBAAwB,0BACtB,cACA,oCACF;GACA,oBAAoB,mBAAmB,cAAc,+BAA+B;GACpF,qBAAqB,oBAAoB,cAAc,gCAAgC;GACvF,oBAAoB,mBAAmB,cAAc,+BAA+B;GACpF,qBAAqB,oBAAoB,cAAc,gCAAgC;GACvF,cAAc,aAAa,cAAc,yBAAyB;GAClE,WAAW,UAAU,cAAc,sBAAsB;EAC3D;EACA,QAAQ,UAAU,OAAO;EACzB,QAAQ,QAAmC;GACzC,MAAM,8BAA8B,IAAI,UAAU,cAAc;GAChE,IAAI,QAAQ,cAAc,YAAY,QAAQ,CAAC,6BAC7C,IAAI,OAAO,MACT,8IACF;GAGF,OAAO,EACL,SAAS,EACP,eAAe;IACb,MAAM;KACJ,QAAQ,EACN,MAAM,MACJ,MAMA,SACA;MACA,IACE,CAAC,WACD,QAAQ,2BAA2B,QACnC,KAAK,UAAU,QACf,KAAK,UAAU,KAAA,KACf,KAAK,UAAU,IAEf;MAEF,IAAI;OACF,MAAM,SAAS,MAAM,wBAAwB;QAC3C,SAAS,IAAI;QACb,QAAQ,QAAQ;QAChB,QAAQ,IAAI;QACZ,WAAW;SACT,IAAI,KAAK;SACT,MAAM;SACN,OAAO,KAAK;SACZ,MAAM,KAAK;SACX,eAAe,KAAK;SACpB,sBAAuB,KACpB;QACL;OACF,CAAC;OACD,MAAM,eAAe,QAAQ,SAAS;OAEtC,IACE,QAAQ,YAAY,QACpB,OAAO,iBAAiB,YACxB,OAAO,QAAQ,qBAAqB,YAEpC,MAAM,QAAQ,iBACZ;QACE,kBAAkB,OAAO;QACzB,MAAM;SACJ,GAAI;SACJ,sBAAsB;QACxB;OACF,GACA,OACF;MAEJ,SAAS,OAAgB;OACvB,IAAI,OAAO,MAAM,+CAA+C,KAAK;MACvE;KACF,EACF;KACA,QAAQ,EACN,MAAM,MAAM,MAA6C;MACvD,MAAM,gBACJ,MAAM,8BAA8B,IAAI,OAAO,CAAC,CAAC,wBAC/C,QACA,KAAK,EACP,EAAA,EACC;MACH,IACE,OAAO,iBAAiB,YACxB,iBAAiB,MACjB,OAAO,KAAK,UAAU,YACtB,KAAK,UAAU,IAEf;MACF,IAAI;OACF,MAAM,sBAAsB,QAAQ,cAAc,CAAC,CAAC,eAClD,cACA,EAAE,OAAO,KAAK,MAAM,CACtB;MACF,SAAS,OAAgB;OACvB,IAAI,OAAO,MAAM,iDAAiD,KAAK;MACzE;KACF,EACF;IACF;IACA,cACE,QAAQ,cAAc,YAAY,QAAQ,8BACtC;KACE,QAAQ,EACN,MAAM,MACJ,KACA,SACA;MACA,IAAI;OACF,MAAM,oBACJ,OAAO,QAAQ,cAAc,4BAA4B,aACrD,MACE,QAAQ,aAAa,wBAIrB,KAAK,OAAQ,IACf,CAAC;OAEP,IAAI,cAAc,IAAI;OACtB,IAAI,gBAAgB,KAAA,KAAa,gBAAgB,MAAM;QACrD,MAAM,QAAQ,8BAA8B,IAAI,OAAO;QACvD,MAAM,cAAc,MAAM,MAAM,sBAAsB,IAAI,EAAE;QAC5D,IAAI,gBAAgB,QAAQ,gBAAgB,KAAA,GAE1C,eAAc,MADU,MAAM,SAAS,YAAY,MAAM,EAAA,EAChC;OAE7B;OAEA,IAAI,gBAAgB,KAAA,KAAa,gBAAgB,MAAM;OAEvD,MAAM,SAAS,MAAM,wBAAwB;QAC3C,SAAS,IAAI;QACb,QAAQ,QAAQ;QAChB,QAAQ,IAAI;QACZ,WAAW;SACT,IAAI,IAAI;SACR,MAAM;SACN,OAAO;SACP,MAAM,IAAI;SACV,sBACE,IACA;QACJ;QACA,cAAc,KAAK,CAAC,GAAG,iBAAiB;OAC1C,CAAC;OACD,MAAM,eAAe,QAAQ,SAAS;OAEtC,IACE,QAAQ,YAAY,QACpB,OAAO,iBAAiB,YACxB,OAAO,QAAQ,cAAc,qBAAqB,YAElD,MAAM,QAAQ,aAAa,iBACzB;QACE,kBAAkB,OAAO;QACzB,cAAc;SACZ,GAAG;SACH,sBAAsB;QACxB;OACF,GACA,OACF;MAEJ,SAAS,OAAgB;OACvB,IAAI,OAAO,MACT,uDACA,KACF;MACF;KACF,EACF;KACA,QAAQ,EACN,MAAM,MACJ,KAKA,SACA;MACA,MAAM,YAAY,MAAM,8BACtB,IAAI,OACN,CAAC,CAAC,iBAAiB,IAAI,EAAE;MACzB,MAAM,gBACJ,MAAM,8BAA8B,IAAI,OAAO,CAAC,CAAC,wBAC/C,gBACA,IAAI,EACN,EAAA,EACC;MACH,IAAI,OAAO,iBAAiB,YAAY,iBAAiB,IAAI;MAC7D,IAAI;OACF,MAAM,aACJ,OAAO,QAAQ,cAAc,4BAA4B,cACzD,UACI,MAAM,QAAQ,aAAa,wBACzB;QACE,IAAI,IAAI;QACR,MAAM,IAAI,QAAQ,WAAW,QAAQ;QACrC,OACE,IAAI,SACH,WACG;OACR,GACA,OACF,IACA,CAAC;OACP,MAAM,kBACJ,OAAO,WAAW,UAAU,YAAY,WAAW,UAAU,KACzD,WAAW,QACX,KAAA;OACN,MAAM,sBAAsB,QAAQ,cAAc,CAAC,CAAC,eAClD,cACA;QACE,GAAI,oBAAoB,KAAA,KACvB,OAAO,IAAI,UAAU,YAAY,IAAI,UAAU,KAC5C,EAAE,OAAO,mBAAmB,IAAI,SAAS,KAAA,EAAU,IACnD,CAAC;QACL,GAAI,OAAO,IAAI,SAAS,YAAY,IAAI,SAAS,KAC7C,EAAE,YAAY,IAAI,KAAK,IACvB,CAAC;OACP,CACF;MACF,SAAS,OAAgB;OACvB,IAAI,OAAO,MACT,wDACA,KACF;MACF;KACF,EACF;KACA,QAAQ,EACN,MAAM,OAAO,KAAqB;MAChC,MAAM,QAAQ,8BAA8B,IAAI,OAAO;MAEvD,KACE,MAF0B,MAAM,6BAA6B,IAAI,EAAE,EAAA,CAErD,MACX,iBACC,aAAa,WAAW,YACxB,aAAa,WAAW,UAC5B,GAEA,MAAM,IAAI,SAAS,eAAe,EAChC,SACE,qEACJ,CAAC;MAGH,MAAM,gBACJ,MAAM,MAAM,wBAAwB,gBAAgB,IAAI,EAAE,EAAA,EACzD;MACH,IAAI,OAAO,iBAAiB,YAAY,iBAAiB,IAAI;MAC7D,IAAI;OAMF,KACE,MANsB,sBACtB,QAAQ,cACV,CAAC,CAAC,cAAc,YAAY,EAAA,CAIjB,eAAe,MACrB,iBACC,aAAa,WAAW,YACxB,aAAa,WAAW,UAC5B,MAAM,MAEN,MAAM,IAAI,SAAS,eAAe,EAChC,SACE,qEACJ,CAAC;MAEL,SAAS,OAAgB;OACvB,IAAI,iBAAiB,UAAU,MAAM;OACrC,IAAI,OAAO,MACT,uEACA,KACF;OACA,MAAM,IAAI,SAAS,eAAe,EAChC,SACE,oEACJ,CAAC;MACH;KACF,EACF;IACF,IACA,KAAA;IACN,QAAQ,8BACJ;KACE,QAAQ;MACN,QAAQ,OACN,QACA,QACG;OACH,IACE,QAAQ,cAAc,YAAY,QAClC,OAAO,kBACP,QAAQ,QACR,QAAQ,KAAA,GAER,MAAM,eAAe,KAAK,OAAO,cAAc;MAEnD;MACA,OAAO,OACL,QACA,QACG;OACH,IACE,QAAQ,cAAc,YAAY,QAClC,OAAO,QAAQ,mBAAmB,YAClC,KAEA,MAAM,sBAAsB,KAAK,OAAO,gBAAgB,YAAY;MAExE;KACF;KACA,QAAQ,EACN,OAAO,OACL,QACA,QACG;MACH,IACE,QAAQ,cAAc,YAAY,QAClC,OAAO,QAAQ,mBAAmB,YAClC,KAEA,MAAM,sBAAsB,KAAK,OAAO,gBAAgB,YAAY;KAExE,EACF;IACF,IACA,KAAA;IACJ,YAAY,8BACR;KACE,QAAQ;MACN,QAAQ,OACN,YACA,QACG;OACH,IACE,QAAQ,cAAc,YAAY,QAClC,WAAW,kBACX,QAAQ,QACR,QAAQ,KAAA,GAER,MAAM,eAAe,KAAK,WAAW,cAAc;MAEvD;MACA,OAAO,OACL,YACA,QACG;OACH,IACE,QAAQ,cAAc,YAAY,QAClC,OAAO,YAAY,mBAAmB,YACtC,KAEA,MAAM,sBAAsB,KAAK,WAAW,gBAAgB,YAAY;MAE5E;KACF;KACA,QAAQ,EACN,OAAO,OACL,YACA,QACG;MACH,IACE,QAAQ,cAAc,YAAY,QAClC,OAAO,YAAY,mBAAmB,YACtC,KAEA,MAAM,sBAAsB,KAAK,WAAW,gBAAgB,YAAY;KAE5E,EACF;IACF,IACA,KAAA;IACJ,MAAM,8BACF,EACE,QAAQ,EACN,QAAQ,OACN,MACA,QACG;KACH,IAAI,QAAQ,cAAc,YAAY,QAAQ,KAAK,kBAAkB,KAAK;MAMxE,MAAM,YAAW,MALU,4BACzB,KACA,KAAK,gBACL,YACF,EAAA,CAC8B,OAAO;MACrC,IAAI,OAAO,aAAa,UACtB,MAAM,eAAe,KAAK,KAAK,gBAAgB,QAAQ;KAE3D;IACF,EACF,EACF,IACA,KAAA;GACN,EACF,EACF;EACF;EACA,cAAc;EACL;CACX;AACF;AAEA,MAAa,WAAwC"}