ngx-api-forms 1.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/LICENSE +21 -0
- package/README.md +657 -0
- package/analog/index.d.ts +76 -0
- package/django/index.d.ts +56 -0
- package/express-validator/index.d.ts +60 -0
- package/fesm2022/ngx-api-forms-analog.mjs +195 -0
- package/fesm2022/ngx-api-forms-analog.mjs.map +1 -0
- package/fesm2022/ngx-api-forms-django.mjs +173 -0
- package/fesm2022/ngx-api-forms-django.mjs.map +1 -0
- package/fesm2022/ngx-api-forms-express-validator.mjs +202 -0
- package/fesm2022/ngx-api-forms-express-validator.mjs.map +1 -0
- package/fesm2022/ngx-api-forms-laravel.mjs +167 -0
- package/fesm2022/ngx-api-forms-laravel.mjs.map +1 -0
- package/fesm2022/ngx-api-forms-zod.mjs +226 -0
- package/fesm2022/ngx-api-forms-zod.mjs.map +1 -0
- package/fesm2022/ngx-api-forms.mjs +890 -0
- package/fesm2022/ngx-api-forms.mjs.map +1 -0
- package/index.d.ts +621 -0
- package/laravel/index.d.ts +49 -0
- package/package.json +85 -0
- package/schematics/collection.json +10 -0
- package/schematics/ng-add/index.js +300 -0
- package/schematics/ng-add/index.spec.js +119 -0
- package/schematics/ng-add/schema.json +34 -0
- package/zod/index.d.ts +58 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngx-api-forms.mjs","sources":["../../../projects/ngx-api-forms/src/lib/models/api-forms.models.ts","../../../projects/ngx-api-forms/src/lib/presets/class-validator.preset.ts","../../../projects/ngx-api-forms/src/lib/form-bridge/form-bridge.ts","../../../projects/ngx-api-forms/src/lib/directives/form-error.directive.ts","../../../projects/ngx-api-forms/src/lib/utils/form-utils.ts","../../../projects/ngx-api-forms/src/lib/interceptor/api-error.interceptor.ts","../../../projects/ngx-api-forms/src/public-api.ts","../../../projects/ngx-api-forms/src/ngx-api-forms.ts"],"sourcesContent":["/**\n * ngx-api-forms - Models & Interfaces\n *\n * Core types for bridging API validation errors to Angular Reactive Forms.\n */\n\nimport { FormGroup } from '@angular/forms';\n\n// ---------------------------------------------------------------------------\n// API Error Structures\n// ---------------------------------------------------------------------------\n\n/**\n * A single field-level validation error returned by the API.\n */\nexport interface ApiFieldError {\n /** The form control name / field property name */\n field: string;\n /** The validation constraint key (e.g. 'required', 'minLength', 'isEmail') */\n constraint: string;\n /** The human-readable error message */\n message: string;\n}\n\n/**\n * Raw error shape from class-validator / NestJS (ValidationPipe).\n * This is the standard shape when `exceptionFactory` is not customized.\n */\nexport interface ClassValidatorError {\n property: string;\n constraints?: Record<string, string>;\n children?: ClassValidatorError[];\n}\n\n/**\n * Raw error shape from Laravel validation.\n * Laravel returns `{ errors: { field: ['message1', 'message2'] } }`.\n */\nexport type LaravelValidationErrors = Record<string, string[]>;\n\n/**\n * Raw error shape from Django REST Framework.\n * DRF returns `{ field: ['message1', 'message2'] }`.\n */\nexport type DjangoValidationErrors = Record<string, string[]>;\n\n/**\n * Raw error shape from Zod (.flatten()).\n * Zod returns `{ fieldErrors: { field: ['message1'] } }`.\n */\nexport interface ZodFlatError {\n formErrors: string[];\n fieldErrors: Record<string, string[]>;\n}\n\n// ---------------------------------------------------------------------------\n// Global (Non-Field) Errors\n// ---------------------------------------------------------------------------\n\n/**\n * Sentinel field name used by presets to tag errors that are not bound to a\n * specific form control (e.g. Django `non_field_errors`, Zod `formErrors`).\n *\n * FormBridge also routes any ApiFieldError whose field does not match a control\n * to `globalErrorsSignal`, so custom presets do not need to use this constant -\n * unmatched fields are captured automatically.\n */\nexport const GLOBAL_ERROR_FIELD = '__global__';\n\n/**\n * An error that does not belong to any specific form control.\n *\n * Sources:\n * - Django `non_field_errors` / `detail`\n * - Zod `formErrors`\n * - Any API error whose field name does not match a control in the form\n */\nexport interface GlobalError {\n /** The human-readable error message */\n message: string;\n /** The constraint key (e.g. 'serverError') */\n constraint: string;\n /** The original field name from the API response, if any */\n originalField?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Error Preset\n// ---------------------------------------------------------------------------\n\n/**\n * An ErrorPreset knows how to parse a specific API error shape\n * into a normalized array of `ApiFieldError`.\n *\n * This is the extension point for supporting any backend.\n */\nexport interface ErrorPreset {\n /** Unique name for identification (e.g. 'class-validator', 'laravel') */\n readonly name: string;\n\n /**\n * Parse the raw API error body into normalized field errors.\n * Should return an empty array if the format is not recognized.\n */\n parse(error: unknown): ApiFieldError[];\n\n /**\n * Optional constraint map shipped with this preset.\n * When provided, FormBridge merges it into its constraint resolution table\n * automatically - no need to pass a `constraintMap` in the config.\n */\n readonly constraintMap?: ConstraintMap;\n}\n\n// ---------------------------------------------------------------------------\n// Error Mapping\n// ---------------------------------------------------------------------------\n\n/**\n * Maps a constraint key to an Angular validation error key.\n * For example: `{ isEmail: 'email', minLength: 'minlength' }`\n */\nexport type ConstraintMap = Record<string, string>;\n\n/**\n * Configuration for i18n error message resolution.\n */\nexport interface I18nConfig {\n /**\n * Prefix for i18n translation keys.\n * Example: 'forms.errors' → key becomes 'forms.errors.email.required'\n */\n prefix?: string;\n\n /**\n * Custom resolver function for translating error keys.\n * If provided, this is called instead of using a prefix.\n *\n * @param field - The form field name\n * @param constraint - The constraint key\n * @param message - The original API message\n * @returns The translated message, or null to use the original\n */\n resolver?: (field: string, constraint: string, message: string) => string | null;\n}\n\n// ---------------------------------------------------------------------------\n// FormBridge Configuration\n// ---------------------------------------------------------------------------\n\n/**\n * Configuration options for creating a FormBridge instance.\n */\nexport interface FormBridgeConfig {\n /**\n * The error preset to use for parsing API errors.\n * Can be a single preset or an array (tried in order).\n */\n preset?: ErrorPreset | ErrorPreset[];\n\n /**\n * Custom constraint-to-Angular-error mapping.\n * Overrides the defaults from the preset.\n * Example: `{ isEmail: 'email', isNotEmpty: 'required' }`\n */\n constraintMap?: ConstraintMap;\n\n /**\n * i18n configuration for error messages.\n */\n i18n?: I18nConfig;\n\n /**\n * When true, unmapped API errors are set as `{ generic: message }` on the control.\n * When false (default), unmapped errors are ignored.\n */\n catchAll?: boolean;\n\n /**\n * When true, existing validation errors on the form are preserved\n * when applying API errors (merged). When false (default), API errors\n * replace existing errors on affected controls.\n */\n mergeErrors?: boolean;\n\n /**\n * When true, logs warnings to the console when:\n * - No preset produces results for a given error payload.\n * - A parsed error field does not match any form control.\n *\n * Useful during development. Should be disabled in production.\n */\n debug?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// FormBridge State\n// ---------------------------------------------------------------------------\n\n/**\n * Represents a resolved error on a specific form field.\n */\nexport interface ResolvedFieldError {\n /** The form control name */\n field: string;\n /** The Angular validation error key (e.g. 'required', 'email') */\n errorKey: string;\n /** The error message */\n message: string;\n}\n\n/**\n * Return type for `getFirstError()`.\n */\nexport interface FirstError {\n field: string;\n errorKey: string;\n message: string;\n}\n\n/**\n * Options for `enableForm()`.\n */\nexport interface EnableFormOptions {\n /** Control names to exclude from enabling */\n except?: string[];\n}\n\n/**\n * Options for `disableForm()`.\n */\nexport interface DisableFormOptions {\n /** Control names to exclude from disabling */\n except?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Utility Types\n// ---------------------------------------------------------------------------\n\n/**\n * Extract control names from a typed FormGroup.\n */\nexport type FormControlNames<T extends FormGroup> = T extends FormGroup<infer C>\n ? Extract<keyof C, string>\n : string;\n\n/**\n * Signature for a custom error handler that can intercept\n * errors before they are applied to the form.\n */\nexport type ErrorInterceptor = (\n errors: ApiFieldError[],\n form: FormGroup\n) => ApiFieldError[];\n","/**\n * class-validator / NestJS error preset.\n *\n * Parses the standard ValidationPipe error format:\n * ```json\n * {\n * \"statusCode\": 400,\n * \"message\": [\n * { \"property\": \"email\", \"constraints\": { \"isEmail\": \"email must be an email\" } }\n * ],\n * \"error\": \"Bad Request\"\n * }\n * ```\n *\n * Also handles flat string messages from NestJS:\n * ```json\n * { \"statusCode\": 400, \"message\": \"email is already used\" }\n * ```\n */\nimport { ApiFieldError, ClassValidatorError, ErrorPreset } from '../models/api-forms.models';\n\nfunction flattenErrors(\n errors: ClassValidatorError[],\n parentPath: string = ''\n): ApiFieldError[] {\n const result: ApiFieldError[] = [];\n\n for (const error of errors) {\n const path = parentPath ? `${parentPath}.${error.property}` : error.property;\n\n if (error.constraints) {\n for (const [constraint, message] of Object.entries(error.constraints)) {\n result.push({ field: path, constraint, message });\n }\n }\n\n // Recursively handle nested validation (e.g. nested DTOs)\n if (error.children && error.children.length > 0) {\n result.push(...flattenErrors(error.children, path));\n }\n }\n\n return result;\n}\n\nfunction parseStringMessage(message: string): ApiFieldError[] {\n // Attempt to extract field name and constraint from common class-validator messages\n const patterns: Array<{ regex: RegExp; constraint: string }> = [\n { regex: /^(\\w+) is required$/, constraint: 'required' },\n { regex: /^(\\w+) must be shorter/, constraint: 'maxLength' },\n { regex: /^(\\w+) must be longer/, constraint: 'minLength' },\n { regex: /^(\\w+) must not be less/, constraint: 'min' },\n { regex: /^(\\w+) must not be more/, constraint: 'max' },\n { regex: /^(\\w+) must be an? email/, constraint: 'isEmail' },\n { regex: /^(\\w+) must be an? valid phone/, constraint: 'isPhoneNumber' },\n { regex: /^(\\w+) must be one of the following/, constraint: 'isEnum' },\n { regex: /^(\\w+) must be an? Date/, constraint: 'isDate' },\n { regex: /^(\\w+) must be an? IBAN/, constraint: 'isIBAN' },\n { regex: /^(\\w+) must be an? EAN/, constraint: 'isEAN' },\n { regex: /^(\\w+) must be an? URL/, constraint: 'isUrl' },\n { regex: /^(\\w+) must be an? valid url/i, constraint: 'isUrl' },\n { regex: /^(\\w+) is not valid/i, constraint: 'invalid' },\n { regex: /^(\\w+) is already taken/i, constraint: 'unique' },\n { regex: /^(\\w+) is already used/i, constraint: 'unique' },\n { regex: /^(\\w+) must be a valid decimal/i, constraint: 'isDecimal' },\n ];\n\n for (const { regex, constraint } of patterns) {\n const match = message.match(regex);\n if (match) {\n const field = match[1]\n ? match[1].charAt(0).toLowerCase() + match[1].slice(1)\n : 'unknown';\n return [{ field, constraint, message }];\n }\n }\n\n // Specific messages without a field name captured by regex\n if (/^file is required/i.test(message)) {\n return [{ field: 'file', constraint: 'required', message }];\n }\n\n return [];\n}\n\n/**\n * Creates a class-validator / NestJS error preset.\n *\n * @param options.noInference - When true, skips constraint guessing for string messages.\n * Structured `constraints` objects (e.g. `{ isEmail: 'message' }`) are always used as-is.\n * Only affects the fallback string message parser.\n *\n * @example\n * ```typescript\n * import { classValidatorPreset } from 'ngx-api-forms';\n *\n * const bridge = createFormBridge(form, { preset: classValidatorPreset() });\n *\n * // No inference on string messages\n * const bridge = createFormBridge(form, { preset: classValidatorPreset({ noInference: true }) });\n * ```\n */\nexport function classValidatorPreset(options?: { noInference?: boolean }): ErrorPreset {\n const skipInference = options?.noInference ?? false;\n return {\n name: 'class-validator',\n constraintMap: CLASS_VALIDATOR_CONSTRAINT_MAP,\n parse(error: unknown): ApiFieldError[] {\n if (!error || typeof error !== 'object') return [];\n\n const err = error as Record<string, unknown>;\n\n // Standard NestJS ValidationPipe format: { message: ClassValidatorError[] }\n if (Array.isArray(err['message'])) {\n const messages = err['message'];\n\n // Check if it's an array of ClassValidatorError objects\n if (messages.length > 0 && typeof messages[0] === 'object' && 'property' in messages[0]) {\n return flattenErrors(messages as ClassValidatorError[]);\n }\n\n // It might be an array of strings (simple messages)\n if (messages.length > 0 && typeof messages[0] === 'string') {\n if (skipInference) {\n return (messages as string[]).map(msg => ({ field: 'unknown', constraint: 'serverError', message: msg }));\n }\n const results: ApiFieldError[] = [];\n for (const msg of messages as string[]) {\n results.push(...parseStringMessage(msg));\n }\n return results;\n }\n }\n\n // Single string message: { message: \"email is required\" }\n if (typeof err['message'] === 'string') {\n if (skipInference) {\n return [{ field: 'unknown', constraint: 'serverError', message: err['message'] as string }];\n }\n return parseStringMessage(err['message'] as string);\n }\n\n // Direct array (no wrapper): [{ property: 'email', constraints: {...} }]\n if (Array.isArray(error)) {\n const items = error as unknown[];\n if (items.length > 0 && typeof items[0] === 'object' && items[0] !== null && 'property' in items[0]) {\n return flattenErrors(items as ClassValidatorError[]);\n }\n }\n\n return [];\n },\n };\n}\n\n/**\n * Default constraint map for class-validator.\n * Maps class-validator constraint names to Angular form error keys.\n */\nexport const CLASS_VALIDATOR_CONSTRAINT_MAP: Record<string, string> = {\n isNotEmpty: 'required',\n isEmail: 'email',\n minLength: 'minlength',\n maxLength: 'maxlength',\n min: 'min',\n max: 'max',\n isPhoneNumber: 'phone',\n isEnum: 'enum',\n isDate: 'date',\n isDateString: 'date',\n isIBAN: 'iban',\n isEAN: 'ean',\n isUrl: 'url',\n isURL: 'url',\n isDecimal: 'decimal',\n isNumber: 'number',\n isInt: 'integer',\n isBoolean: 'boolean',\n isString: 'string',\n isArray: 'array',\n arrayMinSize: 'minlength',\n arrayMaxSize: 'maxlength',\n matches: 'pattern',\n isStrongPassword: 'password',\n unique: 'unique',\n invalid: 'invalid',\n required: 'required',\n serverError: 'serverError',\n};\n","/**\n * FormBridge - The core class of ngx-api-forms.\n *\n * Bridges API validation errors to Angular Reactive Forms with:\n * - Automatic error parsing via presets (class-validator, Laravel, Django, Zod)\n * - i18n-friendly error messages\n * - Angular Signals support\n * - SSR-safe operations\n */\nimport { signal, computed, Signal, WritableSignal } from '@angular/core';\nimport { FormGroup, FormArray, ValidationErrors, AbstractControl } from '@angular/forms';\n\nimport {\n ApiFieldError,\n ConstraintMap,\n ErrorInterceptor,\n ErrorPreset,\n FirstError,\n FormBridgeConfig,\n GlobalError,\n GLOBAL_ERROR_FIELD,\n I18nConfig,\n ResolvedFieldError,\n} from '../models/api-forms.models';\nimport { CLASS_VALIDATOR_CONSTRAINT_MAP, classValidatorPreset } from '../presets/class-validator.preset';\n\n\n/**\n * FormBridge wraps an Angular FormGroup and provides a clean API\n * for bridging API validation errors and managing form state.\n *\n * @example\n * ```typescript\n * const bridge = new FormBridge(myForm, {\n * preset: classValidatorPreset(),\n * });\n *\n * // Apply API errors\n * bridge.applyApiErrors(err.error);\n *\n * // Use signals in templates\n * readonly errors = bridge.errorsSignal;\n * readonly firstError = bridge.firstErrorSignal;\n * ```\n */\nexport class FormBridge<T extends FormGroup = FormGroup> {\n private readonly _form: T;\n private readonly _presets: ErrorPreset[];\n private readonly _constraintMap: ConstraintMap;\n private readonly _i18n: I18nConfig | undefined;\n private readonly _catchAll: boolean;\n private readonly _mergeErrors: boolean;\n private readonly _debug: boolean;\n private _interceptors: ErrorInterceptor[] = [];\n\n /** Signal containing the last set of resolved API errors */\n private readonly _apiErrors: WritableSignal<ResolvedFieldError[]> = signal([]);\n\n /** Signal containing global (non-field) errors */\n private readonly _globalErrors: WritableSignal<GlobalError[]> = signal([]);\n\n /** Tracks which error keys were set by the API on each control */\n private _apiErrorKeys = new Map<AbstractControl, Set<string>>();\n\n // ---- Public Signals ----\n\n /** Reactive signal of all current API errors applied to the form */\n readonly errorsSignal: Signal<ResolvedFieldError[]> = this._apiErrors.asReadonly();\n\n /**\n * Reactive signal of global (non-field) errors.\n *\n * Contains errors from:\n * - Django `non_field_errors` / `detail`\n * - Zod `formErrors`\n * - Any API error whose field does not match a form control\n */\n readonly globalErrorsSignal: Signal<GlobalError[]> = this._globalErrors.asReadonly();\n\n /** Reactive signal of the first error (or null) */\n readonly firstErrorSignal: Signal<FirstError | null> = computed(() => {\n const errors = this._apiErrors();\n return errors.length > 0 ? errors[0] : null;\n });\n\n /** Whether any API errors are currently applied */\n readonly hasErrorsSignal: Signal<boolean> = computed(() =>\n this._apiErrors().length > 0 || this._globalErrors().length > 0,\n );\n\n constructor(form: T, config?: FormBridgeConfig) {\n this._form = form;\n this._catchAll = config?.catchAll ?? false;\n this._mergeErrors = config?.mergeErrors ?? false;\n this._debug = config?.debug ?? false;\n this._i18n = config?.i18n;\n\n // Resolve presets\n if (config?.preset) {\n this._presets = Array.isArray(config.preset) ? config.preset : [config.preset];\n } else {\n this._presets = [classValidatorPreset()];\n }\n\n // Build constraint map: preset defaults + custom overrides\n const presetDefaults = this._resolvePresetConstraintMap(this._presets);\n this._constraintMap = {\n ...presetDefaults,\n ...(config?.constraintMap ?? {}),\n };\n }\n\n // ---- Public API - Error Management ----\n\n /**\n * Parse and apply API validation errors to the form.\n *\n * Tries each configured preset in order until one returns results.\n * Errors are mapped to Angular form control errors.\n *\n * @param apiError - The raw error body from the API (e.g. `err.error`)\n * @returns The array of resolved field errors that were applied\n */\n applyApiErrors(apiError: unknown): ResolvedFieldError[] {\n let fieldErrors: ApiFieldError[] = [];\n\n // Try each preset until one returns results\n for (const preset of this._presets) {\n fieldErrors = preset.parse(apiError);\n if (fieldErrors.length > 0) break;\n }\n\n if (this._debug && fieldErrors.length === 0) {\n console.warn(\n '[ngx-api-forms] No preset produced results for the given error payload.',\n 'Presets tried:', this._presets.map(p => p.name).join(', '),\n 'Payload:', apiError,\n );\n }\n\n // Run interceptors\n for (const interceptor of this._interceptors) {\n fieldErrors = interceptor(fieldErrors, this._form);\n }\n\n // Map and apply to form\n const resolved = this._applyErrors(fieldErrors);\n this._apiErrors.set(resolved);\n\n return resolved;\n }\n\n /**\n * Clear only the errors that were set by `applyApiErrors()`.\n * Client-side validation errors (e.g. `Validators.required`) are preserved.\n */\n clearApiErrors(): void {\n for (const [control, keys] of this._apiErrorKeys) {\n if (!control.errors) continue;\n const remaining = { ...control.errors };\n for (const key of keys) {\n delete remaining[key];\n }\n control.setErrors(Object.keys(remaining).length > 0 ? remaining : null);\n control.updateValueAndValidity();\n }\n this._apiErrorKeys.clear();\n this._form.updateValueAndValidity({ onlySelf: false, emitEvent: true });\n this._apiErrors.set([]);\n this._globalErrors.set([]);\n }\n\n /**\n * Get the first error across all form controls.\n */\n getFirstError(): FirstError | null {\n // Check API errors first\n const apiErrors = this._apiErrors();\n if (apiErrors.length > 0) {\n return apiErrors[0];\n }\n\n // Fall back to client-side validation errors\n for (const key of Object.keys(this._form.controls)) {\n const control = this._form.controls[key];\n if (control?.errors) {\n const errorKeys = Object.keys(control.errors);\n if (errorKeys.length > 0) {\n const errorKey = errorKeys[0];\n const errorValue = control.errors[errorKey];\n return {\n field: key,\n errorKey,\n message: typeof errorValue === 'string' ? errorValue : errorKey,\n };\n }\n }\n }\n\n return null;\n }\n\n /**\n * Get all errors for a specific field.\n */\n getFieldErrors(fieldName: string): ValidationErrors | null {\n return this._form.controls[fieldName]?.errors ?? null;\n }\n\n /**\n * Register an error interceptor that can modify or filter errors\n * before they are applied to the form.\n * Returns a dispose function to remove the interceptor.\n */\n addInterceptor(interceptor: ErrorInterceptor): () => void {\n this._interceptors.push(interceptor);\n return () => {\n this._interceptors = this._interceptors.filter(i => i !== interceptor);\n };\n }\n\n // ---- Public API - Utilities ----\n\n /**\n * Access the underlying FormGroup.\n */\n get form(): T {\n return this._form;\n }\n\n // ---- Private Methods ----\n\n private _resolvePresetConstraintMap(presets: ErrorPreset[]): ConstraintMap {\n const merged: ConstraintMap = {};\n for (const preset of presets) {\n if (preset.constraintMap) Object.assign(merged, preset.constraintMap);\n }\n // If no preset provided a constraint map, fall back to class-validator\n if (Object.keys(merged).length === 0) {\n Object.assign(merged, CLASS_VALIDATOR_CONSTRAINT_MAP);\n }\n return merged;\n }\n\n private _applyErrors(fieldErrors: ApiFieldError[]): ResolvedFieldError[] {\n const resolved: ResolvedFieldError[] = [];\n const globalErrors: GlobalError[] = [];\n\n // Accumulate errors per control to avoid overwrite within a single applyApiErrors call\n const pendingErrors = new Map<AbstractControl, ValidationErrors>();\n\n for (const fieldError of fieldErrors) {\n // Global errors (explicit sentinel or unmatched field)\n if (fieldError.field === GLOBAL_ERROR_FIELD) {\n globalErrors.push({\n message: fieldError.message,\n constraint: fieldError.constraint,\n });\n continue;\n }\n\n let control: AbstractControl | null = this._form.controls[fieldError.field] ?? null;\n if (!control) {\n // Try nested path (e.g. 'address.city' or 'items.0.name')\n control = this._resolveNestedControl(fieldError.field);\n if (!control) {\n // Route unmatched field errors to global errors\n globalErrors.push({\n message: fieldError.message,\n constraint: fieldError.constraint,\n originalField: fieldError.field,\n });\n if (this._debug) {\n console.warn(\n `[ngx-api-forms] Field \"${fieldError.field}\" does not match any form control - routed to globalErrorsSignal.`,\n 'Available controls:', Object.keys(this._form.controls).join(', '),\n );\n }\n continue;\n }\n }\n\n const errorKey = this._resolveErrorKey(fieldError.constraint);\n const message = this._resolveMessage(fieldError);\n\n if (!errorKey && !this._catchAll) continue;\n\n const finalErrorKey = errorKey || 'generic';\n\n // Deduplicate: if the same key already exists on this control, suffix it\n const existing = pendingErrors.get(control) ?? (this._mergeErrors ? (control.errors ?? {}) : {});\n let uniqueKey = finalErrorKey;\n if (existing[uniqueKey] !== undefined) {\n let idx = 1;\n while (existing[`${finalErrorKey}_${idx}`] !== undefined) idx++;\n uniqueKey = `${finalErrorKey}_${idx}`;\n }\n pendingErrors.set(control, { ...existing, [uniqueKey]: message });\n\n // Track this key as API-set\n if (!this._apiErrorKeys.has(control)) {\n this._apiErrorKeys.set(control, new Set());\n }\n this._apiErrorKeys.get(control)!.add(uniqueKey);\n\n resolved.push({ field: fieldError.field, errorKey: uniqueKey, message });\n }\n\n // Apply accumulated errors once per control\n for (const [control, errors] of pendingErrors) {\n control.markAsTouched();\n control.setErrors(errors);\n }\n\n // Publish global errors\n this._globalErrors.set(globalErrors);\n\n return resolved;\n }\n\n private _resolveNestedControl(path: string): AbstractControl | null {\n const parts = path.split('.');\n let current: AbstractControl = this._form;\n\n for (const part of parts) {\n if (current instanceof FormGroup) {\n const child = current.controls[part];\n if (!child) return null;\n current = child;\n } else if (current instanceof FormArray) {\n const index = parseInt(part, 10);\n if (isNaN(index) || index < 0 || index >= current.length) return null;\n current = current.at(index);\n } else {\n return null;\n }\n }\n\n return current;\n }\n\n private _resolveErrorKey(constraint: string): string {\n // If constraint is in the map, use the mapped value.\n // Otherwise, use the constraint as-is (pass-through).\n // This returns '' only when constraint is empty.\n if (this._constraintMap[constraint] !== undefined) {\n return this._constraintMap[constraint];\n }\n return constraint;\n }\n\n private _resolveMessage(error: ApiFieldError): string {\n if (this._i18n?.resolver) {\n const resolved = this._i18n.resolver(error.field, error.constraint, error.message);\n if (resolved !== null) return resolved;\n }\n\n if (this._i18n?.prefix) {\n // Return the i18n key (to be resolved by the consumer's i18n system)\n return `${this._i18n.prefix}.${error.field}.${error.constraint}`;\n }\n\n return error.message;\n }\n}\n\n/**\n * Factory function to create a FormBridge instance.\n *\n * @example\n * ```typescript\n * import { createFormBridge, classValidatorPreset } from 'ngx-api-forms';\n *\n * const bridge = createFormBridge(this.myForm, {\n * preset: classValidatorPreset(),\n * i18n: { prefix: 'validation' },\n * });\n *\n * // In your API call error handler:\n * bridge.applyApiErrors(err.error);\n * ```\n */\nexport function createFormBridge<T extends FormGroup>(form: T, config: FormBridgeConfig): FormBridge<T>;\nexport function createFormBridge<T extends FormGroup>(form: T): FormBridge<T>;\nexport function createFormBridge<T extends FormGroup>(form: T, config?: FormBridgeConfig): FormBridge<T> {\n return new FormBridge(form, config);\n}\n\n/**\n * Alias for `createFormBridge`.\n *\n * Both functions are identical since FormBridge no longer holds internal\n * subscriptions. Kept for API compatibility with existing code.\n *\n * @example\n * ```typescript\n * @Component({ ... })\n * export class MyComponent {\n * private form = inject(FormBuilder).group({ email: [''] });\n * private bridge = provideFormBridge(this.form, {\n * preset: classValidatorPreset(),\n * });\n *\n * onSubmit() {\n * this.http.post('/api', this.form.value).subscribe({\n * error: (err) => this.bridge.applyApiErrors(err.error),\n * });\n * }\n * }\n * ```\n */\nexport function provideFormBridge<T extends FormGroup>(form: T, config: FormBridgeConfig): FormBridge<T>;\nexport function provideFormBridge<T extends FormGroup>(form: T): FormBridge<T>;\nexport function provideFormBridge<T extends FormGroup>(form: T, config?: FormBridgeConfig): FormBridge<T> {\n return new FormBridge(form, config);\n}\n","/**\n * NgxFormError directive.\n *\n * Automatically displays the error message for a form control.\n * Works with both client-side validators and API errors set by FormBridge.\n *\n * @example\n * ```html\n * <input formControlName=\"email\" />\n * <span ngxFormError=\"email\" [form]=\"myForm\"></span>\n * <!-- Displays: \"email must be a valid email\" -->\n *\n * <!-- With custom error map -->\n * <span ngxFormError=\"email\"\n * [form]=\"myForm\"\n * [errorMessages]=\"{ required: 'Email is required', email: 'Invalid email' }\">\n * </span>\n * ```\n */\nimport {\n Directive,\n DestroyRef,\n ElementRef,\n Input,\n OnChanges,\n OnInit,\n Renderer2,\n SimpleChanges,\n inject,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { FormGroup, AbstractControl } from '@angular/forms';\nimport { Subject, merge, takeUntil } from 'rxjs';\n\n@Directive({\n selector: '[ngxFormError]',\n standalone: true,\n})\nexport class NgxFormErrorDirective implements OnInit, OnChanges {\n private readonly el = inject(ElementRef);\n private readonly renderer = inject(Renderer2);\n private readonly destroyRef = inject(DestroyRef);\n private readonly resubscribe$ = new Subject<void>();\n\n /** The form control name to observe */\n @Input('ngxFormError') controlName!: string;\n\n /** The parent FormGroup */\n @Input() form!: FormGroup;\n\n /**\n * Optional map of error keys to display messages.\n * If not provided, the raw error value is used (which is the API message\n * when set by FormBridge).\n */\n @Input() errorMessages?: Record<string, string>;\n\n /**\n * CSS class applied to the host element when an error is displayed.\n * Default: 'ngx-form-error-visible'\n */\n @Input() errorClass = 'ngx-form-error-visible';\n\n /**\n * Whether to show errors only when the control is touched.\n * Default: true\n */\n @Input() showOnTouched = true;\n\n ngOnInit(): void {\n this._subscribe();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if ((changes['form'] || changes['controlName']) && !changes['form']?.firstChange) {\n this._subscribe();\n }\n }\n\n private _subscribe(): void {\n // Signal existing subscription to complete\n this.resubscribe$.next();\n\n const control = this.form?.get(this.controlName);\n if (!control) {\n this._hide();\n return;\n }\n\n merge(control.statusChanges, control.valueChanges).pipe(\n takeUntil(this.resubscribe$),\n takeUntilDestroyed(this.destroyRef),\n ).subscribe(() => {\n this._updateDisplay(control);\n });\n\n this._updateDisplay(control);\n }\n\n private _updateDisplay(control: AbstractControl): void {\n if (!control.errors || (this.showOnTouched && !control.touched && !control.dirty)) {\n this._hide();\n return;\n }\n\n const errorKeys = Object.keys(control.errors);\n if (errorKeys.length === 0) {\n this._hide();\n return;\n }\n\n const firstKey = errorKeys[0];\n const rawValue = control.errors[firstKey];\n let message: string;\n\n // Priority: custom errorMessages map > raw string value > error key\n if (this.errorMessages?.[firstKey]) {\n message = this.errorMessages[firstKey];\n } else if (typeof rawValue === 'string') {\n message = rawValue;\n } else {\n message = firstKey;\n }\n\n this._show(message);\n }\n\n private _show(message: string): void {\n const el = this.el.nativeElement;\n this.renderer.setProperty(el, 'textContent', message);\n this.renderer.addClass(el, this.errorClass);\n this.renderer.setStyle(el, 'display', '');\n }\n\n private _hide(): void {\n const el = this.el.nativeElement;\n this.renderer.setProperty(el, 'textContent', '');\n this.renderer.removeClass(el, this.errorClass);\n this.renderer.setStyle(el, 'display', 'none');\n }\n}\n","/**\n * Standalone utility functions for common form operations.\n * These are tree-shakeable and don't require DI.\n */\nimport { FormGroup } from '@angular/forms';\nimport { Observable, tap, catchError } from 'rxjs';\nimport { ApiFieldError, ErrorPreset, EnableFormOptions, DisableFormOptions } from '../models/api-forms.models';\nimport { classValidatorPreset } from '../presets/class-validator.preset';\n\n/**\n * Parse raw API error body into normalized field errors without touching any form.\n * Tries each preset in order until one returns results.\n *\n * Use this when you only need the parsing logic (e.g. in an HttpInterceptor,\n * a store effect, or any context where you don't have a FormBridge).\n *\n * @param apiError - The raw error body from the API (e.g. `err.error`)\n * @param preset - One or more presets to try. Defaults to class-validator.\n * @param options - Optional settings. `debug: true` logs a warning when no preset matches.\n * @returns Normalized array of field errors\n *\n * @example\n * ```typescript\n * import { parseApiErrors } from 'ngx-api-forms';\n * import { laravelPreset } from 'ngx-api-forms/laravel';\n *\n * const errors = parseApiErrors(err.error, laravelPreset());\n * // [{ field: 'email', constraint: 'required', message: 'The email field is required.' }]\n * ```\n */\nexport function parseApiErrors(\n apiError: unknown,\n preset?: ErrorPreset | ErrorPreset[],\n options?: { debug?: boolean },\n): ApiFieldError[] {\n const presets = preset\n ? (Array.isArray(preset) ? preset : [preset])\n : [classValidatorPreset()];\n\n for (const p of presets) {\n const result = p.parse(apiError);\n if (result.length > 0) return result;\n }\n\n if (options?.debug) {\n console.warn(\n '[ngx-api-forms] parseApiErrors: no preset produced results.',\n 'Presets tried:', presets.map(p => p.name).join(', '),\n 'Payload:', apiError,\n );\n }\n\n return [];\n}\n\n/**\n * Wrap an Observable with form submit lifecycle management.\n *\n * Standalone submit helper. Useful when you want disable/enable lifecycle\n * without a full FormBridge instance.\n *\n * - Disables the form before subscribing\n * - Re-enables the form on success or error\n * - Returns the original Observable (errors are re-thrown)\n *\n * @param form - The FormGroup to manage\n * @param source - The Observable to wrap (e.g. HttpClient call)\n * @param options.onError - Callback invoked with the error before re-throwing\n * @returns The wrapped Observable\n *\n * @example\n * ```typescript\n * import { wrapSubmit } from 'ngx-api-forms';\n *\n * wrapSubmit(this.form, this.http.post('/api', data), {\n * onError: (err) => this.bridge.applyApiErrors(err.error),\n * }).subscribe();\n * ```\n */\nexport function wrapSubmit<T>(\n form: FormGroup,\n source: Observable<T>,\n options?: { onError?: (err: unknown) => void },\n): Observable<T> {\n form.disable();\n return source.pipe(\n tap(() => form.enable()),\n catchError((err) => {\n form.enable();\n options?.onError?.(err);\n throw err;\n }),\n );\n}\n\n/**\n * Convert a plain object to FormData.\n * Handles Files, Blobs, Arrays, Dates, nested objects.\n */\nexport function toFormData(data: Record<string, unknown>): FormData {\n const formData = new FormData();\n\n for (const [key, value] of Object.entries(data)) {\n if (value === null || value === undefined) continue;\n\n if (value instanceof File || value instanceof Blob) {\n formData.append(key, value);\n continue;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item instanceof File || item instanceof Blob) {\n formData.append(key, item);\n } else if (typeof item === 'object' && item !== null) {\n formData.append(key, JSON.stringify(item));\n } else {\n formData.append(key, String(item));\n }\n }\n continue;\n }\n\n if (value instanceof Date) {\n formData.append(key, value.toISOString());\n continue;\n }\n\n if (typeof value === 'object') {\n formData.append(key, JSON.stringify(value));\n continue;\n }\n\n formData.append(key, String(value));\n }\n\n return formData;\n}\n\n/**\n * Enable all controls in a form, with optional exceptions.\n */\nexport function enableForm(form: FormGroup, options?: EnableFormOptions): void {\n for (const key of Object.keys(form.controls)) {\n if (options?.except?.includes(key)) continue;\n form.controls[key].enable();\n }\n form.updateValueAndValidity({ onlySelf: false, emitEvent: true });\n}\n\n/**\n * Disable all controls in a form, with optional exceptions.\n */\nexport function disableForm(form: FormGroup, options?: DisableFormOptions): void {\n for (const key of Object.keys(form.controls)) {\n if (options?.except?.includes(key)) continue;\n form.controls[key].disable();\n }\n}\n\n/**\n * Reset all errors on a form's controls (client-side and API).\n */\nexport function clearFormErrors(form: FormGroup): void {\n for (const key of Object.keys(form.controls)) {\n form.controls[key].setErrors(null);\n form.controls[key].updateValueAndValidity();\n }\n form.updateValueAndValidity({ onlySelf: false, emitEvent: true });\n}\n\n/**\n * Get a flat record of only the dirty (changed) fields.\n */\nexport function getDirtyValues(form: FormGroup): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(form.controls)) {\n if (form.controls[key].dirty) {\n result[key] = form.controls[key].value;\n }\n }\n return result;\n}\n\n/**\n * Check if any control in the form has a specific error key.\n */\nexport function hasError(form: FormGroup, errorKey: string): boolean {\n for (const key of Object.keys(form.controls)) {\n if (form.controls[key].hasError(errorKey)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Get the error message for a specific field and error key.\n * Returns the error value if it's a string, otherwise the error key.\n */\nexport function getErrorMessage(form: FormGroup, fieldName: string, errorKey?: string): string | null {\n const control = form.controls[fieldName];\n if (!control?.errors) return null;\n\n if (errorKey) {\n const value = control.errors[errorKey];\n return value ? (typeof value === 'string' ? value : errorKey) : null;\n }\n\n // Return first error\n const keys = Object.keys(control.errors);\n if (keys.length === 0) return null;\n\n const firstValue = control.errors[keys[0]];\n return typeof firstValue === 'string' ? firstValue : keys[0];\n}\n","/**\n * Angular HttpInterceptorFn that automatically applies API validation errors\n * to a FormBridge instance attached via HttpContext.\n *\n * Two usage patterns:\n * 1. Per-request: tag individual requests with `withFormBridge(bridge)` --\n * the interceptor catches 422/400 and calls `bridge.applyApiErrors()`.\n * 2. Global: provide a custom `onError` callback in the interceptor config\n * to centralize error handling (e.g. dispatch to a store or service).\n */\nimport {\n HttpContext,\n HttpContextToken,\n HttpErrorResponse,\n HttpInterceptorFn,\n} from '@angular/common/http';\nimport { catchError, throwError } from 'rxjs';\n\nimport { FormBridge } from '../form-bridge/form-bridge';\nimport { ApiFieldError, ErrorPreset, ResolvedFieldError } from '../models/api-forms.models';\nimport { classValidatorPreset } from '../presets/class-validator.preset';\nimport { parseApiErrors } from '../utils/form-utils';\n\n/**\n * HttpContext token that carries a FormBridge reference on a request.\n * Used by `withFormBridge()` to tag requests for automatic error handling.\n */\nexport const FORM_BRIDGE = new HttpContextToken<FormBridge | null>(() => null);\n\n/**\n * Configuration for `apiErrorInterceptor`.\n */\nexport interface ApiErrorInterceptorConfig {\n /**\n * Preset(s) used for standalone parsing when no FormBridge is attached\n * but `onError` is provided. Ignored when a FormBridge is attached\n * (the bridge uses its own presets).\n * Defaults to `classValidatorPreset()`.\n */\n preset?: ErrorPreset | ErrorPreset[];\n\n /**\n * HTTP status codes that trigger error handling.\n * Defaults to `[422, 400]`.\n */\n statusCodes?: number[];\n\n /**\n * Global callback invoked for every matching error response,\n * whether or not a FormBridge is attached.\n * Receives the parsed field errors and the raw HttpErrorResponse.\n * When a FormBridge is attached, receives ResolvedFieldError[];\n * otherwise receives ApiFieldError[] from standalone parsing.\n */\n onError?: (errors: (ApiFieldError | ResolvedFieldError)[], response: HttpErrorResponse) => void;\n}\n\n/**\n * Create an Angular functional HTTP interceptor that handles API validation errors.\n *\n * When a response matches one of the configured status codes (default: 422, 400):\n * - If the request was tagged with `withFormBridge(bridge)`, errors are automatically\n * applied to that bridge. Zero code needed in `subscribe()`.\n * - If an `onError` callback is provided, it is called with the parsed errors for\n * global handling (store, toast, logging, etc.).\n * - The error is always re-thrown so downstream `catchError` or `error` callbacks\n * still fire when needed.\n *\n * @example\n * ```typescript\n * // app.config.ts\n * import { provideHttpClient, withInterceptors } from '@angular/common/http';\n * import { apiErrorInterceptor } from 'ngx-api-forms';\n *\n * export const appConfig = {\n * providers: [\n * provideHttpClient(\n * withInterceptors([apiErrorInterceptor()])\n * ),\n * ],\n * };\n *\n * // component.ts -- zero error handling code\n * this.http.post('/api/save', data, withFormBridge(this.bridge)).subscribe({\n * next: () => this.router.navigate(['/done']),\n * });\n * ```\n */\nexport function apiErrorInterceptor(config?: ApiErrorInterceptorConfig): HttpInterceptorFn {\n const statusCodes = config?.statusCodes ?? [422, 400];\n const fallbackPreset = config?.preset ?? classValidatorPreset();\n\n return (req, next) => {\n return next(req).pipe(\n catchError((error: HttpErrorResponse) => {\n if (statusCodes.includes(error.status)) {\n const bridge = req.context.get(FORM_BRIDGE);\n\n if (bridge) {\n bridge.applyApiErrors(error.error);\n }\n\n if (config?.onError) {\n const parsed = bridge\n ? bridge.errorsSignal()\n : parseApiErrors(error.error, fallbackPreset);\n config.onError(parsed, error);\n }\n }\n\n return throwError(() => error);\n }),\n );\n };\n}\n\n/**\n * Attach a FormBridge to an HTTP request via HttpContext.\n *\n * When used with `apiErrorInterceptor`, the interceptor automatically calls\n * `bridge.applyApiErrors()` on 422/400 responses. No error handling needed\n * in `subscribe()`.\n *\n * @param bridge - The FormBridge instance to receive API errors\n * @returns An options object to spread into HttpClient methods\n *\n * @example\n * ```typescript\n * // Errors are applied automatically -- no subscribe error handler needed\n * this.http.post('/api/save', data, withFormBridge(this.bridge)).subscribe();\n *\n * // Works with all HttpClient methods\n * this.http.put('/api/users/1', data, withFormBridge(this.bridge)).subscribe();\n * ```\n */\nexport function withFormBridge(bridge: FormBridge): { context: HttpContext } {\n return {\n context: new HttpContext().set(FORM_BRIDGE, bridge),\n };\n}\n","/*\n * Public API Surface of ngx-api-forms\n */\n\n// Models and types\nexport * from './lib/models/api-forms.models';\n\n// Core\nexport { FormBridge, createFormBridge, provideFormBridge } from './lib/form-bridge/form-bridge';\n\n// Presets (default only - others available via secondary entry points)\nexport { classValidatorPreset, CLASS_VALIDATOR_CONSTRAINT_MAP } from './lib/presets/class-validator.preset';\n\n// Directives\nexport { NgxFormErrorDirective } from './lib/directives/form-error.directive';\n\n// Interceptor\nexport {\n apiErrorInterceptor,\n withFormBridge,\n FORM_BRIDGE,\n} from './lib/interceptor/api-error.interceptor';\nexport type { ApiErrorInterceptorConfig } from './lib/interceptor/api-error.interceptor';\n\n// Utility functions (tree-shakeable)\nexport {\n parseApiErrors,\n wrapSubmit,\n toFormData,\n enableForm,\n disableForm,\n clearFormErrors,\n getDirtyValues,\n hasError,\n getErrorMessage,\n} from './lib/utils/form-utils';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;AAAA;;;;AAIG;AAmDH;AACA;AACA;AAEA;;;;;;;AAOG;AACI,MAAM,kBAAkB,GAAG;;AC9ClC,SAAS,aAAa,CACpB,MAA6B,EAC7B,aAAqB,EAAE,EAAA;IAEvB,MAAM,MAAM,GAAoB,EAAE;AAElC,IAAA,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;AAC1B,QAAA,MAAM,IAAI,GAAG,UAAU,GAAG,GAAG,UAAU,CAAA,CAAA,EAAI,KAAK,CAAC,QAAQ,EAAE,GAAG,KAAK,CAAC,QAAQ;AAE5E,QAAA,IAAI,KAAK,CAAC,WAAW,EAAE;AACrB,YAAA,KAAK,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;AACrE,gBAAA,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;YACnD;QACF;;AAGA,QAAA,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;AAC/C,YAAA,MAAM,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrD;IACF;AAEA,IAAA,OAAO,MAAM;AACf;AAEA,SAAS,kBAAkB,CAAC,OAAe,EAAA;;AAEzC,IAAA,MAAM,QAAQ,GAAiD;AAC7D,QAAA,EAAE,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,UAAU,EAAE;AACxD,QAAA,EAAE,KAAK,EAAE,wBAAwB,EAAE,UAAU,EAAE,WAAW,EAAE;AAC5D,QAAA,EAAE,KAAK,EAAE,uBAAuB,EAAE,UAAU,EAAE,WAAW,EAAE;AAC3D,QAAA,EAAE,KAAK,EAAE,yBAAyB,EAAE,UAAU,EAAE,KAAK,EAAE;AACvD,QAAA,EAAE,KAAK,EAAE,yBAAyB,EAAE,UAAU,EAAE,KAAK,EAAE;AACvD,QAAA,EAAE,KAAK,EAAE,0BAA0B,EAAE,UAAU,EAAE,SAAS,EAAE;AAC5D,QAAA,EAAE,KAAK,EAAE,gCAAgC,EAAE,UAAU,EAAE,eAAe,EAAE;AACxE,QAAA,EAAE,KAAK,EAAE,qCAAqC,EAAE,UAAU,EAAE,QAAQ,EAAE;AACtE,QAAA,EAAE,KAAK,EAAE,yBAAyB,EAAE,UAAU,EAAE,QAAQ,EAAE;AAC1D,QAAA,EAAE,KAAK,EAAE,yBAAyB,EAAE,UAAU,EAAE,QAAQ,EAAE;AAC1D,QAAA,EAAE,KAAK,EAAE,wBAAwB,EAAE,UAAU,EAAE,OAAO,EAAE;AACxD,QAAA,EAAE,KAAK,EAAE,wBAAwB,EAAE,UAAU,EAAE,OAAO,EAAE;AACxD,QAAA,EAAE,KAAK,EAAE,+BAA+B,EAAE,UAAU,EAAE,OAAO,EAAE;AAC/D,QAAA,EAAE,KAAK,EAAE,sBAAsB,EAAE,UAAU,EAAE,SAAS,EAAE;AACxD,QAAA,EAAE,KAAK,EAAE,0BAA0B,EAAE,UAAU,EAAE,QAAQ,EAAE;AAC3D,QAAA,EAAE,KAAK,EAAE,yBAAyB,EAAE,UAAU,EAAE,QAAQ,EAAE;AAC1D,QAAA,EAAE,KAAK,EAAE,iCAAiC,EAAE,UAAU,EAAE,WAAW,EAAE;KACtE;IAED,KAAK,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,QAAQ,EAAE;QAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;QAClC,IAAI,KAAK,EAAE;AACT,YAAA,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC;kBACjB,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;kBACnD,SAAS;YACb,OAAO,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;QACzC;IACF;;AAGA,IAAA,IAAI,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;AACtC,QAAA,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;IAC7D;AAEA,IAAA,OAAO,EAAE;AACX;AAEA;;;;;;;;;;;;;;;;AAgBG;AACG,SAAU,oBAAoB,CAAC,OAAmC,EAAA;AACtE,IAAA,MAAM,aAAa,GAAG,OAAO,EAAE,WAAW,IAAI,KAAK;IACnD,OAAO;AACL,QAAA,IAAI,EAAE,iBAAiB;AACvB,QAAA,aAAa,EAAE,8BAA8B;AAC7C,QAAA,KAAK,CAAC,KAAc,EAAA;AAClB,YAAA,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;AAAE,gBAAA,OAAO,EAAE;YAElD,MAAM,GAAG,GAAG,KAAgC;;YAG5C,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE;AACjC,gBAAA,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC;;gBAG/B,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,UAAU,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE;AACvF,oBAAA,OAAO,aAAa,CAAC,QAAiC,CAAC;gBACzD;;AAGA,gBAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;oBAC1D,IAAI,aAAa,EAAE;wBACjB,OAAQ,QAAqB,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;oBAC3G;oBACA,MAAM,OAAO,GAAoB,EAAE;AACnC,oBAAA,KAAK,MAAM,GAAG,IAAI,QAAoB,EAAE;wBACtC,OAAO,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;oBAC1C;AACA,oBAAA,OAAO,OAAO;gBAChB;YACF;;YAGA,IAAI,OAAO,GAAG,CAAC,SAAS,CAAC,KAAK,QAAQ,EAAE;gBACtC,IAAI,aAAa,EAAE;AACjB,oBAAA,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,CAAC,SAAS,CAAW,EAAE,CAAC;gBAC7F;AACA,gBAAA,OAAO,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAW,CAAC;YACrD;;AAGA,YAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBACxB,MAAM,KAAK,GAAG,KAAkB;AAChC,gBAAA,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,UAAU,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE;AACnG,oBAAA,OAAO,aAAa,CAAC,KAA8B,CAAC;gBACtD;YACF;AAEA,YAAA,OAAO,EAAE;QACX,CAAC;KACF;AACH;AAEA;;;AAGG;AACI,MAAM,8BAA8B,GAA2B;AACpE,IAAA,UAAU,EAAE,UAAU;AACtB,IAAA,OAAO,EAAE,OAAO;AAChB,IAAA,SAAS,EAAE,WAAW;AACtB,IAAA,SAAS,EAAE,WAAW;AACtB,IAAA,GAAG,EAAE,KAAK;AACV,IAAA,GAAG,EAAE,KAAK;AACV,IAAA,aAAa,EAAE,OAAO;AACtB,IAAA,MAAM,EAAE,MAAM;AACd,IAAA,MAAM,EAAE,MAAM;AACd,IAAA,YAAY,EAAE,MAAM;AACpB,IAAA,MAAM,EAAE,MAAM;AACd,IAAA,KAAK,EAAE,KAAK;AACZ,IAAA,KAAK,EAAE,KAAK;AACZ,IAAA,KAAK,EAAE,KAAK;AACZ,IAAA,SAAS,EAAE,SAAS;AACpB,IAAA,QAAQ,EAAE,QAAQ;AAClB,IAAA,KAAK,EAAE,SAAS;AAChB,IAAA,SAAS,EAAE,SAAS;AACpB,IAAA,QAAQ,EAAE,QAAQ;AAClB,IAAA,OAAO,EAAE,OAAO;AAChB,IAAA,YAAY,EAAE,WAAW;AACzB,IAAA,YAAY,EAAE,WAAW;AACzB,IAAA,OAAO,EAAE,SAAS;AAClB,IAAA,gBAAgB,EAAE,UAAU;AAC5B,IAAA,MAAM,EAAE,QAAQ;AAChB,IAAA,OAAO,EAAE,SAAS;AAClB,IAAA,QAAQ,EAAE,UAAU;AACpB,IAAA,WAAW,EAAE,aAAa;;;AC3L5B;;;;;;;;AAQG;AAmBH;;;;;;;;;;;;;;;;;AAiBG;MACU,UAAU,CAAA;AACJ,IAAA,KAAK;AACL,IAAA,QAAQ;AACR,IAAA,cAAc;AACd,IAAA,KAAK;AACL,IAAA,SAAS;AACT,IAAA,YAAY;AACZ,IAAA,MAAM;IACf,aAAa,GAAuB,EAAE;;AAG7B,IAAA,UAAU,GAAyC,MAAM,CAAC,EAAE,sDAAC;;AAG7D,IAAA,aAAa,GAAkC,MAAM,CAAC,EAAE,yDAAC;;AAGlE,IAAA,aAAa,GAAG,IAAI,GAAG,EAAgC;;;AAKtD,IAAA,YAAY,GAAiC,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE;AAElF;;;;;;;AAOG;AACM,IAAA,kBAAkB,GAA0B,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE;;AAG3E,IAAA,gBAAgB,GAA8B,QAAQ,CAAC,MAAK;AACnE,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE;AAChC,QAAA,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI;AAC7C,IAAA,CAAC,4DAAC;;IAGO,eAAe,GAAoB,QAAQ,CAAC,MACnD,IAAI,CAAC,UAAU,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC,MAAM,GAAG,CAAC,EAAA,IAAA,SAAA,GAAA,CAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,CAAA,GAAA,EAAA,CAAA,CAChE;IAED,WAAA,CAAY,IAAO,EAAE,MAAyB,EAAA;AAC5C,QAAA,IAAI,CAAC,KAAK,GAAG,IAAI;QACjB,IAAI,CAAC,SAAS,GAAG,MAAM,EAAE,QAAQ,IAAI,KAAK;QAC1C,IAAI,CAAC,YAAY,GAAG,MAAM,EAAE,WAAW,IAAI,KAAK;QAChD,IAAI,CAAC,MAAM,GAAG,MAAM,EAAE,KAAK,IAAI,KAAK;AACpC,QAAA,IAAI,CAAC,KAAK,GAAG,MAAM,EAAE,IAAI;;AAGzB,QAAA,IAAI,MAAM,EAAE,MAAM,EAAE;YAClB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;QAChF;aAAO;AACL,YAAA,IAAI,CAAC,QAAQ,GAAG,CAAC,oBAAoB,EAAE,CAAC;QAC1C;;QAGA,MAAM,cAAc,GAAG,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,QAAQ,CAAC;QACtE,IAAI,CAAC,cAAc,GAAG;AACpB,YAAA,GAAG,cAAc;AACjB,YAAA,IAAI,MAAM,EAAE,aAAa,IAAI,EAAE,CAAC;SACjC;IACH;;AAIA;;;;;;;;AAQG;AACH,IAAA,cAAc,CAAC,QAAiB,EAAA;QAC9B,IAAI,WAAW,GAAoB,EAAE;;AAGrC,QAAA,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE;AAClC,YAAA,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;AACpC,YAAA,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;gBAAE;QAC9B;QAEA,IAAI,IAAI,CAAC,MAAM,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;AAC3C,YAAA,OAAO,CAAC,IAAI,CACV,yEAAyE,EACzE,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAC3D,UAAU,EAAE,QAAQ,CACrB;QACH;;AAGA,QAAA,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,aAAa,EAAE;YAC5C,WAAW,GAAG,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC;QACpD;;QAGA,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC;AAC/C,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;AAE7B,QAAA,OAAO,QAAQ;IACjB;AAEA;;;AAGG;IACH,cAAc,GAAA;QACZ,KAAK,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE;YAChD,IAAI,CAAC,OAAO,CAAC,MAAM;gBAAE;YACrB,MAAM,SAAS,GAAG,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE;AACvC,YAAA,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;AACtB,gBAAA,OAAO,SAAS,CAAC,GAAG,CAAC;YACvB;YACA,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;YACvE,OAAO,CAAC,sBAAsB,EAAE;QAClC;AACA,QAAA,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE;AAC1B,QAAA,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACvE,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;AACvB,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;IAC5B;AAEA;;AAEG;IACH,aAAa,GAAA;;AAEX,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,EAAE;AACnC,QAAA,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AACxB,YAAA,OAAO,SAAS,CAAC,CAAC,CAAC;QACrB;;AAGA,QAAA,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE;YAClD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC;AACxC,YAAA,IAAI,OAAO,EAAE,MAAM,EAAE;gBACnB,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;AAC7C,gBAAA,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;AACxB,oBAAA,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC;oBAC7B,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;oBAC3C,OAAO;AACL,wBAAA,KAAK,EAAE,GAAG;wBACV,QAAQ;AACR,wBAAA,OAAO,EAAE,OAAO,UAAU,KAAK,QAAQ,GAAG,UAAU,GAAG,QAAQ;qBAChE;gBACH;YACF;QACF;AAEA,QAAA,OAAO,IAAI;IACb;AAEA;;AAEG;AACH,IAAA,cAAc,CAAC,SAAiB,EAAA;AAC9B,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,IAAI,IAAI;IACvD;AAEA;;;;AAIG;AACH,IAAA,cAAc,CAAC,WAA6B,EAAA;AAC1C,QAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC;AACpC,QAAA,OAAO,MAAK;AACV,YAAA,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,WAAW,CAAC;AACxE,QAAA,CAAC;IACH;;AAIA;;AAEG;AACH,IAAA,IAAI,IAAI,GAAA;QACN,OAAO,IAAI,CAAC,KAAK;IACnB;;AAIQ,IAAA,2BAA2B,CAAC,OAAsB,EAAA;QACxD,MAAM,MAAM,GAAkB,EAAE;AAChC,QAAA,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;YAC5B,IAAI,MAAM,CAAC,aAAa;gBAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC;QACvE;;QAEA,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;AACpC,YAAA,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,8BAA8B,CAAC;QACvD;AACA,QAAA,OAAO,MAAM;IACf;AAEQ,IAAA,YAAY,CAAC,WAA4B,EAAA;QAC/C,MAAM,QAAQ,GAAyB,EAAE;QACzC,MAAM,YAAY,GAAkB,EAAE;;AAGtC,QAAA,MAAM,aAAa,GAAG,IAAI,GAAG,EAAqC;AAElE,QAAA,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE;;AAEpC,YAAA,IAAI,UAAU,CAAC,KAAK,KAAK,kBAAkB,EAAE;gBAC3C,YAAY,CAAC,IAAI,CAAC;oBAChB,OAAO,EAAE,UAAU,CAAC,OAAO;oBAC3B,UAAU,EAAE,UAAU,CAAC,UAAU;AAClC,iBAAA,CAAC;gBACF;YACF;AAEA,YAAA,IAAI,OAAO,GAA2B,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI;YACnF,IAAI,CAAC,OAAO,EAAE;;gBAEZ,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC,KAAK,CAAC;gBACtD,IAAI,CAAC,OAAO,EAAE;;oBAEZ,YAAY,CAAC,IAAI,CAAC;wBAChB,OAAO,EAAE,UAAU,CAAC,OAAO;wBAC3B,UAAU,EAAE,UAAU,CAAC,UAAU;wBACjC,aAAa,EAAE,UAAU,CAAC,KAAK;AAChC,qBAAA,CAAC;AACF,oBAAA,IAAI,IAAI,CAAC,MAAM,EAAE;wBACf,OAAO,CAAC,IAAI,CACV,CAAA,uBAAA,EAA0B,UAAU,CAAC,KAAK,CAAA,iEAAA,CAAmE,EAC7G,qBAAqB,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CACnE;oBACH;oBACA;gBACF;YACF;YAEA,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,UAAU,CAAC;YAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;AAEhD,YAAA,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS;gBAAE;AAElC,YAAA,MAAM,aAAa,GAAG,QAAQ,IAAI,SAAS;;AAG3C,YAAA,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,YAAY,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE,IAAI,EAAE,CAAC;YAChG,IAAI,SAAS,GAAG,aAAa;AAC7B,YAAA,IAAI,QAAQ,CAAC,SAAS,CAAC,KAAK,SAAS,EAAE;gBACrC,IAAI,GAAG,GAAG,CAAC;gBACX,OAAO,QAAQ,CAAC,CAAA,EAAG,aAAa,IAAI,GAAG,CAAA,CAAE,CAAC,KAAK,SAAS;AAAE,oBAAA,GAAG,EAAE;AAC/D,gBAAA,SAAS,GAAG,CAAA,EAAG,aAAa,CAAA,CAAA,EAAI,GAAG,EAAE;YACvC;AACA,YAAA,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,GAAG,QAAQ,EAAE,CAAC,SAAS,GAAG,OAAO,EAAE,CAAC;;YAGjE,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;gBACpC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,GAAG,EAAE,CAAC;YAC5C;AACA,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC,GAAG,CAAC,SAAS,CAAC;AAE/C,YAAA,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;QAC1E;;QAGA,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,aAAa,EAAE;YAC7C,OAAO,CAAC,aAAa,EAAE;AACvB,YAAA,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC;QAC3B;;AAGA,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC;AAEpC,QAAA,OAAO,QAAQ;IACjB;AAEQ,IAAA,qBAAqB,CAAC,IAAY,EAAA;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;AAC7B,QAAA,IAAI,OAAO,GAAoB,IAAI,CAAC,KAAK;AAEzC,QAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;AACxB,YAAA,IAAI,OAAO,YAAY,SAAS,EAAE;gBAChC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;AACpC,gBAAA,IAAI,CAAC,KAAK;AAAE,oBAAA,OAAO,IAAI;gBACvB,OAAO,GAAG,KAAK;YACjB;AAAO,iBAAA,IAAI,OAAO,YAAY,SAAS,EAAE;gBACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;AAChC,gBAAA,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,OAAO,CAAC,MAAM;AAAE,oBAAA,OAAO,IAAI;AACrE,gBAAA,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC;YAC7B;iBAAO;AACL,gBAAA,OAAO,IAAI;YACb;QACF;AAEA,QAAA,OAAO,OAAO;IAChB;AAEQ,IAAA,gBAAgB,CAAC,UAAkB,EAAA;;;;QAIzC,IAAI,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,SAAS,EAAE;AACjD,YAAA,OAAO,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC;QACxC;AACA,QAAA,OAAO,UAAU;IACnB;AAEQ,IAAA,eAAe,CAAC,KAAoB,EAAA;AAC1C,QAAA,IAAI,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE;YACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC;YAClF,IAAI,QAAQ,KAAK,IAAI;AAAE,gBAAA,OAAO,QAAQ;QACxC;AAEA,QAAA,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE;;AAEtB,YAAA,OAAO,CAAA,EAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAA,CAAA,EAAI,KAAK,CAAC,KAAK,CAAA,CAAA,EAAI,KAAK,CAAC,UAAU,EAAE;QAClE;QAEA,OAAO,KAAK,CAAC,OAAO;IACtB;AACD;AAoBK,SAAU,gBAAgB,CAAsB,IAAO,EAAE,MAAyB,EAAA;AACtF,IAAA,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;AACrC;AA2BM,SAAU,iBAAiB,CAAsB,IAAO,EAAE,MAAyB,EAAA;AACvF,IAAA,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;AACrC;;AC/ZA;;;;;;;;;;;;;;;;;;AAkBG;MAoBU,qBAAqB,CAAA;AACf,IAAA,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC;AACvB,IAAA,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC;AAC5B,IAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;AAC/B,IAAA,YAAY,GAAG,IAAI,OAAO,EAAQ;;AAG5B,IAAA,WAAW;;AAGzB,IAAA,IAAI;AAEb;;;;AAIG;AACM,IAAA,aAAa;AAEtB;;;AAGG;IACM,UAAU,GAAG,wBAAwB;AAE9C;;;AAGG;IACM,aAAa,GAAG,IAAI;IAE7B,QAAQ,GAAA;QACN,IAAI,CAAC,UAAU,EAAE;IACnB;AAEA,IAAA,WAAW,CAAC,OAAsB,EAAA;QAChC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE;YAChF,IAAI,CAAC,UAAU,EAAE;QACnB;IACF;IAEQ,UAAU,GAAA;;AAEhB,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;AAExB,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;QAChD,IAAI,CAAC,OAAO,EAAE;YACZ,IAAI,CAAC,KAAK,EAAE;YACZ;QACF;AAEA,QAAA,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,IAAI,CACrD,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,EAC5B,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,CACpC,CAAC,SAAS,CAAC,MAAK;AACf,YAAA,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;AAC9B,QAAA,CAAC,CAAC;AAEF,QAAA,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;IAC9B;AAEQ,IAAA,cAAc,CAAC,OAAwB,EAAA;QAC7C,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,IAAI,CAAC,aAAa,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YACjF,IAAI,CAAC,KAAK,EAAE;YACZ;QACF;QAEA,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;AAC7C,QAAA,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE;YAC1B,IAAI,CAAC,KAAK,EAAE;YACZ;QACF;AAEA,QAAA,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC;QAC7B,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;AACzC,QAAA,IAAI,OAAe;;QAGnB,IAAI,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,EAAE;AAClC,YAAA,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC;QACxC;AAAO,aAAA,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;YACvC,OAAO,GAAG,QAAQ;QACpB;aAAO;YACL,OAAO,GAAG,QAAQ;QACpB;AAEA,QAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;IACrB;AAEQ,IAAA,KAAK,CAAC,OAAe,EAAA;AAC3B,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,aAAa;QAChC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,EAAE,aAAa,EAAE,OAAO,CAAC;QACrD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC;QAC3C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC;IAC3C;IAEQ,KAAK,GAAA;AACX,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,aAAa;QAChC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,EAAE,aAAa,EAAE,EAAE,CAAC;QAChD,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC;QAC9C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC;IAC/C;wGArGW,qBAAqB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAArB,qBAAqB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,EAAA,WAAA,EAAA,CAAA,cAAA,EAAA,aAAA,CAAA,EAAA,IAAA,EAAA,MAAA,EAAA,aAAA,EAAA,eAAA,EAAA,UAAA,EAAA,YAAA,EAAA,aAAA,EAAA,eAAA,EAAA,EAAA,aAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;4FAArB,qBAAqB,EAAA,UAAA,EAAA,CAAA;kBAJjC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,gBAAgB;AAC1B,oBAAA,UAAU,EAAE,IAAI;AACjB,iBAAA;;sBAQE,KAAK;uBAAC,cAAc;;sBAGpB;;sBAOA;;sBAMA;;sBAMA;;;AC1DH;;;;;;;;;;;;;;;;;;;;AAoBG;SACa,cAAc,CAC5B,QAAiB,EACjB,MAAoC,EACpC,OAA6B,EAAA;IAE7B,MAAM,OAAO,GAAG;AACd,WAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;AAC5C,UAAE,CAAC,oBAAoB,EAAE,CAAC;AAE5B,IAAA,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE;QACvB,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;AAChC,QAAA,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;AAAE,YAAA,OAAO,MAAM;IACtC;AAEA,IAAA,IAAI,OAAO,EAAE,KAAK,EAAE;AAClB,QAAA,OAAO,CAAC,IAAI,CACV,6DAA6D,EAC7D,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EACrD,UAAU,EAAE,QAAQ,CACrB;IACH;AAEA,IAAA,OAAO,EAAE;AACX;AAEA;;;;;;;;;;;;;;;;;;;;;;;AAuBG;SACa,UAAU,CACxB,IAAe,EACf,MAAqB,EACrB,OAA8C,EAAA;IAE9C,IAAI,CAAC,OAAO,EAAE;IACd,OAAO,MAAM,CAAC,IAAI,CAChB,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,EACxB,UAAU,CAAC,CAAC,GAAG,KAAI;QACjB,IAAI,CAAC,MAAM,EAAE;AACb,QAAA,OAAO,EAAE,OAAO,GAAG,GAAG,CAAC;AACvB,QAAA,MAAM,GAAG;IACX,CAAC,CAAC,CACH;AACH;AAEA;;;AAGG;AACG,SAAU,UAAU,CAAC,IAA6B,EAAA;AACtD,IAAA,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE;AAE/B,IAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AAC/C,QAAA,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;YAAE;QAE3C,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,YAAY,IAAI,EAAE;AAClD,YAAA,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC;YAC3B;QACF;AAEA,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACxB,YAAA,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;gBACxB,IAAI,IAAI,YAAY,IAAI,IAAI,IAAI,YAAY,IAAI,EAAE;AAChD,oBAAA,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC;gBAC5B;qBAAO,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE;AACpD,oBAAA,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBAC5C;qBAAO;oBACL,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;gBACpC;YACF;YACA;QACF;AAEA,QAAA,IAAI,KAAK,YAAY,IAAI,EAAE;YACzB,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;YACzC;QACF;AAEA,QAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7B,YAAA,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC3C;QACF;QAEA,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACrC;AAEA,IAAA,OAAO,QAAQ;AACjB;AAEA;;AAEG;AACG,SAAU,UAAU,CAAC,IAAe,EAAE,OAA2B,EAAA;AACrE,IAAA,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AAC5C,QAAA,IAAI,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC;YAAE;QACpC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE;IAC7B;AACA,IAAA,IAAI,CAAC,sBAAsB,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACnE;AAEA;;AAEG;AACG,SAAU,WAAW,CAAC,IAAe,EAAE,OAA4B,EAAA;AACvE,IAAA,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AAC5C,QAAA,IAAI,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC;YAAE;QACpC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE;IAC9B;AACF;AAEA;;AAEG;AACG,SAAU,eAAe,CAAC,IAAe,EAAA;AAC7C,IAAA,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAC5C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,sBAAsB,EAAE;IAC7C;AACA,IAAA,IAAI,CAAC,sBAAsB,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACnE;AAEA;;AAEG;AACG,SAAU,cAAc,CAAC,IAAe,EAAA;IAC5C,MAAM,MAAM,GAA4B,EAAE;AAC1C,IAAA,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;QAC5C,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE;AAC5B,YAAA,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK;QACxC;IACF;AACA,IAAA,OAAO,MAAM;AACf;AAEA;;AAEG;AACG,SAAU,QAAQ,CAAC,IAAe,EAAE,QAAgB,EAAA;AACxD,IAAA,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AAC5C,QAAA,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;AACzC,YAAA,OAAO,IAAI;QACb;IACF;AACA,IAAA,OAAO,KAAK;AACd;AAEA;;;AAGG;SACa,eAAe,CAAC,IAAe,EAAE,SAAiB,EAAE,QAAiB,EAAA;IACnF,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;IACxC,IAAI,CAAC,OAAO,EAAE,MAAM;AAAE,QAAA,OAAO,IAAI;IAEjC,IAAI,QAAQ,EAAE;QACZ,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;QACtC,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,GAAG,KAAK,GAAG,QAAQ,IAAI,IAAI;IACtE;;IAGA,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;AACxC,IAAA,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;AAAE,QAAA,OAAO,IAAI;IAElC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1C,IAAA,OAAO,OAAO,UAAU,KAAK,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC;AAC9D;;ACvNA;;;;;;;;;AASG;AAcH;;;AAGG;AACI,MAAM,WAAW,GAAG,IAAI,gBAAgB,CAAoB,MAAM,IAAI;AA8B7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BG;AACG,SAAU,mBAAmB,CAAC,MAAkC,EAAA;IACpE,MAAM,WAAW,GAAG,MAAM,EAAE,WAAW,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC;IACrD,MAAM,cAAc,GAAG,MAAM,EAAE,MAAM,IAAI,oBAAoB,EAAE;AAE/D,IAAA,OAAO,CAAC,GAAG,EAAE,IAAI,KAAI;AACnB,QAAA,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CACnB,UAAU,CAAC,CAAC,KAAwB,KAAI;YACtC,IAAI,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE;gBACtC,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;gBAE3C,IAAI,MAAM,EAAE;AACV,oBAAA,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC;gBACpC;AAEA,gBAAA,IAAI,MAAM,EAAE,OAAO,EAAE;oBACnB,MAAM,MAAM,GAAG;AACb,0BAAE,MAAM,CAAC,YAAY;0BACnB,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,cAAc,CAAC;AAC/C,oBAAA,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC;gBAC/B;YACF;AAEA,YAAA,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC;QAChC,CAAC,CAAC,CACH;AACH,IAAA,CAAC;AACH;AAEA;;;;;;;;;;;;;;;;;;AAkBG;AACG,SAAU,cAAc,CAAC,MAAkB,EAAA;IAC/C,OAAO;QACL,OAAO,EAAE,IAAI,WAAW,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC;KACpD;AACH;;AC3IA;;AAEG;AAEH;;ACJA;;AAEG;;;;"}
|