next-form-request 0.1.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ZodAdapter-D7D3Sc-a.d.mts → ZodAdapter-Ni7VwvnR.d.mts} +1 -1
- package/dist/{ZodAdapter-D7D3Sc-a.d.ts → ZodAdapter-Ni7VwvnR.d.ts} +1 -1
- package/dist/adapters/validators/ZodAdapter.d.mts +1 -1
- package/dist/adapters/validators/ZodAdapter.d.ts +1 -1
- package/dist/index.d.mts +849 -15
- package/dist/index.d.ts +849 -15
- package/dist/index.js +987 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +958 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/types.ts","../src/core/errors.ts","../src/core/FormRequest.ts","../src/middleware/withRequest.ts","../src/adapters/validators/ZodAdapter.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { NextApiRequest } from 'next';\n\n/**\n * Validation errors mapped by field name to array of error messages\n */\nexport type ValidationErrors = Record<string, string[]>;\n\n/**\n * Result of a validation operation\n */\nexport interface ValidationResult<T> {\n success: boolean;\n data?: T;\n errors?: ValidationErrors;\n}\n\n/**\n * Configuration options for custom error messages and attribute names\n */\nexport interface ValidationConfig {\n messages?: Record<string, string>;\n attributes?: Record<string, string>;\n}\n\n/**\n * Adapter interface for validation libraries (Zod, Yup, etc.)\n */\nexport interface ValidatorAdapter<T> {\n /**\n * Validate data asynchronously\n */\n validate(data: unknown, config?: ValidationConfig): Promise<ValidationResult<T>>;\n\n /**\n * Validate data synchronously (optional)\n */\n validateSync?(data: unknown, config?: ValidationConfig): ValidationResult<T>;\n}\n\n/**\n * Data extracted from the incoming request\n */\nexport interface RequestData {\n body: unknown;\n query: Record<string, string | string[] | undefined>;\n params: Record<string, string>;\n headers: Record<string, string | string[] | undefined>;\n}\n\n/**\n * Union type for supported request types\n */\nexport type SupportedRequest = Request | NextApiRequest;\n\n/**\n * Type guard to check if request is App Router Request\n */\nexport function isAppRouterRequest(request: SupportedRequest): request is Request {\n return 'headers' in request && request.headers instanceof Headers;\n}\n\n/**\n * Type guard to check if request is Pages Router NextApiRequest\n */\nexport function isPagesRouterRequest(request: SupportedRequest): request is NextApiRequest {\n return 'query' in request && !('headers' in request && request.headers instanceof Headers);\n}\n\n/**\n * Constructor type for FormRequest classes\n */\nexport interface FormRequestConstructor<T, TValidated> {\n new (): T;\n fromAppRouter(request: Request, params?: Record<string, string>): Promise<T>;\n fromPagesRouter(request: NextApiRequest, params?: Record<string, string>): Promise<T>;\n}\n\n/**\n * Handler function for App Router withRequest wrapper\n */\nexport type AppRouterHandler<TValidated> = (\n validated: TValidated,\n request: Request\n) => Response | Promise<Response>;\n\n/**\n * Handler function for Pages Router withApiRequest wrapper\n */\nexport type PagesRouterHandler<TValidated> = (\n validated: TValidated,\n request: NextApiRequest,\n response: import('next').NextApiResponse\n) => void | Promise<void>;\n","import type { ValidationErrors } from './types';\n\n/**\n * Error thrown when request validation fails\n */\nexport class ValidationError extends Error {\n public readonly errors: ValidationErrors;\n\n constructor(errors: ValidationErrors) {\n const firstError = Object.values(errors)[0]?.[0] ?? 'Validation failed';\n super(firstError);\n this.name = 'ValidationError';\n this.errors = errors;\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ValidationError);\n }\n }\n\n /**\n * Get all error messages as a flat array\n */\n getAllMessages(): string[] {\n return Object.values(this.errors).flat();\n }\n\n /**\n * Get errors for a specific field\n */\n getFieldErrors(field: string): string[] {\n return this.errors[field] ?? [];\n }\n\n /**\n * Check if a specific field has errors\n */\n hasFieldError(field: string): boolean {\n return field in this.errors && this.errors[field].length > 0;\n }\n\n /**\n * Convert to JSON-serializable object\n */\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n errors: this.errors,\n };\n }\n}\n\n/**\n * Error thrown when request authorization fails\n */\nexport class AuthorizationError extends Error {\n constructor(message = 'Unauthorized') {\n super(message);\n this.name = 'AuthorizationError';\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, AuthorizationError);\n }\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n };\n }\n}\n","import type { NextApiRequest } from 'next';\nimport type {\n ValidatorAdapter,\n RequestData,\n SupportedRequest,\n ValidationErrors,\n} from './types';\nimport { isAppRouterRequest } from './types';\nimport { ValidationError, AuthorizationError } from './errors';\n\n/**\n * Abstract base class for form request validation.\n * Inspired by Laravel's Form Request pattern.\n *\n * @example\n * ```typescript\n * import { FormRequest, ZodAdapter } from 'next-request';\n * import { z } from 'zod';\n *\n * const schema = z.object({\n * email: z.string().email(),\n * password: z.string().min(8),\n * });\n *\n * export class LoginRequest extends FormRequest<z.infer<typeof schema>> {\n * rules() {\n * return new ZodAdapter(schema);\n * }\n *\n * async authorize() {\n * return true; // Allow all requests\n * }\n *\n * beforeValidation() {\n * this.body.email = this.body.email?.toLowerCase().trim();\n * }\n * }\n * ```\n */\nexport abstract class FormRequest<TValidated = unknown> {\n /**\n * The original request object\n */\n protected request!: SupportedRequest;\n\n /**\n * Parsed request body (mutable for beforeValidation hook)\n */\n protected body: Record<string, unknown> = {};\n\n /**\n * Query parameters from the URL\n */\n protected query: Record<string, string | string[] | undefined> = {};\n\n /**\n * Route parameters (e.g., /users/[id])\n */\n protected params: Record<string, string> = {};\n\n /**\n * Request headers\n */\n protected headers: Record<string, string | string[] | undefined> = {};\n\n /**\n * Validated data (populated after successful validation)\n */\n private _validated: TValidated | null = null;\n\n /**\n * Partial validated data (fields that passed validation)\n */\n private _safe: Partial<TValidated> = {};\n\n // ─────────────────────────────────────────────────────────────\n // ABSTRACT METHODS (must be implemented by subclasses)\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Define the validation rules for this request.\n * Return a ValidatorAdapter instance (e.g., ZodAdapter, YupAdapter).\n */\n abstract rules(): ValidatorAdapter<TValidated>;\n\n // ─────────────────────────────────────────────────────────────\n // LIFECYCLE HOOKS (can be overridden)\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Determine if the user is authorized to make this request.\n * Override this method to add authorization logic.\n *\n * @returns true if authorized, false otherwise\n */\n authorize(): boolean | Promise<boolean> {\n return true;\n }\n\n /**\n * Called before validation runs.\n * Use this to normalize or transform input data.\n *\n * @example\n * ```typescript\n * beforeValidation() {\n * this.body.email = this.body.email?.toLowerCase().trim();\n * }\n * ```\n */\n beforeValidation(): void | Promise<void> {}\n\n /**\n * Called after validation succeeds.\n * Use this for logging, analytics, or post-processing.\n *\n * @param data The validated data\n */\n afterValidation(_data: TValidated): void | Promise<void> {}\n\n /**\n * Called when validation fails.\n * Use this for logging or custom error handling.\n *\n * @param errors The validation errors\n */\n onValidationFailed(_errors: ValidationErrors): void | Promise<void> {}\n\n /**\n * Called when authorization fails.\n * Use this for logging or custom error handling.\n */\n onAuthorizationFailed(): void | Promise<void> {}\n\n // ─────────────────────────────────────────────────────────────\n // CUSTOM MESSAGES (can be overridden)\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Custom validation error messages.\n * Keys can be field names or \"field.rule\" patterns.\n *\n * @example\n * ```typescript\n * messages() {\n * return {\n * 'email.email': 'Please provide a valid email address',\n * 'password.min': 'Password must be at least 8 characters',\n * };\n * }\n * ```\n */\n messages(): Record<string, string> {\n return {};\n }\n\n /**\n * Custom attribute names for error messages.\n * Used to replace field names in error messages.\n *\n * @example\n * ```typescript\n * attributes() {\n * return {\n * 'email': 'email address',\n * 'dob': 'date of birth',\n * };\n * }\n * ```\n */\n attributes(): Record<string, string> {\n return {};\n }\n\n // ─────────────────────────────────────────────────────────────\n // STATIC FACTORY METHODS\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Create a FormRequest instance from an App Router Request.\n *\n * @param request The incoming Request object\n * @param params Route parameters (from params in route handler)\n */\n static async fromAppRouter<T extends FormRequest>(\n this: new () => T,\n request: Request,\n params: Record<string, string> = {}\n ): Promise<T> {\n const instance = new this();\n instance.request = request;\n instance.params = params;\n\n // Parse headers\n instance.headers = {};\n request.headers.forEach((value, key) => {\n instance.headers[key] = value;\n });\n\n // Parse query from URL\n const url = new URL(request.url);\n instance.query = {};\n url.searchParams.forEach((value, key) => {\n const existing = instance.query[key];\n if (existing !== undefined) {\n instance.query[key] = Array.isArray(existing)\n ? [...existing, value]\n : [existing, value];\n } else {\n instance.query[key] = value;\n }\n });\n\n // Parse body for appropriate methods\n const method = request.method.toUpperCase();\n if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {\n try {\n const contentType = request.headers.get('content-type') ?? '';\n if (contentType.includes('application/json')) {\n instance.body = await request.clone().json();\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n const text = await request.clone().text();\n const formData = new URLSearchParams(text);\n instance.body = Object.fromEntries(formData.entries());\n } else if (contentType.includes('multipart/form-data')) {\n const formData = await request.clone().formData();\n instance.body = Object.fromEntries(formData.entries());\n }\n } catch {\n instance.body = {};\n }\n }\n\n return instance;\n }\n\n /**\n * Create a FormRequest instance from a Pages Router NextApiRequest.\n *\n * @param request The incoming NextApiRequest object\n * @param params Route parameters\n */\n static async fromPagesRouter<T extends FormRequest>(\n this: new () => T,\n request: NextApiRequest,\n params: Record<string, string> = {}\n ): Promise<T> {\n const instance = new this();\n instance.request = request;\n instance.params = { ...params, ...(request.query as Record<string, string>) };\n\n // Parse headers\n instance.headers = request.headers as Record<string, string | string[] | undefined>;\n\n // Parse query - Next.js already parses this\n instance.query = request.query as Record<string, string | string[] | undefined>;\n\n // Body is already parsed by Next.js\n instance.body = (request.body as Record<string, unknown>) ?? {};\n\n return instance;\n }\n\n // ─────────────────────────────────────────────────────────────\n // CORE VALIDATION METHODS\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Run validation and return the validated data.\n * Throws ValidationError if validation fails.\n * Throws AuthorizationError if authorization fails.\n *\n * @returns The validated data with full type inference\n */\n async validate(): Promise<TValidated> {\n // Check authorization first\n const isAuthorized = await this.authorize();\n if (!isAuthorized) {\n await this.onAuthorizationFailed();\n throw new AuthorizationError();\n }\n\n // Run beforeValidation hook\n await this.beforeValidation();\n\n // Get the validator and run validation\n const validator = this.rules();\n const result = await validator.validate(this.getDataForValidation(), {\n messages: this.messages(),\n attributes: this.attributes(),\n });\n\n if (!result.success) {\n const errors = result.errors ?? { _error: ['Validation failed'] };\n await this.onValidationFailed(errors);\n throw new ValidationError(errors);\n }\n\n // Store validated data\n this._validated = result.data!;\n this._safe = result.data as Partial<TValidated>;\n\n // Run afterValidation hook\n await this.afterValidation(this._validated);\n\n return this._validated;\n }\n\n /**\n * Get the validated data (after calling validate()).\n * Throws if validate() hasn't been called successfully.\n */\n validated(): TValidated {\n if (this._validated === null) {\n throw new Error(\n 'Cannot access validated data before calling validate(). ' +\n 'Call validate() first and handle any errors.'\n );\n }\n return this._validated;\n }\n\n /**\n * Get only the fields that passed validation.\n * Safe to call even if validation hasn't completed.\n */\n safe(): Partial<TValidated> {\n return { ...this._safe };\n }\n\n /**\n * Get raw input data (body merged with query for GET requests).\n */\n all(): Record<string, unknown> {\n return { ...this.body };\n }\n\n /**\n * Get a specific input value.\n */\n input<T = unknown>(key: string, defaultValue?: T): T | undefined {\n const value = this.body[key] ?? this.query[key];\n return (value as T) ?? defaultValue;\n }\n\n /**\n * Check if input has a specific key.\n */\n has(key: string): boolean {\n return key in this.body || key in this.query;\n }\n\n /**\n * Get only specified keys from input.\n */\n only<K extends string>(...keys: K[]): Pick<Record<string, unknown>, K> {\n const result: Record<string, unknown> = {};\n for (const key of keys) {\n if (this.has(key)) {\n result[key] = this.input(key);\n }\n }\n return result as Pick<Record<string, unknown>, K>;\n }\n\n /**\n * Get all input except specified keys.\n */\n except(...keys: string[]): Record<string, unknown> {\n const result = { ...this.body };\n for (const key of keys) {\n delete result[key];\n }\n return result;\n }\n\n /**\n * Get the original request object.\n */\n getRequest(): SupportedRequest {\n return this.request;\n }\n\n /**\n * Check if this is an App Router request.\n */\n isAppRouter(): boolean {\n return isAppRouterRequest(this.request);\n }\n\n /**\n * Get a header value.\n */\n header(name: string): string | string[] | undefined {\n const lowerName = name.toLowerCase();\n if (isAppRouterRequest(this.request)) {\n return this.request.headers.get(lowerName) ?? undefined;\n }\n return this.headers[lowerName];\n }\n\n /**\n * Get a route parameter.\n */\n param(name: string): string | undefined {\n return this.params[name];\n }\n\n // ─────────────────────────────────────────────────────────────\n // PROTECTED HELPERS\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Get the data that will be validated.\n * Override this to customize what data is passed to the validator.\n */\n protected getDataForValidation(): unknown {\n return this.body;\n }\n}\n\nexport default FormRequest;\n","import type { NextApiRequest, NextApiResponse } from 'next';\nimport { FormRequest } from '../core/FormRequest';\nimport { ValidationError, AuthorizationError } from '../core/errors';\n\n/**\n * Type for FormRequest constructor\n */\ntype FormRequestClass<TValidated> = {\n new (): FormRequest<TValidated>;\n fromAppRouter(request: Request, params?: Record<string, string>): Promise<FormRequest<TValidated>>;\n fromPagesRouter(request: NextApiRequest, params?: Record<string, string>): Promise<FormRequest<TValidated>>;\n};\n\n/**\n * Handler function for App Router\n */\ntype AppRouterHandler<TValidated> = (\n validated: TValidated,\n request: Request,\n formRequest: FormRequest<TValidated>\n) => Response | Promise<Response>;\n\n/**\n * Handler function for Pages Router\n */\ntype PagesRouterHandler<TValidated> = (\n validated: TValidated,\n req: NextApiRequest,\n res: NextApiResponse,\n formRequest: FormRequest<TValidated>\n) => void | Promise<void>;\n\n/**\n * Context parameter for App Router (Next.js 13+)\n */\ninterface AppRouterContext {\n params?: Record<string, string> | Promise<Record<string, string>>;\n}\n\n/**\n * Wrap an App Router route handler with form request validation.\n *\n * The handler receives validated data and only executes if:\n * 1. Authorization passes (authorize() returns true)\n * 2. Validation passes (rules() validates successfully)\n *\n * Errors are thrown, not auto-handled - catch ValidationError and\n * AuthorizationError in your handler or error boundary.\n *\n * @example\n * ```typescript\n * // app/api/users/route.ts\n * import { withRequest } from 'next-request';\n * import { CreateUserRequest } from '@/requests/CreateUserRequest';\n *\n * export const POST = withRequest(CreateUserRequest, async (data, request) => {\n * const user = await db.users.create({ data });\n * return Response.json({ user }, { status: 201 });\n * });\n * ```\n */\nexport function withRequest<TValidated>(\n RequestClass: FormRequestClass<TValidated>,\n handler: AppRouterHandler<TValidated>\n): (request: Request, context?: AppRouterContext) => Promise<Response> {\n return async (request: Request, context?: AppRouterContext) => {\n // Resolve params (may be a Promise in Next.js 15+)\n const params = context?.params\n ? (context.params instanceof Promise ? await context.params : context.params)\n : {};\n\n const formRequest = await RequestClass.fromAppRouter(request, params);\n const validated = await formRequest.validate();\n\n return handler(validated, request, formRequest);\n };\n}\n\n/**\n * Wrap a Pages Router API handler with form request validation.\n *\n * The handler receives validated data and only executes if:\n * 1. Authorization passes (authorize() returns true)\n * 2. Validation passes (rules() validates successfully)\n *\n * Errors are thrown, not auto-handled - catch ValidationError and\n * AuthorizationError in your handler.\n *\n * @example\n * ```typescript\n * // pages/api/users.ts\n * import { withApiRequest } from 'next-request';\n * import { CreateUserRequest } from '@/requests/CreateUserRequest';\n *\n * export default withApiRequest(CreateUserRequest, async (data, req, res) => {\n * const user = await db.users.create({ data });\n * res.status(201).json({ user });\n * });\n * ```\n */\nexport function withApiRequest<TValidated>(\n RequestClass: FormRequestClass<TValidated>,\n handler: PagesRouterHandler<TValidated>\n): (req: NextApiRequest, res: NextApiResponse) => Promise<void> {\n return async (req: NextApiRequest, res: NextApiResponse) => {\n const formRequest = await RequestClass.fromPagesRouter(req);\n const validated = await formRequest.validate();\n\n await handler(validated, req, res, formRequest);\n };\n}\n\n/**\n * Create a wrapper with custom error handling for App Router.\n *\n * @example\n * ```typescript\n * import { createAppRouterWrapper, ValidationError, AuthorizationError } from 'next-request';\n *\n * const withValidation = createAppRouterWrapper({\n * onValidationError: (error) => Response.json({ errors: error.errors }, { status: 422 }),\n * onAuthorizationError: () => Response.json({ message: 'Forbidden' }, { status: 403 }),\n * });\n *\n * export const POST = withValidation(CreateUserRequest, async (data) => {\n * const user = await db.users.create({ data });\n * return Response.json({ user }, { status: 201 });\n * });\n * ```\n */\nexport function createAppRouterWrapper(options: {\n onValidationError?: (error: ValidationError) => Response;\n onAuthorizationError?: (error: AuthorizationError) => Response;\n onError?: (error: unknown) => Response;\n}): <TValidated>(\n RequestClass: FormRequestClass<TValidated>,\n handler: AppRouterHandler<TValidated>\n) => (request: Request, context?: AppRouterContext) => Promise<Response> {\n return <TValidated>(\n RequestClass: FormRequestClass<TValidated>,\n handler: AppRouterHandler<TValidated>\n ) => {\n return async (request: Request, context?: AppRouterContext) => {\n try {\n const params = context?.params\n ? (context.params instanceof Promise ? await context.params : context.params)\n : {};\n\n const formRequest = await RequestClass.fromAppRouter(request, params);\n const validated = await formRequest.validate();\n\n return handler(validated, request, formRequest);\n } catch (error) {\n if (error instanceof ValidationError && options.onValidationError) {\n return options.onValidationError(error);\n }\n if (error instanceof AuthorizationError && options.onAuthorizationError) {\n return options.onAuthorizationError(error);\n }\n if (options.onError) {\n return options.onError(error);\n }\n throw error;\n }\n };\n };\n}\n\n/**\n * Create a wrapper with custom error handling for Pages Router.\n *\n * @example\n * ```typescript\n * import { createPagesRouterWrapper, ValidationError, AuthorizationError } from 'next-request';\n *\n * const withValidation = createPagesRouterWrapper({\n * onValidationError: (error, req, res) => res.status(422).json({ errors: error.errors }),\n * onAuthorizationError: (error, req, res) => res.status(403).json({ message: 'Forbidden' }),\n * });\n *\n * export default withValidation(CreateUserRequest, async (data, req, res) => {\n * const user = await db.users.create({ data });\n * res.status(201).json({ user });\n * });\n * ```\n */\nexport function createPagesRouterWrapper(options: {\n onValidationError?: (\n error: ValidationError,\n req: NextApiRequest,\n res: NextApiResponse\n ) => void | Promise<void>;\n onAuthorizationError?: (\n error: AuthorizationError,\n req: NextApiRequest,\n res: NextApiResponse\n ) => void | Promise<void>;\n onError?: (\n error: unknown,\n req: NextApiRequest,\n res: NextApiResponse\n ) => void | Promise<void>;\n}): <TValidated>(\n RequestClass: FormRequestClass<TValidated>,\n handler: PagesRouterHandler<TValidated>\n) => (req: NextApiRequest, res: NextApiResponse) => Promise<void> {\n return <TValidated>(\n RequestClass: FormRequestClass<TValidated>,\n handler: PagesRouterHandler<TValidated>\n ) => {\n return async (req: NextApiRequest, res: NextApiResponse) => {\n try {\n const formRequest = await RequestClass.fromPagesRouter(req);\n const validated = await formRequest.validate();\n\n await handler(validated, req, res, formRequest);\n } catch (error) {\n if (error instanceof ValidationError && options.onValidationError) {\n return options.onValidationError(error, req, res);\n }\n if (error instanceof AuthorizationError && options.onAuthorizationError) {\n return options.onAuthorizationError(error, req, res);\n }\n if (options.onError) {\n return options.onError(error, req, res);\n }\n throw error;\n }\n };\n };\n}\n","import type { ZodSchema, ZodError } from 'zod';\nimport type { ValidatorAdapter, ValidationResult, ValidationConfig, ValidationErrors } from '../../core/types';\n\n/**\n * Validator adapter for Zod schemas\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { ZodAdapter } from 'next-request/zod';\n *\n * const schema = z.object({\n * email: z.string().email(),\n * name: z.string().min(2),\n * });\n *\n * class MyRequest extends FormRequest<z.infer<typeof schema>> {\n * rules() {\n * return new ZodAdapter(schema);\n * }\n * }\n * ```\n */\nexport class ZodAdapter<T> implements ValidatorAdapter<T> {\n constructor(private schema: ZodSchema<T>) {}\n\n async validate(data: unknown, config?: ValidationConfig): Promise<ValidationResult<T>> {\n return this.validateSync(data, config);\n }\n\n validateSync(data: unknown, config?: ValidationConfig): ValidationResult<T> {\n const result = this.schema.safeParse(data);\n\n if (result.success) {\n return {\n success: true,\n data: result.data,\n };\n }\n\n const errors = this.formatZodErrors(result.error, config);\n\n return {\n success: false,\n errors,\n };\n }\n\n private formatZodErrors(error: ZodError, config?: ValidationConfig): ValidationErrors {\n const errors: ValidationErrors = {};\n const customMessages = config?.messages ?? {};\n const customAttributes = config?.attributes ?? {};\n\n for (const issue of error.issues) {\n const path = issue.path.join('.');\n const fieldName = path || '_root';\n\n // Get custom attribute name if available\n const attributeName = customAttributes[fieldName] ?? fieldName;\n\n // Build the message key for custom messages (e.g., \"email.email\", \"password.min\")\n const messageKey = `${fieldName}.${issue.code}`;\n\n // Check for custom message, otherwise use Zod's message with custom attribute\n let message: string;\n if (customMessages[messageKey]) {\n message = customMessages[messageKey];\n } else if (customMessages[fieldName]) {\n message = customMessages[fieldName];\n } else {\n // Replace field references in Zod's default message\n message = issue.message.replace(\n new RegExp(`\\\\b${fieldName}\\\\b`, 'gi'),\n attributeName\n );\n }\n\n if (!errors[fieldName]) {\n errors[fieldName] = [];\n }\n errors[fieldName].push(message);\n }\n\n return errors;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/types.ts","../src/core/errors.ts","../src/utils/rateLimit.ts","../src/utils/coerce.ts","../src/core/FormRequest.ts","../src/middleware/withRequest.ts","../src/middleware/withSchema.ts","../src/adapters/validators/ZodAdapter.ts","../src/adapters/validators/YupAdapter.ts","../src/adapters/validators/ValibotAdapter.ts","../src/adapters/validators/ArkTypeAdapter.ts","../src/utils/formFile.ts","../src/utils/errorFormatting.ts","../src/utils/testing.ts","../src/utils/compose.ts"],"names":["result","z"],"mappings":";;;;;AAyDO,SAAS,mBAAmB,OAAA,EAA+C;AAChF,EAAA,OAAO,SAAA,IAAa,OAAA,IAAW,OAAA,CAAQ,OAAA,YAAmB,OAAA;AAC5D;AAKO,SAAS,qBAAqB,OAAA,EAAsD;AACzF,EAAA,OAAO,WAAW,OAAA,IAAW,EAAE,SAAA,IAAa,OAAA,IAAW,QAAQ,OAAA,YAAmB,OAAA,CAAA;AACpF;;;AC7DO,IAAM,eAAA,GAAN,MAAM,gBAAA,SAAwB,KAAA,CAAM;AAAA,EAGzC,YAAY,MAAA,EAA0B;AACpC,IAAA,MAAM,UAAA,GAAa,OAAO,MAAA,CAAO,MAAM,EAAE,CAAC,CAAA,GAAI,CAAC,CAAA,IAAK,mBAAA;AACpD,IAAA,KAAA,CAAM,UAAU,CAAA;AAChB,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAGd,IAAA,IAAI,MAAM,iBAAA,EAAmB;AAC3B,MAAA,KAAA,CAAM,iBAAA,CAAkB,MAAM,gBAAe,CAAA;AAAA,IAC/C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAA,GAA2B;AACzB,IAAA,OAAO,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,MAAM,EAAE,IAAA,EAAK;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,KAAA,EAAyB;AACtC,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,IAAK,EAAC;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,KAAA,EAAwB;AACpC,IAAA,OAAO,SAAS,IAAA,CAAK,MAAA,IAAU,KAAK,MAAA,CAAO,KAAK,EAAE,MAAA,GAAS,CAAA;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA,GAAS;AACP,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,QAAQ,IAAA,CAAK;AAAA,KACf;AAAA,EACF;AACF;AAKO,IAAM,kBAAA,GAAN,MAAM,mBAAA,SAA2B,KAAA,CAAM;AAAA,EAC5C,WAAA,CAAY,UAAU,cAAA,EAAgB;AACpC,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AAEZ,IAAA,IAAI,MAAM,iBAAA,EAAmB;AAC3B,MAAA,KAAA,CAAM,iBAAA,CAAkB,MAAM,mBAAkB,CAAA;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,MAAA,GAAS;AACP,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,EACF;AACF;;;ACUO,IAAM,uBAAN,MAAqD;AAAA,EAArD,WAAA,GAAA;AACL,IAAA,IAAA,CAAQ,KAAA,uBAAY,GAAA,EAA4B;AAAA,EAAA;AAAA,EAEhD,MAAM,IAAI,GAAA,EAA6C;AACrD,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAChC,IAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AAGnB,IAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,KAAA,CAAM,OAAA,EAAS;AAC9B,MAAA,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AACrB,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,MAAM,GAAA,CAAI,GAAA,EAAa,KAAA,EAAuB,MAAA,EAA+B;AAC3E,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAGzB,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,IAAA,GAAO,GAAA,EAAM;AAC1B,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IACf;AAAA,EACF;AAAA,EAEA,MAAM,SAAA,CAAU,GAAA,EAAa,QAAA,EAA2C;AACtE,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAEnC,IAAA,IAAI,CAAC,QAAA,IAAY,GAAA,GAAM,QAAA,CAAS,OAAA,EAAS;AAEvC,MAAA,MAAM,KAAA,GAAwB;AAAA,QAC5B,KAAA,EAAO,CAAA;AAAA,QACP,SAAS,GAAA,GAAM;AAAA,OACjB;AACA,MAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AACzB,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,QAAA,CAAS,KAAA,EAAA;AACT,IAAA,OAAO,QAAA;AAAA,EACT;AAAA,EAEQ,OAAA,GAAgB;AACtB,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,IAAA,CAAK,KAAA,CAAM,SAAQ,EAAG;AAC/C,MAAA,IAAI,GAAA,GAAM,MAAM,OAAA,EAAS;AACvB,QAAA,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACF;AAGA,IAAI,YAAA,GAA+B,IAAI,oBAAA,EAAqB;AAMrD,SAAS,yBAAyB,KAAA,EAA6B;AACpE,EAAA,YAAA,GAAe,KAAA;AACjB;AAKA,SAAS,YAAY,OAAA,EAA2C;AAE9D,EAAA,IAAI,SAAA,IAAa,OAAA,IAAW,OAAA,CAAQ,OAAA,YAAmB,OAAA,EAAS;AAC9D,IAAA,OACE,QAAQ,OAAA,CAAQ,GAAA,CAAI,iBAAiB,CAAA,EAAG,MAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,MAAK,IAC5D,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,WAAW,CAAA,IAC/B,SAAA;AAAA,EAEJ;AAGA,EAAA,MAAM,GAAA,GAAM,OAAA;AACZ,EAAA,MAAM,SAAA,GAAY,GAAA,CAAI,OAAA,CAAQ,iBAAiB,CAAA;AAC/C,EAAA,IAAI,OAAO,cAAc,QAAA,EAAU;AACjC,IAAA,OAAO,UAAU,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA,EAAG,MAAK,IAAK,SAAA;AAAA,EAC5C;AACA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC5B,IAAA,OAAO,SAAA,CAAU,CAAC,CAAA,EAAG,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,IAAA,EAAK,IAAK,SAAA;AAAA,EAChD;AAEA,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,OAAA,CAAQ,WAAW,CAAA;AACtC,EAAA,IAAI,OAAO,WAAW,QAAA,EAAU;AAC9B,IAAA,OAAO,MAAA;AAAA,EACT;AAGA,EAAA,MAAM,SAAU,GAAA,CAA2D,MAAA;AAC3E,EAAA,OAAO,QAAQ,aAAA,IAAiB,SAAA;AAClC;AAKA,eAAsB,cAAA,CACpB,SACA,MAAA,EAC0B;AAC1B,EAAA,MAAM,EAAE,WAAA,EAAa,QAAA,EAAU,KAAK,KAAA,GAAQ,YAAA,EAAc,MAAK,GAAI,MAAA;AAGnE,EAAA,IAAI,IAAA,IAAS,MAAM,IAAA,CAAK,OAAO,CAAA,EAAI;AACjC,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,IAAA;AAAA,MACT,SAAA,EAAW,WAAA;AAAA,MACX,KAAA,EAAO,WAAA;AAAA,MACP,OAAA,EAAS,IAAA,CAAK,GAAA,EAAI,GAAI,QAAA;AAAA,MACtB,UAAA,EAAY;AAAA,KACd;AAAA,EACF;AAGA,EAAA,MAAM,eAAe,GAAA,GAAM,MAAM,IAAI,OAAO,CAAA,GAAI,YAAY,OAAO,CAAA;AACnE,EAAA,MAAM,OAAA,GAAU,aAAa,YAAY,CAAA,CAAA;AAGzC,EAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,SAAA,CAAU,SAAS,QAAQ,CAAA;AAErD,EAAA,MAAM,OAAA,GAAU,MAAM,KAAA,IAAS,WAAA;AAC/B,EAAA,MAAM,YAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,WAAA,GAAc,MAAM,KAAK,CAAA;AACvD,EAAA,MAAM,UAAA,GAAa,OAAA,GAAU,CAAA,GAAI,IAAA,CAAK,IAAA,CAAA,CAAM,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,EAAI,IAAK,GAAI,CAAA;AAE9E,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA,EAAO,WAAA;AAAA,IACP,SAAS,KAAA,CAAM,OAAA;AAAA,IACf;AAAA,GACF;AACF;AAKO,IAAM,cAAA,GAAN,cAA6B,KAAA,CAAM;AAAA,EAMxC,WAAA,CAAY,QAAyB,OAAA,EAAkB;AACrD,IAAA,KAAA,CAAM,OAAA,IAAW,CAAA,iCAAA,EAAoC,MAAA,CAAO,UAAU,CAAA,SAAA,CAAW,CAAA;AACjF,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AACZ,IAAA,IAAA,CAAK,aAAa,MAAA,CAAO,UAAA;AACzB,IAAA,IAAA,CAAK,YAAY,MAAA,CAAO,SAAA;AACxB,IAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AACpB,IAAA,IAAA,CAAK,UAAU,MAAA,CAAO,OAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAAqC;AACnC,IAAA,OAAO;AAAA,MACL,mBAAA,EAAqB,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AAAA,MACtC,uBAAA,EAAyB,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA;AAAA,MAC9C,mBAAA,EAAqB,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AAAA,MACxC,aAAA,EAAe,MAAA,CAAO,IAAA,CAAK,UAAU;AAAA,KACvC;AAAA,EACF;AACF;AAKO,SAAS,UAAU,MAAA,EAA+F;AACvH,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,WAAA;AAAA,IACL,GAAG;AAAA,GACL;AACF;;;AC1OA,IAAM,cAAA,GAAkC;AAAA,EACtC,QAAA,EAAU,IAAA;AAAA,EACV,OAAA,EAAS,IAAA;AAAA,EACT,KAAA,EAAO,IAAA;AAAA,EACP,KAAA,EAAO,IAAA;AAAA,EACP,YAAA,EAAc,KAAA;AAAA,EACd,IAAA,EAAM;AACR,CAAA;AAKA,SAAS,gBAAgB,KAAA,EAAwB;AAE/C,EAAA,MAAM,YAAA,GAAe,2EAAA;AACrB,EAAA,OAAO,YAAA,CAAa,KAAK,KAAK,CAAA;AAChC;AAKA,SAAS,gBAAgB,KAAA,EAAwB;AAC/C,EAAA,IAAI,KAAA,KAAU,EAAA,IAAM,KAAA,KAAU,IAAA,EAAM,OAAO,KAAA;AAE3C,EAAA,IAAI,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAG,OAAO,KAAA;AAC/B,EAAA,IAAI,KAAA,CAAM,MAAA,GAAS,EAAA,EAAI,OAAO,KAAA;AAC9B,EAAA,OAAO,CAAC,MAAM,MAAA,CAAO,KAAK,CAAC,CAAA,IAAK,QAAA,CAAS,MAAA,CAAO,KAAK,CAAC,CAAA;AACxD;AAKA,SAAS,WAAA,CAAY,OAAgB,OAAA,EAAmC;AACtE,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,IAAI,OAAA,CAAQ,YAAA,IAAgB,KAAA,KAAU,EAAA,EAAI;AACxC,IAAA,OAAO,MAAA;AAAA,EACT;AAGA,EAAA,IAAI,OAAA,CAAQ,KAAA,IAAS,KAAA,KAAU,MAAA,EAAQ;AACrC,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,IAAA,MAAM,KAAA,GAAQ,MAAM,WAAA,EAAY;AAChC,IAAA,IAAI,KAAA,KAAU,QAAQ,OAAO,IAAA;AAC7B,IAAA,IAAI,KAAA,KAAU,SAAS,OAAO,KAAA;AAAA,EAChC;AAGA,EAAA,IAAI,OAAA,CAAQ,KAAA,IAAS,eAAA,CAAgB,KAAK,CAAA,EAAG;AAC3C,IAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,KAAK,CAAA;AAC3B,IAAA,IAAI,CAAC,KAAA,CAAM,IAAA,CAAK,OAAA,EAAS,CAAA,EAAG;AAC1B,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,IAAI,OAAA,CAAQ,OAAA,IAAW,eAAA,CAAgB,KAAK,CAAA,EAAG;AAC7C,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB;AAGA,EAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,IAAA,IAAK,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,IAAK,QAAQ,QAAA,CAAS,GAAG,CAAA,IAC/C,OAAA,CAAQ,WAAW,GAAG,CAAA,IAAK,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAI;AACtD,MAAA,IAAI;AACF,QAAA,OAAO,IAAA,CAAK,MAAM,KAAK,CAAA;AAAA,MACzB,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT;AAKA,SAAS,YAAA,CACP,IAAA,EACA,OAAA,EACA,IAAA,GAAe,EAAA,EACU;AACzB,EAAA,MAAM,SAAkC,EAAC;AAEzC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC/C,IAAA,MAAM,YAAY,IAAA,GAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA,GAAK,GAAA;AAG5C,IAAA,IAAI,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,MAAA,CAAO,SAAS,CAAA,EAAG;AAC/C,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,OAAA,CAAQ,MAAA,CAAO,SAAS,EAAE,KAAK,CAAA;AAC7C,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA,CAAM,GAAA,CAAI,CAAC,MAAM,KAAA,KAAU;AACvC,QAAA,IAAI,IAAA,KAAS,QAAQ,OAAO,IAAA,KAAS,YAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AACrE,UAAA,OAAO,aAAa,IAAA,EAAiC,OAAA,EAAS,GAAG,SAAS,CAAA,CAAA,EAAI,KAAK,CAAA,CAAE,CAAA;AAAA,QACvF;AACA,QAAA,OAAO,WAAA,CAAY,MAAM,OAAO,CAAA;AAAA,MAClC,CAAC,CAAA;AAAA,IACH,CAAA,MAAA,IAAW,KAAA,KAAU,IAAA,IAAQ,OAAO,UAAU,QAAA,EAAU;AACtD,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,YAAA,CAAa,KAAA,EAAkC,SAAS,SAAS,CAAA;AAAA,IACjF,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,WAAA,CAAY,KAAA,EAAO,OAAO,CAAA;AAAA,IAC1C;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AA8BO,SAAS,cAAA,CACd,IAAA,EACA,OAAA,GAA2B,EAAC,EACzB;AACH,EAAA,MAAM,aAAA,GAAgB,EAAE,GAAG,cAAA,EAAgB,GAAG,OAAA,EAAQ;AACtD,EAAA,OAAO,YAAA,CAAa,MAAM,aAAa,CAAA;AACzC;AAoBO,SAAS,SAAA,CAAU,OAAA,GAA2B,EAAC,EAA+B;AACnF,EAAA,OAAO,CAAC,IAAA,KAAkB;AACxB,IAAA,IAAI,IAAA,KAAS,QAAQ,OAAO,IAAA,KAAS,YAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AACrE,MAAA,OAAO,cAAA,CAAe,MAAiC,OAAO,CAAA;AAAA,IAChE;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AACF;AAKO,IAAM,eAAA,GAAkB;AAAA;AAAA,EAE7B,GAAA,EAAK,EAAE,QAAA,EAAU,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,YAAA,EAAc,IAAA,EAAM,MAAM,IAAA,EAAK;AAAA;AAAA,EAE/F,IAAA,EAAM,EAAE,QAAA,EAAU,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,MAAM,KAAA,EAAM;AAAA;AAAA,EAEpG,QAAA,EAAU,EAAE,QAAA,EAAU,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,MAAM,KAAA,EAAM;AAAA;AAAA,EAEvG,IAAA,EAAM,EAAE,QAAA,EAAU,KAAA,EAAO,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,MAAM,KAAA;AAClG;;;ACjLO,IAAe,cAAf,MAAiD;AAAA,EAAjD,WAAA,GAAA;AASL;AAAA;AAAA;AAAA,IAAA,IAAA,CAAU,OAAgC,EAAC;AAK3C;AAAA;AAAA;AAAA,IAAA,IAAA,CAAU,QAAuD,EAAC;AAKlE;AAAA;AAAA;AAAA,IAAA,IAAA,CAAU,SAAiC,EAAC;AAK5C;AAAA;AAAA;AAAA,IAAA,IAAA,CAAU,UAAyD,EAAC;AAKpE;AAAA;AAAA;AAAA,IAAA,IAAA,CAAQ,UAAA,GAAgC,IAAA;AAKxC;AAAA;AAAA;AAAA,IAAA,IAAA,CAAQ,QAA6B,EAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBtC,SAAA,GAAwC;AACtC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,SAAA,GAAoC;AAClC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,QAAA,GAAmC;AACjC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,gBAAA,GAAyC;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1C,gBAAgB,KAAA,EAAyC;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1D,mBAAmB,OAAA,EAAiD;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrE,qBAAA,GAA8C;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoB/C,QAAA,GAAmC;AACjC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,UAAA,GAAqC;AACnC,IAAA,OAAO,EAAC;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,aAAa,aAAA,CAEX,OAAA,EACA,MAAA,GAAiC,EAAC,EACtB;AACZ,IAAA,MAAM,QAAA,GAAW,IAAI,IAAA,EAAK;AAC1B,IAAA,QAAA,CAAS,OAAA,GAAU,OAAA;AACnB,IAAA,QAAA,CAAS,MAAA,GAAS,MAAA;AAGlB,IAAA,QAAA,CAAS,UAAU,EAAC;AACpB,IAAA,OAAA,CAAQ,OAAA,CAAQ,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AACtC,MAAA,QAAA,CAAS,OAAA,CAAQ,GAAG,CAAA,GAAI,KAAA;AAAA,IAC1B,CAAC,CAAA;AAGD,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA;AAC/B,IAAA,QAAA,CAAS,QAAQ,EAAC;AAClB,IAAA,GAAA,CAAI,YAAA,CAAa,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AACvC,MAAA,MAAM,QAAA,GAAW,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA;AACnC,MAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,QAAA,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,QAAQ,CAAA,GACxC,CAAC,GAAG,QAAA,EAAU,KAAK,CAAA,GACnB,CAAC,UAAU,KAAK,CAAA;AAAA,MACtB,CAAA,MAAO;AACL,QAAA,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,GAAI,KAAA;AAAA,MACxB;AAAA,IACF,CAAC,CAAA;AAGD,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,WAAA,EAAY;AAC1C,IAAA,IAAI,CAAC,QAAQ,KAAA,EAAO,OAAA,EAAS,QAAQ,CAAA,CAAE,QAAA,CAAS,MAAM,CAAA,EAAG;AACvD,MAAA,IAAI;AACF,QAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AAC3D,QAAA,IAAI,WAAA,CAAY,QAAA,CAAS,kBAAkB,CAAA,EAAG;AAC5C,UAAA,QAAA,CAAS,IAAA,GAAO,MAAM,OAAA,CAAQ,KAAA,GAAQ,IAAA,EAAK;AAAA,QAC7C,CAAA,MAAA,IAAW,WAAA,CAAY,QAAA,CAAS,mCAAmC,CAAA,EAAG;AACpE,UAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,KAAA,GAAQ,IAAA,EAAK;AACxC,UAAA,MAAM,QAAA,GAAW,IAAI,eAAA,CAAgB,IAAI,CAAA;AACzC,UAAA,QAAA,CAAS,IAAA,GAAO,MAAA,CAAO,WAAA,CAAY,QAAA,CAAS,SAAS,CAAA;AAAA,QACvD,CAAA,MAAA,IAAW,WAAA,CAAY,QAAA,CAAS,qBAAqB,CAAA,EAAG;AACtD,UAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,KAAA,GAAQ,QAAA,EAAS;AAChD,UAAA,QAAA,CAAS,IAAA,GAAO,MAAA,CAAO,WAAA,CAAY,QAAA,CAAS,SAAS,CAAA;AAAA,QACvD;AAAA,MACF,CAAA,CAAA,MAAQ;AACN,QAAA,QAAA,CAAS,OAAO,EAAC;AAAA,MACnB;AAAA,IACF;AAEA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,eAAA,CAEX,OAAA,EACA,MAAA,GAAiC,EAAC,EACtB;AACZ,IAAA,MAAM,QAAA,GAAW,IAAI,IAAA,EAAK;AAC1B,IAAA,QAAA,CAAS,OAAA,GAAU,OAAA;AACnB,IAAA,QAAA,CAAS,SAAS,EAAE,GAAG,MAAA,EAAQ,GAAI,QAAQ,KAAA,EAAiC;AAG5E,IAAA,QAAA,CAAS,UAAU,OAAA,CAAQ,OAAA;AAG3B,IAAA,QAAA,CAAS,QAAQ,OAAA,CAAQ,KAAA;AAGzB,IAAA,QAAA,CAAS,IAAA,GAAQ,OAAA,CAAQ,IAAA,IAAoC,EAAC;AAE9D,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,QAAA,GAAgC;AAEpC,IAAA,MAAM,eAAA,GAAkB,KAAK,SAAA,EAAU;AACvC,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,MAAMA,OAAAA,GAAS,MAAM,cAAA,CAAe,IAAA,CAAK,SAAS,eAAe,CAAA;AACjE,MAAA,IAAI,CAACA,QAAO,OAAA,EAAS;AACnB,QAAA,MAAM,IAAI,cAAA,CAAeA,OAAAA,EAAQ,eAAA,CAAgB,OAAO,CAAA;AAAA,MAC1D;AAAA,IACF;AAGA,IAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,SAAA,EAAU;AAC1C,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,MAAM,KAAK,qBAAA,EAAsB;AACjC,MAAA,MAAM,IAAI,kBAAA,EAAmB;AAAA,IAC/B;AAGA,IAAA,MAAM,eAAA,GAAkB,KAAK,QAAA,EAAS;AACtC,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,IAAA,CAAK,IAAA,GAAO,cAAA,CAAe,IAAA,CAAK,IAAA,EAAM,eAAe,CAAA;AAAA,IACvD;AAGA,IAAA,MAAM,KAAK,gBAAA,EAAiB;AAG5B,IAAA,MAAM,SAAA,GAAY,KAAK,KAAA,EAAM;AAC7B,IAAA,MAAM,SAAS,MAAM,SAAA,CAAU,QAAA,CAAS,IAAA,CAAK,sBAAqB,EAAG;AAAA,MACnE,QAAA,EAAU,KAAK,QAAA,EAAS;AAAA,MACxB,UAAA,EAAY,KAAK,UAAA;AAAW,KAC7B,CAAA;AAED,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,MAAM,SAAS,MAAA,CAAO,MAAA,IAAU,EAAE,MAAA,EAAQ,CAAC,mBAAmB,CAAA,EAAE;AAChE,MAAA,MAAM,IAAA,CAAK,mBAAmB,MAAM,CAAA;AACpC,MAAA,MAAM,IAAI,gBAAgB,MAAM,CAAA;AAAA,IAClC;AAGA,IAAA,IAAA,CAAK,aAAa,MAAA,CAAO,IAAA;AACzB,IAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA;AAGpB,IAAA,MAAM,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,UAAU,CAAA;AAE1C,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAA,GAAwB;AACtB,IAAA,IAAI,IAAA,CAAK,eAAe,IAAA,EAAM;AAC5B,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OAEF;AAAA,IACF;AACA,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAA,GAA4B;AAC1B,IAAA,OAAO,EAAE,GAAG,IAAA,CAAK,KAAA,EAAM;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,GAAA,GAA+B;AAC7B,IAAA,OAAO,EAAE,GAAG,IAAA,CAAK,IAAA,EAAK;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,CAAmB,KAAa,YAAA,EAAiC;AAC/D,IAAA,MAAM,QAAQ,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,IAAK,IAAA,CAAK,MAAM,GAAG,CAAA;AAC9C,IAAA,OAAQ,KAAA,IAAe,YAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,GAAA,EAAsB;AACxB,IAAA,OAAO,GAAA,IAAO,IAAA,CAAK,IAAA,IAAQ,GAAA,IAAO,IAAA,CAAK,KAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,QAA0B,IAAA,EAA6C;AACrE,IAAA,MAAM,SAAkC,EAAC;AACzC,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG;AACjB,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAAA,MAC9B;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,IAAA,EAAyC;AACjD,IAAA,MAAM,MAAA,GAAS,EAAE,GAAG,IAAA,CAAK,IAAA,EAAK;AAC9B,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,MAAA,OAAO,OAAO,GAAG,CAAA;AAAA,IACnB;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAA+B;AAC7B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA,GAAuB;AACrB,IAAA,OAAO,kBAAA,CAAmB,KAAK,OAAO,CAAA;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAAA,EAA6C;AAClD,IAAA,MAAM,SAAA,GAAY,KAAK,WAAA,EAAY;AACnC,IAAA,IAAI,kBAAA,CAAmB,IAAA,CAAK,OAAO,CAAA,EAAG;AACpC,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA,IAAK,MAAA;AAAA,IAChD;AACA,IAAA,OAAO,IAAA,CAAK,QAAQ,SAAS,CAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IAAA,EAAkC;AACtC,IAAA,OAAO,IAAA,CAAK,OAAO,IAAI,CAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUU,oBAAA,GAAgC;AACxC,IAAA,OAAO,IAAA,CAAK,IAAA;AAAA,EACd;AACF;;;ACrZO,SAAS,WAAA,CACd,cAGA,OAAA,EACqE;AACrE,EAAA,OAAO,OAAO,SAAkB,OAAA,KAA+B;AAE7D,IAAA,MAAM,MAAA,GAAS,OAAA,EAAS,MAAA,GACnB,OAAA,CAAQ,MAAA,YAAkB,OAAA,GAAU,MAAM,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,MAAA,GACpE,EAAC;AAEL,IAAA,MAAM,WAAA,GAAc,MAAM,YAAA,CAAa,aAAA,CAAc,SAAS,MAAM,CAAA;AACpE,IAAA,MAAM,SAAA,GAAY,MAAM,WAAA,CAAY,QAAA,EAAS;AAE7C,IAAA,OAAO,OAAA,CAAQ,SAAA,EAAW,OAAA,EAAS,WAAW,CAAA;AAAA,EAChD,CAAA;AACF;AAwBO,SAAS,cAAA,CACd,cAGA,OAAA,EAC8D;AAC9D,EAAA,OAAO,OAAO,KAAqB,GAAA,KAAyB;AAC1D,IAAA,MAAM,WAAA,GAAc,MAAM,YAAA,CAAa,eAAA,CAAgB,GAAG,CAAA;AAC1D,IAAA,MAAM,SAAA,GAAY,MAAM,WAAA,CAAY,QAAA,EAAS;AAE7C,IAAA,MAAM,OAAA,CAAQ,SAAA,EAAW,GAAA,EAAK,GAAA,EAAK,WAAW,CAAA;AAAA,EAChD,CAAA;AACF;AAoBO,SAAS,uBAAuB,OAAA,EASkC;AACvE,EAAA,OAAO,CACL,cAGA,OAAA,KACG;AACH,IAAA,OAAO,OAAO,SAAkB,OAAA,KAA+B;AAC7D,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,OAAA,EAAS,MAAA,GACnB,OAAA,CAAQ,MAAA,YAAkB,OAAA,GAAU,MAAM,OAAA,CAAQ,MAAA,GAAS,OAAA,CAAQ,MAAA,GACpE,EAAC;AAEL,QAAA,MAAM,WAAA,GAAc,MAAM,YAAA,CAAa,aAAA,CAAc,SAAS,MAAM,CAAA;AACpE,QAAA,MAAM,SAAA,GAAY,MAAM,WAAA,CAAY,QAAA,EAAS;AAE7C,QAAA,OAAO,OAAA,CAAQ,SAAA,EAAW,OAAA,EAAS,WAAW,CAAA;AAAA,MAChD,SAAS,KAAA,EAAO;AACd,QAAA,IAAI,KAAA,YAAiB,eAAA,IAAmB,OAAA,CAAQ,iBAAA,EAAmB;AACjE,UAAA,OAAO,OAAA,CAAQ,kBAAkB,KAAK,CAAA;AAAA,QACxC;AACA,QAAA,IAAI,KAAA,YAAiB,kBAAA,IAAsB,OAAA,CAAQ,oBAAA,EAAsB;AACvE,UAAA,OAAO,OAAA,CAAQ,qBAAqB,KAAK,CAAA;AAAA,QAC3C;AACA,QAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,UAAA,OAAO,OAAA,CAAQ,QAAQ,KAAK,CAAA;AAAA,QAC9B;AACA,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF,CAAA;AAAA,EACF,CAAA;AACF;AAoBO,SAAS,yBAAyB,OAAA,EAqByB;AAChE,EAAA,OAAO,CACL,cAGA,OAAA,KACG;AACH,IAAA,OAAO,OAAO,KAAqB,GAAA,KAAyB;AAC1D,MAAA,IAAI;AACF,QAAA,MAAM,WAAA,GAAc,MAAM,YAAA,CAAa,eAAA,CAAgB,GAAG,CAAA;AAC1D,QAAA,MAAM,SAAA,GAAY,MAAM,WAAA,CAAY,QAAA,EAAS;AAE7C,QAAA,MAAM,OAAA,CAAQ,SAAA,EAAW,GAAA,EAAK,GAAA,EAAK,WAAW,CAAA;AAAA,MAChD,SAAS,KAAA,EAAO;AACd,QAAA,IAAI,KAAA,YAAiB,eAAA,IAAmB,OAAA,CAAQ,iBAAA,EAAmB;AACjE,UAAA,OAAO,OAAA,CAAQ,iBAAA,CAAkB,KAAA,EAAO,GAAA,EAAK,GAAG,CAAA;AAAA,QAClD;AACA,QAAA,IAAI,KAAA,YAAiB,kBAAA,IAAsB,OAAA,CAAQ,oBAAA,EAAsB;AACvE,UAAA,OAAO,OAAA,CAAQ,oBAAA,CAAqB,KAAA,EAAO,GAAA,EAAK,GAAG,CAAA;AAAA,QACrD;AACA,QAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,UAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAO,GAAA,EAAK,GAAG,CAAA;AAAA,QACxC;AACA,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF,CAAA;AAAA,EACF,CAAA;AACF;;;ACvNA,eAAe,iBAAiB,OAAA,EAAoC;AAClE,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AAE3D,EAAA,IAAI,WAAA,CAAY,QAAA,CAAS,kBAAkB,CAAA,EAAG;AAC5C,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,QAAQ,IAAA,EAAK;AAAA,IAC5B,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,EAAC;AAAA,IACV;AAAA,EACF;AAEA,EAAA,IAAI,YAAY,QAAA,CAAS,mCAAmC,KAAK,WAAA,CAAY,QAAA,CAAS,qBAAqB,CAAA,EAAG;AAC5G,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,QAAA,EAAS;AACxC,MAAA,MAAM,OAAgC,EAAC;AAEvC,MAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AAC/B,QAAA,IAAI,IAAA,CAAK,GAAG,CAAA,EAAG;AAEb,UAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAC,CAAA,EAAG;AAC5B,YAAC,IAAA,CAAK,GAAG,CAAA,CAAgB,IAAA,CAAK,KAAK,CAAA;AAAA,UACrC,CAAA,MAAO;AACL,YAAA,IAAA,CAAK,GAAG,CAAA,GAAI,CAAC,IAAA,CAAK,GAAG,GAAG,KAAK,CAAA;AAAA,UAC/B;AAAA,QACF,CAAA,MAAO;AACL,UAAA,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA;AAAA,QACd;AAAA,MACF,CAAC,CAAA;AAED,MAAA,OAAO,IAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,EAAC;AAAA,IACV;AAAA,EACF;AAEA,EAAA,OAAO,EAAC;AACV;AA6BO,SAAS,UAAA,CACd,SACA,OAAA,EACqE;AACrE,EAAA,OAAO,OAAO,SAAkB,OAAA,KAA+B;AAE7D,IAAA,MAAM,IAAA,GAAO,MAAM,gBAAA,CAAiB,OAAO,CAAA;AAG3C,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAA;AAE1C,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,MAAM,IAAI,eAAA,CAAgB,MAAA,CAAO,MAAA,IAAU,EAAE,CAAA;AAAA,IAC/C;AAGA,IAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,IAAA,EAA+B,OAAO,CAAA;AAAA,EAC9D,CAAA;AACF;AA6BO,SAAS,aAAA,CACd,SACA,OAAA,EAC8D;AAC9D,EAAA,OAAO,OAAO,KAAqB,GAAA,KAAyB;AAE1D,IAAA,MAAM,OAAO,GAAA,CAAI,IAAA;AAGjB,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAA;AAE1C,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,MAAM,IAAI,eAAA,CAAgB,MAAA,CAAO,MAAA,IAAU,EAAE,CAAA;AAAA,IAC/C;AAGA,IAAA,MAAM,OAAA,CAAQ,MAAA,CAAO,IAAA,EAA+B,GAAA,EAAK,GAAG,CAAA;AAAA,EAC9D,CAAA;AACF;;;AChJO,IAAM,aAAN,MAAmD;AAAA,EACxD,YAAoB,MAAA,EAAsB;AAAtB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAuB;AAAA,EAE3C,MAAM,QAAA,CAAS,IAAA,EAAe,MAAA,EAAyD;AACrF,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,IAAA,EAAM,MAAM,CAAA;AAAA,EACvC;AAAA,EAEA,YAAA,CAAa,MAAe,MAAA,EAAgD;AAC1E,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,IAAI,CAAA;AAEzC,IAAA,IAAI,OAAO,OAAA,EAAS;AAClB,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,IAAA;AAAA,QACT,MAAM,MAAA,CAAO;AAAA,OACf;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,eAAA,CAAgB,MAAA,CAAO,OAAO,MAAM,CAAA;AAExD,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT;AAAA,KACF;AAAA,EACF;AAAA,EAEQ,eAAA,CAAgB,OAAiB,MAAA,EAA6C;AACpF,IAAA,MAAM,SAA2B,EAAC;AAClC,IAAA,MAAM,cAAA,GAAiB,MAAA,EAAQ,QAAA,IAAY,EAAC;AAC5C,IAAA,MAAM,gBAAA,GAAmB,MAAA,EAAQ,UAAA,IAAc,EAAC;AAEhD,IAAA,KAAA,MAAW,KAAA,IAAS,MAAM,MAAA,EAAQ;AAChC,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA;AAChC,MAAA,MAAM,YAAY,IAAA,IAAQ,OAAA;AAG1B,MAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,SAAS,CAAA,IAAK,SAAA;AAGrD,MAAA,MAAM,UAAA,GAAa,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,MAAM,IAAI,CAAA,CAAA;AAG7C,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI,cAAA,CAAe,UAAU,CAAA,EAAG;AAC9B,QAAA,OAAA,GAAU,eAAe,UAAU,CAAA;AAAA,MACrC,CAAA,MAAA,IAAW,cAAA,CAAe,SAAS,CAAA,EAAG;AACpC,QAAA,OAAA,GAAU,eAAe,SAAS,CAAA;AAAA,MACpC,CAAA,MAAO;AAEL,QAAA,OAAA,GAAU,MAAM,OAAA,CAAQ,OAAA;AAAA,UACtB,IAAI,MAAA,CAAO,CAAA,GAAA,EAAM,SAAS,OAAO,IAAI,CAAA;AAAA,UACrC;AAAA,SACF;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,MAAA,CAAO,SAAS,CAAA,EAAG;AACtB,QAAA,MAAA,CAAO,SAAS,IAAI,EAAC;AAAA,MACvB;AACA,MAAA,MAAA,CAAO,SAAS,CAAA,CAAE,IAAA,CAAK,OAAO,CAAA;AAAA,IAChC;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;;;ACjDO,IAAM,aAAN,MAAmD;AAAA,EACxD,YAAoB,MAAA,EAAsB;AAAtB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAuB;AAAA,EAE3C,MAAM,QAAA,CAAS,IAAA,EAAe,MAAA,EAAyD;AACrF,IAAA,IAAI;AACF,MAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,MAAA,CAAO,SAAS,IAAA,EAAM;AAAA,QACjD,UAAA,EAAY,KAAA;AAAA,QACZ,YAAA,EAAc;AAAA,OACf,CAAA;AAED,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,IAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACR;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,IAAA,CAAK,oBAAA,CAAqB,KAAK,CAAA,EAAG;AACpC,QAAA,MAAM,MAAA,GAAS,IAAA,CAAK,eAAA,CAAgB,KAAA,EAAO,MAAM,CAAA;AACjD,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT;AAAA,SACF;AAAA,MACF;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEA,YAAA,CAAa,MAAe,MAAA,EAAgD;AAC1E,IAAA,IAAI;AACF,MAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,IAAA,EAAM;AAAA,QAC/C,UAAA,EAAY,KAAA;AAAA,QACZ,YAAA,EAAc;AAAA,OACf,CAAA;AAED,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,IAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACR;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,IAAA,CAAK,oBAAA,CAAqB,KAAK,CAAA,EAAG;AACpC,QAAA,MAAM,MAAA,GAAS,IAAA,CAAK,eAAA,CAAgB,KAAA,EAAO,MAAM,CAAA;AACjD,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT;AAAA,SACF;AAAA,MACF;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,qBAAqB,KAAA,EAA6C;AACxE,IAAA,OACE,KAAA,KAAU,IAAA,IACV,OAAO,KAAA,KAAU,QAAA,IACjB,WAAW,KAAA,IACX,MAAA,IAAU,KAAA,IACT,KAAA,CAA2B,IAAA,KAAS,iBAAA;AAAA,EAEzC;AAAA,EAEQ,eAAA,CAAgB,OAA2B,MAAA,EAA6C;AAC9F,IAAA,MAAM,SAA2B,EAAC;AAClC,IAAA,MAAM,cAAA,GAAiB,MAAA,EAAQ,QAAA,IAAY,EAAC;AAC5C,IAAA,MAAM,gBAAA,GAAmB,MAAA,EAAQ,UAAA,IAAc,EAAC;AAGhD,IAAA,MAAM,WAAA,GAAc,MAAM,KAAA,CAAM,MAAA,GAAS,IAAI,KAAA,CAAM,KAAA,GAAQ,CAAC,KAAK,CAAA;AAEjE,IAAA,KAAA,MAAW,SAAS,WAAA,EAAa;AAC/B,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,IAAQ,OAAA;AAG3B,MAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,IAAI,CAAA,IAAK,IAAA;AAGhD,MAAA,MAAM,aAAa,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAA,CAAM,QAAQ,SAAS,CAAA,CAAA;AAGrD,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI,cAAA,CAAe,UAAU,CAAA,EAAG;AAC9B,QAAA,OAAA,GAAU,eAAe,UAAU,CAAA;AAAA,MACrC,CAAA,MAAA,IAAW,cAAA,CAAe,IAAI,CAAA,EAAG;AAC/B,QAAA,OAAA,GAAU,eAAe,IAAI,CAAA;AAAA,MAC/B,CAAA,MAAO;AAEL,QAAA,OAAA,GAAU,MAAM,OAAA,CAAQ,OAAA;AAAA,UACtB,IAAI,MAAA,CAAO,CAAA,GAAA,EAAM,IAAI,OAAO,IAAI,CAAA;AAAA,UAChC;AAAA,SACF;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,MAAA,CAAO,IAAI,CAAA,EAAG;AACjB,QAAA,MAAA,CAAO,IAAI,IAAI,EAAC;AAAA,MAClB;AACA,MAAA,MAAA,CAAO,IAAI,CAAA,CAAE,IAAA,CAAK,OAAO,CAAA;AAAA,IAC3B;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;;;AC3FO,IAAM,iBAAN,MAAuD;AAAA,EAG5D,WAAA,CACU,QACR,SAAA,EACA;AAFQ,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAGR,IAAA,IAAA,CAAK,aAAA,GAAgB,SAAA;AAAA,EACvB;AAAA,EAEA,MAAM,QAAA,CAAS,IAAA,EAAe,MAAA,EAAyD;AACrF,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,IAAA,EAAM,MAAM,CAAA;AAAA,EACvC;AAAA,EAEA,YAAA,CAAa,MAAe,MAAA,EAAgD;AAC1E,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,QAAQ,IAAI,CAAA;AAEnD,IAAA,IAAI,OAAO,OAAA,EAAS;AAClB,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,IAAA;AAAA,QACT,MAAM,MAAA,CAAO;AAAA,OACf;AAAA,IACF;AAEA,IAAA,MAAM,SAAS,IAAA,CAAK,mBAAA,CAAoB,OAAO,MAAA,IAAU,IAAI,MAAM,CAAA;AAEnE,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT;AAAA,KACF;AAAA,EACF;AAAA,EAEQ,mBAAA,CAAoB,QAAwB,MAAA,EAA6C;AAC/F,IAAA,MAAM,SAA2B,EAAC;AAClC,IAAA,MAAM,cAAA,GAAiB,MAAA,EAAQ,QAAA,IAAY,EAAC;AAC5C,IAAA,MAAM,gBAAA,GAAmB,MAAA,EAAQ,UAAA,IAAc,EAAC;AAEhD,IAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAE1B,MAAA,MAAM,SAAA,GAAY,KAAA,CAAM,IAAA,EAAM,GAAA,CAAI,CAAC,CAAA,KAAkD;AACnF,QAAA,IAAI,OAAO,CAAA,KAAM,QAAA,IAAY,CAAA,KAAM,IAAA,IAAQ,SAAS,CAAA,EAAG;AACrD,UAAA,OAAO,MAAA,CAAO,EAAE,GAAG,CAAA;AAAA,QACrB;AACA,QAAA,OAAO,OAAO,CAAC,CAAA;AAAA,MACjB,CAAC,KAAK,EAAC;AACP,MAAA,MAAM,IAAA,GAAO,SAAA,CAAU,IAAA,CAAK,GAAG,CAAA,IAAK,OAAA;AAGpC,MAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,IAAI,CAAA,IAAK,IAAA;AAGhD,MAAA,MAAM,aAAa,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAA,CAAM,QAAQ,SAAS,CAAA,CAAA;AAGrD,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI,cAAA,CAAe,UAAU,CAAA,EAAG;AAC9B,QAAA,OAAA,GAAU,eAAe,UAAU,CAAA;AAAA,MACrC,CAAA,MAAA,IAAW,cAAA,CAAe,IAAI,CAAA,EAAG;AAC/B,QAAA,OAAA,GAAU,eAAe,IAAI,CAAA;AAAA,MAC/B,CAAA,MAAO;AAEL,QAAA,OAAA,GAAA,CAAW,KAAA,CAAM,WAAW,mBAAA,EAAqB,OAAA;AAAA,UAC/C,IAAI,MAAA,CAAO,CAAA,GAAA,EAAM,IAAI,OAAO,IAAI,CAAA;AAAA,UAChC;AAAA,SACF;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,MAAA,CAAO,IAAI,CAAA,EAAG;AACjB,QAAA,MAAA,CAAO,IAAI,IAAI,EAAC;AAAA,MAClB;AACA,MAAA,MAAA,CAAO,IAAI,CAAA,CAAE,IAAA,CAAK,OAAO,CAAA;AAAA,IAC3B;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;;;AClGA,SAAS,gBAAgB,MAAA,EAA0C;AACjE,EAAA,OACE,WAAW,IAAA,IACX,OAAO,MAAA,KAAW,QAAA,IAClB,aAAa,MAAA,IACb,IAAA;AAEJ;AAsBO,IAAM,iBAAN,MAAuD;AAAA,EAC5D,YAAoB,MAAA,EAA0B;AAA1B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA2B;AAAA,EAE/C,MAAM,QAAA,CAAS,IAAA,EAAe,MAAA,EAAyD;AACrF,IAAA,OAAO,IAAA,CAAK,YAAA,CAAa,IAAA,EAAM,MAAM,CAAA;AAAA,EACvC;AAAA,EAEA,YAAA,CAAa,MAAe,MAAA,EAAgD;AAC1E,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA;AAE/B,IAAA,IAAI,CAAC,eAAA,CAAgB,MAAM,CAAA,EAAG;AAC5B,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,IAAA;AAAA,QACT,IAAA,EAAM;AAAA,OACR;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,mBAAA,CAAoB,MAAA,EAAQ,MAAM,CAAA;AAEtD,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT;AAAA,KACF;AAAA,EACF;AAAA,EAEQ,mBAAA,CAAoB,WAA0B,MAAA,EAA6C;AACjG,IAAA,MAAM,SAA2B,EAAC;AAClC,IAAA,MAAM,cAAA,GAAiB,MAAA,EAAQ,QAAA,IAAY,EAAC;AAC5C,IAAA,MAAM,gBAAA,GAAmB,MAAA,EAAQ,UAAA,IAAc,EAAC;AAGhD,IAAA,MAAM,YAAuE,EAAC;AAE9E,IAAA,IAAI,UAAU,MAAA,IAAU,KAAA,CAAM,OAAA,CAAQ,SAAA,CAAU,MAAM,CAAA,EAAG;AACvD,MAAA,SAAA,CAAU,IAAA,CAAK,GAAG,SAAA,CAAU,MAAM,CAAA;AAAA,IACpC,CAAA,MAAA,IAAW,SAAA,CAAU,MAAA,CAAO,QAAQ,CAAA,EAAG;AACrC,MAAA,MAAM,UAAA,GAAa,SAAA,CAAU,MAAA,CAAO,QAAQ,CAAA;AAC5C,MAAA,IAAI,OAAO,eAAe,UAAA,EAAY;AACpC,QAAA,MAAM,QAAA,GAAW,UAAA,CAAW,IAAA,CAAK,SAAS,CAAA;AAC1C,QAAA,IAAI,MAAA,GAAS,SAAS,IAAA,EAAK;AAC3B,QAAA,OAAO,CAAC,OAAO,IAAA,EAAM;AACnB,UAAA,SAAA,CAAU,IAAA,CAAK,OAAO,KAAK,CAAA;AAC3B,UAAA,MAAA,GAAS,SAAS,IAAA,EAAK;AAAA,QACzB;AAAA,MACF;AAAA,IACF,CAAA,MAAO;AAEL,MAAA,SAAA,CAAU,IAAA,CAAK;AAAA,QACb,MAAM,EAAC;AAAA,QACP,SAAS,SAAA,CAAU;AAAA,OACpB,CAAA;AAAA,IACH;AAEA,IAAA,KAAA,MAAW,SAAS,SAAA,EAAW;AAC7B,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA,IAAK,OAAA;AAGrC,MAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,IAAI,CAAA,IAAK,IAAA;AAGhD,MAAA,MAAM,aAAa,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAA,CAAM,QAAQ,SAAS,CAAA,CAAA;AAGrD,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI,cAAA,CAAe,UAAU,CAAA,EAAG;AAC9B,QAAA,OAAA,GAAU,eAAe,UAAU,CAAA;AAAA,MACrC,CAAA,MAAA,IAAW,cAAA,CAAe,IAAI,CAAA,EAAG;AAC/B,QAAA,OAAA,GAAU,eAAe,IAAI,CAAA;AAAA,MAC/B,CAAA,MAAO;AAEL,QAAA,OAAA,GAAU,MAAM,OAAA,CAAQ,OAAA;AAAA,UACtB,IAAI,MAAA,CAAO,CAAA,GAAA,EAAM,IAAI,OAAO,IAAI,CAAA;AAAA,UAChC;AAAA,SACF;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,MAAA,CAAO,IAAI,CAAA,EAAG;AACjB,QAAA,MAAA,CAAO,IAAI,IAAI,EAAC;AAAA,MAClB;AACA,MAAA,MAAA,CAAO,IAAI,CAAA,CAAE,IAAA,CAAK,OAAO,CAAA;AAAA,IAC3B;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AC3HA,SAAS,UAAU,IAAA,EAA+B;AAChD,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,WAAA,EAAY,CAAE,MAAM,mCAAmC,CAAA;AAC1E,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,IAAI,CAAA,4CAAA,CAA8C,CAAA;AAAA,EAC5F;AAEA,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAM,CAAC,CAAC,CAAA;AACjC,EAAA,MAAM,IAAA,GAAQ,KAAA,CAAM,CAAC,CAAA,IAAK,GAAA;AAE1B,EAAA,MAAM,WAAA,GAAwC;AAAA,IAC5C,CAAA,EAAG,CAAA;AAAA,IACH,EAAA,EAAI,IAAA;AAAA,IACJ,IAAI,IAAA,GAAO,IAAA;AAAA,IACX,EAAA,EAAI,OAAO,IAAA,GAAO;AAAA,GACpB;AAEA,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,WAAA,CAAY,IAAI,CAAC,CAAA;AAC7C;AAMA,SAAS,eAAA,CAAgB,UAAkB,OAAA,EAA0B;AACnE,EAAA,IAAI,OAAA,KAAY,GAAA,IAAO,OAAA,KAAY,KAAA,EAAO;AACxC,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAA,EAAG;AAC1B,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AACpC,IAAA,OAAO,QAAA,CAAS,UAAA,CAAW,QAAA,GAAW,GAAG,CAAA;AAAA,EAC3C;AAEA,EAAA,OAAO,QAAA,KAAa,OAAA;AACtB;AA4DA,SAAS,oBAAoB,IAAA,EAA2B;AACtD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,GACpC,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,EAAI,EAAG,WAAA,MAAiB,EAAA,GAC7C,EAAA;AAEJ,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,IAAA;AAAA,IACA,SAAA;AAAA,IACA,WAAA,EAAa,MAAM,IAAA,CAAK,WAAA,EAAY;AAAA,IACpC,IAAA,EAAM,MAAM,IAAA,CAAK,IAAA,EAAK;AAAA,IACtB,MAAA,EAAQ,MAAM,IAAA,CAAK,MAAA;AAAO,GAC5B;AACF;AAiBO,SAAS,QAAA,CAAS,OAAA,GAA2B,EAAC,EAA6B;AAChF,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA,GAAW;AAAA,GACb,GAAI,OAAA;AAEJ,EAAA,MAAM,YAAA,GAAe,OAAA,GAAU,SAAA,CAAU,OAAO,CAAA,GAAI,MAAA;AACpD,EAAA,MAAM,YAAA,GAAe,OAAA,GAAU,SAAA,CAAU,OAAO,CAAA,GAAI,MAAA;AAEpD,EAAA,MAAM,UAAA,GAAaC,MAChB,UAAA,CAAW,IAAA,EAAM,EAAE,OAAA,EAAS,iBAAA,EAAmB,CAAA,CAC/C,MAAA;AAAA,IACC,CAAC,IAAA,KAAS;AACR,MAAA,IAAI,CAAC,QAAA,IAAY,IAAA,CAAK,IAAA,KAAS,GAAG,OAAO,IAAA;AACzC,MAAA,OAAO,KAAK,IAAA,GAAO,CAAA;AAAA,IACrB,CAAA;AAAA,IACA,EAAE,SAAS,kBAAA;AAAmB,GAChC,CACC,MAAA;AAAA,IACC,CAAC,IAAA,KAAS;AACR,MAAA,IAAI,CAAC,cAAc,OAAO,IAAA;AAC1B,MAAA,OAAO,KAAK,IAAA,IAAQ,YAAA;AAAA,IACtB,CAAA;AAAA,IACA;AAAA,MACE,OAAA,EAAS,OAAA,GACL,CAAA,0BAAA,EAA6B,OAAO,OAAA,KAAY,WAAW,OAAA,GAAU,CAAA,EAAG,OAAO,CAAA,MAAA,CAAQ,CAAA,CAAA,GACvF;AAAA;AACN,GACF,CACC,MAAA;AAAA,IACC,CAAC,IAAA,KAAS;AACR,MAAA,IAAI,CAAC,cAAc,OAAO,IAAA;AAC1B,MAAA,OAAO,KAAK,IAAA,IAAQ,YAAA;AAAA,IACtB,CAAA;AAAA,IACA;AAAA,MACE,OAAA,EAAS,OAAA,GACL,CAAA,2BAAA,EAA8B,OAAO,OAAA,KAAY,WAAW,OAAA,GAAU,CAAA,EAAG,OAAO,CAAA,MAAA,CAAQ,CAAA,CAAA,GACxF;AAAA;AACN,GACF,CACC,MAAA;AAAA,IACC,CAAC,IAAA,KAAS;AACR,MAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,MAAA,KAAW,GAAG,OAAO,IAAA;AACzC,MAAA,OAAO,KAAA,CAAM,KAAK,CAAC,OAAA,KAAY,gBAAgB,IAAA,CAAK,IAAA,EAAM,OAAO,CAAC,CAAA;AAAA,IACpE,CAAA;AAAA,IACA;AAAA,MACE,SAAS,KAAA,GACL,CAAA,0BAAA,EAA6B,MAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,GAC7C;AAAA;AACN,GACF,CACC,MAAA;AAAA,IACC,CAAC,IAAA,KAAS;AACR,MAAA,IAAI,CAAC,UAAA,IAAc,UAAA,CAAW,MAAA,KAAW,GAAG,OAAO,IAAA;AACnD,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,GAClC,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,EAAI,EAAG,aAAY,GACxC,EAAA;AACJ,MAAA,OAAO,WAAW,IAAA,CAAK,CAAC,QAAQ,GAAA,CAAI,WAAA,OAAkB,OAAO,CAAA;AAAA,IAC/D,CAAA;AAAA,IACA;AAAA,MACE,SAAS,UAAA,GACL,CAAA,+BAAA,EAAkC,WAAW,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,GACvD;AAAA;AACN,GACF,CACC,UAAU,mBAAmB,CAAA;AAGhC,EAAA,OAAO,UAAA;AACT;AAeO,SAAS,SAAA,CACd,OAAA,GAKI,EAAC,EACuB;AAC5B,EAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAU,GAAG,aAAY,GAAI,OAAA;AAC/C,EAAA,MAAM,mBAAmB,QAAA,CAAS,EAAE,GAAG,WAAA,EAAa,QAAA,EAAU,MAAM,CAAA;AAEpE,EAAA,IAAI,WAAA,GAAcA,KAAA,CAAE,KAAA,CAAM,gBAAgB,CAAA;AAE1C,EAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,IAAA,WAAA,GAAc,WAAA,CAAY,IAAI,QAAA,EAAU;AAAA,MACtC,OAAA,EAAS,YAAY,QAAQ,CAAA,iBAAA;AAAA,KAC9B,CAAA;AAAA,EACH;AAEA,EAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,IAAA,WAAA,GAAc,WAAA,CAAY,IAAI,QAAA,EAAU;AAAA,MACtC,OAAA,EAAS,WAAW,QAAQ,CAAA,gBAAA;AAAA,KAC7B,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,WAAA;AACT;;;ACtNA,SAAS,UAAU,IAAA,EAAmC;AACpD,EAAA,MAAM,WAAgC,EAAC;AACvC,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAE5B,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AAExB,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,kBAAkB,CAAA;AAChD,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,QAAA,CAAS,IAAA,CAAK,UAAA,CAAW,CAAC,CAAC,CAAA;AAC3B,MAAA,QAAA,CAAS,KAAK,QAAA,CAAS,UAAA,CAAW,CAAC,CAAA,EAAG,EAAE,CAAC,CAAA;AAAA,IAC3C,CAAA,MAAA,IAAW,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,EAAG;AAC7B,MAAA,QAAA,CAAS,IAAA,CAAK,QAAA,CAAS,IAAA,EAAM,EAAE,CAAC,CAAA;AAAA,IAClC,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,KAAK,IAAI,CAAA;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,OAAO,QAAA;AACT;AAKA,SAAS,cAAA,CACP,GAAA,EACA,IAAA,EACA,KAAA,EACM;AACN,EAAA,IAAI,OAAA,GAAmC,GAAA;AAEvC,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,GAAS,GAAG,CAAA,EAAA,EAAK;AACxC,IAAA,MAAM,GAAA,GAAM,KAAK,CAAC,CAAA;AAClB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA;AAC1B,IAAA,MAAM,MAAA,GAAS,OAAO,GAAG,CAAA;AAEzB,IAAA,IAAI,EAAE,UAAU,OAAA,CAAA,EAAU;AAExB,MAAA,OAAA,CAAQ,MAAM,CAAA,GAAI,OAAO,YAAY,QAAA,GAAW,KAAK,EAAC;AAAA,IACxD;AAEA,IAAA,OAAA,GAAU,QAAQ,MAAM,CAAA;AAAA,EAC1B;AAEA,EAAA,MAAM,UAAU,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,MAAA,GAAS,CAAC,CAAC,CAAA;AAC5C,EAAA,OAAA,CAAQ,OAAO,CAAA,GAAI,KAAA;AACrB;AAuBO,SAAS,YAAA,CACd,MAAA,EACA,OAAA,GAAkC,EAAC,EACjB;AAClB,EAAA,MAAM,EAAE,mBAAkB,GAAI,OAAA;AAE9B,EAAA,MAAM,OAAyB,EAAC;AAChC,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,MAAM,MAAgB,EAAC;AAEvB,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,QAAQ,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AAEtD,IAAA,MAAM,kBAAkB,iBAAA,GACpB,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,iBAAiB,CAAA,GACnC,QAAA;AAGJ,IAAA,IAAA,CAAK,KAAK,CAAA,GAAI,eAAA;AAGd,IAAA,GAAA,CAAI,IAAA,CAAK,GAAG,eAAe,CAAA;AAG3B,IAAA,MAAM,IAAA,GAAO,UAAU,KAAK,CAAA;AAC5B,IAAA,cAAA,CAAe,MAAA,EAAQ,MAAM,eAAe,CAAA;AAAA,EAC9C;AAEA,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,MAAA;AAAA,IACA,GAAA;AAAA,IACA,OAAO,GAAA,CAAI,MAAA;AAAA,IACX,IAAI,KAAA,EAAwB;AAC1B,MAAA,OAAO,KAAA,IAAS,IAAA,IAAQ,IAAA,CAAK,KAAK,EAAE,MAAA,GAAS,CAAA;AAAA,IAC/C,CAAA;AAAA,IACA,IAAI,KAAA,EAAyB;AAC3B,MAAA,OAAO,IAAA,CAAK,KAAK,CAAA,IAAK,EAAC;AAAA,IACzB,CAAA;AAAA,IACA,MAAM,KAAA,EAAmC;AACvC,MAAA,OAAO,IAAA,CAAK,KAAK,CAAA,GAAI,CAAC,CAAA;AAAA,IACxB;AAAA,GACF;AACF;AAkBO,SAAS,aAAA,CACd,MAAA,EACA,OAAA,GAAkC,EAAC,EACjB;AAClB,EAAA,MAAM,EAAE,aAAA,GAAgB,GAAA,EAAK,mBAAA,GAAsB,MAAK,GAAI,OAAA;AAC5D,EAAA,MAAM,SAA2B,EAAC;AAElC,EAAA,SAAS,OAAA,CAAQ,GAAA,EAAc,MAAA,GAAiB,EAAA,EAAU;AACxD,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AAEtB,MAAA,IAAI,IAAI,KAAA,CAAM,CAAC,SAAS,OAAO,IAAA,KAAS,QAAQ,CAAA,EAAG;AACjD,QAAA,MAAA,CAAO,MAAM,CAAA,GAAI,GAAA;AACjB,QAAA;AAAA,MACF;AAGA,MAAA,GAAA,CAAI,OAAA,CAAQ,CAAC,IAAA,EAAM,KAAA,KAAU;AAC3B,QAAA,MAAM,GAAA,GAAM,mBAAA,GACR,CAAA,EAAG,MAAM,CAAA,EAAG,SAAS,aAAA,GAAgB,EAAE,CAAA,EAAG,KAAK,CAAA,CAAA,GAC/C,MAAA;AACJ,QAAA,OAAA,CAAQ,MAAM,GAAG,CAAA;AAAA,MACnB,CAAC,CAAA;AAAA,IACH,CAAA,MAAA,IAAW,GAAA,KAAQ,IAAA,IAAQ,OAAO,QAAQ,QAAA,EAAU;AAClD,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AAC9C,QAAA,MAAM,SAAA,GAAY,SAAS,CAAA,EAAG,MAAM,GAAG,aAAa,CAAA,EAAG,GAAG,CAAA,CAAA,GAAK,GAAA;AAC/D,QAAA,OAAA,CAAQ,OAAO,SAAS,CAAA;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,MAAM,CAAA;AACd,EAAA,OAAO,MAAA;AACT;AAKO,SAAS,gBAAgB,MAAA,EAAkC;AAChE,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA;AACrC,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAAQ,CAAC,CAAA;AACnC,IAAA,OAAO,CAAA,EAAG,KAAK,CAAA,EAAA,EAAK,QAAA,CAAS,CAAC,CAAC,CAAA,CAAA;AAAA,EACjC;AAEA,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,MAAA,CAAO,CAAC,GAAA,EAAK,GAAG,IAAI,CAAA,KAAM,GAAA,GAAM,IAAA,CAAK,MAAA,EAAQ,CAAC,CAAA;AAC1E,EAAA,OAAO,CAAA,EAAG,WAAW,CAAA,iBAAA,EAAoB,WAAA,GAAc,IAAI,GAAA,GAAM,EAAE,CAAA,IAAA,EAAO,OAAA,CAAQ,MAAM,CAAA,MAAA,EAAS,OAAA,CAAQ,MAAA,GAAS,CAAA,GAAI,MAAM,EAAE,CAAA,CAAA;AAChI;AAKO,SAAS,YAAA,CACd,QACA,MAAA,EACkB;AAClB,EAAA,MAAM,SAA2B,EAAC;AAClC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,IAAI,MAAA,CAAO,KAAK,CAAA,EAAG;AACjB,MAAA,MAAA,CAAO,KAAK,CAAA,GAAI,MAAA,CAAO,KAAK,CAAA;AAAA,IAC9B;AAEA,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,QAAQ,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACpD,MAAA,IAAI,GAAA,CAAI,UAAA,CAAW,CAAA,EAAG,KAAK,GAAG,CAAA,EAAG;AAC/B,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,QAAA;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAKO,SAAS,eAAe,SAAA,EAAiD;AAC9E,EAAA,MAAM,SAA2B,EAAC;AAClC,EAAA,KAAA,MAAW,UAAU,SAAA,EAAW;AAC9B,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,QAAQ,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACtD,MAAA,IAAI,CAAC,MAAA,CAAO,KAAK,CAAA,EAAG;AAClB,QAAA,MAAA,CAAO,KAAK,IAAI,EAAC;AAAA,MACnB;AACA,MAAA,MAAA,CAAO,KAAK,CAAA,CAAE,IAAA,CAAK,GAAG,QAAQ,CAAA;AAAA,IAChC;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;;;ACxNO,SAAS,iBAAA,CACd,IAAA,EACA,OAAA,GAA8B,EAAC,EACtB;AACT,EAAA,MAAM;AAAA,IACJ,MAAA,GAAS,MAAA;AAAA,IACT,UAAU,EAAC;AAAA,IACX,QAAQ,EAAC;AAAA,IACT,OAAA,GAAU;AAAA,GACZ,GAAI,OAAA;AAGJ,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,OAAO,CAAA;AAC3B,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAChD,IAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,EACjC;AAGA,EAAA,MAAM,cAAA,GAAiB,IAAI,OAAA,CAAQ,OAAO,CAAA;AAC1C,EAAA,IAAI,CAAC,QAAQ,KAAA,EAAO,OAAO,EAAE,QAAA,CAAS,MAAA,CAAO,WAAA,EAAa,CAAA,EAAG;AAC3D,IAAA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,cAAc,CAAA,EAAG;AACvC,MAAA,cAAA,CAAe,GAAA,CAAI,gBAAgB,kBAAkB,CAAA;AAAA,IACvD;AAAA,EACF;AAEA,EAAA,OAAO,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,EAAS,EAAG;AAAA,IACjC,MAAA;AAAA,IACA,OAAA,EAAS,cAAA;AAAA,IACT,MAAM,IAAA,KAAS,MAAA,GAAY,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,GAAI;AAAA,GACnD,CAAA;AACH;AAgCA,eAAsB,eAAA,CACpB,YAAA,EACA,IAAA,EACA,OAAA,GAA8B,EAAC,EACG;AAClC,EAAA,MAAM,OAAA,GAAU,iBAAA,CAAkB,IAAA,EAAM,OAAO,CAAA;AAG/C,EAAA,MAAM,qBAAA,GAAwB,YAAA;AAK9B,EAAA,MAAM,WAAW,MAAM,qBAAA,CAAsB,aAAA,CAAc,OAAA,EAAS,QAAQ,MAAM,CAAA;AAElF,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,QAAA,EAAS;AACrC,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,IAAA;AAAA,MACT,IAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,IAAI,iBAAiB,eAAA,EAAiB;AACpC,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,QAAQ,KAAA,CAAM,MAAA;AAAA,QACd;AAAA,OACF;AAAA,IACF;AACA,IAAA,IAAI,iBAAiB,kBAAA,EAAoB;AACvC,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,YAAA,EAAc,IAAA;AAAA,QACd;AAAA,OACF;AAAA,IACF;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AACF;AAkBO,SAAS,cACd,YAAA,EACM;AACN,EAAC,YAAA,CAAoD,OAAO,OAC1D,IAAA,EACA,YACG,eAAA,CAAgB,YAAA,EAAc,MAAM,OAAO,CAAA;AAClD;AAaO,SAAS,YAAe,MAAA,EAAyG;AACtI,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,YAAA,GAAe,MAAA,CAAO,MAAA,GACxB,MAAA,CAAO,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,CACzB,GAAA,CAAI,CAAC,CAAC,KAAA,EAAO,QAAQ,CAAA,KAAM,CAAA,EAAG,KAAK,CAAA,EAAA,EAAK,QAAA,CAAS,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA,CAC7D,IAAA,CAAK,IAAI,CAAA,GACZ,MAAA,CAAO,YAAA,GACL,sBAAA,GACA,eAAA;AACN,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA;AAAA,EAAgD,YAAY,CAAA,CAAE,CAAA;AAAA,EAChF;AACF;AAKO,SAAS,cAAiB,MAAA,EAA2H;AAC1J,EAAA,IAAI,OAAO,OAAA,EAAS;AAClB,IAAA,MAAM,IAAI,MAAM,CAAA,sDAAA,EAAyD,IAAA,CAAK,UAAU,MAAA,CAAO,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,EACxG;AACA,EAAA,IAAI,CAAC,OAAO,MAAA,EAAQ;AAClB,IAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,EAC5D;AACF;AAKO,SAAS,gBAAA,CACd,MAAA,EACA,KAAA,EACA,cAAA,EACM;AACN,EAAA,aAAA,CAAc,MAAM,CAAA;AAEpB,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA;AACvC,EAAA,IAAI,CAAC,WAAA,IAAe,WAAA,CAAY,MAAA,KAAW,CAAA,EAAG;AAC5C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,8BAA8B,KAAK,CAAA,2BAAA,EAA8B,KAAK,SAAA,CAAU,MAAA,CAAO,MAAM,CAAC,CAAA;AAAA,KAChG;AAAA,EACF;AAEA,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,MAAM,WAAW,WAAA,CAAY,IAAA;AAAA,MAAK,CAAC,GAAA,KACjC,OAAO,cAAA,KAAmB,QAAA,GACtB,GAAA,CAAI,QAAA,CAAS,cAAc,CAAA,GAC3B,cAAA,CAAe,IAAA,CAAK,GAAG;AAAA,KAC7B;AACA,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,oBAAA,EAAuB,KAAK,CAAA,YAAA,EAAe,cAAc,eAAe,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,OAChG;AAAA,IACF;AAAA,EACF;AACF;;;AC1KO,SAAS,2BACd,WAAA,EACsC;AAAA,EACtC,MAAe,iCAAoC,WAAA,CAAe;AAAA,IAChE,MAAM,SAAA,GAA8B;AAClC,MAAA,OAAO,YAAY,IAAqC,CAAA;AAAA,IAC1D;AAAA;AAEF,EAAA,OAAO,wBAAA;AACT;AAmBO,SAAS,wBACX,MAAA,EAC+C;AAClD,EAAA,OAAO,iBAA8D;AACnE,IAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,MAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,IAAI,CAAA;AAC/B,MAAA,IAAI,CAAC,QAAQ,OAAO,KAAA;AAAA,IACtB;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AACF;AAKO,IAAM,WAAA,GAAc;AAAA;AAAA;AAAA;AAAA,EAIzB,SAAA,EAAW,CAAC,UAAA,KAAuB,CAAC,OAAA,KAA2C;AAC7E,IAAA,OAAO,CAAC,CAAC,OAAA,CAAQ,MAAA,CAAO,UAAU,CAAA;AAAA,EACpC,CAAA;AAAA;AAAA;AAAA;AAAA,EAKA,eAAA,EAAiB,CAAC,OAAA,KAA2C;AAC3D,IAAA,OAAO,CAAC,CAAC,OAAA,CAAQ,MAAA,CAAO,eAAe,CAAA;AAAA,EACzC,CAAA;AAAA;AAAA;AAAA;AAAA,EAKA,cAAA,EAAgB,CAAC,OAAA,KAA2C;AAC1D,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,eAAe,CAAA;AAC3C,IAAA,OAAO,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,CAAK,WAAW,SAAS,CAAA;AAAA,EAC9D,CAAA;AAAA;AAAA;AAAA;AAAA,EAKA,cAAA,EAAgB,CAAC,OAAA,KAAiD;AAChE,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,eAAe,CAAA;AAC3C,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,CAAK,UAAA,CAAW,SAAS,CAAA,EAAG;AAC1D,MAAA,OAAO,IAAA,CAAK,MAAM,CAAC,CAAA;AAAA,IACrB;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,EAAW,CAAC,UAAA,GAAqB,WAAA,KAC/B,CAAC,OAAA,KAA2C;AAC1C,IAAA,OAAO,CAAC,CAAC,OAAA,CAAQ,MAAA,CAAO,UAAU,CAAA;AAAA,EACpC;AACJ;AAKO,IAAM,WAAA,GAAc;AAAA;AAAA;AAAA;AAAA,EAIzB,gBAAA,EAAkB,CAAA,GAAI,KAAA,KACpB,iBAA2D;AACzD,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,MAAM,IAAA,CAAK,KAAK,IAAI,CAAA;AAAA,IACtB;AAAA,EACF,CAAA;AAAA;AAAA;AAAA;AAAA,EAKF,eAAA,EAAiB,CAAA,GAAO,KAAA,KACtB,eAAsC,IAAA,EAAwB;AAC5D,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,MAAM,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,IAAI,CAAA;AAAA,IAC5B;AAAA,EACF,CAAA;AAAA;AAAA;AAAA;AAAA,EAKF,UAAA,EAAY;AAAA;AAAA,IAEV,aAAa,WAA4C;AACvD,MAAA,MAAM,IAAA,GAAO,KAAK,GAAA,EAAI;AACtB,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC/C,QAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,UAAC,IAAA,CAAiC,GAAG,CAAA,GAAI,KAAA,CAAM,IAAA,EAAK;AAAA,QACtD;AAAA,MACF;AAAA,IACF,CAAA;AAAA;AAAA,IAGA,SAAA,EAAW,CAAA,GAAI,MAAA,KACb,WAA4C;AAC1C,MAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AAC9B,QAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,UAAC,KAAK,GAAA,EAAI,CAA8B,KAAK,CAAA,GAAI,MAAM,WAAA,EAAY;AAAA,QACrE;AAAA,MACF;AAAA,IACF,CAAA;AAAA;AAAA,IAGF,SAAA,EAAW,CAAA,GAAI,MAAA,KACb,WAA4C;AAC1C,MAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AAC9B,QAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,UAAC,KAAK,GAAA,EAAI,CAA8B,KAAK,CAAA,GAAI,MAAM,WAAA,EAAY;AAAA,QACrE;AAAA,MACF;AAAA,IACF;AAAA;AAEN","file":"index.js","sourcesContent":["import type { NextApiRequest } from 'next';\n\n/**\n * Validation errors mapped by field name to array of error messages\n */\nexport type ValidationErrors = Record<string, string[]>;\n\n/**\n * Result of a validation operation\n */\nexport interface ValidationResult<T> {\n success: boolean;\n data?: T;\n errors?: ValidationErrors;\n}\n\n/**\n * Configuration options for custom error messages and attribute names\n */\nexport interface ValidationConfig {\n messages?: Record<string, string>;\n attributes?: Record<string, string>;\n}\n\n/**\n * Adapter interface for validation libraries (Zod, Yup, etc.)\n */\nexport interface ValidatorAdapter<T> {\n /**\n * Validate data asynchronously\n */\n validate(data: unknown, config?: ValidationConfig): Promise<ValidationResult<T>>;\n\n /**\n * Validate data synchronously (optional)\n */\n validateSync?(data: unknown, config?: ValidationConfig): ValidationResult<T>;\n}\n\n/**\n * Data extracted from the incoming request\n */\nexport interface RequestData {\n body: unknown;\n query: Record<string, string | string[] | undefined>;\n params: Record<string, string>;\n headers: Record<string, string | string[] | undefined>;\n}\n\n/**\n * Union type for supported request types\n */\nexport type SupportedRequest = Request | NextApiRequest;\n\n/**\n * Type guard to check if request is App Router Request\n */\nexport function isAppRouterRequest(request: SupportedRequest): request is Request {\n return 'headers' in request && request.headers instanceof Headers;\n}\n\n/**\n * Type guard to check if request is Pages Router NextApiRequest\n */\nexport function isPagesRouterRequest(request: SupportedRequest): request is NextApiRequest {\n return 'query' in request && !('headers' in request && request.headers instanceof Headers);\n}\n\n/**\n * Constructor type for FormRequest classes\n */\nexport interface FormRequestConstructor<T, TValidated> {\n new (): T;\n fromAppRouter(request: Request, params?: Record<string, string>): Promise<T>;\n fromPagesRouter(request: NextApiRequest, params?: Record<string, string>): Promise<T>;\n}\n\n/**\n * Handler function for App Router withRequest wrapper\n */\nexport type AppRouterHandler<TValidated> = (\n validated: TValidated,\n request: Request\n) => Response | Promise<Response>;\n\n/**\n * Handler function for Pages Router withApiRequest wrapper\n */\nexport type PagesRouterHandler<TValidated> = (\n validated: TValidated,\n request: NextApiRequest,\n response: import('next').NextApiResponse\n) => void | Promise<void>;\n","import type { ValidationErrors } from './types';\n\n/**\n * Error thrown when request validation fails\n */\nexport class ValidationError extends Error {\n public readonly errors: ValidationErrors;\n\n constructor(errors: ValidationErrors) {\n const firstError = Object.values(errors)[0]?.[0] ?? 'Validation failed';\n super(firstError);\n this.name = 'ValidationError';\n this.errors = errors;\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ValidationError);\n }\n }\n\n /**\n * Get all error messages as a flat array\n */\n getAllMessages(): string[] {\n return Object.values(this.errors).flat();\n }\n\n /**\n * Get errors for a specific field\n */\n getFieldErrors(field: string): string[] {\n return this.errors[field] ?? [];\n }\n\n /**\n * Check if a specific field has errors\n */\n hasFieldError(field: string): boolean {\n return field in this.errors && this.errors[field].length > 0;\n }\n\n /**\n * Convert to JSON-serializable object\n */\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n errors: this.errors,\n };\n }\n}\n\n/**\n * Error thrown when request authorization fails\n */\nexport class AuthorizationError extends Error {\n constructor(message = 'Unauthorized') {\n super(message);\n this.name = 'AuthorizationError';\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, AuthorizationError);\n }\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n };\n }\n}\n","import type { NextApiRequest } from 'next';\n\n/**\n * Rate limit configuration\n */\nexport interface RateLimitConfig {\n /**\n * Maximum number of requests allowed in the time window\n */\n maxAttempts: number;\n\n /**\n * Time window in milliseconds\n */\n windowMs: number;\n\n /**\n * Function to generate the rate limit key from the request\n * Common options: IP address, user ID, API key, etc.\n * @default Uses IP address\n */\n key?: (request: Request | NextApiRequest) => string | Promise<string>;\n\n /**\n * Custom store for rate limit data\n * Defaults to in-memory store (not suitable for production with multiple instances)\n */\n store?: RateLimitStore;\n\n /**\n * Whether to skip rate limiting for certain requests\n */\n skip?: (request: Request | NextApiRequest) => boolean | Promise<boolean>;\n\n /**\n * Custom error message when rate limited\n */\n message?: string;\n}\n\n/**\n * Rate limit state for a specific key\n */\nexport interface RateLimitState {\n /** Number of requests made in the current window */\n count: number;\n /** Timestamp when the window resets */\n resetAt: number;\n}\n\n/**\n * Rate limit check result\n */\nexport interface RateLimitResult {\n /** Whether the request is allowed */\n allowed: boolean;\n /** Number of requests remaining in the current window */\n remaining: number;\n /** Total limit */\n limit: number;\n /** Timestamp when the window resets */\n resetAt: number;\n /** Number of seconds until reset */\n retryAfter: number;\n}\n\n/**\n * Interface for rate limit storage\n */\nexport interface RateLimitStore {\n /** Get the current state for a key */\n get(key: string): Promise<RateLimitState | null>;\n /** Set the state for a key */\n set(key: string, state: RateLimitState, ttlMs: number): Promise<void>;\n /** Increment the count for a key, returns new state */\n increment(key: string, windowMs: number): Promise<RateLimitState>;\n}\n\n/**\n * In-memory rate limit store (for development/testing only)\n * In production, use Redis or another distributed store\n */\nexport class MemoryRateLimitStore implements RateLimitStore {\n private store = new Map<string, RateLimitState>();\n\n async get(key: string): Promise<RateLimitState | null> {\n const state = this.store.get(key);\n if (!state) return null;\n\n // Check if window has expired\n if (Date.now() > state.resetAt) {\n this.store.delete(key);\n return null;\n }\n\n return state;\n }\n\n async set(key: string, state: RateLimitState, _ttlMs: number): Promise<void> {\n this.store.set(key, state);\n\n // Clean up expired entries periodically\n if (this.store.size > 1000) {\n this.cleanup();\n }\n }\n\n async increment(key: string, windowMs: number): Promise<RateLimitState> {\n const now = Date.now();\n const existing = this.store.get(key);\n\n if (!existing || now > existing.resetAt) {\n // Start new window\n const state: RateLimitState = {\n count: 1,\n resetAt: now + windowMs,\n };\n this.store.set(key, state);\n return state;\n }\n\n // Increment existing window\n existing.count++;\n return existing;\n }\n\n private cleanup(): void {\n const now = Date.now();\n for (const [key, state] of this.store.entries()) {\n if (now > state.resetAt) {\n this.store.delete(key);\n }\n }\n }\n}\n\n// Default shared store instance\nlet defaultStore: RateLimitStore = new MemoryRateLimitStore();\n\n/**\n * Set a custom default rate limit store\n * Useful for setting up Redis or other distributed stores\n */\nexport function setDefaultRateLimitStore(store: RateLimitStore): void {\n defaultStore = store;\n}\n\n/**\n * Get the client IP from a request\n */\nfunction getClientIp(request: Request | NextApiRequest): string {\n // App Router Request\n if ('headers' in request && request.headers instanceof Headers) {\n return (\n request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ||\n request.headers.get('x-real-ip') ||\n 'unknown'\n );\n }\n\n // Pages Router NextApiRequest\n const req = request as NextApiRequest;\n const forwarded = req.headers['x-forwarded-for'];\n if (typeof forwarded === 'string') {\n return forwarded.split(',')[0]?.trim() || 'unknown';\n }\n if (Array.isArray(forwarded)) {\n return forwarded[0]?.split(',')[0]?.trim() || 'unknown';\n }\n\n const realIp = req.headers['x-real-ip'];\n if (typeof realIp === 'string') {\n return realIp;\n }\n\n // Fallback to socket address if available\n const socket = (req as unknown as { socket?: { remoteAddress?: string } }).socket;\n return socket?.remoteAddress || 'unknown';\n}\n\n/**\n * Check rate limit for a request\n */\nexport async function checkRateLimit(\n request: Request | NextApiRequest,\n config: RateLimitConfig\n): Promise<RateLimitResult> {\n const { maxAttempts, windowMs, key, store = defaultStore, skip } = config;\n\n // Check if we should skip rate limiting\n if (skip && (await skip(request))) {\n return {\n allowed: true,\n remaining: maxAttempts,\n limit: maxAttempts,\n resetAt: Date.now() + windowMs,\n retryAfter: 0,\n };\n }\n\n // Get the rate limit key\n const rateLimitKey = key ? await key(request) : getClientIp(request);\n const fullKey = `ratelimit:${rateLimitKey}`;\n\n // Increment the counter\n const state = await store.increment(fullKey, windowMs);\n\n const allowed = state.count <= maxAttempts;\n const remaining = Math.max(0, maxAttempts - state.count);\n const retryAfter = allowed ? 0 : Math.ceil((state.resetAt - Date.now()) / 1000);\n\n return {\n allowed,\n remaining,\n limit: maxAttempts,\n resetAt: state.resetAt,\n retryAfter,\n };\n}\n\n/**\n * Rate limit error thrown when a request exceeds the rate limit\n */\nexport class RateLimitError extends Error {\n readonly retryAfter: number;\n readonly remaining: number;\n readonly limit: number;\n readonly resetAt: number;\n\n constructor(result: RateLimitResult, message?: string) {\n super(message || `Rate limit exceeded. Retry after ${result.retryAfter} seconds.`);\n this.name = 'RateLimitError';\n this.retryAfter = result.retryAfter;\n this.remaining = result.remaining;\n this.limit = result.limit;\n this.resetAt = result.resetAt;\n }\n\n /**\n * Get headers to send with the rate limit response\n */\n getHeaders(): Record<string, string> {\n return {\n 'X-RateLimit-Limit': String(this.limit),\n 'X-RateLimit-Remaining': String(this.remaining),\n 'X-RateLimit-Reset': String(this.resetAt),\n 'Retry-After': String(this.retryAfter),\n };\n }\n}\n\n/**\n * Create rate limit configuration with sensible defaults\n */\nexport function rateLimit(config: Partial<RateLimitConfig> & { maxAttempts: number; windowMs: number }): RateLimitConfig {\n return {\n key: getClientIp,\n ...config,\n };\n}\n","/**\n * Coercion utilities for automatically converting string values from form data\n * to their appropriate JavaScript types.\n */\n\n/**\n * Options for coercion\n */\nexport interface CoercionOptions {\n /** Coerce \"true\"/\"false\" strings to booleans */\n booleans?: boolean;\n /** Coerce numeric strings to numbers */\n numbers?: boolean;\n /** Coerce ISO date strings to Date objects */\n dates?: boolean;\n /** Coerce \"null\" string to null */\n nulls?: boolean;\n /** Coerce empty strings to undefined */\n emptyStrings?: boolean;\n /** Coerce JSON strings to objects/arrays */\n json?: boolean;\n /** Custom coercion functions for specific fields */\n fields?: Record<string, (value: unknown) => unknown>;\n}\n\nconst defaultOptions: CoercionOptions = {\n booleans: true,\n numbers: true,\n dates: true,\n nulls: true,\n emptyStrings: false,\n json: false,\n};\n\n/**\n * Check if a string looks like an ISO date\n */\nfunction isIsoDateString(value: string): boolean {\n // ISO 8601 date patterns\n const isoDateRegex = /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,3})?(Z|[+-]\\d{2}:?\\d{2})?)?$/;\n return isoDateRegex.test(value);\n}\n\n/**\n * Check if a string is a valid number\n */\nfunction isNumericString(value: string): boolean {\n if (value === '' || value === null) return false;\n // Don't coerce strings that look like IDs or codes (leading zeros, too long, etc.)\n if (/^0\\d/.test(value)) return false; // Leading zero (like \"01234\")\n if (value.length > 15) return false; // Too long to be a safe number\n return !isNaN(Number(value)) && isFinite(Number(value));\n}\n\n/**\n * Coerce a single value based on options\n */\nfunction coerceValue(value: unknown, options: CoercionOptions): unknown {\n if (typeof value !== 'string') {\n return value;\n }\n\n // Empty string handling\n if (options.emptyStrings && value === '') {\n return undefined;\n }\n\n // Null handling\n if (options.nulls && value === 'null') {\n return null;\n }\n\n // Boolean handling\n if (options.booleans) {\n const lower = value.toLowerCase();\n if (lower === 'true') return true;\n if (lower === 'false') return false;\n }\n\n // Date handling (check before numbers to avoid coercing \"2024\" to a number when it might be a year)\n if (options.dates && isIsoDateString(value)) {\n const date = new Date(value);\n if (!isNaN(date.getTime())) {\n return date;\n }\n }\n\n // Number handling\n if (options.numbers && isNumericString(value)) {\n return Number(value);\n }\n\n // JSON handling\n if (options.json) {\n const trimmed = value.trim();\n if ((trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'))) {\n try {\n return JSON.parse(value);\n } catch {\n // Not valid JSON, return as string\n }\n }\n }\n\n return value;\n}\n\n/**\n * Recursively coerce values in an object\n */\nfunction coerceObject(\n data: Record<string, unknown>,\n options: CoercionOptions,\n path: string = ''\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(data)) {\n const fieldPath = path ? `${path}.${key}` : key;\n\n // Check for custom field coercion\n if (options.fields && options.fields[fieldPath]) {\n result[key] = options.fields[fieldPath](value);\n continue;\n }\n\n if (Array.isArray(value)) {\n result[key] = value.map((item, index) => {\n if (item !== null && typeof item === 'object' && !Array.isArray(item)) {\n return coerceObject(item as Record<string, unknown>, options, `${fieldPath}.${index}`);\n }\n return coerceValue(item, options);\n });\n } else if (value !== null && typeof value === 'object') {\n result[key] = coerceObject(value as Record<string, unknown>, options, fieldPath);\n } else {\n result[key] = coerceValue(value, options);\n }\n }\n\n return result;\n}\n\n/**\n * Coerce form data values to their appropriate JavaScript types.\n *\n * Form submissions typically send everything as strings. This function\n * automatically converts common patterns:\n * - \"true\" / \"false\" → boolean\n * - \"123\" / \"45.67\" → number\n * - \"2024-01-01\" → Date\n * - \"null\" → null\n *\n * @example\n * ```typescript\n * const formData = {\n * name: \"John\",\n * age: \"25\",\n * active: \"true\",\n * createdAt: \"2024-01-01\",\n * };\n *\n * const coerced = coerceFormData(formData);\n * // {\n * // name: \"John\",\n * // age: 25,\n * // active: true,\n * // createdAt: Date(\"2024-01-01\"),\n * // }\n * ```\n */\nexport function coerceFormData<T extends Record<string, unknown>>(\n data: T,\n options: CoercionOptions = {}\n): T {\n const mergedOptions = { ...defaultOptions, ...options };\n return coerceObject(data, mergedOptions) as T;\n}\n\n/**\n * Create a Zod preprocessor for automatic coercion\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { zodCoerce } from 'next-request';\n *\n * const schema = z.preprocess(\n * zodCoerce(),\n * z.object({\n * name: z.string(),\n * age: z.number(),\n * active: z.boolean(),\n * })\n * );\n * ```\n */\nexport function zodCoerce(options: CoercionOptions = {}): (data: unknown) => unknown {\n return (data: unknown) => {\n if (data !== null && typeof data === 'object' && !Array.isArray(data)) {\n return coerceFormData(data as Record<string, unknown>, options);\n }\n return data;\n };\n}\n\n/**\n * Common coercion presets\n */\nexport const coercionPresets = {\n /** Coerce all supported types */\n all: { booleans: true, numbers: true, dates: true, nulls: true, emptyStrings: true, json: true },\n /** Only coerce booleans and numbers (safest) */\n safe: { booleans: true, numbers: true, dates: false, nulls: false, emptyStrings: false, json: false },\n /** Coerce booleans, numbers, and dates */\n standard: { booleans: true, numbers: true, dates: true, nulls: false, emptyStrings: false, json: false },\n /** No coercion */\n none: { booleans: false, numbers: false, dates: false, nulls: false, emptyStrings: false, json: false },\n} satisfies Record<string, CoercionOptions>;\n","import type { NextApiRequest } from 'next';\nimport type {\n ValidatorAdapter,\n RequestData,\n SupportedRequest,\n ValidationErrors,\n} from './types';\nimport { isAppRouterRequest } from './types';\nimport { ValidationError, AuthorizationError } from './errors';\nimport type { RateLimitConfig, RateLimitResult } from '../utils/rateLimit';\nimport { checkRateLimit, RateLimitError } from '../utils/rateLimit';\nimport { coerceFormData, type CoercionOptions } from '../utils/coerce';\n\n/**\n * Abstract base class for form request validation.\n * Inspired by Laravel's Form Request pattern.\n *\n * @example\n * ```typescript\n * import { FormRequest, ZodAdapter } from 'next-request';\n * import { z } from 'zod';\n *\n * const schema = z.object({\n * email: z.string().email(),\n * password: z.string().min(8),\n * });\n *\n * export class LoginRequest extends FormRequest<z.infer<typeof schema>> {\n * rules() {\n * return new ZodAdapter(schema);\n * }\n *\n * async authorize() {\n * return true; // Allow all requests\n * }\n *\n * beforeValidation() {\n * this.body.email = this.body.email?.toLowerCase().trim();\n * }\n * }\n * ```\n */\nexport abstract class FormRequest<TValidated = unknown> {\n /**\n * The original request object\n */\n protected request!: SupportedRequest;\n\n /**\n * Parsed request body (mutable for beforeValidation hook)\n */\n protected body: Record<string, unknown> = {};\n\n /**\n * Query parameters from the URL\n */\n protected query: Record<string, string | string[] | undefined> = {};\n\n /**\n * Route parameters (e.g., /users/[id])\n */\n protected params: Record<string, string> = {};\n\n /**\n * Request headers\n */\n protected headers: Record<string, string | string[] | undefined> = {};\n\n /**\n * Validated data (populated after successful validation)\n */\n private _validated: TValidated | null = null;\n\n /**\n * Partial validated data (fields that passed validation)\n */\n private _safe: Partial<TValidated> = {};\n\n // ─────────────────────────────────────────────────────────────\n // ABSTRACT METHODS (must be implemented by subclasses)\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Define the validation rules for this request.\n * Return a ValidatorAdapter instance (e.g., ZodAdapter, YupAdapter).\n */\n abstract rules(): ValidatorAdapter<TValidated>;\n\n // ─────────────────────────────────────────────────────────────\n // LIFECYCLE HOOKS (can be overridden)\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Determine if the user is authorized to make this request.\n * Override this method to add authorization logic.\n *\n * @returns true if authorized, false otherwise\n */\n authorize(): boolean | Promise<boolean> {\n return true;\n }\n\n /**\n * Define rate limiting for this request.\n * Override this method to add rate limiting.\n *\n * @example\n * ```typescript\n * rateLimit() {\n * return {\n * maxAttempts: 5,\n * windowMs: 60000, // 1 minute\n * key: (req) => this.input('email') || 'anonymous',\n * };\n * }\n * ```\n */\n rateLimit(): RateLimitConfig | null {\n return null;\n }\n\n /**\n * Define coercion options for form data.\n * Override this method to enable automatic type coercion.\n *\n * @example\n * ```typescript\n * coercion() {\n * return {\n * booleans: true, // \"true\" → true\n * numbers: true, // \"123\" → 123\n * dates: true, // \"2024-01-01\" → Date\n * };\n * }\n * ```\n */\n coercion(): CoercionOptions | null {\n return null;\n }\n\n /**\n * Called before validation runs.\n * Use this to normalize or transform input data.\n *\n * @example\n * ```typescript\n * beforeValidation() {\n * this.body.email = this.body.email?.toLowerCase().trim();\n * }\n * ```\n */\n beforeValidation(): void | Promise<void> {}\n\n /**\n * Called after validation succeeds.\n * Use this for logging, analytics, or post-processing.\n *\n * @param data The validated data\n */\n afterValidation(_data: TValidated): void | Promise<void> {}\n\n /**\n * Called when validation fails.\n * Use this for logging or custom error handling.\n *\n * @param errors The validation errors\n */\n onValidationFailed(_errors: ValidationErrors): void | Promise<void> {}\n\n /**\n * Called when authorization fails.\n * Use this for logging or custom error handling.\n */\n onAuthorizationFailed(): void | Promise<void> {}\n\n // ─────────────────────────────────────────────────────────────\n // CUSTOM MESSAGES (can be overridden)\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Custom validation error messages.\n * Keys can be field names or \"field.rule\" patterns.\n *\n * @example\n * ```typescript\n * messages() {\n * return {\n * 'email.email': 'Please provide a valid email address',\n * 'password.min': 'Password must be at least 8 characters',\n * };\n * }\n * ```\n */\n messages(): Record<string, string> {\n return {};\n }\n\n /**\n * Custom attribute names for error messages.\n * Used to replace field names in error messages.\n *\n * @example\n * ```typescript\n * attributes() {\n * return {\n * 'email': 'email address',\n * 'dob': 'date of birth',\n * };\n * }\n * ```\n */\n attributes(): Record<string, string> {\n return {};\n }\n\n // ─────────────────────────────────────────────────────────────\n // STATIC FACTORY METHODS\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Create a FormRequest instance from an App Router Request.\n *\n * @param request The incoming Request object\n * @param params Route parameters (from params in route handler)\n */\n static async fromAppRouter<T extends FormRequest>(\n this: new () => T,\n request: Request,\n params: Record<string, string> = {}\n ): Promise<T> {\n const instance = new this();\n instance.request = request;\n instance.params = params;\n\n // Parse headers\n instance.headers = {};\n request.headers.forEach((value, key) => {\n instance.headers[key] = value;\n });\n\n // Parse query from URL\n const url = new URL(request.url);\n instance.query = {};\n url.searchParams.forEach((value, key) => {\n const existing = instance.query[key];\n if (existing !== undefined) {\n instance.query[key] = Array.isArray(existing)\n ? [...existing, value]\n : [existing, value];\n } else {\n instance.query[key] = value;\n }\n });\n\n // Parse body for appropriate methods\n const method = request.method.toUpperCase();\n if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {\n try {\n const contentType = request.headers.get('content-type') ?? '';\n if (contentType.includes('application/json')) {\n instance.body = await request.clone().json();\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n const text = await request.clone().text();\n const formData = new URLSearchParams(text);\n instance.body = Object.fromEntries(formData.entries());\n } else if (contentType.includes('multipart/form-data')) {\n const formData = await request.clone().formData();\n instance.body = Object.fromEntries(formData.entries());\n }\n } catch {\n instance.body = {};\n }\n }\n\n return instance;\n }\n\n /**\n * Create a FormRequest instance from a Pages Router NextApiRequest.\n *\n * @param request The incoming NextApiRequest object\n * @param params Route parameters\n */\n static async fromPagesRouter<T extends FormRequest>(\n this: new () => T,\n request: NextApiRequest,\n params: Record<string, string> = {}\n ): Promise<T> {\n const instance = new this();\n instance.request = request;\n instance.params = { ...params, ...(request.query as Record<string, string>) };\n\n // Parse headers\n instance.headers = request.headers as Record<string, string | string[] | undefined>;\n\n // Parse query - Next.js already parses this\n instance.query = request.query as Record<string, string | string[] | undefined>;\n\n // Body is already parsed by Next.js\n instance.body = (request.body as Record<string, unknown>) ?? {};\n\n return instance;\n }\n\n // ─────────────────────────────────────────────────────────────\n // CORE VALIDATION METHODS\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Run validation and return the validated data.\n * Throws ValidationError if validation fails.\n * Throws AuthorizationError if authorization fails.\n * Throws RateLimitError if rate limit is exceeded.\n *\n * @returns The validated data with full type inference\n */\n async validate(): Promise<TValidated> {\n // Check rate limit first\n const rateLimitConfig = this.rateLimit();\n if (rateLimitConfig) {\n const result = await checkRateLimit(this.request, rateLimitConfig);\n if (!result.allowed) {\n throw new RateLimitError(result, rateLimitConfig.message);\n }\n }\n\n // Check authorization\n const isAuthorized = await this.authorize();\n if (!isAuthorized) {\n await this.onAuthorizationFailed();\n throw new AuthorizationError();\n }\n\n // Apply coercion if configured\n const coercionOptions = this.coercion();\n if (coercionOptions) {\n this.body = coerceFormData(this.body, coercionOptions);\n }\n\n // Run beforeValidation hook\n await this.beforeValidation();\n\n // Get the validator and run validation\n const validator = this.rules();\n const result = await validator.validate(this.getDataForValidation(), {\n messages: this.messages(),\n attributes: this.attributes(),\n });\n\n if (!result.success) {\n const errors = result.errors ?? { _error: ['Validation failed'] };\n await this.onValidationFailed(errors);\n throw new ValidationError(errors);\n }\n\n // Store validated data\n this._validated = result.data!;\n this._safe = result.data as Partial<TValidated>;\n\n // Run afterValidation hook\n await this.afterValidation(this._validated);\n\n return this._validated;\n }\n\n /**\n * Get the validated data (after calling validate()).\n * Throws if validate() hasn't been called successfully.\n */\n validated(): TValidated {\n if (this._validated === null) {\n throw new Error(\n 'Cannot access validated data before calling validate(). ' +\n 'Call validate() first and handle any errors.'\n );\n }\n return this._validated;\n }\n\n /**\n * Get only the fields that passed validation.\n * Safe to call even if validation hasn't completed.\n */\n safe(): Partial<TValidated> {\n return { ...this._safe };\n }\n\n /**\n * Get raw input data (body merged with query for GET requests).\n */\n all(): Record<string, unknown> {\n return { ...this.body };\n }\n\n /**\n * Get a specific input value.\n */\n input<T = unknown>(key: string, defaultValue?: T): T | undefined {\n const value = this.body[key] ?? this.query[key];\n return (value as T) ?? defaultValue;\n }\n\n /**\n * Check if input has a specific key.\n */\n has(key: string): boolean {\n return key in this.body || key in this.query;\n }\n\n /**\n * Get only specified keys from input.\n */\n only<K extends string>(...keys: K[]): Pick<Record<string, unknown>, K> {\n const result: Record<string, unknown> = {};\n for (const key of keys) {\n if (this.has(key)) {\n result[key] = this.input(key);\n }\n }\n return result as Pick<Record<string, unknown>, K>;\n }\n\n /**\n * Get all input except specified keys.\n */\n except(...keys: string[]): Record<string, unknown> {\n const result = { ...this.body };\n for (const key of keys) {\n delete result[key];\n }\n return result;\n }\n\n /**\n * Get the original request object.\n */\n getRequest(): SupportedRequest {\n return this.request;\n }\n\n /**\n * Check if this is an App Router request.\n */\n isAppRouter(): boolean {\n return isAppRouterRequest(this.request);\n }\n\n /**\n * Get a header value.\n */\n header(name: string): string | string[] | undefined {\n const lowerName = name.toLowerCase();\n if (isAppRouterRequest(this.request)) {\n return this.request.headers.get(lowerName) ?? undefined;\n }\n return this.headers[lowerName];\n }\n\n /**\n * Get a route parameter.\n */\n param(name: string): string | undefined {\n return this.params[name];\n }\n\n // ─────────────────────────────────────────────────────────────\n // PROTECTED HELPERS\n // ─────────────────────────────────────────────────────────────\n\n /**\n * Get the data that will be validated.\n * Override this to customize what data is passed to the validator.\n */\n protected getDataForValidation(): unknown {\n return this.body;\n }\n}\n\nexport default FormRequest;\n","import type { NextApiRequest, NextApiResponse } from 'next';\nimport { FormRequest } from '../core/FormRequest';\nimport { ValidationError, AuthorizationError } from '../core/errors';\n\n/**\n * Extract the validated type from a FormRequest constructor\n * This works by:\n * 1. Getting the instance type from the constructor: InstanceType<T>\n * 2. Checking if that instance extends FormRequest<infer V>\n * 3. Extracting V which is the TValidated generic parameter\n */\ntype InferValidatedType<T extends new () => any> =\n InstanceType<T> extends FormRequest<infer V> ? V : never;\n\n/**\n * Type for FormRequest constructor (legacy - kept for backward compatibility)\n */\ntype FormRequestClass<TValidated> = {\n new (): FormRequest<TValidated>;\n fromAppRouter(request: Request, params?: Record<string, string>): Promise<FormRequest<TValidated>>;\n fromPagesRouter(request: NextApiRequest, params?: Record<string, string>): Promise<FormRequest<TValidated>>;\n};\n\n/**\n * Handler function for App Router\n */\ntype AppRouterHandler<TValidated> = (\n validated: TValidated,\n request: Request,\n formRequest: FormRequest<TValidated>\n) => Response | Promise<Response>;\n\n/**\n * Handler function for Pages Router\n */\ntype PagesRouterHandler<TValidated> = (\n validated: TValidated,\n req: NextApiRequest,\n res: NextApiResponse,\n formRequest: FormRequest<TValidated>\n) => void | Promise<void>;\n\n/**\n * Context parameter for App Router (Next.js 13+)\n */\ninterface AppRouterContext {\n params?: Record<string, string> | Promise<Record<string, string>>;\n}\n\n/**\n * Wrap an App Router route handler with form request validation.\n *\n * The handler receives validated data and only executes if:\n * 1. Authorization passes (authorize() returns true)\n * 2. Validation passes (rules() validates successfully)\n *\n * Errors are thrown, not auto-handled - catch ValidationError and\n * AuthorizationError in your handler or error boundary.\n *\n * @example\n * ```typescript\n * // app/api/users/route.ts\n * import { withRequest } from 'next-request';\n * import { CreateUserRequest } from '@/requests/CreateUserRequest';\n *\n * export const POST = withRequest(CreateUserRequest, async (data, request) => {\n * const user = await db.users.create({ data });\n * return Response.json({ user }, { status: 201 });\n * });\n * ```\n */\nexport function withRequest<T extends new () => FormRequest<any>>(\n RequestClass: T & {\n fromAppRouter(request: Request, params?: Record<string, string>): Promise<InstanceType<T>>;\n },\n handler: AppRouterHandler<InferValidatedType<T>>\n): (request: Request, context?: AppRouterContext) => Promise<Response> {\n return async (request: Request, context?: AppRouterContext) => {\n // Resolve params (may be a Promise in Next.js 15+)\n const params = context?.params\n ? (context.params instanceof Promise ? await context.params : context.params)\n : {};\n\n const formRequest = await RequestClass.fromAppRouter(request, params);\n const validated = await formRequest.validate();\n\n return handler(validated, request, formRequest);\n };\n}\n\n/**\n * Wrap a Pages Router API handler with form request validation.\n *\n * The handler receives validated data and only executes if:\n * 1. Authorization passes (authorize() returns true)\n * 2. Validation passes (rules() validates successfully)\n *\n * Errors are thrown, not auto-handled - catch ValidationError and\n * AuthorizationError in your handler.\n *\n * @example\n * ```typescript\n * // pages/api/users.ts\n * import { withApiRequest } from 'next-request';\n * import { CreateUserRequest } from '@/requests/CreateUserRequest';\n *\n * export default withApiRequest(CreateUserRequest, async (data, req, res) => {\n * const user = await db.users.create({ data });\n * res.status(201).json({ user });\n * });\n * ```\n */\nexport function withApiRequest<T extends new () => FormRequest<any>>(\n RequestClass: T & {\n fromPagesRouter(request: NextApiRequest, params?: Record<string, string>): Promise<InstanceType<T>>;\n },\n handler: PagesRouterHandler<InferValidatedType<T>>\n): (req: NextApiRequest, res: NextApiResponse) => Promise<void> {\n return async (req: NextApiRequest, res: NextApiResponse) => {\n const formRequest = await RequestClass.fromPagesRouter(req);\n const validated = await formRequest.validate();\n\n await handler(validated, req, res, formRequest);\n };\n}\n\n/**\n * Create a wrapper with custom error handling for App Router.\n *\n * @example\n * ```typescript\n * import { createAppRouterWrapper, ValidationError, AuthorizationError } from 'next-request';\n *\n * const withValidation = createAppRouterWrapper({\n * onValidationError: (error) => Response.json({ errors: error.errors }, { status: 422 }),\n * onAuthorizationError: () => Response.json({ message: 'Forbidden' }, { status: 403 }),\n * });\n *\n * export const POST = withValidation(CreateUserRequest, async (data) => {\n * const user = await db.users.create({ data });\n * return Response.json({ user }, { status: 201 });\n * });\n * ```\n */\nexport function createAppRouterWrapper(options: {\n onValidationError?: (error: ValidationError) => Response;\n onAuthorizationError?: (error: AuthorizationError) => Response;\n onError?: (error: unknown) => Response;\n}): <T extends new () => FormRequest<any>>(\n RequestClass: T & {\n fromAppRouter(request: Request, params?: Record<string, string>): Promise<InstanceType<T>>;\n },\n handler: AppRouterHandler<InferValidatedType<T>>\n) => (request: Request, context?: AppRouterContext) => Promise<Response> {\n return <T extends new () => FormRequest<any>>(\n RequestClass: T & {\n fromAppRouter(request: Request, params?: Record<string, string>): Promise<InstanceType<T>>;\n },\n handler: AppRouterHandler<InferValidatedType<T>>\n ) => {\n return async (request: Request, context?: AppRouterContext) => {\n try {\n const params = context?.params\n ? (context.params instanceof Promise ? await context.params : context.params)\n : {};\n\n const formRequest = await RequestClass.fromAppRouter(request, params);\n const validated = await formRequest.validate();\n\n return handler(validated, request, formRequest);\n } catch (error) {\n if (error instanceof ValidationError && options.onValidationError) {\n return options.onValidationError(error);\n }\n if (error instanceof AuthorizationError && options.onAuthorizationError) {\n return options.onAuthorizationError(error);\n }\n if (options.onError) {\n return options.onError(error);\n }\n throw error;\n }\n };\n };\n}\n\n/**\n * Create a wrapper with custom error handling for Pages Router.\n *\n * @example\n * ```typescript\n * import { createPagesRouterWrapper, ValidationError, AuthorizationError } from 'next-request';\n *\n * const withValidation = createPagesRouterWrapper({\n * onValidationError: (error, req, res) => res.status(422).json({ errors: error.errors }),\n * onAuthorizationError: (error, req, res) => res.status(403).json({ message: 'Forbidden' }),\n * });\n *\n * export default withValidation(CreateUserRequest, async (data, req, res) => {\n * const user = await db.users.create({ data });\n * res.status(201).json({ user });\n * });\n * ```\n */\nexport function createPagesRouterWrapper(options: {\n onValidationError?: (\n error: ValidationError,\n req: NextApiRequest,\n res: NextApiResponse\n ) => void | Promise<void>;\n onAuthorizationError?: (\n error: AuthorizationError,\n req: NextApiRequest,\n res: NextApiResponse\n ) => void | Promise<void>;\n onError?: (\n error: unknown,\n req: NextApiRequest,\n res: NextApiResponse\n ) => void | Promise<void>;\n}): <T extends new () => FormRequest<any>>(\n RequestClass: T & {\n fromPagesRouter(request: NextApiRequest, params?: Record<string, string>): Promise<InstanceType<T>>;\n },\n handler: PagesRouterHandler<InferValidatedType<T>>\n) => (req: NextApiRequest, res: NextApiResponse) => Promise<void> {\n return <T extends new () => FormRequest<any>>(\n RequestClass: T & {\n fromPagesRouter(request: NextApiRequest, params?: Record<string, string>): Promise<InstanceType<T>>;\n },\n handler: PagesRouterHandler<InferValidatedType<T>>\n ) => {\n return async (req: NextApiRequest, res: NextApiResponse) => {\n try {\n const formRequest = await RequestClass.fromPagesRouter(req);\n const validated = await formRequest.validate();\n\n await handler(validated, req, res, formRequest);\n } catch (error) {\n if (error instanceof ValidationError && options.onValidationError) {\n return options.onValidationError(error, req, res);\n }\n if (error instanceof AuthorizationError && options.onAuthorizationError) {\n return options.onAuthorizationError(error, req, res);\n }\n if (options.onError) {\n return options.onError(error, req, res);\n }\n throw error;\n }\n };\n };\n}\n","import type { NextApiRequest, NextApiResponse } from 'next';\nimport type { ValidatorAdapter } from '../core/types';\nimport { ValidationError } from '../core/errors';\n\n/**\n * Infer the validated type from a ValidationAdapter\n * This extracts the generic type parameter T from ValidatorAdapter<T>\n */\ntype InferValidatedType<T> = T extends ValidatorAdapter<infer V> ? V : never;\n\n/**\n * Handler function for App Router with schema validation\n */\ntype SchemaHandler<TValidated> = (\n data: TValidated,\n request: Request\n) => Response | Promise<Response>;\n\n/**\n * Handler function for Pages Router with schema validation\n */\ntype ApiSchemaHandler<TValidated> = (\n data: TValidated,\n req: NextApiRequest,\n res: NextApiResponse\n) => void | Promise<void>;\n\n/**\n * Context parameter for App Router (Next.js 13+)\n */\ninterface AppRouterContext {\n params?: Record<string, string> | Promise<Record<string, string>>;\n}\n\n/**\n * Parse request body based on content type\n */\nasync function parseRequestBody(request: Request): Promise<unknown> {\n const contentType = request.headers.get('content-type') || '';\n\n if (contentType.includes('application/json')) {\n try {\n return await request.json();\n } catch {\n return {};\n }\n }\n\n if (contentType.includes('application/x-www-form-urlencoded') || contentType.includes('multipart/form-data')) {\n try {\n const formData = await request.formData();\n const data: Record<string, unknown> = {};\n\n formData.forEach((value, key) => {\n if (data[key]) {\n // Handle multiple values for same key\n if (Array.isArray(data[key])) {\n (data[key] as unknown[]).push(value);\n } else {\n data[key] = [data[key], value];\n }\n } else {\n data[key] = value;\n }\n });\n\n return data;\n } catch {\n return {};\n }\n }\n\n return {};\n}\n\n/**\n * Wrap an App Router route handler with simple schema validation.\n *\n * This is a lightweight alternative to withRequest for cases where you don't need\n * hooks or authorization - just schema validation.\n *\n * The handler receives validated data and only executes if validation passes.\n * ValidationError is thrown on validation failure.\n *\n * @example\n * ```typescript\n * // app/api/users/route.ts\n * import { withSchema, ZodAdapter } from 'next-request';\n * import { z } from 'zod';\n *\n * const userSchema = z.object({\n * name: z.string().min(2),\n * email: z.string().email(),\n * });\n *\n * export const POST = withSchema(new ZodAdapter(userSchema), async (data) => {\n * // data is typed as { name: string; email: string }\n * const user = await db.users.create({ data });\n * return Response.json({ user }, { status: 201 });\n * });\n * ```\n */\nexport function withSchema<T extends ValidatorAdapter<any>>(\n adapter: T,\n handler: SchemaHandler<InferValidatedType<T>>\n): (request: Request, context?: AppRouterContext) => Promise<Response> {\n return async (request: Request, context?: AppRouterContext) => {\n // Parse request body\n const body = await parseRequestBody(request);\n\n // Validate the data\n const result = await adapter.validate(body);\n\n if (!result.success) {\n throw new ValidationError(result.errors || {});\n }\n\n // Call handler with validated data\n return handler(result.data as InferValidatedType<T>, request);\n };\n}\n\n/**\n * Wrap a Pages Router API handler with simple schema validation.\n *\n * This is a lightweight alternative to withApiRequest for cases where you don't need\n * hooks or authorization - just schema validation.\n *\n * The handler receives validated data and only executes if validation passes.\n * ValidationError is thrown on validation failure.\n *\n * @example\n * ```typescript\n * // pages/api/users.ts\n * import { withApiSchema, ZodAdapter } from 'next-request';\n * import { z } from 'zod';\n *\n * const userSchema = z.object({\n * name: z.string().min(2),\n * email: z.string().email(),\n * });\n *\n * export default withApiSchema(new ZodAdapter(userSchema), async (data, req, res) => {\n * // data is typed as { name: string; email: string }\n * const user = await db.users.create({ data });\n * res.status(201).json({ user });\n * });\n * ```\n */\nexport function withApiSchema<T extends ValidatorAdapter<any>>(\n adapter: T,\n handler: ApiSchemaHandler<InferValidatedType<T>>\n): (req: NextApiRequest, res: NextApiResponse) => Promise<void> {\n return async (req: NextApiRequest, res: NextApiResponse) => {\n // Get body from request (Next.js Pages Router automatically parses JSON)\n const body = req.body;\n\n // Validate the data\n const result = await adapter.validate(body);\n\n if (!result.success) {\n throw new ValidationError(result.errors || {});\n }\n\n // Call handler with validated data\n await handler(result.data as InferValidatedType<T>, req, res);\n };\n}\n","import type { ZodSchema, ZodError } from 'zod';\nimport type { ValidatorAdapter, ValidationResult, ValidationConfig, ValidationErrors } from '../../core/types';\n\n/**\n * Validator adapter for Zod schemas\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { ZodAdapter } from 'next-request/zod';\n *\n * const schema = z.object({\n * email: z.string().email(),\n * name: z.string().min(2),\n * });\n *\n * class MyRequest extends FormRequest<z.infer<typeof schema>> {\n * rules() {\n * return new ZodAdapter(schema);\n * }\n * }\n * ```\n */\nexport class ZodAdapter<T> implements ValidatorAdapter<T> {\n constructor(private schema: ZodSchema<T>) {}\n\n async validate(data: unknown, config?: ValidationConfig): Promise<ValidationResult<T>> {\n return this.validateSync(data, config);\n }\n\n validateSync(data: unknown, config?: ValidationConfig): ValidationResult<T> {\n const result = this.schema.safeParse(data);\n\n if (result.success) {\n return {\n success: true,\n data: result.data,\n };\n }\n\n const errors = this.formatZodErrors(result.error, config);\n\n return {\n success: false,\n errors,\n };\n }\n\n private formatZodErrors(error: ZodError, config?: ValidationConfig): ValidationErrors {\n const errors: ValidationErrors = {};\n const customMessages = config?.messages ?? {};\n const customAttributes = config?.attributes ?? {};\n\n for (const issue of error.issues) {\n const path = issue.path.join('.');\n const fieldName = path || '_root';\n\n // Get custom attribute name if available\n const attributeName = customAttributes[fieldName] ?? fieldName;\n\n // Build the message key for custom messages (e.g., \"email.email\", \"password.min\")\n const messageKey = `${fieldName}.${issue.code}`;\n\n // Check for custom message, otherwise use Zod's message with custom attribute\n let message: string;\n if (customMessages[messageKey]) {\n message = customMessages[messageKey];\n } else if (customMessages[fieldName]) {\n message = customMessages[fieldName];\n } else {\n // Replace field references in Zod's default message\n message = issue.message.replace(\n new RegExp(`\\\\b${fieldName}\\\\b`, 'gi'),\n attributeName\n );\n }\n\n if (!errors[fieldName]) {\n errors[fieldName] = [];\n }\n errors[fieldName].push(message);\n }\n\n return errors;\n }\n}\n","import type { ValidatorAdapter, ValidationResult, ValidationConfig, ValidationErrors } from '../../core/types';\n\n// Yup types - defined locally to avoid hard dependency\ninterface YupValidationError {\n inner: YupValidationError[];\n path?: string;\n message: string;\n type?: string;\n name: string;\n}\n\ninterface YupSchema<T> {\n validate(data: unknown, options?: { abortEarly?: boolean; stripUnknown?: boolean }): Promise<T>;\n validateSync(data: unknown, options?: { abortEarly?: boolean; stripUnknown?: boolean }): T;\n}\n\n/**\n * Validator adapter for Yup schemas\n *\n * @example\n * ```typescript\n * import * as yup from 'yup';\n * import { YupAdapter } from 'next-request';\n *\n * const schema = yup.object({\n * email: yup.string().email().required(),\n * name: yup.string().min(2).required(),\n * });\n *\n * class MyRequest extends FormRequest<yup.InferType<typeof schema>> {\n * rules() {\n * return new YupAdapter(schema);\n * }\n * }\n * ```\n */\nexport class YupAdapter<T> implements ValidatorAdapter<T> {\n constructor(private schema: YupSchema<T>) {}\n\n async validate(data: unknown, config?: ValidationConfig): Promise<ValidationResult<T>> {\n try {\n const validated = await this.schema.validate(data, {\n abortEarly: false,\n stripUnknown: true,\n });\n\n return {\n success: true,\n data: validated as T,\n };\n } catch (error) {\n if (this.isYupValidationError(error)) {\n const errors = this.formatYupErrors(error, config);\n return {\n success: false,\n errors,\n };\n }\n throw error;\n }\n }\n\n validateSync(data: unknown, config?: ValidationConfig): ValidationResult<T> {\n try {\n const validated = this.schema.validateSync(data, {\n abortEarly: false,\n stripUnknown: true,\n });\n\n return {\n success: true,\n data: validated as T,\n };\n } catch (error) {\n if (this.isYupValidationError(error)) {\n const errors = this.formatYupErrors(error, config);\n return {\n success: false,\n errors,\n };\n }\n throw error;\n }\n }\n\n private isYupValidationError(error: unknown): error is YupValidationError {\n return (\n error !== null &&\n typeof error === 'object' &&\n 'inner' in error &&\n 'name' in error &&\n (error as { name: string }).name === 'ValidationError'\n );\n }\n\n private formatYupErrors(error: YupValidationError, config?: ValidationConfig): ValidationErrors {\n const errors: ValidationErrors = {};\n const customMessages = config?.messages ?? {};\n const customAttributes = config?.attributes ?? {};\n\n // Handle case where there are no inner errors (single error)\n const innerErrors = error.inner.length > 0 ? error.inner : [error];\n\n for (const issue of innerErrors) {\n const path = issue.path ?? '_root';\n\n // Get custom attribute name if available\n const attributeName = customAttributes[path] ?? path;\n\n // Build the message key for custom messages (e.g., \"email.email\", \"password.min\")\n const messageKey = `${path}.${issue.type ?? 'invalid'}`;\n\n // Check for custom message, otherwise use Yup's message with custom attribute\n let message: string;\n if (customMessages[messageKey]) {\n message = customMessages[messageKey];\n } else if (customMessages[path]) {\n message = customMessages[path];\n } else {\n // Replace field references in Yup's default message\n message = issue.message.replace(\n new RegExp(`\\\\b${path}\\\\b`, 'gi'),\n attributeName\n );\n }\n\n if (!errors[path]) {\n errors[path] = [];\n }\n errors[path].push(message);\n }\n\n return errors;\n }\n}\n","import type { ValidatorAdapter, ValidationResult, ValidationConfig, ValidationErrors } from '../../core/types';\n\n// Valibot types - defined locally to avoid hard dependency\ninterface ValibotIssue {\n path?: Array<{ key: string | number } | string | number>;\n message?: string;\n type?: string;\n}\n\ninterface SafeParseResult<T> {\n success: boolean;\n output?: T;\n issues?: ValibotIssue[];\n}\n\n// Generic schema type for Valibot\ninterface ValibotSchema<TOutput = unknown> {\n _output?: TOutput;\n}\n\n/**\n * Validator adapter for Valibot schemas.\n *\n * Since valibot is an optional peer dependency, you must pass the safeParse function\n * from your valibot installation.\n *\n * @example\n * ```typescript\n * import * as v from 'valibot';\n * import { ValibotAdapter } from 'next-request';\n *\n * const schema = v.object({\n * email: v.pipe(v.string(), v.email()),\n * name: v.pipe(v.string(), v.minLength(2)),\n * });\n *\n * class MyRequest extends FormRequest<v.InferOutput<typeof schema>> {\n * rules() {\n * return new ValibotAdapter(schema, v.safeParse);\n * }\n * }\n * ```\n */\nexport class ValibotAdapter<T> implements ValidatorAdapter<T> {\n private safeParseFunc: (schema: ValibotSchema<T>, data: unknown) => SafeParseResult<T>;\n\n constructor(\n private schema: ValibotSchema<T>,\n safeParse: (schema: ValibotSchema<T>, data: unknown) => SafeParseResult<T>\n ) {\n this.safeParseFunc = safeParse;\n }\n\n async validate(data: unknown, config?: ValidationConfig): Promise<ValidationResult<T>> {\n return this.validateSync(data, config);\n }\n\n validateSync(data: unknown, config?: ValidationConfig): ValidationResult<T> {\n const result = this.safeParseFunc(this.schema, data);\n\n if (result.success) {\n return {\n success: true,\n data: result.output,\n };\n }\n\n const errors = this.formatValibotErrors(result.issues ?? [], config);\n\n return {\n success: false,\n errors,\n };\n }\n\n private formatValibotErrors(issues: ValibotIssue[], config?: ValidationConfig): ValidationErrors {\n const errors: ValidationErrors = {};\n const customMessages = config?.messages ?? {};\n const customAttributes = config?.attributes ?? {};\n\n for (const issue of issues) {\n // Valibot uses path array similar to Zod\n const pathParts = issue.path?.map((p: { key: string | number } | string | number) => {\n if (typeof p === 'object' && p !== null && 'key' in p) {\n return String(p.key);\n }\n return String(p);\n }) ?? [];\n const path = pathParts.join('.') || '_root';\n\n // Get custom attribute name if available\n const attributeName = customAttributes[path] ?? path;\n\n // Build the message key for custom messages\n const messageKey = `${path}.${issue.type ?? 'invalid'}`;\n\n // Check for custom message, otherwise use Valibot's message with custom attribute\n let message: string;\n if (customMessages[messageKey]) {\n message = customMessages[messageKey];\n } else if (customMessages[path]) {\n message = customMessages[path];\n } else {\n // Replace field references in Valibot's default message\n message = (issue.message ?? 'Validation failed').replace(\n new RegExp(`\\\\b${path}\\\\b`, 'gi'),\n attributeName\n );\n }\n\n if (!errors[path]) {\n errors[path] = [];\n }\n errors[path].push(message);\n }\n\n return errors;\n }\n}\n","import type { ValidatorAdapter, ValidationResult, ValidationConfig, ValidationErrors } from '../../core/types';\n\n// ArkType types - we use generics to avoid hard dependency\ninterface ArkTypeSchema<T = unknown> {\n (data: unknown): T | ArkTypeErrors;\n}\n\ninterface ArkTypeErrors {\n summary: string;\n errors?: Array<{\n path: string[];\n message: string;\n code?: string;\n }>;\n [Symbol.iterator]?: () => Iterator<{ path: string[]; message: string }>;\n}\n\n/**\n * Type guard to check if result is ArkType errors\n */\nfunction isArkTypeErrors(result: unknown): result is ArkTypeErrors {\n return (\n result !== null &&\n typeof result === 'object' &&\n 'summary' in result &&\n true\n );\n}\n\n/**\n * Validator adapter for ArkType schemas\n *\n * @example\n * ```typescript\n * import { type } from 'arktype';\n * import { ArkTypeAdapter } from 'next-request';\n *\n * const schema = type({\n * email: 'string.email',\n * name: 'string >= 2',\n * });\n *\n * class MyRequest extends FormRequest<typeof schema.infer> {\n * rules() {\n * return new ArkTypeAdapter(schema);\n * }\n * }\n * ```\n */\nexport class ArkTypeAdapter<T> implements ValidatorAdapter<T> {\n constructor(private schema: ArkTypeSchema<T>) {}\n\n async validate(data: unknown, config?: ValidationConfig): Promise<ValidationResult<T>> {\n return this.validateSync(data, config);\n }\n\n validateSync(data: unknown, config?: ValidationConfig): ValidationResult<T> {\n const result = this.schema(data);\n\n if (!isArkTypeErrors(result)) {\n return {\n success: true,\n data: result as T,\n };\n }\n\n const errors = this.formatArkTypeErrors(result, config);\n\n return {\n success: false,\n errors,\n };\n }\n\n private formatArkTypeErrors(arkErrors: ArkTypeErrors, config?: ValidationConfig): ValidationErrors {\n const errors: ValidationErrors = {};\n const customMessages = config?.messages ?? {};\n const customAttributes = config?.attributes ?? {};\n\n // Try to iterate over errors if possible\n const errorList: Array<{ path: string[]; message: string; code?: string }> = [];\n\n if (arkErrors.errors && Array.isArray(arkErrors.errors)) {\n errorList.push(...arkErrors.errors);\n } else if (arkErrors[Symbol.iterator]) {\n const iteratorFn = arkErrors[Symbol.iterator];\n if (typeof iteratorFn === 'function') {\n const iterator = iteratorFn.call(arkErrors);\n let result = iterator.next();\n while (!result.done) {\n errorList.push(result.value);\n result = iterator.next();\n }\n }\n } else {\n // Fallback to summary as root error\n errorList.push({\n path: [],\n message: arkErrors.summary,\n });\n }\n\n for (const issue of errorList) {\n const path = issue.path.join('.') || '_root';\n\n // Get custom attribute name if available\n const attributeName = customAttributes[path] ?? path;\n\n // Build the message key for custom messages\n const messageKey = `${path}.${issue.code ?? 'invalid'}`;\n\n // Check for custom message, otherwise use ArkType's message with custom attribute\n let message: string;\n if (customMessages[messageKey]) {\n message = customMessages[messageKey];\n } else if (customMessages[path]) {\n message = customMessages[path];\n } else {\n // Replace field references in ArkType's default message\n message = issue.message.replace(\n new RegExp(`\\\\b${path}\\\\b`, 'gi'),\n attributeName\n );\n }\n\n if (!errors[path]) {\n errors[path] = [];\n }\n errors[path].push(message);\n }\n\n return errors;\n }\n}\n","import { z } from 'zod';\n\n/**\n * Size units for file size limits\n */\ntype SizeUnit = 'b' | 'kb' | 'mb' | 'gb';\n\n/**\n * Parse a size string like \"5mb\" into bytes\n */\nfunction parseSize(size: string | number): number {\n if (typeof size === 'number') {\n return size;\n }\n\n const match = size.toLowerCase().match(/^(\\d+(?:\\.\\d+)?)\\s*(b|kb|mb|gb)?$/);\n if (!match) {\n throw new Error(`Invalid size format: ${size}. Use formats like \"5mb\", \"1024kb\", or \"1gb\"`);\n }\n\n const value = parseFloat(match[1]);\n const unit = (match[2] || 'b') as SizeUnit;\n\n const multipliers: Record<SizeUnit, number> = {\n b: 1,\n kb: 1024,\n mb: 1024 * 1024,\n gb: 1024 * 1024 * 1024,\n };\n\n return Math.floor(value * multipliers[unit]);\n}\n\n/**\n * Check if a MIME type matches a pattern\n * Supports wildcards like \"image/*\"\n */\nfunction mimeTypeMatches(mimeType: string, pattern: string): boolean {\n if (pattern === '*' || pattern === '*/*') {\n return true;\n }\n\n if (pattern.endsWith('/*')) {\n const category = pattern.slice(0, -2);\n return mimeType.startsWith(category + '/');\n }\n\n return mimeType === pattern;\n}\n\n/**\n * Options for file validation\n */\nexport interface FormFileOptions {\n /**\n * Maximum file size. Can be a number (bytes) or a string like \"5mb\"\n */\n maxSize?: string | number;\n\n /**\n * Minimum file size. Can be a number (bytes) or a string like \"1kb\"\n */\n minSize?: string | number;\n\n /**\n * Allowed MIME types. Supports wildcards like \"image/*\"\n * @example ['image/*', 'application/pdf']\n */\n types?: string[];\n\n /**\n * Allowed file extensions (without the dot)\n * @example ['jpg', 'png', 'pdf']\n */\n extensions?: string[];\n\n /**\n * Whether the file is required\n * @default true\n */\n required?: boolean;\n}\n\n/**\n * Validated file data returned after successful validation\n */\nexport interface ValidatedFile {\n /** Original file name */\n name: string;\n /** File size in bytes */\n size: number;\n /** MIME type */\n type: string;\n /** The File object (browser) or Blob */\n file: File | Blob;\n /** File extension (lowercase, without dot) */\n extension: string;\n /** Get file as ArrayBuffer */\n arrayBuffer(): Promise<ArrayBuffer>;\n /** Get file as text */\n text(): Promise<string>;\n /** Get file as readable stream */\n stream(): ReadableStream<Uint8Array>;\n}\n\n/**\n * Create a validated file object from a File\n */\nfunction createValidatedFile(file: File): ValidatedFile {\n const extension = file.name.includes('.')\n ? file.name.split('.').pop()?.toLowerCase() ?? ''\n : '';\n\n return {\n name: file.name,\n size: file.size,\n type: file.type,\n file,\n extension,\n arrayBuffer: () => file.arrayBuffer(),\n text: () => file.text(),\n stream: () => file.stream(),\n };\n}\n\n/**\n * Create a Zod schema for file validation with common file constraints.\n *\n * @example\n * ```typescript\n * import { formFile } from 'next-request';\n * import { z } from 'zod';\n *\n * const schema = z.object({\n * avatar: formFile({ maxSize: '5mb', types: ['image/*'] }),\n * document: formFile({ maxSize: '10mb', types: ['application/pdf'] }),\n * attachment: formFile({ maxSize: '20mb', extensions: ['pdf', 'doc', 'docx'] }),\n * });\n * ```\n */\nexport function formFile(options: FormFileOptions = {}): z.ZodType<ValidatedFile> {\n const {\n maxSize,\n minSize,\n types,\n extensions,\n required = true,\n } = options;\n\n const maxSizeBytes = maxSize ? parseSize(maxSize) : undefined;\n const minSizeBytes = minSize ? parseSize(minSize) : undefined;\n\n const fileSchema = z\n .instanceof(File, { message: 'Expected a file' })\n .refine(\n (file) => {\n if (!required && file.size === 0) return true;\n return file.size > 0;\n },\n { message: 'File is required' }\n )\n .refine(\n (file) => {\n if (!maxSizeBytes) return true;\n return file.size <= maxSizeBytes;\n },\n {\n message: maxSize\n ? `File size must not exceed ${typeof maxSize === 'string' ? maxSize : `${maxSize} bytes`}`\n : 'File is too large',\n }\n )\n .refine(\n (file) => {\n if (!minSizeBytes) return true;\n return file.size >= minSizeBytes;\n },\n {\n message: minSize\n ? `File size must be at least ${typeof minSize === 'string' ? minSize : `${minSize} bytes`}`\n : 'File is too small',\n }\n )\n .refine(\n (file) => {\n if (!types || types.length === 0) return true;\n return types.some((pattern) => mimeTypeMatches(file.type, pattern));\n },\n {\n message: types\n ? `File type must be one of: ${types.join(', ')}`\n : 'Invalid file type',\n }\n )\n .refine(\n (file) => {\n if (!extensions || extensions.length === 0) return true;\n const fileExt = file.name.includes('.')\n ? file.name.split('.').pop()?.toLowerCase()\n : '';\n return extensions.some((ext) => ext.toLowerCase() === fileExt);\n },\n {\n message: extensions\n ? `File extension must be one of: ${extensions.join(', ')}`\n : 'Invalid file extension',\n }\n )\n .transform(createValidatedFile);\n\n // Use unknown cast to work around Zod's strict input type checking\n return fileSchema as unknown as z.ZodType<ValidatedFile>;\n}\n\n/**\n * Create a Zod schema for multiple file uploads\n *\n * @example\n * ```typescript\n * import { formFiles } from 'next-request';\n * import { z } from 'zod';\n *\n * const schema = z.object({\n * images: formFiles({ maxSize: '5mb', types: ['image/*'], maxFiles: 5 }),\n * });\n * ```\n */\nexport function formFiles(\n options: FormFileOptions & {\n /** Minimum number of files */\n minFiles?: number;\n /** Maximum number of files */\n maxFiles?: number;\n } = {}\n): z.ZodType<ValidatedFile[]> {\n const { minFiles, maxFiles, ...fileOptions } = options;\n const singleFileSchema = formFile({ ...fileOptions, required: true });\n\n let arraySchema = z.array(singleFileSchema);\n\n if (minFiles !== undefined) {\n arraySchema = arraySchema.min(minFiles, {\n message: `At least ${minFiles} file(s) required`,\n });\n }\n\n if (maxFiles !== undefined) {\n arraySchema = arraySchema.max(maxFiles, {\n message: `Maximum ${maxFiles} file(s) allowed`,\n });\n }\n\n return arraySchema;\n}\n\n/**\n * Type helper to extract the inferred type from a formFile schema\n */\nexport type InferFormFile = ValidatedFile;\nexport type InferFormFiles = ValidatedFile[];\n","import type { ValidationErrors } from '../core/types';\n\n/**\n * Options for error formatting\n */\nexport interface ErrorFormattingOptions {\n /** Include field path in error messages */\n includePath?: boolean;\n /** Custom path separator for nested fields */\n pathSeparator?: string;\n /** Maximum number of errors per field */\n maxErrorsPerField?: number;\n /** Include array indices in paths */\n includeArrayIndices?: boolean;\n}\n\n/**\n * Structured error format for nested objects and arrays\n */\nexport interface StructuredErrors {\n /** Flat errors (field path → messages) */\n flat: ValidationErrors;\n /** Nested errors matching the original object structure */\n nested: Record<string, unknown>;\n /** Array of all error messages */\n all: string[];\n /** Count of total errors */\n count: number;\n /** Check if a specific field has errors */\n has(field: string): boolean;\n /** Get errors for a specific field */\n get(field: string): string[];\n /** Get first error for a specific field */\n first(field: string): string | undefined;\n}\n\n/**\n * Parse a dot-notation path into segments\n */\nfunction parsePath(path: string): (string | number)[] {\n const segments: (string | number)[] = [];\n const parts = path.split('.');\n\n for (const part of parts) {\n // Check for array notation like \"items[0]\" or just \"0\"\n const arrayMatch = part.match(/^(.+?)\\[(\\d+)\\]$/);\n if (arrayMatch) {\n segments.push(arrayMatch[1]);\n segments.push(parseInt(arrayMatch[2], 10));\n } else if (/^\\d+$/.test(part)) {\n segments.push(parseInt(part, 10));\n } else {\n segments.push(part);\n }\n }\n\n return segments;\n}\n\n/**\n * Set a value at a nested path in an object\n */\nfunction setNestedValue(\n obj: Record<string, unknown>,\n path: (string | number)[],\n value: unknown\n): void {\n let current: Record<string, unknown> = obj;\n\n for (let i = 0; i < path.length - 1; i++) {\n const key = path[i];\n const nextKey = path[i + 1];\n const keyStr = String(key);\n\n if (!(keyStr in current)) {\n // Create array or object based on next key type\n current[keyStr] = typeof nextKey === 'number' ? [] : {};\n }\n\n current = current[keyStr] as Record<string, unknown>;\n }\n\n const lastKey = String(path[path.length - 1]);\n current[lastKey] = value;\n}\n\n/**\n * Format validation errors with improved support for nested objects and arrays.\n *\n * @example\n * ```typescript\n * const errors = {\n * 'user.email': ['Invalid email'],\n * 'items.0.name': ['Name is required'],\n * 'items.1.price': ['Price must be positive'],\n * };\n *\n * const formatted = formatErrors(errors);\n * // formatted.nested = {\n * // user: { email: ['Invalid email'] },\n * // items: [\n * // { name: ['Name is required'] },\n * // { price: ['Price must be positive'] },\n * // ],\n * // }\n * ```\n */\nexport function formatErrors(\n errors: ValidationErrors,\n options: ErrorFormattingOptions = {}\n): StructuredErrors {\n const { maxErrorsPerField } = options;\n\n const flat: ValidationErrors = {};\n const nested: Record<string, unknown> = {};\n const all: string[] = [];\n\n for (const [field, messages] of Object.entries(errors)) {\n // Apply max errors per field limit\n const limitedMessages = maxErrorsPerField\n ? messages.slice(0, maxErrorsPerField)\n : messages;\n\n // Store flat errors\n flat[field] = limitedMessages;\n\n // Add to all errors\n all.push(...limitedMessages);\n\n // Build nested structure\n const path = parsePath(field);\n setNestedValue(nested, path, limitedMessages);\n }\n\n return {\n flat,\n nested,\n all,\n count: all.length,\n has(field: string): boolean {\n return field in flat && flat[field].length > 0;\n },\n get(field: string): string[] {\n return flat[field] ?? [];\n },\n first(field: string): string | undefined {\n return flat[field]?.[0];\n },\n };\n}\n\n/**\n * Flatten nested errors into dot-notation paths\n *\n * @example\n * ```typescript\n * const nested = {\n * user: { email: ['Invalid email'] },\n * items: [\n * { name: ['Name is required'] },\n * ],\n * };\n *\n * const flat = flattenErrors(nested);\n * // { 'user.email': ['Invalid email'], 'items.0.name': ['Name is required'] }\n * ```\n */\nexport function flattenErrors(\n nested: Record<string, unknown>,\n options: ErrorFormattingOptions = {}\n): ValidationErrors {\n const { pathSeparator = '.', includeArrayIndices = true } = options;\n const result: ValidationErrors = {};\n\n function flatten(obj: unknown, prefix: string = ''): void {\n if (Array.isArray(obj)) {\n // Check if it's an array of error messages (strings)\n if (obj.every((item) => typeof item === 'string')) {\n result[prefix] = obj as string[];\n return;\n }\n\n // It's an array of nested objects\n obj.forEach((item, index) => {\n const key = includeArrayIndices\n ? `${prefix}${prefix ? pathSeparator : ''}${index}`\n : prefix;\n flatten(item, key);\n });\n } else if (obj !== null && typeof obj === 'object') {\n for (const [key, value] of Object.entries(obj)) {\n const newPrefix = prefix ? `${prefix}${pathSeparator}${key}` : key;\n flatten(value, newPrefix);\n }\n }\n }\n\n flatten(nested);\n return result;\n}\n\n/**\n * Get human-readable error summary\n */\nexport function summarizeErrors(errors: ValidationErrors): string {\n const entries = Object.entries(errors);\n if (entries.length === 0) {\n return 'No errors';\n }\n\n if (entries.length === 1) {\n const [field, messages] = entries[0];\n return `${field}: ${messages[0]}`;\n }\n\n const totalErrors = entries.reduce((sum, [, msgs]) => sum + msgs.length, 0);\n return `${totalErrors} validation error${totalErrors > 1 ? 's' : ''} in ${entries.length} field${entries.length > 1 ? 's' : ''}`;\n}\n\n/**\n * Filter errors to only include specific fields\n */\nexport function filterErrors(\n errors: ValidationErrors,\n fields: string[]\n): ValidationErrors {\n const result: ValidationErrors = {};\n for (const field of fields) {\n if (errors[field]) {\n result[field] = errors[field];\n }\n // Also check for nested fields\n for (const [key, messages] of Object.entries(errors)) {\n if (key.startsWith(`${field}.`)) {\n result[key] = messages;\n }\n }\n }\n return result;\n}\n\n/**\n * Merge multiple error objects\n */\nexport function mergeErrors(...errorSets: ValidationErrors[]): ValidationErrors {\n const result: ValidationErrors = {};\n for (const errors of errorSets) {\n for (const [field, messages] of Object.entries(errors)) {\n if (!result[field]) {\n result[field] = [];\n }\n result[field].push(...messages);\n }\n }\n return result;\n}\n","import type { ValidationErrors } from '../core/types';\nimport { FormRequest } from '../core/FormRequest';\nimport { ValidationError, AuthorizationError } from '../core/errors';\n\n/**\n * Result of a mock validation\n */\nexport interface MockValidationResult<T> {\n /** Whether validation succeeded */\n success: boolean;\n /** Validated data (if successful) */\n data?: T;\n /** Validation errors (if failed) */\n errors?: ValidationErrors;\n /** Whether authorization was denied */\n unauthorized?: boolean;\n /** The FormRequest instance */\n instance: FormRequest<T>;\n}\n\n/**\n * Options for creating a mock request\n */\nexport interface MockRequestOptions {\n /** HTTP method */\n method?: string;\n /** Request headers */\n headers?: Record<string, string>;\n /** Query parameters */\n query?: Record<string, string>;\n /** Route parameters */\n params?: Record<string, string>;\n /** Base URL for the request */\n baseUrl?: string;\n}\n\n/**\n * Create a mock Request object for testing\n */\nexport function createMockRequest(\n body: unknown,\n options: MockRequestOptions = {}\n): Request {\n const {\n method = 'POST',\n headers = {},\n query = {},\n baseUrl = 'http://localhost:3000/api/test',\n } = options;\n\n // Build URL with query parameters\n const url = new URL(baseUrl);\n for (const [key, value] of Object.entries(query)) {\n url.searchParams.set(key, value);\n }\n\n // Set default content type for POST/PUT/PATCH\n const requestHeaders = new Headers(headers);\n if (['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {\n if (!requestHeaders.has('content-type')) {\n requestHeaders.set('content-type', 'application/json');\n }\n }\n\n return new Request(url.toString(), {\n method,\n headers: requestHeaders,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n}\n\n/**\n * Test a FormRequest with mock data\n *\n * @example\n * ```typescript\n * import { testFormRequest } from 'next-request/testing';\n *\n * describe('CreateUserRequest', () => {\n * it('should validate valid data', async () => {\n * const result = await testFormRequest(CreateUserRequest, {\n * email: 'user@example.com',\n * password: 'securepassword123',\n * });\n *\n * expect(result.success).toBe(true);\n * expect(result.data?.email).toBe('user@example.com');\n * });\n *\n * it('should reject invalid email', async () => {\n * const result = await testFormRequest(CreateUserRequest, {\n * email: 'invalid-email',\n * password: 'securepassword123',\n * });\n *\n * expect(result.success).toBe(false);\n * expect(result.errors?.email).toBeDefined();\n * });\n * });\n * ```\n */\nexport async function testFormRequest<T>(\n RequestClass: new () => FormRequest<T>,\n body: unknown,\n options: MockRequestOptions = {}\n): Promise<MockValidationResult<T>> {\n const request = createMockRequest(body, options);\n\n // Use the static factory method\n const FormRequestWithStatic = RequestClass as unknown as {\n new (): FormRequest<T>;\n fromAppRouter(request: Request, params?: Record<string, string>): Promise<FormRequest<T>>;\n };\n\n const instance = await FormRequestWithStatic.fromAppRouter(request, options.params);\n\n try {\n const data = await instance.validate();\n return {\n success: true,\n data,\n instance,\n };\n } catch (error) {\n if (error instanceof ValidationError) {\n return {\n success: false,\n errors: error.errors,\n instance,\n };\n }\n if (error instanceof AuthorizationError) {\n return {\n success: false,\n unauthorized: true,\n instance,\n };\n }\n throw error;\n }\n}\n\n/**\n * Add static mock method to FormRequest class\n * This allows calling CreateUserRequest.mock({ ... }) directly\n *\n * @example\n * ```typescript\n * import { addMockMethod } from 'next-request/testing';\n *\n * // Add mock method to a specific request class\n * addMockMethod(CreateUserRequest);\n *\n * // Now you can use it directly\n * const result = await CreateUserRequest.mock({ email: 'invalid' });\n * expect(result.errors?.email).toBeDefined();\n * ```\n */\nexport function addMockMethod<T>(\n RequestClass: new () => FormRequest<T>\n): void {\n (RequestClass as unknown as Record<string, unknown>).mock = async (\n body: unknown,\n options?: MockRequestOptions\n ) => testFormRequest(RequestClass, body, options);\n}\n\n/**\n * Type helper for FormRequest classes with mock method\n */\nexport interface MockableFormRequest<T> {\n new (): FormRequest<T>;\n mock(body: unknown, options?: MockRequestOptions): Promise<MockValidationResult<T>>;\n}\n\n/**\n * Assert that validation passes\n */\nexport function expectValid<T>(result: MockValidationResult<T>): asserts result is MockValidationResult<T> & { success: true; data: T } {\n if (!result.success) {\n const errorDetails = result.errors\n ? Object.entries(result.errors)\n .map(([field, messages]) => `${field}: ${messages.join(', ')}`)\n .join('\\n')\n : result.unauthorized\n ? 'Authorization denied'\n : 'Unknown error';\n throw new Error(`Expected validation to pass, but it failed:\\n${errorDetails}`);\n }\n}\n\n/**\n * Assert that validation fails\n */\nexport function expectInvalid<T>(result: MockValidationResult<T>): asserts result is MockValidationResult<T> & { success: false; errors: ValidationErrors } {\n if (result.success) {\n throw new Error(`Expected validation to fail, but it passed with data: ${JSON.stringify(result.data)}`);\n }\n if (!result.errors) {\n throw new Error('Expected validation errors, but got none');\n }\n}\n\n/**\n * Assert that a specific field has errors\n */\nexport function expectFieldError<T>(\n result: MockValidationResult<T>,\n field: string,\n messagePattern?: string | RegExp\n): void {\n expectInvalid(result);\n\n const fieldErrors = result.errors[field];\n if (!fieldErrors || fieldErrors.length === 0) {\n throw new Error(\n `Expected errors for field \"${field}\", but found none. Errors: ${JSON.stringify(result.errors)}`\n );\n }\n\n if (messagePattern) {\n const hasMatch = fieldErrors.some((msg) =>\n typeof messagePattern === 'string'\n ? msg.includes(messagePattern)\n : messagePattern.test(msg)\n );\n if (!hasMatch) {\n throw new Error(\n `Expected error for \"${field}\" to match \"${messagePattern}\", but got: ${fieldErrors.join(', ')}`\n );\n }\n }\n}\n","import type { NextApiRequest } from 'next';\nimport { FormRequest } from '../core/FormRequest';\nimport type { ValidatorAdapter } from '../core/types';\n\n/**\n * Base request class for common authorization patterns.\n * Extend this class to create reusable authorization logic.\n *\n * @example\n * ```typescript\n * // Create a base authenticated request\n * abstract class AuthenticatedRequest<T> extends FormRequest<T> {\n * async authorize() {\n * const token = this.header('authorization');\n * if (!token) return false;\n * // Verify token...\n * return true;\n * }\n * }\n *\n * // Create an admin request that inherits authentication\n * abstract class AdminRequest<T> extends AuthenticatedRequest<T> {\n * async authorize() {\n * // First check parent authorization\n * if (!(await super.authorize())) return false;\n * // Then check admin role...\n * return this.isAdmin();\n * }\n * }\n *\n * // Use in specific requests\n * class CreateProductRequest extends AdminRequest<CreateProductData> {\n * rules() {\n * return new ZodAdapter(createProductSchema);\n * }\n * // Automatically requires admin authorization!\n * }\n * ```\n */\n\n/**\n * Mixin type for adding functionality to FormRequest classes\n */\nexport type FormRequestMixin<T> = {\n new <TValidated>(): FormRequest<TValidated> & T;\n};\n\n/**\n * Create an authenticated request base class\n *\n * @example\n * ```typescript\n * const AuthenticatedRequest = createAuthenticatedRequest(async (request) => {\n * const token = request.header('authorization');\n * return !!token && await verifyToken(token);\n * });\n *\n * class MyRequest extends AuthenticatedRequest<MyData> {\n * rules() { return new ZodAdapter(schema); }\n * }\n * ```\n */\nexport function createAuthenticatedRequest<TBase = unknown>(\n authorizeFn: (request: FormRequest<TBase>) => boolean | Promise<boolean>\n): abstract new <T>() => FormRequest<T> {\n abstract class AuthenticatedFormRequest<T> extends FormRequest<T> {\n async authorize(): Promise<boolean> {\n return authorizeFn(this as unknown as FormRequest<TBase>);\n }\n }\n return AuthenticatedFormRequest as abstract new <T>() => FormRequest<T>;\n}\n\n/**\n * Compose multiple authorization checks\n *\n * @example\n * ```typescript\n * const authorize = composeAuthorization(\n * isAuthenticated,\n * hasRole('admin'),\n * hasPermission('products.create')\n * );\n *\n * class CreateProductRequest extends FormRequest<CreateProductData> {\n * authorize = authorize;\n * rules() { return new ZodAdapter(schema); }\n * }\n * ```\n */\nexport function composeAuthorization(\n ...checks: Array<(request: FormRequest<unknown>) => boolean | Promise<boolean>>\n): (this: FormRequest<unknown>) => Promise<boolean> {\n return async function (this: FormRequest<unknown>): Promise<boolean> {\n for (const check of checks) {\n const result = await check(this);\n if (!result) return false;\n }\n return true;\n };\n}\n\n/**\n * Common authorization helpers\n */\nexport const authHelpers = {\n /**\n * Check if request has a specific header\n */\n hasHeader: (headerName: string) => (request: FormRequest<unknown>): boolean => {\n return !!request.header(headerName);\n },\n\n /**\n * Check if request has authorization header\n */\n isAuthenticated: (request: FormRequest<unknown>): boolean => {\n return !!request.header('authorization');\n },\n\n /**\n * Check if request has a bearer token\n */\n hasBearerToken: (request: FormRequest<unknown>): boolean => {\n const auth = request.header('authorization');\n return typeof auth === 'string' && auth.startsWith('Bearer ');\n },\n\n /**\n * Extract bearer token from request\n */\n getBearerToken: (request: FormRequest<unknown>): string | null => {\n const auth = request.header('authorization');\n if (typeof auth === 'string' && auth.startsWith('Bearer ')) {\n return auth.slice(7);\n }\n return null;\n },\n\n /**\n * Check if request has API key\n */\n hasApiKey: (headerName: string = 'x-api-key') =>\n (request: FormRequest<unknown>): boolean => {\n return !!request.header(headerName);\n },\n};\n\n/**\n * Lifecycle hook composition utilities\n */\nexport const hookHelpers = {\n /**\n * Compose multiple beforeValidation hooks\n */\n beforeValidation: (...hooks: Array<(this: FormRequest<unknown>) => void | Promise<void>>) =>\n async function (this: FormRequest<unknown>): Promise<void> {\n for (const hook of hooks) {\n await hook.call(this);\n }\n },\n\n /**\n * Compose multiple afterValidation hooks\n */\n afterValidation: <T>(...hooks: Array<(this: FormRequest<T>, data: T) => void | Promise<void>>) =>\n async function (this: FormRequest<T>, data: T): Promise<void> {\n for (const hook of hooks) {\n await hook.call(this, data);\n }\n },\n\n /**\n * Common beforeValidation transformations\n */\n transforms: {\n /** Trim all string values */\n trimStrings: function (this: FormRequest<unknown>): void {\n const body = this.all();\n for (const [key, value] of Object.entries(body)) {\n if (typeof value === 'string') {\n (body as Record<string, unknown>)[key] = value.trim();\n }\n }\n },\n\n /** Lowercase specific fields */\n lowercase: (...fields: string[]) =>\n function (this: FormRequest<unknown>): void {\n for (const field of fields) {\n const value = this.input(field);\n if (typeof value === 'string') {\n (this.all() as Record<string, unknown>)[field] = value.toLowerCase();\n }\n }\n },\n\n /** Uppercase specific fields */\n uppercase: (...fields: string[]) =>\n function (this: FormRequest<unknown>): void {\n for (const field of fields) {\n const value = this.input(field);\n if (typeof value === 'string') {\n (this.all() as Record<string, unknown>)[field] = value.toUpperCase();\n }\n }\n },\n },\n};\n"]}
|