billsdk 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1277,7 +1277,8 @@ var webhookEndpoints = {
1277
1277
  }
1278
1278
  ctx.logger.debug("Payment confirmation received", {
1279
1279
  subscriptionId: result.subscriptionId,
1280
- status: result.status
1280
+ status: result.status,
1281
+ amount: result.amount
1281
1282
  });
1282
1283
  if (result.status === "active") {
1283
1284
  const subscription = await ctx.internalAdapter.findSubscriptionById(
@@ -1310,6 +1311,28 @@ var webhookEndpoints = {
1310
1311
  });
1311
1312
  }
1312
1313
  }
1314
+ if (result.amount && result.amount > 0) {
1315
+ await ctx.internalAdapter.createPayment({
1316
+ customerId: subscription.customerId,
1317
+ subscriptionId: subscription.id,
1318
+ type: "subscription",
1319
+ status: "succeeded",
1320
+ amount: result.amount,
1321
+ currency: result.currency ?? "usd",
1322
+ providerPaymentId: result.providerPaymentId,
1323
+ metadata: {
1324
+ planCode: subscription.planCode,
1325
+ interval: subscription.interval,
1326
+ confirmedVia: "webhook"
1327
+ }
1328
+ });
1329
+ ctx.logger.info("Payment record created", {
1330
+ subscriptionId: subscription.id,
1331
+ amount: result.amount,
1332
+ currency: result.currency,
1333
+ providerPaymentId: result.providerPaymentId
1334
+ });
1335
+ }
1313
1336
  ctx.logger.info("Subscription activated via webhook", {
1314
1337
  subscriptionId: subscription.id,
1315
1338
  providerSubscriptionId: result.providerSubscriptionId
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/routes/customer.ts","../src/api/routes/features.ts","../src/api/routes/health.ts","../src/api/routes/payment.ts","../src/api/routes/plan.ts","../src/logic/payment-failed-service.ts","../src/logic/refund-service.ts","../src/logic/proration.ts","../src/logic/subscription-service.ts","../src/logic/trial-end-service.ts","../src/logic/behaviors/defaults.ts","../src/logic/behaviors/runner.ts","../src/api/routes/refund.ts","../src/logic/renewal-service.ts","../src/api/routes/renewals.ts","../src/api/routes/subscription.ts","../src/api/routes/webhook.ts","../src/api/router.ts","../src/db/internal-adapter.ts","../src/context/create-context.ts","../src/billsdk/base.ts"],"names":["z","canceled","updatedSubscription","newPeriodEnd","endpoint"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from \"zod\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Create customer schema\n */\nconst createCustomerSchema = z.object({\n externalId: z.string().min(1),\n email: z.string().email(),\n name: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\n/**\n * Get customer query schema\n */\nconst getCustomerQuerySchema = z.object({\n externalId: z.string().min(1),\n});\n\n/**\n * Customer endpoints\n */\nexport const customerEndpoints: Record<string, BillingEndpoint> = {\n createCustomer: {\n path: \"/customer\",\n options: {\n method: \"POST\",\n body: createCustomerSchema,\n },\n handler: async (\n context: EndpointContext<z.infer<typeof createCustomerSchema>>,\n ) => {\n const { ctx, body } = context;\n\n // Check if customer already exists\n const existing = await ctx.internalAdapter.findCustomerByExternalId(\n body.externalId,\n );\n if (existing) {\n return { customer: existing };\n }\n\n // Create customer\n const customer = await ctx.internalAdapter.createCustomer(body);\n return { customer };\n },\n },\n\n getCustomer: {\n path: \"/customer\",\n options: {\n method: \"GET\",\n query: getCustomerQuerySchema,\n },\n handler: async (\n context: EndpointContext<unknown, z.infer<typeof getCustomerQuerySchema>>,\n ) => {\n const { ctx, query } = context;\n\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n query.externalId,\n );\n if (!customer) {\n return { customer: null };\n }\n\n return { customer };\n },\n },\n};\n","import { z } from \"zod\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Check feature access query schema\n */\nconst checkFeatureQuerySchema = z.object({\n customerId: z.string().min(1),\n feature: z.string().min(1),\n});\n\n/**\n * List features query schema\n */\nconst listFeaturesQuerySchema = z.object({\n customerId: z.string().min(1),\n});\n\n/**\n * Feature endpoints\n */\nexport const featureEndpoints: Record<string, BillingEndpoint> = {\n checkFeature: {\n path: \"/features/check\",\n options: {\n method: \"GET\",\n query: checkFeatureQuerySchema,\n },\n handler: async (\n context: EndpointContext<\n unknown,\n z.infer<typeof checkFeatureQuerySchema>\n >,\n ) => {\n const { ctx, query } = context;\n\n const result = await ctx.internalAdapter.checkFeatureAccess(\n query.customerId,\n query.feature,\n );\n return result;\n },\n },\n\n listFeatures: {\n path: \"/features\",\n options: {\n method: \"GET\",\n query: listFeaturesQuerySchema,\n },\n handler: async (\n context: EndpointContext<\n unknown,\n z.infer<typeof listFeaturesQuerySchema>\n >,\n ) => {\n const { ctx, query } = context;\n\n // Find customer\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n query.customerId,\n );\n if (!customer) {\n return { features: [] };\n }\n\n // Find active subscription\n const subscription =\n await ctx.internalAdapter.findSubscriptionByCustomerId(customer.id);\n if (!subscription) {\n return { features: [] };\n }\n\n // Get plan features from config (synchronous)\n const featureCodes = ctx.internalAdapter.getPlanFeatures(\n subscription.planCode,\n );\n const features = featureCodes.map((code: string) => {\n const feature = ctx.internalAdapter.findFeatureByCode(code);\n return {\n code,\n name: feature?.name ?? code,\n type: feature?.type ?? \"boolean\",\n enabled: true,\n };\n });\n\n return { features };\n },\n },\n};\n","import type { BillingEndpoint } from \"../../types/api\";\n\n/**\n * Health check endpoint\n */\nexport const healthEndpoint: Record<string, BillingEndpoint> = {\n health: {\n path: \"/health\",\n options: {\n method: \"GET\",\n },\n handler: async () => {\n return {\n status: \"ok\",\n timestamp: new Date().toISOString(),\n version: \"0.1.0\",\n };\n },\n },\n};\n","import { z } from \"zod\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * List payments query schema\n */\nconst listPaymentsQuerySchema = z.object({\n customerId: z.string().min(1),\n limit: z.coerce.number().positive().max(100).optional().default(25),\n offset: z.coerce.number().nonnegative().optional().default(0),\n});\n\n/**\n * Get payment query schema\n */\nconst getPaymentQuerySchema = z.object({\n paymentId: z.string().min(1),\n});\n\n/**\n * Payment endpoints\n */\nexport const paymentEndpoints: Record<string, BillingEndpoint> = {\n listPayments: {\n path: \"/payments\",\n options: {\n method: \"GET\",\n query: listPaymentsQuerySchema,\n },\n handler: async (\n context: EndpointContext<\n unknown,\n z.infer<typeof listPaymentsQuerySchema>\n >,\n ) => {\n const { ctx, query } = context;\n\n // Find customer by external ID\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n query.customerId,\n );\n if (!customer) {\n return { payments: [] };\n }\n\n // List payments for customer\n const payments = await ctx.internalAdapter.listPayments(customer.id, {\n limit: query.limit,\n offset: query.offset,\n });\n\n return { payments };\n },\n },\n\n getPayment: {\n path: \"/payment\",\n options: {\n method: \"GET\",\n query: getPaymentQuerySchema,\n },\n handler: async (\n context: EndpointContext<unknown, z.infer<typeof getPaymentQuerySchema>>,\n ) => {\n const { ctx, query } = context;\n\n const payment = await ctx.internalAdapter.findPaymentById(\n query.paymentId,\n );\n\n return { payment };\n },\n },\n};\n","import { z } from \"zod\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Plan endpoints - plans come from config, not DB\n */\nexport const planEndpoints: Record<string, BillingEndpoint> = {\n listPlans: {\n path: \"/plans\",\n options: {\n method: \"GET\",\n },\n handler: async (context: EndpointContext) => {\n const { ctx } = context;\n // Plans come from config, synchronous\n const plans = ctx.internalAdapter.listPlans({ includePrivate: false });\n return { plans };\n },\n },\n\n getPlan: {\n path: \"/plan\",\n options: {\n method: \"GET\",\n query: z.object({\n code: z.string(),\n }),\n },\n handler: async (context: EndpointContext<unknown, { code: string }>) => {\n const { ctx, query } = context;\n // Plans come from config, synchronous\n const plan = ctx.internalAdapter.findPlanByCode(query.code);\n\n if (!plan) {\n return { plan: null };\n }\n\n // Prices are included in the plan from config\n return { plan };\n },\n },\n};\n","import type { Subscription } from \"@billsdk/core\";\nimport type { BillingContext } from \"../context/create-context\";\n\nexport interface HandlePaymentFailedParams {\n /**\n * Subscription ID whose payment failed\n */\n subscriptionId: string;\n /**\n * Error message from the payment provider\n */\n error?: string;\n}\n\nexport interface HandlePaymentFailedResult {\n /**\n * The subscription that was marked as past_due\n */\n subscription: Subscription;\n}\n\n/**\n * Handle a failed payment for a subscription.\n *\n * This is the single source of truth for payment failure logic.\n * The default behavior marks the subscription as past_due to give\n * the customer a chance to update their payment method.\n */\nexport async function handlePaymentFailed(\n ctx: BillingContext,\n params: HandlePaymentFailedParams,\n): Promise<HandlePaymentFailedResult> {\n const { subscriptionId, error } = params;\n\n // Find the subscription\n const subscription =\n await ctx.internalAdapter.findSubscriptionById(subscriptionId);\n if (!subscription) {\n throw new Error(\"Subscription not found\");\n }\n\n ctx.logger.info(\"Payment failed, marking subscription as past_due\", {\n subscriptionId: subscription.id,\n error,\n });\n\n // Update subscription status to past_due\n const updatedSubscription = await ctx.internalAdapter.updateSubscription(\n subscription.id,\n { status: \"past_due\" },\n );\n\n return {\n subscription: updatedSubscription ?? {\n ...subscription,\n status: \"past_due\",\n },\n };\n}\n","import type { Payment } from \"@billsdk/core\";\nimport type { BillingContext } from \"../context/create-context\";\n\nexport interface CreateRefundParams {\n /**\n * Payment ID to refund (BillSDK payment ID)\n */\n paymentId: string;\n /**\n * Amount to refund in cents (partial refund)\n * If omitted, full refund is issued\n */\n amount?: number;\n /**\n * Reason for the refund\n */\n reason?: string;\n}\n\nexport interface CreateRefundResult {\n refund: Payment;\n originalPayment: Payment;\n}\n\n/**\n * Create a refund for a payment.\n *\n * This is the single source of truth for refund logic.\n * Both HTTP endpoints and direct API methods should use this function.\n */\nexport async function createRefund(\n ctx: BillingContext,\n params: CreateRefundParams,\n): Promise<CreateRefundResult> {\n const { paymentId, amount, reason } = params;\n\n // Check if payment adapter supports refunds\n if (!ctx.paymentAdapter?.refund) {\n throw new Error(\"Payment adapter does not support refunds\");\n }\n\n // Find the payment\n const payment = await ctx.internalAdapter.findPaymentById(paymentId);\n if (!payment) {\n throw new Error(\"Payment not found\");\n }\n\n // Check payment is refundable\n if (payment.status !== \"succeeded\") {\n throw new Error(`Cannot refund payment with status \"${payment.status}\"`);\n }\n\n // Check if already fully refunded\n const alreadyRefunded = payment.refundedAmount ?? 0;\n const remainingAmount = payment.amount - alreadyRefunded;\n\n if (remainingAmount <= 0) {\n throw new Error(\"Payment has already been fully refunded\");\n }\n\n // Determine refund amount\n const refundAmount = amount ?? remainingAmount;\n\n if (refundAmount > remainingAmount) {\n throw new Error(\n `Cannot refund ${refundAmount}. Only ${remainingAmount} is available for refund.`,\n );\n }\n\n // Check if payment has a provider payment ID\n if (!payment.providerPaymentId) {\n throw new Error(\n \"Payment does not have a provider payment ID. Cannot process refund.\",\n );\n }\n\n // Call the adapter to process the refund\n const result = await ctx.paymentAdapter.refund({\n providerPaymentId: payment.providerPaymentId,\n amount: refundAmount,\n reason,\n });\n\n if (result.status === \"failed\") {\n throw new Error(result.error ?? \"Refund failed\");\n }\n\n // Update the original payment with refunded amount\n const newRefundedAmount = alreadyRefunded + refundAmount;\n const newStatus =\n newRefundedAmount >= payment.amount ? \"refunded\" : \"succeeded\";\n\n await ctx.internalAdapter.updatePayment(payment.id, {\n status: newStatus,\n refundedAmount: newRefundedAmount,\n });\n\n // Record the refund as a negative payment\n const refundPayment = await ctx.internalAdapter.createPayment({\n customerId: payment.customerId,\n subscriptionId: payment.subscriptionId ?? undefined,\n type: \"refund\",\n status: \"succeeded\",\n amount: -refundAmount, // Negative to indicate refund\n currency: payment.currency,\n providerPaymentId: result.providerRefundId,\n metadata: {\n originalPaymentId: payment.id,\n reason,\n },\n });\n\n ctx.logger.info(\"Refund processed\", {\n originalPaymentId: payment.id,\n refundPaymentId: refundPayment.id,\n amount: refundAmount,\n });\n\n if (payment.subscriptionId) {\n const subscription = await ctx.internalAdapter.findSubscriptionById(\n payment.subscriptionId,\n );\n\n if (subscription && subscription.status !== \"canceled\") {\n ctx.logger.info(\"Refund includes subscription cancellation\", {\n subscriptionId: subscription.id,\n paymentId,\n });\n\n await ctx.internalAdapter.cancelSubscription(subscription.id);\n }\n }\n\n return {\n refund: refundPayment,\n originalPayment: {\n ...payment,\n status: newStatus,\n refundedAmount: newRefundedAmount,\n },\n };\n}\n","import type { BillingInterval } from \"../types/models\";\n\n/**\n * Result of a proration calculation (period reset model)\n *\n * When upgrading, the billing period resets to start from the change date.\n * The user gets credit for unused days on the old plan, which is deducted\n * from the full price of the new plan.\n */\nexport interface ProrationResult {\n /**\n * Credit for unused time on current plan (in cents)\n */\n credit: number;\n /**\n * Full price of the new plan (in cents)\n */\n charge: number;\n /**\n * Net amount to charge: newPlanAmount - credit\n */\n netAmount: number;\n /**\n * Days used on old plan (from period start to change date)\n */\n daysUsed: number;\n /**\n * Total days in the original billing period\n */\n totalDays: number;\n}\n\n/**\n * Parameters for proration calculation\n */\nexport interface ProrationParams {\n /**\n * Current plan amount in cents\n */\n oldPlanAmount: number;\n /**\n * New plan amount in cents\n */\n newPlanAmount: number;\n /**\n * Start of current billing period\n */\n currentPeriodStart: Date;\n /**\n * End of current billing period\n */\n currentPeriodEnd: Date;\n /**\n * Date when the plan change occurs (defaults to now)\n */\n changeDate?: Date;\n}\n\n/**\n * Calculate the number of days between two dates\n */\nfunction daysBetween(start: Date, end: Date): number {\n const msPerDay = 1000 * 60 * 60 * 24;\n return Math.ceil((end.getTime() - start.getTime()) / msPerDay);\n}\n\n/**\n * Calculate proration for a plan upgrade (period reset model)\n *\n * When upgrading:\n * 1. Calculate credit for unused days on old plan\n * 2. Charge full price of new plan minus the credit\n * 3. Reset billing period to start from change date\n *\n * @example\n * ```typescript\n * // User on Starter ($10/mo) upgrading to Pro ($20/mo)\n * // Subscribed Jan 1, upgrading Jan 7 (used 6 days, 25 remaining)\n * const result = calculateProration({\n * oldPlanAmount: 1000, // $10 in cents\n * newPlanAmount: 2000, // $20 in cents\n * currentPeriodStart: new Date('2024-01-01'),\n * currentPeriodEnd: new Date('2024-02-01'),\n * changeDate: new Date('2024-01-07'),\n * });\n *\n * // result.credit = 806 ($8.06 - unused Starter time: 25/31 × $10)\n * // result.charge = 2000 ($20 - full Pro price)\n * // result.netAmount = 1194 ($11.94 to charge)\n * // New period: Jan 7 - Feb 7\n * ```\n */\nexport function calculateProration(params: ProrationParams): ProrationResult {\n const {\n oldPlanAmount,\n newPlanAmount,\n currentPeriodStart,\n currentPeriodEnd,\n changeDate = new Date(),\n } = params;\n\n const totalDays = daysBetween(currentPeriodStart, currentPeriodEnd);\n const daysUsed = daysBetween(currentPeriodStart, changeDate);\n const daysRemaining = totalDays - daysUsed;\n\n const effectiveDaysRemaining = Math.max(\n 0,\n Math.min(daysRemaining, totalDays),\n );\n\n // Credit = unused portion of old plan\n const credit = Math.round(\n (oldPlanAmount / totalDays) * effectiveDaysRemaining,\n );\n\n // Charge = full price of new plan (period resets)\n const charge = newPlanAmount;\n\n // Net = new plan price minus credit\n const netAmount = Math.max(0, charge - credit);\n\n return {\n credit,\n charge,\n netAmount,\n daysUsed: Math.max(0, Math.min(daysUsed, totalDays)),\n totalDays,\n };\n}\n\n/**\n * Calculate the full amount for a new subscription period\n * (No proration - full amount for the interval)\n */\nexport function calculateFullPeriodAmount(\n amount: number,\n _interval: BillingInterval,\n): number {\n // For now, just return the amount as-is\n // In the future, this could handle quarterly calculations, etc.\n return amount;\n}\n","import type {\n BillingInterval,\n Payment,\n Plan,\n Subscription,\n} from \"@billsdk/core\";\nimport type { BillingContext } from \"../context/create-context\";\nimport { calculateProration } from \"./proration\";\n\nexport interface CreateSubscriptionParams {\n customerId: string;\n planCode: string;\n interval?: \"monthly\" | \"yearly\";\n successUrl?: string;\n cancelUrl?: string;\n}\n\nexport interface CreateSubscriptionResult {\n subscription: Subscription;\n redirectUrl?: string;\n}\n\nexport async function createSubscription(\n ctx: BillingContext,\n params: CreateSubscriptionParams,\n): Promise<CreateSubscriptionResult> {\n const {\n customerId,\n planCode,\n interval = \"monthly\",\n successUrl,\n cancelUrl,\n } = params;\n\n if (!ctx.paymentAdapter) {\n throw new Error(\"Payment adapter not configured\");\n }\n\n const customer =\n await ctx.internalAdapter.findCustomerByExternalId(customerId);\n if (!customer) {\n throw new Error(\"Customer not found\");\n }\n\n const plan = ctx.internalAdapter.findPlanByCode(planCode);\n if (!plan) {\n throw new Error(\"Plan not found\");\n }\n\n const price = ctx.internalAdapter.getPlanPrice(planCode, interval);\n if (!price) {\n throw new Error(\n `No price found for plan ${planCode} with interval ${interval}`,\n );\n }\n\n const subscription = await ctx.internalAdapter.createSubscription({\n customerId: customer.id,\n planCode,\n interval,\n status: \"pending_payment\",\n trialDays: price.trialDays,\n });\n\n const result = await ctx.paymentAdapter.processPayment({\n customer: {\n id: customer.id,\n email: customer.email,\n providerCustomerId: customer.providerCustomerId,\n },\n plan: {\n code: plan.code,\n name: plan.name,\n },\n price: {\n amount: price.amount,\n currency: price.currency,\n interval: price.interval,\n },\n subscription: {\n id: subscription.id,\n },\n successUrl,\n cancelUrl,\n metadata: {\n subscriptionId: subscription.id,\n customerId: customer.id,\n },\n });\n\n if (result.status === \"active\") {\n const existingSubscriptions = await ctx.internalAdapter.listSubscriptions(\n customer.id,\n );\n for (const existing of existingSubscriptions) {\n if (\n existing.id !== subscription.id &&\n (existing.status === \"active\" || existing.status === \"trialing\")\n ) {\n await ctx.internalAdapter.cancelSubscription(existing.id);\n }\n }\n\n const activeSubscription = await ctx.internalAdapter.updateSubscription(\n subscription.id,\n { status: \"active\" },\n );\n\n if (result.providerCustomerId && !customer.providerCustomerId) {\n await ctx.internalAdapter.updateCustomer(customer.id, {\n providerCustomerId: result.providerCustomerId,\n });\n }\n\n if (price.amount > 0) {\n await ctx.internalAdapter.createPayment({\n customerId: customer.id,\n subscriptionId: subscription.id,\n type: \"subscription\",\n status: \"succeeded\",\n amount: price.amount,\n currency: price.currency,\n metadata: {\n planCode: plan.code,\n interval,\n },\n });\n }\n\n return {\n subscription: activeSubscription ?? {\n ...subscription,\n status: \"active\" as const,\n },\n };\n }\n\n if (result.status === \"pending\") {\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n providerCheckoutSessionId: result.sessionId,\n });\n\n if (result.providerCustomerId && !customer.providerCustomerId) {\n await ctx.internalAdapter.updateCustomer(customer.id, {\n providerCustomerId: result.providerCustomerId,\n });\n }\n\n return {\n subscription,\n redirectUrl: result.redirectUrl,\n };\n }\n\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n status: \"canceled\",\n });\n throw new Error(result.error);\n}\n\nexport interface CancelSubscriptionParams {\n customerId: string;\n cancelAt?: \"period_end\" | \"immediately\";\n}\n\nexport interface CancelSubscriptionResult {\n subscription: Subscription | null;\n canceledImmediately: boolean;\n accessUntil?: Date;\n}\n\nexport async function cancelSubscription(\n ctx: BillingContext,\n params: CancelSubscriptionParams,\n): Promise<CancelSubscriptionResult> {\n const { customerId, cancelAt = \"period_end\" } = params;\n\n const customer =\n await ctx.internalAdapter.findCustomerByExternalId(customerId);\n if (!customer) {\n throw new Error(\"Customer not found\");\n }\n\n const subscription = await ctx.internalAdapter.findSubscriptionByCustomerId(\n customer.id,\n );\n if (!subscription) {\n throw new Error(\"No active subscription found\");\n }\n\n if (cancelAt === \"immediately\") {\n const canceled = await ctx.internalAdapter.cancelSubscription(\n subscription.id,\n );\n return { subscription: canceled, canceledImmediately: true };\n }\n\n const canceled = await ctx.internalAdapter.cancelSubscription(\n subscription.id,\n subscription.currentPeriodEnd,\n );\n return {\n subscription: canceled,\n canceledImmediately: false,\n accessUntil: subscription.currentPeriodEnd,\n };\n}\n\nexport interface ChangeSubscriptionParams {\n customerId: string;\n newPlanCode: string;\n newInterval?: BillingInterval;\n prorate?: boolean;\n}\n\nexport interface ChangeSubscriptionResult {\n subscription: Subscription | null;\n previousPlan: Plan | null;\n newPlan: Plan;\n payment: Payment | null;\n scheduled: boolean;\n effectiveAt?: Date;\n}\n\nconst intervalRank: Record<BillingInterval, number> = {\n monthly: 1,\n quarterly: 2,\n yearly: 3,\n};\n\nfunction isUpgrade(\n oldPrice: number,\n newPrice: number,\n oldInterval: BillingInterval,\n newInterval: BillingInterval,\n): boolean {\n if (oldInterval !== newInterval) {\n return intervalRank[newInterval] > intervalRank[oldInterval];\n }\n return newPrice > oldPrice;\n}\n\nexport async function changeSubscription(\n ctx: BillingContext,\n params: ChangeSubscriptionParams,\n): Promise<ChangeSubscriptionResult> {\n const { customerId, newPlanCode, newInterval, prorate = true } = params;\n\n const customer =\n await ctx.internalAdapter.findCustomerByExternalId(customerId);\n if (!customer) {\n throw new Error(\"Customer not found\");\n }\n\n const subscription = await ctx.internalAdapter.findSubscriptionByCustomerId(\n customer.id,\n );\n if (!subscription) {\n throw new Error(\"No active subscription found\");\n }\n\n const targetInterval = newInterval ?? subscription.interval;\n\n if (\n subscription.planCode === newPlanCode &&\n subscription.interval === targetInterval\n ) {\n throw new Error(\"Already on this plan\");\n }\n\n const oldPlan = ctx.internalAdapter.findPlanByCode(subscription.planCode);\n const oldPrice = ctx.internalAdapter.getPlanPrice(\n subscription.planCode,\n subscription.interval,\n );\n if (!oldPrice) {\n throw new Error(\"Current plan price not found\");\n }\n\n const newPlan = ctx.internalAdapter.findPlanByCode(newPlanCode);\n if (!newPlan) {\n throw new Error(\"New plan not found\");\n }\n\n const newPrice = ctx.internalAdapter.getPlanPrice(\n newPlanCode,\n targetInterval,\n );\n if (!newPrice) {\n throw new Error(\n `No price found for plan ${newPlanCode} with interval ${targetInterval}`,\n );\n }\n\n const upgrade = isUpgrade(\n oldPrice.amount,\n newPrice.amount,\n subscription.interval,\n targetInterval,\n );\n\n ctx.logger.info(\"Plan change detected\", {\n from: `${subscription.planCode} (${subscription.interval})`,\n to: `${newPlanCode} (${targetInterval})`,\n oldAmount: oldPrice.amount,\n newAmount: newPrice.amount,\n isUpgrade: upgrade,\n });\n\n // Downgrade: schedule for period end\n if (!upgrade) {\n ctx.logger.info(\"Downgrade scheduled for period end\", {\n scheduledPlanCode: newPlanCode,\n scheduledInterval: targetInterval,\n effectiveAt: subscription.currentPeriodEnd,\n });\n\n const updatedSubscription = await ctx.internalAdapter.updateSubscription(\n subscription.id,\n {\n scheduledPlanCode: newPlanCode,\n scheduledInterval: targetInterval,\n },\n );\n\n return {\n subscription: updatedSubscription,\n previousPlan: oldPlan,\n newPlan,\n payment: null,\n scheduled: true,\n effectiveAt: subscription.currentPeriodEnd,\n };\n }\n\n // Upgrade: immediate change with proration and period reset\n let payment: Payment | null = null;\n const changeDate = await ctx.timeProvider.now(params.customerId);\n\n ctx.logger.info(\"changeDate from timeProvider\", {\n changeDate: changeDate.toISOString(),\n realTime: new Date().toISOString(),\n });\n\n if (prorate) {\n const prorationResult = calculateProration({\n oldPlanAmount: oldPrice.amount,\n newPlanAmount: newPrice.amount,\n currentPeriodStart: subscription.currentPeriodStart,\n currentPeriodEnd: subscription.currentPeriodEnd,\n changeDate,\n });\n\n ctx.logger.info(\"Proration calculated\", {\n credit: prorationResult.credit,\n charge: prorationResult.charge,\n netAmount: prorationResult.netAmount,\n daysUsed: prorationResult.daysUsed,\n });\n\n if (prorationResult.netAmount > 0) {\n if (!ctx.paymentAdapter?.charge) {\n throw new Error(\n \"Payment adapter does not support direct charging. Cannot process upgrade.\",\n );\n }\n\n if (!customer.providerCustomerId) {\n throw new Error(\n \"Customer does not have a saved payment method. Cannot process upgrade.\",\n );\n }\n\n const chargeResult = await ctx.paymentAdapter.charge({\n customer: {\n id: customer.id,\n email: customer.email,\n providerCustomerId: customer.providerCustomerId,\n },\n amount: prorationResult.netAmount,\n currency: newPrice.currency,\n description: `Upgrade from ${oldPlan?.name ?? subscription.planCode} to ${newPlan.name}`,\n metadata: {\n subscriptionId: subscription.id,\n customerId: customer.id,\n type: \"upgrade\",\n oldPlanCode: subscription.planCode,\n newPlanCode,\n },\n });\n\n if (chargeResult.status === \"failed\") {\n throw new Error(chargeResult.error ?? \"Charge failed\");\n }\n\n payment = await ctx.internalAdapter.createPayment({\n customerId: customer.id,\n subscriptionId: subscription.id,\n type: \"upgrade\",\n status: \"succeeded\",\n amount: prorationResult.netAmount,\n currency: newPrice.currency,\n providerPaymentId: chargeResult.providerPaymentId,\n metadata: {\n oldPlanCode: subscription.planCode,\n newPlanCode,\n proration: {\n credit: prorationResult.credit,\n charge: prorationResult.charge,\n },\n },\n });\n }\n }\n\n // Calculate new period end based on interval\n const newPeriodStart = changeDate;\n const newPeriodEnd = new Date(changeDate);\n if (targetInterval === \"yearly\") {\n newPeriodEnd.setFullYear(newPeriodEnd.getFullYear() + 1);\n } else if (targetInterval === \"quarterly\") {\n newPeriodEnd.setMonth(newPeriodEnd.getMonth() + 3);\n } else {\n newPeriodEnd.setMonth(newPeriodEnd.getMonth() + 1);\n }\n\n const updatedSubscription = await ctx.internalAdapter.updateSubscription(\n subscription.id,\n {\n planCode: newPlanCode,\n interval: targetInterval,\n currentPeriodStart: newPeriodStart,\n currentPeriodEnd: newPeriodEnd,\n scheduledPlanCode: undefined,\n scheduledInterval: undefined,\n },\n );\n\n ctx.logger.info(\"Period reset\", {\n from: `${subscription.currentPeriodStart.toISOString()} - ${subscription.currentPeriodEnd.toISOString()}`,\n to: `${newPeriodStart.toISOString()} - ${newPeriodEnd.toISOString()}`,\n });\n\n return {\n subscription: updatedSubscription,\n previousPlan: oldPlan,\n newPlan,\n payment,\n scheduled: false,\n };\n}\n","import type { Subscription } from \"@billsdk/core\";\nimport type { BillingContext } from \"../context/create-context\";\n\nexport interface HandleTrialEndParams {\n /**\n * Subscription ID whose trial is ending\n */\n subscriptionId: string;\n}\n\nexport interface HandleTrialEndResult {\n /**\n * The subscription after trial processing\n */\n subscription: Subscription;\n /**\n * Whether the subscription was converted to paid (true) or canceled (false)\n */\n converted: boolean;\n}\n\n/**\n * Handle the end of a trial period for a subscription.\n *\n * This is the single source of truth for trial end logic.\n * The default behavior:\n * - If customer has a payment method: activates the subscription\n * - If no payment method: cancels the subscription\n */\nexport async function handleTrialEnd(\n ctx: BillingContext,\n params: HandleTrialEndParams,\n): Promise<HandleTrialEndResult> {\n const { subscriptionId } = params;\n\n // Find the subscription\n const subscription =\n await ctx.internalAdapter.findSubscriptionById(subscriptionId);\n if (!subscription) {\n throw new Error(\"Subscription not found\");\n }\n\n // Find the customer\n const customer = await ctx.internalAdapter.findCustomerById(\n subscription.customerId,\n );\n if (!customer) {\n throw new Error(\"Customer not found\");\n }\n\n // Get the plan\n const plan = ctx.internalAdapter.findPlanByCode(subscription.planCode);\n\n ctx.logger.info(\"Processing trial end\", {\n subscriptionId: subscription.id,\n customerId: customer.id,\n planCode: plan?.code,\n });\n\n // If customer has no payment method, cancel the subscription\n if (!customer.providerCustomerId) {\n ctx.logger.info(\"No payment method, canceling subscription\", {\n subscriptionId: subscription.id,\n });\n\n const canceledSubscription = await ctx.internalAdapter.cancelSubscription(\n subscription.id,\n );\n\n return {\n subscription: canceledSubscription ?? {\n ...subscription,\n status: \"canceled\",\n },\n converted: false,\n };\n }\n\n // Customer has payment method - activate the subscription\n ctx.logger.info(\"Payment method exists, activating subscription\", {\n subscriptionId: subscription.id,\n });\n\n const activeSubscription = await ctx.internalAdapter.updateSubscription(\n subscription.id,\n { status: \"active\" },\n );\n\n return {\n subscription: activeSubscription ?? { ...subscription, status: \"active\" },\n converted: true,\n };\n}\n","import type {\n OnPaymentFailedParams,\n OnPaymentFailedResult,\n OnRefundParams,\n OnRefundResult,\n OnSubscriptionCancelParams,\n OnSubscriptionCancelResult,\n OnTrialEndParams,\n OnTrialEndResult,\n} from \"@billsdk/core\";\nimport type { BillingContext } from \"../../context/create-context\";\nimport { handlePaymentFailed as handlePaymentFailedService } from \"../payment-failed-service\";\nimport { createRefund as createRefundService } from \"../refund-service\";\nimport { cancelSubscription as cancelSubscriptionService } from \"../subscription-service\";\nimport { handleTrialEnd as handleTrialEndService } from \"../trial-end-service\";\n\n/**\n * Default billing behaviors - these are the opinionated defaults that BillSDK\n * provides out of the box. Each can be overridden in the billsdk config.\n *\n * Philosophy: Defaults should be safe, predictable, and align with common\n * billing best practices.\n */\nexport const defaultBehaviors = {\n /**\n * Default onRefund behavior: Delegates to refund service.\n *\n * The service handles all business logic:\n * - Process the refund via payment adapter\n * - Cancel the associated subscription (BillSDK opinionated default)\n *\n * Override this behavior if you want different logic (e.g., refund without cancel).\n */\n onRefund: async (\n ctx: BillingContext,\n params: OnRefundParams,\n ): Promise<OnRefundResult> => {\n return createRefundService(ctx, {\n paymentId: params.paymentId,\n amount: params.amount,\n reason: params.reason,\n });\n },\n\n /**\n * Default onPaymentFailed behavior: Delegates to payment-failed service.\n *\n * The service handles all business logic:\n * - Find subscription\n * - Mark as past_due\n *\n * Override this behavior if you want different logic (e.g., immediate cancel).\n */\n onPaymentFailed: async (\n ctx: BillingContext,\n params: OnPaymentFailedParams,\n ): Promise<OnPaymentFailedResult> => {\n return handlePaymentFailedService(ctx, {\n subscriptionId: params.subscriptionId,\n error: params.error,\n });\n },\n\n /**\n * Default onSubscriptionCancel behavior: Delegates to cancel service.\n *\n * The service handles all business logic:\n * - Find customer and subscription\n * - Cancel immediately or at period end\n *\n * Override this behavior if you want different logic (e.g., downgrade to free).\n */\n onSubscriptionCancel: async (\n ctx: BillingContext,\n params: OnSubscriptionCancelParams,\n ): Promise<OnSubscriptionCancelResult> => {\n return cancelSubscriptionService(ctx, {\n customerId: params.customerId,\n cancelAt: params.cancelAt,\n });\n },\n\n /**\n * Default onTrialEnd behavior: Delegates to trial-end service.\n *\n * The service handles all business logic:\n * - If customer has payment method: activates subscription\n * - If no payment method: cancels subscription\n *\n * Override this behavior if you want different logic (e.g., extend trial).\n */\n onTrialEnd: async (\n ctx: BillingContext,\n params: OnTrialEndParams,\n ): Promise<OnTrialEndResult> => {\n return handleTrialEndService(ctx, {\n subscriptionId: params.subscriptionId,\n });\n },\n};\n\n/**\n * Type for the default behaviors object\n */\nexport type DefaultBehaviors = typeof defaultBehaviors;\n","import type {\n OnPaymentFailedParams,\n OnPaymentFailedResult,\n OnRefundParams,\n OnRefundResult,\n OnSubscriptionCancelParams,\n OnSubscriptionCancelResult,\n OnTrialEndParams,\n OnTrialEndResult,\n} from \"@billsdk/core\";\nimport type { BillingContext } from \"../../context/create-context\";\nimport { defaultBehaviors } from \"./defaults\";\n\n/**\n * Map of behavior names to their parameter and result types.\n * Used for type inference in runBehavior.\n */\ntype BehaviorConfig = {\n onRefund: { params: OnRefundParams; result: OnRefundResult };\n onPaymentFailed: {\n params: OnPaymentFailedParams;\n result: OnPaymentFailedResult;\n };\n onSubscriptionCancel: {\n params: OnSubscriptionCancelParams;\n result: OnSubscriptionCancelResult;\n };\n onTrialEnd: { params: OnTrialEndParams; result: OnTrialEndResult };\n};\n\n/**\n * Run a billing behavior with optional user override.\n *\n * This is the core of the configurable behaviors system:\n * 1. If the user provided an override, call it with the default as an argument\n * 2. If no override, run the default behavior\n *\n * The behavior controls the entire operation and returns the result.\n *\n * @param ctx - The billing context\n * @param behaviorName - Name of the behavior to run\n * @param params - Input parameters for the behavior\n * @returns The result of the behavior operation\n *\n * @example\n * ```typescript\n * // Entry point calls behavior with inputs:\n * const result = await runBehavior(ctx, \"onRefund\", {\n * paymentId: \"pay_123\",\n * amount: 1000,\n * });\n * ```\n */\nexport async function runBehavior<T extends keyof BehaviorConfig>(\n ctx: BillingContext,\n behaviorName: T,\n params: BehaviorConfig[T][\"params\"],\n): Promise<BehaviorConfig[T][\"result\"]> {\n const userBehavior = ctx.options.behaviors?.[behaviorName];\n const defaultFn = defaultBehaviors[behaviorName];\n\n // Create the default behavior function that the user can optionally call\n const defaultBehavior = async (): Promise<BehaviorConfig[T][\"result\"]> => {\n // biome-ignore lint/suspicious/noExplicitAny: Generic behavior dispatch - type safety is ensured by BehaviorConfig mapping\n return defaultFn(ctx, params as any);\n };\n\n if (userBehavior) {\n ctx.logger.debug(`Running user-defined behavior: ${behaviorName}`);\n // User provided an override - call it with the default available\n // biome-ignore lint/suspicious/noExplicitAny: Generic behavior dispatch - type safety is ensured by BehaviorConfig mapping\n return userBehavior(ctx as any, params as any, defaultBehavior as any);\n }\n\n ctx.logger.debug(`Running default behavior: ${behaviorName}`);\n // No override - run the default\n return defaultBehavior();\n}\n","import { z } from \"zod\";\nimport type { BillingContext } from \"../../context/create-context\";\nimport { runBehavior } from \"../../logic/behaviors/runner\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Create refund schema\n */\nconst createRefundSchema = z.object({\n /**\n * Payment ID to refund (BillSDK payment ID)\n */\n paymentId: z.string().min(1),\n /**\n * Amount to refund in cents (partial refund)\n * If omitted, full refund is issued\n */\n amount: z.number().positive().optional(),\n /**\n * Reason for the refund\n */\n reason: z.string().optional(),\n});\n\n/**\n * Refund endpoints\n */\nexport const refundEndpoints: Record<string, BillingEndpoint> = {\n createRefund: {\n path: \"/refund\",\n options: {\n method: \"POST\",\n body: createRefundSchema,\n },\n handler: async (\n context: EndpointContext<z.infer<typeof createRefundSchema>>,\n ) => {\n const { ctx, body } = context;\n\n // Delegate to behavior (default: refund + cancel subscription)\n return runBehavior(ctx as BillingContext, \"onRefund\", {\n paymentId: body.paymentId,\n amount: body.amount,\n reason: body.reason,\n });\n },\n },\n};\n","import type { Subscription, Where } from \"@billsdk/core\";\nimport type { BillingContext } from \"../context/create-context\";\nimport { TABLES } from \"../db/schema\";\n\n/**\n * Parameters for processing renewals\n */\nexport interface ProcessRenewalsParams {\n /**\n * Process only a specific customer (useful for testing)\n */\n customerId?: string;\n\n /**\n * Dry run - don't actually charge, just report what would happen\n */\n dryRun?: boolean;\n\n /**\n * Maximum number of subscriptions to process (for batching)\n */\n limit?: number;\n}\n\n/**\n * Individual renewal result\n */\nexport interface RenewalDetail {\n subscriptionId: string;\n customerId: string;\n status: \"succeeded\" | \"failed\" | \"skipped\";\n amount?: number;\n error?: string;\n /**\n * If a scheduled plan change was applied\n */\n planChanged?: {\n from: string;\n to: string;\n };\n}\n\n/**\n * Result of processing renewals\n */\nexport interface ProcessRenewalsResult {\n /**\n * Total subscriptions processed\n */\n processed: number;\n\n /**\n * Successful renewals\n */\n succeeded: number;\n\n /**\n * Failed renewals\n */\n failed: number;\n\n /**\n * Skipped (already renewed, etc.)\n */\n skipped: number;\n\n /**\n * Details for each renewal\n */\n renewals: RenewalDetail[];\n}\n\n/**\n * Calculate new period end based on interval\n */\nfunction calculateNewPeriodEnd(\n from: Date,\n interval: \"monthly\" | \"quarterly\" | \"yearly\",\n): Date {\n const newEnd = new Date(from);\n if (interval === \"yearly\") {\n newEnd.setFullYear(newEnd.getFullYear() + 1);\n } else if (interval === \"quarterly\") {\n newEnd.setMonth(newEnd.getMonth() + 3);\n } else {\n newEnd.setMonth(newEnd.getMonth() + 1);\n }\n return newEnd;\n}\n\n/**\n * Find subscriptions that are due for renewal\n */\nasync function findDueSubscriptions(\n ctx: BillingContext,\n params: ProcessRenewalsParams,\n): Promise<Subscription[]> {\n const now = params.customerId\n ? await ctx.timeProvider.now(params.customerId)\n : new Date();\n\n // Build where clause\n const where: Where[] = [\n // Only active or past_due subscriptions\n {\n field: \"status\",\n operator: \"in\",\n value: [\"active\", \"past_due\"],\n },\n // Period has ended\n {\n field: \"currentPeriodEnd\",\n operator: \"lte\",\n value: now,\n },\n ];\n\n // If specific customer, filter by customer\n if (params.customerId) {\n // Need to find the internal customer ID first\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n params.customerId,\n );\n if (!customer) {\n return [];\n }\n where.push({\n field: \"customerId\",\n operator: \"eq\",\n value: customer.id,\n });\n }\n\n return ctx.adapter.findMany<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where,\n limit: params.limit,\n sortBy: { field: \"currentPeriodEnd\", direction: \"asc\" },\n });\n}\n\n/**\n * Apply scheduled plan changes (downgrades)\n * Returns the new plan code if changed, null if no change\n */\nasync function applyScheduledChanges(\n ctx: BillingContext,\n subscription: Subscription,\n): Promise<{ planChanged: boolean; newPlanCode: string; newInterval: string }> {\n if (!subscription.scheduledPlanCode) {\n return {\n planChanged: false,\n newPlanCode: subscription.planCode,\n newInterval: subscription.interval,\n };\n }\n\n const newPlanCode = subscription.scheduledPlanCode;\n const newInterval = subscription.scheduledInterval ?? subscription.interval;\n\n ctx.logger.info(\"Applying scheduled plan change\", {\n subscriptionId: subscription.id,\n from: subscription.planCode,\n to: newPlanCode,\n newInterval,\n });\n\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n planCode: newPlanCode,\n interval: newInterval,\n scheduledPlanCode: undefined,\n scheduledInterval: undefined,\n });\n\n return {\n planChanged: true,\n newPlanCode,\n newInterval,\n };\n}\n\n/**\n * Process a single subscription renewal\n */\nasync function processSubscriptionRenewal(\n ctx: BillingContext,\n subscription: Subscription,\n dryRun: boolean,\n): Promise<RenewalDetail> {\n const customer = await ctx.internalAdapter.findCustomerById(\n subscription.customerId,\n );\n if (!customer) {\n return {\n subscriptionId: subscription.id,\n customerId: subscription.customerId,\n status: \"failed\",\n error: \"Customer not found\",\n };\n }\n\n // Apply any scheduled plan changes first\n const {\n planChanged,\n newPlanCode,\n newInterval: newIntervalStr,\n } = await applyScheduledChanges(ctx, subscription);\n const newInterval = newIntervalStr as \"monthly\" | \"quarterly\" | \"yearly\";\n\n // Get the price for the (possibly new) plan\n const price = ctx.internalAdapter.getPlanPrice(newPlanCode, newInterval);\n if (!price) {\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"failed\",\n error: `No price found for plan ${newPlanCode} with interval ${newInterval}`,\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n const amount = price.amount;\n const now = await ctx.timeProvider.now(customer.externalId);\n\n // If dry run, don't actually charge\n if (dryRun) {\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"succeeded\",\n amount,\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n // Free plan - just update the period\n if (amount === 0) {\n const newPeriodEnd = calculateNewPeriodEnd(now, newInterval);\n\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n currentPeriodStart: now,\n currentPeriodEnd: newPeriodEnd,\n status: \"active\",\n });\n\n ctx.logger.info(\"Free renewal processed\", {\n subscriptionId: subscription.id,\n newPeriodEnd: newPeriodEnd.toISOString(),\n });\n\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"succeeded\",\n amount: 0,\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n // Check if customer has a payment method\n if (!customer.providerCustomerId) {\n ctx.logger.warn(\"Customer has no payment method, marking as past_due\", {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n });\n\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n status: \"past_due\",\n });\n\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"failed\",\n error: \"No payment method on file\",\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n // Check if payment adapter supports charging\n if (!ctx.paymentAdapter?.charge) {\n ctx.logger.error(\"Payment adapter does not support direct charging\", {\n subscriptionId: subscription.id,\n });\n\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"failed\",\n error: \"Payment adapter does not support direct charging\",\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n // Charge the customer\n const plan = ctx.internalAdapter.findPlanByCode(newPlanCode);\n const chargeResult = await ctx.paymentAdapter.charge({\n customer: {\n id: customer.id,\n email: customer.email,\n providerCustomerId: customer.providerCustomerId,\n },\n amount,\n currency: price.currency,\n description: `Renewal: ${plan?.name ?? newPlanCode} (${newInterval})`,\n metadata: {\n subscriptionId: subscription.id,\n customerId: customer.id,\n type: \"renewal\",\n planCode: newPlanCode,\n },\n });\n\n if (chargeResult.status === \"failed\") {\n ctx.logger.warn(\"Renewal charge failed\", {\n subscriptionId: subscription.id,\n error: chargeResult.error,\n });\n\n // Mark as past_due for retry on next cron run\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n status: \"past_due\",\n });\n\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"failed\",\n error: chargeResult.error ?? \"Charge failed\",\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n // Charge succeeded - update subscription and create payment record\n const newPeriodEnd = calculateNewPeriodEnd(now, newInterval);\n\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n currentPeriodStart: now,\n currentPeriodEnd: newPeriodEnd,\n status: \"active\",\n });\n\n await ctx.internalAdapter.createPayment({\n customerId: customer.id,\n subscriptionId: subscription.id,\n type: \"renewal\",\n status: \"succeeded\",\n amount,\n currency: price.currency,\n providerPaymentId: chargeResult.providerPaymentId,\n metadata: {\n planCode: newPlanCode,\n interval: newInterval,\n },\n });\n\n ctx.logger.info(\"Renewal succeeded\", {\n subscriptionId: subscription.id,\n amount,\n newPeriodEnd: newPeriodEnd.toISOString(),\n });\n\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"succeeded\",\n amount,\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n}\n\n/**\n * Process all due renewals\n *\n * This function:\n * 1. Finds all subscriptions where currentPeriodEnd <= now\n * 2. Applies any scheduled plan changes (downgrades)\n * 3. Charges the customer for the new period\n * 4. Updates the subscription period dates\n * 5. Creates payment records\n *\n * Idempotent: Running twice won't double-charge because the period dates are updated.\n */\nexport async function processRenewals(\n ctx: BillingContext,\n params: ProcessRenewalsParams = {},\n): Promise<ProcessRenewalsResult> {\n const { dryRun = false } = params;\n\n ctx.logger.info(\"Starting renewal processing\", {\n dryRun,\n customerId: params.customerId,\n limit: params.limit,\n });\n\n // Find due subscriptions\n const dueSubscriptions = await findDueSubscriptions(ctx, params);\n\n ctx.logger.info(\n `Found ${dueSubscriptions.length} subscriptions due for renewal`,\n );\n\n const result: ProcessRenewalsResult = {\n processed: 0,\n succeeded: 0,\n failed: 0,\n skipped: 0,\n renewals: [],\n };\n\n // Process each subscription\n for (const subscription of dueSubscriptions) {\n result.processed++;\n\n try {\n const renewalResult = await processSubscriptionRenewal(\n ctx,\n subscription,\n dryRun,\n );\n\n result.renewals.push(renewalResult);\n\n if (renewalResult.status === \"succeeded\") {\n result.succeeded++;\n } else if (renewalResult.status === \"failed\") {\n result.failed++;\n } else {\n result.skipped++;\n }\n } catch (error) {\n ctx.logger.error(\"Error processing renewal\", {\n subscriptionId: subscription.id,\n error: error instanceof Error ? error.message : String(error),\n });\n\n result.failed++;\n result.renewals.push({\n subscriptionId: subscription.id,\n customerId: subscription.customerId,\n status: \"failed\",\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n }\n }\n\n ctx.logger.info(\"Renewal processing complete\", {\n processed: result.processed,\n succeeded: result.succeeded,\n failed: result.failed,\n skipped: result.skipped,\n });\n\n return result;\n}\n","import { z } from \"zod\";\nimport type { BillingContext } from \"../../context/create-context\";\nimport { processRenewals } from \"../../logic/renewal-service\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Query schema for renewals endpoint\n */\nconst processRenewalsQuerySchema = z.object({\n /**\n * Process only a specific customer (useful for testing)\n */\n customerId: z.string().optional(),\n\n /**\n * Dry run - don't actually charge, just report what would happen\n */\n dryRun: z\n .string()\n .transform((val) => val === \"true\")\n .optional(),\n\n /**\n * Maximum number of subscriptions to process (for batching)\n */\n limit: z\n .string()\n .transform((val) => Number.parseInt(val, 10))\n .refine((val) => !Number.isNaN(val) && val > 0, {\n message: \"limit must be a positive number\",\n })\n .optional(),\n});\n\n/**\n * Renewals endpoints\n *\n * GET /renewals - Process all due renewals\n *\n * This is designed to be called by a cron job (e.g., Vercel Cron).\n * The user just needs to add this to vercel.json:\n *\n * ```json\n * {\n * \"crons\": [{\n * \"path\": \"/api/billing/renewals\",\n * \"schedule\": \"0 * * * *\"\n * }]\n * }\n * ```\n */\nexport const renewalEndpoints: Record<string, BillingEndpoint> = {\n processRenewals: {\n path: \"/renewals\",\n options: {\n method: \"GET\",\n query: processRenewalsQuerySchema,\n },\n handler: async (\n context: EndpointContext<\n unknown,\n z.infer<typeof processRenewalsQuerySchema>\n >,\n ) => {\n const { ctx, query } = context;\n\n const result = await processRenewals(ctx as BillingContext, {\n customerId: query.customerId,\n dryRun: query.dryRun ?? false,\n limit: query.limit,\n });\n\n return result;\n },\n },\n};\n","import { z } from \"zod\";\nimport type { BillingContext } from \"../../context/create-context\";\nimport { runBehavior } from \"../../logic/behaviors/runner\";\nimport {\n changeSubscription as changeSubscriptionService,\n createSubscription as createSubscriptionService,\n} from \"../../logic/subscription-service\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Get subscription query schema\n */\nconst getSubscriptionQuerySchema = z.object({\n customerId: z.string().min(1),\n});\n\n/**\n * Create subscription schema\n * successUrl and cancelUrl are optional - only required if payment adapter needs them\n */\nconst createSubscriptionSchema = z.object({\n customerId: z.string().min(1),\n planCode: z.string().min(1),\n interval: z.enum([\"monthly\", \"yearly\"]).optional().default(\"monthly\"),\n successUrl: z.string().url().optional(),\n cancelUrl: z.string().url().optional(),\n});\n\n/**\n * Cancel subscription schema\n */\nconst cancelSubscriptionSchema = z.object({\n customerId: z.string().min(1),\n cancelAt: z\n .enum([\"period_end\", \"immediately\"])\n .optional()\n .default(\"period_end\"),\n});\n\n/**\n * Change subscription (upgrade/downgrade) schema\n */\nconst changeSubscriptionSchema = z.object({\n customerId: z.string().min(1),\n newPlanCode: z.string().min(1),\n /**\n * Whether to prorate the charge/credit\n * If false, the new plan starts at the next billing cycle\n */\n prorate: z.boolean().optional().default(true),\n});\n\n/**\n * Subscription endpoints\n */\nexport const subscriptionEndpoints: Record<string, BillingEndpoint> = {\n getSubscription: {\n path: \"/subscription\",\n options: {\n method: \"GET\",\n query: getSubscriptionQuerySchema,\n },\n handler: async (\n context: EndpointContext<\n unknown,\n z.infer<typeof getSubscriptionQuerySchema>\n >,\n ) => {\n const { ctx, query } = context;\n\n // Find customer by external ID\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n query.customerId,\n );\n if (!customer) {\n return { subscription: null };\n }\n\n // Find active subscription\n const subscription =\n await ctx.internalAdapter.findSubscriptionByCustomerId(customer.id);\n if (!subscription) {\n return { subscription: null };\n }\n\n // Get plan from config (synchronous)\n const plan = ctx.internalAdapter.findPlanByCode(subscription.planCode);\n const price = plan\n ? ctx.internalAdapter.getPlanPrice(\n subscription.planCode,\n subscription.interval,\n )\n : null;\n\n return {\n subscription,\n plan,\n price,\n };\n },\n },\n\n createSubscription: {\n path: \"/subscription\",\n options: {\n method: \"POST\",\n body: createSubscriptionSchema,\n },\n handler: async (\n context: EndpointContext<z.infer<typeof createSubscriptionSchema>>,\n ) => {\n const { ctx, body } = context;\n\n // Delegate to shared service\n return createSubscriptionService(ctx as BillingContext, {\n customerId: body.customerId,\n planCode: body.planCode,\n interval: body.interval,\n successUrl: body.successUrl,\n cancelUrl: body.cancelUrl,\n });\n },\n },\n\n cancelSubscription: {\n path: \"/subscription/cancel\",\n options: {\n method: \"POST\",\n body: cancelSubscriptionSchema,\n },\n handler: async (\n context: EndpointContext<z.infer<typeof cancelSubscriptionSchema>>,\n ) => {\n const { ctx, body } = context;\n\n // Delegate to behavior (default: cancel subscription)\n return runBehavior(ctx as BillingContext, \"onSubscriptionCancel\", {\n customerId: body.customerId,\n cancelAt: body.cancelAt,\n });\n },\n },\n\n changeSubscription: {\n path: \"/subscription/change\",\n options: {\n method: \"POST\",\n body: changeSubscriptionSchema,\n },\n handler: async (\n context: EndpointContext<z.infer<typeof changeSubscriptionSchema>>,\n ) => {\n const { ctx, body } = context;\n const billingCtx = ctx as BillingContext;\n return changeSubscriptionService(billingCtx, body);\n },\n },\n};\n","import type { BillingContext } from \"../../context/create-context\";\nimport type { BillingEndpoint } from \"../../types/api\";\n\n/**\n * Webhook endpoints\n */\nexport const webhookEndpoints: Record<string, BillingEndpoint> = {\n handleWebhook: {\n path: \"/webhook\",\n options: {\n method: \"POST\",\n },\n handler: async (context: { ctx: BillingContext; request: Request }) => {\n const { ctx, request } = context;\n\n if (!ctx.paymentAdapter) {\n throw new Error(\"Payment adapter not configured\");\n }\n\n // Check if payment adapter supports confirmPayment\n if (!ctx.paymentAdapter.confirmPayment) {\n // Adapter doesn't need webhooks (e.g., default adapter that activates immediately)\n ctx.logger.debug(\"Payment adapter does not support confirmPayment\");\n return { received: true };\n }\n\n // Confirm payment from webhook/callback\n const result = await ctx.paymentAdapter.confirmPayment(request);\n\n // If result is null, the event was acknowledged but not relevant to us\n if (!result) {\n ctx.logger.debug(\"Webhook event acknowledged but not processed\");\n return { received: true };\n }\n\n ctx.logger.debug(\"Payment confirmation received\", {\n subscriptionId: result.subscriptionId,\n status: result.status,\n });\n\n if (result.status === \"active\") {\n // Find the subscription\n const subscription = await ctx.internalAdapter.findSubscriptionById(\n result.subscriptionId,\n );\n\n if (subscription) {\n // Cancel any other active subscriptions for this customer\n const existingSubscriptions =\n await ctx.internalAdapter.listSubscriptions(\n subscription.customerId,\n );\n\n for (const existing of existingSubscriptions) {\n if (\n existing.id !== subscription.id &&\n (existing.status === \"active\" || existing.status === \"trialing\")\n ) {\n await ctx.internalAdapter.cancelSubscription(existing.id);\n ctx.logger.info(\"Canceled previous subscription\", {\n subscriptionId: existing.id,\n planCode: existing.planCode,\n });\n }\n }\n\n // Update subscription to active\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n status: \"active\",\n providerSubscriptionId: result.providerSubscriptionId,\n });\n\n // Update customer provider ID if present\n if (result.providerCustomerId) {\n const customer = await ctx.internalAdapter.findCustomerById(\n subscription.customerId,\n );\n if (customer && !customer.providerCustomerId) {\n await ctx.internalAdapter.updateCustomer(customer.id, {\n providerCustomerId: result.providerCustomerId,\n });\n }\n }\n\n ctx.logger.info(\"Subscription activated via webhook\", {\n subscriptionId: subscription.id,\n providerSubscriptionId: result.providerSubscriptionId,\n });\n } else {\n ctx.logger.warn(\"Subscription not found for confirmation\", {\n subscriptionId: result.subscriptionId,\n });\n }\n } else if (result.status === \"failed\") {\n // Mark subscription as failed/canceled\n const subscription = await ctx.internalAdapter.findSubscriptionById(\n result.subscriptionId,\n );\n\n if (subscription) {\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n status: \"canceled\",\n });\n ctx.logger.warn(\"Payment failed, subscription canceled\", {\n subscriptionId: subscription.id,\n });\n }\n }\n\n return { received: true };\n },\n },\n};\n","import type { BillingContext } from \"../context/create-context\";\nimport type { BillingEndpoint } from \"../types/api\";\nimport { customerEndpoints } from \"./routes/customer\";\nimport { featureEndpoints } from \"./routes/features\";\nimport { healthEndpoint } from \"./routes/health\";\nimport { paymentEndpoints } from \"./routes/payment\";\nimport { planEndpoints } from \"./routes/plan\";\nimport { refundEndpoints } from \"./routes/refund\";\nimport { renewalEndpoints } from \"./routes/renewals\";\nimport { subscriptionEndpoints } from \"./routes/subscription\";\nimport { webhookEndpoints } from \"./routes/webhook\";\n\n/**\n * Collect all endpoints\n */\nexport function getEndpoints(\n ctx: BillingContext,\n): Record<string, BillingEndpoint> {\n const baseEndpoints: Record<string, BillingEndpoint> = {\n ...healthEndpoint,\n ...customerEndpoints,\n ...planEndpoints,\n ...subscriptionEndpoints,\n ...featureEndpoints,\n ...paymentEndpoints,\n ...refundEndpoints,\n ...renewalEndpoints,\n ...webhookEndpoints,\n };\n\n // Add plugin endpoints\n let allEndpoints = { ...baseEndpoints };\n for (const plugin of ctx.plugins) {\n if (plugin.endpoints) {\n allEndpoints = { ...allEndpoints, ...plugin.endpoints };\n }\n }\n\n return allEndpoints;\n}\n\n/**\n * Parse URL to get path and query params\n */\nfunction parseUrl(\n url: string,\n basePath: string,\n): { path: string; query: URLSearchParams } {\n const urlObj = new URL(url);\n let path = urlObj.pathname;\n\n // Remove base path\n if (path.startsWith(basePath)) {\n path = path.slice(basePath.length);\n }\n\n // Ensure path starts with /\n if (!path.startsWith(\"/\")) {\n path = `/${path}`;\n }\n\n return { path, query: urlObj.searchParams };\n}\n\n/**\n * Parse query params to object\n */\nfunction queryToObject(query: URLSearchParams): Record<string, string> {\n const obj: Record<string, string> = {};\n query.forEach((value, key) => {\n obj[key] = value;\n });\n return obj;\n}\n\n/**\n * Create a JSON response\n */\nfunction jsonResponse(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n}\n\n/**\n * Create an error response\n */\nfunction errorResponse(code: string, message: string, status = 400): Response {\n return jsonResponse({ error: { code, message } }, status);\n}\n\n/**\n * Create the router\n */\nexport function createRouter(ctx: BillingContext): {\n handler: (request: Request) => Promise<Response>;\n endpoints: Record<string, BillingEndpoint>;\n} {\n const endpoints = getEndpoints(ctx);\n\n const handler = async (request: Request): Promise<Response> => {\n const method = request.method.toUpperCase();\n const { path, query } = parseUrl(request.url, ctx.basePath);\n\n ctx.logger.debug(`${method} ${path}`);\n\n // Run before hooks\n if (ctx.options.hooks.before) {\n const result = await ctx.options.hooks.before({\n request,\n path,\n method,\n });\n if (result instanceof Response) {\n return result;\n }\n }\n\n // Run plugin before hooks\n for (const plugin of ctx.plugins) {\n if (plugin.hooks?.before) {\n for (const hook of plugin.hooks.before) {\n if (hook.matcher({ path, method })) {\n const result = await hook.handler({\n request,\n path,\n method,\n billingContext: ctx,\n });\n if (result instanceof Response) {\n return result;\n }\n }\n }\n }\n }\n\n // Find matching endpoint\n const endpointKey = Object.keys(endpoints).find((key) => {\n const endpoint = endpoints[key];\n if (!endpoint) return false;\n\n // Check method\n if (endpoint.options.method !== method) return false;\n\n // Check path (simple matching for now)\n // TODO: Add path params support\n return endpoint.path === path;\n });\n\n if (!endpointKey) {\n return errorResponse(\n \"NOT_FOUND\",\n `No endpoint found for ${method} ${path}`,\n 404,\n );\n }\n\n const endpoint = endpoints[endpointKey]!;\n\n try {\n const requestForHandler = request.clone();\n\n // Parse body for POST/PUT/PATCH\n let body: unknown;\n if ([\"POST\", \"PUT\", \"PATCH\"].includes(method) && endpoint.options.body) {\n try {\n const text = await request.text();\n if (text) {\n body = JSON.parse(text);\n }\n } catch {\n // Body might be empty or not JSON\n }\n }\n\n // Validate body if schema provided\n if (endpoint.options.body && body) {\n const result = endpoint.options.body.safeParse(body);\n if (!result.success) {\n const issues = \"issues\" in result.error ? result.error.issues : [];\n return errorResponse(\n \"VALIDATION_ERROR\",\n (issues as Array<{ message: string }>)\n .map((e) => e.message)\n .join(\", \"),\n 400,\n );\n }\n body = result.data;\n }\n\n // Validate query if schema provided\n let queryObj: Record<string, string> = queryToObject(query);\n if (endpoint.options.query) {\n const result = endpoint.options.query.safeParse(queryObj);\n if (!result.success) {\n const issues = \"issues\" in result.error ? result.error.issues : [];\n return errorResponse(\n \"VALIDATION_ERROR\",\n (issues as Array<{ message: string }>)\n .map((e) => e.message)\n .join(\", \"),\n 400,\n );\n }\n queryObj = result.data as Record<string, string>;\n }\n\n // Create endpoint context\n // Use cloned request so handlers can read the body if needed (e.g., webhooks)\n const endpointContext = {\n request: requestForHandler,\n body,\n query: queryObj,\n headers: requestForHandler.headers,\n params: {},\n ctx, // Add billing context\n };\n\n // Execute handler\n // biome-ignore lint/suspicious/noExplicitAny: Each endpoint defines its own body/query types - router dispatches generically\n const response = await endpoint.handler(endpointContext as any);\n\n // Run after hooks\n let finalResponse = jsonResponse(response);\n\n // Run plugin after hooks\n for (const plugin of ctx.plugins) {\n if (plugin.hooks?.after) {\n for (const hook of plugin.hooks.after) {\n if (hook.matcher({ path, method })) {\n const result = await hook.handler({\n request,\n path,\n method,\n billingContext: ctx,\n });\n if (result instanceof Response) {\n finalResponse = result;\n }\n }\n }\n }\n }\n\n if (ctx.options.hooks.after) {\n const result = await ctx.options.hooks.after({\n request,\n path,\n method,\n });\n if (result instanceof Response) {\n finalResponse = result;\n }\n }\n\n return finalResponse;\n } catch (error) {\n ctx.logger.error(\"Endpoint error\", error);\n\n if (error instanceof Error) {\n return errorResponse(\"INTERNAL_ERROR\", error.message, 500);\n }\n\n return errorResponse(\n \"INTERNAL_ERROR\",\n \"An unexpected error occurred\",\n 500,\n );\n }\n };\n\n return { handler, endpoints };\n}\n","import type { DBAdapter } from \"../types/adapter\";\nimport type {\n BillingInterval,\n CreateCustomerInput,\n CreatePaymentInput,\n CreateSubscriptionInput,\n Customer,\n Feature,\n Payment,\n Plan,\n PlanPrice,\n Subscription,\n} from \"../types/models\";\nimport type { FeatureConfig, PlanConfig } from \"../types/options\";\nimport { TABLES } from \"./schema\";\n\n/**\n * Internal adapter that wraps DBAdapter with business logic\n * Plans and features come from config, only customer/subscription from DB\n */\nexport interface InternalAdapter {\n // Customer operations (DB)\n createCustomer(data: CreateCustomerInput): Promise<Customer>;\n findCustomerById(id: string): Promise<Customer | null>;\n findCustomerByExternalId(externalId: string): Promise<Customer | null>;\n updateCustomer(id: string, data: Partial<Customer>): Promise<Customer | null>;\n deleteCustomer(id: string): Promise<void>;\n listCustomers(options?: {\n limit?: number;\n offset?: number;\n }): Promise<Customer[]>;\n\n // Plan operations (from config)\n findPlanByCode(code: string): Plan | null;\n listPlans(options?: { includePrivate?: boolean }): Plan[];\n getPlanPrice(planCode: string, interval: BillingInterval): PlanPrice | null;\n\n // Feature operations (from config)\n findFeatureByCode(code: string): Feature | null;\n listFeatures(): Feature[];\n getPlanFeatures(planCode: string): string[];\n\n // Subscription operations (DB)\n createSubscription(data: CreateSubscriptionInput): Promise<Subscription>;\n findSubscriptionById(id: string): Promise<Subscription | null>;\n findSubscriptionByCustomerId(\n customerId: string,\n ): Promise<Subscription | null>;\n findSubscriptionByProviderSessionId(\n sessionId: string,\n ): Promise<Subscription | null>;\n updateSubscription(\n id: string,\n data: Partial<Subscription>,\n ): Promise<Subscription | null>;\n cancelSubscription(id: string, cancelAt?: Date): Promise<Subscription | null>;\n listSubscriptions(customerId: string): Promise<Subscription[]>;\n\n // Feature access check\n checkFeatureAccess(\n customerId: string,\n featureCode: string,\n ): Promise<{ allowed: boolean }>;\n\n // Payment operations (DB)\n createPayment(data: CreatePaymentInput): Promise<Payment>;\n findPaymentById(id: string): Promise<Payment | null>;\n findPaymentByProviderPaymentId(\n providerPaymentId: string,\n ): Promise<Payment | null>;\n updatePayment(id: string, data: Partial<Payment>): Promise<Payment | null>;\n listPayments(\n customerId: string,\n options?: { limit?: number; offset?: number },\n ): Promise<Payment[]>;\n}\n\n/**\n * Convert PlanConfig to Plan\n */\nfunction planConfigToPlan(config: PlanConfig): Plan {\n return {\n code: config.code,\n name: config.name,\n description: config.description,\n isPublic: config.isPublic ?? true,\n prices: config.prices.map((p) => ({\n amount: p.amount,\n currency: p.currency ?? \"usd\",\n interval: p.interval,\n trialDays: p.trialDays,\n })),\n features: config.features ?? [],\n };\n}\n\n/**\n * Convert FeatureConfig to Feature\n */\nfunction featureConfigToFeature(config: FeatureConfig): Feature {\n return {\n code: config.code,\n name: config.name,\n type: config.type ?? \"boolean\",\n };\n}\n\n/**\n * Create an internal adapter from a DBAdapter and config\n */\nexport function createInternalAdapter(\n adapter: DBAdapter,\n plans: PlanConfig[] = [],\n features: FeatureConfig[] = [],\n getNow: () => Promise<Date> = async () => new Date(),\n): InternalAdapter {\n // Build lookup maps for fast access\n const plansByCode = new Map<string, Plan>();\n for (const config of plans) {\n plansByCode.set(config.code, planConfigToPlan(config));\n }\n\n const featuresByCode = new Map<string, Feature>();\n for (const config of features) {\n featuresByCode.set(config.code, featureConfigToFeature(config));\n }\n\n return {\n // Customer operations (DB)\n async createCustomer(data: CreateCustomerInput): Promise<Customer> {\n const now = await getNow();\n return adapter.create<Customer>({\n model: TABLES.CUSTOMER,\n data: {\n ...data,\n createdAt: now,\n updatedAt: now,\n } as Omit<Customer, \"id\">,\n });\n },\n\n async findCustomerById(id: string): Promise<Customer | null> {\n return adapter.findOne<Customer>({\n model: TABLES.CUSTOMER,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n });\n },\n\n async findCustomerByExternalId(\n externalId: string,\n ): Promise<Customer | null> {\n return adapter.findOne<Customer>({\n model: TABLES.CUSTOMER,\n where: [{ field: \"externalId\", operator: \"eq\", value: externalId }],\n });\n },\n\n async updateCustomer(\n id: string,\n data: Partial<Customer>,\n ): Promise<Customer | null> {\n return adapter.update<Customer>({\n model: TABLES.CUSTOMER,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n update: { ...data, updatedAt: new Date() },\n });\n },\n\n async deleteCustomer(id: string): Promise<void> {\n await adapter.delete({\n model: TABLES.CUSTOMER,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n });\n },\n\n async listCustomers(options?: {\n limit?: number;\n offset?: number;\n }): Promise<Customer[]> {\n return adapter.findMany<Customer>({\n model: TABLES.CUSTOMER,\n limit: options?.limit,\n offset: options?.offset,\n sortBy: { field: \"createdAt\", direction: \"desc\" },\n });\n },\n\n // Plan operations (from config - synchronous)\n findPlanByCode(code: string): Plan | null {\n return plansByCode.get(code) ?? null;\n },\n\n listPlans(options?: { includePrivate?: boolean }): Plan[] {\n const allPlans = Array.from(plansByCode.values());\n if (options?.includePrivate) {\n return allPlans;\n }\n return allPlans.filter((p) => p.isPublic);\n },\n\n getPlanPrice(\n planCode: string,\n interval: BillingInterval,\n ): PlanPrice | null {\n const plan = plansByCode.get(planCode);\n if (!plan) return null;\n return (\n plan.prices.find((p) => p.interval === interval) ??\n plan.prices[0] ??\n null\n );\n },\n\n // Feature operations (from config - synchronous)\n findFeatureByCode(code: string): Feature | null {\n return featuresByCode.get(code) ?? null;\n },\n\n listFeatures(): Feature[] {\n return Array.from(featuresByCode.values());\n },\n\n getPlanFeatures(planCode: string): string[] {\n const plan = plansByCode.get(planCode);\n return plan?.features ?? [];\n },\n\n // Subscription operations (DB)\n async createSubscription(\n data: CreateSubscriptionInput,\n ): Promise<Subscription> {\n const now = await getNow();\n const interval = data.interval ?? \"monthly\";\n const currentPeriodEnd = new Date(now);\n\n // Set period end based on interval\n if (interval === \"yearly\") {\n currentPeriodEnd.setFullYear(currentPeriodEnd.getFullYear() + 1);\n } else if (interval === \"quarterly\") {\n currentPeriodEnd.setMonth(currentPeriodEnd.getMonth() + 3);\n } else {\n currentPeriodEnd.setMonth(currentPeriodEnd.getMonth() + 1);\n }\n\n let trialStart: Date | undefined;\n let trialEnd: Date | undefined;\n let status = data.status ?? \"pending_payment\";\n\n if (data.trialDays && data.trialDays > 0) {\n trialStart = now;\n trialEnd = new Date(now);\n trialEnd.setDate(trialEnd.getDate() + data.trialDays);\n status = \"trialing\";\n }\n\n return adapter.create<Subscription>({\n model: TABLES.SUBSCRIPTION,\n data: {\n customerId: data.customerId,\n planCode: data.planCode,\n interval,\n status,\n providerSubscriptionId: data.providerSubscriptionId,\n providerCheckoutSessionId: data.providerCheckoutSessionId,\n currentPeriodStart: now,\n currentPeriodEnd: trialEnd ?? currentPeriodEnd,\n trialStart,\n trialEnd,\n metadata: data.metadata,\n createdAt: now,\n updatedAt: now,\n } as Omit<Subscription, \"id\">,\n });\n },\n\n async findSubscriptionById(id: string): Promise<Subscription | null> {\n return adapter.findOne<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n });\n },\n\n async findSubscriptionByCustomerId(\n customerId: string,\n ): Promise<Subscription | null> {\n return adapter.findOne<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [\n { field: \"customerId\", operator: \"eq\", value: customerId },\n {\n field: \"status\",\n operator: \"in\",\n value: [\"active\", \"trialing\", \"past_due\", \"pending_payment\"],\n },\n ],\n });\n },\n\n async findSubscriptionByProviderSessionId(\n sessionId: string,\n ): Promise<Subscription | null> {\n return adapter.findOne<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [\n {\n field: \"providerCheckoutSessionId\",\n operator: \"eq\",\n value: sessionId,\n },\n ],\n });\n },\n\n async updateSubscription(\n id: string,\n data: Partial<Subscription>,\n ): Promise<Subscription | null> {\n const now = await getNow();\n return adapter.update<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n update: { ...data, updatedAt: now },\n });\n },\n\n async cancelSubscription(\n id: string,\n cancelAt?: Date,\n ): Promise<Subscription | null> {\n const now = await getNow();\n return adapter.update<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n update: {\n status: cancelAt ? \"active\" : \"canceled\",\n canceledAt: now,\n cancelAt: cancelAt ?? now,\n updatedAt: now,\n },\n });\n },\n\n async listSubscriptions(customerId: string): Promise<Subscription[]> {\n return adapter.findMany<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [{ field: \"customerId\", operator: \"eq\", value: customerId }],\n sortBy: { field: \"createdAt\", direction: \"desc\" },\n });\n },\n\n // Feature access check\n async checkFeatureAccess(\n customerId: string,\n featureCode: string,\n ): Promise<{ allowed: boolean }> {\n // Find customer by external ID\n const customer = await adapter.findOne<Customer>({\n model: TABLES.CUSTOMER,\n where: [{ field: \"externalId\", operator: \"eq\", value: customerId }],\n });\n\n if (!customer) {\n return { allowed: false };\n }\n\n // Find active subscription\n const subscription = await adapter.findOne<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [\n { field: \"customerId\", operator: \"eq\", value: customer.id },\n { field: \"status\", operator: \"in\", value: [\"active\", \"trialing\"] },\n ],\n });\n\n if (!subscription) {\n return { allowed: false };\n }\n\n // Check if plan has the feature (from config)\n const planFeatures = this.getPlanFeatures(subscription.planCode);\n return { allowed: planFeatures.includes(featureCode) };\n },\n\n // Payment operations (DB)\n async createPayment(data: CreatePaymentInput): Promise<Payment> {\n const now = await getNow();\n return adapter.create<Payment>({\n model: TABLES.PAYMENT,\n data: {\n customerId: data.customerId,\n subscriptionId: data.subscriptionId,\n type: data.type,\n status: data.status ?? \"pending\",\n amount: data.amount,\n currency: data.currency ?? \"usd\",\n providerPaymentId: data.providerPaymentId,\n metadata: data.metadata,\n createdAt: now,\n updatedAt: now,\n } as Omit<Payment, \"id\">,\n });\n },\n\n async findPaymentById(id: string): Promise<Payment | null> {\n return adapter.findOne<Payment>({\n model: TABLES.PAYMENT,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n });\n },\n\n async findPaymentByProviderPaymentId(\n providerPaymentId: string,\n ): Promise<Payment | null> {\n return adapter.findOne<Payment>({\n model: TABLES.PAYMENT,\n where: [\n {\n field: \"providerPaymentId\",\n operator: \"eq\",\n value: providerPaymentId,\n },\n ],\n });\n },\n\n async updatePayment(\n id: string,\n data: Partial<Payment>,\n ): Promise<Payment | null> {\n return adapter.update<Payment>({\n model: TABLES.PAYMENT,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n update: { ...data, updatedAt: new Date() },\n });\n },\n\n async listPayments(\n customerId: string,\n options?: { limit?: number; offset?: number },\n ): Promise<Payment[]> {\n return adapter.findMany<Payment>({\n model: TABLES.PAYMENT,\n where: [{ field: \"customerId\", operator: \"eq\", value: customerId }],\n limit: options?.limit,\n offset: options?.offset,\n sortBy: { field: \"createdAt\", direction: \"desc\" },\n });\n },\n };\n}\n","import { createDefaultTimeProvider, type TimeProvider } from \"@billsdk/core\";\nimport {\n createInternalAdapter,\n type InternalAdapter,\n} from \"../db/internal-adapter\";\nimport { type DBSchema, getBillingSchema } from \"../db/schema\";\nimport type { DBAdapter } from \"../types/adapter\";\nimport type { BillSDKOptions, ResolvedBillSDKOptions } from \"../types/options\";\nimport type { PaymentAdapter } from \"../types/payment\";\nimport type { BillSDKPlugin } from \"../types/plugins\";\n\n/**\n * Logger interface for the billing context\n */\nexport interface Logger {\n debug: (message: string, ...args: unknown[]) => void;\n info: (message: string, ...args: unknown[]) => void;\n warn: (message: string, ...args: unknown[]) => void;\n error: (message: string, ...args: unknown[]) => void;\n}\n\n/**\n * The billing context containing all runtime state\n */\nexport interface BillingContext {\n /**\n * Resolved options with defaults\n */\n options: ResolvedBillSDKOptions;\n\n /**\n * Base path for the API\n */\n basePath: string;\n\n /**\n * Database adapter\n */\n adapter: DBAdapter;\n\n /**\n * Payment adapter (optional)\n */\n paymentAdapter?: PaymentAdapter;\n\n /**\n * Internal adapter with business logic\n */\n internalAdapter: InternalAdapter;\n\n /**\n * Database schema\n */\n schema: DBSchema;\n\n /**\n * Registered plugins\n */\n plugins: BillSDKPlugin[];\n\n /**\n * Logger instance\n */\n logger: Logger;\n\n /**\n * Secret for signing\n */\n secret: string;\n\n /**\n * Time provider for getting current time\n * Can be overridden by plugins (e.g., time-travel) for testing\n */\n timeProvider: TimeProvider;\n\n /**\n * Check if a plugin is registered\n */\n hasPlugin: (id: string) => boolean;\n\n /**\n * Get a plugin by ID\n */\n getPlugin: <T extends BillSDKPlugin>(id: string) => T | null;\n\n /**\n * Generate a unique ID\n */\n generateId: () => string;\n}\n\n/**\n * Create a logger instance\n */\nfunction createLogger(options: BillSDKOptions[\"logger\"]): Logger {\n const level = options?.level ?? \"info\";\n const disabled = options?.disabled ?? false;\n\n const levels = [\"debug\", \"info\", \"warn\", \"error\"];\n const currentLevelIndex = levels.indexOf(level);\n\n const shouldLog = (logLevel: string) => {\n if (disabled) return false;\n return levels.indexOf(logLevel) >= currentLevelIndex;\n };\n\n return {\n debug: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"debug\")) console.debug(`[billsdk] ${message}`, ...args);\n },\n info: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"info\")) console.info(`[billsdk] ${message}`, ...args);\n },\n warn: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"warn\")) console.warn(`[billsdk] ${message}`, ...args);\n },\n error: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"error\")) console.error(`[billsdk] ${message}`, ...args);\n },\n };\n}\n\n/**\n * Resolve options with defaults\n */\nfunction resolveOptions(\n options: BillSDKOptions,\n adapter: DBAdapter,\n): ResolvedBillSDKOptions {\n return {\n database: adapter,\n payment: options.payment,\n basePath: options.basePath ?? \"/api/billing\",\n secret: options.secret ?? generateDefaultSecret(),\n plans: options.plans,\n features: options.features,\n plugins: options.plugins ?? [],\n hooks: options.hooks ?? {},\n behaviors: options.behaviors,\n logger: {\n level: options.logger?.level ?? \"info\",\n disabled: options.logger?.disabled ?? false,\n },\n };\n}\n\n/**\n * Generate a default secret (for development only)\n */\nfunction generateDefaultSecret(): string {\n return \"billsdk-development-secret-change-in-production\";\n}\n\n/**\n * Create the billing context\n */\nexport async function createBillingContext(\n adapter: DBAdapter,\n options: BillSDKOptions,\n): Promise<BillingContext> {\n const resolvedOptions = resolveOptions(options, adapter);\n const logger = createLogger(options.logger);\n const plugins = resolvedOptions.plugins;\n\n // Get base schema\n let schema = getBillingSchema();\n\n // Extend schema with plugins\n for (const plugin of plugins) {\n if (plugin.schema) {\n schema = { ...schema, ...plugin.schema };\n }\n }\n\n // Timestamps like createdAt/updatedAt should always be real system time\n const getNow = async () => new Date();\n\n const internalAdapter = createInternalAdapter(\n adapter,\n options.plans ?? [],\n options.features ?? [],\n getNow,\n );\n\n // Build context\n const context: BillingContext = {\n options: resolvedOptions,\n basePath: resolvedOptions.basePath,\n adapter,\n paymentAdapter: options.payment,\n internalAdapter,\n schema,\n plugins,\n logger,\n secret: resolvedOptions.secret,\n timeProvider: createDefaultTimeProvider(),\n\n hasPlugin(id: string): boolean {\n return plugins.some((p) => p.id === id);\n },\n\n getPlugin<T extends BillSDKPlugin>(id: string): T | null {\n const plugin = plugins.find((p) => p.id === id);\n return (plugin as T) ?? null;\n },\n\n generateId(): string {\n return crypto.randomUUID();\n },\n };\n\n // Initialize plugins (may override timeProvider)\n for (const plugin of plugins) {\n if (plugin.init) {\n await plugin.init(context);\n }\n }\n\n logger.debug(\"BillingContext created\", {\n basePath: context.basePath,\n plugins: plugins.map((p) => p.id),\n hasPaymentAdapter: !!context.paymentAdapter,\n plans: options.plans?.length ?? 0,\n features: options.features?.length ?? 0,\n });\n\n return context;\n}\n","import { memoryAdapter } from \"../adapters/memory-adapter\";\nimport { paymentAdapter } from \"../adapters/payment\";\nimport { createRouter } from \"../api\";\nimport {\n type BillingContext,\n createBillingContext,\n} from \"../context/create-context\";\nimport { runBehavior } from \"../logic/behaviors/runner\";\nimport { processRenewals as processRenewalsService } from \"../logic/renewal-service\";\nimport {\n changeSubscription as changeSubscriptionService,\n createSubscription as createSubscriptionService,\n} from \"../logic/subscription-service\";\nimport type { BillSDK, InferredAPI } from \"../types/billsdk\";\nimport type { BillSDKOptions, FeatureConfig } from \"../types/options\";\n\n/**\n * Base error codes for BillSDK\n */\nconst BASE_ERROR_CODES = {\n CUSTOMER_NOT_FOUND: \"CUSTOMER_NOT_FOUND\",\n PLAN_NOT_FOUND: \"PLAN_NOT_FOUND\",\n SUBSCRIPTION_NOT_FOUND: \"SUBSCRIPTION_NOT_FOUND\",\n FEATURE_NOT_FOUND: \"FEATURE_NOT_FOUND\",\n PAYMENT_ADAPTER_NOT_CONFIGURED: \"PAYMENT_ADAPTER_NOT_CONFIGURED\",\n INVALID_REQUEST: \"INVALID_REQUEST\",\n INTERNAL_ERROR: \"INTERNAL_ERROR\",\n} as const;\n\n/**\n * Create the API object for direct server-side access\n * The generic is for type inference only - runtime behavior is the same\n */\nfunction createAPI<TFeatureCode extends string = string>(\n contextPromise: Promise<BillingContext>,\n): InferredAPI<TFeatureCode> {\n return {\n async getCustomer(params) {\n const ctx = await contextPromise;\n return ctx.internalAdapter.findCustomerByExternalId(params.externalId);\n },\n\n async createCustomer(data) {\n const ctx = await contextPromise;\n return ctx.internalAdapter.createCustomer(data);\n },\n\n async listPlans() {\n const ctx = await contextPromise;\n // Plans come from config, synchronous\n return ctx.internalAdapter.listPlans();\n },\n\n async getPlan(params) {\n const ctx = await contextPromise;\n // Plans come from config, synchronous\n return ctx.internalAdapter.findPlanByCode(params.code);\n },\n\n async getSubscription(params) {\n const ctx = await contextPromise;\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n params.customerId,\n );\n if (!customer) return null;\n return ctx.internalAdapter.findSubscriptionByCustomerId(customer.id);\n },\n\n async createSubscription(params) {\n const ctx = await contextPromise;\n\n // Delegate to shared service\n return createSubscriptionService(ctx, {\n customerId: params.customerId,\n planCode: params.planCode,\n interval: params.interval,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n });\n },\n\n async cancelSubscription(params) {\n const ctx = await contextPromise;\n\n // Delegate to behavior (default: cancel subscription)\n const result = await runBehavior(ctx, \"onSubscriptionCancel\", {\n customerId: params.customerId,\n cancelAt: params.cancelAt,\n });\n\n return result.subscription;\n },\n\n async changeSubscription(params) {\n const ctx = await contextPromise;\n return changeSubscriptionService(ctx, params);\n },\n\n async checkFeature(params) {\n const ctx = await contextPromise;\n return ctx.internalAdapter.checkFeatureAccess(\n params.customerId,\n params.feature,\n );\n },\n\n async listFeatures(params) {\n const ctx = await contextPromise;\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n params.customerId,\n );\n if (!customer) return [];\n\n const subscription =\n await ctx.internalAdapter.findSubscriptionByCustomerId(customer.id);\n if (!subscription) return [];\n\n // Get features from config (synchronous)\n const featureCodes = ctx.internalAdapter.getPlanFeatures(\n subscription.planCode,\n );\n return featureCodes.map((code) => {\n const feature = ctx.internalAdapter.findFeatureByCode(code);\n return feature\n ? {\n code: feature.code as TFeatureCode,\n name: feature.name,\n enabled: true as const,\n }\n : { code: code as TFeatureCode, name: code, enabled: true as const };\n });\n },\n\n async health() {\n return {\n status: \"ok\" as const,\n timestamp: new Date().toISOString(),\n };\n },\n\n async listPayments(params) {\n const ctx = await contextPromise;\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n params.customerId,\n );\n if (!customer) return [];\n return ctx.internalAdapter.listPayments(customer.id, {\n limit: params.limit,\n offset: params.offset,\n });\n },\n\n async getPayment(params) {\n const ctx = await contextPromise;\n return ctx.internalAdapter.findPaymentById(params.paymentId);\n },\n\n async createRefund(params) {\n const ctx = await contextPromise;\n\n // Delegate to behavior (default: refund + cancel subscription)\n return runBehavior(ctx, \"onRefund\", {\n paymentId: params.paymentId,\n amount: params.amount,\n reason: params.reason,\n });\n },\n\n async processRenewals(params) {\n const ctx = await contextPromise;\n return processRenewalsService(ctx, params);\n },\n };\n}\n\n/**\n * Initialize the billing context\n */\nasync function init(options: BillSDKOptions): Promise<BillingContext> {\n const database = options.database ?? memoryAdapter();\n const payment = options.payment ?? paymentAdapter();\n return createBillingContext(database, { ...options, payment });\n}\n\n/**\n * Create a BillSDK instance\n *\n * @param options - Configuration options\n * @returns BillSDK instance\n */\n// biome-ignore lint/suspicious/noExplicitAny: TypeScript requires `any` here to support both readonly and mutable feature arrays (const vs let)\nexport function createBillSDK<Options extends BillSDKOptions<any>>(\n options: Options,\n): BillSDK<Options> {\n // Lazy initialization - context is created only when needed\n const contextPromise = init(options);\n\n // Collect error codes from plugins\n const errorCodes: Record<string, string> = {};\n for (const plugin of options.plugins ?? []) {\n if (plugin.$ERROR_CODES) {\n Object.assign(errorCodes, plugin.$ERROR_CODES);\n }\n }\n\n // Create the request handler\n const handler = async (request: Request): Promise<Response> => {\n const ctx = await contextPromise;\n const { handler: routeHandler } = createRouter(ctx);\n return routeHandler(request);\n };\n\n // Create the API object\n // Type assertion needed because runtime uses string but we want type inference\n const api = createAPI(contextPromise) as BillSDK<Options>[\"api\"];\n\n return {\n handler,\n api,\n options,\n $context: contextPromise,\n $Infer: {} as BillSDK<Options>[\"$Infer\"],\n $ERROR_CODES: {\n ...BASE_ERROR_CODES,\n ...errorCodes,\n } as BillSDK<Options>[\"$ERROR_CODES\"],\n };\n}\n\n/**\n * Create a BillSDK instance\n *\n * @example\n * ```typescript\n * import { billsdk } from \"@billsdk/core\";\n *\n * export const billing = billsdk({\n * basePath: \"/api/billing\",\n * features: [\n * { code: \"export\", name: \"Export\" },\n * ],\n * plans: [\n * { code: \"pro\", features: [\"export\"] }, // Validated!\n * ],\n * });\n * ```\n */\nexport function billsdk<\n const TFeatures extends readonly FeatureConfig<string>[],\n>(options: BillSDKOptions<TFeatures>): BillSDK<BillSDKOptions<TFeatures>> {\n // biome-ignore lint/suspicious/noExplicitAny: Bridging `const` inference (readonly[]) to createBillSDK's mutable array expectation\n return createBillSDK(options as any);\n}\n"]}
1
+ {"version":3,"sources":["../src/api/routes/customer.ts","../src/api/routes/features.ts","../src/api/routes/health.ts","../src/api/routes/payment.ts","../src/api/routes/plan.ts","../src/logic/payment-failed-service.ts","../src/logic/refund-service.ts","../src/logic/proration.ts","../src/logic/subscription-service.ts","../src/logic/trial-end-service.ts","../src/logic/behaviors/defaults.ts","../src/logic/behaviors/runner.ts","../src/api/routes/refund.ts","../src/logic/renewal-service.ts","../src/api/routes/renewals.ts","../src/api/routes/subscription.ts","../src/api/routes/webhook.ts","../src/api/router.ts","../src/db/internal-adapter.ts","../src/context/create-context.ts","../src/billsdk/base.ts"],"names":["z","canceled","updatedSubscription","newPeriodEnd","endpoint"],"mappings":";;;;;;;;;;;AAMA,IAAM,oBAAA,GAAuB,EAAE,MAAA,CAAO;AAAA,EACpC,UAAA,EAAY,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC5B,KAAA,EAAO,CAAA,CAAE,MAAA,EAAO,CAAE,KAAA,EAAM;AAAA,EACxB,IAAA,EAAM,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC1B,QAAA,EAAU,CAAA,CAAE,MAAA,CAAO,CAAA,CAAE,MAAA,IAAU,CAAA,CAAE,OAAA,EAAS,CAAA,CAAE,QAAA;AAC9C,CAAC,CAAA;AAKD,IAAM,sBAAA,GAAyB,EAAE,MAAA,CAAO;AAAA,EACtC,UAAA,EAAY,CAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC;AAC9B,CAAC,CAAA;AAKM,IAAM,iBAAA,GAAqD;AAAA,EAChE,cAAA,EAAgB;AAAA,IACd,IAAA,EAAM,WAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACR;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KACG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,IAAA,EAAK,GAAI,OAAA;AAGtB,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,wBAAA;AAAA,QACzC,IAAA,CAAK;AAAA,OACP;AACA,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,OAAO,EAAE,UAAU,QAAA,EAAS;AAAA,MAC9B;AAGA,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,eAAe,IAAI,CAAA;AAC9D,MAAA,OAAO,EAAE,QAAA,EAAS;AAAA,IACpB;AAAA,GACF;AAAA,EAEA,WAAA,EAAa;AAAA,IACX,IAAA,EAAM,WAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAO;AAAA,KACT;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KACG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,KAAA,EAAM,GAAI,OAAA;AAEvB,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,wBAAA;AAAA,QACzC,KAAA,CAAM;AAAA,OACR;AACA,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAO,EAAE,UAAU,IAAA,EAAK;AAAA,MAC1B;AAEA,MAAA,OAAO,EAAE,QAAA,EAAS;AAAA,IACpB;AAAA;AAEJ,CAAA;AChEA,IAAM,uBAAA,GAA0BA,EAAE,MAAA,CAAO;AAAA,EACvC,UAAA,EAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC5B,OAAA,EAASA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC;AAC3B,CAAC,CAAA;AAKD,IAAM,uBAAA,GAA0BA,EAAE,MAAA,CAAO;AAAA,EACvC,UAAA,EAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC;AAC9B,CAAC,CAAA;AAKM,IAAM,gBAAA,GAAoD;AAAA,EAC/D,YAAA,EAAc;AAAA,IACZ,IAAA,EAAM,iBAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAO;AAAA,KACT;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KAIG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,KAAA,EAAM,GAAI,OAAA;AAEvB,MAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA;AAAA,QACvC,KAAA,CAAM,UAAA;AAAA,QACN,KAAA,CAAM;AAAA,OACR;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,GACF;AAAA,EAEA,YAAA,EAAc;AAAA,IACZ,IAAA,EAAM,WAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAO;AAAA,KACT;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KAIG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,KAAA,EAAM,GAAI,OAAA;AAGvB,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,wBAAA;AAAA,QACzC,KAAA,CAAM;AAAA,OACR;AACA,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAO,EAAE,QAAA,EAAU,EAAC,EAAE;AAAA,MACxB;AAGA,MAAA,MAAM,eACJ,MAAM,GAAA,CAAI,eAAA,CAAgB,4BAAA,CAA6B,SAAS,EAAE,CAAA;AACpE,MAAA,IAAI,CAAC,YAAA,EAAc;AACjB,QAAA,OAAO,EAAE,QAAA,EAAU,EAAC,EAAE;AAAA,MACxB;AAGA,MAAA,MAAM,YAAA,GAAe,IAAI,eAAA,CAAgB,eAAA;AAAA,QACvC,YAAA,CAAa;AAAA,OACf;AACA,MAAA,MAAM,QAAA,GAAW,YAAA,CAAa,GAAA,CAAI,CAAC,IAAA,KAAiB;AAClD,QAAA,MAAM,OAAA,GAAU,GAAA,CAAI,eAAA,CAAgB,iBAAA,CAAkB,IAAI,CAAA;AAC1D,QAAA,OAAO;AAAA,UACL,IAAA;AAAA,UACA,IAAA,EAAM,SAAS,IAAA,IAAQ,IAAA;AAAA,UACvB,IAAA,EAAM,SAAS,IAAA,IAAQ,SAAA;AAAA,UACvB,OAAA,EAAS;AAAA,SACX;AAAA,MACF,CAAC,CAAA;AAED,MAAA,OAAO,EAAE,QAAA,EAAS;AAAA,IACpB;AAAA;AAEJ,CAAA;;;ACrFO,IAAM,cAAA,GAAkD;AAAA,EAC7D,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,SAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,SAAS,YAAY;AACnB,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,IAAA;AAAA,QACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAClC,OAAA,EAAS;AAAA,OACX;AAAA,IACF;AAAA;AAEJ,CAAA;ACbA,IAAM,uBAAA,GAA0BA,EAAE,MAAA,CAAO;AAAA,EACvC,UAAA,EAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC5B,KAAA,EAAOA,CAAAA,CAAE,MAAA,CAAO,MAAA,EAAO,CAAE,QAAA,EAAS,CAAE,GAAA,CAAI,GAAG,CAAA,CAAE,QAAA,EAAS,CAAE,QAAQ,EAAE,CAAA;AAAA,EAClE,MAAA,EAAQA,CAAAA,CAAE,MAAA,CAAO,MAAA,EAAO,CAAE,aAAY,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQ,CAAC;AAC9D,CAAC,CAAA;AAKD,IAAM,qBAAA,GAAwBA,EAAE,MAAA,CAAO;AAAA,EACrC,SAAA,EAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC;AAC7B,CAAC,CAAA;AAKM,IAAM,gBAAA,GAAoD;AAAA,EAC/D,YAAA,EAAc;AAAA,IACZ,IAAA,EAAM,WAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAO;AAAA,KACT;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KAIG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,KAAA,EAAM,GAAI,OAAA;AAGvB,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,wBAAA;AAAA,QACzC,KAAA,CAAM;AAAA,OACR;AACA,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAO,EAAE,QAAA,EAAU,EAAC,EAAE;AAAA,MACxB;AAGA,MAAA,MAAM,WAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,YAAA,CAAa,SAAS,EAAA,EAAI;AAAA,QACnE,OAAO,KAAA,CAAM,KAAA;AAAA,QACb,QAAQ,KAAA,CAAM;AAAA,OACf,CAAA;AAED,MAAA,OAAO,EAAE,QAAA,EAAS;AAAA,IACpB;AAAA,GACF;AAAA,EAEA,UAAA,EAAY;AAAA,IACV,IAAA,EAAM,UAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAO;AAAA,KACT;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KACG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,KAAA,EAAM,GAAI,OAAA;AAEvB,MAAA,MAAM,OAAA,GAAU,MAAM,GAAA,CAAI,eAAA,CAAgB,eAAA;AAAA,QACxC,KAAA,CAAM;AAAA,OACR;AAEA,MAAA,OAAO,EAAE,OAAA,EAAQ;AAAA,IACnB;AAAA;AAEJ,CAAA;ACnEO,IAAM,aAAA,GAAiD;AAAA,EAC5D,SAAA,EAAW;AAAA,IACT,IAAA,EAAM,QAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,OAAA,EAAS,OAAO,OAAA,KAA6B;AAC3C,MAAA,MAAM,EAAE,KAAI,GAAI,OAAA;AAEhB,MAAA,MAAM,QAAQ,GAAA,CAAI,eAAA,CAAgB,UAAU,EAAE,cAAA,EAAgB,OAAO,CAAA;AACrE,MAAA,OAAO,EAAE,KAAA,EAAM;AAAA,IACjB;AAAA,GACF;AAAA,EAEA,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,OAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAOA,EAAE,MAAA,CAAO;AAAA,QACd,IAAA,EAAMA,EAAE,MAAA;AAAO,OAChB;AAAA,KACH;AAAA,IACA,OAAA,EAAS,OAAO,OAAA,KAAwD;AACtE,MAAA,MAAM,EAAE,GAAA,EAAK,KAAA,EAAM,GAAI,OAAA;AAEvB,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,MAAM,IAAI,CAAA;AAE1D,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,OAAO,EAAE,MAAM,IAAA,EAAK;AAAA,MACtB;AAGA,MAAA,OAAO,EAAE,IAAA,EAAK;AAAA,IAChB;AAAA;AAEJ,CAAA;;;ACbA,eAAsB,mBAAA,CACpB,KACA,MAAA,EACoC;AACpC,EAAA,MAAM,EAAE,cAAA,EAAgB,KAAA,EAAM,GAAI,MAAA;AAGlC,EAAA,MAAM,YAAA,GACJ,MAAM,GAAA,CAAI,eAAA,CAAgB,qBAAqB,cAAc,CAAA;AAC/D,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,EAC1C;AAEA,EAAA,GAAA,CAAI,MAAA,CAAO,KAAK,kDAAA,EAAoD;AAAA,IAClE,gBAAgB,YAAA,CAAa,EAAA;AAAA,IAC7B;AAAA,GACD,CAAA;AAGD,EAAA,MAAM,mBAAA,GAAsB,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA;AAAA,IACpD,YAAA,CAAa,EAAA;AAAA,IACb,EAAE,QAAQ,UAAA;AAAW,GACvB;AAEA,EAAA,OAAO;AAAA,IACL,cAAc,mBAAA,IAAuB;AAAA,MACnC,GAAG,YAAA;AAAA,MACH,MAAA,EAAQ;AAAA;AACV,GACF;AACF;;;AC5BA,eAAsB,YAAA,CACpB,KACA,MAAA,EAC6B;AAC7B,EAAA,MAAM,EAAE,SAAA,EAAW,MAAA,EAAQ,MAAA,EAAO,GAAI,MAAA;AAGtC,EAAA,IAAI,CAAC,GAAA,CAAI,cAAA,EAAgB,MAAA,EAAQ;AAC/B,IAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,EAC5D;AAGA,EAAA,MAAM,OAAA,GAAU,MAAM,GAAA,CAAI,eAAA,CAAgB,gBAAgB,SAAS,CAAA;AACnE,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,EACrC;AAGA,EAAA,IAAI,OAAA,CAAQ,WAAW,WAAA,EAAa;AAClC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mCAAA,EAAsC,OAAA,CAAQ,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,EACzE;AAGA,EAAA,MAAM,eAAA,GAAkB,QAAQ,cAAA,IAAkB,CAAA;AAClD,EAAA,MAAM,eAAA,GAAkB,QAAQ,MAAA,GAAS,eAAA;AAEzC,EAAA,IAAI,mBAAmB,CAAA,EAAG;AACxB,IAAA,MAAM,IAAI,MAAM,yCAAyC,CAAA;AAAA,EAC3D;AAGA,EAAA,MAAM,eAAe,MAAA,IAAU,eAAA;AAE/B,EAAA,IAAI,eAAe,eAAA,EAAiB;AAClC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,cAAA,EAAiB,YAAY,CAAA,OAAA,EAAU,eAAe,CAAA,yBAAA;AAAA,KACxD;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,QAAQ,iBAAA,EAAmB;AAC9B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAGA,EAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,cAAA,CAAe,MAAA,CAAO;AAAA,IAC7C,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,IAC3B,MAAA,EAAQ,YAAA;AAAA,IACR;AAAA,GACD,CAAA;AAED,EAAA,IAAI,MAAA,CAAO,WAAW,QAAA,EAAU;AAC9B,IAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,KAAA,IAAS,eAAe,CAAA;AAAA,EACjD;AAGA,EAAA,MAAM,oBAAoB,eAAA,GAAkB,YAAA;AAC5C,EAAA,MAAM,SAAA,GACJ,iBAAA,IAAqB,OAAA,CAAQ,MAAA,GAAS,UAAA,GAAa,WAAA;AAErD,EAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,aAAA,CAAc,OAAA,CAAQ,EAAA,EAAI;AAAA,IAClD,MAAA,EAAQ,SAAA;AAAA,IACR,cAAA,EAAgB;AAAA,GACjB,CAAA;AAGD,EAAA,MAAM,aAAA,GAAgB,MAAM,GAAA,CAAI,eAAA,CAAgB,aAAA,CAAc;AAAA,IAC5D,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,cAAA,EAAgB,QAAQ,cAAA,IAAkB,MAAA;AAAA,IAC1C,IAAA,EAAM,QAAA;AAAA,IACN,MAAA,EAAQ,WAAA;AAAA,IACR,QAAQ,CAAC,YAAA;AAAA;AAAA,IACT,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,mBAAmB,MAAA,CAAO,gBAAA;AAAA,IAC1B,QAAA,EAAU;AAAA,MACR,mBAAmB,OAAA,CAAQ,EAAA;AAAA,MAC3B;AAAA;AACF,GACD,CAAA;AAED,EAAA,GAAA,CAAI,MAAA,CAAO,KAAK,kBAAA,EAAoB;AAAA,IAClC,mBAAmB,OAAA,CAAQ,EAAA;AAAA,IAC3B,iBAAiB,aAAA,CAAc,EAAA;AAAA,IAC/B,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,IAAI,QAAQ,cAAA,EAAgB;AAC1B,IAAA,MAAM,YAAA,GAAe,MAAM,GAAA,CAAI,eAAA,CAAgB,oBAAA;AAAA,MAC7C,OAAA,CAAQ;AAAA,KACV;AAEA,IAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,MAAA,KAAW,UAAA,EAAY;AACtD,MAAA,GAAA,CAAI,MAAA,CAAO,KAAK,2CAAA,EAA6C;AAAA,QAC3D,gBAAgB,YAAA,CAAa,EAAA;AAAA,QAC7B;AAAA,OACD,CAAA;AAED,MAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,YAAA,CAAa,EAAE,CAAA;AAAA,IAC9D;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,aAAA;AAAA,IACR,eAAA,EAAiB;AAAA,MACf,GAAG,OAAA;AAAA,MACH,MAAA,EAAQ,SAAA;AAAA,MACR,cAAA,EAAgB;AAAA;AAClB,GACF;AACF;;;AChFA,SAAS,WAAA,CAAY,OAAa,GAAA,EAAmB;AACnD,EAAA,MAAM,QAAA,GAAW,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA;AAClC,EAAA,OAAO,IAAA,CAAK,MAAM,GAAA,CAAI,OAAA,KAAY,KAAA,CAAM,OAAA,MAAa,QAAQ,CAAA;AAC/D;AA4BO,SAAS,mBAAmB,MAAA,EAA0C;AAC3E,EAAA,MAAM;AAAA,IACJ,aAAA;AAAA,IACA,aAAA;AAAA,IACA,kBAAA;AAAA,IACA,gBAAA;AAAA,IACA,UAAA,uBAAiB,IAAA;AAAK,GACxB,GAAI,MAAA;AAEJ,EAAA,MAAM,SAAA,GAAY,WAAA,CAAY,kBAAA,EAAoB,gBAAgB,CAAA;AAClE,EAAA,MAAM,QAAA,GAAW,WAAA,CAAY,kBAAA,EAAoB,UAAU,CAAA;AAC3D,EAAA,MAAM,gBAAgB,SAAA,GAAY,QAAA;AAElC,EAAA,MAAM,yBAAyB,IAAA,CAAK,GAAA;AAAA,IAClC,CAAA;AAAA,IACA,IAAA,CAAK,GAAA,CAAI,aAAA,EAAe,SAAS;AAAA,GACnC;AAGA,EAAA,MAAM,SAAS,IAAA,CAAK,KAAA;AAAA,IACjB,gBAAgB,SAAA,GAAa;AAAA,GAChC;AAGA,EAAA,MAAM,MAAA,GAAS,aAAA;AAGf,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,SAAS,MAAM,CAAA;AAE7C,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA,EAAU,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,QAAA,EAAU,SAAS,CAAC,CAAA;AAAA,IACnD;AAAA,GACF;AACF;;;AC1GA,eAAsB,kBAAA,CACpB,KACA,MAAA,EACmC;AACnC,EAAA,MAAM;AAAA,IACJ,UAAA;AAAA,IACA,QAAA;AAAA,IACA,QAAA,GAAW,SAAA;AAAA,IACX,UAAA;AAAA,IACA;AAAA,GACF,GAAI,MAAA;AAEJ,EAAA,IAAI,CAAC,IAAI,cAAA,EAAgB;AACvB,IAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,EAClD;AAEA,EAAA,MAAM,QAAA,GACJ,MAAM,GAAA,CAAI,eAAA,CAAgB,yBAAyB,UAAU,CAAA;AAC/D,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAAA,EACtC;AAEA,EAAA,MAAM,IAAA,GAAO,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,QAAQ,CAAA;AACxD,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,MAAM,IAAI,MAAM,gBAAgB,CAAA;AAAA,EAClC;AAEA,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,eAAA,CAAgB,YAAA,CAAa,UAAU,QAAQ,CAAA;AACjE,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,wBAAA,EAA2B,QAAQ,CAAA,eAAA,EAAkB,QAAQ,CAAA;AAAA,KAC/D;AAAA,EACF;AAEA,EAAA,MAAM,YAAA,GAAe,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB;AAAA,IAChE,YAAY,QAAA,CAAS,EAAA;AAAA,IACrB,QAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA,EAAQ,iBAAA;AAAA,IACR,WAAW,KAAA,CAAM;AAAA,GAClB,CAAA;AAED,EAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,cAAA,CAAe,cAAA,CAAe;AAAA,IACrD,QAAA,EAAU;AAAA,MACR,IAAI,QAAA,CAAS,EAAA;AAAA,MACb,OAAO,QAAA,CAAS,KAAA;AAAA,MAChB,oBAAoB,QAAA,CAAS;AAAA,KAC/B;AAAA,IACA,IAAA,EAAM;AAAA,MACJ,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,MAAM,IAAA,CAAK;AAAA,KACb;AAAA,IACA,KAAA,EAAO;AAAA,MACL,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,UAAU,KAAA,CAAM;AAAA,KAClB;AAAA,IACA,YAAA,EAAc;AAAA,MACZ,IAAI,YAAA,CAAa;AAAA,KACnB;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA,EAAU;AAAA,MACR,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,YAAY,QAAA,CAAS;AAAA;AACvB,GACD,CAAA;AAED,EAAA,IAAI,MAAA,CAAO,WAAW,QAAA,EAAU;AAC9B,IAAA,MAAM,qBAAA,GAAwB,MAAM,GAAA,CAAI,eAAA,CAAgB,iBAAA;AAAA,MACtD,QAAA,CAAS;AAAA,KACX;AACA,IAAA,KAAA,MAAW,YAAY,qBAAA,EAAuB;AAC5C,MAAA,IACE,QAAA,CAAS,OAAO,YAAA,CAAa,EAAA,KAC5B,SAAS,MAAA,KAAW,QAAA,IAAY,QAAA,CAAS,MAAA,KAAW,UAAA,CAAA,EACrD;AACA,QAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,QAAA,CAAS,EAAE,CAAA;AAAA,MAC1D;AAAA,IACF;AAEA,IAAA,MAAM,kBAAA,GAAqB,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA;AAAA,MACnD,YAAA,CAAa,EAAA;AAAA,MACb,EAAE,QAAQ,QAAA;AAAS,KACrB;AAEA,IAAA,IAAI,MAAA,CAAO,kBAAA,IAAsB,CAAC,QAAA,CAAS,kBAAA,EAAoB;AAC7D,MAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,QAAA,CAAS,EAAA,EAAI;AAAA,QACpD,oBAAoB,MAAA,CAAO;AAAA,OAC5B,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AACpB,MAAA,MAAM,GAAA,CAAI,gBAAgB,aAAA,CAAc;AAAA,QACtC,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,gBAAgB,YAAA,CAAa,EAAA;AAAA,QAC7B,IAAA,EAAM,cAAA;AAAA,QACN,MAAA,EAAQ,WAAA;AAAA,QACR,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd,UAAU,KAAA,CAAM,QAAA;AAAA,QAChB,QAAA,EAAU;AAAA,UACR,UAAU,IAAA,CAAK,IAAA;AAAA,UACf;AAAA;AACF,OACD,CAAA;AAAA,IACH;AAEA,IAAA,OAAO;AAAA,MACL,cAAc,kBAAA,IAAsB;AAAA,QAClC,GAAG,YAAA;AAAA,QACH,MAAA,EAAQ;AAAA;AACV,KACF;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,CAAO,WAAW,SAAA,EAAW;AAC/B,IAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,YAAA,CAAa,EAAA,EAAI;AAAA,MAC5D,2BAA2B,MAAA,CAAO;AAAA,KACnC,CAAA;AAED,IAAA,IAAI,MAAA,CAAO,kBAAA,IAAsB,CAAC,QAAA,CAAS,kBAAA,EAAoB;AAC7D,MAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,QAAA,CAAS,EAAA,EAAI;AAAA,QACpD,oBAAoB,MAAA,CAAO;AAAA,OAC5B,CAAA;AAAA,IACH;AAEA,IAAA,OAAO;AAAA,MACL,YAAA;AAAA,MACA,aAAa,MAAA,CAAO;AAAA,KACtB;AAAA,EACF;AAEA,EAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,YAAA,CAAa,EAAA,EAAI;AAAA,IAC5D,MAAA,EAAQ;AAAA,GACT,CAAA;AACD,EAAA,MAAM,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAA;AAC9B;AAaA,eAAsB,kBAAA,CACpB,KACA,MAAA,EACmC;AACnC,EAAA,MAAM,EAAE,UAAA,EAAY,QAAA,GAAW,YAAA,EAAa,GAAI,MAAA;AAEhD,EAAA,MAAM,QAAA,GACJ,MAAM,GAAA,CAAI,eAAA,CAAgB,yBAAyB,UAAU,CAAA;AAC/D,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAAA,EACtC;AAEA,EAAA,MAAM,YAAA,GAAe,MAAM,GAAA,CAAI,eAAA,CAAgB,4BAAA;AAAA,IAC7C,QAAA,CAAS;AAAA,GACX;AACA,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,IAAI,MAAM,8BAA8B,CAAA;AAAA,EAChD;AAEA,EAAA,IAAI,aAAa,aAAA,EAAe;AAC9B,IAAA,MAAMC,SAAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA;AAAA,MACzC,YAAA,CAAa;AAAA,KACf;AACA,IAAA,OAAO,EAAE,YAAA,EAAcA,SAAAA,EAAU,mBAAA,EAAqB,IAAA,EAAK;AAAA,EAC7D;AAEA,EAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA;AAAA,IACzC,YAAA,CAAa,EAAA;AAAA,IACb,YAAA,CAAa;AAAA,GACf;AACA,EAAA,OAAO;AAAA,IACL,YAAA,EAAc,QAAA;AAAA,IACd,mBAAA,EAAqB,KAAA;AAAA,IACrB,aAAa,YAAA,CAAa;AAAA,GAC5B;AACF;AAkBA,IAAM,YAAA,GAAgD;AAAA,EACpD,OAAA,EAAS,CAAA;AAAA,EACT,SAAA,EAAW,CAAA;AAAA,EACX,MAAA,EAAQ;AACV,CAAA;AAEA,SAAS,SAAA,CACP,QAAA,EACA,QAAA,EACA,WAAA,EACA,WAAA,EACS;AACT,EAAA,IAAI,gBAAgB,WAAA,EAAa;AAC/B,IAAA,OAAO,YAAA,CAAa,WAAW,CAAA,GAAI,YAAA,CAAa,WAAW,CAAA;AAAA,EAC7D;AACA,EAAA,OAAO,QAAA,GAAW,QAAA;AACpB;AAEA,eAAsB,kBAAA,CACpB,KACA,MAAA,EACmC;AACnC,EAAA,MAAM,EAAE,UAAA,EAAY,WAAA,EAAa,WAAA,EAAa,OAAA,GAAU,MAAK,GAAI,MAAA;AAEjE,EAAA,MAAM,QAAA,GACJ,MAAM,GAAA,CAAI,eAAA,CAAgB,yBAAyB,UAAU,CAAA;AAC/D,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAAA,EACtC;AAEA,EAAA,MAAM,YAAA,GAAe,MAAM,GAAA,CAAI,eAAA,CAAgB,4BAAA;AAAA,IAC7C,QAAA,CAAS;AAAA,GACX;AACA,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,IAAI,MAAM,8BAA8B,CAAA;AAAA,EAChD;AAEA,EAAA,MAAM,cAAA,GAAiB,eAAe,YAAA,CAAa,QAAA;AAEnD,EAAA,IACE,YAAA,CAAa,QAAA,KAAa,WAAA,IAC1B,YAAA,CAAa,aAAa,cAAA,EAC1B;AACA,IAAA,MAAM,IAAI,MAAM,sBAAsB,CAAA;AAAA,EACxC;AAEA,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,aAAa,QAAQ,CAAA;AACxE,EAAA,MAAM,QAAA,GAAW,IAAI,eAAA,CAAgB,YAAA;AAAA,IACnC,YAAA,CAAa,QAAA;AAAA,IACb,YAAA,CAAa;AAAA,GACf;AACA,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,IAAI,MAAM,8BAA8B,CAAA;AAAA,EAChD;AAEA,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,WAAW,CAAA;AAC9D,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAAA,EACtC;AAEA,EAAA,MAAM,QAAA,GAAW,IAAI,eAAA,CAAgB,YAAA;AAAA,IACnC,WAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,wBAAA,EAA2B,WAAW,CAAA,eAAA,EAAkB,cAAc,CAAA;AAAA,KACxE;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,SAAA;AAAA,IACd,QAAA,CAAS,MAAA;AAAA,IACT,QAAA,CAAS,MAAA;AAAA,IACT,YAAA,CAAa,QAAA;AAAA,IACb;AAAA,GACF;AAEA,EAAA,GAAA,CAAI,MAAA,CAAO,KAAK,sBAAA,EAAwB;AAAA,IACtC,MAAM,CAAA,EAAG,YAAA,CAAa,QAAQ,CAAA,EAAA,EAAK,aAAa,QAAQ,CAAA,CAAA,CAAA;AAAA,IACxD,EAAA,EAAI,CAAA,EAAG,WAAW,CAAA,EAAA,EAAK,cAAc,CAAA,CAAA,CAAA;AAAA,IACrC,WAAW,QAAA,CAAS,MAAA;AAAA,IACpB,WAAW,QAAA,CAAS,MAAA;AAAA,IACpB,SAAA,EAAW;AAAA,GACZ,CAAA;AAGD,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,GAAA,CAAI,MAAA,CAAO,KAAK,oCAAA,EAAsC;AAAA,MACpD,iBAAA,EAAmB,WAAA;AAAA,MACnB,iBAAA,EAAmB,cAAA;AAAA,MACnB,aAAa,YAAA,CAAa;AAAA,KAC3B,CAAA;AAED,IAAA,MAAMC,oBAAAA,GAAsB,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA;AAAA,MACpD,YAAA,CAAa,EAAA;AAAA,MACb;AAAA,QACE,iBAAA,EAAmB,WAAA;AAAA,QACnB,iBAAA,EAAmB;AAAA;AACrB,KACF;AAEA,IAAA,OAAO;AAAA,MACL,YAAA,EAAcA,oBAAAA;AAAA,MACd,YAAA,EAAc,OAAA;AAAA,MACd,OAAA;AAAA,MACA,OAAA,EAAS,IAAA;AAAA,MACT,SAAA,EAAW,IAAA;AAAA,MACX,aAAa,YAAA,CAAa;AAAA,KAC5B;AAAA,EACF;AAGA,EAAA,IAAI,OAAA,GAA0B,IAAA;AAC9B,EAAA,MAAM,aAAa,MAAM,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,OAAO,UAAU,CAAA;AAE/D,EAAA,GAAA,CAAI,MAAA,CAAO,KAAK,8BAAA,EAAgC;AAAA,IAC9C,UAAA,EAAY,WAAW,WAAA,EAAY;AAAA,IACnC,QAAA,EAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,GAClC,CAAA;AAED,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,MAAM,kBAAkB,kBAAA,CAAmB;AAAA,MACzC,eAAe,QAAA,CAAS,MAAA;AAAA,MACxB,eAAe,QAAA,CAAS,MAAA;AAAA,MACxB,oBAAoB,YAAA,CAAa,kBAAA;AAAA,MACjC,kBAAkB,YAAA,CAAa,gBAAA;AAAA,MAC/B;AAAA,KACD,CAAA;AAED,IAAA,GAAA,CAAI,MAAA,CAAO,KAAK,sBAAA,EAAwB;AAAA,MACtC,QAAQ,eAAA,CAAgB,MAAA;AAAA,MACxB,QAAQ,eAAA,CAAgB,MAAA;AAAA,MACxB,WAAW,eAAA,CAAgB,SAAA;AAAA,MAC3B,UAAU,eAAA,CAAgB;AAAA,KAC3B,CAAA;AAED,IAAA,IAAI,eAAA,CAAgB,YAAY,CAAA,EAAG;AACjC,MAAA,IAAI,CAAC,GAAA,CAAI,cAAA,EAAgB,MAAA,EAAQ;AAC/B,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,SAAS,kBAAA,EAAoB;AAChC,QAAA,MAAM,IAAI,KAAA;AAAA,UACR;AAAA,SACF;AAAA,MACF;AAEA,MAAA,MAAM,YAAA,GAAe,MAAM,GAAA,CAAI,cAAA,CAAe,MAAA,CAAO;AAAA,QACnD,QAAA,EAAU;AAAA,UACR,IAAI,QAAA,CAAS,EAAA;AAAA,UACb,OAAO,QAAA,CAAS,KAAA;AAAA,UAChB,oBAAoB,QAAA,CAAS;AAAA,SAC/B;AAAA,QACA,QAAQ,eAAA,CAAgB,SAAA;AAAA,QACxB,UAAU,QAAA,CAAS,QAAA;AAAA,QACnB,WAAA,EAAa,gBAAgB,OAAA,EAAS,IAAA,IAAQ,aAAa,QAAQ,CAAA,IAAA,EAAO,QAAQ,IAAI,CAAA,CAAA;AAAA,QACtF,QAAA,EAAU;AAAA,UACR,gBAAgB,YAAA,CAAa,EAAA;AAAA,UAC7B,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,IAAA,EAAM,SAAA;AAAA,UACN,aAAa,YAAA,CAAa,QAAA;AAAA,UAC1B;AAAA;AACF,OACD,CAAA;AAED,MAAA,IAAI,YAAA,CAAa,WAAW,QAAA,EAAU;AACpC,QAAA,MAAM,IAAI,KAAA,CAAM,YAAA,CAAa,KAAA,IAAS,eAAe,CAAA;AAAA,MACvD;AAEA,MAAA,OAAA,GAAU,MAAM,GAAA,CAAI,eAAA,CAAgB,aAAA,CAAc;AAAA,QAChD,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,gBAAgB,YAAA,CAAa,EAAA;AAAA,QAC7B,IAAA,EAAM,SAAA;AAAA,QACN,MAAA,EAAQ,WAAA;AAAA,QACR,QAAQ,eAAA,CAAgB,SAAA;AAAA,QACxB,UAAU,QAAA,CAAS,QAAA;AAAA,QACnB,mBAAmB,YAAA,CAAa,iBAAA;AAAA,QAChC,QAAA,EAAU;AAAA,UACR,aAAa,YAAA,CAAa,QAAA;AAAA,UAC1B,WAAA;AAAA,UACA,SAAA,EAAW;AAAA,YACT,QAAQ,eAAA,CAAgB,MAAA;AAAA,YACxB,QAAQ,eAAA,CAAgB;AAAA;AAC1B;AACF,OACD,CAAA;AAAA,IACH;AAAA,EACF;AAGA,EAAA,MAAM,cAAA,GAAiB,UAAA;AACvB,EAAA,MAAM,YAAA,GAAe,IAAI,IAAA,CAAK,UAAU,CAAA;AACxC,EAAA,IAAI,mBAAmB,QAAA,EAAU;AAC/B,IAAA,YAAA,CAAa,WAAA,CAAY,YAAA,CAAa,WAAA,EAAY,GAAI,CAAC,CAAA;AAAA,EACzD,CAAA,MAAA,IAAW,mBAAmB,WAAA,EAAa;AACzC,IAAA,YAAA,CAAa,QAAA,CAAS,YAAA,CAAa,QAAA,EAAS,GAAI,CAAC,CAAA;AAAA,EACnD,CAAA,MAAO;AACL,IAAA,YAAA,CAAa,QAAA,CAAS,YAAA,CAAa,QAAA,EAAS,GAAI,CAAC,CAAA;AAAA,EACnD;AAEA,EAAA,MAAM,mBAAA,GAAsB,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA;AAAA,IACpD,YAAA,CAAa,EAAA;AAAA,IACb;AAAA,MACE,QAAA,EAAU,WAAA;AAAA,MACV,QAAA,EAAU,cAAA;AAAA,MACV,kBAAA,EAAoB,cAAA;AAAA,MACpB,gBAAA,EAAkB,YAAA;AAAA,MAClB,iBAAA,EAAmB,MAAA;AAAA,MACnB,iBAAA,EAAmB;AAAA;AACrB,GACF;AAEA,EAAA,GAAA,CAAI,MAAA,CAAO,KAAK,cAAA,EAAgB;AAAA,IAC9B,IAAA,EAAM,CAAA,EAAG,YAAA,CAAa,kBAAA,CAAmB,WAAA,EAAa,CAAA,GAAA,EAAM,YAAA,CAAa,gBAAA,CAAiB,WAAA,EAAa,CAAA,CAAA;AAAA,IACvG,EAAA,EAAI,GAAG,cAAA,CAAe,WAAA,EAAa,CAAA,GAAA,EAAM,YAAA,CAAa,aAAa,CAAA;AAAA,GACpE,CAAA;AAED,EAAA,OAAO;AAAA,IACL,YAAA,EAAc,mBAAA;AAAA,IACd,YAAA,EAAc,OAAA;AAAA,IACd,OAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA,EAAW;AAAA,GACb;AACF;;;ACraA,eAAsB,cAAA,CACpB,KACA,MAAA,EAC+B;AAC/B,EAAA,MAAM,EAAE,gBAAe,GAAI,MAAA;AAG3B,EAAA,MAAM,YAAA,GACJ,MAAM,GAAA,CAAI,eAAA,CAAgB,qBAAqB,cAAc,CAAA;AAC/D,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,EAC1C;AAGA,EAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,gBAAA;AAAA,IACzC,YAAA,CAAa;AAAA,GACf;AACA,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,MAAM,IAAI,MAAM,oBAAoB,CAAA;AAAA,EACtC;AAGA,EAAA,MAAM,IAAA,GAAO,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,aAAa,QAAQ,CAAA;AAErE,EAAA,GAAA,CAAI,MAAA,CAAO,KAAK,sBAAA,EAAwB;AAAA,IACtC,gBAAgB,YAAA,CAAa,EAAA;AAAA,IAC7B,YAAY,QAAA,CAAS,EAAA;AAAA,IACrB,UAAU,IAAA,EAAM;AAAA,GACjB,CAAA;AAGD,EAAA,IAAI,CAAC,SAAS,kBAAA,EAAoB;AAChC,IAAA,GAAA,CAAI,MAAA,CAAO,KAAK,2CAAA,EAA6C;AAAA,MAC3D,gBAAgB,YAAA,CAAa;AAAA,KAC9B,CAAA;AAED,IAAA,MAAM,oBAAA,GAAuB,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA;AAAA,MACrD,YAAA,CAAa;AAAA,KACf;AAEA,IAAA,OAAO;AAAA,MACL,cAAc,oBAAA,IAAwB;AAAA,QACpC,GAAG,YAAA;AAAA,QACH,MAAA,EAAQ;AAAA,OACV;AAAA,MACA,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AAGA,EAAA,GAAA,CAAI,MAAA,CAAO,KAAK,gDAAA,EAAkD;AAAA,IAChE,gBAAgB,YAAA,CAAa;AAAA,GAC9B,CAAA;AAED,EAAA,MAAM,kBAAA,GAAqB,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA;AAAA,IACnD,YAAA,CAAa,EAAA;AAAA,IACb,EAAE,QAAQ,QAAA;AAAS,GACrB;AAEA,EAAA,OAAO;AAAA,IACL,cAAc,kBAAA,IAAsB,EAAE,GAAG,YAAA,EAAc,QAAQ,QAAA,EAAS;AAAA,IACxE,SAAA,EAAW;AAAA,GACb;AACF;;;ACrEO,IAAM,gBAAA,GAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU9B,QAAA,EAAU,OACR,GAAA,EACA,MAAA,KAC4B;AAC5B,IAAA,OAAO,aAAoB,GAAA,EAAK;AAAA,MAC9B,WAAW,MAAA,CAAO,SAAA;AAAA,MAClB,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,QAAQ,MAAA,CAAO;AAAA,KAChB,CAAA;AAAA,EACH,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,eAAA,EAAiB,OACf,GAAA,EACA,MAAA,KACmC;AACnC,IAAA,OAAO,oBAA2B,GAAA,EAAK;AAAA,MACrC,gBAAgB,MAAA,CAAO,cAAA;AAAA,MACvB,OAAO,MAAA,CAAO;AAAA,KACf,CAAA;AAAA,EACH,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,oBAAA,EAAsB,OACpB,GAAA,EACA,MAAA,KACwC;AACxC,IAAA,OAAO,mBAA0B,GAAA,EAAK;AAAA,MACpC,YAAY,MAAA,CAAO,UAAA;AAAA,MACnB,UAAU,MAAA,CAAO;AAAA,KAClB,CAAA;AAAA,EACH,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,UAAA,EAAY,OACV,GAAA,EACA,MAAA,KAC8B;AAC9B,IAAA,OAAO,eAAsB,GAAA,EAAK;AAAA,MAChC,gBAAgB,MAAA,CAAO;AAAA,KACxB,CAAA;AAAA,EACH;AACF,CAAA;;;AC9CA,eAAsB,WAAA,CACpB,GAAA,EACA,YAAA,EACA,MAAA,EACsC;AACtC,EAAA,MAAM,YAAA,GAAe,GAAA,CAAI,OAAA,CAAQ,SAAA,GAAY,YAAY,CAAA;AACzD,EAAA,MAAM,SAAA,GAAY,iBAAiB,YAAY,CAAA;AAG/C,EAAA,MAAM,kBAAkB,YAAkD;AAExE,IAAA,OAAO,SAAA,CAAU,KAAK,MAAa,CAAA;AAAA,EACrC,CAAA;AAEA,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,GAAA,CAAI,MAAA,CAAO,KAAA,CAAM,CAAA,+BAAA,EAAkC,YAAY,CAAA,CAAE,CAAA;AAGjE,IAAA,OAAO,YAAA,CAAa,GAAA,EAAY,MAAA,EAAe,eAAsB,CAAA;AAAA,EACvE;AAEA,EAAA,GAAA,CAAI,MAAA,CAAO,KAAA,CAAM,CAAA,0BAAA,EAA6B,YAAY,CAAA,CAAE,CAAA;AAE5D,EAAA,OAAO,eAAA,EAAgB;AACzB;;;ACrEA,IAAM,kBAAA,GAAqBF,EAAE,MAAA,CAAO;AAAA;AAAA;AAAA;AAAA,EAIlC,SAAA,EAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAK3B,QAAQA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,GAAW,QAAA,EAAS;AAAA;AAAA;AAAA;AAAA,EAIvC,MAAA,EAAQA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AACrB,CAAC,CAAA;AAKM,IAAM,eAAA,GAAmD;AAAA,EAC9D,YAAA,EAAc;AAAA,IACZ,IAAA,EAAM,SAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACR;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KACG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,IAAA,EAAK,GAAI,OAAA;AAGtB,MAAA,OAAO,WAAA,CAAY,KAAuB,UAAA,EAAY;AAAA,QACpD,WAAW,IAAA,CAAK,SAAA;AAAA,QAChB,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,QAAQ,IAAA,CAAK;AAAA,OACd,CAAA;AAAA,IACH;AAAA;AAEJ,CAAA;;;AC4BA,SAAS,qBAAA,CACP,MACA,QAAA,EACM;AACN,EAAA,MAAM,MAAA,GAAS,IAAI,IAAA,CAAK,IAAI,CAAA;AAC5B,EAAA,IAAI,aAAa,QAAA,EAAU;AACzB,IAAA,MAAA,CAAO,WAAA,CAAY,MAAA,CAAO,WAAA,EAAY,GAAI,CAAC,CAAA;AAAA,EAC7C,CAAA,MAAA,IAAW,aAAa,WAAA,EAAa;AACnC,IAAA,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,QAAA,EAAS,GAAI,CAAC,CAAA;AAAA,EACvC,CAAA,MAAO;AACL,IAAA,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,QAAA,EAAS,GAAI,CAAC,CAAA;AAAA,EACvC;AACA,EAAA,OAAO,MAAA;AACT;AAKA,eAAe,oBAAA,CACb,KACA,MAAA,EACyB;AACzB,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,UAAA,GACf,MAAM,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,MAAA,CAAO,UAAU,CAAA,mBAC5C,IAAI,IAAA,EAAK;AAGb,EAAA,MAAM,KAAA,GAAiB;AAAA;AAAA,IAErB;AAAA,MACE,KAAA,EAAO,QAAA;AAAA,MACP,QAAA,EAAU,IAAA;AAAA,MACV,KAAA,EAAO,CAAC,QAAA,EAAU,UAAU;AAAA,KAC9B;AAAA;AAAA,IAEA;AAAA,MACE,KAAA,EAAO,kBAAA;AAAA,MACP,QAAA,EAAU,KAAA;AAAA,MACV,KAAA,EAAO;AAAA;AACT,GACF;AAGA,EAAA,IAAI,OAAO,UAAA,EAAY;AAErB,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,wBAAA;AAAA,MACzC,MAAA,CAAO;AAAA,KACT;AACA,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,OAAO,EAAC;AAAA,IACV;AACA,IAAA,KAAA,CAAM,IAAA,CAAK;AAAA,MACT,KAAA,EAAO,YAAA;AAAA,MACP,QAAA,EAAU,IAAA;AAAA,MACV,OAAO,QAAA,CAAS;AAAA,KACjB,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,GAAA,CAAI,QAAQ,QAAA,CAAuB;AAAA,IACxC,OAAO,MAAA,CAAO,YAAA;AAAA,IACd,KAAA;AAAA,IACA,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,MAAA,EAAQ,EAAE,KAAA,EAAO,kBAAA,EAAoB,WAAW,KAAA;AAAM,GACvD,CAAA;AACH;AAMA,eAAe,qBAAA,CACb,KACA,YAAA,EAC6E;AAC7E,EAAA,IAAI,CAAC,aAAa,iBAAA,EAAmB;AACnC,IAAA,OAAO;AAAA,MACL,WAAA,EAAa,KAAA;AAAA,MACb,aAAa,YAAA,CAAa,QAAA;AAAA,MAC1B,aAAa,YAAA,CAAa;AAAA,KAC5B;AAAA,EACF;AAEA,EAAA,MAAM,cAAc,YAAA,CAAa,iBAAA;AACjC,EAAA,MAAM,WAAA,GAAc,YAAA,CAAa,iBAAA,IAAqB,YAAA,CAAa,QAAA;AAEnE,EAAA,GAAA,CAAI,MAAA,CAAO,KAAK,gCAAA,EAAkC;AAAA,IAChD,gBAAgB,YAAA,CAAa,EAAA;AAAA,IAC7B,MAAM,YAAA,CAAa,QAAA;AAAA,IACnB,EAAA,EAAI,WAAA;AAAA,IACJ;AAAA,GACD,CAAA;AAED,EAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,YAAA,CAAa,EAAA,EAAI;AAAA,IAC5D,QAAA,EAAU,WAAA;AAAA,IACV,QAAA,EAAU,WAAA;AAAA,IACV,iBAAA,EAAmB,MAAA;AAAA,IACnB,iBAAA,EAAmB;AAAA,GACpB,CAAA;AAED,EAAA,OAAO;AAAA,IACL,WAAA,EAAa,IAAA;AAAA,IACb,WAAA;AAAA,IACA;AAAA,GACF;AACF;AAKA,eAAe,0BAAA,CACb,GAAA,EACA,YAAA,EACA,MAAA,EACwB;AACxB,EAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,gBAAA;AAAA,IACzC,YAAA,CAAa;AAAA,GACf;AACA,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO;AAAA,MACL,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,YAAY,YAAA,CAAa,UAAA;AAAA,MACzB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO;AAAA,KACT;AAAA,EACF;AAGA,EAAA,MAAM;AAAA,IACJ,WAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA,EAAa;AAAA,GACf,GAAI,MAAM,qBAAA,CAAsB,GAAA,EAAK,YAAY,CAAA;AACjD,EAAA,MAAM,WAAA,GAAc,cAAA;AAGpB,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,eAAA,CAAgB,YAAA,CAAa,aAAa,WAAW,CAAA;AACvE,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO;AAAA,MACL,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,YAAY,QAAA,CAAS,UAAA;AAAA,MACrB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,CAAA,wBAAA,EAA2B,WAAW,CAAA,eAAA,EAAkB,WAAW,CAAA,CAAA;AAAA,MAC1E,WAAA,EAAa,cACT,EAAE,IAAA,EAAM,aAAa,QAAA,EAAU,EAAA,EAAI,aAAY,GAC/C;AAAA,KACN;AAAA,EACF;AAEA,EAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,EAAA,MAAM,MAAM,MAAM,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,SAAS,UAAU,CAAA;AAG1D,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,OAAO;AAAA,MACL,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,YAAY,QAAA,CAAS,UAAA;AAAA,MACrB,MAAA,EAAQ,WAAA;AAAA,MACR,MAAA;AAAA,MACA,WAAA,EAAa,cACT,EAAE,IAAA,EAAM,aAAa,QAAA,EAAU,EAAA,EAAI,aAAY,GAC/C;AAAA,KACN;AAAA,EACF;AAGA,EAAA,IAAI,WAAW,CAAA,EAAG;AAChB,IAAA,MAAMG,aAAAA,GAAe,qBAAA,CAAsB,GAAA,EAAK,WAAW,CAAA;AAE3D,IAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,YAAA,CAAa,EAAA,EAAI;AAAA,MAC5D,kBAAA,EAAoB,GAAA;AAAA,MACpB,gBAAA,EAAkBA,aAAAA;AAAA,MAClB,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,GAAA,CAAI,MAAA,CAAO,KAAK,wBAAA,EAA0B;AAAA,MACxC,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,YAAA,EAAcA,cAAa,WAAA;AAAY,KACxC,CAAA;AAED,IAAA,OAAO;AAAA,MACL,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,YAAY,QAAA,CAAS,UAAA;AAAA,MACrB,MAAA,EAAQ,WAAA;AAAA,MACR,MAAA,EAAQ,CAAA;AAAA,MACR,WAAA,EAAa,cACT,EAAE,IAAA,EAAM,aAAa,QAAA,EAAU,EAAA,EAAI,aAAY,GAC/C;AAAA,KACN;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,SAAS,kBAAA,EAAoB;AAChC,IAAA,GAAA,CAAI,MAAA,CAAO,KAAK,qDAAA,EAAuD;AAAA,MACrE,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,YAAY,QAAA,CAAS;AAAA,KACtB,CAAA;AAED,IAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,YAAA,CAAa,EAAA,EAAI;AAAA,MAC5D,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,OAAO;AAAA,MACL,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,YAAY,QAAA,CAAS,UAAA;AAAA,MACrB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,2BAAA;AAAA,MACP,WAAA,EAAa,cACT,EAAE,IAAA,EAAM,aAAa,QAAA,EAAU,EAAA,EAAI,aAAY,GAC/C;AAAA,KACN;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,GAAA,CAAI,cAAA,EAAgB,MAAA,EAAQ;AAC/B,IAAA,GAAA,CAAI,MAAA,CAAO,MAAM,kDAAA,EAAoD;AAAA,MACnE,gBAAgB,YAAA,CAAa;AAAA,KAC9B,CAAA;AAED,IAAA,OAAO;AAAA,MACL,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,YAAY,QAAA,CAAS,UAAA;AAAA,MACrB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,kDAAA;AAAA,MACP,WAAA,EAAa,cACT,EAAE,IAAA,EAAM,aAAa,QAAA,EAAU,EAAA,EAAI,aAAY,GAC/C;AAAA,KACN;AAAA,EACF;AAGA,EAAA,MAAM,IAAA,GAAO,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,WAAW,CAAA;AAC3D,EAAA,MAAM,YAAA,GAAe,MAAM,GAAA,CAAI,cAAA,CAAe,MAAA,CAAO;AAAA,IACnD,QAAA,EAAU;AAAA,MACR,IAAI,QAAA,CAAS,EAAA;AAAA,MACb,OAAO,QAAA,CAAS,KAAA;AAAA,MAChB,oBAAoB,QAAA,CAAS;AAAA,KAC/B;AAAA,IACA,MAAA;AAAA,IACA,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,aAAa,CAAA,SAAA,EAAY,IAAA,EAAM,IAAA,IAAQ,WAAW,KAAK,WAAW,CAAA,CAAA,CAAA;AAAA,IAClE,QAAA,EAAU;AAAA,MACR,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,YAAY,QAAA,CAAS,EAAA;AAAA,MACrB,IAAA,EAAM,SAAA;AAAA,MACN,QAAA,EAAU;AAAA;AACZ,GACD,CAAA;AAED,EAAA,IAAI,YAAA,CAAa,WAAW,QAAA,EAAU;AACpC,IAAA,GAAA,CAAI,MAAA,CAAO,KAAK,uBAAA,EAAyB;AAAA,MACvC,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,OAAO,YAAA,CAAa;AAAA,KACrB,CAAA;AAGD,IAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,YAAA,CAAa,EAAA,EAAI;AAAA,MAC5D,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,OAAO;AAAA,MACL,gBAAgB,YAAA,CAAa,EAAA;AAAA,MAC7B,YAAY,QAAA,CAAS,UAAA;AAAA,MACrB,MAAA,EAAQ,QAAA;AAAA,MACR,KAAA,EAAO,aAAa,KAAA,IAAS,eAAA;AAAA,MAC7B,WAAA,EAAa,cACT,EAAE,IAAA,EAAM,aAAa,QAAA,EAAU,EAAA,EAAI,aAAY,GAC/C;AAAA,KACN;AAAA,EACF;AAGA,EAAA,MAAM,YAAA,GAAe,qBAAA,CAAsB,GAAA,EAAK,WAAW,CAAA;AAE3D,EAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,YAAA,CAAa,EAAA,EAAI;AAAA,IAC5D,kBAAA,EAAoB,GAAA;AAAA,IACpB,gBAAA,EAAkB,YAAA;AAAA,IAClB,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,MAAM,GAAA,CAAI,gBAAgB,aAAA,CAAc;AAAA,IACtC,YAAY,QAAA,CAAS,EAAA;AAAA,IACrB,gBAAgB,YAAA,CAAa,EAAA;AAAA,IAC7B,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,WAAA;AAAA,IACR,MAAA;AAAA,IACA,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,mBAAmB,YAAA,CAAa,iBAAA;AAAA,IAChC,QAAA,EAAU;AAAA,MACR,QAAA,EAAU,WAAA;AAAA,MACV,QAAA,EAAU;AAAA;AACZ,GACD,CAAA;AAED,EAAA,GAAA,CAAI,MAAA,CAAO,KAAK,mBAAA,EAAqB;AAAA,IACnC,gBAAgB,YAAA,CAAa,EAAA;AAAA,IAC7B,MAAA;AAAA,IACA,YAAA,EAAc,aAAa,WAAA;AAAY,GACxC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,gBAAgB,YAAA,CAAa,EAAA;AAAA,IAC7B,YAAY,QAAA,CAAS,UAAA;AAAA,IACrB,MAAA,EAAQ,WAAA;AAAA,IACR,MAAA;AAAA,IACA,WAAA,EAAa,cACT,EAAE,IAAA,EAAM,aAAa,QAAA,EAAU,EAAA,EAAI,aAAY,GAC/C;AAAA,GACN;AACF;AAcA,eAAsB,eAAA,CACpB,GAAA,EACA,MAAA,GAAgC,EAAC,EACD;AAChC,EAAA,MAAM,EAAE,MAAA,GAAS,KAAA,EAAM,GAAI,MAAA;AAE3B,EAAA,GAAA,CAAI,MAAA,CAAO,KAAK,6BAAA,EAA+B;AAAA,IAC7C,MAAA;AAAA,IACA,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,OAAO,MAAA,CAAO;AAAA,GACf,CAAA;AAGD,EAAA,MAAM,gBAAA,GAAmB,MAAM,oBAAA,CAAqB,GAAA,EAAK,MAAM,CAAA;AAE/D,EAAA,GAAA,CAAI,MAAA,CAAO,IAAA;AAAA,IACT,CAAA,MAAA,EAAS,iBAAiB,MAAM,CAAA,8BAAA;AAAA,GAClC;AAEA,EAAA,MAAM,MAAA,GAAgC;AAAA,IACpC,SAAA,EAAW,CAAA;AAAA,IACX,SAAA,EAAW,CAAA;AAAA,IACX,MAAA,EAAQ,CAAA;AAAA,IACR,OAAA,EAAS,CAAA;AAAA,IACT,UAAU;AAAC,GACb;AAGA,EAAA,KAAA,MAAW,gBAAgB,gBAAA,EAAkB;AAC3C,IAAA,MAAA,CAAO,SAAA,EAAA;AAEP,IAAA,IAAI;AACF,MAAA,MAAM,gBAAgB,MAAM,0BAAA;AAAA,QAC1B,GAAA;AAAA,QACA,YAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,MAAA,CAAO,QAAA,CAAS,KAAK,aAAa,CAAA;AAElC,MAAA,IAAI,aAAA,CAAc,WAAW,WAAA,EAAa;AACxC,QAAA,MAAA,CAAO,SAAA,EAAA;AAAA,MACT,CAAA,MAAA,IAAW,aAAA,CAAc,MAAA,KAAW,QAAA,EAAU;AAC5C,QAAA,MAAA,CAAO,MAAA,EAAA;AAAA,MACT,CAAA,MAAO;AACL,QAAA,MAAA,CAAO,OAAA,EAAA;AAAA,MACT;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,GAAA,CAAI,MAAA,CAAO,MAAM,0BAAA,EAA4B;AAAA,QAC3C,gBAAgB,YAAA,CAAa,EAAA;AAAA,QAC7B,OAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK;AAAA,OAC7D,CAAA;AAED,MAAA,MAAA,CAAO,MAAA,EAAA;AACP,MAAA,MAAA,CAAO,SAAS,IAAA,CAAK;AAAA,QACnB,gBAAgB,YAAA,CAAa,EAAA;AAAA,QAC7B,YAAY,YAAA,CAAa,UAAA;AAAA,QACzB,MAAA,EAAQ,QAAA;AAAA,QACR,KAAA,EAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU;AAAA,OACjD,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,GAAA,CAAI,MAAA,CAAO,KAAK,6BAAA,EAA+B;AAAA,IAC7C,WAAW,MAAA,CAAO,SAAA;AAAA,IAClB,WAAW,MAAA,CAAO,SAAA;AAAA,IAClB,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,SAAS,MAAA,CAAO;AAAA,GACjB,CAAA;AAED,EAAA,OAAO,MAAA;AACT;;;AC5cA,IAAM,0BAAA,GAA6BH,EAAE,MAAA,CAAO;AAAA;AAAA;AAAA;AAAA,EAI1C,UAAA,EAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA;AAAA;AAAA;AAAA,EAKhC,MAAA,EAAQA,CAAAA,CACL,MAAA,EAAO,CACP,SAAA,CAAU,CAAC,GAAA,KAAQ,GAAA,KAAQ,MAAM,CAAA,CACjC,QAAA,EAAS;AAAA;AAAA;AAAA;AAAA,EAKZ,KAAA,EAAOA,EACJ,MAAA,EAAO,CACP,UAAU,CAAC,GAAA,KAAQ,MAAA,CAAO,QAAA,CAAS,GAAA,EAAK,EAAE,CAAC,CAAA,CAC3C,MAAA,CAAO,CAAC,GAAA,KAAQ,CAAC,OAAO,KAAA,CAAM,GAAG,CAAA,IAAK,GAAA,GAAM,CAAA,EAAG;AAAA,IAC9C,OAAA,EAAS;AAAA,GACV,EACA,QAAA;AACL,CAAC,CAAA;AAmBM,IAAM,gBAAA,GAAoD;AAAA,EAC/D,eAAA,EAAiB;AAAA,IACf,IAAA,EAAM,WAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAO;AAAA,KACT;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KAIG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,KAAA,EAAM,GAAI,OAAA;AAEvB,MAAA,MAAM,MAAA,GAAS,MAAM,eAAA,CAAgB,GAAA,EAAuB;AAAA,QAC1D,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,MAAA,EAAQ,MAAM,MAAA,IAAU,KAAA;AAAA,QACxB,OAAO,KAAA,CAAM;AAAA,OACd,CAAA;AAED,MAAA,OAAO,MAAA;AAAA,IACT;AAAA;AAEJ,CAAA;AC/DA,IAAM,0BAAA,GAA6BA,EAAE,MAAA,CAAO;AAAA,EAC1C,UAAA,EAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC;AAC9B,CAAC,CAAA;AAMD,IAAM,wBAAA,GAA2BA,EAAE,MAAA,CAAO;AAAA,EACxC,UAAA,EAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC5B,QAAA,EAAUA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC1B,QAAA,EAAUA,CAAAA,CAAE,IAAA,CAAK,CAAC,SAAA,EAAW,QAAQ,CAAC,CAAA,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQ,SAAS,CAAA;AAAA,EACpE,YAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,GAAM,QAAA,EAAS;AAAA,EACtC,WAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,GAAA,GAAM,QAAA;AAC9B,CAAC,CAAA;AAKD,IAAM,wBAAA,GAA2BA,EAAE,MAAA,CAAO;AAAA,EACxC,UAAA,EAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC5B,QAAA,EAAUA,CAAAA,CACP,IAAA,CAAK,CAAC,YAAA,EAAc,aAAa,CAAC,CAAA,CAClC,QAAA,EAAS,CACT,OAAA,CAAQ,YAAY;AACzB,CAAC,CAAA;AAKD,IAAM,wBAAA,GAA2BA,EAAE,MAAA,CAAO;AAAA,EACxC,UAAA,EAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA,EAC5B,WAAA,EAAaA,CAAAA,CAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7B,SAASA,CAAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CAAE,QAAQ,IAAI;AAC9C,CAAC,CAAA;AAKM,IAAM,qBAAA,GAAyD;AAAA,EACpE,eAAA,EAAiB;AAAA,IACf,IAAA,EAAM,eAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAO;AAAA,KACT;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KAIG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,KAAA,EAAM,GAAI,OAAA;AAGvB,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,wBAAA;AAAA,QACzC,KAAA,CAAM;AAAA,OACR;AACA,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAO,EAAE,cAAc,IAAA,EAAK;AAAA,MAC9B;AAGA,MAAA,MAAM,eACJ,MAAM,GAAA,CAAI,eAAA,CAAgB,4BAAA,CAA6B,SAAS,EAAE,CAAA;AACpE,MAAA,IAAI,CAAC,YAAA,EAAc;AACjB,QAAA,OAAO,EAAE,cAAc,IAAA,EAAK;AAAA,MAC9B;AAGA,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,aAAa,QAAQ,CAAA;AACrE,MAAA,MAAM,KAAA,GAAQ,IAAA,GACV,GAAA,CAAI,eAAA,CAAgB,YAAA;AAAA,QAClB,YAAA,CAAa,QAAA;AAAA,QACb,YAAA,CAAa;AAAA,OACf,GACA,IAAA;AAEJ,MAAA,OAAO;AAAA,QACL,YAAA;AAAA,QACA,IAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAAA,GACF;AAAA,EAEA,kBAAA,EAAoB;AAAA,IAClB,IAAA,EAAM,eAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACR;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KACG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,IAAA,EAAK,GAAI,OAAA;AAGtB,MAAA,OAAO,mBAA0B,GAAA,EAAuB;AAAA,QACtD,YAAY,IAAA,CAAK,UAAA;AAAA,QACjB,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,YAAY,IAAA,CAAK,UAAA;AAAA,QACjB,WAAW,IAAA,CAAK;AAAA,OACjB,CAAA;AAAA,IACH;AAAA,GACF;AAAA,EAEA,kBAAA,EAAoB;AAAA,IAClB,IAAA,EAAM,sBAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACR;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KACG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,IAAA,EAAK,GAAI,OAAA;AAGtB,MAAA,OAAO,WAAA,CAAY,KAAuB,sBAAA,EAAwB;AAAA,QAChE,YAAY,IAAA,CAAK,UAAA;AAAA,QACjB,UAAU,IAAA,CAAK;AAAA,OAChB,CAAA;AAAA,IACH;AAAA,GACF;AAAA,EAEA,kBAAA,EAAoB;AAAA,IAClB,IAAA,EAAM,sBAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM;AAAA,KACR;AAAA,IACA,OAAA,EAAS,OACP,OAAA,KACG;AACH,MAAA,MAAM,EAAE,GAAA,EAAK,IAAA,EAAK,GAAI,OAAA;AACtB,MAAA,MAAM,UAAA,GAAa,GAAA;AACnB,MAAA,OAAO,kBAAA,CAA0B,YAAY,IAAI,CAAA;AAAA,IACnD;AAAA;AAEJ,CAAA;;;ACvJO,IAAM,gBAAA,GAAoD;AAAA,EAC/D,aAAA,EAAe;AAAA,IACb,IAAA,EAAM,UAAA;AAAA,IACN,OAAA,EAAS;AAAA,MACP,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,OAAA,EAAS,OAAO,OAAA,KAAuD;AACrE,MAAA,MAAM,EAAE,GAAA,EAAK,OAAA,EAAQ,GAAI,OAAA;AAEzB,MAAA,IAAI,CAAC,IAAI,cAAA,EAAgB;AACvB,QAAA,MAAM,IAAI,MAAM,gCAAgC,CAAA;AAAA,MAClD;AAGA,MAAA,IAAI,CAAC,GAAA,CAAI,cAAA,CAAe,cAAA,EAAgB;AAEtC,QAAA,GAAA,CAAI,MAAA,CAAO,MAAM,iDAAiD,CAAA;AAClE,QAAA,OAAO,EAAE,UAAU,IAAA,EAAK;AAAA,MAC1B;AAGA,MAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,cAAA,CAAe,eAAe,OAAO,CAAA;AAG9D,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,GAAA,CAAI,MAAA,CAAO,MAAM,8CAA8C,CAAA;AAC/D,QAAA,OAAO,EAAE,UAAU,IAAA,EAAK;AAAA,MAC1B;AAEA,MAAA,GAAA,CAAI,MAAA,CAAO,MAAM,+BAAA,EAAiC;AAAA,QAChD,gBAAgB,MAAA,CAAO,cAAA;AAAA,QACvB,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,QAAQ,MAAA,CAAO;AAAA,OAChB,CAAA;AAED,MAAA,IAAI,MAAA,CAAO,WAAW,QAAA,EAAU;AAE9B,QAAA,MAAM,YAAA,GAAe,MAAM,GAAA,CAAI,eAAA,CAAgB,oBAAA;AAAA,UAC7C,MAAA,CAAO;AAAA,SACT;AAEA,QAAA,IAAI,YAAA,EAAc;AAEhB,UAAA,MAAM,qBAAA,GACJ,MAAM,GAAA,CAAI,eAAA,CAAgB,iBAAA;AAAA,YACxB,YAAA,CAAa;AAAA,WACf;AAEF,UAAA,KAAA,MAAW,YAAY,qBAAA,EAAuB;AAC5C,YAAA,IACE,QAAA,CAAS,OAAO,YAAA,CAAa,EAAA,KAC5B,SAAS,MAAA,KAAW,QAAA,IAAY,QAAA,CAAS,MAAA,KAAW,UAAA,CAAA,EACrD;AACA,cAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,QAAA,CAAS,EAAE,CAAA;AACxD,cAAA,GAAA,CAAI,MAAA,CAAO,KAAK,gCAAA,EAAkC;AAAA,gBAChD,gBAAgB,QAAA,CAAS,EAAA;AAAA,gBACzB,UAAU,QAAA,CAAS;AAAA,eACpB,CAAA;AAAA,YACH;AAAA,UACF;AAGA,UAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,YAAA,CAAa,EAAA,EAAI;AAAA,YAC5D,MAAA,EAAQ,QAAA;AAAA,YACR,wBAAwB,MAAA,CAAO;AAAA,WAChC,CAAA;AAGD,UAAA,IAAI,OAAO,kBAAA,EAAoB;AAC7B,YAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,gBAAA;AAAA,cACzC,YAAA,CAAa;AAAA,aACf;AACA,YAAA,IAAI,QAAA,IAAY,CAAC,QAAA,CAAS,kBAAA,EAAoB;AAC5C,cAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,QAAA,CAAS,EAAA,EAAI;AAAA,gBACpD,oBAAoB,MAAA,CAAO;AAAA,eAC5B,CAAA;AAAA,YACH;AAAA,UACF;AAGA,UAAA,IAAI,MAAA,CAAO,MAAA,IAAU,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG;AACtC,YAAA,MAAM,GAAA,CAAI,gBAAgB,aAAA,CAAc;AAAA,cACtC,YAAY,YAAA,CAAa,UAAA;AAAA,cACzB,gBAAgB,YAAA,CAAa,EAAA;AAAA,cAC7B,IAAA,EAAM,cAAA;AAAA,cACN,MAAA,EAAQ,WAAA;AAAA,cACR,QAAQ,MAAA,CAAO,MAAA;AAAA,cACf,QAAA,EAAU,OAAO,QAAA,IAAY,KAAA;AAAA,cAC7B,mBAAmB,MAAA,CAAO,iBAAA;AAAA,cAC1B,QAAA,EAAU;AAAA,gBACR,UAAU,YAAA,CAAa,QAAA;AAAA,gBACvB,UAAU,YAAA,CAAa,QAAA;AAAA,gBACvB,YAAA,EAAc;AAAA;AAChB,aACD,CAAA;AAED,YAAA,GAAA,CAAI,MAAA,CAAO,KAAK,wBAAA,EAA0B;AAAA,cACxC,gBAAgB,YAAA,CAAa,EAAA;AAAA,cAC7B,QAAQ,MAAA,CAAO,MAAA;AAAA,cACf,UAAU,MAAA,CAAO,QAAA;AAAA,cACjB,mBAAmB,MAAA,CAAO;AAAA,aAC3B,CAAA;AAAA,UACH;AAEA,UAAA,GAAA,CAAI,MAAA,CAAO,KAAK,oCAAA,EAAsC;AAAA,YACpD,gBAAgB,YAAA,CAAa,EAAA;AAAA,YAC7B,wBAAwB,MAAA,CAAO;AAAA,WAChC,CAAA;AAAA,QACH,CAAA,MAAO;AACL,UAAA,GAAA,CAAI,MAAA,CAAO,KAAK,yCAAA,EAA2C;AAAA,YACzD,gBAAgB,MAAA,CAAO;AAAA,WACxB,CAAA;AAAA,QACH;AAAA,MACF,CAAA,MAAA,IAAW,MAAA,CAAO,MAAA,KAAW,QAAA,EAAU;AAErC,QAAA,MAAM,YAAA,GAAe,MAAM,GAAA,CAAI,eAAA,CAAgB,oBAAA;AAAA,UAC7C,MAAA,CAAO;AAAA,SACT;AAEA,QAAA,IAAI,YAAA,EAAc;AAChB,UAAA,MAAM,GAAA,CAAI,eAAA,CAAgB,kBAAA,CAAmB,YAAA,CAAa,EAAA,EAAI;AAAA,YAC5D,MAAA,EAAQ;AAAA,WACT,CAAA;AACD,UAAA,GAAA,CAAI,MAAA,CAAO,KAAK,uCAAA,EAAyC;AAAA,YACvD,gBAAgB,YAAA,CAAa;AAAA,WAC9B,CAAA;AAAA,QACH;AAAA,MACF;AAEA,MAAA,OAAO,EAAE,UAAU,IAAA,EAAK;AAAA,IAC1B;AAAA;AAEJ,CAAA;;;AC3HO,SAAS,aACd,GAAA,EACiC;AACjC,EAAA,MAAM,aAAA,GAAiD;AAAA,IACrD,GAAG,cAAA;AAAA,IACH,GAAG,iBAAA;AAAA,IACH,GAAG,aAAA;AAAA,IACH,GAAG,qBAAA;AAAA,IACH,GAAG,gBAAA;AAAA,IACH,GAAG,gBAAA;AAAA,IACH,GAAG,eAAA;AAAA,IACH,GAAG,gBAAA;AAAA,IACH,GAAG;AAAA,GACL;AAGA,EAAA,IAAI,YAAA,GAAe,EAAE,GAAG,aAAA,EAAc;AACtC,EAAA,KAAA,MAAW,MAAA,IAAU,IAAI,OAAA,EAAS;AAChC,IAAA,IAAI,OAAO,SAAA,EAAW;AACpB,MAAA,YAAA,GAAe,EAAE,GAAG,YAAA,EAAc,GAAG,OAAO,SAAA,EAAU;AAAA,IACxD;AAAA,EACF;AAEA,EAAA,OAAO,YAAA;AACT;AAKA,SAAS,QAAA,CACP,KACA,QAAA,EAC0C;AAC1C,EAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,GAAG,CAAA;AAC1B,EAAA,IAAI,OAAO,MAAA,CAAO,QAAA;AAGlB,EAAA,IAAI,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC7B,IAAA,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,MAAM,CAAA;AAAA,EACnC;AAGA,EAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG;AACzB,IAAA,IAAA,GAAO,IAAI,IAAI,CAAA,CAAA;AAAA,EACjB;AAEA,EAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,MAAA,CAAO,YAAA,EAAa;AAC5C;AAKA,SAAS,cAAc,KAAA,EAAgD;AACrE,EAAA,MAAM,MAA8B,EAAC;AACrC,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AAC5B,IAAA,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AAAA,EACb,CAAC,CAAA;AACD,EAAA,OAAO,GAAA;AACT;AAKA,SAAS,YAAA,CAAa,IAAA,EAAe,MAAA,GAAS,GAAA,EAAe;AAC3D,EAAA,OAAO,IAAI,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AAAA,IACxC,MAAA;AAAA,IACA,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB;AAAA;AAClB,GACD,CAAA;AACH;AAKA,SAAS,aAAA,CAAc,IAAA,EAAc,OAAA,EAAiB,MAAA,GAAS,GAAA,EAAe;AAC5E,EAAA,OAAO,YAAA,CAAa,EAAE,KAAA,EAAO,EAAE,MAAM,OAAA,EAAQ,IAAK,MAAM,CAAA;AAC1D;AAKO,SAAS,aAAa,GAAA,EAG3B;AACA,EAAA,MAAM,SAAA,GAAY,aAAa,GAAG,CAAA;AAElC,EAAA,MAAM,OAAA,GAAU,OAAO,OAAA,KAAwC;AAC7D,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,WAAA,EAAY;AAC1C,IAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,SAAS,OAAA,CAAQ,GAAA,EAAK,IAAI,QAAQ,CAAA;AAE1D,IAAA,GAAA,CAAI,OAAO,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,CAAA;AAGpC,IAAA,IAAI,GAAA,CAAI,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAQ;AAC5B,MAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,OAAA,CAAQ,MAAM,MAAA,CAAO;AAAA,QAC5C,OAAA;AAAA,QACA,IAAA;AAAA,QACA;AAAA,OACD,CAAA;AACD,MAAA,IAAI,kBAAkB,QAAA,EAAU;AAC9B,QAAA,OAAO,MAAA;AAAA,MACT;AAAA,IACF;AAGA,IAAA,KAAA,MAAW,MAAA,IAAU,IAAI,OAAA,EAAS;AAChC,MAAA,IAAI,MAAA,CAAO,OAAO,MAAA,EAAQ;AACxB,QAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,MAAA,EAAQ;AACtC,UAAA,IAAI,KAAK,OAAA,CAAQ,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAA,EAAG;AAClC,YAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ;AAAA,cAChC,OAAA;AAAA,cACA,IAAA;AAAA,cACA,MAAA;AAAA,cACA,cAAA,EAAgB;AAAA,aACjB,CAAA;AACD,YAAA,IAAI,kBAAkB,QAAA,EAAU;AAC9B,cAAA,OAAO,MAAA;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,IAAA,MAAM,cAAc,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA,CAAE,IAAA,CAAK,CAAC,GAAA,KAAQ;AACvD,MAAA,MAAMI,SAAAA,GAAW,UAAU,GAAG,CAAA;AAC9B,MAAA,IAAI,CAACA,WAAU,OAAO,KAAA;AAGtB,MAAA,IAAIA,SAAAA,CAAS,OAAA,CAAQ,MAAA,KAAW,MAAA,EAAQ,OAAO,KAAA;AAI/C,MAAA,OAAOA,UAAS,IAAA,KAAS,IAAA;AAAA,IAC3B,CAAC,CAAA;AAED,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,OAAO,aAAA;AAAA,QACL,WAAA;AAAA,QACA,CAAA,sBAAA,EAAyB,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAAA,QACvC;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,UAAU,WAAW,CAAA;AAEtC,IAAA,IAAI;AACF,MAAA,MAAM,iBAAA,GAAoB,QAAQ,KAAA,EAAM;AAGxC,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI,CAAC,MAAA,EAAQ,KAAA,EAAO,OAAO,CAAA,CAAE,SAAS,MAAM,CAAA,IAAK,QAAA,CAAS,OAAA,CAAQ,IAAA,EAAM;AACtE,QAAA,IAAI;AACF,UAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,IAAA,EAAK;AAChC,UAAA,IAAI,IAAA,EAAM;AACR,YAAA,IAAA,GAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,UACxB;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AAGA,MAAA,IAAI,QAAA,CAAS,OAAA,CAAQ,IAAA,IAAQ,IAAA,EAAM;AACjC,QAAA,MAAM,MAAA,GAAS,QAAA,CAAS,OAAA,CAAQ,IAAA,CAAK,UAAU,IAAI,CAAA;AACnD,QAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,UAAA,MAAM,SAAS,QAAA,IAAY,MAAA,CAAO,QAAQ,MAAA,CAAO,KAAA,CAAM,SAAS,EAAC;AACjE,UAAA,OAAO,aAAA;AAAA,YACL,kBAAA;AAAA,YACC,MAAA,CACE,IAAI,CAAC,CAAA,KAAM,EAAE,OAAO,CAAA,CACpB,KAAK,IAAI,CAAA;AAAA,YACZ;AAAA,WACF;AAAA,QACF;AACA,QAAA,IAAA,GAAO,MAAA,CAAO,IAAA;AAAA,MAChB;AAGA,MAAA,IAAI,QAAA,GAAmC,cAAc,KAAK,CAAA;AAC1D,MAAA,IAAI,QAAA,CAAS,QAAQ,KAAA,EAAO;AAC1B,QAAA,MAAM,MAAA,GAAS,QAAA,CAAS,OAAA,CAAQ,KAAA,CAAM,UAAU,QAAQ,CAAA;AACxD,QAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,UAAA,MAAM,SAAS,QAAA,IAAY,MAAA,CAAO,QAAQ,MAAA,CAAO,KAAA,CAAM,SAAS,EAAC;AACjE,UAAA,OAAO,aAAA;AAAA,YACL,kBAAA;AAAA,YACC,MAAA,CACE,IAAI,CAAC,CAAA,KAAM,EAAE,OAAO,CAAA,CACpB,KAAK,IAAI,CAAA;AAAA,YACZ;AAAA,WACF;AAAA,QACF;AACA,QAAA,QAAA,GAAW,MAAA,CAAO,IAAA;AAAA,MACpB;AAIA,MAAA,MAAM,eAAA,GAAkB;AAAA,QACtB,OAAA,EAAS,iBAAA;AAAA,QACT,IAAA;AAAA,QACA,KAAA,EAAO,QAAA;AAAA,QACP,SAAS,iBAAA,CAAkB,OAAA;AAAA,QAC3B,QAAQ,EAAC;AAAA,QACT;AAAA;AAAA,OACF;AAIA,MAAA,MAAM,QAAA,GAAW,MAAM,QAAA,CAAS,OAAA,CAAQ,eAAsB,CAAA;AAG9D,MAAA,IAAI,aAAA,GAAgB,aAAa,QAAQ,CAAA;AAGzC,MAAA,KAAA,MAAW,MAAA,IAAU,IAAI,OAAA,EAAS;AAChC,QAAA,IAAI,MAAA,CAAO,OAAO,KAAA,EAAO;AACvB,UAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,KAAA,CAAM,KAAA,EAAO;AACrC,YAAA,IAAI,KAAK,OAAA,CAAQ,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAA,EAAG;AAClC,cAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ;AAAA,gBAChC,OAAA;AAAA,gBACA,IAAA;AAAA,gBACA,MAAA;AAAA,gBACA,cAAA,EAAgB;AAAA,eACjB,CAAA;AACD,cAAA,IAAI,kBAAkB,QAAA,EAAU;AAC9B,gBAAA,aAAA,GAAgB,MAAA;AAAA,cAClB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,GAAA,CAAI,OAAA,CAAQ,KAAA,CAAM,KAAA,EAAO;AAC3B,QAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,OAAA,CAAQ,MAAM,KAAA,CAAM;AAAA,UAC3C,OAAA;AAAA,UACA,IAAA;AAAA,UACA;AAAA,SACD,CAAA;AACD,QAAA,IAAI,kBAAkB,QAAA,EAAU;AAC9B,UAAA,aAAA,GAAgB,MAAA;AAAA,QAClB;AAAA,MACF;AAEA,MAAA,OAAO,aAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,GAAA,CAAI,MAAA,CAAO,KAAA,CAAM,gBAAA,EAAkB,KAAK,CAAA;AAExC,MAAA,IAAI,iBAAiB,KAAA,EAAO;AAC1B,QAAA,OAAO,aAAA,CAAc,gBAAA,EAAkB,KAAA,CAAM,OAAA,EAAS,GAAG,CAAA;AAAA,MAC3D;AAEA,MAAA,OAAO,aAAA;AAAA,QACL,gBAAA;AAAA,QACA,8BAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,EAAE,SAAS,SAAA,EAAU;AAC9B;;;ACrMA,SAAS,iBAAiB,MAAA,EAA0B;AAClD,EAAA,OAAO;AAAA,IACL,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,QAAA,EAAU,OAAO,QAAA,IAAY,IAAA;AAAA,IAC7B,MAAA,EAAQ,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MAChC,QAAQ,CAAA,CAAE,MAAA;AAAA,MACV,QAAA,EAAU,EAAE,QAAA,IAAY,KAAA;AAAA,MACxB,UAAU,CAAA,CAAE,QAAA;AAAA,MACZ,WAAW,CAAA,CAAE;AAAA,KACf,CAAE,CAAA;AAAA,IACF,QAAA,EAAU,MAAA,CAAO,QAAA,IAAY;AAAC,GAChC;AACF;AAKA,SAAS,uBAAuB,MAAA,EAAgC;AAC9D,EAAA,OAAO;AAAA,IACL,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,IAAA,EAAM,OAAO,IAAA,IAAQ;AAAA,GACvB;AACF;AAKO,SAAS,qBAAA,CACd,OAAA,EACA,KAAA,GAAsB,EAAC,EACvB,QAAA,GAA4B,EAAC,EAC7B,MAAA,GAA8B,4BAAY,IAAI,IAAA,EAAK,EAClC;AAEjB,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAkB;AAC1C,EAAA,KAAA,MAAW,UAAU,KAAA,EAAO;AAC1B,IAAA,WAAA,CAAY,GAAA,CAAI,MAAA,CAAO,IAAA,EAAM,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAAA,EACvD;AAEA,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAqB;AAChD,EAAA,KAAA,MAAW,UAAU,QAAA,EAAU;AAC7B,IAAA,cAAA,CAAe,GAAA,CAAI,MAAA,CAAO,IAAA,EAAM,sBAAA,CAAuB,MAAM,CAAC,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO;AAAA;AAAA,IAEL,MAAM,eAAe,IAAA,EAA8C;AACjE,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,EAAO;AACzB,MAAA,OAAO,QAAQ,MAAA,CAAiB;AAAA,QAC9B,OAAO,MAAA,CAAO,QAAA;AAAA,QACd,IAAA,EAAM;AAAA,UACJ,GAAG,IAAA;AAAA,UACH,SAAA,EAAW,GAAA;AAAA,UACX,SAAA,EAAW;AAAA;AACb,OACD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,iBAAiB,EAAA,EAAsC;AAC3D,MAAA,OAAO,QAAQ,OAAA,CAAkB;AAAA,QAC/B,OAAO,MAAA,CAAO,QAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,MAAM,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI;AAAA,OACnD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,yBACJ,UAAA,EAC0B;AAC1B,MAAA,OAAO,QAAQ,OAAA,CAAkB;AAAA,QAC/B,OAAO,MAAA,CAAO,QAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,cAAc,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,UAAA,EAAY;AAAA,OACnE,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,cAAA,CACJ,EAAA,EACA,IAAA,EAC0B;AAC1B,MAAA,OAAO,QAAQ,MAAA,CAAiB;AAAA,QAC9B,OAAO,MAAA,CAAO,QAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,MAAM,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI,CAAA;AAAA,QAClD,QAAQ,EAAE,GAAG,MAAM,SAAA,kBAAW,IAAI,MAAK;AAAE,OAC1C,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,eAAe,EAAA,EAA2B;AAC9C,MAAA,MAAM,QAAQ,MAAA,CAAO;AAAA,QACnB,OAAO,MAAA,CAAO,QAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,MAAM,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI;AAAA,OACnD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,cAAc,OAAA,EAGI;AACtB,MAAA,OAAO,QAAQ,QAAA,CAAmB;AAAA,QAChC,OAAO,MAAA,CAAO,QAAA;AAAA,QACd,OAAO,OAAA,EAAS,KAAA;AAAA,QAChB,QAAQ,OAAA,EAAS,MAAA;AAAA,QACjB,MAAA,EAAQ,EAAE,KAAA,EAAO,WAAA,EAAa,WAAW,MAAA;AAAO,OACjD,CAAA;AAAA,IACH,CAAA;AAAA;AAAA,IAGA,eAAe,IAAA,EAA2B;AACxC,MAAA,OAAO,WAAA,CAAY,GAAA,CAAI,IAAI,CAAA,IAAK,IAAA;AAAA,IAClC,CAAA;AAAA,IAEA,UAAU,OAAA,EAAgD;AACxD,MAAA,MAAM,QAAA,GAAW,KAAA,CAAM,IAAA,CAAK,WAAA,CAAY,QAAQ,CAAA;AAChD,MAAA,IAAI,SAAS,cAAA,EAAgB;AAC3B,QAAA,OAAO,QAAA;AAAA,MACT;AACA,MAAA,OAAO,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AAAA,IAC1C,CAAA;AAAA,IAEA,YAAA,CACE,UACA,QAAA,EACkB;AAClB,MAAA,MAAM,IAAA,GAAO,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAA;AACrC,MAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,MAAA,OACE,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,QAAQ,CAAA,IAC/C,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,IACb,IAAA;AAAA,IAEJ,CAAA;AAAA;AAAA,IAGA,kBAAkB,IAAA,EAA8B;AAC9C,MAAA,OAAO,cAAA,CAAe,GAAA,CAAI,IAAI,CAAA,IAAK,IAAA;AAAA,IACrC,CAAA;AAAA,IAEA,YAAA,GAA0B;AACxB,MAAA,OAAO,KAAA,CAAM,IAAA,CAAK,cAAA,CAAe,MAAA,EAAQ,CAAA;AAAA,IAC3C,CAAA;AAAA,IAEA,gBAAgB,QAAA,EAA4B;AAC1C,MAAA,MAAM,IAAA,GAAO,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAA;AACrC,MAAA,OAAO,IAAA,EAAM,YAAY,EAAC;AAAA,IAC5B,CAAA;AAAA;AAAA,IAGA,MAAM,mBACJ,IAAA,EACuB;AACvB,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,EAAO;AACzB,MAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,SAAA;AAClC,MAAA,MAAM,gBAAA,GAAmB,IAAI,IAAA,CAAK,GAAG,CAAA;AAGrC,MAAA,IAAI,aAAa,QAAA,EAAU;AACzB,QAAA,gBAAA,CAAiB,WAAA,CAAY,gBAAA,CAAiB,WAAA,EAAY,GAAI,CAAC,CAAA;AAAA,MACjE,CAAA,MAAA,IAAW,aAAa,WAAA,EAAa;AACnC,QAAA,gBAAA,CAAiB,QAAA,CAAS,gBAAA,CAAiB,QAAA,EAAS,GAAI,CAAC,CAAA;AAAA,MAC3D,CAAA,MAAO;AACL,QAAA,gBAAA,CAAiB,QAAA,CAAS,gBAAA,CAAiB,QAAA,EAAS,GAAI,CAAC,CAAA;AAAA,MAC3D;AAEA,MAAA,IAAI,UAAA;AACJ,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI,MAAA,GAAS,KAAK,MAAA,IAAU,iBAAA;AAE5B,MAAA,IAAI,IAAA,CAAK,SAAA,IAAa,IAAA,CAAK,SAAA,GAAY,CAAA,EAAG;AACxC,QAAA,UAAA,GAAa,GAAA;AACb,QAAA,QAAA,GAAW,IAAI,KAAK,GAAG,CAAA;AACvB,QAAA,QAAA,CAAS,OAAA,CAAQ,QAAA,CAAS,OAAA,EAAQ,GAAI,KAAK,SAAS,CAAA;AACpD,QAAA,MAAA,GAAS,UAAA;AAAA,MACX;AAEA,MAAA,OAAO,QAAQ,MAAA,CAAqB;AAAA,QAClC,OAAO,MAAA,CAAO,YAAA;AAAA,QACd,IAAA,EAAM;AAAA,UACJ,YAAY,IAAA,CAAK,UAAA;AAAA,UACjB,UAAU,IAAA,CAAK,QAAA;AAAA,UACf,QAAA;AAAA,UACA,MAAA;AAAA,UACA,wBAAwB,IAAA,CAAK,sBAAA;AAAA,UAC7B,2BAA2B,IAAA,CAAK,yBAAA;AAAA,UAChC,kBAAA,EAAoB,GAAA;AAAA,UACpB,kBAAkB,QAAA,IAAY,gBAAA;AAAA,UAC9B,UAAA;AAAA,UACA,QAAA;AAAA,UACA,UAAU,IAAA,CAAK,QAAA;AAAA,UACf,SAAA,EAAW,GAAA;AAAA,UACX,SAAA,EAAW;AAAA;AACb,OACD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,qBAAqB,EAAA,EAA0C;AACnE,MAAA,OAAO,QAAQ,OAAA,CAAsB;AAAA,QACnC,OAAO,MAAA,CAAO,YAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,MAAM,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI;AAAA,OACnD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,6BACJ,UAAA,EAC8B;AAC9B,MAAA,OAAO,QAAQ,OAAA,CAAsB;AAAA,QACnC,OAAO,MAAA,CAAO,YAAA;AAAA,QACd,KAAA,EAAO;AAAA,UACL,EAAE,KAAA,EAAO,YAAA,EAAc,QAAA,EAAU,IAAA,EAAM,OAAO,UAAA,EAAW;AAAA,UACzD;AAAA,YACE,KAAA,EAAO,QAAA;AAAA,YACP,QAAA,EAAU,IAAA;AAAA,YACV,KAAA,EAAO,CAAC,QAAA,EAAU,UAAA,EAAY,YAAY,iBAAiB;AAAA;AAC7D;AACF,OACD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,oCACJ,SAAA,EAC8B;AAC9B,MAAA,OAAO,QAAQ,OAAA,CAAsB;AAAA,QACnC,OAAO,MAAA,CAAO,YAAA;AAAA,QACd,KAAA,EAAO;AAAA,UACL;AAAA,YACE,KAAA,EAAO,2BAAA;AAAA,YACP,QAAA,EAAU,IAAA;AAAA,YACV,KAAA,EAAO;AAAA;AACT;AACF,OACD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,kBAAA,CACJ,EAAA,EACA,IAAA,EAC8B;AAC9B,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,EAAO;AACzB,MAAA,OAAO,QAAQ,MAAA,CAAqB;AAAA,QAClC,OAAO,MAAA,CAAO,YAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,MAAM,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI,CAAA;AAAA,QAClD,MAAA,EAAQ,EAAE,GAAG,IAAA,EAAM,WAAW,GAAA;AAAI,OACnC,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,kBAAA,CACJ,EAAA,EACA,QAAA,EAC8B;AAC9B,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,EAAO;AACzB,MAAA,OAAO,QAAQ,MAAA,CAAqB;AAAA,QAClC,OAAO,MAAA,CAAO,YAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,MAAM,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI,CAAA;AAAA,QAClD,MAAA,EAAQ;AAAA,UACN,MAAA,EAAQ,WAAW,QAAA,GAAW,UAAA;AAAA,UAC9B,UAAA,EAAY,GAAA;AAAA,UACZ,UAAU,QAAA,IAAY,GAAA;AAAA,UACtB,SAAA,EAAW;AAAA;AACb,OACD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,kBAAkB,UAAA,EAA6C;AACnE,MAAA,OAAO,QAAQ,QAAA,CAAuB;AAAA,QACpC,OAAO,MAAA,CAAO,YAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,cAAc,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,UAAA,EAAY,CAAA;AAAA,QAClE,MAAA,EAAQ,EAAE,KAAA,EAAO,WAAA,EAAa,WAAW,MAAA;AAAO,OACjD,CAAA;AAAA,IACH,CAAA;AAAA;AAAA,IAGA,MAAM,kBAAA,CACJ,UAAA,EACA,WAAA,EAC+B;AAE/B,MAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,OAAA,CAAkB;AAAA,QAC/C,OAAO,MAAA,CAAO,QAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,cAAc,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,UAAA,EAAY;AAAA,OACnE,CAAA;AAED,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAO,EAAE,SAAS,KAAA,EAAM;AAAA,MAC1B;AAGA,MAAA,MAAM,YAAA,GAAe,MAAM,OAAA,CAAQ,OAAA,CAAsB;AAAA,QACvD,OAAO,MAAA,CAAO,YAAA;AAAA,QACd,KAAA,EAAO;AAAA,UACL,EAAE,KAAA,EAAO,YAAA,EAAc,UAAU,IAAA,EAAM,KAAA,EAAO,SAAS,EAAA,EAAG;AAAA,UAC1D,EAAE,OAAO,QAAA,EAAU,QAAA,EAAU,MAAM,KAAA,EAAO,CAAC,QAAA,EAAU,UAAU,CAAA;AAAE;AACnE,OACD,CAAA;AAED,MAAA,IAAI,CAAC,YAAA,EAAc;AACjB,QAAA,OAAO,EAAE,SAAS,KAAA,EAAM;AAAA,MAC1B;AAGA,MAAA,MAAM,YAAA,GAAe,IAAA,CAAK,eAAA,CAAgB,YAAA,CAAa,QAAQ,CAAA;AAC/D,MAAA,OAAO,EAAE,OAAA,EAAS,YAAA,CAAa,QAAA,CAAS,WAAW,CAAA,EAAE;AAAA,IACvD,CAAA;AAAA;AAAA,IAGA,MAAM,cAAc,IAAA,EAA4C;AAC9D,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,EAAO;AACzB,MAAA,OAAO,QAAQ,MAAA,CAAgB;AAAA,QAC7B,OAAO,MAAA,CAAO,OAAA;AAAA,QACd,IAAA,EAAM;AAAA,UACJ,YAAY,IAAA,CAAK,UAAA;AAAA,UACjB,gBAAgB,IAAA,CAAK,cAAA;AAAA,UACrB,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,MAAA,EAAQ,KAAK,MAAA,IAAU,SAAA;AAAA,UACvB,QAAQ,IAAA,CAAK,MAAA;AAAA,UACb,QAAA,EAAU,KAAK,QAAA,IAAY,KAAA;AAAA,UAC3B,mBAAmB,IAAA,CAAK,iBAAA;AAAA,UACxB,UAAU,IAAA,CAAK,QAAA;AAAA,UACf,SAAA,EAAW,GAAA;AAAA,UACX,SAAA,EAAW;AAAA;AACb,OACD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,gBAAgB,EAAA,EAAqC;AACzD,MAAA,OAAO,QAAQ,OAAA,CAAiB;AAAA,QAC9B,OAAO,MAAA,CAAO,OAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,MAAM,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI;AAAA,OACnD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,+BACJ,iBAAA,EACyB;AACzB,MAAA,OAAO,QAAQ,OAAA,CAAiB;AAAA,QAC9B,OAAO,MAAA,CAAO,OAAA;AAAA,QACd,KAAA,EAAO;AAAA,UACL;AAAA,YACE,KAAA,EAAO,mBAAA;AAAA,YACP,QAAA,EAAU,IAAA;AAAA,YACV,KAAA,EAAO;AAAA;AACT;AACF,OACD,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,aAAA,CACJ,EAAA,EACA,IAAA,EACyB;AACzB,MAAA,OAAO,QAAQ,MAAA,CAAgB;AAAA,QAC7B,OAAO,MAAA,CAAO,OAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,MAAM,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI,CAAA;AAAA,QAClD,QAAQ,EAAE,GAAG,MAAM,SAAA,kBAAW,IAAI,MAAK;AAAE,OAC1C,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,YAAA,CACJ,UAAA,EACA,OAAA,EACoB;AACpB,MAAA,OAAO,QAAQ,QAAA,CAAkB;AAAA,QAC/B,OAAO,MAAA,CAAO,OAAA;AAAA,QACd,KAAA,EAAO,CAAC,EAAE,KAAA,EAAO,cAAc,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,UAAA,EAAY,CAAA;AAAA,QAClE,OAAO,OAAA,EAAS,KAAA;AAAA,QAChB,QAAQ,OAAA,EAAS,MAAA;AAAA,QACjB,MAAA,EAAQ,EAAE,KAAA,EAAO,WAAA,EAAa,WAAW,MAAA;AAAO,OACjD,CAAA;AAAA,IACH;AAAA,GACF;AACF;;;AClWA,SAAS,aAAa,OAAA,EAA2C;AAC/D,EAAA,MAAM,KAAA,GAAQ,SAAS,KAAA,IAAS,MAAA;AAChC,EAAA,MAAM,QAAA,GAAW,SAAS,QAAA,IAAY,KAAA;AAEtC,EAAA,MAAM,MAAA,GAAS,CAAC,OAAA,EAAS,MAAA,EAAQ,QAAQ,OAAO,CAAA;AAChD,EAAA,MAAM,iBAAA,GAAoB,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA;AAE9C,EAAA,MAAM,SAAA,GAAY,CAAC,QAAA,KAAqB;AACtC,IAAA,IAAI,UAAU,OAAO,KAAA;AACrB,IAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,IAAK,iBAAA;AAAA,EACrC,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,CAAC,OAAA,EAAA,GAAoB,IAAA,KAAoB;AAC9C,MAAA,IAAI,SAAA,CAAU,OAAO,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA,UAAA,EAAa,OAAO,CAAA,CAAA,EAAI,GAAG,IAAI,CAAA;AAAA,IACvE,CAAA;AAAA,IACA,IAAA,EAAM,CAAC,OAAA,EAAA,GAAoB,IAAA,KAAoB;AAC7C,MAAA,IAAI,SAAA,CAAU,MAAM,CAAA,EAAG,OAAA,CAAQ,KAAK,CAAA,UAAA,EAAa,OAAO,CAAA,CAAA,EAAI,GAAG,IAAI,CAAA;AAAA,IACrE,CAAA;AAAA,IACA,IAAA,EAAM,CAAC,OAAA,EAAA,GAAoB,IAAA,KAAoB;AAC7C,MAAA,IAAI,SAAA,CAAU,MAAM,CAAA,EAAG,OAAA,CAAQ,KAAK,CAAA,UAAA,EAAa,OAAO,CAAA,CAAA,EAAI,GAAG,IAAI,CAAA;AAAA,IACrE,CAAA;AAAA,IACA,KAAA,EAAO,CAAC,OAAA,EAAA,GAAoB,IAAA,KAAoB;AAC9C,MAAA,IAAI,SAAA,CAAU,OAAO,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA,UAAA,EAAa,OAAO,CAAA,CAAA,EAAI,GAAG,IAAI,CAAA;AAAA,IACvE;AAAA,GACF;AACF;AAKA,SAAS,cAAA,CACP,SACA,OAAA,EACwB;AACxB,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,OAAA;AAAA,IACV,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,QAAA,EAAU,QAAQ,QAAA,IAAY,cAAA;AAAA,IAC9B,MAAA,EAAQ,OAAA,CAAQ,MAAA,IAAU,qBAAA,EAAsB;AAAA,IAChD,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,OAAA,EAAS,OAAA,CAAQ,OAAA,IAAW,EAAC;AAAA,IAC7B,KAAA,EAAO,OAAA,CAAQ,KAAA,IAAS,EAAC;AAAA,IACzB,WAAW,OAAA,CAAQ,SAAA;AAAA,IACnB,MAAA,EAAQ;AAAA,MACN,KAAA,EAAO,OAAA,CAAQ,MAAA,EAAQ,KAAA,IAAS,MAAA;AAAA,MAChC,QAAA,EAAU,OAAA,CAAQ,MAAA,EAAQ,QAAA,IAAY;AAAA;AACxC,GACF;AACF;AAKA,SAAS,qBAAA,GAAgC;AACvC,EAAA,OAAO,iDAAA;AACT;AAKA,eAAsB,oBAAA,CACpB,SACA,OAAA,EACyB;AACzB,EAAA,MAAM,eAAA,GAAkB,cAAA,CAAe,OAAA,EAAS,OAAO,CAAA;AACvD,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,OAAA,CAAQ,MAAM,CAAA;AAC1C,EAAA,MAAM,UAAU,eAAA,CAAgB,OAAA;AAGhC,EAAA,IAAI,SAAS,gBAAA,EAAiB;AAG9B,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,MAAA,MAAA,GAAS,EAAE,GAAG,MAAA,EAAQ,GAAG,OAAO,MAAA,EAAO;AAAA,IACzC;AAAA,EACF;AAGA,EAAA,MAAM,MAAA,GAAS,4BAAY,IAAI,IAAA,EAAK;AAEpC,EAAA,MAAM,eAAA,GAAkB,qBAAA;AAAA,IACtB,OAAA;AAAA,IACA,OAAA,CAAQ,SAAS,EAAC;AAAA,IAClB,OAAA,CAAQ,YAAY,EAAC;AAAA,IACrB;AAAA,GACF;AAGA,EAAA,MAAM,OAAA,GAA0B;AAAA,IAC9B,OAAA,EAAS,eAAA;AAAA,IACT,UAAU,eAAA,CAAgB,QAAA;AAAA,IAC1B,OAAA;AAAA,IACA,gBAAgB,OAAA,CAAQ,OAAA;AAAA,IACxB,eAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA,QAAQ,eAAA,CAAgB,MAAA;AAAA,IACxB,cAAc,yBAAA,EAA0B;AAAA,IAExC,UAAU,EAAA,EAAqB;AAC7B,MAAA,OAAO,QAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AAAA,IACxC,CAAA;AAAA,IAEA,UAAmC,EAAA,EAAsB;AACvD,MAAA,MAAM,SAAS,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AAC9C,MAAA,OAAQ,MAAA,IAAgB,IAAA;AAAA,IAC1B,CAAA;AAAA,IAEA,UAAA,GAAqB;AACnB,MAAA,OAAO,OAAO,UAAA,EAAW;AAAA,IAC3B;AAAA,GACF;AAGA,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA,MAAM,MAAA,CAAO,KAAK,OAAO,CAAA;AAAA,IAC3B;AAAA,EACF;AAEA,EAAA,MAAA,CAAO,MAAM,wBAAA,EAA0B;AAAA,IACrC,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,SAAS,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,EAAE,CAAA;AAAA,IAChC,iBAAA,EAAmB,CAAC,CAAC,OAAA,CAAQ,cAAA;AAAA,IAC7B,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,MAAA,IAAU,CAAA;AAAA,IAChC,QAAA,EAAU,OAAA,CAAQ,QAAA,EAAU,MAAA,IAAU;AAAA,GACvC,CAAA;AAED,EAAA,OAAO,OAAA;AACT;;;ACjNA,IAAM,gBAAA,GAAmB;AAAA,EACvB,kBAAA,EAAoB,oBAAA;AAAA,EACpB,cAAA,EAAgB,gBAAA;AAAA,EAChB,sBAAA,EAAwB,wBAAA;AAAA,EACxB,iBAAA,EAAmB,mBAAA;AAAA,EACnB,8BAAA,EAAgC,gCAAA;AAAA,EAChC,eAAA,EAAiB,iBAAA;AAAA,EACjB,cAAA,EAAgB;AAClB,CAAA;AAMA,SAAS,UACP,cAAA,EAC2B;AAC3B,EAAA,OAAO;AAAA,IACL,MAAM,YAAY,MAAA,EAAQ;AACxB,MAAA,MAAM,MAAM,MAAM,cAAA;AAClB,MAAA,OAAO,GAAA,CAAI,eAAA,CAAgB,wBAAA,CAAyB,MAAA,CAAO,UAAU,CAAA;AAAA,IACvE,CAAA;AAAA,IAEA,MAAM,eAAe,IAAA,EAAM;AACzB,MAAA,MAAM,MAAM,MAAM,cAAA;AAClB,MAAA,OAAO,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,IAAI,CAAA;AAAA,IAChD,CAAA;AAAA,IAEA,MAAM,SAAA,GAAY;AAChB,MAAA,MAAM,MAAM,MAAM,cAAA;AAElB,MAAA,OAAO,GAAA,CAAI,gBAAgB,SAAA,EAAU;AAAA,IACvC,CAAA;AAAA,IAEA,MAAM,QAAQ,MAAA,EAAQ;AACpB,MAAA,MAAM,MAAM,MAAM,cAAA;AAElB,MAAA,OAAO,GAAA,CAAI,eAAA,CAAgB,cAAA,CAAe,MAAA,CAAO,IAAI,CAAA;AAAA,IACvD,CAAA;AAAA,IAEA,MAAM,gBAAgB,MAAA,EAAQ;AAC5B,MAAA,MAAM,MAAM,MAAM,cAAA;AAClB,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,wBAAA;AAAA,QACzC,MAAA,CAAO;AAAA,OACT;AACA,MAAA,IAAI,CAAC,UAAU,OAAO,IAAA;AACtB,MAAA,OAAO,GAAA,CAAI,eAAA,CAAgB,4BAAA,CAA6B,QAAA,CAAS,EAAE,CAAA;AAAA,IACrE,CAAA;AAAA,IAEA,MAAM,mBAAmB,MAAA,EAAQ;AAC/B,MAAA,MAAM,MAAM,MAAM,cAAA;AAGlB,MAAA,OAAO,mBAA0B,GAAA,EAAK;AAAA,QACpC,YAAY,MAAA,CAAO,UAAA;AAAA,QACnB,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,YAAY,MAAA,CAAO,UAAA;AAAA,QACnB,WAAW,MAAA,CAAO;AAAA,OACnB,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,mBAAmB,MAAA,EAAQ;AAC/B,MAAA,MAAM,MAAM,MAAM,cAAA;AAGlB,MAAA,MAAM,MAAA,GAAS,MAAM,WAAA,CAAY,GAAA,EAAK,sBAAA,EAAwB;AAAA,QAC5D,YAAY,MAAA,CAAO,UAAA;AAAA,QACnB,UAAU,MAAA,CAAO;AAAA,OAClB,CAAA;AAED,MAAA,OAAO,MAAA,CAAO,YAAA;AAAA,IAChB,CAAA;AAAA,IAEA,MAAM,mBAAmB,MAAA,EAAQ;AAC/B,MAAA,MAAM,MAAM,MAAM,cAAA;AAClB,MAAA,OAAO,kBAAA,CAA0B,KAAK,MAAM,CAAA;AAAA,IAC9C,CAAA;AAAA,IAEA,MAAM,aAAa,MAAA,EAAQ;AACzB,MAAA,MAAM,MAAM,MAAM,cAAA;AAClB,MAAA,OAAO,IAAI,eAAA,CAAgB,kBAAA;AAAA,QACzB,MAAA,CAAO,UAAA;AAAA,QACP,MAAA,CAAO;AAAA,OACT;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,aAAa,MAAA,EAAQ;AACzB,MAAA,MAAM,MAAM,MAAM,cAAA;AAClB,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,wBAAA;AAAA,QACzC,MAAA,CAAO;AAAA,OACT;AACA,MAAA,IAAI,CAAC,QAAA,EAAU,OAAO,EAAC;AAEvB,MAAA,MAAM,eACJ,MAAM,GAAA,CAAI,eAAA,CAAgB,4BAAA,CAA6B,SAAS,EAAE,CAAA;AACpE,MAAA,IAAI,CAAC,YAAA,EAAc,OAAO,EAAC;AAG3B,MAAA,MAAM,YAAA,GAAe,IAAI,eAAA,CAAgB,eAAA;AAAA,QACvC,YAAA,CAAa;AAAA,OACf;AACA,MAAA,OAAO,YAAA,CAAa,GAAA,CAAI,CAAC,IAAA,KAAS;AAChC,QAAA,MAAM,OAAA,GAAU,GAAA,CAAI,eAAA,CAAgB,iBAAA,CAAkB,IAAI,CAAA;AAC1D,QAAA,OAAO,OAAA,GACH;AAAA,UACE,MAAM,OAAA,CAAQ,IAAA;AAAA,UACd,MAAM,OAAA,CAAQ,IAAA;AAAA,UACd,OAAA,EAAS;AAAA,YAEX,EAAE,IAAA,EAA4B,IAAA,EAAM,IAAA,EAAM,SAAS,IAAA,EAAc;AAAA,MACvE,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,MAAA,GAAS;AACb,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,IAAA;AAAA,QACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,OACpC;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,aAAa,MAAA,EAAQ;AACzB,MAAA,MAAM,MAAM,MAAM,cAAA;AAClB,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,eAAA,CAAgB,wBAAA;AAAA,QACzC,MAAA,CAAO;AAAA,OACT;AACA,MAAA,IAAI,CAAC,QAAA,EAAU,OAAO,EAAC;AACvB,MAAA,OAAO,GAAA,CAAI,eAAA,CAAgB,YAAA,CAAa,QAAA,CAAS,EAAA,EAAI;AAAA,QACnD,OAAO,MAAA,CAAO,KAAA;AAAA,QACd,QAAQ,MAAA,CAAO;AAAA,OAChB,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,WAAW,MAAA,EAAQ;AACvB,MAAA,MAAM,MAAM,MAAM,cAAA;AAClB,MAAA,OAAO,GAAA,CAAI,eAAA,CAAgB,eAAA,CAAgB,MAAA,CAAO,SAAS,CAAA;AAAA,IAC7D,CAAA;AAAA,IAEA,MAAM,aAAa,MAAA,EAAQ;AACzB,MAAA,MAAM,MAAM,MAAM,cAAA;AAGlB,MAAA,OAAO,WAAA,CAAY,KAAK,UAAA,EAAY;AAAA,QAClC,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,QAAQ,MAAA,CAAO;AAAA,OAChB,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,MAAM,gBAAgB,MAAA,EAAQ;AAC5B,MAAA,MAAM,MAAM,MAAM,cAAA;AAClB,MAAA,OAAO,eAAA,CAAuB,KAAK,MAAM,CAAA;AAAA,IAC3C;AAAA,GACF;AACF;AAKA,eAAe,KAAK,OAAA,EAAkD;AACpE,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAY,aAAA,EAAc;AACnD,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,IAAW,cAAA,EAAe;AAClD,EAAA,OAAO,qBAAqB,QAAA,EAAU,EAAE,GAAG,OAAA,EAAS,SAAS,CAAA;AAC/D;AASO,SAAS,cACd,OAAA,EACkB;AAElB,EAAA,MAAM,cAAA,GAAiB,KAAK,OAAO,CAAA;AAGnC,EAAA,MAAM,aAAqC,EAAC;AAC5C,EAAA,KAAA,MAAW,MAAA,IAAU,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AAC1C,IAAA,IAAI,OAAO,YAAA,EAAc;AACvB,MAAA,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,MAAA,CAAO,YAAY,CAAA;AAAA,IAC/C;AAAA,EACF;AAGA,EAAA,MAAM,OAAA,GAAU,OAAO,OAAA,KAAwC;AAC7D,IAAA,MAAM,MAAM,MAAM,cAAA;AAClB,IAAA,MAAM,EAAE,OAAA,EAAS,YAAA,EAAa,GAAI,aAAa,GAAG,CAAA;AAClD,IAAA,OAAO,aAAa,OAAO,CAAA;AAAA,EAC7B,CAAA;AAIA,EAAA,MAAM,GAAA,GAAM,UAAU,cAAc,CAAA;AAEpC,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,GAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA,EAAU,cAAA;AAAA,IACV,QAAQ,EAAC;AAAA,IACT,YAAA,EAAc;AAAA,MACZ,GAAG,gBAAA;AAAA,MACH,GAAG;AAAA;AACL,GACF;AACF;AAoBO,SAAS,QAEd,OAAA,EAAwE;AAExE,EAAA,OAAO,cAAc,OAAc,CAAA;AACrC","file":"index.js","sourcesContent":["import { z } from \"zod\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Create customer schema\n */\nconst createCustomerSchema = z.object({\n externalId: z.string().min(1),\n email: z.string().email(),\n name: z.string().optional(),\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\n/**\n * Get customer query schema\n */\nconst getCustomerQuerySchema = z.object({\n externalId: z.string().min(1),\n});\n\n/**\n * Customer endpoints\n */\nexport const customerEndpoints: Record<string, BillingEndpoint> = {\n createCustomer: {\n path: \"/customer\",\n options: {\n method: \"POST\",\n body: createCustomerSchema,\n },\n handler: async (\n context: EndpointContext<z.infer<typeof createCustomerSchema>>,\n ) => {\n const { ctx, body } = context;\n\n // Check if customer already exists\n const existing = await ctx.internalAdapter.findCustomerByExternalId(\n body.externalId,\n );\n if (existing) {\n return { customer: existing };\n }\n\n // Create customer\n const customer = await ctx.internalAdapter.createCustomer(body);\n return { customer };\n },\n },\n\n getCustomer: {\n path: \"/customer\",\n options: {\n method: \"GET\",\n query: getCustomerQuerySchema,\n },\n handler: async (\n context: EndpointContext<unknown, z.infer<typeof getCustomerQuerySchema>>,\n ) => {\n const { ctx, query } = context;\n\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n query.externalId,\n );\n if (!customer) {\n return { customer: null };\n }\n\n return { customer };\n },\n },\n};\n","import { z } from \"zod\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Check feature access query schema\n */\nconst checkFeatureQuerySchema = z.object({\n customerId: z.string().min(1),\n feature: z.string().min(1),\n});\n\n/**\n * List features query schema\n */\nconst listFeaturesQuerySchema = z.object({\n customerId: z.string().min(1),\n});\n\n/**\n * Feature endpoints\n */\nexport const featureEndpoints: Record<string, BillingEndpoint> = {\n checkFeature: {\n path: \"/features/check\",\n options: {\n method: \"GET\",\n query: checkFeatureQuerySchema,\n },\n handler: async (\n context: EndpointContext<\n unknown,\n z.infer<typeof checkFeatureQuerySchema>\n >,\n ) => {\n const { ctx, query } = context;\n\n const result = await ctx.internalAdapter.checkFeatureAccess(\n query.customerId,\n query.feature,\n );\n return result;\n },\n },\n\n listFeatures: {\n path: \"/features\",\n options: {\n method: \"GET\",\n query: listFeaturesQuerySchema,\n },\n handler: async (\n context: EndpointContext<\n unknown,\n z.infer<typeof listFeaturesQuerySchema>\n >,\n ) => {\n const { ctx, query } = context;\n\n // Find customer\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n query.customerId,\n );\n if (!customer) {\n return { features: [] };\n }\n\n // Find active subscription\n const subscription =\n await ctx.internalAdapter.findSubscriptionByCustomerId(customer.id);\n if (!subscription) {\n return { features: [] };\n }\n\n // Get plan features from config (synchronous)\n const featureCodes = ctx.internalAdapter.getPlanFeatures(\n subscription.planCode,\n );\n const features = featureCodes.map((code: string) => {\n const feature = ctx.internalAdapter.findFeatureByCode(code);\n return {\n code,\n name: feature?.name ?? code,\n type: feature?.type ?? \"boolean\",\n enabled: true,\n };\n });\n\n return { features };\n },\n },\n};\n","import type { BillingEndpoint } from \"../../types/api\";\n\n/**\n * Health check endpoint\n */\nexport const healthEndpoint: Record<string, BillingEndpoint> = {\n health: {\n path: \"/health\",\n options: {\n method: \"GET\",\n },\n handler: async () => {\n return {\n status: \"ok\",\n timestamp: new Date().toISOString(),\n version: \"0.1.0\",\n };\n },\n },\n};\n","import { z } from \"zod\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * List payments query schema\n */\nconst listPaymentsQuerySchema = z.object({\n customerId: z.string().min(1),\n limit: z.coerce.number().positive().max(100).optional().default(25),\n offset: z.coerce.number().nonnegative().optional().default(0),\n});\n\n/**\n * Get payment query schema\n */\nconst getPaymentQuerySchema = z.object({\n paymentId: z.string().min(1),\n});\n\n/**\n * Payment endpoints\n */\nexport const paymentEndpoints: Record<string, BillingEndpoint> = {\n listPayments: {\n path: \"/payments\",\n options: {\n method: \"GET\",\n query: listPaymentsQuerySchema,\n },\n handler: async (\n context: EndpointContext<\n unknown,\n z.infer<typeof listPaymentsQuerySchema>\n >,\n ) => {\n const { ctx, query } = context;\n\n // Find customer by external ID\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n query.customerId,\n );\n if (!customer) {\n return { payments: [] };\n }\n\n // List payments for customer\n const payments = await ctx.internalAdapter.listPayments(customer.id, {\n limit: query.limit,\n offset: query.offset,\n });\n\n return { payments };\n },\n },\n\n getPayment: {\n path: \"/payment\",\n options: {\n method: \"GET\",\n query: getPaymentQuerySchema,\n },\n handler: async (\n context: EndpointContext<unknown, z.infer<typeof getPaymentQuerySchema>>,\n ) => {\n const { ctx, query } = context;\n\n const payment = await ctx.internalAdapter.findPaymentById(\n query.paymentId,\n );\n\n return { payment };\n },\n },\n};\n","import { z } from \"zod\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Plan endpoints - plans come from config, not DB\n */\nexport const planEndpoints: Record<string, BillingEndpoint> = {\n listPlans: {\n path: \"/plans\",\n options: {\n method: \"GET\",\n },\n handler: async (context: EndpointContext) => {\n const { ctx } = context;\n // Plans come from config, synchronous\n const plans = ctx.internalAdapter.listPlans({ includePrivate: false });\n return { plans };\n },\n },\n\n getPlan: {\n path: \"/plan\",\n options: {\n method: \"GET\",\n query: z.object({\n code: z.string(),\n }),\n },\n handler: async (context: EndpointContext<unknown, { code: string }>) => {\n const { ctx, query } = context;\n // Plans come from config, synchronous\n const plan = ctx.internalAdapter.findPlanByCode(query.code);\n\n if (!plan) {\n return { plan: null };\n }\n\n // Prices are included in the plan from config\n return { plan };\n },\n },\n};\n","import type { Subscription } from \"@billsdk/core\";\nimport type { BillingContext } from \"../context/create-context\";\n\nexport interface HandlePaymentFailedParams {\n /**\n * Subscription ID whose payment failed\n */\n subscriptionId: string;\n /**\n * Error message from the payment provider\n */\n error?: string;\n}\n\nexport interface HandlePaymentFailedResult {\n /**\n * The subscription that was marked as past_due\n */\n subscription: Subscription;\n}\n\n/**\n * Handle a failed payment for a subscription.\n *\n * This is the single source of truth for payment failure logic.\n * The default behavior marks the subscription as past_due to give\n * the customer a chance to update their payment method.\n */\nexport async function handlePaymentFailed(\n ctx: BillingContext,\n params: HandlePaymentFailedParams,\n): Promise<HandlePaymentFailedResult> {\n const { subscriptionId, error } = params;\n\n // Find the subscription\n const subscription =\n await ctx.internalAdapter.findSubscriptionById(subscriptionId);\n if (!subscription) {\n throw new Error(\"Subscription not found\");\n }\n\n ctx.logger.info(\"Payment failed, marking subscription as past_due\", {\n subscriptionId: subscription.id,\n error,\n });\n\n // Update subscription status to past_due\n const updatedSubscription = await ctx.internalAdapter.updateSubscription(\n subscription.id,\n { status: \"past_due\" },\n );\n\n return {\n subscription: updatedSubscription ?? {\n ...subscription,\n status: \"past_due\",\n },\n };\n}\n","import type { Payment } from \"@billsdk/core\";\nimport type { BillingContext } from \"../context/create-context\";\n\nexport interface CreateRefundParams {\n /**\n * Payment ID to refund (BillSDK payment ID)\n */\n paymentId: string;\n /**\n * Amount to refund in cents (partial refund)\n * If omitted, full refund is issued\n */\n amount?: number;\n /**\n * Reason for the refund\n */\n reason?: string;\n}\n\nexport interface CreateRefundResult {\n refund: Payment;\n originalPayment: Payment;\n}\n\n/**\n * Create a refund for a payment.\n *\n * This is the single source of truth for refund logic.\n * Both HTTP endpoints and direct API methods should use this function.\n */\nexport async function createRefund(\n ctx: BillingContext,\n params: CreateRefundParams,\n): Promise<CreateRefundResult> {\n const { paymentId, amount, reason } = params;\n\n // Check if payment adapter supports refunds\n if (!ctx.paymentAdapter?.refund) {\n throw new Error(\"Payment adapter does not support refunds\");\n }\n\n // Find the payment\n const payment = await ctx.internalAdapter.findPaymentById(paymentId);\n if (!payment) {\n throw new Error(\"Payment not found\");\n }\n\n // Check payment is refundable\n if (payment.status !== \"succeeded\") {\n throw new Error(`Cannot refund payment with status \"${payment.status}\"`);\n }\n\n // Check if already fully refunded\n const alreadyRefunded = payment.refundedAmount ?? 0;\n const remainingAmount = payment.amount - alreadyRefunded;\n\n if (remainingAmount <= 0) {\n throw new Error(\"Payment has already been fully refunded\");\n }\n\n // Determine refund amount\n const refundAmount = amount ?? remainingAmount;\n\n if (refundAmount > remainingAmount) {\n throw new Error(\n `Cannot refund ${refundAmount}. Only ${remainingAmount} is available for refund.`,\n );\n }\n\n // Check if payment has a provider payment ID\n if (!payment.providerPaymentId) {\n throw new Error(\n \"Payment does not have a provider payment ID. Cannot process refund.\",\n );\n }\n\n // Call the adapter to process the refund\n const result = await ctx.paymentAdapter.refund({\n providerPaymentId: payment.providerPaymentId,\n amount: refundAmount,\n reason,\n });\n\n if (result.status === \"failed\") {\n throw new Error(result.error ?? \"Refund failed\");\n }\n\n // Update the original payment with refunded amount\n const newRefundedAmount = alreadyRefunded + refundAmount;\n const newStatus =\n newRefundedAmount >= payment.amount ? \"refunded\" : \"succeeded\";\n\n await ctx.internalAdapter.updatePayment(payment.id, {\n status: newStatus,\n refundedAmount: newRefundedAmount,\n });\n\n // Record the refund as a negative payment\n const refundPayment = await ctx.internalAdapter.createPayment({\n customerId: payment.customerId,\n subscriptionId: payment.subscriptionId ?? undefined,\n type: \"refund\",\n status: \"succeeded\",\n amount: -refundAmount, // Negative to indicate refund\n currency: payment.currency,\n providerPaymentId: result.providerRefundId,\n metadata: {\n originalPaymentId: payment.id,\n reason,\n },\n });\n\n ctx.logger.info(\"Refund processed\", {\n originalPaymentId: payment.id,\n refundPaymentId: refundPayment.id,\n amount: refundAmount,\n });\n\n if (payment.subscriptionId) {\n const subscription = await ctx.internalAdapter.findSubscriptionById(\n payment.subscriptionId,\n );\n\n if (subscription && subscription.status !== \"canceled\") {\n ctx.logger.info(\"Refund includes subscription cancellation\", {\n subscriptionId: subscription.id,\n paymentId,\n });\n\n await ctx.internalAdapter.cancelSubscription(subscription.id);\n }\n }\n\n return {\n refund: refundPayment,\n originalPayment: {\n ...payment,\n status: newStatus,\n refundedAmount: newRefundedAmount,\n },\n };\n}\n","import type { BillingInterval } from \"../types/models\";\n\n/**\n * Result of a proration calculation (period reset model)\n *\n * When upgrading, the billing period resets to start from the change date.\n * The user gets credit for unused days on the old plan, which is deducted\n * from the full price of the new plan.\n */\nexport interface ProrationResult {\n /**\n * Credit for unused time on current plan (in cents)\n */\n credit: number;\n /**\n * Full price of the new plan (in cents)\n */\n charge: number;\n /**\n * Net amount to charge: newPlanAmount - credit\n */\n netAmount: number;\n /**\n * Days used on old plan (from period start to change date)\n */\n daysUsed: number;\n /**\n * Total days in the original billing period\n */\n totalDays: number;\n}\n\n/**\n * Parameters for proration calculation\n */\nexport interface ProrationParams {\n /**\n * Current plan amount in cents\n */\n oldPlanAmount: number;\n /**\n * New plan amount in cents\n */\n newPlanAmount: number;\n /**\n * Start of current billing period\n */\n currentPeriodStart: Date;\n /**\n * End of current billing period\n */\n currentPeriodEnd: Date;\n /**\n * Date when the plan change occurs (defaults to now)\n */\n changeDate?: Date;\n}\n\n/**\n * Calculate the number of days between two dates\n */\nfunction daysBetween(start: Date, end: Date): number {\n const msPerDay = 1000 * 60 * 60 * 24;\n return Math.ceil((end.getTime() - start.getTime()) / msPerDay);\n}\n\n/**\n * Calculate proration for a plan upgrade (period reset model)\n *\n * When upgrading:\n * 1. Calculate credit for unused days on old plan\n * 2. Charge full price of new plan minus the credit\n * 3. Reset billing period to start from change date\n *\n * @example\n * ```typescript\n * // User on Starter ($10/mo) upgrading to Pro ($20/mo)\n * // Subscribed Jan 1, upgrading Jan 7 (used 6 days, 25 remaining)\n * const result = calculateProration({\n * oldPlanAmount: 1000, // $10 in cents\n * newPlanAmount: 2000, // $20 in cents\n * currentPeriodStart: new Date('2024-01-01'),\n * currentPeriodEnd: new Date('2024-02-01'),\n * changeDate: new Date('2024-01-07'),\n * });\n *\n * // result.credit = 806 ($8.06 - unused Starter time: 25/31 × $10)\n * // result.charge = 2000 ($20 - full Pro price)\n * // result.netAmount = 1194 ($11.94 to charge)\n * // New period: Jan 7 - Feb 7\n * ```\n */\nexport function calculateProration(params: ProrationParams): ProrationResult {\n const {\n oldPlanAmount,\n newPlanAmount,\n currentPeriodStart,\n currentPeriodEnd,\n changeDate = new Date(),\n } = params;\n\n const totalDays = daysBetween(currentPeriodStart, currentPeriodEnd);\n const daysUsed = daysBetween(currentPeriodStart, changeDate);\n const daysRemaining = totalDays - daysUsed;\n\n const effectiveDaysRemaining = Math.max(\n 0,\n Math.min(daysRemaining, totalDays),\n );\n\n // Credit = unused portion of old plan\n const credit = Math.round(\n (oldPlanAmount / totalDays) * effectiveDaysRemaining,\n );\n\n // Charge = full price of new plan (period resets)\n const charge = newPlanAmount;\n\n // Net = new plan price minus credit\n const netAmount = Math.max(0, charge - credit);\n\n return {\n credit,\n charge,\n netAmount,\n daysUsed: Math.max(0, Math.min(daysUsed, totalDays)),\n totalDays,\n };\n}\n\n/**\n * Calculate the full amount for a new subscription period\n * (No proration - full amount for the interval)\n */\nexport function calculateFullPeriodAmount(\n amount: number,\n _interval: BillingInterval,\n): number {\n // For now, just return the amount as-is\n // In the future, this could handle quarterly calculations, etc.\n return amount;\n}\n","import type {\n BillingInterval,\n Payment,\n Plan,\n Subscription,\n} from \"@billsdk/core\";\nimport type { BillingContext } from \"../context/create-context\";\nimport { calculateProration } from \"./proration\";\n\nexport interface CreateSubscriptionParams {\n customerId: string;\n planCode: string;\n interval?: \"monthly\" | \"yearly\";\n successUrl?: string;\n cancelUrl?: string;\n}\n\nexport interface CreateSubscriptionResult {\n subscription: Subscription;\n redirectUrl?: string;\n}\n\nexport async function createSubscription(\n ctx: BillingContext,\n params: CreateSubscriptionParams,\n): Promise<CreateSubscriptionResult> {\n const {\n customerId,\n planCode,\n interval = \"monthly\",\n successUrl,\n cancelUrl,\n } = params;\n\n if (!ctx.paymentAdapter) {\n throw new Error(\"Payment adapter not configured\");\n }\n\n const customer =\n await ctx.internalAdapter.findCustomerByExternalId(customerId);\n if (!customer) {\n throw new Error(\"Customer not found\");\n }\n\n const plan = ctx.internalAdapter.findPlanByCode(planCode);\n if (!plan) {\n throw new Error(\"Plan not found\");\n }\n\n const price = ctx.internalAdapter.getPlanPrice(planCode, interval);\n if (!price) {\n throw new Error(\n `No price found for plan ${planCode} with interval ${interval}`,\n );\n }\n\n const subscription = await ctx.internalAdapter.createSubscription({\n customerId: customer.id,\n planCode,\n interval,\n status: \"pending_payment\",\n trialDays: price.trialDays,\n });\n\n const result = await ctx.paymentAdapter.processPayment({\n customer: {\n id: customer.id,\n email: customer.email,\n providerCustomerId: customer.providerCustomerId,\n },\n plan: {\n code: plan.code,\n name: plan.name,\n },\n price: {\n amount: price.amount,\n currency: price.currency,\n interval: price.interval,\n },\n subscription: {\n id: subscription.id,\n },\n successUrl,\n cancelUrl,\n metadata: {\n subscriptionId: subscription.id,\n customerId: customer.id,\n },\n });\n\n if (result.status === \"active\") {\n const existingSubscriptions = await ctx.internalAdapter.listSubscriptions(\n customer.id,\n );\n for (const existing of existingSubscriptions) {\n if (\n existing.id !== subscription.id &&\n (existing.status === \"active\" || existing.status === \"trialing\")\n ) {\n await ctx.internalAdapter.cancelSubscription(existing.id);\n }\n }\n\n const activeSubscription = await ctx.internalAdapter.updateSubscription(\n subscription.id,\n { status: \"active\" },\n );\n\n if (result.providerCustomerId && !customer.providerCustomerId) {\n await ctx.internalAdapter.updateCustomer(customer.id, {\n providerCustomerId: result.providerCustomerId,\n });\n }\n\n if (price.amount > 0) {\n await ctx.internalAdapter.createPayment({\n customerId: customer.id,\n subscriptionId: subscription.id,\n type: \"subscription\",\n status: \"succeeded\",\n amount: price.amount,\n currency: price.currency,\n metadata: {\n planCode: plan.code,\n interval,\n },\n });\n }\n\n return {\n subscription: activeSubscription ?? {\n ...subscription,\n status: \"active\" as const,\n },\n };\n }\n\n if (result.status === \"pending\") {\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n providerCheckoutSessionId: result.sessionId,\n });\n\n if (result.providerCustomerId && !customer.providerCustomerId) {\n await ctx.internalAdapter.updateCustomer(customer.id, {\n providerCustomerId: result.providerCustomerId,\n });\n }\n\n return {\n subscription,\n redirectUrl: result.redirectUrl,\n };\n }\n\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n status: \"canceled\",\n });\n throw new Error(result.error);\n}\n\nexport interface CancelSubscriptionParams {\n customerId: string;\n cancelAt?: \"period_end\" | \"immediately\";\n}\n\nexport interface CancelSubscriptionResult {\n subscription: Subscription | null;\n canceledImmediately: boolean;\n accessUntil?: Date;\n}\n\nexport async function cancelSubscription(\n ctx: BillingContext,\n params: CancelSubscriptionParams,\n): Promise<CancelSubscriptionResult> {\n const { customerId, cancelAt = \"period_end\" } = params;\n\n const customer =\n await ctx.internalAdapter.findCustomerByExternalId(customerId);\n if (!customer) {\n throw new Error(\"Customer not found\");\n }\n\n const subscription = await ctx.internalAdapter.findSubscriptionByCustomerId(\n customer.id,\n );\n if (!subscription) {\n throw new Error(\"No active subscription found\");\n }\n\n if (cancelAt === \"immediately\") {\n const canceled = await ctx.internalAdapter.cancelSubscription(\n subscription.id,\n );\n return { subscription: canceled, canceledImmediately: true };\n }\n\n const canceled = await ctx.internalAdapter.cancelSubscription(\n subscription.id,\n subscription.currentPeriodEnd,\n );\n return {\n subscription: canceled,\n canceledImmediately: false,\n accessUntil: subscription.currentPeriodEnd,\n };\n}\n\nexport interface ChangeSubscriptionParams {\n customerId: string;\n newPlanCode: string;\n newInterval?: BillingInterval;\n prorate?: boolean;\n}\n\nexport interface ChangeSubscriptionResult {\n subscription: Subscription | null;\n previousPlan: Plan | null;\n newPlan: Plan;\n payment: Payment | null;\n scheduled: boolean;\n effectiveAt?: Date;\n}\n\nconst intervalRank: Record<BillingInterval, number> = {\n monthly: 1,\n quarterly: 2,\n yearly: 3,\n};\n\nfunction isUpgrade(\n oldPrice: number,\n newPrice: number,\n oldInterval: BillingInterval,\n newInterval: BillingInterval,\n): boolean {\n if (oldInterval !== newInterval) {\n return intervalRank[newInterval] > intervalRank[oldInterval];\n }\n return newPrice > oldPrice;\n}\n\nexport async function changeSubscription(\n ctx: BillingContext,\n params: ChangeSubscriptionParams,\n): Promise<ChangeSubscriptionResult> {\n const { customerId, newPlanCode, newInterval, prorate = true } = params;\n\n const customer =\n await ctx.internalAdapter.findCustomerByExternalId(customerId);\n if (!customer) {\n throw new Error(\"Customer not found\");\n }\n\n const subscription = await ctx.internalAdapter.findSubscriptionByCustomerId(\n customer.id,\n );\n if (!subscription) {\n throw new Error(\"No active subscription found\");\n }\n\n const targetInterval = newInterval ?? subscription.interval;\n\n if (\n subscription.planCode === newPlanCode &&\n subscription.interval === targetInterval\n ) {\n throw new Error(\"Already on this plan\");\n }\n\n const oldPlan = ctx.internalAdapter.findPlanByCode(subscription.planCode);\n const oldPrice = ctx.internalAdapter.getPlanPrice(\n subscription.planCode,\n subscription.interval,\n );\n if (!oldPrice) {\n throw new Error(\"Current plan price not found\");\n }\n\n const newPlan = ctx.internalAdapter.findPlanByCode(newPlanCode);\n if (!newPlan) {\n throw new Error(\"New plan not found\");\n }\n\n const newPrice = ctx.internalAdapter.getPlanPrice(\n newPlanCode,\n targetInterval,\n );\n if (!newPrice) {\n throw new Error(\n `No price found for plan ${newPlanCode} with interval ${targetInterval}`,\n );\n }\n\n const upgrade = isUpgrade(\n oldPrice.amount,\n newPrice.amount,\n subscription.interval,\n targetInterval,\n );\n\n ctx.logger.info(\"Plan change detected\", {\n from: `${subscription.planCode} (${subscription.interval})`,\n to: `${newPlanCode} (${targetInterval})`,\n oldAmount: oldPrice.amount,\n newAmount: newPrice.amount,\n isUpgrade: upgrade,\n });\n\n // Downgrade: schedule for period end\n if (!upgrade) {\n ctx.logger.info(\"Downgrade scheduled for period end\", {\n scheduledPlanCode: newPlanCode,\n scheduledInterval: targetInterval,\n effectiveAt: subscription.currentPeriodEnd,\n });\n\n const updatedSubscription = await ctx.internalAdapter.updateSubscription(\n subscription.id,\n {\n scheduledPlanCode: newPlanCode,\n scheduledInterval: targetInterval,\n },\n );\n\n return {\n subscription: updatedSubscription,\n previousPlan: oldPlan,\n newPlan,\n payment: null,\n scheduled: true,\n effectiveAt: subscription.currentPeriodEnd,\n };\n }\n\n // Upgrade: immediate change with proration and period reset\n let payment: Payment | null = null;\n const changeDate = await ctx.timeProvider.now(params.customerId);\n\n ctx.logger.info(\"changeDate from timeProvider\", {\n changeDate: changeDate.toISOString(),\n realTime: new Date().toISOString(),\n });\n\n if (prorate) {\n const prorationResult = calculateProration({\n oldPlanAmount: oldPrice.amount,\n newPlanAmount: newPrice.amount,\n currentPeriodStart: subscription.currentPeriodStart,\n currentPeriodEnd: subscription.currentPeriodEnd,\n changeDate,\n });\n\n ctx.logger.info(\"Proration calculated\", {\n credit: prorationResult.credit,\n charge: prorationResult.charge,\n netAmount: prorationResult.netAmount,\n daysUsed: prorationResult.daysUsed,\n });\n\n if (prorationResult.netAmount > 0) {\n if (!ctx.paymentAdapter?.charge) {\n throw new Error(\n \"Payment adapter does not support direct charging. Cannot process upgrade.\",\n );\n }\n\n if (!customer.providerCustomerId) {\n throw new Error(\n \"Customer does not have a saved payment method. Cannot process upgrade.\",\n );\n }\n\n const chargeResult = await ctx.paymentAdapter.charge({\n customer: {\n id: customer.id,\n email: customer.email,\n providerCustomerId: customer.providerCustomerId,\n },\n amount: prorationResult.netAmount,\n currency: newPrice.currency,\n description: `Upgrade from ${oldPlan?.name ?? subscription.planCode} to ${newPlan.name}`,\n metadata: {\n subscriptionId: subscription.id,\n customerId: customer.id,\n type: \"upgrade\",\n oldPlanCode: subscription.planCode,\n newPlanCode,\n },\n });\n\n if (chargeResult.status === \"failed\") {\n throw new Error(chargeResult.error ?? \"Charge failed\");\n }\n\n payment = await ctx.internalAdapter.createPayment({\n customerId: customer.id,\n subscriptionId: subscription.id,\n type: \"upgrade\",\n status: \"succeeded\",\n amount: prorationResult.netAmount,\n currency: newPrice.currency,\n providerPaymentId: chargeResult.providerPaymentId,\n metadata: {\n oldPlanCode: subscription.planCode,\n newPlanCode,\n proration: {\n credit: prorationResult.credit,\n charge: prorationResult.charge,\n },\n },\n });\n }\n }\n\n // Calculate new period end based on interval\n const newPeriodStart = changeDate;\n const newPeriodEnd = new Date(changeDate);\n if (targetInterval === \"yearly\") {\n newPeriodEnd.setFullYear(newPeriodEnd.getFullYear() + 1);\n } else if (targetInterval === \"quarterly\") {\n newPeriodEnd.setMonth(newPeriodEnd.getMonth() + 3);\n } else {\n newPeriodEnd.setMonth(newPeriodEnd.getMonth() + 1);\n }\n\n const updatedSubscription = await ctx.internalAdapter.updateSubscription(\n subscription.id,\n {\n planCode: newPlanCode,\n interval: targetInterval,\n currentPeriodStart: newPeriodStart,\n currentPeriodEnd: newPeriodEnd,\n scheduledPlanCode: undefined,\n scheduledInterval: undefined,\n },\n );\n\n ctx.logger.info(\"Period reset\", {\n from: `${subscription.currentPeriodStart.toISOString()} - ${subscription.currentPeriodEnd.toISOString()}`,\n to: `${newPeriodStart.toISOString()} - ${newPeriodEnd.toISOString()}`,\n });\n\n return {\n subscription: updatedSubscription,\n previousPlan: oldPlan,\n newPlan,\n payment,\n scheduled: false,\n };\n}\n","import type { Subscription } from \"@billsdk/core\";\nimport type { BillingContext } from \"../context/create-context\";\n\nexport interface HandleTrialEndParams {\n /**\n * Subscription ID whose trial is ending\n */\n subscriptionId: string;\n}\n\nexport interface HandleTrialEndResult {\n /**\n * The subscription after trial processing\n */\n subscription: Subscription;\n /**\n * Whether the subscription was converted to paid (true) or canceled (false)\n */\n converted: boolean;\n}\n\n/**\n * Handle the end of a trial period for a subscription.\n *\n * This is the single source of truth for trial end logic.\n * The default behavior:\n * - If customer has a payment method: activates the subscription\n * - If no payment method: cancels the subscription\n */\nexport async function handleTrialEnd(\n ctx: BillingContext,\n params: HandleTrialEndParams,\n): Promise<HandleTrialEndResult> {\n const { subscriptionId } = params;\n\n // Find the subscription\n const subscription =\n await ctx.internalAdapter.findSubscriptionById(subscriptionId);\n if (!subscription) {\n throw new Error(\"Subscription not found\");\n }\n\n // Find the customer\n const customer = await ctx.internalAdapter.findCustomerById(\n subscription.customerId,\n );\n if (!customer) {\n throw new Error(\"Customer not found\");\n }\n\n // Get the plan\n const plan = ctx.internalAdapter.findPlanByCode(subscription.planCode);\n\n ctx.logger.info(\"Processing trial end\", {\n subscriptionId: subscription.id,\n customerId: customer.id,\n planCode: plan?.code,\n });\n\n // If customer has no payment method, cancel the subscription\n if (!customer.providerCustomerId) {\n ctx.logger.info(\"No payment method, canceling subscription\", {\n subscriptionId: subscription.id,\n });\n\n const canceledSubscription = await ctx.internalAdapter.cancelSubscription(\n subscription.id,\n );\n\n return {\n subscription: canceledSubscription ?? {\n ...subscription,\n status: \"canceled\",\n },\n converted: false,\n };\n }\n\n // Customer has payment method - activate the subscription\n ctx.logger.info(\"Payment method exists, activating subscription\", {\n subscriptionId: subscription.id,\n });\n\n const activeSubscription = await ctx.internalAdapter.updateSubscription(\n subscription.id,\n { status: \"active\" },\n );\n\n return {\n subscription: activeSubscription ?? { ...subscription, status: \"active\" },\n converted: true,\n };\n}\n","import type {\n OnPaymentFailedParams,\n OnPaymentFailedResult,\n OnRefundParams,\n OnRefundResult,\n OnSubscriptionCancelParams,\n OnSubscriptionCancelResult,\n OnTrialEndParams,\n OnTrialEndResult,\n} from \"@billsdk/core\";\nimport type { BillingContext } from \"../../context/create-context\";\nimport { handlePaymentFailed as handlePaymentFailedService } from \"../payment-failed-service\";\nimport { createRefund as createRefundService } from \"../refund-service\";\nimport { cancelSubscription as cancelSubscriptionService } from \"../subscription-service\";\nimport { handleTrialEnd as handleTrialEndService } from \"../trial-end-service\";\n\n/**\n * Default billing behaviors - these are the opinionated defaults that BillSDK\n * provides out of the box. Each can be overridden in the billsdk config.\n *\n * Philosophy: Defaults should be safe, predictable, and align with common\n * billing best practices.\n */\nexport const defaultBehaviors = {\n /**\n * Default onRefund behavior: Delegates to refund service.\n *\n * The service handles all business logic:\n * - Process the refund via payment adapter\n * - Cancel the associated subscription (BillSDK opinionated default)\n *\n * Override this behavior if you want different logic (e.g., refund without cancel).\n */\n onRefund: async (\n ctx: BillingContext,\n params: OnRefundParams,\n ): Promise<OnRefundResult> => {\n return createRefundService(ctx, {\n paymentId: params.paymentId,\n amount: params.amount,\n reason: params.reason,\n });\n },\n\n /**\n * Default onPaymentFailed behavior: Delegates to payment-failed service.\n *\n * The service handles all business logic:\n * - Find subscription\n * - Mark as past_due\n *\n * Override this behavior if you want different logic (e.g., immediate cancel).\n */\n onPaymentFailed: async (\n ctx: BillingContext,\n params: OnPaymentFailedParams,\n ): Promise<OnPaymentFailedResult> => {\n return handlePaymentFailedService(ctx, {\n subscriptionId: params.subscriptionId,\n error: params.error,\n });\n },\n\n /**\n * Default onSubscriptionCancel behavior: Delegates to cancel service.\n *\n * The service handles all business logic:\n * - Find customer and subscription\n * - Cancel immediately or at period end\n *\n * Override this behavior if you want different logic (e.g., downgrade to free).\n */\n onSubscriptionCancel: async (\n ctx: BillingContext,\n params: OnSubscriptionCancelParams,\n ): Promise<OnSubscriptionCancelResult> => {\n return cancelSubscriptionService(ctx, {\n customerId: params.customerId,\n cancelAt: params.cancelAt,\n });\n },\n\n /**\n * Default onTrialEnd behavior: Delegates to trial-end service.\n *\n * The service handles all business logic:\n * - If customer has payment method: activates subscription\n * - If no payment method: cancels subscription\n *\n * Override this behavior if you want different logic (e.g., extend trial).\n */\n onTrialEnd: async (\n ctx: BillingContext,\n params: OnTrialEndParams,\n ): Promise<OnTrialEndResult> => {\n return handleTrialEndService(ctx, {\n subscriptionId: params.subscriptionId,\n });\n },\n};\n\n/**\n * Type for the default behaviors object\n */\nexport type DefaultBehaviors = typeof defaultBehaviors;\n","import type {\n OnPaymentFailedParams,\n OnPaymentFailedResult,\n OnRefundParams,\n OnRefundResult,\n OnSubscriptionCancelParams,\n OnSubscriptionCancelResult,\n OnTrialEndParams,\n OnTrialEndResult,\n} from \"@billsdk/core\";\nimport type { BillingContext } from \"../../context/create-context\";\nimport { defaultBehaviors } from \"./defaults\";\n\n/**\n * Map of behavior names to their parameter and result types.\n * Used for type inference in runBehavior.\n */\ntype BehaviorConfig = {\n onRefund: { params: OnRefundParams; result: OnRefundResult };\n onPaymentFailed: {\n params: OnPaymentFailedParams;\n result: OnPaymentFailedResult;\n };\n onSubscriptionCancel: {\n params: OnSubscriptionCancelParams;\n result: OnSubscriptionCancelResult;\n };\n onTrialEnd: { params: OnTrialEndParams; result: OnTrialEndResult };\n};\n\n/**\n * Run a billing behavior with optional user override.\n *\n * This is the core of the configurable behaviors system:\n * 1. If the user provided an override, call it with the default as an argument\n * 2. If no override, run the default behavior\n *\n * The behavior controls the entire operation and returns the result.\n *\n * @param ctx - The billing context\n * @param behaviorName - Name of the behavior to run\n * @param params - Input parameters for the behavior\n * @returns The result of the behavior operation\n *\n * @example\n * ```typescript\n * // Entry point calls behavior with inputs:\n * const result = await runBehavior(ctx, \"onRefund\", {\n * paymentId: \"pay_123\",\n * amount: 1000,\n * });\n * ```\n */\nexport async function runBehavior<T extends keyof BehaviorConfig>(\n ctx: BillingContext,\n behaviorName: T,\n params: BehaviorConfig[T][\"params\"],\n): Promise<BehaviorConfig[T][\"result\"]> {\n const userBehavior = ctx.options.behaviors?.[behaviorName];\n const defaultFn = defaultBehaviors[behaviorName];\n\n // Create the default behavior function that the user can optionally call\n const defaultBehavior = async (): Promise<BehaviorConfig[T][\"result\"]> => {\n // biome-ignore lint/suspicious/noExplicitAny: Generic behavior dispatch - type safety is ensured by BehaviorConfig mapping\n return defaultFn(ctx, params as any);\n };\n\n if (userBehavior) {\n ctx.logger.debug(`Running user-defined behavior: ${behaviorName}`);\n // User provided an override - call it with the default available\n // biome-ignore lint/suspicious/noExplicitAny: Generic behavior dispatch - type safety is ensured by BehaviorConfig mapping\n return userBehavior(ctx as any, params as any, defaultBehavior as any);\n }\n\n ctx.logger.debug(`Running default behavior: ${behaviorName}`);\n // No override - run the default\n return defaultBehavior();\n}\n","import { z } from \"zod\";\nimport type { BillingContext } from \"../../context/create-context\";\nimport { runBehavior } from \"../../logic/behaviors/runner\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Create refund schema\n */\nconst createRefundSchema = z.object({\n /**\n * Payment ID to refund (BillSDK payment ID)\n */\n paymentId: z.string().min(1),\n /**\n * Amount to refund in cents (partial refund)\n * If omitted, full refund is issued\n */\n amount: z.number().positive().optional(),\n /**\n * Reason for the refund\n */\n reason: z.string().optional(),\n});\n\n/**\n * Refund endpoints\n */\nexport const refundEndpoints: Record<string, BillingEndpoint> = {\n createRefund: {\n path: \"/refund\",\n options: {\n method: \"POST\",\n body: createRefundSchema,\n },\n handler: async (\n context: EndpointContext<z.infer<typeof createRefundSchema>>,\n ) => {\n const { ctx, body } = context;\n\n // Delegate to behavior (default: refund + cancel subscription)\n return runBehavior(ctx as BillingContext, \"onRefund\", {\n paymentId: body.paymentId,\n amount: body.amount,\n reason: body.reason,\n });\n },\n },\n};\n","import type { Subscription, Where } from \"@billsdk/core\";\nimport type { BillingContext } from \"../context/create-context\";\nimport { TABLES } from \"../db/schema\";\n\n/**\n * Parameters for processing renewals\n */\nexport interface ProcessRenewalsParams {\n /**\n * Process only a specific customer (useful for testing)\n */\n customerId?: string;\n\n /**\n * Dry run - don't actually charge, just report what would happen\n */\n dryRun?: boolean;\n\n /**\n * Maximum number of subscriptions to process (for batching)\n */\n limit?: number;\n}\n\n/**\n * Individual renewal result\n */\nexport interface RenewalDetail {\n subscriptionId: string;\n customerId: string;\n status: \"succeeded\" | \"failed\" | \"skipped\";\n amount?: number;\n error?: string;\n /**\n * If a scheduled plan change was applied\n */\n planChanged?: {\n from: string;\n to: string;\n };\n}\n\n/**\n * Result of processing renewals\n */\nexport interface ProcessRenewalsResult {\n /**\n * Total subscriptions processed\n */\n processed: number;\n\n /**\n * Successful renewals\n */\n succeeded: number;\n\n /**\n * Failed renewals\n */\n failed: number;\n\n /**\n * Skipped (already renewed, etc.)\n */\n skipped: number;\n\n /**\n * Details for each renewal\n */\n renewals: RenewalDetail[];\n}\n\n/**\n * Calculate new period end based on interval\n */\nfunction calculateNewPeriodEnd(\n from: Date,\n interval: \"monthly\" | \"quarterly\" | \"yearly\",\n): Date {\n const newEnd = new Date(from);\n if (interval === \"yearly\") {\n newEnd.setFullYear(newEnd.getFullYear() + 1);\n } else if (interval === \"quarterly\") {\n newEnd.setMonth(newEnd.getMonth() + 3);\n } else {\n newEnd.setMonth(newEnd.getMonth() + 1);\n }\n return newEnd;\n}\n\n/**\n * Find subscriptions that are due for renewal\n */\nasync function findDueSubscriptions(\n ctx: BillingContext,\n params: ProcessRenewalsParams,\n): Promise<Subscription[]> {\n const now = params.customerId\n ? await ctx.timeProvider.now(params.customerId)\n : new Date();\n\n // Build where clause\n const where: Where[] = [\n // Only active or past_due subscriptions\n {\n field: \"status\",\n operator: \"in\",\n value: [\"active\", \"past_due\"],\n },\n // Period has ended\n {\n field: \"currentPeriodEnd\",\n operator: \"lte\",\n value: now,\n },\n ];\n\n // If specific customer, filter by customer\n if (params.customerId) {\n // Need to find the internal customer ID first\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n params.customerId,\n );\n if (!customer) {\n return [];\n }\n where.push({\n field: \"customerId\",\n operator: \"eq\",\n value: customer.id,\n });\n }\n\n return ctx.adapter.findMany<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where,\n limit: params.limit,\n sortBy: { field: \"currentPeriodEnd\", direction: \"asc\" },\n });\n}\n\n/**\n * Apply scheduled plan changes (downgrades)\n * Returns the new plan code if changed, null if no change\n */\nasync function applyScheduledChanges(\n ctx: BillingContext,\n subscription: Subscription,\n): Promise<{ planChanged: boolean; newPlanCode: string; newInterval: string }> {\n if (!subscription.scheduledPlanCode) {\n return {\n planChanged: false,\n newPlanCode: subscription.planCode,\n newInterval: subscription.interval,\n };\n }\n\n const newPlanCode = subscription.scheduledPlanCode;\n const newInterval = subscription.scheduledInterval ?? subscription.interval;\n\n ctx.logger.info(\"Applying scheduled plan change\", {\n subscriptionId: subscription.id,\n from: subscription.planCode,\n to: newPlanCode,\n newInterval,\n });\n\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n planCode: newPlanCode,\n interval: newInterval,\n scheduledPlanCode: undefined,\n scheduledInterval: undefined,\n });\n\n return {\n planChanged: true,\n newPlanCode,\n newInterval,\n };\n}\n\n/**\n * Process a single subscription renewal\n */\nasync function processSubscriptionRenewal(\n ctx: BillingContext,\n subscription: Subscription,\n dryRun: boolean,\n): Promise<RenewalDetail> {\n const customer = await ctx.internalAdapter.findCustomerById(\n subscription.customerId,\n );\n if (!customer) {\n return {\n subscriptionId: subscription.id,\n customerId: subscription.customerId,\n status: \"failed\",\n error: \"Customer not found\",\n };\n }\n\n // Apply any scheduled plan changes first\n const {\n planChanged,\n newPlanCode,\n newInterval: newIntervalStr,\n } = await applyScheduledChanges(ctx, subscription);\n const newInterval = newIntervalStr as \"monthly\" | \"quarterly\" | \"yearly\";\n\n // Get the price for the (possibly new) plan\n const price = ctx.internalAdapter.getPlanPrice(newPlanCode, newInterval);\n if (!price) {\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"failed\",\n error: `No price found for plan ${newPlanCode} with interval ${newInterval}`,\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n const amount = price.amount;\n const now = await ctx.timeProvider.now(customer.externalId);\n\n // If dry run, don't actually charge\n if (dryRun) {\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"succeeded\",\n amount,\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n // Free plan - just update the period\n if (amount === 0) {\n const newPeriodEnd = calculateNewPeriodEnd(now, newInterval);\n\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n currentPeriodStart: now,\n currentPeriodEnd: newPeriodEnd,\n status: \"active\",\n });\n\n ctx.logger.info(\"Free renewal processed\", {\n subscriptionId: subscription.id,\n newPeriodEnd: newPeriodEnd.toISOString(),\n });\n\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"succeeded\",\n amount: 0,\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n // Check if customer has a payment method\n if (!customer.providerCustomerId) {\n ctx.logger.warn(\"Customer has no payment method, marking as past_due\", {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n });\n\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n status: \"past_due\",\n });\n\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"failed\",\n error: \"No payment method on file\",\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n // Check if payment adapter supports charging\n if (!ctx.paymentAdapter?.charge) {\n ctx.logger.error(\"Payment adapter does not support direct charging\", {\n subscriptionId: subscription.id,\n });\n\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"failed\",\n error: \"Payment adapter does not support direct charging\",\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n // Charge the customer\n const plan = ctx.internalAdapter.findPlanByCode(newPlanCode);\n const chargeResult = await ctx.paymentAdapter.charge({\n customer: {\n id: customer.id,\n email: customer.email,\n providerCustomerId: customer.providerCustomerId,\n },\n amount,\n currency: price.currency,\n description: `Renewal: ${plan?.name ?? newPlanCode} (${newInterval})`,\n metadata: {\n subscriptionId: subscription.id,\n customerId: customer.id,\n type: \"renewal\",\n planCode: newPlanCode,\n },\n });\n\n if (chargeResult.status === \"failed\") {\n ctx.logger.warn(\"Renewal charge failed\", {\n subscriptionId: subscription.id,\n error: chargeResult.error,\n });\n\n // Mark as past_due for retry on next cron run\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n status: \"past_due\",\n });\n\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"failed\",\n error: chargeResult.error ?? \"Charge failed\",\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n }\n\n // Charge succeeded - update subscription and create payment record\n const newPeriodEnd = calculateNewPeriodEnd(now, newInterval);\n\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n currentPeriodStart: now,\n currentPeriodEnd: newPeriodEnd,\n status: \"active\",\n });\n\n await ctx.internalAdapter.createPayment({\n customerId: customer.id,\n subscriptionId: subscription.id,\n type: \"renewal\",\n status: \"succeeded\",\n amount,\n currency: price.currency,\n providerPaymentId: chargeResult.providerPaymentId,\n metadata: {\n planCode: newPlanCode,\n interval: newInterval,\n },\n });\n\n ctx.logger.info(\"Renewal succeeded\", {\n subscriptionId: subscription.id,\n amount,\n newPeriodEnd: newPeriodEnd.toISOString(),\n });\n\n return {\n subscriptionId: subscription.id,\n customerId: customer.externalId,\n status: \"succeeded\",\n amount,\n planChanged: planChanged\n ? { from: subscription.planCode, to: newPlanCode }\n : undefined,\n };\n}\n\n/**\n * Process all due renewals\n *\n * This function:\n * 1. Finds all subscriptions where currentPeriodEnd <= now\n * 2. Applies any scheduled plan changes (downgrades)\n * 3. Charges the customer for the new period\n * 4. Updates the subscription period dates\n * 5. Creates payment records\n *\n * Idempotent: Running twice won't double-charge because the period dates are updated.\n */\nexport async function processRenewals(\n ctx: BillingContext,\n params: ProcessRenewalsParams = {},\n): Promise<ProcessRenewalsResult> {\n const { dryRun = false } = params;\n\n ctx.logger.info(\"Starting renewal processing\", {\n dryRun,\n customerId: params.customerId,\n limit: params.limit,\n });\n\n // Find due subscriptions\n const dueSubscriptions = await findDueSubscriptions(ctx, params);\n\n ctx.logger.info(\n `Found ${dueSubscriptions.length} subscriptions due for renewal`,\n );\n\n const result: ProcessRenewalsResult = {\n processed: 0,\n succeeded: 0,\n failed: 0,\n skipped: 0,\n renewals: [],\n };\n\n // Process each subscription\n for (const subscription of dueSubscriptions) {\n result.processed++;\n\n try {\n const renewalResult = await processSubscriptionRenewal(\n ctx,\n subscription,\n dryRun,\n );\n\n result.renewals.push(renewalResult);\n\n if (renewalResult.status === \"succeeded\") {\n result.succeeded++;\n } else if (renewalResult.status === \"failed\") {\n result.failed++;\n } else {\n result.skipped++;\n }\n } catch (error) {\n ctx.logger.error(\"Error processing renewal\", {\n subscriptionId: subscription.id,\n error: error instanceof Error ? error.message : String(error),\n });\n\n result.failed++;\n result.renewals.push({\n subscriptionId: subscription.id,\n customerId: subscription.customerId,\n status: \"failed\",\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n }\n }\n\n ctx.logger.info(\"Renewal processing complete\", {\n processed: result.processed,\n succeeded: result.succeeded,\n failed: result.failed,\n skipped: result.skipped,\n });\n\n return result;\n}\n","import { z } from \"zod\";\nimport type { BillingContext } from \"../../context/create-context\";\nimport { processRenewals } from \"../../logic/renewal-service\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Query schema for renewals endpoint\n */\nconst processRenewalsQuerySchema = z.object({\n /**\n * Process only a specific customer (useful for testing)\n */\n customerId: z.string().optional(),\n\n /**\n * Dry run - don't actually charge, just report what would happen\n */\n dryRun: z\n .string()\n .transform((val) => val === \"true\")\n .optional(),\n\n /**\n * Maximum number of subscriptions to process (for batching)\n */\n limit: z\n .string()\n .transform((val) => Number.parseInt(val, 10))\n .refine((val) => !Number.isNaN(val) && val > 0, {\n message: \"limit must be a positive number\",\n })\n .optional(),\n});\n\n/**\n * Renewals endpoints\n *\n * GET /renewals - Process all due renewals\n *\n * This is designed to be called by a cron job (e.g., Vercel Cron).\n * The user just needs to add this to vercel.json:\n *\n * ```json\n * {\n * \"crons\": [{\n * \"path\": \"/api/billing/renewals\",\n * \"schedule\": \"0 * * * *\"\n * }]\n * }\n * ```\n */\nexport const renewalEndpoints: Record<string, BillingEndpoint> = {\n processRenewals: {\n path: \"/renewals\",\n options: {\n method: \"GET\",\n query: processRenewalsQuerySchema,\n },\n handler: async (\n context: EndpointContext<\n unknown,\n z.infer<typeof processRenewalsQuerySchema>\n >,\n ) => {\n const { ctx, query } = context;\n\n const result = await processRenewals(ctx as BillingContext, {\n customerId: query.customerId,\n dryRun: query.dryRun ?? false,\n limit: query.limit,\n });\n\n return result;\n },\n },\n};\n","import { z } from \"zod\";\nimport type { BillingContext } from \"../../context/create-context\";\nimport { runBehavior } from \"../../logic/behaviors/runner\";\nimport {\n changeSubscription as changeSubscriptionService,\n createSubscription as createSubscriptionService,\n} from \"../../logic/subscription-service\";\nimport type { BillingEndpoint, EndpointContext } from \"../../types/api\";\n\n/**\n * Get subscription query schema\n */\nconst getSubscriptionQuerySchema = z.object({\n customerId: z.string().min(1),\n});\n\n/**\n * Create subscription schema\n * successUrl and cancelUrl are optional - only required if payment adapter needs them\n */\nconst createSubscriptionSchema = z.object({\n customerId: z.string().min(1),\n planCode: z.string().min(1),\n interval: z.enum([\"monthly\", \"yearly\"]).optional().default(\"monthly\"),\n successUrl: z.string().url().optional(),\n cancelUrl: z.string().url().optional(),\n});\n\n/**\n * Cancel subscription schema\n */\nconst cancelSubscriptionSchema = z.object({\n customerId: z.string().min(1),\n cancelAt: z\n .enum([\"period_end\", \"immediately\"])\n .optional()\n .default(\"period_end\"),\n});\n\n/**\n * Change subscription (upgrade/downgrade) schema\n */\nconst changeSubscriptionSchema = z.object({\n customerId: z.string().min(1),\n newPlanCode: z.string().min(1),\n /**\n * Whether to prorate the charge/credit\n * If false, the new plan starts at the next billing cycle\n */\n prorate: z.boolean().optional().default(true),\n});\n\n/**\n * Subscription endpoints\n */\nexport const subscriptionEndpoints: Record<string, BillingEndpoint> = {\n getSubscription: {\n path: \"/subscription\",\n options: {\n method: \"GET\",\n query: getSubscriptionQuerySchema,\n },\n handler: async (\n context: EndpointContext<\n unknown,\n z.infer<typeof getSubscriptionQuerySchema>\n >,\n ) => {\n const { ctx, query } = context;\n\n // Find customer by external ID\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n query.customerId,\n );\n if (!customer) {\n return { subscription: null };\n }\n\n // Find active subscription\n const subscription =\n await ctx.internalAdapter.findSubscriptionByCustomerId(customer.id);\n if (!subscription) {\n return { subscription: null };\n }\n\n // Get plan from config (synchronous)\n const plan = ctx.internalAdapter.findPlanByCode(subscription.planCode);\n const price = plan\n ? ctx.internalAdapter.getPlanPrice(\n subscription.planCode,\n subscription.interval,\n )\n : null;\n\n return {\n subscription,\n plan,\n price,\n };\n },\n },\n\n createSubscription: {\n path: \"/subscription\",\n options: {\n method: \"POST\",\n body: createSubscriptionSchema,\n },\n handler: async (\n context: EndpointContext<z.infer<typeof createSubscriptionSchema>>,\n ) => {\n const { ctx, body } = context;\n\n // Delegate to shared service\n return createSubscriptionService(ctx as BillingContext, {\n customerId: body.customerId,\n planCode: body.planCode,\n interval: body.interval,\n successUrl: body.successUrl,\n cancelUrl: body.cancelUrl,\n });\n },\n },\n\n cancelSubscription: {\n path: \"/subscription/cancel\",\n options: {\n method: \"POST\",\n body: cancelSubscriptionSchema,\n },\n handler: async (\n context: EndpointContext<z.infer<typeof cancelSubscriptionSchema>>,\n ) => {\n const { ctx, body } = context;\n\n // Delegate to behavior (default: cancel subscription)\n return runBehavior(ctx as BillingContext, \"onSubscriptionCancel\", {\n customerId: body.customerId,\n cancelAt: body.cancelAt,\n });\n },\n },\n\n changeSubscription: {\n path: \"/subscription/change\",\n options: {\n method: \"POST\",\n body: changeSubscriptionSchema,\n },\n handler: async (\n context: EndpointContext<z.infer<typeof changeSubscriptionSchema>>,\n ) => {\n const { ctx, body } = context;\n const billingCtx = ctx as BillingContext;\n return changeSubscriptionService(billingCtx, body);\n },\n },\n};\n","import type { BillingContext } from \"../../context/create-context\";\nimport type { BillingEndpoint } from \"../../types/api\";\n\n/**\n * Webhook endpoints\n */\nexport const webhookEndpoints: Record<string, BillingEndpoint> = {\n handleWebhook: {\n path: \"/webhook\",\n options: {\n method: \"POST\",\n },\n handler: async (context: { ctx: BillingContext; request: Request }) => {\n const { ctx, request } = context;\n\n if (!ctx.paymentAdapter) {\n throw new Error(\"Payment adapter not configured\");\n }\n\n // Check if payment adapter supports confirmPayment\n if (!ctx.paymentAdapter.confirmPayment) {\n // Adapter doesn't need webhooks (e.g., default adapter that activates immediately)\n ctx.logger.debug(\"Payment adapter does not support confirmPayment\");\n return { received: true };\n }\n\n // Confirm payment from webhook/callback\n const result = await ctx.paymentAdapter.confirmPayment(request);\n\n // If result is null, the event was acknowledged but not relevant to us\n if (!result) {\n ctx.logger.debug(\"Webhook event acknowledged but not processed\");\n return { received: true };\n }\n\n ctx.logger.debug(\"Payment confirmation received\", {\n subscriptionId: result.subscriptionId,\n status: result.status,\n amount: result.amount,\n });\n\n if (result.status === \"active\") {\n // Find the subscription\n const subscription = await ctx.internalAdapter.findSubscriptionById(\n result.subscriptionId,\n );\n\n if (subscription) {\n // Cancel any other active subscriptions for this customer\n const existingSubscriptions =\n await ctx.internalAdapter.listSubscriptions(\n subscription.customerId,\n );\n\n for (const existing of existingSubscriptions) {\n if (\n existing.id !== subscription.id &&\n (existing.status === \"active\" || existing.status === \"trialing\")\n ) {\n await ctx.internalAdapter.cancelSubscription(existing.id);\n ctx.logger.info(\"Canceled previous subscription\", {\n subscriptionId: existing.id,\n planCode: existing.planCode,\n });\n }\n }\n\n // Update subscription to active\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n status: \"active\",\n providerSubscriptionId: result.providerSubscriptionId,\n });\n\n // Update customer provider ID if present\n if (result.providerCustomerId) {\n const customer = await ctx.internalAdapter.findCustomerById(\n subscription.customerId,\n );\n if (customer && !customer.providerCustomerId) {\n await ctx.internalAdapter.updateCustomer(customer.id, {\n providerCustomerId: result.providerCustomerId,\n });\n }\n }\n\n // Create payment record if a payment was made\n if (result.amount && result.amount > 0) {\n await ctx.internalAdapter.createPayment({\n customerId: subscription.customerId,\n subscriptionId: subscription.id,\n type: \"subscription\",\n status: \"succeeded\",\n amount: result.amount,\n currency: result.currency ?? \"usd\",\n providerPaymentId: result.providerPaymentId,\n metadata: {\n planCode: subscription.planCode,\n interval: subscription.interval,\n confirmedVia: \"webhook\",\n },\n });\n\n ctx.logger.info(\"Payment record created\", {\n subscriptionId: subscription.id,\n amount: result.amount,\n currency: result.currency,\n providerPaymentId: result.providerPaymentId,\n });\n }\n\n ctx.logger.info(\"Subscription activated via webhook\", {\n subscriptionId: subscription.id,\n providerSubscriptionId: result.providerSubscriptionId,\n });\n } else {\n ctx.logger.warn(\"Subscription not found for confirmation\", {\n subscriptionId: result.subscriptionId,\n });\n }\n } else if (result.status === \"failed\") {\n // Mark subscription as failed/canceled\n const subscription = await ctx.internalAdapter.findSubscriptionById(\n result.subscriptionId,\n );\n\n if (subscription) {\n await ctx.internalAdapter.updateSubscription(subscription.id, {\n status: \"canceled\",\n });\n ctx.logger.warn(\"Payment failed, subscription canceled\", {\n subscriptionId: subscription.id,\n });\n }\n }\n\n return { received: true };\n },\n },\n};\n","import type { BillingContext } from \"../context/create-context\";\nimport type { BillingEndpoint } from \"../types/api\";\nimport { customerEndpoints } from \"./routes/customer\";\nimport { featureEndpoints } from \"./routes/features\";\nimport { healthEndpoint } from \"./routes/health\";\nimport { paymentEndpoints } from \"./routes/payment\";\nimport { planEndpoints } from \"./routes/plan\";\nimport { refundEndpoints } from \"./routes/refund\";\nimport { renewalEndpoints } from \"./routes/renewals\";\nimport { subscriptionEndpoints } from \"./routes/subscription\";\nimport { webhookEndpoints } from \"./routes/webhook\";\n\n/**\n * Collect all endpoints\n */\nexport function getEndpoints(\n ctx: BillingContext,\n): Record<string, BillingEndpoint> {\n const baseEndpoints: Record<string, BillingEndpoint> = {\n ...healthEndpoint,\n ...customerEndpoints,\n ...planEndpoints,\n ...subscriptionEndpoints,\n ...featureEndpoints,\n ...paymentEndpoints,\n ...refundEndpoints,\n ...renewalEndpoints,\n ...webhookEndpoints,\n };\n\n // Add plugin endpoints\n let allEndpoints = { ...baseEndpoints };\n for (const plugin of ctx.plugins) {\n if (plugin.endpoints) {\n allEndpoints = { ...allEndpoints, ...plugin.endpoints };\n }\n }\n\n return allEndpoints;\n}\n\n/**\n * Parse URL to get path and query params\n */\nfunction parseUrl(\n url: string,\n basePath: string,\n): { path: string; query: URLSearchParams } {\n const urlObj = new URL(url);\n let path = urlObj.pathname;\n\n // Remove base path\n if (path.startsWith(basePath)) {\n path = path.slice(basePath.length);\n }\n\n // Ensure path starts with /\n if (!path.startsWith(\"/\")) {\n path = `/${path}`;\n }\n\n return { path, query: urlObj.searchParams };\n}\n\n/**\n * Parse query params to object\n */\nfunction queryToObject(query: URLSearchParams): Record<string, string> {\n const obj: Record<string, string> = {};\n query.forEach((value, key) => {\n obj[key] = value;\n });\n return obj;\n}\n\n/**\n * Create a JSON response\n */\nfunction jsonResponse(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n}\n\n/**\n * Create an error response\n */\nfunction errorResponse(code: string, message: string, status = 400): Response {\n return jsonResponse({ error: { code, message } }, status);\n}\n\n/**\n * Create the router\n */\nexport function createRouter(ctx: BillingContext): {\n handler: (request: Request) => Promise<Response>;\n endpoints: Record<string, BillingEndpoint>;\n} {\n const endpoints = getEndpoints(ctx);\n\n const handler = async (request: Request): Promise<Response> => {\n const method = request.method.toUpperCase();\n const { path, query } = parseUrl(request.url, ctx.basePath);\n\n ctx.logger.debug(`${method} ${path}`);\n\n // Run before hooks\n if (ctx.options.hooks.before) {\n const result = await ctx.options.hooks.before({\n request,\n path,\n method,\n });\n if (result instanceof Response) {\n return result;\n }\n }\n\n // Run plugin before hooks\n for (const plugin of ctx.plugins) {\n if (plugin.hooks?.before) {\n for (const hook of plugin.hooks.before) {\n if (hook.matcher({ path, method })) {\n const result = await hook.handler({\n request,\n path,\n method,\n billingContext: ctx,\n });\n if (result instanceof Response) {\n return result;\n }\n }\n }\n }\n }\n\n // Find matching endpoint\n const endpointKey = Object.keys(endpoints).find((key) => {\n const endpoint = endpoints[key];\n if (!endpoint) return false;\n\n // Check method\n if (endpoint.options.method !== method) return false;\n\n // Check path (simple matching for now)\n // TODO: Add path params support\n return endpoint.path === path;\n });\n\n if (!endpointKey) {\n return errorResponse(\n \"NOT_FOUND\",\n `No endpoint found for ${method} ${path}`,\n 404,\n );\n }\n\n const endpoint = endpoints[endpointKey]!;\n\n try {\n const requestForHandler = request.clone();\n\n // Parse body for POST/PUT/PATCH\n let body: unknown;\n if ([\"POST\", \"PUT\", \"PATCH\"].includes(method) && endpoint.options.body) {\n try {\n const text = await request.text();\n if (text) {\n body = JSON.parse(text);\n }\n } catch {\n // Body might be empty or not JSON\n }\n }\n\n // Validate body if schema provided\n if (endpoint.options.body && body) {\n const result = endpoint.options.body.safeParse(body);\n if (!result.success) {\n const issues = \"issues\" in result.error ? result.error.issues : [];\n return errorResponse(\n \"VALIDATION_ERROR\",\n (issues as Array<{ message: string }>)\n .map((e) => e.message)\n .join(\", \"),\n 400,\n );\n }\n body = result.data;\n }\n\n // Validate query if schema provided\n let queryObj: Record<string, string> = queryToObject(query);\n if (endpoint.options.query) {\n const result = endpoint.options.query.safeParse(queryObj);\n if (!result.success) {\n const issues = \"issues\" in result.error ? result.error.issues : [];\n return errorResponse(\n \"VALIDATION_ERROR\",\n (issues as Array<{ message: string }>)\n .map((e) => e.message)\n .join(\", \"),\n 400,\n );\n }\n queryObj = result.data as Record<string, string>;\n }\n\n // Create endpoint context\n // Use cloned request so handlers can read the body if needed (e.g., webhooks)\n const endpointContext = {\n request: requestForHandler,\n body,\n query: queryObj,\n headers: requestForHandler.headers,\n params: {},\n ctx, // Add billing context\n };\n\n // Execute handler\n // biome-ignore lint/suspicious/noExplicitAny: Each endpoint defines its own body/query types - router dispatches generically\n const response = await endpoint.handler(endpointContext as any);\n\n // Run after hooks\n let finalResponse = jsonResponse(response);\n\n // Run plugin after hooks\n for (const plugin of ctx.plugins) {\n if (plugin.hooks?.after) {\n for (const hook of plugin.hooks.after) {\n if (hook.matcher({ path, method })) {\n const result = await hook.handler({\n request,\n path,\n method,\n billingContext: ctx,\n });\n if (result instanceof Response) {\n finalResponse = result;\n }\n }\n }\n }\n }\n\n if (ctx.options.hooks.after) {\n const result = await ctx.options.hooks.after({\n request,\n path,\n method,\n });\n if (result instanceof Response) {\n finalResponse = result;\n }\n }\n\n return finalResponse;\n } catch (error) {\n ctx.logger.error(\"Endpoint error\", error);\n\n if (error instanceof Error) {\n return errorResponse(\"INTERNAL_ERROR\", error.message, 500);\n }\n\n return errorResponse(\n \"INTERNAL_ERROR\",\n \"An unexpected error occurred\",\n 500,\n );\n }\n };\n\n return { handler, endpoints };\n}\n","import type { DBAdapter } from \"../types/adapter\";\nimport type {\n BillingInterval,\n CreateCustomerInput,\n CreatePaymentInput,\n CreateSubscriptionInput,\n Customer,\n Feature,\n Payment,\n Plan,\n PlanPrice,\n Subscription,\n} from \"../types/models\";\nimport type { FeatureConfig, PlanConfig } from \"../types/options\";\nimport { TABLES } from \"./schema\";\n\n/**\n * Internal adapter that wraps DBAdapter with business logic\n * Plans and features come from config, only customer/subscription from DB\n */\nexport interface InternalAdapter {\n // Customer operations (DB)\n createCustomer(data: CreateCustomerInput): Promise<Customer>;\n findCustomerById(id: string): Promise<Customer | null>;\n findCustomerByExternalId(externalId: string): Promise<Customer | null>;\n updateCustomer(id: string, data: Partial<Customer>): Promise<Customer | null>;\n deleteCustomer(id: string): Promise<void>;\n listCustomers(options?: {\n limit?: number;\n offset?: number;\n }): Promise<Customer[]>;\n\n // Plan operations (from config)\n findPlanByCode(code: string): Plan | null;\n listPlans(options?: { includePrivate?: boolean }): Plan[];\n getPlanPrice(planCode: string, interval: BillingInterval): PlanPrice | null;\n\n // Feature operations (from config)\n findFeatureByCode(code: string): Feature | null;\n listFeatures(): Feature[];\n getPlanFeatures(planCode: string): string[];\n\n // Subscription operations (DB)\n createSubscription(data: CreateSubscriptionInput): Promise<Subscription>;\n findSubscriptionById(id: string): Promise<Subscription | null>;\n findSubscriptionByCustomerId(\n customerId: string,\n ): Promise<Subscription | null>;\n findSubscriptionByProviderSessionId(\n sessionId: string,\n ): Promise<Subscription | null>;\n updateSubscription(\n id: string,\n data: Partial<Subscription>,\n ): Promise<Subscription | null>;\n cancelSubscription(id: string, cancelAt?: Date): Promise<Subscription | null>;\n listSubscriptions(customerId: string): Promise<Subscription[]>;\n\n // Feature access check\n checkFeatureAccess(\n customerId: string,\n featureCode: string,\n ): Promise<{ allowed: boolean }>;\n\n // Payment operations (DB)\n createPayment(data: CreatePaymentInput): Promise<Payment>;\n findPaymentById(id: string): Promise<Payment | null>;\n findPaymentByProviderPaymentId(\n providerPaymentId: string,\n ): Promise<Payment | null>;\n updatePayment(id: string, data: Partial<Payment>): Promise<Payment | null>;\n listPayments(\n customerId: string,\n options?: { limit?: number; offset?: number },\n ): Promise<Payment[]>;\n}\n\n/**\n * Convert PlanConfig to Plan\n */\nfunction planConfigToPlan(config: PlanConfig): Plan {\n return {\n code: config.code,\n name: config.name,\n description: config.description,\n isPublic: config.isPublic ?? true,\n prices: config.prices.map((p) => ({\n amount: p.amount,\n currency: p.currency ?? \"usd\",\n interval: p.interval,\n trialDays: p.trialDays,\n })),\n features: config.features ?? [],\n };\n}\n\n/**\n * Convert FeatureConfig to Feature\n */\nfunction featureConfigToFeature(config: FeatureConfig): Feature {\n return {\n code: config.code,\n name: config.name,\n type: config.type ?? \"boolean\",\n };\n}\n\n/**\n * Create an internal adapter from a DBAdapter and config\n */\nexport function createInternalAdapter(\n adapter: DBAdapter,\n plans: PlanConfig[] = [],\n features: FeatureConfig[] = [],\n getNow: () => Promise<Date> = async () => new Date(),\n): InternalAdapter {\n // Build lookup maps for fast access\n const plansByCode = new Map<string, Plan>();\n for (const config of plans) {\n plansByCode.set(config.code, planConfigToPlan(config));\n }\n\n const featuresByCode = new Map<string, Feature>();\n for (const config of features) {\n featuresByCode.set(config.code, featureConfigToFeature(config));\n }\n\n return {\n // Customer operations (DB)\n async createCustomer(data: CreateCustomerInput): Promise<Customer> {\n const now = await getNow();\n return adapter.create<Customer>({\n model: TABLES.CUSTOMER,\n data: {\n ...data,\n createdAt: now,\n updatedAt: now,\n } as Omit<Customer, \"id\">,\n });\n },\n\n async findCustomerById(id: string): Promise<Customer | null> {\n return adapter.findOne<Customer>({\n model: TABLES.CUSTOMER,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n });\n },\n\n async findCustomerByExternalId(\n externalId: string,\n ): Promise<Customer | null> {\n return adapter.findOne<Customer>({\n model: TABLES.CUSTOMER,\n where: [{ field: \"externalId\", operator: \"eq\", value: externalId }],\n });\n },\n\n async updateCustomer(\n id: string,\n data: Partial<Customer>,\n ): Promise<Customer | null> {\n return adapter.update<Customer>({\n model: TABLES.CUSTOMER,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n update: { ...data, updatedAt: new Date() },\n });\n },\n\n async deleteCustomer(id: string): Promise<void> {\n await adapter.delete({\n model: TABLES.CUSTOMER,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n });\n },\n\n async listCustomers(options?: {\n limit?: number;\n offset?: number;\n }): Promise<Customer[]> {\n return adapter.findMany<Customer>({\n model: TABLES.CUSTOMER,\n limit: options?.limit,\n offset: options?.offset,\n sortBy: { field: \"createdAt\", direction: \"desc\" },\n });\n },\n\n // Plan operations (from config - synchronous)\n findPlanByCode(code: string): Plan | null {\n return plansByCode.get(code) ?? null;\n },\n\n listPlans(options?: { includePrivate?: boolean }): Plan[] {\n const allPlans = Array.from(plansByCode.values());\n if (options?.includePrivate) {\n return allPlans;\n }\n return allPlans.filter((p) => p.isPublic);\n },\n\n getPlanPrice(\n planCode: string,\n interval: BillingInterval,\n ): PlanPrice | null {\n const plan = plansByCode.get(planCode);\n if (!plan) return null;\n return (\n plan.prices.find((p) => p.interval === interval) ??\n plan.prices[0] ??\n null\n );\n },\n\n // Feature operations (from config - synchronous)\n findFeatureByCode(code: string): Feature | null {\n return featuresByCode.get(code) ?? null;\n },\n\n listFeatures(): Feature[] {\n return Array.from(featuresByCode.values());\n },\n\n getPlanFeatures(planCode: string): string[] {\n const plan = plansByCode.get(planCode);\n return plan?.features ?? [];\n },\n\n // Subscription operations (DB)\n async createSubscription(\n data: CreateSubscriptionInput,\n ): Promise<Subscription> {\n const now = await getNow();\n const interval = data.interval ?? \"monthly\";\n const currentPeriodEnd = new Date(now);\n\n // Set period end based on interval\n if (interval === \"yearly\") {\n currentPeriodEnd.setFullYear(currentPeriodEnd.getFullYear() + 1);\n } else if (interval === \"quarterly\") {\n currentPeriodEnd.setMonth(currentPeriodEnd.getMonth() + 3);\n } else {\n currentPeriodEnd.setMonth(currentPeriodEnd.getMonth() + 1);\n }\n\n let trialStart: Date | undefined;\n let trialEnd: Date | undefined;\n let status = data.status ?? \"pending_payment\";\n\n if (data.trialDays && data.trialDays > 0) {\n trialStart = now;\n trialEnd = new Date(now);\n trialEnd.setDate(trialEnd.getDate() + data.trialDays);\n status = \"trialing\";\n }\n\n return adapter.create<Subscription>({\n model: TABLES.SUBSCRIPTION,\n data: {\n customerId: data.customerId,\n planCode: data.planCode,\n interval,\n status,\n providerSubscriptionId: data.providerSubscriptionId,\n providerCheckoutSessionId: data.providerCheckoutSessionId,\n currentPeriodStart: now,\n currentPeriodEnd: trialEnd ?? currentPeriodEnd,\n trialStart,\n trialEnd,\n metadata: data.metadata,\n createdAt: now,\n updatedAt: now,\n } as Omit<Subscription, \"id\">,\n });\n },\n\n async findSubscriptionById(id: string): Promise<Subscription | null> {\n return adapter.findOne<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n });\n },\n\n async findSubscriptionByCustomerId(\n customerId: string,\n ): Promise<Subscription | null> {\n return adapter.findOne<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [\n { field: \"customerId\", operator: \"eq\", value: customerId },\n {\n field: \"status\",\n operator: \"in\",\n value: [\"active\", \"trialing\", \"past_due\", \"pending_payment\"],\n },\n ],\n });\n },\n\n async findSubscriptionByProviderSessionId(\n sessionId: string,\n ): Promise<Subscription | null> {\n return adapter.findOne<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [\n {\n field: \"providerCheckoutSessionId\",\n operator: \"eq\",\n value: sessionId,\n },\n ],\n });\n },\n\n async updateSubscription(\n id: string,\n data: Partial<Subscription>,\n ): Promise<Subscription | null> {\n const now = await getNow();\n return adapter.update<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n update: { ...data, updatedAt: now },\n });\n },\n\n async cancelSubscription(\n id: string,\n cancelAt?: Date,\n ): Promise<Subscription | null> {\n const now = await getNow();\n return adapter.update<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n update: {\n status: cancelAt ? \"active\" : \"canceled\",\n canceledAt: now,\n cancelAt: cancelAt ?? now,\n updatedAt: now,\n },\n });\n },\n\n async listSubscriptions(customerId: string): Promise<Subscription[]> {\n return adapter.findMany<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [{ field: \"customerId\", operator: \"eq\", value: customerId }],\n sortBy: { field: \"createdAt\", direction: \"desc\" },\n });\n },\n\n // Feature access check\n async checkFeatureAccess(\n customerId: string,\n featureCode: string,\n ): Promise<{ allowed: boolean }> {\n // Find customer by external ID\n const customer = await adapter.findOne<Customer>({\n model: TABLES.CUSTOMER,\n where: [{ field: \"externalId\", operator: \"eq\", value: customerId }],\n });\n\n if (!customer) {\n return { allowed: false };\n }\n\n // Find active subscription\n const subscription = await adapter.findOne<Subscription>({\n model: TABLES.SUBSCRIPTION,\n where: [\n { field: \"customerId\", operator: \"eq\", value: customer.id },\n { field: \"status\", operator: \"in\", value: [\"active\", \"trialing\"] },\n ],\n });\n\n if (!subscription) {\n return { allowed: false };\n }\n\n // Check if plan has the feature (from config)\n const planFeatures = this.getPlanFeatures(subscription.planCode);\n return { allowed: planFeatures.includes(featureCode) };\n },\n\n // Payment operations (DB)\n async createPayment(data: CreatePaymentInput): Promise<Payment> {\n const now = await getNow();\n return adapter.create<Payment>({\n model: TABLES.PAYMENT,\n data: {\n customerId: data.customerId,\n subscriptionId: data.subscriptionId,\n type: data.type,\n status: data.status ?? \"pending\",\n amount: data.amount,\n currency: data.currency ?? \"usd\",\n providerPaymentId: data.providerPaymentId,\n metadata: data.metadata,\n createdAt: now,\n updatedAt: now,\n } as Omit<Payment, \"id\">,\n });\n },\n\n async findPaymentById(id: string): Promise<Payment | null> {\n return adapter.findOne<Payment>({\n model: TABLES.PAYMENT,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n });\n },\n\n async findPaymentByProviderPaymentId(\n providerPaymentId: string,\n ): Promise<Payment | null> {\n return adapter.findOne<Payment>({\n model: TABLES.PAYMENT,\n where: [\n {\n field: \"providerPaymentId\",\n operator: \"eq\",\n value: providerPaymentId,\n },\n ],\n });\n },\n\n async updatePayment(\n id: string,\n data: Partial<Payment>,\n ): Promise<Payment | null> {\n return adapter.update<Payment>({\n model: TABLES.PAYMENT,\n where: [{ field: \"id\", operator: \"eq\", value: id }],\n update: { ...data, updatedAt: new Date() },\n });\n },\n\n async listPayments(\n customerId: string,\n options?: { limit?: number; offset?: number },\n ): Promise<Payment[]> {\n return adapter.findMany<Payment>({\n model: TABLES.PAYMENT,\n where: [{ field: \"customerId\", operator: \"eq\", value: customerId }],\n limit: options?.limit,\n offset: options?.offset,\n sortBy: { field: \"createdAt\", direction: \"desc\" },\n });\n },\n };\n}\n","import { createDefaultTimeProvider, type TimeProvider } from \"@billsdk/core\";\nimport {\n createInternalAdapter,\n type InternalAdapter,\n} from \"../db/internal-adapter\";\nimport { type DBSchema, getBillingSchema } from \"../db/schema\";\nimport type { DBAdapter } from \"../types/adapter\";\nimport type { BillSDKOptions, ResolvedBillSDKOptions } from \"../types/options\";\nimport type { PaymentAdapter } from \"../types/payment\";\nimport type { BillSDKPlugin } from \"../types/plugins\";\n\n/**\n * Logger interface for the billing context\n */\nexport interface Logger {\n debug: (message: string, ...args: unknown[]) => void;\n info: (message: string, ...args: unknown[]) => void;\n warn: (message: string, ...args: unknown[]) => void;\n error: (message: string, ...args: unknown[]) => void;\n}\n\n/**\n * The billing context containing all runtime state\n */\nexport interface BillingContext {\n /**\n * Resolved options with defaults\n */\n options: ResolvedBillSDKOptions;\n\n /**\n * Base path for the API\n */\n basePath: string;\n\n /**\n * Database adapter\n */\n adapter: DBAdapter;\n\n /**\n * Payment adapter (optional)\n */\n paymentAdapter?: PaymentAdapter;\n\n /**\n * Internal adapter with business logic\n */\n internalAdapter: InternalAdapter;\n\n /**\n * Database schema\n */\n schema: DBSchema;\n\n /**\n * Registered plugins\n */\n plugins: BillSDKPlugin[];\n\n /**\n * Logger instance\n */\n logger: Logger;\n\n /**\n * Secret for signing\n */\n secret: string;\n\n /**\n * Time provider for getting current time\n * Can be overridden by plugins (e.g., time-travel) for testing\n */\n timeProvider: TimeProvider;\n\n /**\n * Check if a plugin is registered\n */\n hasPlugin: (id: string) => boolean;\n\n /**\n * Get a plugin by ID\n */\n getPlugin: <T extends BillSDKPlugin>(id: string) => T | null;\n\n /**\n * Generate a unique ID\n */\n generateId: () => string;\n}\n\n/**\n * Create a logger instance\n */\nfunction createLogger(options: BillSDKOptions[\"logger\"]): Logger {\n const level = options?.level ?? \"info\";\n const disabled = options?.disabled ?? false;\n\n const levels = [\"debug\", \"info\", \"warn\", \"error\"];\n const currentLevelIndex = levels.indexOf(level);\n\n const shouldLog = (logLevel: string) => {\n if (disabled) return false;\n return levels.indexOf(logLevel) >= currentLevelIndex;\n };\n\n return {\n debug: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"debug\")) console.debug(`[billsdk] ${message}`, ...args);\n },\n info: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"info\")) console.info(`[billsdk] ${message}`, ...args);\n },\n warn: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"warn\")) console.warn(`[billsdk] ${message}`, ...args);\n },\n error: (message: string, ...args: unknown[]) => {\n if (shouldLog(\"error\")) console.error(`[billsdk] ${message}`, ...args);\n },\n };\n}\n\n/**\n * Resolve options with defaults\n */\nfunction resolveOptions(\n options: BillSDKOptions,\n adapter: DBAdapter,\n): ResolvedBillSDKOptions {\n return {\n database: adapter,\n payment: options.payment,\n basePath: options.basePath ?? \"/api/billing\",\n secret: options.secret ?? generateDefaultSecret(),\n plans: options.plans,\n features: options.features,\n plugins: options.plugins ?? [],\n hooks: options.hooks ?? {},\n behaviors: options.behaviors,\n logger: {\n level: options.logger?.level ?? \"info\",\n disabled: options.logger?.disabled ?? false,\n },\n };\n}\n\n/**\n * Generate a default secret (for development only)\n */\nfunction generateDefaultSecret(): string {\n return \"billsdk-development-secret-change-in-production\";\n}\n\n/**\n * Create the billing context\n */\nexport async function createBillingContext(\n adapter: DBAdapter,\n options: BillSDKOptions,\n): Promise<BillingContext> {\n const resolvedOptions = resolveOptions(options, adapter);\n const logger = createLogger(options.logger);\n const plugins = resolvedOptions.plugins;\n\n // Get base schema\n let schema = getBillingSchema();\n\n // Extend schema with plugins\n for (const plugin of plugins) {\n if (plugin.schema) {\n schema = { ...schema, ...plugin.schema };\n }\n }\n\n // Timestamps like createdAt/updatedAt should always be real system time\n const getNow = async () => new Date();\n\n const internalAdapter = createInternalAdapter(\n adapter,\n options.plans ?? [],\n options.features ?? [],\n getNow,\n );\n\n // Build context\n const context: BillingContext = {\n options: resolvedOptions,\n basePath: resolvedOptions.basePath,\n adapter,\n paymentAdapter: options.payment,\n internalAdapter,\n schema,\n plugins,\n logger,\n secret: resolvedOptions.secret,\n timeProvider: createDefaultTimeProvider(),\n\n hasPlugin(id: string): boolean {\n return plugins.some((p) => p.id === id);\n },\n\n getPlugin<T extends BillSDKPlugin>(id: string): T | null {\n const plugin = plugins.find((p) => p.id === id);\n return (plugin as T) ?? null;\n },\n\n generateId(): string {\n return crypto.randomUUID();\n },\n };\n\n // Initialize plugins (may override timeProvider)\n for (const plugin of plugins) {\n if (plugin.init) {\n await plugin.init(context);\n }\n }\n\n logger.debug(\"BillingContext created\", {\n basePath: context.basePath,\n plugins: plugins.map((p) => p.id),\n hasPaymentAdapter: !!context.paymentAdapter,\n plans: options.plans?.length ?? 0,\n features: options.features?.length ?? 0,\n });\n\n return context;\n}\n","import { memoryAdapter } from \"../adapters/memory-adapter\";\nimport { paymentAdapter } from \"../adapters/payment\";\nimport { createRouter } from \"../api\";\nimport {\n type BillingContext,\n createBillingContext,\n} from \"../context/create-context\";\nimport { runBehavior } from \"../logic/behaviors/runner\";\nimport { processRenewals as processRenewalsService } from \"../logic/renewal-service\";\nimport {\n changeSubscription as changeSubscriptionService,\n createSubscription as createSubscriptionService,\n} from \"../logic/subscription-service\";\nimport type { BillSDK, InferredAPI } from \"../types/billsdk\";\nimport type { BillSDKOptions, FeatureConfig } from \"../types/options\";\n\n/**\n * Base error codes for BillSDK\n */\nconst BASE_ERROR_CODES = {\n CUSTOMER_NOT_FOUND: \"CUSTOMER_NOT_FOUND\",\n PLAN_NOT_FOUND: \"PLAN_NOT_FOUND\",\n SUBSCRIPTION_NOT_FOUND: \"SUBSCRIPTION_NOT_FOUND\",\n FEATURE_NOT_FOUND: \"FEATURE_NOT_FOUND\",\n PAYMENT_ADAPTER_NOT_CONFIGURED: \"PAYMENT_ADAPTER_NOT_CONFIGURED\",\n INVALID_REQUEST: \"INVALID_REQUEST\",\n INTERNAL_ERROR: \"INTERNAL_ERROR\",\n} as const;\n\n/**\n * Create the API object for direct server-side access\n * The generic is for type inference only - runtime behavior is the same\n */\nfunction createAPI<TFeatureCode extends string = string>(\n contextPromise: Promise<BillingContext>,\n): InferredAPI<TFeatureCode> {\n return {\n async getCustomer(params) {\n const ctx = await contextPromise;\n return ctx.internalAdapter.findCustomerByExternalId(params.externalId);\n },\n\n async createCustomer(data) {\n const ctx = await contextPromise;\n return ctx.internalAdapter.createCustomer(data);\n },\n\n async listPlans() {\n const ctx = await contextPromise;\n // Plans come from config, synchronous\n return ctx.internalAdapter.listPlans();\n },\n\n async getPlan(params) {\n const ctx = await contextPromise;\n // Plans come from config, synchronous\n return ctx.internalAdapter.findPlanByCode(params.code);\n },\n\n async getSubscription(params) {\n const ctx = await contextPromise;\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n params.customerId,\n );\n if (!customer) return null;\n return ctx.internalAdapter.findSubscriptionByCustomerId(customer.id);\n },\n\n async createSubscription(params) {\n const ctx = await contextPromise;\n\n // Delegate to shared service\n return createSubscriptionService(ctx, {\n customerId: params.customerId,\n planCode: params.planCode,\n interval: params.interval,\n successUrl: params.successUrl,\n cancelUrl: params.cancelUrl,\n });\n },\n\n async cancelSubscription(params) {\n const ctx = await contextPromise;\n\n // Delegate to behavior (default: cancel subscription)\n const result = await runBehavior(ctx, \"onSubscriptionCancel\", {\n customerId: params.customerId,\n cancelAt: params.cancelAt,\n });\n\n return result.subscription;\n },\n\n async changeSubscription(params) {\n const ctx = await contextPromise;\n return changeSubscriptionService(ctx, params);\n },\n\n async checkFeature(params) {\n const ctx = await contextPromise;\n return ctx.internalAdapter.checkFeatureAccess(\n params.customerId,\n params.feature,\n );\n },\n\n async listFeatures(params) {\n const ctx = await contextPromise;\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n params.customerId,\n );\n if (!customer) return [];\n\n const subscription =\n await ctx.internalAdapter.findSubscriptionByCustomerId(customer.id);\n if (!subscription) return [];\n\n // Get features from config (synchronous)\n const featureCodes = ctx.internalAdapter.getPlanFeatures(\n subscription.planCode,\n );\n return featureCodes.map((code) => {\n const feature = ctx.internalAdapter.findFeatureByCode(code);\n return feature\n ? {\n code: feature.code as TFeatureCode,\n name: feature.name,\n enabled: true as const,\n }\n : { code: code as TFeatureCode, name: code, enabled: true as const };\n });\n },\n\n async health() {\n return {\n status: \"ok\" as const,\n timestamp: new Date().toISOString(),\n };\n },\n\n async listPayments(params) {\n const ctx = await contextPromise;\n const customer = await ctx.internalAdapter.findCustomerByExternalId(\n params.customerId,\n );\n if (!customer) return [];\n return ctx.internalAdapter.listPayments(customer.id, {\n limit: params.limit,\n offset: params.offset,\n });\n },\n\n async getPayment(params) {\n const ctx = await contextPromise;\n return ctx.internalAdapter.findPaymentById(params.paymentId);\n },\n\n async createRefund(params) {\n const ctx = await contextPromise;\n\n // Delegate to behavior (default: refund + cancel subscription)\n return runBehavior(ctx, \"onRefund\", {\n paymentId: params.paymentId,\n amount: params.amount,\n reason: params.reason,\n });\n },\n\n async processRenewals(params) {\n const ctx = await contextPromise;\n return processRenewalsService(ctx, params);\n },\n };\n}\n\n/**\n * Initialize the billing context\n */\nasync function init(options: BillSDKOptions): Promise<BillingContext> {\n const database = options.database ?? memoryAdapter();\n const payment = options.payment ?? paymentAdapter();\n return createBillingContext(database, { ...options, payment });\n}\n\n/**\n * Create a BillSDK instance\n *\n * @param options - Configuration options\n * @returns BillSDK instance\n */\n// biome-ignore lint/suspicious/noExplicitAny: TypeScript requires `any` here to support both readonly and mutable feature arrays (const vs let)\nexport function createBillSDK<Options extends BillSDKOptions<any>>(\n options: Options,\n): BillSDK<Options> {\n // Lazy initialization - context is created only when needed\n const contextPromise = init(options);\n\n // Collect error codes from plugins\n const errorCodes: Record<string, string> = {};\n for (const plugin of options.plugins ?? []) {\n if (plugin.$ERROR_CODES) {\n Object.assign(errorCodes, plugin.$ERROR_CODES);\n }\n }\n\n // Create the request handler\n const handler = async (request: Request): Promise<Response> => {\n const ctx = await contextPromise;\n const { handler: routeHandler } = createRouter(ctx);\n return routeHandler(request);\n };\n\n // Create the API object\n // Type assertion needed because runtime uses string but we want type inference\n const api = createAPI(contextPromise) as BillSDK<Options>[\"api\"];\n\n return {\n handler,\n api,\n options,\n $context: contextPromise,\n $Infer: {} as BillSDK<Options>[\"$Infer\"],\n $ERROR_CODES: {\n ...BASE_ERROR_CODES,\n ...errorCodes,\n } as BillSDK<Options>[\"$ERROR_CODES\"],\n };\n}\n\n/**\n * Create a BillSDK instance\n *\n * @example\n * ```typescript\n * import { billsdk } from \"@billsdk/core\";\n *\n * export const billing = billsdk({\n * basePath: \"/api/billing\",\n * features: [\n * { code: \"export\", name: \"Export\" },\n * ],\n * plans: [\n * { code: \"pro\", features: [\"export\"] }, // Validated!\n * ],\n * });\n * ```\n */\nexport function billsdk<\n const TFeatures extends readonly FeatureConfig<string>[],\n>(options: BillSDKOptions<TFeatures>): BillSDK<BillSDKOptions<TFeatures>> {\n // biome-ignore lint/suspicious/noExplicitAny: Bridging `const` inference (readonly[]) to createBillSDK's mutable array expectation\n return createBillSDK(options as any);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "billsdk",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "The billing SDK for SaaS applications",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -86,16 +86,16 @@
86
86
  "dependencies": {
87
87
  "defu": "6.1.4",
88
88
  "zod": "4.3.5",
89
- "@billsdk/drizzle-adapter": "1.0.1",
90
- "@billsdk/core": "0.3.0",
91
- "@billsdk/memory-adapter": "1.0.1",
92
- "@billsdk/payment-adapter": "1.0.1"
89
+ "@billsdk/core": "0.4.0",
90
+ "@billsdk/drizzle-adapter": "1.0.3",
91
+ "@billsdk/memory-adapter": "1.0.3",
92
+ "@billsdk/payment-adapter": "1.0.3"
93
93
  },
94
94
  "devDependencies": {
95
95
  "@biomejs/biome": "2.3.11",
96
96
  "@types/node": "22.15.29",
97
- "@types/react": "^19.0.0",
98
- "react": "^19.0.0",
97
+ "@types/react": "19.2.10",
98
+ "react": "19.2.4",
99
99
  "tsup": "8.5.1",
100
100
  "typescript": "5.9.3",
101
101
  "vitest": "4.0.17"