@dbsp/core 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +30 -9
- package/dist/index.js +262 -115
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/model-ir.ts","../src/intent-ast.ts","../src/model-impl.ts","../src/dx/logger.ts","../src/dx/symbols.ts","../src/dx/table-ref.ts","../src/dx/table-ref-factory.ts","../src/dx/schema.ts","../src/conventions.ts","../src/schema-dsl.ts","../src/schema-dsl-types.ts","../src/dx/errors.ts","../src/planner.ts","../src/adapter.ts","../src/dx/batch-values.ts","../src/dx/expressions.ts","../src/dx/case-when-builder.ts","../src/dx/builder-utils.ts","../src/dx/cte-builder.ts","../src/dx/feature-checkers.ts","../src/dx/column-utils.ts","../src/dx/window-functions.ts","../src/dx/filters.ts","../src/dx/full-text-search.ts","../src/dx/hook-utils.ts","../src/dx/hooks.ts","../src/dx/subquery-builder.ts","../src/dx/object-filter.ts","../src/dx/types.ts","../src/dx/intent-builder.ts","../src/dx/lightweight-model.ts","../src/dx/mutation-builders.ts","../src/dx/negotiate-features.ts","../src/dx/nql.ts","../src/dx/hierarchy-helpers.ts","../src/dx/pagination-impl.ts","../src/dx/hydration-utils.ts","../src/dx/result-hydrator.ts","../src/dx/set-operation-builder.ts","../src/dx/stream-impl.ts","../src/dx/query-builder.ts","../src/dx/raw-cte-builder.ts","../src/dx/orm-instance.ts","../src/dx/orm.ts","../src/dx/range.ts","../src/dx/schema-bridge.ts","../src/dialects/index.ts","../src/sql-utils.ts","../src/assert/assertion-functions.ts","../src/assert/assertion-parser.ts","../src/assert/assertion-runner.ts","../src/assert/types.ts"],"sourcesContent":["/**\n * @module model-ir\n * ModelIR (Model Intermediate Representation) - Schema definition format for db-semantic-planner.\n * Represents database tables, columns, and relations with planning metadata.\n *\n * Type definitions live in @dbsp/types. This module re-exports them\n * and provides runtime functions.\n */\n\n// Re-export all types from @dbsp/types for backward compatibility\nexport type {\n\tAmbiguityCheckResult,\n\tCardinality,\n\tCheckConstraintIR,\n\tColumnIR,\n\tColumnType,\n\tEnumIR,\n\tFilterStrategy,\n\tForeignKeyIR,\n\tIncludeStrategy,\n\tIndexIR,\n\tJoinDefault,\n\tModelIR,\n\tOnDeleteAction,\n\tOptionality,\n\tPartitionIR,\n\tPseudoColumnMetadata,\n\tRecursiveMetadata,\n\tRelationIR,\n\tRelationKind,\n\tRelationType,\n\tSequenceIR,\n\tTableIR,\n} from '@dbsp/types';\n\nimport type {\n\tPseudoColumnMetadata,\n\tRecursiveMetadata,\n\tRelationIR,\n\tRelationKind,\n} from '@dbsp/types';\n\n// ============================================================================\n// Runtime Functions (stay in @dbsp/core)\n// ============================================================================\n\n/**\n * Creates pseudo-column metadata from a self-referential FK.\n */\nexport function createPseudoColumnMetadata(\n\ttable: string,\n\tforeignKeyColumn: string,\n\ttargetColumn: string,\n\tparentRole: string,\n\tchildRole: string,\n): PseudoColumnMetadata {\n\t// For single self-ref FK: ascendant/descendant are direct keywords\n\t// For multi-FK: they become scoped (e.g., manager.ascendant)\n\treturn {\n\t\ttable,\n\t\tforeignKeyColumn,\n\t\ttargetColumn,\n\t\tparentRole,\n\t\tchildRole,\n\t\tascendantKeyword: 'ascendant',\n\t\tdescendantKeyword: 'descendant',\n\t};\n}\n\n/**\n * CLI-NQL: Convert ORM-style RelationType to database-style RelationKind.\n * Handles recursive relations when recursive metadata is present.\n */\nexport function getRelationKind(relation: RelationIR): RelationKind {\n\t// Check for recursive relation first\n\tif (relation.recursive) {\n\t\treturn relation.recursive.direction === 'up'\n\t\t\t? 'recursive-up'\n\t\t\t: 'recursive-down';\n\t}\n\n\t// Map ORM types to database perspective\n\tswitch (relation.type) {\n\t\tcase 'belongsTo':\n\t\tcase 'hasOne':\n\t\t\treturn 'many-to-one';\n\t\tcase 'hasMany':\n\t\t\treturn 'one-to-many';\n\t\tcase 'belongsToMany':\n\t\t\treturn 'many-to-many';\n\t}\n}\n\n/**\n * CLI-NQL: Type guard to check if a relation has recursive metadata.\n */\nexport function isRecursiveRelation(\n\trelation: RelationIR,\n): relation is RelationIR & { recursive: RecursiveMetadata } {\n\treturn relation.recursive !== undefined;\n}\n\n/**\n * CLI-NQL: Check if a relation is self-referential (source === target).\n * Self-referential relations are candidates for recursive traversal.\n */\nexport function isSelfReferential(relation: RelationIR): boolean {\n\treturn relation.source === relation.target;\n}\n\n/**\n * CLI-NQL: Create default recursive metadata for a self-referential relation.\n * Used when schema doesn't explicitly define recursive metadata.\n */\nexport function createRecursiveMetadata(\n\tdirection: 'up' | 'down',\n\tthroughRelation: string,\n\tmaxDepth = 10,\n): RecursiveMetadata {\n\treturn {\n\t\tdirection,\n\t\tmaxDepth,\n\t\tthrough: throughRelation,\n\t};\n}\n","/**\n * @module intent-ast\n * IntentAST (Intent Abstract Syntax Tree) - Query intent representation for db-semantic-planner.\n *\n * This module re-exports all IntentAST types and type guards from @dbsp/types.\n * The canonical source is @dbsp/types/intent-ast.\n *\n * @since ARCH-007: Types centralized in @dbsp/types to avoid circular dependencies.\n */\n\n// Re-export everything from @dbsp/types (types + type guards + helpers)\nexport * from '@dbsp/types';\n","/**\n * @module model-impl\n * ModelIR implementation with Map-based storage and helper methods.\n */\n\nimport type {\n\tAmbiguityCheckResult,\n\tEnumIR,\n\tModelIR,\n\tRelationIR,\n\tSequenceIR,\n\tTableIR,\n} from './model-ir.js';\n\n/**\n * Immutable ModelIR implementation\n */\nexport class ModelIRImpl implements ModelIR {\n\treadonly tables: ReadonlyMap<string, TableIR>;\n\treadonly relations: ReadonlyMap<string, RelationIR>;\n\treadonly enums?: ReadonlyMap<string, EnumIR>;\n\treadonly extensions?: readonly string[];\n\treadonly sequences?: ReadonlyMap<string, SequenceIR>;\n\n\t// Pre-computed indexes for efficient lookups\n\tprivate readonly relationsBySource: ReadonlyMap<\n\t\tstring,\n\t\treadonly RelationIR[]\n\t>;\n\tprivate readonly relationsByTarget: ReadonlyMap<\n\t\tstring,\n\t\treadonly RelationIR[]\n\t>;\n\n\tconstructor(\n\t\ttables: Map<string, TableIR>,\n\t\trelations: Map<string, RelationIR>,\n\t\tenums?: Map<string, EnumIR>,\n\t\textensions?: readonly string[],\n\t\tsequences?: Map<string, SequenceIR>,\n\t) {\n\t\t// Freeze the maps to ensure immutability\n\t\tthis.tables = Object.freeze(new Map(tables)) as ReadonlyMap<\n\t\t\tstring,\n\t\t\tTableIR\n\t\t>;\n\t\tthis.relations = Object.freeze(new Map(relations)) as ReadonlyMap<\n\t\t\tstring,\n\t\t\tRelationIR\n\t\t>;\n\t\tif (enums) {\n\t\t\tthis.enums = Object.freeze(new Map(enums)) as ReadonlyMap<string, EnumIR>;\n\t\t}\n\t\tif (extensions && extensions.length > 0) {\n\t\t\tthis.extensions = Object.freeze([...extensions]) as readonly string[];\n\t\t}\n\t\tif (sequences) {\n\t\t\tthis.sequences = Object.freeze(new Map(sequences)) as ReadonlyMap<\n\t\t\t\tstring,\n\t\t\t\tSequenceIR\n\t\t\t>;\n\t\t}\n\n\t\t// Build indexes\n\t\tthis.relationsBySource = this.buildRelationsBySourceIndex(relations);\n\t\tthis.relationsByTarget = this.buildRelationsByTargetIndex(relations);\n\n\t\t// Validate the schema\n\t\tthis.validate();\n\t}\n\n\t/**\n\t * Get table by name\n\t */\n\tgetTable(name: string): TableIR | undefined {\n\t\treturn this.tables.get(name);\n\t}\n\n\t/**\n\t * Get relation by qualified name \"source.relationName\"\n\t */\n\tgetRelation(qualifiedName: string): RelationIR | undefined {\n\t\treturn this.relations.get(qualifiedName);\n\t}\n\n\t/**\n\t * Get all relations from a source table\n\t */\n\tgetRelationsFrom(sourceTable: string): readonly RelationIR[] {\n\t\treturn this.relationsBySource.get(sourceTable) ?? [];\n\t}\n\n\t/**\n\t * Get all relations to a target table\n\t */\n\tgetRelationsTo(targetTable: string): readonly RelationIR[] {\n\t\treturn this.relationsByTarget.get(targetTable) ?? [];\n\t}\n\n\t/**\n\t * Check if relation path is ambiguous (multiple relations to same target)\n\t */\n\tisAmbiguous(sourceTable: string, targetTable: string): AmbiguityCheckResult {\n\t\tconst relationsFromSource = this.getRelationsFrom(sourceTable);\n\t\tconst matchingRelations = relationsFromSource.filter(\n\t\t\t(r) => r.target === targetTable,\n\t\t);\n\n\t\tif (matchingRelations.length <= 1) {\n\t\t\treturn {\n\t\t\t\tambiguous: false,\n\t\t\t\toptions: matchingRelations.map((r) => r.name),\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tambiguous: true,\n\t\t\toptions: matchingRelations.map((r) => r.name),\n\t\t};\n\t}\n\n\t// =========================================================================\n\t// Private Methods\n\t// =========================================================================\n\n\tprivate buildRelationsBySourceIndex(\n\t\trelations: Map<string, RelationIR>,\n\t): ReadonlyMap<string, readonly RelationIR[]> {\n\t\tconst index = new Map<string, RelationIR[]>();\n\n\t\tfor (const relation of relations.values()) {\n\t\t\tconst existing = index.get(relation.source) ?? [];\n\t\t\tindex.set(relation.source, [...existing, relation]);\n\t\t}\n\n\t\t// Create frozen index with readonly arrays\n\t\tconst frozenIndex = new Map<string, readonly RelationIR[]>();\n\t\tfor (const [key, value] of index) {\n\t\t\tfrozenIndex.set(key, Object.freeze(value));\n\t\t}\n\n\t\treturn Object.freeze(frozenIndex) as ReadonlyMap<\n\t\t\tstring,\n\t\t\treadonly RelationIR[]\n\t\t>;\n\t}\n\n\tprivate buildRelationsByTargetIndex(\n\t\trelations: Map<string, RelationIR>,\n\t): ReadonlyMap<string, readonly RelationIR[]> {\n\t\tconst index = new Map<string, RelationIR[]>();\n\n\t\tfor (const relation of relations.values()) {\n\t\t\tconst existing = index.get(relation.target) ?? [];\n\t\t\tindex.set(relation.target, [...existing, relation]);\n\t\t}\n\n\t\t// Create frozen index with readonly arrays\n\t\tconst frozenIndex = new Map<string, readonly RelationIR[]>();\n\t\tfor (const [key, value] of index) {\n\t\t\tfrozenIndex.set(key, Object.freeze(value));\n\t\t}\n\n\t\treturn Object.freeze(frozenIndex) as ReadonlyMap<\n\t\t\tstring,\n\t\t\treadonly RelationIR[]\n\t\t>;\n\t}\n\n\tprivate validate(): void {\n\t\tconst errors: string[] = [];\n\n\t\t// Validate PK columns exist when PK is defined\n\t\tfor (const table of this.tables.values()) {\n\t\t\tif (table.primaryKey) {\n\t\t\t\tconst pkCols = Array.isArray(table.primaryKey)\n\t\t\t\t\t? table.primaryKey\n\t\t\t\t\t: [table.primaryKey];\n\t\t\t\tfor (const pk of pkCols) {\n\t\t\t\t\tif (!table.columns.some((c) => c.name === pk)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`Table \"${table.name}\" primary key column \"${pk}\" not found in columns`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Validate all FK references point to existing tables\n\t\tfor (const table of this.tables.values()) {\n\t\t\tfor (const fk of table.foreignKeys) {\n\t\t\t\tif (!this.tables.has(fk.references.table)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Table \"${table.name}\" has FK referencing non-existent table \"${fk.references.table}\"`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Validate all relation targets exist\n\t\tfor (const relation of this.relations.values()) {\n\t\t\tif (!this.tables.has(relation.source)) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Relation \"${relation.name}\" has non-existent source table \"${relation.source}\"`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!this.tables.has(relation.target)) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Relation \"${relation.name}\" has non-existent target table \"${relation.target}\"`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (relation.through && !this.tables.has(relation.through)) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Relation \"${relation.name}\" has non-existent through table \"${relation.through}\"`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Detect circular relations (informational only, not an error)\n\t\t// Detection logic is retained but logging removed to avoid test pollution\n\t\tthis.detectCircularRelations();\n\n\t\tif (errors.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`ModelIR validation failed:\\n${errors.map((e) => ` - ${e}`).join('\\n')}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate detectCircularRelations(): string[] {\n\t\tconst circular: string[] = [];\n\t\tconst visited = new Set<string>();\n\t\tconst recursionStack = new Set<string>();\n\n\t\tconst dfs = (table: string, path: string[]): void => {\n\t\t\tif (recursionStack.has(table)) {\n\t\t\t\tconst cycleStart = path.indexOf(table);\n\t\t\t\tconst cycle = [...path.slice(cycleStart), table].join(' -> ');\n\t\t\t\tcircular.push(cycle);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (visited.has(table)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvisited.add(table);\n\t\t\trecursionStack.add(table);\n\n\t\t\tconst relations = this.getRelationsFrom(table);\n\t\t\tfor (const relation of relations) {\n\t\t\t\tdfs(relation.target, [...path, table]);\n\t\t\t}\n\n\t\t\trecursionStack.delete(table);\n\t\t};\n\n\t\tfor (const tableName of this.tables.keys()) {\n\t\t\tdfs(tableName, []);\n\t\t}\n\n\t\treturn circular;\n\t}\n}\n","/**\n * E10: Injectable Logger\n *\n * Provides a pluggable logging interface for library code.\n * Default implementation uses console, but can be replaced for:\n * - Silent mode (testing, production)\n * - Custom logging frameworks (pino, winston, etc.)\n * - Structured logging\n */\n\n/**\n * Logger interface for dbsp library code.\n *\n * Only includes methods actually used by the library.\n * Extend as needed when new log levels are required.\n */\nexport interface Logger {\n\t/**\n\t * Log a warning message.\n\t * Used for: reserved word usage, raw SQL warnings, deprecation notices.\n\t */\n\twarn(message: string): void;\n}\n\n/**\n * Default logger that writes to console.\n * Used when no custom logger is provided.\n */\nexport const defaultLogger: Logger = {\n\twarn: (message: string) => console.warn(message),\n};\n\n/**\n * Silent logger that discards all messages.\n * Useful for testing or when warnings should be suppressed.\n */\nexport const silentLogger: Logger = {\n\twarn: () => {},\n};\n\n/**\n * Global logger instance.\n * Can be replaced via setLogger() for application-wide configuration.\n */\nlet globalLogger: Logger = defaultLogger;\n\n/**\n * Set the global logger instance.\n *\n * @param logger - Logger implementation to use globally\n *\n * @example\n * ```typescript\n * import { setLogger, silentLogger } from '@dbsp/core';\n *\n * // Silence all warnings in tests\n * setLogger(silentLogger);\n *\n * // Use custom logger\n * setLogger({\n * warn: (msg) => myLogger.warning('[dbsp]', msg),\n * });\n * ```\n */\nexport function setLogger(logger: Logger): void {\n\tglobalLogger = logger;\n}\n\n/**\n * Get the current global logger.\n * Internal use - prefer using getLogger() in library code.\n */\nexport function getLogger(): Logger {\n\treturn globalLogger;\n}\n\n/**\n * Reset logger to default (for testing).\n */\nexport function resetLogger(): void {\n\tglobalLogger = defaultLogger;\n}\n","/**\n * @fileoverview ES6 Symbols for type-safe query API metadata.\n *\n * These symbols are used as property keys in TableRef, ColumnRef, and RelationRef\n * to store metadata without colliding with user-defined column names.\n *\n * @example\n * ```typescript\n * import { TABLE_META, COLUMN_META } from './symbols';\n *\n * // Access table name from TableRef\n * const tableName = users[TABLE_META]; // 'users'\n *\n * // Access column name from ColumnRef\n * const columnName = users.id[COLUMN_META]; // 'id'\n * ```\n *\n * @module symbols\n * @since DX-040\n */\n\n/**\n * Symbol for accessing table name metadata from a TableRef.\n *\n * @description\n * Used internally to retrieve the table name from a TableRef object.\n * Uses `Symbol.for()` to create a global symbol that survives serialization\n * and can be accessed across module boundaries.\n *\n * @example\n * ```typescript\n * const { users } = schema.tables;\n * const tableName = users[TABLE_META]; // 'users'\n * ```\n */\nexport const TABLE_META: unique symbol = Symbol.for('dbsp:table');\n\n/**\n * Symbol for accessing column name metadata from a ColumnRef.\n *\n * @description\n * Used internally to retrieve the column name from a ColumnRef object.\n * Uses `Symbol.for()` for cross-module accessibility.\n *\n * @example\n * ```typescript\n * const { users } = schema.tables;\n * const columnName = users.id[COLUMN_META]; // 'id'\n * ```\n */\nexport const COLUMN_META: unique symbol = Symbol.for('dbsp:column');\n\n/**\n * Symbol for accessing relation metadata from a RelationRef.\n *\n * @description\n * Used internally to retrieve relation information (target table, relation type)\n * from a RelationRef object. Uses `Symbol.for()` for cross-module accessibility.\n *\n * @example\n * ```typescript\n * const { users } = schema.tables;\n * const relInfo = users.posts[RELATION_META];\n * // { target: 'posts', type: 'hasMany' }\n * ```\n */\nexport const RELATION_META: unique symbol = Symbol.for('dbsp:relation');\n\n/**\n * Symbol for type branding (internal use).\n *\n * @description\n * Used internally to distinguish between TableRef, ColumnRef, and RelationRef\n * at runtime. This enables type guards and runtime validation.\n * Uses `Symbol.for()` for cross-module accessibility.\n *\n * @example\n * ```typescript\n * function isTableRef(value: unknown): value is TableRef<any, any> {\n * return typeof value === 'object' && value !== null && BRAND in value\n * && (value as any)[BRAND] === 'TableRef';\n * }\n * ```\n */\nexport const BRAND: unique symbol = Symbol.for('dbsp:brand');\n\n/**\n * Symbol for tracking the relation path through which a column was accessed.\n *\n * @description\n * Used to enable cross-table queries. When a column is accessed through a relation\n * (e.g., `users.posts.published`), this symbol stores the relation path.\n * This allows the query builder to generate EXISTS subqueries automatically.\n * Uses `Symbol.for()` for cross-module accessibility.\n *\n * @example\n * ```typescript\n * const { users } = schema.tables;\n * const col = users.posts.published;\n * const path = col[RELATION_PATH]; // ['posts']\n * // Multiple hops: users.posts.comments.author\n * // path would be ['posts', 'comments']\n * ```\n */\nexport const RELATION_PATH: unique symbol = Symbol.for('dbsp:relationPath');\n\n/**\n * Type declarations for Symbol keys to enable TypeScript inference.\n *\n * These types allow TypeScript to understand the shape of objects\n * that use these symbols as keys.\n */\nexport type TableMetaKey = typeof TABLE_META;\nexport type ColumnMetaKey = typeof COLUMN_META;\nexport type RelationMetaKey = typeof RELATION_META;\nexport type BrandKey = typeof BRAND;\n\n// ============================================================================\n// Type Guards for Symbol-keyed Properties\n// ============================================================================\n\n/**\n * Type-safe check for the presence of a symbol-keyed property on an unknown value.\n *\n * Replaces `SYMBOL in (value as unknown as object)` casts throughout the DX layer.\n *\n * @param value - The value to check (any type)\n * @param sym - The symbol key to look for\n * @returns `true` if `value` is a non-null object containing `sym`\n *\n * @example\n * ```typescript\n * if (hasSymbolMeta(value, COLUMN_META)) {\n * // value is narrowed to Record<typeof COLUMN_META, unknown>\n * }\n * ```\n */\nexport function hasSymbolMeta<S extends symbol>(\n\tvalue: unknown,\n\tsym: S,\n): value is Record<S, unknown> {\n\treturn typeof value === 'object' && value !== null && sym in value;\n}\n","/**\n * @fileoverview Type-safe table and column reference types for the query API.\n *\n * This module defines the core reference types used in the type-safe query builder:\n * - `TableRef`: Reference to a table with typed columns and relations\n * - `ColumnRef`: Reference to a column with table, name, and TypeScript type\n * - `RelationRef`: Reference to a relation (FK-based join path)\n * - `AliasedColumn`: Column with an alias for result type inference\n * - `AllColumns`: Wildcard type for SELECT *\n *\n * These types use ES6 Symbols for internal metadata to avoid collision\n * with user-defined column names (see symbols.ts).\n *\n * @example\n * ```typescript\n * const { users } = schema.tables;\n *\n * // TableRef with columns\n * users.id // ColumnRef<'users', 'id', number>\n * users.name // ColumnRef<'users', 'name', string>\n * users['*'] // AllColumns<'users', {...}>\n *\n * // RelationRef for cross-table queries\n * users.posts // RelationRef<'posts', Post[], 'hasMany'>\n * users.posts.title // ColumnRef<'posts', 'title', string>\n * ```\n *\n * @module table-ref\n * @since DX-040\n */\n\nimport {\n\tBRAND,\n\tCOLUMN_META,\n\thasSymbolMeta,\n\tRELATION_META,\n\tRELATION_PATH,\n\tTABLE_META,\n} from './symbols.js';\n\n// Re-export symbols for convenience\nexport {\n\tBRAND,\n\tCOLUMN_META,\n\thasSymbolMeta,\n\tRELATION_META,\n\tRELATION_PATH,\n\tTABLE_META,\n};\n\n/**\n * Relation types supported by the ORM.\n */\nexport type RelationType = 'belongsTo' | 'hasMany' | 'hasOne';\n\n/**\n * Base interface for ColumnRef metadata (using Symbols).\n * @internal\n */\ninterface ColumnRefBase<TTable extends string, TColumn extends string, TType> {\n\t/** @internal Table name metadata (via Symbol) */\n\treadonly [TABLE_META]: TTable;\n\n\t/** @internal Column name metadata (via Symbol) */\n\treadonly [COLUMN_META]: TColumn;\n\n\t/** @internal Type brand for runtime identification */\n\treadonly [BRAND]: 'ColumnRef';\n\n\t/**\n\t * Phantom type for TypeScript inference.\n\t * @internal Not used at runtime - only for type inference.\n\t */\n\treadonly _type: TType;\n}\n\n/**\n * Reference to a column in a table.\n *\n * @typeParam TTable - The table name as a string literal type (e.g., 'users')\n * @typeParam TColumn - The column name as a string literal type (e.g., 'id')\n * @typeParam TType - The TypeScript type of the column value (e.g., number, string)\n *\n * @description\n * ColumnRef carries type information for compile-time inference while also\n * containing runtime metadata accessible via Symbols. The `_type` property\n * is a phantom type (never instantiated at runtime) used for inference.\n *\n * @example\n * ```typescript\n * // users.id is ColumnRef<'users', 'id', number>\n * const id: ColumnRef<'users', 'id', number>;\n *\n * // Access metadata (rarely needed by users)\n * id[TABLE_META] // 'users'\n * id[COLUMN_META] // 'id'\n *\n * // Create alias for result type\n * id.as('userId') // AliasedColumn<'users', 'id', number, 'userId'>\n * ```\n */\nexport type ColumnRef<\n\tTTable extends string,\n\tTColumn extends string,\n\tTType,\n> = ColumnRefBase<TTable, TColumn, TType> & {\n\t/**\n\t * Create an aliased version of this column for result type inference.\n\t *\n\t * @typeParam TAlias - The alias name as a string literal type\n\t * @param alias - Must match `/^[a-zA-Z_][a-zA-Z0-9_]*$/` (validated at runtime)\n\t * @returns AliasedColumn with the specified alias\n\t * @throws Error if alias doesn't match the valid identifier pattern\n\t *\n\t * @example\n\t * ```typescript\n\t * users.id.as('userId')\n\t * // Result type will use 'userId' instead of 'id'\n\t * ```\n\t */\n\tas<TAlias extends string>(\n\t\talias: TAlias,\n\t): AliasedColumn<TTable, TColumn, TType, TAlias>;\n};\n\n/**\n * Column with an alias for result type inference.\n *\n * @typeParam TTable - The source table name\n * @typeParam TColumn - The source column name\n * @typeParam TType - The TypeScript type of the column value\n * @typeParam TAlias - The alias name that will appear in query results\n *\n * @description\n * Extends ColumnRef with an `_alias` property. When used in a query,\n * the result type will use the alias instead of the original column name.\n *\n * @example\n * ```typescript\n * const query = orm.from(users)\n * .select(users.id.as('userId'))\n * .all();\n * // Result type: { userId: number }[]\n * ```\n */\nexport type AliasedColumn<\n\tTTable extends string,\n\tTColumn extends string,\n\tTType,\n\tTAlias extends string,\n> = ColumnRef<TTable, TColumn, TType> & {\n\t/**\n\t * The alias name for this column.\n\t * Used to determine the property name in query results.\n\t */\n\treadonly _alias: TAlias;\n};\n\n/**\n * Represents all columns from a table for SELECT * operations.\n *\n * @typeParam TTable - The table name\n * @typeParam TColumns - Record mapping column names to their TypeScript types\n *\n * @description\n * Used when accessing the wildcard property `table['*']`.\n * When used in a query, selects all columns from the table.\n *\n * @example\n * ```typescript\n * orm.from(users).select(users['*']).all()\n * // SQL: SELECT * FROM users\n * // Result type: User[]\n * ```\n */\nexport interface AllColumns<\n\tTTable extends string,\n\tTColumns extends Record<string, unknown>,\n> {\n\t/** @internal Type brand for runtime identification */\n\treadonly [BRAND]: 'AllColumns';\n\n\t/** @internal Table name metadata */\n\treadonly [TABLE_META]: TTable;\n\n\t/**\n\t * Phantom type containing all column types.\n\t * @internal Used for result type inference.\n\t */\n\treadonly _columns: TColumns;\n}\n\n/**\n * Base interface for RelationRef metadata (using Symbols).\n * @internal\n */\ninterface RelationRefBase<\n\tTTarget extends string,\n\tTTargetType,\n\tTRelationType extends RelationType,\n> {\n\t/** @internal Relation metadata containing target and type */\n\treadonly [RELATION_META]: { target: TTarget; type: TRelationType };\n\n\t/** @internal Type brand for runtime identification */\n\treadonly [BRAND]: 'RelationRef';\n\n\t/**\n\t * Phantom type for the related records.\n\t * @internal Used for result type inference with include().\n\t */\n\treadonly _type: TTargetType;\n}\n\n/**\n * Reference to a relation (FK-based join path).\n *\n * @typeParam TTarget - The target table name (e.g., 'posts')\n * @typeParam TTargetType - The TypeScript type of related records (e.g., Post[])\n * @typeParam TRelationType - The relation type: 'belongsTo' | 'hasMany' | 'hasOne'\n * @typeParam TTargetColumns - Record mapping target column names to their types\n *\n * @description\n * RelationRef enables cross-table queries by allowing access to columns\n * from related tables. It also supports the wildcard `'*'` for selecting\n * all columns from the related table.\n *\n * @example\n * ```typescript\n * // users.posts is RelationRef<'posts', Post[], 'hasMany'>\n *\n * // Access related table's columns\n * users.posts.title // ColumnRef<'posts', 'title', string>\n * users.posts['*'] // AllColumns<'posts', {...}>\n *\n * // Use in cross-table queries\n * orm.from(users).where(eq(users.posts.published, true))\n * // Generates EXISTS subquery\n * ```\n */\nexport type RelationRef<\n\tTTarget extends string,\n\tTTargetType,\n\tTRelationType extends RelationType,\n\tTTargetColumns extends Record<string, unknown> = Record<string, unknown>,\n> = RelationRefBase<TTarget, TTargetType, TRelationType> & {\n\t/**\n\t * Access columns through relation (for cross-table queries).\n\t */\n\treadonly [K in keyof TTargetColumns]: ColumnRef<\n\t\tTTarget,\n\t\tK & string,\n\t\tTTargetColumns[K]\n\t>;\n} & {\n\t/**\n\t * Wildcard for selecting all columns from the related table.\n\t *\n\t * @example\n\t * ```typescript\n\t * users.posts['*'] // AllColumns<'posts', {...}>\n\t * ```\n\t */\n\treadonly '*': AllColumns<TTarget, TTargetColumns>;\n};\n\n/**\n * Base interface for TableRef metadata (using Symbols).\n * @internal\n */\ninterface TableRefBase<TName extends string> {\n\t/** @internal Table name metadata (via Symbol) */\n\treadonly [TABLE_META]: TName;\n\n\t/** @internal Type brand for runtime identification */\n\treadonly [BRAND]: 'TableRef';\n}\n\n/**\n * Reference to a table in the schema.\n *\n * @typeParam TName - The table name as a string literal type (e.g., 'users')\n * @typeParam TColumns - Record mapping column names to ColumnRef types\n * @typeParam TRelations - Record mapping relation names to RelationRef types\n *\n * @description\n * TableRef is the primary type for type-safe queries. It provides:\n * - Access to all columns as ColumnRef properties\n * - Access to all relations as RelationRef properties\n * - A `'*'` wildcard for SELECT * operations\n * - Internal metadata via Symbols (no collision with user columns)\n *\n * TableRef objects are created by the schema builder and accessed via\n * `schema.tables.tableName`.\n *\n * @example\n * ```typescript\n * const { users, posts } = schema.tables;\n *\n * // Access columns\n * users.id // ColumnRef<'users', 'id', number>\n * users.name // ColumnRef<'users', 'name', string>\n *\n * // Access relations\n * users.posts // RelationRef<'posts', Post[], 'hasMany'>\n *\n * // Wildcard\n * users['*'] // AllColumns<'users', {...}>\n *\n * // Internal metadata (rarely needed)\n * users[TABLE_META] // 'users'\n * ```\n */\nexport type TableRef<\n\tTName extends string,\n\tTColumns extends Record<string, ColumnRef<TName, string, unknown>>,\n\tTRelations extends Record<\n\t\tstring,\n\t\tRelationRef<string, unknown, RelationType>\n\t> = Record<never, never>,\n> = TableRefBase<TName> & {\n\t/**\n\t * All columns as ColumnRef properties.\n\t */\n\treadonly [K in keyof TColumns]: TColumns[K];\n} & {\n\t/**\n\t * All relations as RelationRef properties (excluding column name conflicts).\n\t */\n\treadonly [K in keyof TRelations as K extends keyof TColumns\n\t\t? never\n\t\t: K]: TRelations[K];\n} & {\n\t/**\n\t * Wildcard for SELECT * operations.\n\t * The `'*'` character is never a valid SQL identifier, preventing collisions.\n\t *\n\t * @example\n\t * ```typescript\n\t * orm.from(users).select(users['*']).all()\n\t * // SQL: SELECT * FROM users\n\t * ```\n\t */\n\treadonly '*': AllColumns<TName, InferColumnTypes<TColumns>>;\n};\n\n/**\n * Helper type to extract column types from a TColumns record.\n *\n * @typeParam TColumns - Record of column names to ColumnRef types\n * @returns Record mapping column names to their TypeScript types\n *\n * @internal\n */\nexport type InferColumnTypes<\n\tTColumns extends Record<string, ColumnRef<string, string, unknown>>,\n> = {\n\t[K in keyof TColumns]: TColumns[K] extends ColumnRef<string, string, infer T>\n\t\t? T\n\t\t: never;\n};\n\n/**\n * Helper type to infer the row type from a TableRef.\n *\n * @typeParam T - A TableRef type\n * @returns The TypeScript type representing a single row from the table\n *\n * @example\n * ```typescript\n * type UserRow = InferTableRow<typeof users>;\n * // { id: number; name: string; email: string }\n * ```\n */\nexport type InferTableRow<T> =\n\tT extends TableRef<string, infer TColumns, infer _TRelations>\n\t\t? InferColumnTypes<TColumns>\n\t\t: never;\n\n/**\n * Type guard to check if a value is a TableRef.\n *\n * @param value - The value to check\n * @returns True if the value is a TableRef\n *\n * @example\n * ```typescript\n * if (isTableRef(value)) {\n * const tableName = value[TABLE_META];\n * }\n * ```\n */\nexport function isTableRef(\n\tvalue: unknown,\n): value is TableRef<\n\tstring,\n\tRecord<string, ColumnRef<string, string, unknown>>\n> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tBRAND in value &&\n\t\t(value as Record<symbol, unknown>)[BRAND] === 'TableRef'\n\t);\n}\n\n/**\n * Type guard to check if a value is a ColumnRef.\n *\n * @param value - The value to check\n * @returns True if the value is a ColumnRef\n *\n * @example\n * ```typescript\n * if (isColumnRef(value)) {\n * const columnName = value[COLUMN_META];\n * }\n * ```\n */\nexport function isColumnRef(\n\tvalue: unknown,\n): value is ColumnRef<string, string, unknown> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tBRAND in value &&\n\t\t(value as Record<symbol, unknown>)[BRAND] === 'ColumnRef'\n\t);\n}\n\n/**\n * Type guard to check if a value is a RelationRef.\n *\n * @param value - The value to check\n * @returns True if the value is a RelationRef\n *\n * @example\n * ```typescript\n * if (isRelationRef(value)) {\n * const relInfo = value[RELATION_META];\n * }\n * ```\n */\nexport function isRelationRef(\n\tvalue: unknown,\n): value is RelationRef<string, unknown, RelationType> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tBRAND in value &&\n\t\t(value as Record<symbol, unknown>)[BRAND] === 'RelationRef'\n\t);\n}\n\n/**\n * Type guard to check if a value is an AllColumns.\n *\n * @param value - The value to check\n * @returns True if the value is an AllColumns\n *\n * @example\n * ```typescript\n * if (isAllColumns(value)) {\n * const tableName = value[TABLE_META];\n * }\n * ```\n */\nexport function isAllColumns(\n\tvalue: unknown,\n): value is AllColumns<string, Record<string, unknown>> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tBRAND in value &&\n\t\t(value as Record<symbol, unknown>)[BRAND] === 'AllColumns'\n\t);\n}\n\n/**\n * Type guard to check if a value is an AliasedColumn.\n *\n * @param value - The value to check\n * @returns True if the value is an AliasedColumn\n */\nexport function isAliasedColumn(\n\tvalue: unknown,\n): value is AliasedColumn<string, string, unknown, string> {\n\treturn isColumnRef(value) && '_alias' in value;\n}\n","/**\n * @fileoverview Runtime factory for creating TableRef, ColumnRef, and RelationRef objects.\n *\n * This module creates the runtime representations of the type-safe table references.\n * It uses ES6 Symbols for metadata and Proxies for lazy property access.\n *\n * @module table-ref-factory\n * @since DX-040\n */\n\nimport type { ModelIR } from '../model-ir.js';\nimport { getLogger } from './logger.js';\nimport {\n\tBRAND,\n\tCOLUMN_META,\n\tRELATION_META,\n\tRELATION_PATH,\n\ttype RelationType,\n\tTABLE_META,\n} from './table-ref.js';\n\n// ============================================================================\n// JS Reserved Words (H-03)\n// ============================================================================\n\n/**\n * JavaScript reserved words and built-in properties that might conflict\n * with column names. When accessed, these are intercepted by the Proxy\n * and a warning is logged.\n */\nconst JS_RESERVED_WORDS = new Set([\n\t// Object built-ins\n\t'constructor',\n\t'prototype',\n\t'__proto__',\n\t'hasOwnProperty',\n\t'isPrototypeOf',\n\t'propertyIsEnumerable',\n\t'toLocaleString',\n\t'toString',\n\t'valueOf',\n\t// Function built-ins\n\t'arguments',\n\t'caller',\n\t'callee',\n\t'length',\n\t'name',\n\t// Common JS keywords used as identifiers\n\t'class',\n\t'default',\n\t'delete',\n\t'export',\n\t'extends',\n\t'import',\n\t'new',\n\t'return',\n\t'super',\n\t'switch',\n\t'this',\n\t'throw',\n\t'typeof',\n]);\n\n/**\n * Log a warning when a reserved word is used as a column name.\n * This is ERR-05 from the spec.\n */\nfunction warnReservedWord(tableName: string, columnName: string): void {\n\tgetLogger().warn(\n\t\t`[dbsp] Warning: Column \"${columnName}\" in table \"${tableName}\" is a JavaScript reserved word. ` +\n\t\t\t`Access it via bracket notation: table['${columnName}']`,\n\t);\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Create a ColumnRef object with Symbol metadata.\n *\n * @param tableName - The table name\n * @param columnName - The column name\n * @param relationPath - Optional relation path for cross-table queries (DX-040 Block 7)\n * @returns A ColumnRef-like object with Symbol properties\n */\nexport function createColumnRef(\n\ttableName: string,\n\tcolumnName: string,\n\trelationPath?: readonly string[],\n): object {\n\tconst columnRef: Record<symbol | string, unknown> = {\n\t\t[TABLE_META]: tableName,\n\t\t[COLUMN_META]: columnName,\n\t\t[BRAND]: 'ColumnRef' as const,\n\t\t_type: undefined as unknown, // Phantom type placeholder\n\t\tas(alias: string) {\n\t\t\t// Validate alias (ERR-04)\n\t\t\tif (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(alias)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid alias \"${alias}\": must match /^[a-zA-Z_][a-zA-Z0-9_]*$/`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...this,\n\t\t\t\t_alias: alias,\n\t\t\t};\n\t\t},\n\t};\n\n\t// Add relation path if provided (for cross-table queries)\n\tif (relationPath && relationPath.length > 0) {\n\t\tcolumnRef[RELATION_PATH] = relationPath;\n\t}\n\n\treturn columnRef;\n}\n\n/**\n * Create an AllColumns object for SELECT * operations.\n *\n * @param tableName - The table name\n * @returns An AllColumns-like object\n */\nexport function createAllColumns(tableName: string): object {\n\treturn {\n\t\t[TABLE_META]: tableName,\n\t\t[BRAND]: 'AllColumns' as const,\n\t\t_columns: {}, // Phantom type placeholder\n\t};\n}\n\n/**\n * Map ModelIR RelationType to table-ref RelationType.\n */\nfunction mapRelationType(modelRelationType: string): RelationType {\n\tswitch (modelRelationType) {\n\t\tcase 'belongsTo':\n\t\t\treturn 'belongsTo';\n\t\tcase 'hasMany':\n\t\tcase 'belongsToMany':\n\t\t\treturn 'hasMany';\n\t\tcase 'hasOne':\n\t\t\treturn 'hasOne';\n\t\tdefault:\n\t\t\treturn 'hasMany'; // Default fallback\n\t}\n}\n\n/**\n * Helper to check if a column exists in a table.\n */\nfunction hasColumn(\n\tcolumns: readonly { name: string }[],\n\tcolumnName: string,\n): boolean {\n\treturn columns.some((col) => col.name === columnName);\n}\n\n/**\n * Helper to get column names from a table.\n */\nfunction getColumnNames(columns: readonly { name: string }[]): string[] {\n\treturn columns.map((col) => col.name);\n}\n\n/**\n * Create a RelationRef object with column access via Proxy.\n *\n * @param targetTable - The target table name\n * @param relationType - The relation type (belongsTo, hasMany, hasOne)\n * @param model - The ModelIR for looking up target table columns\n * @param relationName - The name of the relation (for building relation path)\n * @param parentPath - The parent relation path (for chained relations like users.posts.comments)\n * @returns A RelationRef-like object with Proxy for column access\n */\nexport function createRelationRef(\n\ttargetTable: string,\n\trelationType: RelationType,\n\tmodel: ModelIR,\n\trelationName?: string,\n\tparentPath?: readonly string[],\n): object {\n\t// Build the current relation path\n\tconst currentPath: readonly string[] =\n\t\trelationName !== undefined\n\t\t\t? [...(parentPath ?? []), relationName]\n\t\t\t: (parentPath ?? []);\n\n\tconst base = {\n\t\t[RELATION_META]: { target: targetTable, type: relationType },\n\t\t[BRAND]: 'RelationRef' as const,\n\t\t[RELATION_PATH]: currentPath, // Store path on RelationRef too\n\t\t_type: undefined as unknown, // Phantom type placeholder\n\t};\n\n\t// Use Proxy for lazy column access on the relation\n\treturn new Proxy(base, {\n\t\tget(target, prop, receiver) {\n\t\t\t// Handle Symbol properties\n\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\t// Handle '*' wildcard\n\t\t\tif (prop === '*') {\n\t\t\t\treturn createAllColumns(targetTable);\n\t\t\t}\n\n\t\t\t// Handle built-in properties\n\t\t\tif (prop in target) {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\t// Check if this is a column in the target table\n\t\t\tconst targetTableIR = model.getTable(targetTable);\n\t\t\tif (targetTableIR && hasColumn(targetTableIR.columns, prop as string)) {\n\t\t\t\t// Pass the relation path for cross-table query support\n\t\t\t\treturn createColumnRef(targetTable, prop as string, currentPath);\n\t\t\t}\n\n\t\t\t// Check if this is a relation from the target table (chained relations)\n\t\t\tfor (const rel of model.getRelationsFrom(targetTable)) {\n\t\t\t\tif (rel.name === prop) {\n\t\t\t\t\treturn createRelationRef(\n\t\t\t\t\t\trel.target,\n\t\t\t\t\t\tmapRelationType(rel.type),\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tprop as string,\n\t\t\t\t\t\tcurrentPath,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check inverse relations\n\t\t\tfor (const rel of model.getRelationsTo(targetTable)) {\n\t\t\t\tif (rel.source === prop) {\n\t\t\t\t\treturn createRelationRef(\n\t\t\t\t\t\trel.source,\n\t\t\t\t\t\t'hasMany',\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tprop as string,\n\t\t\t\t\t\tcurrentPath,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Return undefined for non-existent properties\n\t\t\treturn undefined;\n\t\t},\n\t\thas(target, prop) {\n\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\treturn prop in target;\n\t\t\t}\n\t\t\tif (prop === '*') {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tconst targetTableIR = model.getTable(targetTable);\n\t\t\treturn (\n\t\t\t\tprop in target ||\n\t\t\t\t(targetTableIR !== undefined &&\n\t\t\t\t\thasColumn(targetTableIR.columns, prop as string))\n\t\t\t);\n\t\t},\n\t\townKeys(target) {\n\t\t\tconst targetTableIR = model.getTable(targetTable);\n\t\t\tconst columnNames = targetTableIR\n\t\t\t\t? getColumnNames(targetTableIR.columns)\n\t\t\t\t: [];\n\t\t\treturn [...Reflect.ownKeys(target), '*', ...columnNames];\n\t\t},\n\t\tgetOwnPropertyDescriptor(target, prop) {\n\t\t\tconst self = this as ProxyHandler<typeof base>;\n\t\t\tif (\n\t\t\t\tprop === '*' ||\n\t\t\t\t(typeof prop === 'string' && self.has?.(target, prop))\n\t\t\t) {\n\t\t\t\treturn {\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tvalue: self.get?.(target, prop, target),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn Reflect.getOwnPropertyDescriptor(target, prop);\n\t\t},\n\t});\n}\n\n/**\n * Create a TableRef object with columns and relations via Proxy.\n *\n * @param tableName - The table name\n * @param model - The ModelIR containing table and relation information\n * @returns A TableRef-like object with Proxy for lazy property access\n */\nexport function createTableRef(tableName: string, model: ModelIR): object {\n\tconst tableIR = model.getTable(tableName);\n\tif (!tableIR) {\n\t\tthrow new Error(`Table \"${tableName}\" not found in model`);\n\t}\n\n\tconst base = {\n\t\t[TABLE_META]: tableName,\n\t\t[BRAND]: 'TableRef' as const,\n\t};\n\n\t// Build relations map: relation name -> { targetTable, relationType }\n\t// Include both direct relations (from this table) and inverse relations (to this table)\n\tconst relations = new Map<string, { target: string; type: RelationType }>();\n\n\t// Direct relations (belongsTo) - where this table is the source\n\tfor (const relation of model.getRelationsFrom(tableName)) {\n\t\tconst relationType = mapRelationType(relation.type);\n\t\trelations.set(relation.name, {\n\t\t\ttarget: relation.target,\n\t\t\ttype: relationType,\n\t\t});\n\t}\n\n\t// Inverse relations (hasMany/hasOne) - where this table is the target\n\tfor (const relation of model.getRelationsTo(tableName)) {\n\t\t// Skip if the relation is from this table to itself (would be handled above)\n\t\tif (relation.source === tableName) continue;\n\n\t\t// Derive inverse relation name: use explicit inverse option or default to source table name\n\t\t// The inverse name should be on the relation itself if specified\n\t\tconst inverseName = relation.source; // Default: source table name (e.g., 'posts')\n\n\t\t// Only add if not already present (direct relations take precedence)\n\t\tif (!relations.has(inverseName)) {\n\t\t\t// Inverse of belongsTo is hasMany (or hasOne if the FK is unique, but we default to hasMany)\n\t\t\trelations.set(inverseName, { target: relation.source, type: 'hasMany' });\n\t\t}\n\t}\n\n\t// Track which reserved words have been warned about\n\tconst warnedReservedWords = new Set<string>();\n\n\treturn new Proxy(base, {\n\t\tget(target, prop, receiver) {\n\t\t\t// Handle Symbol properties\n\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\t// Handle '*' wildcard (H-02)\n\t\t\tif (prop === '*') {\n\t\t\t\treturn createAllColumns(tableName);\n\t\t\t}\n\n\t\t\t// Handle built-in properties\n\t\t\tif (prop in target) {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\tconst propStr = prop as string;\n\n\t\t\t// Check for JS reserved words (H-03, ERR-05)\n\t\t\tif (JS_RESERVED_WORDS.has(propStr)) {\n\t\t\t\t// Check if it's actually a column\n\t\t\t\tif (hasColumn(tableIR.columns, propStr)) {\n\t\t\t\t\tif (!warnedReservedWords.has(propStr)) {\n\t\t\t\t\t\twarnReservedWord(tableName, propStr);\n\t\t\t\t\t\twarnedReservedWords.add(propStr);\n\t\t\t\t\t}\n\t\t\t\t\treturn createColumnRef(tableName, propStr);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if this is a column\n\t\t\tif (hasColumn(tableIR.columns, propStr)) {\n\t\t\t\treturn createColumnRef(tableName, propStr);\n\t\t\t}\n\n\t\t\t// Check if this is a relation\n\t\t\tconst relation = relations.get(propStr);\n\t\t\tif (relation) {\n\t\t\t\t// Pass relation name for building relation path (DX-040 Block 7)\n\t\t\t\treturn createRelationRef(\n\t\t\t\t\trelation.target,\n\t\t\t\t\trelation.type,\n\t\t\t\t\tmodel,\n\t\t\t\t\tpropStr,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Return undefined for non-existent properties\n\t\t\treturn undefined;\n\t\t},\n\t\thas(target, prop) {\n\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\treturn prop in target;\n\t\t\t}\n\t\t\tif (prop === '*') {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tconst propStr = prop as string;\n\t\t\treturn (\n\t\t\t\tprop in target ||\n\t\t\t\thasColumn(tableIR.columns, propStr) ||\n\t\t\t\trelations.has(propStr)\n\t\t\t);\n\t\t},\n\t\townKeys(target) {\n\t\t\tconst columnNames = getColumnNames(tableIR.columns);\n\t\t\tconst relationNames = Array.from(relations.keys());\n\t\t\treturn [\n\t\t\t\t...Reflect.ownKeys(target),\n\t\t\t\t'*',\n\t\t\t\t...columnNames,\n\t\t\t\t...relationNames,\n\t\t\t];\n\t\t},\n\t\tgetOwnPropertyDescriptor(target, prop) {\n\t\t\tconst self = this as ProxyHandler<typeof base>;\n\t\t\tif (\n\t\t\t\tprop === '*' ||\n\t\t\t\t(typeof prop === 'string' && self.has?.(target, prop))\n\t\t\t) {\n\t\t\t\treturn {\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tvalue: self.get?.(target, prop, target),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn Reflect.getOwnPropertyDescriptor(target, prop);\n\t\t},\n\t});\n}\n\n/**\n * Create the tables Proxy for a schema.\n *\n * This is the main entry point that creates a Proxy which lazily\n * instantiates TableRef objects when tables are accessed.\n *\n * @param model - The ModelIR containing all table and relation information\n * @param tableNames - List of table names in the schema\n * @returns A Proxy that returns TableRef objects for each table\n */\nexport function createTablesProxy(\n\tmodel: ModelIR,\n\ttableNames: string[],\n): object {\n\tconst tableSet = new Set(tableNames);\n\tconst cache = new Map<string, object>();\n\n\treturn new Proxy(\n\t\t{},\n\t\t{\n\t\t\tget(_target, prop) {\n\t\t\t\t// Handle Symbol properties\n\t\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst propStr = prop as string;\n\n\t\t\t\t// Return cached TableRef if exists\n\t\t\t\tif (cache.has(propStr)) {\n\t\t\t\t\treturn cache.get(propStr);\n\t\t\t\t}\n\n\t\t\t\t// Create TableRef if this is a valid table\n\t\t\t\tif (tableSet.has(propStr)) {\n\t\t\t\t\tconst tableRef = createTableRef(propStr, model);\n\t\t\t\t\tcache.set(propStr, tableRef);\n\t\t\t\t\treturn tableRef;\n\t\t\t\t}\n\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\thas(_target, prop) {\n\t\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn tableSet.has(prop as string);\n\t\t\t},\n\t\t\townKeys() {\n\t\t\t\treturn tableNames;\n\t\t\t},\n\t\t\tgetOwnPropertyDescriptor(_target, prop) {\n\t\t\t\tif (typeof prop === 'string' && tableSet.has(prop)) {\n\t\t\t\t\t// Get or create the TableRef\n\t\t\t\t\tlet tableRef = cache.get(prop);\n\t\t\t\t\tif (!tableRef) {\n\t\t\t\t\t\ttableRef = createTableRef(prop, model);\n\t\t\t\t\t\tcache.set(prop, tableRef);\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tconfigurable: true,\n\t\t\t\t\t\tenumerable: true,\n\t\t\t\t\t\tvalue: tableRef,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t},\n\t);\n}\n","/**\n * ARCH-005: Unified Schema API\n *\n * Replaces defineSchema(), TypedSchema, and GeneratedSchema with a single\n * schema() + ref() API. Relations are auto-inferred from FK declarations.\n *\n * @example\n * ```typescript\n * import { schema, ref } from '@dbsp/core';\n *\n * const db = schema({\n * users: { id: 'uuid', email: { type: 'text', unique: true } },\n * posts: { id: 'uuid', authorId: ref('users') },\n * });\n * ```\n */\n\nimport type { WhereIntent } from '@dbsp/types';\nimport type { Mutable } from '@dbsp/types/internal';\nimport type { DbCasing } from '../adapter.js';\nimport { ModelIRImpl } from '../model-impl.js';\nimport type {\n\tCheckConstraintIR,\n\tColumnIR,\n\tColumnType,\n\tForeignKeyIR,\n\tIndexIR,\n\tModelIR,\n\tOnDeleteAction,\n\tPseudoColumnMetadata,\n\tRelationIR,\n\tRelationType,\n\tTableIR,\n} from '../model-ir.js';\nimport { createPseudoColumnMetadata } from '../model-ir.js';\nimport type { InferTables } from './schema-tables-types.js';\nimport { createTablesProxy } from './table-ref-factory.js';\n\n// ============================================================================\n// Public Types\n// ============================================================================\n\n/**\n * Supported column types in schema definitions.\n * Maps to ColumnType from ModelIR.\n */\nexport type SchemaColumnType = ColumnType;\n\n/**\n * Column definition - short form (just type) or long form (with options).\n */\nexport type ColumnDef =\n\t| SchemaColumnType\n\t| {\n\t\t\ttype: SchemaColumnType;\n\t\t\tdbType?: string;\n\t\t\tnullable?: boolean;\n\t\t\tunique?: boolean;\n\t\t\tprimaryKey?: boolean;\n\t\t\tautoIncrement?: boolean;\n\t\t\tdefault?: unknown;\n\t\t\tindex?: boolean;\n\t };\n\n/**\n * Self-referential relation role names.\n * Required when declaring a ref() to the same table.\n */\nexport interface SelfRefRoles {\n\t/** Name for the direct parent relation (e.g., 'parent', 'manager') */\n\tparent: string;\n\t/** Name for the direct children relation (e.g., 'children', 'directReports') */\n\tchildren: string;\n\t/** Name for recursive ancestors (default: 'ancestors') */\n\tancestors?: string;\n\t/** Name for recursive descendants (default: 'descendants') */\n\tdescendants?: string;\n}\n\n/**\n * Options for ref() foreign key declarations.\n */\nexport interface RefOptions {\n\t// FK column constraints\n\t/** Is this FK nullable? → optional relation */\n\tnullable?: boolean;\n\t/** Is this FK unique? → 1:1 instead of 1:N */\n\tunique?: boolean;\n\n\t// FK behavior\n\t/** ON DELETE action */\n\tonDelete?: OnDeleteAction;\n\t/** ON UPDATE action */\n\tonUpdate?: 'CASCADE' | 'SET NULL' | 'RESTRICT' | 'NO ACTION';\n\n\t// Relation naming\n\t/** Local relation name (e.g., 'createdBy' for createdById column) */\n\tas?: string;\n\t/** Inverse relation name on target table (e.g., 'writings' instead of 'author_posts') */\n\tinverse?: string;\n\n\t// Self-ref only (MANDATORY when source === target)\n\t/** Role names for self-referential relations */\n\troles?: SelfRefRoles;\n\n\t/**\n\t * Source columns forming a composite FK (table-level `foreignKeys` only).\n\t */\n\tcolumns?: readonly string[];\n\n\t/**\n\t * Target columns the FK references.\n\t * - For column-level `ref()`: the target column on the referenced\n\t * table. Defaults to `['id']` by convention; the actual target\n\t * PK column is not auto-resolved. Length must be exactly 1.\n\t * - For table-level composite FKs: the list of target columns.\n\t */\n\treferences?: readonly string[];\n}\n\n/**\n * Marker type for ref() declarations in schema.\n * Generic over target and options to preserve literal types for inference.\n * @internal\n */\nexport interface RefDefinition<\n\tTTarget extends string = string,\n\tTOptions extends RefOptions = RefOptions,\n> {\n\treadonly __brand: 'ref';\n\treadonly target: TTarget;\n\treadonly options: TOptions;\n}\n\n/**\n * Table definition - a record of column names to column or ref definitions.\n */\nexport type TableDef = Record<string, ColumnDef | RefDefinition>;\n\n/**\n * Schema definition - a record of table names to table definitions.\n */\nexport type SchemaDefinition = Record<string, TableDef>;\n\n/**\n * Table-level constraints for composite indexes and foreign keys.\n * Used as the 2nd argument to schema() for constraints that span multiple columns.\n *\n * @example\n * ```typescript\n * schema({\n * orderItems: {\n * orderId: 'uuid',\n * productId: 'uuid',\n * quantity: 'integer',\n * },\n * }, {\n * orderItems: {\n * indexes: [\n * { columns: ['orderId', 'productId'], unique: true },\n * ],\n * foreignKeys: [\n * ref('orders', { columns: ['orderId', 'productId'], references: ['orderId', 'productId'] }),\n * ],\n * },\n * });\n * ```\n */\nexport interface SchemaIndexOptions {\n\t/** Columns included in the index */\n\tcolumns: string[];\n\t/** Whether this is a unique index */\n\tunique?: boolean;\n\t/** Custom index name (auto-generated if not provided) */\n\tname?: string;\n\t/** Index access method (default: btree). E.g. 'gin', 'gist', 'hnsw', 'bm25' */\n\tmethod?: string;\n\t/** Partial index predicate (WHERE clause) */\n\twhere?: string;\n\t/** Per-column operator class overrides. Key = column name, value = opclass name */\n\topclass?: Record<string, string>;\n\t/** Index storage parameters (WITH clause). Key = param name, value = param value */\n\twith?: Record<string, string>;\n}\n\nexport interface SchemaTableOptions {\n\t/** Indexes for this table (simple, composite, partial, GIN, HNSW, BM25, etc.) */\n\tindexes?: SchemaIndexOptions[];\n\t/** CHECK constraints for this table */\n\tcheckConstraints?: Array<{\n\t\tname: string;\n\t\texpression: string;\n\t}>;\n\t/** Composite foreign keys for this table (use ref() with columns/references) */\n\tforeignKeys?: RefDefinition[];\n}\n\n/**\n * Per-table constraint options, keyed by table name.\n */\nexport type SchemaConstraints = Record<string, SchemaTableOptions>;\n\n/**\n * Top-level schema-wide DDL objects: extensions, sequences.\n */\nexport interface SchemaExtras {\n\t/** PostgreSQL extensions to ensure (CREATE EXTENSION IF NOT EXISTS \"name\") */\n\textensions?: string[];\n\t/** Sequences to create (CREATE SEQUENCE). Key = sequence name */\n\tsequences?: Record<\n\t\tstring,\n\t\t{\n\t\t\tstartWith?: number;\n\t\t\tincrementBy?: number;\n\t\t\tminValue?: number;\n\t\t\tmaxValue?: number;\n\t\t\tcycle?: boolean;\n\t\t}\n\t>;\n}\n\n/**\n * Result of schema() function with strongly-typed table/column info.\n */\n/**\n * Per-table default filters applied to all queries.\n * Commonly used for soft delete filtering.\n *\n * @example\n * ```typescript\n * import { isNull } from '@dbsp/core';\n *\n * const db = schema(tables, undefined, {\n * defaultFilters: {\n * products: isNull('deletedAt'),\n * users: isNull('deletedAt'),\n * },\n * });\n * ```\n */\nexport type DefaultFilters = Record<string, WhereIntent>;\n\n/**\n * Options for schema() function.\n */\nexport interface SchemaOptions {\n\t/**\n\t * Default filters applied automatically to all queries per table.\n\t * Override with `.withoutDefaultFilters()` on the query builder.\n\t */\n\tdefaultFilters?: DefaultFilters;\n\t/**\n\t * Column name treated as the implicit primary key for short-form column\n\t * declarations. When set (default `'id'`), `inferPrimaryKey` resolves the\n\t * implicit PK BEFORE falling back to FK columns: a column matching this name\n\t * is treated as the PK whenever no explicit `primaryKey: true` flag is present\n\t * on any column — regardless of whether the table also has FK columns.\n\t *\n\t * Default: `'id'` (matches existing codebase convention).\n\t *\n\t * Set to `null` to disable the implicit-PK convention entirely. Primary\n\t * keys must then be declared explicitly with `primaryKey: true` (or are\n\t * inferred from FK columns for junction tables). Empty string (`''`) and\n\t * whitespace-only strings are rejected eagerly at `schema()` time\n\t * (before any per-table processing) with a `SchemaValidationError`.\n\t *\n\t * Match the adapter's `defaultPkColumnName` if your project uses a\n\t * different naming scheme (e.g. `'pk_uuid'`).\n\t *\n\t * @remarks\n\t * `inferPrimaryKey` resolves PKs in this order:\n\t * 1. Explicit `primaryKey: true` on column(s)\n\t * 2. Column matching `defaultPkColumnName` (this option) — skipped when set to `null`\n\t * 3. FK columns (composite, for junction tables — applies regardless of this option)\n\t * 4. No primary key\n\t *\n\t * @example\n\t * // Default — 'id' is implicit PK\n\t * schema({ users: { id: 'uuid' } });\n\t *\n\t * // Custom convention\n\t * schema({ users: { pk_uuid: 'uuid' } }, undefined, { defaultPkColumnName: 'pk_uuid' });\n\t *\n\t * // Strict — no implicit PK convention\n\t * schema({ users: { id: 'uuid' } }, undefined, { defaultPkColumnName: null });\n\t * // ↑ no PK declared — FKs targeting users.id will fail validation.\n\t */\n\tdefaultPkColumnName?: string | null;\n}\n\nexport interface Schema<T extends SchemaDefinition> {\n\t/** The raw schema definition */\n\treadonly definition: T;\n\t/** Converted ModelIR for use with ORM */\n\treadonly model: ModelIR;\n\t/** Table names */\n\treadonly tableNames: (keyof T)[];\n\t/**\n\t * Type-safe table references for query building.\n\t *\n\t * Provides typed access to tables, columns, and relations:\n\t * - `schema.tables.users` returns a TableRef with typed columns\n\t * - `schema.tables.users.id` returns a ColumnRef\n\t * - `schema.tables.users.posts` returns a RelationRef (if relation exists)\n\t * - `schema.tables.users['*']` returns AllColumns for SELECT *\n\t *\n\t * @example\n\t * ```typescript\n\t * const { users, posts } = schema.tables;\n\t *\n\t * // Type-safe column access\n\t * users.id // ColumnRef<'users', 'id', string>\n\t * users.name // ColumnRef<'users', 'name', string>\n\t *\n\t * // Type-safe relation access\n\t * users.posts // RelationRef<'posts', Post[], 'hasMany'>\n\t *\n\t * // Wildcard for SELECT *\n\t * users['*'] // AllColumns<'users', {...}>\n\t * ```\n\t *\n\t * @since DX-040\n\t */\n\treadonly tables: InferTables<T>;\n\t/**\n\t * DB column casing — describes what casing the database uses.\n\t * @see DbCasing\n\t */\n\treadonly dbCasing?: DbCasing;\n\t/**\n\t * Timestamp when this schema was introspected from the database.\n\t * Only present for schemas created via getSchemaFromDb().\n\t * Useful for detecting schema drift.\n\t */\n\treadonly introspectedAt?: Date;\n\t/**\n\t * Default filters per table (e.g., soft delete filtering).\n\t * Applied automatically to all queries unless `.withoutDefaultFilters()` is called.\n\t */\n\treadonly defaultFilters?: DefaultFilters;\n}\n\n// ============================================================================\n// Type Inference Helpers\n// ============================================================================\n\n/**\n * JSON-compatible value type for json/jsonb columns.\n */\nexport type JsonValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| JsonValue[]\n\t| { [key: string]: JsonValue };\n\n/**\n * Range value type for PostgreSQL range types.\n */\nexport interface InferredRangeValue<T> {\n\treadonly start: T | null;\n\treadonly end: T | null;\n\treadonly startInclusive?: boolean;\n\treadonly endInclusive?: boolean;\n}\n\n/**\n * Maps a ColumnType string to its TypeScript type.\n */\nexport type InferColumnType<T extends SchemaColumnType> =\n\t// String types\n\tT extends 'string' | 'text' | 'uuid'\n\t\t? string\n\t\t: // Numeric types\n\t\t\tT extends 'number' | 'integer' | 'decimal'\n\t\t\t? number\n\t\t\t: // BigInt\n\t\t\t\tT extends 'bigint'\n\t\t\t\t? bigint\n\t\t\t\t: // Boolean\n\t\t\t\t\tT extends 'boolean'\n\t\t\t\t\t? boolean\n\t\t\t\t\t: // Date/time types\n\t\t\t\t\t\tT extends 'date' | 'time' | 'datetime' | 'timestamp'\n\t\t\t\t\t\t? Date\n\t\t\t\t\t\t: // JSON types\n\t\t\t\t\t\t\tT extends 'json' | 'jsonb'\n\t\t\t\t\t\t\t? JsonValue\n\t\t\t\t\t\t\t: // PostgreSQL range types\n\t\t\t\t\t\t\t\tT extends 'daterange'\n\t\t\t\t\t\t\t\t? InferredRangeValue<Date>\n\t\t\t\t\t\t\t\t: T extends 'tsrange' | 'tstzrange'\n\t\t\t\t\t\t\t\t\t? InferredRangeValue<Date>\n\t\t\t\t\t\t\t\t\t: T extends 'int4range' | 'int8range'\n\t\t\t\t\t\t\t\t\t\t? InferredRangeValue<number>\n\t\t\t\t\t\t\t\t\t\t: T extends 'numrange'\n\t\t\t\t\t\t\t\t\t\t\t? InferredRangeValue<number>\n\t\t\t\t\t\t\t\t\t\t\t: // Fallback\n\t\t\t\t\t\t\t\t\t\t\t\tunknown;\n\n/**\n * Extracts the type string from a ColumnDef (handles short and long forms).\n */\ntype ExtractColumnType<C extends ColumnDef> = C extends SchemaColumnType\n\t? C\n\t: C extends { type: infer T extends SchemaColumnType }\n\t\t? T\n\t\t: never;\n\n/**\n * Checks if a ColumnDef is nullable.\n */\ntype IsNullable<C extends ColumnDef> = C extends { nullable: true }\n\t? true\n\t: false;\n\n/**\n * Infers the TypeScript type for a single column definition.\n * Handles both short form ('string') and long form ({ type: 'string', nullable: true }).\n */\nexport type InferColumn<C extends ColumnDef> =\n\tIsNullable<C> extends true\n\t\t? InferColumnType<ExtractColumnType<C>> | null\n\t\t: InferColumnType<ExtractColumnType<C>>;\n\n/**\n * Infers the FK column type from a RefDefinition.\n *\n * ⚠️ **Limitation:** FK columns are typed as `number | string` because inferring\n * the target PK type at compile time would require resolving cross-table references,\n * which creates circular type dependencies in TypeScript.\n *\n * **Why not infer from target table?**\n * Given `ref('users')`, we'd need to:\n * 1. Find `users` table in the schema\n * 2. Find column with `primaryKey: true`\n * 3. Get its type\n *\n * This creates circular refs when tables reference each other (A→B→A).\n *\n * **Pragmatic trade-off:** `number | string` covers 99% of PKs (auto-increment int or UUID).\n *\n * @example\n * authorId: ref('users') // Type: number | string\n * editorId: ref('users', { nullable: true }) // Type: number | string | null\n */\nexport type InferRefColumn<R extends RefDefinition> = R extends {\n\toptions: { nullable: true };\n}\n\t? number | string | null\n\t: number | string;\n\n/**\n * Infers the row type for a single table definition.\n * Maps each column to its TypeScript type.\n */\nexport type InferRow<T extends TableDef> = {\n\t[K in keyof T]: T[K] extends RefDefinition\n\t\t? InferRefColumn<T[K]>\n\t\t: T[K] extends ColumnDef\n\t\t\t? InferColumn<T[K]>\n\t\t\t: unknown;\n};\n\n/**\n * Infers the complete database type from a schema definition.\n * Maps each table name to its row type.\n *\n * @example\n * ```typescript\n * const mySchema = schema({\n * users: { id: 'integer', email: 'string', bio: { type: 'text', nullable: true } },\n * posts: { id: 'integer', title: 'string', authorId: ref('users') },\n * });\n *\n * type DB = InferDB<typeof mySchema.definition>;\n * // DB = {\n * // users: { id: number; email: string; bio: string | null };\n * // posts: { id: number; title: string; authorId: number | string };\n * // }\n * ```\n */\nexport type InferDB<S extends SchemaDefinition> = {\n\t[TableName in keyof S]: InferRow<S[TableName]>;\n};\n\n/**\n * Helper type to extract the inferred DB type from a Schema instance.\n */\nexport type InferSchemaDB<S extends Schema<SchemaDefinition>> =\n\tS extends Schema<infer T> ? InferDB<T> : never;\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Declares a foreign key reference to another table.\n *\n * @param target - Target table name (must exist in schema)\n * @param options - Optional FK constraints and relation naming\n * @returns RefDefinition for use in table definitions\n *\n * @example\n * ```typescript\n * // Simple FK (1:N)\n * authorId: ref('users')\n *\n * // Optional FK\n * editorId: ref('users', { nullable: true })\n *\n * // 1:1 relation (unique FK)\n * userId: ref('users', { unique: true })\n *\n * // Custom naming\n * createdById: ref('users', { as: 'createdBy', inverse: 'createdDocuments' })\n *\n * // Self-ref (requires roles)\n * parentId: ref('categories', { roles: { parent: 'parent', children: 'children' } })\n * ```\n */\nexport function ref<\n\tTTarget extends string,\n\tTOptions extends RefOptions = Record<string, never>,\n>(target: TTarget, options?: TOptions): RefDefinition<TTarget, TOptions> {\n\treturn {\n\t\t__brand: 'ref',\n\t\ttarget,\n\t\toptions: (options ?? {}) as TOptions,\n\t};\n}\n\n/**\n * Type guard for RefDefinition.\n */\nexport function isRef(\n\tvalue: ColumnDef | RefDefinition,\n): value is RefDefinition {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'__brand' in value &&\n\t\tvalue.__brand === 'ref'\n\t);\n}\n\n/**\n * Creates a type-safe schema definition and converts it to ModelIR.\n *\n * @param definition - Schema definition with tables and columns\n * @returns Schema object with definition, model, and table names\n *\n * @example\n * ```typescript\n * const db = schema({\n * users: {\n * id: 'uuid',\n * email: { type: 'text', unique: true },\n * },\n * posts: {\n * id: 'uuid',\n * title: 'text',\n * authorId: ref('users'),\n * },\n * });\n *\n * // Use with ORM\n * const orm = createOrm({ model: db.model, adapter });\n * ```\n */\nexport function schema<T extends SchemaDefinition>(\n\tdefinition: T,\n\tconstraints?: SchemaConstraints,\n\toptions?: SchemaOptions,\n\textras?: SchemaExtras,\n): Schema<T> {\n\t// Validate and convert to ModelIR\n\tconst model = schemaToModelIR(definition, constraints, extras, options);\n\tconst tableNames = Object.keys(definition) as (keyof T)[];\n\n\t// Validate default filters reference existing tables\n\tconst defaultFilters = options?.defaultFilters;\n\tif (defaultFilters) {\n\t\tconst tableNameSet = new Set(tableNames as string[]);\n\t\tfor (const tableName of Object.keys(defaultFilters)) {\n\t\t\tif (!tableNameSet.has(tableName)) {\n\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t`Default filter for non-existent table '${tableName}'. ` +\n\t\t\t\t\t\t`Available: ${[...tableNameSet].join(', ')}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Create type-safe tables proxy (DX-040)\n\tconst tables = createTablesProxy(\n\t\tmodel,\n\t\ttableNames as string[],\n\t) as InferTables<T>;\n\n\treturn {\n\t\tdefinition,\n\t\tmodel,\n\t\ttableNames,\n\t\ttables,\n\t\t...(defaultFilters ? { defaultFilters } : {}),\n\t};\n}\n\n// ============================================================================\n// Conversion to ModelIR\n// ============================================================================\n\n/**\n * Validation error during schema conversion.\n */\nexport class SchemaValidationError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly table?: string,\n\t\tpublic readonly column?: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'SchemaValidationError';\n\t}\n}\n\n/**\n * Converts a schema definition to ModelIR.\n *\n * @internal\n */\nexport function schemaToModelIR(\n\tdefinition: SchemaDefinition,\n\tconstraints?: SchemaConstraints,\n\textras?: SchemaExtras,\n\toptions?: SchemaOptions,\n): ModelIR {\n\t// R6-L1: fail-fast before any per-table work. Empty / whitespace-only\n\t// defaultPkColumnName is rejected here (once) rather than per-table in\n\t// inferPrimaryKey, because the error is a schema-level misconfiguration\n\t// and should be reported at the earliest possible point.\n\tif (\n\t\ttypeof options?.defaultPkColumnName === 'string' &&\n\t\toptions.defaultPkColumnName.trim().length === 0\n\t) {\n\t\tthrow new SchemaValidationError(\n\t\t\t`defaultPkColumnName cannot be an empty or whitespace-only string. Pass null to disable the implicit-PK convention or omit the option for the default 'id'.`,\n\t\t);\n\t}\n\n\tconst tableNames = Object.keys(definition);\n\n\t// Phase 1: Validate refs point to existing tables (existence + roles only)\n\tvalidateRefs(definition, tableNames);\n\n\t// Phase 2: Collect all refs and validate constraints\n\tconst refsByTable = collectRefs(definition);\n\n\t// Phase 3: Build tables (columns, PKs, FKs, indexes) — inferPrimaryKey runs here\n\tconst tables = buildTables(\n\t\tdefinition,\n\t\trefsByTable,\n\t\ttableNames,\n\t\tconstraints,\n\t\toptions,\n\t);\n\n\t// Phase 3.5: Validate FK targets exist and are referenceable (post-build, uses resolved PKs)\n\tvalidateFkTargets(tables);\n\n\t// Phase 4: Build relations from refs\n\tconst relations = buildRelations(definition, refsByTable, tableNames);\n\n\t// Phase 5: Build ModelIR\n\tconst tableMap = new Map<string, TableIR>();\n\tfor (const table of tables) {\n\t\ttableMap.set(table.name, table);\n\t}\n\n\tconst relationMap = new Map<string, RelationIR>();\n\tfor (const relation of relations) {\n\t\tconst qualifiedName = `${relation.source}.${relation.name}`;\n\t\trelationMap.set(qualifiedName, relation);\n\t}\n\n\t// Phase 6: Build extras (extensions, sequences)\n\tconst extensions = extras?.extensions;\n\tconst sequenceMap = extras?.sequences\n\t\t? new Map(\n\t\t\t\tObject.entries(extras.sequences).map(([name, seq]) => [\n\t\t\t\t\tname,\n\t\t\t\t\t{ name, ...seq },\n\t\t\t\t]),\n\t\t\t)\n\t\t: undefined;\n\n\treturn new ModelIRImpl(\n\t\ttableMap,\n\t\trelationMap,\n\t\tundefined,\n\t\textensions,\n\t\tsequenceMap,\n\t);\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\nfunction validateRefs(\n\tdefinition: SchemaDefinition,\n\ttableNames: string[],\n): void {\n\tconst tableSet = new Set(tableNames);\n\n\tfor (const [tableName, tableDef] of Object.entries(definition)) {\n\t\tfor (const [columnName, columnDef] of Object.entries(tableDef)) {\n\t\t\tif (isRef(columnDef)) {\n\t\t\t\t// Check target exists\n\t\t\t\tif (!tableSet.has(columnDef.target)) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Foreign key '${columnName}' references non-existent table '${columnDef.target}'`,\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\tcolumnName,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Self-ref requires roles\n\t\t\t\tif (columnDef.target === tableName && !columnDef.options.roles) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Self-referential FK '${columnName}' must have 'roles' option with parent/children names`,\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\tcolumnName,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Roles only valid for self-ref\n\t\t\t\tif (columnDef.target !== tableName && columnDef.options.roles) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`'roles' option is only valid for self-referential FKs, but '${columnName}' references '${columnDef.target}'`,\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\tcolumnName,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * PostgreSQL UNIQUE constraints only support btree and hash index methods.\n * Other methods (gin, gist, brin, spgist, hnsw, bm25, etc.) cannot enforce\n * uniqueness and therefore cannot back a foreign key target column.\n * Treat undefined as 'btree' (the PostgreSQL default).\n */\nconst UNIQUE_CAPABLE_INDEX_METHODS = new Set(['btree', 'hash']);\n\n/**\n * Validates FK target columns exist and are referenceable.\n *\n * For ALL FKs (single-column and composite):\n * - Source and target column counts must match.\n * - Every referenced column must exist on the target table.\n *\n * For single-column FKs only (the case `buildRefColumn` produces where both\n * `fk.columns.length === 1` AND `fk.references.columns.length === 1`):\n * - Referenced column must be referenceable: singleton primary key,\n * column-level `unique: true`, or a single-column UNIQUE index declared\n * via SchemaConstraints covering exactly the referenced column with no\n * partial-index `WHERE` clause, no expression columns, and using a\n * uniqueness-capable index method (btree or hash).\n * - Mirrors PostgreSQL error 42830 (\"there is no unique constraint matching\n * given keys for referenced table\") at schema()-time instead of at DDL\n * apply time.\n *\n * Composite PK members alone do not qualify as referenceable (matches PG strict\n * semantics): a column that is part of a composite PK still needs an explicit\n * UNIQUE constraint to be the target of an FK.\n */\nfunction validateFkTargets(tables: readonly TableIR[]): void {\n\tconst tableMap = new Map(tables.map((t) => [t.name, t]));\n\n\tfor (const table of tables) {\n\t\tfor (const fk of table.foreignKeys) {\n\t\t\tconst target = tableMap.get(fk.references.table);\n\t\t\t// Defensive: column-level FKs are pre-validated by validateRefs (Phase 1),\n\t\t\t// but table-level constraints.foreignKeys bypass that — so this gate is\n\t\t\t// the only barrier against constraint-based FKs to non-existent tables.\n\t\t\t// Throw rather than skip silently.\n\t\t\tif (!target) {\n\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t`Foreign key in '${table.name}' references non-existent table '${fk.references.table}'`,\n\t\t\t\t\ttable.name,\n\t\t\t\t\tfk.columns[0],\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// R4-1: Source-column existence — guard against constraint-level FKs that\n\t\t\t// declare `columns: [...]` referencing local columns that don't exist on\n\t\t\t// the source table. Column-level FKs (via buildRefColumn) can't trigger\n\t\t\t// this because the source column IS the column being declared, but\n\t\t\t// SchemaConstraints.foreignKeys does not validate this elsewhere.\n\t\t\tfor (const srcCol of fk.columns) {\n\t\t\t\tif (!table.columns.some((c) => c.name === srcCol)) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Foreign key in '${table.name}' uses non-existent source column '${srcCol}'`,\n\t\t\t\t\t\ttable.name,\n\t\t\t\t\t\tsrcCol,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Validate column counts. Zero-length arrays on either side are malformed\n\t\t\t// and should be flagged here rather than silently passed to PG.\n\t\t\tif (fk.columns.length === 0 || fk.references.columns.length === 0) {\n\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t`Foreign key in '${table.name}' has zero-length \\`columns\\` or \\`references\\` array`,\n\t\t\t\t\ttable.name,\n\t\t\t\t\tfk.columns[0],\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// R6-3a: source and target column counts must match for ALL FKs (composite included).\n\t\t\t// PostgreSQL requires a 1-to-1 mapping between source and referenced columns.\n\t\t\tif (fk.columns.length !== fk.references.columns.length) {\n\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t`Foreign key in '${table.name}' has mismatched column counts: ` +\n\t\t\t\t\t\t`${fk.columns.length} source column(s) but ${fk.references.columns.length} referenced column(s)`,\n\t\t\t\t\ttable.name,\n\t\t\t\t\tfk.columns[0],\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// R6-3b: every referenced column must exist on the target table — applies to ALL FKs.\n\t\t\tfor (const refCol of fk.references.columns) {\n\t\t\t\tif (!target.columns.some((c) => c.name === refCol)) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Foreign key in '${table.name}' references non-existent column '${target.name}.${refCol}'`,\n\t\t\t\t\t\ttable.name,\n\t\t\t\t\t\tfk.columns[0],\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Uniqueness check is single-column-only — composites left to PostgreSQL.\n\t\t\tif (fk.columns.length !== 1 || fk.references.columns.length !== 1)\n\t\t\t\tcontinue;\n\n\t\t\tfor (const refCol of fk.references.columns) {\n\t\t\t\t// Existence already validated by R6-3b above for all FKs — targetCol is guaranteed defined here.\n\t\t\t\tconst targetCol = target.columns.find((c) => c.name === refCol);\n\t\t\t\tif (!targetCol) continue; // defensive\n\t\t\t\t// Uniqueness — a column is referenceable when any of the following holds:\n\t\t\t\t// 1. It is the table's singleton resolved primaryKey (covers explicit column-level PK,\n\t\t\t\t// table-level singleton PK, and the implicit-id convention resolved by inferPrimaryKey).\n\t\t\t\t// 2. It has explicit `unique: true`.\n\t\t\t\t// 3. It is the sole column of a non-partial, non-expression single-column UNIQUE index\n\t\t\t\t// declared via SchemaConstraints (partial indexes with a WHERE clause, or expression\n\t\t\t\t// indexes, do NOT make a column referenceable — PG error 42830).\n\t\t\t\t// Members of a composite PK alone do not qualify (matches PG strict semantics).\n\t\t\t\tconst isSingletonPk =\n\t\t\t\t\ttypeof target.primaryKey === 'string' && target.primaryKey === refCol;\n\t\t\t\tconst isUnique = targetCol.unique === true;\n\t\t\t\t// R2-F2: PG only allows UNIQUE constraints on btree/hash indexes —\n\t\t\t\t// gin/gist/brin/spgist/hnsw/bm25 cannot enforce uniqueness even when\n\t\t\t\t// `unique: true` is declared. Fail at schema() time instead of DDL apply.\n\t\t\t\tconst isUniqueIndex =\n\t\t\t\t\ttarget.indexes?.some((idx) => {\n\t\t\t\t\t\tconst method = idx.method ?? 'btree';\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\tidx.unique === true &&\n\t\t\t\t\t\t\tidx.columns.length === 1 &&\n\t\t\t\t\t\t\tidx.columns[0] === refCol &&\n\t\t\t\t\t\t\tidx.where === undefined &&\n\t\t\t\t\t\t\t(idx.expressions === undefined || idx.expressions.length === 0) &&\n\t\t\t\t\t\t\tUNIQUE_CAPABLE_INDEX_METHODS.has(method)\n\t\t\t\t\t\t);\n\t\t\t\t\t}) ?? false;\n\t\t\t\tif (!isSingletonPk && !isUnique && !isUniqueIndex) {\n\t\t\t\t\t// R2-F1: tailor the remediation hint based on the target's PK shape.\n\t\t\t\t\t// - composite PK (string[]): no single PK column to target; suggest\n\t\t\t\t\t// marking unique or using a table-level composite FK.\n\t\t\t\t\t// - resolved single PK (string): point at the existing PK column.\n\t\t\t\t\t// - no PK at all: suggest the defaultPkColumnName convention.\n\t\t\t\t\tconst isCompositePk = Array.isArray(target.primaryKey);\n\t\t\t\t\tconst hasSingleResolvedPk = typeof target.primaryKey === 'string';\n\t\t\t\t\tconst suggestion = isCompositePk\n\t\t\t\t\t\t? `Either mark '${target.name}.${refCol}' with \\`unique: true\\` or add a single-column unique index via SchemaConstraints — '${target.name}' has a composite primary key, so a single-column FK cannot target the PK directly (use a table-level composite FK referencing all PK columns if that is the intent).`\n\t\t\t\t\t\t: hasSingleResolvedPk\n\t\t\t\t\t\t\t? `Either mark the target column with \\`unique: true\\`, add a single-column unique index via SchemaConstraints, or change the FK to target the existing primary key column '${target.primaryKey as string}'.`\n\t\t\t\t\t\t\t: `Either mark the target column with \\`unique: true\\`, add a single-column unique index via SchemaConstraints, or — if '${refCol}' is your primary-key column convention — pass \\`{ defaultPkColumnName: '${refCol}' }\\` as the third argument to \\`schema()\\` (or omit the option entirely if '${refCol}' is 'id').`;\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Foreign key in '${table.name}' targets '${target.name}.${refCol}' which is neither primary key nor unique. ${suggestion}`,\n\t\t\t\t\t\ttable.name,\n\t\t\t\t\t\tfk.columns[0],\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Collected ref info for a table.\n */\ninterface CollectedRef {\n\tcolumnName: string;\n\ttarget: string;\n\toptions: RefOptions;\n\tlocalRelation: string; // Derived relation name\n\tinverseRelation: string; // Derived inverse relation name\n}\n\n/**\n * Collects refs per table and validates multi-FK constraints.\n */\nfunction collectRefs(\n\tdefinition: SchemaDefinition,\n): Map<string, CollectedRef[]> {\n\tconst refsByTable = new Map<string, CollectedRef[]>();\n\n\tfor (const [tableName, tableDef] of Object.entries(definition)) {\n\t\tconst refs: CollectedRef[] = [];\n\t\tconst refsByTarget = new Map<string, string[]>(); // target -> column names\n\n\t\tfor (const [columnName, columnDef] of Object.entries(tableDef)) {\n\t\t\tif (isRef(columnDef)) {\n\t\t\t\t// Track refs by target for multi-FK validation\n\t\t\t\tconst existing = refsByTarget.get(columnDef.target) || [];\n\t\t\t\texisting.push(columnName);\n\t\t\t\trefsByTarget.set(columnDef.target, existing);\n\n\t\t\t\t// Derive relation names\n\t\t\t\tconst localRelation = deriveLocalRelation(\n\t\t\t\t\tcolumnName,\n\t\t\t\t\tcolumnDef.options,\n\t\t\t\t);\n\t\t\t\tconst inverseRelation = deriveInverseRelation(\n\t\t\t\t\tlocalRelation,\n\t\t\t\t\ttableName,\n\t\t\t\t\tcolumnDef.options,\n\t\t\t\t\tcolumnDef.target === tableName,\n\t\t\t\t);\n\n\t\t\t\trefs.push({\n\t\t\t\t\tcolumnName,\n\t\t\t\t\ttarget: columnDef.target,\n\t\t\t\t\toptions: columnDef.options,\n\t\t\t\t\tlocalRelation,\n\t\t\t\t\tinverseRelation,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Validate multi-FK to same table requires explicit naming\n\t\tfor (const [target, columns] of refsByTarget) {\n\t\t\tif (columns.length > 1 && target !== tableName) {\n\t\t\t\t// Multiple FKs to same non-self table - all must have 'as'\n\t\t\t\tfor (const columnName of columns) {\n\t\t\t\t\tconst ref = refs.find((r) => r.columnName === columnName);\n\t\t\t\t\tif (ref && !ref.options.as) {\n\t\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t\t`Multiple FKs to '${target}' require explicit 'as' naming. Column '${columnName}' has no 'as' option.`,\n\t\t\t\t\t\t\ttableName,\n\t\t\t\t\t\t\tcolumnName,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check for duplicate relation names within this table\n\t\tconst seenRelations = new Set<string>();\n\t\tfor (const ref of refs) {\n\t\t\tif (ref.options.roles) {\n\t\t\t\t// Self-ref - check all role names\n\t\t\t\tconst roles = ref.options.roles;\n\t\t\t\tconst allNames = [\n\t\t\t\t\troles.parent,\n\t\t\t\t\troles.children,\n\t\t\t\t\troles.ancestors || 'ancestors',\n\t\t\t\t\troles.descendants || 'descendants',\n\t\t\t\t];\n\t\t\t\tfor (const name of allNames) {\n\t\t\t\t\tif (seenRelations.has(name)) {\n\t\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t\t`Duplicate relation name '${name}'`,\n\t\t\t\t\t\t\ttableName,\n\t\t\t\t\t\t\tref.columnName,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tseenRelations.add(name);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (seenRelations.has(ref.localRelation)) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Duplicate relation name '${ref.localRelation}'`,\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\tref.columnName,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tseenRelations.add(ref.localRelation);\n\t\t\t}\n\t\t}\n\n\t\trefsByTable.set(tableName, refs);\n\t}\n\n\treturn refsByTable;\n}\n\n// ============================================================================\n// Naming Derivation\n// ============================================================================\n\n/**\n * Derives local relation name from column name.\n * authorId -> author, user_id -> user\n */\nfunction deriveLocalRelation(columnName: string, options: RefOptions): string {\n\tif (options.as) {\n\t\treturn options.as;\n\t}\n\n\t// Remove 'Id' suffix (camelCase)\n\tif (columnName.endsWith('Id')) {\n\t\treturn columnName.slice(0, -2);\n\t}\n\n\t// Remove '_id' suffix (snake_case - shouldn't happen but handle it)\n\tif (columnName.endsWith('_id')) {\n\t\treturn columnName.slice(0, -3);\n\t}\n\n\t// Fallback: use column name as-is\n\treturn columnName;\n}\n\n/**\n * Derives inverse relation name.\n * Default pattern: {localRelation}_{tableName}\n */\nfunction deriveInverseRelation(\n\tlocalRelation: string,\n\tsourceTable: string,\n\toptions: RefOptions,\n\tisSelfRef: boolean,\n): string {\n\t// Self-ref doesn't use standard inverse naming\n\tif (isSelfRef) {\n\t\treturn ''; // Handled via roles\n\t}\n\n\tif (options.inverse) {\n\t\treturn options.inverse;\n\t}\n\n\t// Pattern: author -> author_posts (for source table 'posts')\n\treturn `${localRelation}_${sourceTable}`;\n}\n\n// ============================================================================\n// Table Building\n// ============================================================================\n\n/**\n * Returns the ColumnType of the primary key in the target table definition.\n * Falls back to 'uuid' if the target is not found or has no explicit PK.\n */\nfunction getTargetPkType(\n\tdefinition: SchemaDefinition,\n\ttarget: string,\n): ColumnType {\n\tconst targetDef = definition[target];\n\tif (!targetDef) return 'uuid';\n\n\tfor (const [, colDef] of Object.entries(targetDef)) {\n\t\tif (isRef(colDef)) continue;\n\t\tconst def = normalizeColumnDef(colDef);\n\t\tif (def.primaryKey) return def.type;\n\t}\n\n\tif ('id' in targetDef) {\n\t\tconst idDef = targetDef.id;\n\t\tif (idDef && !isRef(idDef)) return normalizeColumnDef(idDef).type;\n\t}\n\treturn 'uuid';\n}\n\n/**\n * Returns the ColumnType for a specific named column in a target table definition.\n * Used by buildRefColumn to derive the source column type when `references` points\n * to a non-PK unique column. Falls back to `undefined` when the column is not found\n * or is itself a ref (chain case handled by getTargetPkType).\n */\nfunction getReferencedColumnType(\n\ttargetDef: TableDef,\n\treferencedCol: string,\n\tdefinition?: SchemaDefinition,\n\tvisited?: Set<string>,\n): ColumnType | undefined {\n\tconst colDef = targetDef[referencedCol];\n\tif (!colDef) return undefined;\n\tif (isRef(colDef)) {\n\t\t// R6-5 (chained ref): follow the chain to resolve the final concrete type.\n\t\t// Guard against cycles and runaway chains with a visited-key accumulator.\n\t\tif (!definition) return undefined;\n\t\tconst chainedTableName = colDef.target;\n\t\tconst chainedTargetDef = definition[chainedTableName];\n\t\tif (!chainedTargetDef) return undefined;\n\t\t// The chained ref's referenced column: options.references[0] ?? 'id'\n\t\tconst chainedRefCols = colDef.options.references;\n\t\tconst firstChainedRefCol =\n\t\t\tchainedRefCols && chainedRefCols.length === 1\n\t\t\t\t? chainedRefCols[0]\n\t\t\t\t: undefined;\n\t\tconst chainedRefCol: string = firstChainedRefCol ?? 'id';\n\t\t// Visited key uniquely identifies the (tableDef, column) pair in the chain.\n\t\tconst visitedKey = `${chainedTableName}.${chainedRefCol}`;\n\t\tconst seen = visited ?? new Set<string>();\n\t\tif (seen.has(visitedKey)) return undefined; // cycle detected\n\t\tseen.add(visitedKey);\n\t\treturn getReferencedColumnType(\n\t\t\tchainedTargetDef,\n\t\t\tchainedRefCol,\n\t\t\tdefinition,\n\t\t\tseen,\n\t\t);\n\t}\n\treturn normalizeColumnDef(colDef).type;\n}\n\n/**\n * Builds a FK column + ForeignKeyIR pair from a ref definition.\n */\nfunction buildRefColumn(\n\tcolumnName: string,\n\tcolumnDef: RefDefinition,\n\tdefinition: SchemaDefinition,\n): { col: ColumnIR; fk: ForeignKeyIR } {\n\t// R5-1: When options.references specifies a single target column, derive the\n\t// source column type from THAT column's type rather than the target's PK type.\n\t// This prevents a type mismatch when the FK points at a unique non-PK column\n\t// that has a different type than the table's PK (e.g. email:string vs id:uuid).\n\tconst targetDef = definition[columnDef.target];\n\tconst targetCol =\n\t\tcolumnDef.options.references?.length === 1\n\t\t\t? columnDef.options.references[0]\n\t\t\t: undefined;\n\tconst inferredType =\n\t\ttargetCol && targetDef\n\t\t\t? (getReferencedColumnType(targetDef, targetCol, definition) ??\n\t\t\t\tgetTargetPkType(definition, columnDef.target))\n\t\t\t: getTargetPkType(definition, columnDef.target);\n\tconst col: Mutable<ColumnIR> = {\n\t\tname: columnName,\n\t\ttype: inferredType,\n\t\tnullable: columnDef.options.nullable ?? false,\n\t};\n\tif (columnDef.options.unique) col.unique = true;\n\n\tif (\n\t\tcolumnDef.options.references &&\n\t\tcolumnDef.options.references.length !== 1\n\t) {\n\t\tthrow new SchemaValidationError(\n\t\t\t`FK column '${columnName}' got 'references' with ${columnDef.options.references.length} columns; column-level FK requires exactly one target column (use table-level foreignKeys for composite FKs).`,\n\t\t);\n\t}\n\tconst fk: Mutable<ForeignKeyIR> = {\n\t\tcolumns: [columnName],\n\t\treferences: {\n\t\t\ttable: columnDef.target,\n\t\t\tcolumns: columnDef.options.references ?? ['id'],\n\t\t},\n\t};\n\tif (columnDef.options.onDelete) fk.onDelete = columnDef.options.onDelete;\n\tif (columnDef.options.onUpdate) fk.onUpdate = columnDef.options.onUpdate;\n\n\treturn { col: col as ColumnIR, fk: fk as ForeignKeyIR };\n}\n\n/**\n * Builds a regular ColumnIR from a normalized column definition.\n */\nfunction buildRegularColumn(\n\tcolumnName: string,\n\tcolumnDef: ColumnDef,\n): { col: ColumnIR; isPk: boolean } {\n\tconst def = normalizeColumnDef(columnDef);\n\tconst col: Mutable<ColumnIR> = {\n\t\tname: columnName,\n\t\ttype: def.type,\n\t\tnullable: def.nullable ?? false,\n\t};\n\tif (def.dbType?.trim()) col.originalDbType = def.dbType.trim();\n\tif (def.unique) col.unique = def.unique;\n\tif (def.autoIncrement) col.autoIncrement = def.autoIncrement;\n\tif (def.default !== undefined) col.default = def.default;\n\treturn { col: col as ColumnIR, isPk: def.primaryKey ?? false };\n}\n\n/**\n * Builds columns, foreign keys, and explicit primary key list for a table.\n */\nfunction buildColumnsForTable(\n\t_tableName: string,\n\ttableDef: TableDef,\n\tdefinition: SchemaDefinition,\n): { columns: ColumnIR[]; foreignKeys: ForeignKeyIR[]; primaryKey: string[] } {\n\tconst columns: ColumnIR[] = [];\n\tconst foreignKeys: ForeignKeyIR[] = [];\n\tconst primaryKey: string[] = [];\n\n\tfor (const [columnName, columnDef] of Object.entries(tableDef)) {\n\t\tif (isRef(columnDef)) {\n\t\t\tconst { col, fk } = buildRefColumn(columnName, columnDef, definition);\n\t\t\tcolumns.push(col);\n\t\t\tforeignKeys.push(fk);\n\t\t} else {\n\t\t\tconst { col, isPk } = buildRegularColumn(columnName, columnDef);\n\t\t\tcolumns.push(col);\n\t\t\tif (isPk) primaryKey.push(columnName);\n\t\t}\n\t}\n\treturn { columns, foreignKeys, primaryKey };\n}\n\n/**\n * Infers the final primary key from explicit declarations, the implicit-PK name\n * convention, or FK columns (for junction tables).\n *\n * Resolution order:\n * 1. Explicit `primaryKey: true` on column(s)\n * 2. Column matching `defaultPkColumnName` (options.defaultPkColumnName) — skipped\n * when set to `null` (strict mode)\n * 3. FK columns (composite PK for junction tables — applies regardless of option)\n * 4. No primary key\n */\nfunction inferPrimaryKey(\n\tprimaryKey: string[],\n\tforeignKeys: ForeignKeyIR[],\n\tcolumns: ColumnIR[],\n\toptions?: { defaultPkColumnName?: string | null },\n): string | readonly string[] | undefined {\n\tif (primaryKey.length > 0) {\n\t\treturn primaryKey.length === 1 ? (primaryKey[0] as string) : primaryKey;\n\t}\n\t// Implicit PK convention BEFORE FK fallback. Honoured unless explicitly\n\t// disabled with `defaultPkColumnName: null`. Empty/whitespace-only strings\n\t// are rejected at schemaToModelIR() time (R6-L1 guard fires before this runs).\n\tconst pkColName =\n\t\toptions?.defaultPkColumnName === undefined\n\t\t\t? 'id'\n\t\t\t: options.defaultPkColumnName;\n\tif (pkColName !== null && columns.some((c) => c.name === pkColName)) {\n\t\treturn pkColName;\n\t}\n\t// FK fallback for junction tables (applies regardless of the option above).\n\tconst fkColumns = foreignKeys.flatMap((fk) => fk.columns);\n\tif (fkColumns.length > 0) {\n\t\treturn fkColumns.length === 1 ? fkColumns[0] : fkColumns;\n\t}\n\treturn undefined;\n}\n\n/**\n * Builds pseudo-columns for self-referential FKs with roles.\n */\nfunction buildPseudoColumns(\n\ttableName: string,\n\trefsByTable: Map<string, CollectedRef[]>,\n\tfinalPk: string | readonly string[] | undefined,\n): PseudoColumnMetadata[] {\n\tconst pseudoColumns: PseudoColumnMetadata[] = [];\n\tconst refs = refsByTable.get(tableName) ?? [];\n\tconst pkColumn =\n\t\ttypeof finalPk === 'string' ? finalPk : (finalPk?.[0] ?? 'id');\n\n\tfor (const ref of refs) {\n\t\tif (ref.options.roles && ref.target === tableName) {\n\t\t\tpseudoColumns.push(\n\t\t\t\tcreatePseudoColumnMetadata(\n\t\t\t\t\ttableName,\n\t\t\t\t\tref.columnName,\n\t\t\t\t\tpkColumn,\n\t\t\t\t\tref.options.roles.parent,\n\t\t\t\t\tref.options.roles.children,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn pseudoColumns;\n}\n\n/**\n * Builds IndexIR entries from column-level `index: true` declarations.\n */\nfunction buildColumnIndexes(tableName: string, tableDef: TableDef): IndexIR[] {\n\tconst indexes: IndexIR[] = [];\n\tfor (const [columnName, columnDef] of Object.entries(tableDef)) {\n\t\tif (isRef(columnDef)) continue;\n\t\tconst def = normalizeColumnDef(columnDef);\n\t\tif (def.index) {\n\t\t\tindexes.push({\n\t\t\t\tname: `idx_${tableName}_${columnName}`,\n\t\t\t\tcolumns: [columnName],\n\t\t\t\tunique: false,\n\t\t\t});\n\t\t}\n\t}\n\treturn indexes;\n}\n\n/**\n * Processes table-level constraints (indexes, CHECK constraints, composite FKs).\n */\nfunction buildTableConstraints(\n\ttableName: string,\n\tconstraints: SchemaConstraints | undefined,\n): {\n\textraIndexes: IndexIR[];\n\tcheckConstraints: CheckConstraintIR[];\n\textraForeignKeys: ForeignKeyIR[];\n} {\n\tconst extraIndexes: IndexIR[] = [];\n\tconst checkConstraints: CheckConstraintIR[] = [];\n\tconst extraForeignKeys: ForeignKeyIR[] = [];\n\n\tconst tableConstraints = constraints?.[tableName];\n\tif (!tableConstraints) {\n\t\treturn { extraIndexes, checkConstraints, extraForeignKeys };\n\t}\n\n\tif (tableConstraints.indexes) {\n\t\tfor (const idx of tableConstraints.indexes) {\n\t\t\tconst indexIR: Mutable<IndexIR> = {\n\t\t\t\tname: idx.name ?? `idx_${tableName}_${idx.columns.join('_')}`,\n\t\t\t\tcolumns: idx.columns,\n\t\t\t\tunique: idx.unique ?? false,\n\t\t\t};\n\t\t\tif (idx.method) indexIR.method = idx.method;\n\t\t\tif (idx.where) indexIR.where = idx.where;\n\t\t\tif (idx.opclass) indexIR.opclass = idx.opclass;\n\t\t\tif (idx.with) indexIR.with = idx.with;\n\t\t\textraIndexes.push(indexIR as IndexIR);\n\t\t}\n\t}\n\n\tif (tableConstraints.checkConstraints) {\n\t\tfor (const chk of tableConstraints.checkConstraints) {\n\t\t\tcheckConstraints.push({\n\t\t\t\tname: chk.name,\n\t\t\t\texpression: `CHECK (${chk.expression})`,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (tableConstraints.foreignKeys) {\n\t\tfor (const fkRef of tableConstraints.foreignKeys) {\n\t\t\tif (!fkRef.options.columns?.length) {\n\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t`Composite FK on \"${tableName}\" → \"${fkRef.target}\" requires 'columns' option`,\n\t\t\t\t\ttableName,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst fk: Mutable<ForeignKeyIR> = {\n\t\t\t\tcolumns: [...fkRef.options.columns],\n\t\t\t\treferences: {\n\t\t\t\t\ttable: fkRef.target,\n\t\t\t\t\tcolumns: fkRef.options.references\n\t\t\t\t\t\t? [...fkRef.options.references]\n\t\t\t\t\t\t: ['id'],\n\t\t\t\t},\n\t\t\t};\n\t\t\tif (fkRef.options.onDelete) fk.onDelete = fkRef.options.onDelete;\n\t\t\textraForeignKeys.push(fk as ForeignKeyIR);\n\t\t}\n\t}\n\n\treturn { extraIndexes, checkConstraints, extraForeignKeys };\n}\n\n/**\n * Builds TableIR objects from schema definition.\n */\nfunction buildTables(\n\tdefinition: SchemaDefinition,\n\trefsByTable: Map<string, CollectedRef[]>,\n\ttableNames: string[],\n\tconstraints?: SchemaConstraints,\n\toptions?: SchemaOptions,\n): TableIR[] {\n\tconst tables: TableIR[] = [];\n\n\tfor (const tableName of tableNames) {\n\t\tconst tableDef = definition[tableName];\n\t\tif (!tableDef) continue;\n\n\t\tconst { columns, foreignKeys, primaryKey } = buildColumnsForTable(\n\t\t\ttableName,\n\t\t\ttableDef,\n\t\t\tdefinition,\n\t\t);\n\t\tconst finalPk = inferPrimaryKey(primaryKey, foreignKeys, columns, options);\n\t\tconst pseudoColumns = buildPseudoColumns(tableName, refsByTable, finalPk);\n\t\tconst columnIndexes = buildColumnIndexes(tableName, tableDef);\n\t\tconst { extraIndexes, checkConstraints, extraForeignKeys } =\n\t\t\tbuildTableConstraints(tableName, constraints);\n\n\t\tconst table: TableIR = {\n\t\t\tname: tableName,\n\t\t\tcolumns,\n\t\t\t...(finalPk !== undefined ? { primaryKey: finalPk } : {}),\n\t\t\tforeignKeys: [...foreignKeys, ...extraForeignKeys],\n\t\t\tindexes: [...columnIndexes, ...extraIndexes],\n\t\t\t...(checkConstraints.length > 0 ? { checkConstraints } : {}),\n\t\t\t...(pseudoColumns.length > 0 ? { pseudoColumns } : {}),\n\t\t};\n\t\ttables.push(table);\n\t}\n\n\treturn tables;\n}\n\n/**\n * Normalizes column definition to object form.\n */\nfunction normalizeColumnDef(def: ColumnDef): {\n\ttype: SchemaColumnType;\n\tdbType?: string;\n\tnullable?: boolean;\n\tunique?: boolean;\n\tprimaryKey?: boolean;\n\tautoIncrement?: boolean;\n\tdefault?: unknown;\n\tindex?: boolean;\n} {\n\tif (typeof def === 'string') {\n\t\treturn { type: def };\n\t}\n\treturn def;\n}\n\n// ============================================================================\n// Relation Building\n// ============================================================================\n\n/**\n * Builds RelationIR objects from collected refs.\n */\nfunction buildRelations(\n\t_definition: SchemaDefinition,\n\trefsByTable: Map<string, CollectedRef[]>,\n\ttableNames: string[],\n): RelationIR[] {\n\tconst relations: RelationIR[] = [];\n\n\tfor (const tableName of tableNames) {\n\t\tconst refs = refsByTable.get(tableName) || [];\n\n\t\tfor (const ref of refs) {\n\t\t\tif (ref.options.roles) {\n\t\t\t\t// Self-referential - generate 4 relations\n\t\t\t\tconst roles = ref.options.roles;\n\n\t\t\t\t// 1. Direct parent (belongsTo)\n\t\t\t\trelations.push({\n\t\t\t\t\tname: roles.parent,\n\t\t\t\t\ttype: 'belongsTo',\n\t\t\t\t\tsource: tableName,\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: 'one',\n\t\t\t\t\toptionality: ref.options.nullable ? 'optional' : 'required',\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t});\n\n\t\t\t\t// 2. Direct children (hasMany)\n\t\t\t\trelations.push({\n\t\t\t\t\tname: roles.children,\n\t\t\t\t\ttype: 'hasMany',\n\t\t\t\t\tsource: tableName,\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: 'many',\n\t\t\t\t\toptionality: 'optional', // Children are always optional\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t});\n\n\t\t\t\t// 3. Recursive ancestors (hasMany with recursive metadata)\n\t\t\t\tconst ancestorsName = roles.ancestors || 'ancestors';\n\t\t\t\trelations.push({\n\t\t\t\t\tname: ancestorsName,\n\t\t\t\t\ttype: 'hasMany',\n\t\t\t\t\tsource: tableName,\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: 'many',\n\t\t\t\t\toptionality: 'optional',\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t\trecursive: {\n\t\t\t\t\t\tdirection: 'up',\n\t\t\t\t\t\tmaxDepth: 10,\n\t\t\t\t\t\tthrough: roles.parent,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\t// 4. Recursive descendants (hasMany with recursive metadata)\n\t\t\t\tconst descendantsName = roles.descendants || 'descendants';\n\t\t\t\trelations.push({\n\t\t\t\t\tname: descendantsName,\n\t\t\t\t\ttype: 'hasMany',\n\t\t\t\t\tsource: tableName,\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: 'many',\n\t\t\t\t\toptionality: 'optional',\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t\trecursive: {\n\t\t\t\t\t\tdirection: 'down',\n\t\t\t\t\t\tmaxDepth: 10,\n\t\t\t\t\t\tthrough: roles.children,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Standard relation - generate belongsTo and inverse hasMany/hasOne\n\t\t\t\tconst isUnique = ref.options.unique ?? false;\n\n\t\t\t\t// 1. belongsTo from source to target\n\t\t\t\trelations.push({\n\t\t\t\t\tname: ref.localRelation,\n\t\t\t\t\ttype: 'belongsTo',\n\t\t\t\t\tsource: tableName,\n\t\t\t\t\ttarget: ref.target,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: 'one',\n\t\t\t\t\toptionality: ref.options.nullable ? 'optional' : 'required',\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t});\n\n\t\t\t\t// 2. Inverse relation from target to source\n\t\t\t\tconst inverseType: RelationType = isUnique ? 'hasOne' : 'hasMany';\n\t\t\t\tconst inverseCardinality = isUnique ? 'one' : 'many';\n\n\t\t\t\trelations.push({\n\t\t\t\t\tname: ref.inverseRelation,\n\t\t\t\t\ttype: inverseType,\n\t\t\t\t\tsource: ref.target,\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: inverseCardinality,\n\t\t\t\t\toptionality: 'optional', // Inverse is always optional\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn relations;\n}\n\n// ============================================================================\n// Database Introspection → Schema\n// ============================================================================\n\n/**\n * Options for getSchemaFromDb.\n */\nexport interface GetSchemaFromDbOptions {\n\t/** Schema name to introspect (default: 'public' for PostgreSQL) */\n\treadonly schema?: string;\n\t/** Tables to include (default: all). */\n\treadonly tables?: readonly string[];\n\t/** Tables to exclude (glob patterns supported). */\n\treadonly exclude?: readonly string[];\n}\n\n/**\n * Map ColumnType from ModelIR to JS-friendly runtime type strings.\n * Used by getSchemaFromDb to create user-friendly schema definitions.\n *\n * Tests expect: 'serial/integer' → 'number', 'varchar/text' → 'string'\n */\nfunction columnTypeToJsType(type: ColumnType): SchemaColumnType {\n\tswitch (type) {\n\t\t// Numeric types → 'number' (includes integer, bigint, decimal)\n\t\tcase 'integer':\n\t\tcase 'bigint':\n\t\tcase 'decimal':\n\t\t\treturn 'number';\n\t\t// String types → 'string' (includes text, uuid)\n\t\tcase 'text':\n\t\tcase 'uuid':\n\t\t\treturn 'string';\n\t\t// All other types pass through as-is (they're valid SchemaColumnType)\n\t\tdefault:\n\t\t\treturn type;\n\t}\n}\n\n/**\n * Adapter interface for introspection.\n * Must have introspect() method and optionally dbCasing.\n */\ninterface IntrospectableAdapter {\n\treadonly dbCasing?: DbCasing;\n\tintrospect(options?: {\n\t\tschema?: string;\n\t\tinclude?: readonly string[];\n\t\texclude?: readonly string[];\n\t}): Promise<ModelIR & { introspectedAt?: Date }>;\n}\n\n/**\n * Create a Schema from database introspection.\n *\n * This function introspects the database schema and returns a Schema<T>\n * that can be used with createOrm().\n *\n * @example\n * ```typescript\n * const adapter = createPgsqlAdapter(pool);\n * const schema = await getSchemaFromDb(adapter, { schema: 'public' });\n * const orm = createOrm({ schema, adapter });\n * ```\n *\n * @param adapter - An adapter that implements introspect()\n * @param options - Introspection options (schema name, table filters)\n * @returns A Schema<T> with definition, model, and type-safe tables\n */\nexport async function getSchemaFromDb<\n\tT extends SchemaDefinition = SchemaDefinition,\n>(\n\tadapter: IntrospectableAdapter,\n\toptions?: GetSchemaFromDbOptions,\n): Promise<Schema<T>> {\n\t// Build introspection options, only including defined values\n\tconst introspectOptions: {\n\t\tschema?: string;\n\t\tinclude?: readonly string[];\n\t\texclude?: readonly string[];\n\t} = {};\n\tif (options?.schema !== undefined) introspectOptions.schema = options.schema;\n\tif (options?.tables !== undefined) introspectOptions.include = options.tables;\n\tif (options?.exclude !== undefined)\n\t\tintrospectOptions.exclude = options.exclude;\n\n\t// Call adapter introspection\n\tconst introspectionResult = await adapter.introspect(introspectOptions);\n\n\tconst model = introspectionResult;\n\tconst introspectedAt = introspectionResult.introspectedAt;\n\n\t// Build FK lookup: column name → target table\n\t// ForeignKeyIR uses columns[] array and references.table\n\tconst fkLookup = new Map<\n\t\tstring,\n\t\tMap<string, { target: string; nullable: boolean; unique: boolean }>\n\t>();\n\tfor (const table of model.tables.values()) {\n\t\tconst tableFks = new Map<\n\t\t\tstring,\n\t\t\t{ target: string; nullable: boolean; unique: boolean }\n\t\t>();\n\t\tfor (const fk of table.foreignKeys) {\n\t\t\t// Only handle single-column FKs for now (composite FKs are rare in schema defs)\n\t\t\tconst fkColumn = fk.columns[0];\n\t\t\tif (!fkColumn) continue;\n\n\t\t\t// Find the column to check nullable/unique\n\t\t\tconst column = table.columns.find((c) => c.name === fkColumn);\n\t\t\ttableFks.set(fkColumn, {\n\t\t\t\ttarget: fk.references.table,\n\t\t\t\tnullable: column?.nullable ?? true,\n\t\t\t\tunique: column?.unique ?? false,\n\t\t\t});\n\t\t}\n\t\tfkLookup.set(table.name, tableFks);\n\t}\n\n\t// Convert ModelIR to SchemaDefinition\n\tconst definition: Record<string, TableDef> = {};\n\n\tfor (const table of model.tables.values()) {\n\t\tconst tableDef: TableDef = {};\n\t\tconst tableFks = fkLookup.get(table.name) ?? new Map();\n\n\t\tfor (const column of table.columns) {\n\t\t\tconst fk = tableFks.get(column.name);\n\n\t\t\tif (fk) {\n\t\t\t\t// FK column → ref() definition\n\t\t\t\ttableDef[column.name] = ref(fk.target, {\n\t\t\t\t\tnullable: fk.nullable,\n\t\t\t\t\tunique: fk.unique,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Regular column → JS type\n\t\t\t\ttableDef[column.name] = columnTypeToJsType(column.type);\n\t\t\t}\n\t\t}\n\n\t\tdefinition[table.name] = tableDef;\n\t}\n\n\tconst tableNames = Object.keys(definition) as (keyof T)[];\n\n\t// Create type-safe tables proxy\n\tconst tables = createTablesProxy(\n\t\tmodel,\n\t\ttableNames as string[],\n\t) as InferTables<T>;\n\n\t// Build result with optional properties only if defined\n\tconst result: Mutable<Schema<T>> = {\n\t\tdefinition: definition as T,\n\t\tmodel,\n\t\ttableNames,\n\t\ttables,\n\t};\n\n\t// Add optional properties only if they have values\n\tif (adapter.dbCasing !== undefined) {\n\t\tresult.dbCasing = adapter.dbCasing;\n\t}\n\tif (introspectedAt !== undefined) {\n\t\tresult.introspectedAt = introspectedAt;\n\t}\n\n\treturn result as Schema<T>;\n}\n","/**\n * Schema Convention Inference\n *\n * Detects foreign keys and M:N relations using:\n * 1. Explicit `references` (highest priority)\n * 2. Convention patterns (fallback)\n *\n * M:N auto-detection: tables with exactly 2 FKs and no business columns.\n *\n * Migrated from @dbsp/schema/conventions.ts as part of ARCH-003.\n */\n\nimport type {\n\tSchemaBelongsToRelation,\n\tSchemaColumnDefinition,\n\tSchemaConventionsDefinition,\n\tSchemaHasManyRelation,\n\tSchemaManyToManyRelation,\n\tSchemaRelationsDefinition,\n\tSchemaTableDefinition,\n\tSchemaTablesDefinition,\n} from './schema-dsl-types.js';\n\n// =============================================================================\n// Default Conventions\n// =============================================================================\n\nexport const DEFAULT_CONVENTIONS: Required<SchemaConventionsDefinition> = {\n\tfkPattern: '{singular}Id',\n\tpluralize: true,\n\ttimestamps: ['createdAt', 'updatedAt'],\n\tfkAutoIndex: true,\n};\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Convert table name to singular form.\n * Simple heuristic: remove trailing 's' if present.\n */\n/**\n * Built-in mapping of irregular plural forms to their singular equivalents.\n * Import and extend this to handle domain-specific irregular plurals:\n *\n * ```ts\n * import { IRREGULAR_PLURALS, singularize } from '@dbsp/core';\n * const custom = { ...IRREGULAR_PLURALS, matrices: 'matrix', indices: 'index' };\n * singularize('matrices', custom); // 'matrix'\n * ```\n */\nexport const IRREGULAR_PLURALS: Record<string, string> = {\n\tpeople: 'person',\n\tchildren: 'child',\n\tmen: 'man',\n\twomen: 'woman',\n\tteeth: 'tooth',\n\tfeet: 'foot',\n\tgeese: 'goose',\n\tmice: 'mouse',\n\tdata: 'datum',\n\tmedia: 'medium',\n\tcriteria: 'criterion',\n\tphenomena: 'phenomenon',\n};\n\nexport function singularize(\n\tname: string,\n\toverrides?: Record<string, string>,\n): string {\n\tconst lower = name.toLowerCase();\n\n\t// Check user-provided overrides first\n\tif (overrides) {\n\t\tconst override = overrides[lower];\n\t\tif (override !== undefined) {\n\t\t\tif (name[0]?.toUpperCase() === name[0]) {\n\t\t\t\treturn override.charAt(0).toUpperCase() + override.slice(1);\n\t\t\t}\n\t\t\treturn override;\n\t\t}\n\t}\n\n\t// Check built-in irregular plurals\n\tconst irregular = IRREGULAR_PLURALS[lower];\n\tif (irregular !== undefined) {\n\t\t// Preserve original case pattern\n\t\tif (name[0]?.toUpperCase() === name[0]) {\n\t\t\treturn irregular.charAt(0).toUpperCase() + irregular.slice(1);\n\t\t}\n\t\treturn irregular;\n\t}\n\n\t// Handle 'ies' → 'y' (categories → category)\n\tif (lower.endsWith('ies') && name.length > 3) {\n\t\treturn `${name.slice(0, -3)}y`;\n\t}\n\n\t// Handle 'es' for words ending in -shes, -ches, -xes, -zes, -ses (boxes → box)\n\t// But NOT for -les, -res, -tes, etc. (profiles → profile, not profil)\n\tif (\n\t\tlower.endsWith('es') &&\n\t\tname.length > 2 &&\n\t\t(lower.endsWith('shes') ||\n\t\t\tlower.endsWith('ches') ||\n\t\t\tlower.endsWith('xes') ||\n\t\t\tlower.endsWith('zes') ||\n\t\t\t(lower.endsWith('ses') &&\n\t\t\t\t!lower.endsWith('ases') &&\n\t\t\t\t!lower.endsWith('uses')))\n\t) {\n\t\treturn name.slice(0, -2);\n\t}\n\n\t// Handle regular plurals ending in 's' (but not 'ss')\n\tif (lower.endsWith('s') && !lower.endsWith('ss') && name.length > 1) {\n\t\treturn name.slice(0, -1);\n\t}\n\n\t// Already singular or unknown pattern\n\treturn name;\n}\n\n/**\n * Convert table name to plural form.\n * Simple heuristic: add 's' or 'es' or 'ies'.\n */\nexport function pluralize(name: string): string {\n\tif (\n\t\tname.endsWith('y') &&\n\t\t!['ay', 'ey', 'oy', 'uy'].some((s) => name.endsWith(s))\n\t) {\n\t\treturn `${name.slice(0, -1)}ies`;\n\t}\n\tif (\n\t\tname.endsWith('s') ||\n\t\tname.endsWith('x') ||\n\t\tname.endsWith('ch') ||\n\t\tname.endsWith('sh')\n\t) {\n\t\treturn `${name}es`;\n\t}\n\treturn `${name}s`;\n}\n\n/**\n * Capitalize first letter.\n */\nexport function capitalize(name: string): string {\n\treturn name.charAt(0).toUpperCase() + name.slice(1);\n}\n\n/**\n * Decapitalize first letter.\n */\nexport function decapitalize(name: string): string {\n\treturn name.charAt(0).toLowerCase() + name.slice(1);\n}\n\n/**\n * Get the inverse relation name for a self-referential FK.\n * Special case: parent → children (most common hierarchy pattern).\n * Otherwise: pluralize the belongsTo name (manager → managers).\n */\nexport function getSelfRefInverseName(belongsToName: string): string {\n\t// The most common self-ref pattern\n\tif (belongsToName === 'parent') return 'children';\n\n\t// For other cases, just pluralize (manager → managers)\n\treturn pluralize(belongsToName);\n}\n\n/**\n * Pseudo-column metadata for a self-referential FK.\n * Exported for use by schema builder.\n */\ninterface SelfRefPseudoColumn {\n\t/** FK column name (e.g., 'parentId', 'managerId') */\n\tforeignKeyColumn: string;\n\t/** Target column (usually 'id') */\n\ttargetColumn: string;\n\t/** Parent role name (e.g., 'parent', 'manager') */\n\tparentRole: string;\n\t/** Child role name (e.g., 'children', 'subordinates') */\n\tchildRole: string;\n}\n\n/**\n * Extract pseudo-column metadata from detected FKs.\n * Only self-referential FKs produce pseudo-columns.\n */\nexport function extractSelfRefPseudoColumns(\n\ttableName: string,\n\tfks: DetectedFK[],\n): SelfRefPseudoColumn[] {\n\tconst selfRefFKs = fks.filter((fk) => fk.targetTable === tableName);\n\tif (selfRefFKs.length === 0) return [];\n\n\t// Single self-ref FK: use default parent/child keywords\n\t// Multiple self-ref FKs: require explicit roles (validated elsewhere)\n\treturn selfRefFKs.map((fk) => ({\n\t\tforeignKeyColumn: fk.column,\n\t\ttargetColumn: fk.targetColumn,\n\t\tparentRole: fk.parentRole ?? fk.inferredName,\n\t\tchildRole: fk.childRole ?? getSelfRefInverseName(fk.inferredName),\n\t}));\n}\n\n/**\n * Validate self-referential FK roles for a table.\n * Returns error messages if validation fails.\n */\nexport function validateSelfRefRoles(\n\ttableName: string,\n\tpseudoColumns: SelfRefPseudoColumn[],\n\treservedNames: Set<string> = new Set([\n\t\t'parent',\n\t\t'child',\n\t\t'ascendant',\n\t\t'descendant',\n\t]),\n): string[] {\n\tconst errors: string[] = [];\n\n\tif (pseudoColumns.length === 0) return errors;\n\n\t// Collect all role names for collision detection\n\tconst allRoles = new Set<string>();\n\n\tfor (const pc of pseudoColumns) {\n\t\t// Check reserved name collision (only for multi-FK tables)\n\t\tif (pseudoColumns.length > 1) {\n\t\t\tif (reservedNames.has(pc.parentRole)) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Table '${tableName}': parentRole '${pc.parentRole}' conflicts with reserved keyword. Use a custom role name.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (reservedNames.has(pc.childRole)) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Table '${tableName}': childRole '${pc.childRole}' conflicts with reserved keyword. Use a custom role name.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Check cross-collision between different FKs\n\t\tif (allRoles.has(pc.parentRole)) {\n\t\t\terrors.push(\n\t\t\t\t`Table '${tableName}': duplicate parentRole '${pc.parentRole}'. Each self-ref FK needs unique roles.`,\n\t\t\t);\n\t\t}\n\t\tif (allRoles.has(pc.childRole)) {\n\t\t\terrors.push(\n\t\t\t\t`Table '${tableName}': duplicate childRole '${pc.childRole}'. Each self-ref FK needs unique roles.`,\n\t\t\t);\n\t\t}\n\n\t\tallRoles.add(pc.parentRole);\n\t\tallRoles.add(pc.childRole);\n\t}\n\n\treturn errors;\n}\n\n// =============================================================================\n// FK Detection\n// =============================================================================\n\ninterface DetectedFK {\n\t/** Column name in source table */\n\tcolumn: string;\n\t/** Target table name */\n\ttargetTable: string;\n\t/** Inferred relation name (e.g., 'author' from 'authorId') */\n\tinferredName: string;\n\t/** Whether this was explicitly defined via `references` */\n\texplicit: boolean;\n\t/** Target column (from references.column or default 'id') */\n\ttargetColumn: string;\n\t/** Custom parent role for self-ref FKs (from parentRole or inferred) */\n\tparentRole?: string;\n\t/** Custom child role for self-ref FKs (from childRole or inferred) */\n\tchildRole?: string;\n}\n\n/**\n * Detect foreign keys in a table.\n * Priority: explicit `references` > convention pattern.\n */\nexport function detectForeignKeys(\n\ttableName: string,\n\ttable: SchemaTableDefinition,\n\tconventions: Required<SchemaConventionsDefinition>,\n\ttableNames: Set<string>,\n): DetectedFK[] {\n\tconst fks: DetectedFK[] = [];\n\tconst pattern = conventions.fkPattern;\n\n\tfor (const [colName, colDef] of Object.entries(table)) {\n\t\t// PRIORITY 1: Explicit `references` takes precedence\n\t\tif (colDef.references) {\n\t\t\tconst targetTable = colDef.references.table;\n\t\t\tif (tableNames.has(targetTable)) {\n\t\t\t\t// Infer relation name from column (remove 'Id' suffix if present)\n\t\t\t\tconst inferredName = colName.endsWith('Id')\n\t\t\t\t\t? colName.slice(0, -2)\n\t\t\t\t\t: singularize(targetTable);\n\n\t\t\t\tconst isSelfRef = targetTable === tableName;\n\t\t\t\tconst detectedFK: DetectedFK = {\n\t\t\t\t\tcolumn: colName,\n\t\t\t\t\ttargetTable,\n\t\t\t\t\tinferredName,\n\t\t\t\t\texplicit: true,\n\t\t\t\t\ttargetColumn: colDef.references.column ?? 'id',\n\t\t\t\t};\n\n\t\t\t\t// Add self-ref roles if applicable\n\t\t\t\tif (isSelfRef) {\n\t\t\t\t\tdetectedFK.parentRole = colDef.references.parentRole ?? inferredName;\n\t\t\t\t\tdetectedFK.childRole =\n\t\t\t\t\t\tcolDef.references.childRole ?? getSelfRefInverseName(inferredName);\n\t\t\t\t}\n\n\t\t\t\tfks.push(detectedFK);\n\t\t\t}\n\t\t\tcontinue; // Skip convention check if explicit reference exists\n\t\t}\n\n\t\t// PRIORITY 2: Convention-based detection\n\t\t// Pattern like '{singular}Id' → check if column matches any table's singular form\n\t\tfor (const candidateTable of tableNames) {\n\t\t\tif (candidateTable === tableName) continue; // Skip self (handled separately)\n\n\t\t\tconst singular = singularize(candidateTable);\n\t\t\tconst expectedColumn = pattern.replace('{singular}', singular);\n\n\t\t\tif (colName === expectedColumn) {\n\t\t\t\tfks.push({\n\t\t\t\t\tcolumn: colName,\n\t\t\t\t\ttargetTable: candidateTable,\n\t\t\t\t\tinferredName: singular,\n\t\t\t\t\texplicit: false,\n\t\t\t\t\ttargetColumn: 'id',\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Check for self-referential FK (e.g., parentId → same table)\n\t\tif (colName.endsWith('Id')) {\n\t\t\tconst prefix = colName.slice(0, -2);\n\t\t\tconst singular = singularize(tableName);\n\t\t\t// Common self-ref patterns: parentId, managerId, etc.\n\t\t\tif (\n\t\t\t\t['parent', 'manager', 'supervisor', 'owner', singular].includes(prefix)\n\t\t\t) {\n\t\t\t\tif (!fks.some((fk) => fk.column === colName)) {\n\t\t\t\t\tfks.push({\n\t\t\t\t\t\tcolumn: colName,\n\t\t\t\t\t\ttargetTable: tableName,\n\t\t\t\t\t\tinferredName: prefix,\n\t\t\t\t\t\texplicit: false,\n\t\t\t\t\t\ttargetColumn: 'id',\n\t\t\t\t\t\t// Auto-infer roles for convention-based self-ref FKs\n\t\t\t\t\t\tparentRole: prefix,\n\t\t\t\t\t\tchildRole: getSelfRefInverseName(prefix),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fks;\n}\n\n// =============================================================================\n// M:N Detection\n// =============================================================================\n\ninterface DetectedManyToMany {\n\t/** Junction table name */\n\tjunction: string;\n\t/** First table in the M:N relation */\n\ttableA: string;\n\t/** Second table in the M:N relation */\n\ttableB: string;\n\t/** FK column pointing to tableA */\n\tfkA: string;\n\t/** FK column pointing to tableB */\n\tfkB: string;\n}\n\n/**\n * Check if a column is a \"business\" column (not FK, not metadata).\n */\nfunction isBusinessColumn(\n\tcolName: string,\n\tcolDef: SchemaColumnDefinition,\n\ttimestamps: string[],\n): boolean {\n\t// Primary key is not business data\n\tif (colDef.primaryKey) return false;\n\t// Timestamp columns are metadata\n\tif (timestamps.includes(colName)) return false;\n\t// FK columns are not business data (they reference other tables)\n\tif (colDef.references) return false;\n\t// Columns ending in 'Id' are likely FKs (convention)\n\tif (colName.endsWith('Id')) return false;\n\t// Common metadata columns\n\tif (['id', 'createdBy', 'updatedBy', 'deletedAt'].includes(colName))\n\t\treturn false;\n\n\t// Everything else is business data\n\treturn true;\n}\n\n/**\n * Detect pure M:N junction tables.\n * Criteria: exactly 2 FK columns, no business columns.\n */\nexport function detectManyToMany(\n\ttables: SchemaTablesDefinition,\n\tconventions: Required<SchemaConventionsDefinition>,\n\ttableNames: Set<string>,\n): DetectedManyToMany[] {\n\tconst results: DetectedManyToMany[] = [];\n\n\tfor (const [tableName, table] of Object.entries(tables)) {\n\t\tconst fks = detectForeignKeys(tableName, table, conventions, tableNames);\n\n\t\t// Must have exactly 2 FKs\n\t\tif (fks.length !== 2) continue;\n\n\t\t// Check for business columns\n\t\tconst hasBusinessColumns = Object.entries(table).some(([colName, colDef]) =>\n\t\t\tisBusinessColumn(colName, colDef, conventions.timestamps),\n\t\t);\n\n\t\tif (hasBusinessColumns) continue;\n\n\t\t// This is a pure junction table\n\t\tconst fkA = fks[0];\n\t\tconst fkB = fks[1];\n\t\tif (fkA && fkB) {\n\t\t\tresults.push({\n\t\t\t\tjunction: tableName,\n\t\t\t\ttableA: fkA.targetTable,\n\t\t\t\ttableB: fkB.targetTable,\n\t\t\t\tfkA: fkA.column,\n\t\t\t\tfkB: fkB.column,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn results;\n}\n\n// =============================================================================\n// Relation Inference\n// =============================================================================\n\n/**\n * Infer all relations from table definitions.\n * Returns a map of 'sourceTable.relationName' → RelationDefinition.\n */\nexport function inferRelationsFromSchema(\n\ttables: SchemaTablesDefinition,\n\tconventions: Required<SchemaConventionsDefinition>,\n\texplicitRelations: SchemaRelationsDefinition = {},\n): SchemaRelationsDefinition {\n\tconst result: SchemaRelationsDefinition = { ...explicitRelations };\n\tconst tableNames = new Set(Object.keys(tables));\n\n\t// First pass: detect M:N relations (junction tables)\n\tconst manyToManys = detectManyToMany(tables, conventions, tableNames);\n\tconst junctionTables = new Set(manyToManys.map((m) => m.junction));\n\n\t// Add M:N relations (bidirectional)\n\tfor (const m2m of manyToManys) {\n\t\tconst { junction, tableA, tableB, fkA, fkB } = m2m;\n\n\t\t// Use opposite table name for relation path (not junction name)\n\t\tconst relNameAtoB = conventions.pluralize\n\t\t\t? pluralize(singularize(tableB))\n\t\t\t: tableB;\n\t\tconst relNameBtoA = conventions.pluralize\n\t\t\t? pluralize(singularize(tableA))\n\t\t\t: tableA;\n\n\t\tconst keyAtoB = `${tableA}.${relNameAtoB}`;\n\t\tconst keyBtoA = `${tableB}.${relNameBtoA}`;\n\n\t\t// Only add if not explicitly defined\n\t\tif (!(keyAtoB in result)) {\n\t\t\tconst rel: SchemaManyToManyRelation = {\n\t\t\t\tkind: 'manyToMany',\n\t\t\t\ttarget: tableB,\n\t\t\t\tthrough: junction,\n\t\t\t\tsourceFk: fkA,\n\t\t\t\ttargetFk: fkB,\n\t\t\t};\n\t\t\tresult[keyAtoB] = rel;\n\t\t}\n\n\t\tif (!(keyBtoA in result)) {\n\t\t\tconst rel: SchemaManyToManyRelation = {\n\t\t\t\tkind: 'manyToMany',\n\t\t\t\ttarget: tableA,\n\t\t\t\tthrough: junction,\n\t\t\t\tsourceFk: fkB,\n\t\t\t\ttargetFk: fkA,\n\t\t\t};\n\t\t\tresult[keyBtoA] = rel;\n\t\t}\n\t}\n\n\t// Second pass: detect 1:N and N:1 relations (skip junction tables)\n\tfor (const [tableName, table] of Object.entries(tables)) {\n\t\tif (junctionTables.has(tableName)) continue;\n\n\t\tconst fks = detectForeignKeys(tableName, table, conventions, tableNames);\n\n\t\tfor (const fk of fks) {\n\t\t\t// Skip FKs that point to junction tables\n\t\t\tif (junctionTables.has(fk.targetTable)) continue;\n\n\t\t\t// BelongsTo: source has FK to target\n\t\t\tconst belongsToKey = `${tableName}.${fk.inferredName}`;\n\t\t\tif (!(belongsToKey in result)) {\n\t\t\t\tconst rel: SchemaBelongsToRelation = {\n\t\t\t\t\tkind: 'belongsTo',\n\t\t\t\t\ttarget: fk.targetTable,\n\t\t\t\t\tforeignKey: fk.column,\n\t\t\t\t\ttargetKey: fk.targetColumn,\n\t\t\t\t};\n\t\t\t\tresult[belongsToKey] = rel;\n\t\t\t}\n\n\t\t\t// HasMany: target has many of source (inverse)\n\t\t\t// For self-referential FKs, use semantic inverse name (parent → children)\n\t\t\tconst isSelfRef = fk.targetTable === tableName;\n\t\t\tconst hasManyName = isSelfRef\n\t\t\t\t? getSelfRefInverseName(fk.inferredName)\n\t\t\t\t: (() => {\n\t\t\t\t\t\t// When the FK has a custom alias (inferredName differs from the\n\t\t\t\t\t\t// singularized target table name), use pluralize(inferredName) so\n\t\t\t\t\t\t// that multiple FKs to the same table get distinct hasMany names.\n\t\t\t\t\t\t// e.g. caller_id (inferredName='caller') → 'callers'\n\t\t\t\t\t\t// callee_id (inferredName='callee') → 'callees'\n\t\t\t\t\t\tconst hasCustomAlias =\n\t\t\t\t\t\t\tfk.inferredName !== singularize(fk.targetTable);\n\t\t\t\t\t\tif (hasCustomAlias) {\n\t\t\t\t\t\t\treturn conventions.pluralize\n\t\t\t\t\t\t\t\t? pluralize(fk.inferredName)\n\t\t\t\t\t\t\t\t: fk.inferredName;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn conventions.pluralize\n\t\t\t\t\t\t\t? pluralize(singularize(tableName))\n\t\t\t\t\t\t\t: tableName;\n\t\t\t\t\t})();\n\t\t\tconst hasManyKey = `${fk.targetTable}.${hasManyName}`;\n\t\t\tif (!(hasManyKey in result)) {\n\t\t\t\tconst rel: SchemaHasManyRelation = {\n\t\t\t\t\tkind: 'hasMany',\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: fk.column,\n\t\t\t\t\tsourceKey: 'id',\n\t\t\t\t};\n\t\t\t\tresult[hasManyKey] = rel;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n","/**\n * Schema DSL - defineSchema() function\n *\n * Main entry point for defining the schema Source of Truth.\n * Merges explicit definitions with convention-inferred relations.\n *\n * Migrated from @dbsp/schema/define.ts as part of ARCH-003.\n */\n\nimport {\n\tDEFAULT_CONVENTIONS,\n\tinferRelationsFromSchema,\n} from './conventions.js';\nimport type {\n\tResolvedSchema,\n\tSchemaConfigInput,\n\tSchemaConventionsDefinition,\n\tSchemaDefaultFilters,\n\tSchemaHintsDefinition,\n\tSchemaIndexesDefinition,\n\tSchemaRelationsDefinition,\n\tSchemaTablesDefinition,\n} from './schema-dsl-types.js';\n\n/**\n * Define a schema with tables, relations, hints, and conventions.\n *\n * @example Simple - just tables\n * ```typescript\n * const schema = defineSchema({\n * users: {\n * id: { type: 'uuid', primaryKey: true },\n * name: { type: 'string', nullable: false },\n * },\n * posts: {\n * id: { type: 'uuid', primaryKey: true },\n * authorId: { type: 'uuid', references: { table: 'users' } },\n * },\n * });\n * ```\n *\n * @example With config\n * ```typescript\n * const schema = defineSchema(\n * {\n * users: { id: { type: 'uuid', primaryKey: true } },\n * roles: { id: { type: 'uuid', primaryKey: true } },\n * },\n * {\n * relations: {...}\n * }\n * );\n * ```\n */\nexport function defineSchema<T extends SchemaTablesDefinition>(\n\ttables: T,\n\tconfig?: SchemaConfigInput,\n): ResolvedSchema<T> {\n\tconst relations: SchemaRelationsDefinition = config?.relations ?? {};\n\tconst hints: SchemaHintsDefinition = config?.hints ?? {};\n\tconst conventions: SchemaConventionsDefinition = config?.conventions ?? {};\n\tconst indexes: SchemaIndexesDefinition = config?.indexes ?? {};\n\tconst defaultFilters: SchemaDefaultFilters = config?.defaultFilters ?? {};\n\n\t// Merge user conventions with defaults\n\tconst resolvedConventions: Required<SchemaConventionsDefinition> = {\n\t\t...DEFAULT_CONVENTIONS,\n\t\t...conventions,\n\t};\n\n\t// Infer relations from table definitions + merge with explicit\n\tconst allRelations = inferRelationsFromSchema(\n\t\ttables,\n\t\tresolvedConventions,\n\t\trelations,\n\t);\n\n\t// Validate explicit relations reference existing tables\n\tvalidateRelations(tables, relations);\n\n\t// Validate hints reference existing relations\n\tvalidateHints(allRelations, hints);\n\n\t// Validate default filters reference existing tables\n\tvalidateDefaultFilters(tables, defaultFilters);\n\n\treturn {\n\t\ttables,\n\t\trelations: allRelations,\n\t\thints,\n\t\tconventions: resolvedConventions,\n\t\tindexes,\n\t\tdefaultFilters,\n\t};\n}\n\n/**\n * Validate that explicit relations reference existing tables.\n */\nfunction validateRelations(\n\ttables: SchemaTablesDefinition,\n\trelations: SchemaRelationsDefinition,\n): void {\n\tconst tableNames = new Set(Object.keys(tables));\n\n\tfor (const [key, rel] of Object.entries(relations)) {\n\t\tconst sourceTable = key.split('.')[0] ?? key;\n\n\t\tif (!tableNames.has(sourceTable)) {\n\t\t\tthrow new SchemaValidationError(\n\t\t\t\t`Relation '${key}' references non-existent source table '${sourceTable}'`,\n\t\t\t);\n\t\t}\n\n\t\tif (!tableNames.has(rel.target)) {\n\t\t\tthrow new SchemaValidationError(\n\t\t\t\t`Relation '${key}' references non-existent target table '${rel.target}'`,\n\t\t\t);\n\t\t}\n\n\t\tif (rel.kind === 'manyToMany' && !tableNames.has(rel.through)) {\n\t\t\tthrow new SchemaValidationError(\n\t\t\t\t`Relation '${key}' references non-existent junction table '${rel.through}'`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Validate that hints reference existing relation paths.\n */\nfunction validateHints(\n\trelations: SchemaRelationsDefinition,\n\thints: SchemaHintsDefinition,\n): void {\n\tfor (const path of Object.keys(hints)) {\n\t\tif (!(path in relations)) {\n\t\t\tthrow new SchemaValidationError(\n\t\t\t\t`Hint path '${path}' does not match any relation. ` +\n\t\t\t\t\t`Available: ${Object.keys(relations).join(', ')}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Validate that default filters reference existing tables.\n */\nfunction validateDefaultFilters(\n\ttables: SchemaTablesDefinition,\n\tdefaultFilters: SchemaDefaultFilters,\n): void {\n\tconst tableNames = new Set(Object.keys(tables));\n\n\tfor (const tableName of Object.keys(defaultFilters)) {\n\t\tif (!tableNames.has(tableName)) {\n\t\t\tthrow new SchemaValidationError(\n\t\t\t\t`Default filter for non-existent table '${tableName}'. ` +\n\t\t\t\t\t`Available: ${[...tableNames].join(', ')}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Error thrown when schema validation fails.\n */\nexport class SchemaValidationError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'SchemaValidationError';\n\t}\n}\n","/**\n * Schema DSL Types\n *\n * Input types for defineSchema() - the user-facing schema definition DSL.\n * These types are simpler than the IR types and serve as the \"source of truth\"\n * for schema definitions before they're processed into ModelIR.\n *\n * Migrated from @dbsp/schema/types.ts as part of ARCH-003.\n */\n\nimport type { WhereIntent } from '@dbsp/types';\n\n// =============================================================================\n// Column Types (DSL - simpler than ColumnType in model-ir.ts)\n// =============================================================================\n\n/**\n * Supported column types in the schema DSL.\n * Maps to database types during DDL generation.\n */\nexport type SchemaColumnType =\n\t| 'uuid'\n\t| 'string'\n\t| 'text'\n\t| 'integer'\n\t| 'bigint'\n\t| 'decimal'\n\t| 'boolean'\n\t| 'timestamp'\n\t| 'date'\n\t| 'time'\n\t| 'json'\n\t| 'jsonb'\n\t// PostgreSQL-specific range types (will error on non-PG dialects)\n\t| 'daterange'\n\t| 'tsrange'\n\t| 'tstzrange'\n\t| 'int4range'\n\t| 'int8range'\n\t| 'numrange';\n\n/** Foreign key delete behavior */\nexport type SchemaOnDeleteAction =\n\t| 'CASCADE'\n\t| 'SET NULL'\n\t| 'RESTRICT'\n\t| 'NO ACTION';\n\n/**\n * Foreign key reference definition.\n * When present, takes priority over convention-based FK detection.\n */\nexport interface SchemaForeignKeyReference {\n\t/** Target table name */\n\ttable: string;\n\t/** Target column name (defaults to 'id') */\n\tcolumn?: string;\n\t/** Delete behavior (CASCADE, SET NULL, RESTRICT, NO ACTION) */\n\tonDelete?: SchemaOnDeleteAction;\n\t/**\n\t * Custom role name for parent direction in self-referential FKs.\n\t * Required when table has multiple self-referential FKs.\n\t * Example: parentRole: 'manager' for managerId FK\n\t * @default 'parent' (for single self-ref FK)\n\t */\n\tparentRole?: string;\n\t/**\n\t * Custom role name for child direction in self-referential FKs.\n\t * Required when table has multiple self-referential FKs.\n\t * Example: childRole: 'subordinates' for managerId FK\n\t * @default 'children' or pluralized parentRole (for single self-ref FK)\n\t */\n\tchildRole?: string;\n}\n\n/**\n * Column definition in the schema DSL.\n */\nexport interface SchemaColumnDefinition {\n\t/** Column data type */\n\ttype: SchemaColumnType;\n\t/** Whether the column is the primary key */\n\tprimaryKey?: boolean;\n\t/** Whether the column allows NULL values */\n\tnullable?: boolean;\n\t/** Whether the column has a unique constraint */\n\tunique?: boolean;\n\t/** Default value (e.g., 'now()', 'gen_random_uuid()', 0, true) */\n\tdefault?: string | number | boolean;\n\t/** Explicit foreign key reference (takes priority over conventions) */\n\treferences?: SchemaForeignKeyReference;\n\t/** Create an index on this column (true for auto-name, string for custom name) */\n\tindex?: boolean | string;\n}\n\n/**\n * Table definition: mapping of column names to their definitions.\n */\nexport type SchemaTableDefinition = Record<string, SchemaColumnDefinition>;\n\n/**\n * All tables in the schema.\n */\nexport type SchemaTablesDefinition = Record<string, SchemaTableDefinition>;\n\n/**\n * Index definition for composite indexes.\n */\nexport interface SchemaIndexDefinition {\n\t/** Columns included in the index */\n\tcolumns: string[];\n\t/** Whether this is a unique index */\n\tunique?: boolean;\n\t/** Custom index name (auto-generated if not provided) */\n\tname?: string;\n}\n\n/**\n * Index configuration by table.\n */\nexport type SchemaIndexesDefinition = Record<string, SchemaIndexDefinition[]>;\n\n// =============================================================================\n// Relation Types (Discriminated Union)\n// =============================================================================\n\n/**\n * Relation kinds for discriminated union.\n */\nexport type SchemaRelationKind = 'belongsTo' | 'hasMany' | 'manyToMany';\n\n/**\n * Strategy for including related data in queries.\n * - 'join': Use SQL JOIN (default for belongsTo)\n * - 'subquery': Execute subquery query\n * - 'cte': Use Common Table Expression\n * - 'lateral': Use LATERAL JOIN\n * - 'json_agg': Use JSON aggregation\n * - 'auto': Let planner decide based on relation type\n */\nexport type SchemaIncludeStrategy =\n\t| 'join'\n\t| 'subquery'\n\t| 'cte'\n\t| 'lateral'\n\t| 'json_agg'\n\t| 'auto';\n\n/**\n * Base properties shared by all relation types.\n */\ninterface SchemaRelationBase {\n\t/** Target table name */\n\ttarget: string;\n\t/** Include strategy hint for the planner */\n\tincludeStrategy?: SchemaIncludeStrategy;\n}\n\n/**\n * BelongsTo relation: source table has FK to target table.\n * Example: posts.author → users (posts.authorId references users.id)\n */\nexport interface SchemaBelongsToRelation extends SchemaRelationBase {\n\tkind: 'belongsTo';\n\t/** Foreign key column in the source table */\n\tforeignKey: string;\n\t/** Target column (defaults to 'id') */\n\ttargetKey?: string;\n}\n\n/**\n * HasMany relation: target table has FK to source table.\n * Example: users.posts → posts (posts.authorId references users.id)\n */\nexport interface SchemaHasManyRelation extends SchemaRelationBase {\n\tkind: 'hasMany';\n\t/** Foreign key column in the target table */\n\tforeignKey: string;\n\t/** Source column (defaults to 'id') */\n\tsourceKey?: string;\n}\n\n/**\n * ManyToMany relation: junction table connects source and target.\n * Example: posts ↔ categories via post_categories\n */\nexport interface SchemaManyToManyRelation extends SchemaRelationBase {\n\tkind: 'manyToMany';\n\t/** Junction table name */\n\tthrough: string;\n\t/** FK column in junction pointing to source */\n\tsourceFk: string;\n\t/** FK column in junction pointing to target */\n\ttargetFk: string;\n}\n\n/**\n * Union of all relation types.\n * Use `kind` field for type narrowing.\n */\nexport type SchemaRelationDefinition =\n\t| SchemaBelongsToRelation\n\t| SchemaHasManyRelation\n\t| SchemaManyToManyRelation;\n\n/**\n * Explicit relations mapping.\n * Keys are 'sourceTable.relationName' format.\n */\nexport type SchemaRelationsDefinition = Record<\n\tstring,\n\tSchemaRelationDefinition\n>;\n\n// =============================================================================\n// Planner Hints\n// =============================================================================\n\n/**\n * Strategy hint for filtering on to-many relations.\n */\nexport type SchemaFilterStrategy = 'exists' | 'join';\n\n/**\n * Cardinality hint for relation traversal.\n */\nexport type SchemaCardinality = 'one' | 'many';\n\n/**\n * Hint definition for a specific relation path.\n */\nexport interface SchemaHintDefinition {\n\t/** Preferred filter strategy */\n\tdefaultStrategy?: SchemaFilterStrategy;\n\t/** Expected cardinality */\n\tcardinality?: SchemaCardinality;\n}\n\n/**\n * All hints, keyed by 'table.relation' path.\n */\nexport type SchemaHintsDefinition = Record<string, SchemaHintDefinition>;\n\n// =============================================================================\n// Convention Configuration\n// =============================================================================\n\n/**\n * Convention settings for automatic FK detection and naming.\n */\nexport interface SchemaConventionsDefinition {\n\t/**\n\t * Pattern for foreign key column names.\n\t * {singular} is replaced with singular table name.\n\t * @default '{singular}Id'\n\t */\n\tfkPattern?: string;\n\n\t/**\n\t * Whether to auto-pluralize relation names.\n\t * @default true\n\t */\n\tpluralize?: boolean;\n\n\t/**\n\t * Column names recognized as timestamps.\n\t * @default ['createdAt', 'updatedAt']\n\t */\n\ttimestamps?: string[];\n\n\t/**\n\t * Automatically create indexes on foreign key columns.\n\t * FK columns are frequently used in JOINs, so indexing is a best practice.\n\t * @default true\n\t */\n\tfkAutoIndex?: boolean;\n}\n\n// =============================================================================\n// Schema Definition\n// =============================================================================\n\n/**\n * Complete schema definition input for defineSchema() wrapped form.\n * Prefer the new hybrid API: defineSchema(tables, config?)\n */\nexport interface SchemaDefinitionInput<\n\tT extends SchemaTablesDefinition = SchemaTablesDefinition,\n> {\n\t/** Table definitions */\n\ttables: T;\n\t/** Explicit relation definitions (override auto-detected) */\n\trelations?: SchemaRelationsDefinition;\n\t/** Planner hints */\n\thints?: SchemaHintsDefinition;\n\t/** Convention configuration */\n\tconventions?: SchemaConventionsDefinition;\n}\n\n/**\n * Per-table default filters applied to all queries.\n * Commonly used for soft delete filtering.\n */\nexport type SchemaDefaultFilters = {\n\t[tableName: string]: WhereIntent;\n};\n\n/**\n * Configuration options for defineSchema (new API).\n */\nexport interface SchemaConfigInput {\n\t/** Explicit relation definitions (override auto-detected) */\n\trelations?: SchemaRelationsDefinition;\n\t/** Planner hints */\n\thints?: SchemaHintsDefinition;\n\t/** Convention configuration */\n\tconventions?: SchemaConventionsDefinition;\n\t/** Table-level index definitions (composite indexes) */\n\tindexes?: SchemaIndexesDefinition;\n\t/**\n\t * Default filters applied automatically to all queries on each table.\n\t * Use for soft delete (`isNull('deletedAt')`), multi-tenant, or active filtering.\n\t * Override per-query with `.withoutDefaultFilters()`.\n\t */\n\tdefaultFilters?: SchemaDefaultFilters;\n}\n\n/**\n * Resolved schema with all relations (explicit + inferred).\n * This is the output of defineSchema().\n */\nexport interface ResolvedSchema<\n\tT extends SchemaTablesDefinition = SchemaTablesDefinition,\n> {\n\t/** Original table definitions */\n\ttables: T;\n\t/** All relations (explicit + auto-detected) */\n\trelations: SchemaRelationsDefinition;\n\t/** Planner hints */\n\thints: SchemaHintsDefinition;\n\t/** Resolved conventions with defaults applied */\n\tconventions: Required<SchemaConventionsDefinition>;\n\t/** Table-level index definitions */\n\tindexes: SchemaIndexesDefinition;\n\t/** Default filters per table (e.g., soft delete) */\n\tdefaultFilters: SchemaDefaultFilters;\n}\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Type guard for BelongsTo relation.\n */\nexport function isBelongsTo(\n\trel: SchemaRelationDefinition,\n): rel is SchemaBelongsToRelation {\n\treturn rel.kind === 'belongsTo';\n}\n\n/**\n * Type guard for HasMany relation.\n */\nexport function isHasMany(\n\trel: SchemaRelationDefinition,\n): rel is SchemaHasManyRelation {\n\treturn rel.kind === 'hasMany';\n}\n\n/**\n * Type guard for ManyToMany relation.\n */\nexport function isManyToMany(\n\trel: SchemaRelationDefinition,\n): rel is SchemaManyToManyRelation {\n\treturn rel.kind === 'manyToMany';\n}\n","/**\n * Error thrown when attempting to execute a query without a database configured.\n *\n * @example\n * ```typescript\n * const orm = createOrm({ model: schema, adapter: mockAdapter }); // Mock adapter\n * await orm.select('users').findMany(); // Throws ExecutionError (mock can't execute)\n * ```\n */\nexport class ExecutionError extends Error {\n\toverride readonly name = 'ExecutionError' as const;\n\n\t/**\n\t * The operation that was attempted.\n\t */\n\treadonly operation: string;\n\n\t/**\n\t * The reason the operation failed.\n\t */\n\treadonly reason: string;\n\n\t/**\n\t * How to fix the issue.\n\t */\n\treadonly fix: string;\n\n\tconstructor(opts: { operation: string; reason: string; fix: string }) {\n\t\tconst message =\n\t\t\t`Cannot execute ${opts.operation}: ${opts.reason}\\n\\n` +\n\t\t\t`To fix: ${opts.fix}`;\n\n\t\tsuper(message);\n\n\t\tthis.operation = opts.operation;\n\t\tthis.reason = opts.reason;\n\t\tthis.fix = opts.fix;\n\n\t\tObject.setPrototypeOf(this, ExecutionError.prototype);\n\t}\n}\n\n/**\n * Error thrown when firstOrThrow() finds no results.\n *\n * @example\n * ```typescript\n * await orm.select('users').where(eq('id', 999)).firstOrThrow();\n * // Throws NotFoundError: No record found for 'users'\n * ```\n */\nexport class NotFoundError extends Error {\n\toverride readonly name = 'NotFoundError' as const;\n\n\t/**\n\t * The table that was queried.\n\t */\n\treadonly table: string;\n\n\t/**\n\t * Optional: hint about the query that returned no results.\n\t */\n\treadonly hint?: string;\n\n\tconstructor(table: string, hint?: string) {\n\t\tconst message = hint\n\t\t\t? `No record found for '${table}'. ${hint}`\n\t\t\t: `No record found for '${table}'`;\n\n\t\tsuper(message);\n\t\tthis.table = table;\n\t\tif (hint !== undefined) {\n\t\t\tthis.hint = hint;\n\t\t}\n\t\tObject.setPrototypeOf(this, NotFoundError.prototype);\n\t}\n}\n\n/**\n * Error thrown when strict mode is enabled and an ambiguous relation is detected.\n *\n * This error provides detailed information about the ambiguity and available options\n * for disambiguation.\n *\n * @example\n * ```typescript\n * try {\n * orm.select('users').include('posts').plan();\n * } catch (error) {\n * if (error instanceof AmbiguousRelationError) {\n * console.log(error.options); // ['authoredPosts', 'reviewedPosts']\n * }\n * }\n * ```\n */\nexport class AmbiguousRelationError extends Error {\n\toverride readonly name = 'AmbiguousRelationError' as const;\n\n\t/**\n\t * The source table where the ambiguous relation originates.\n\t */\n\treadonly sourceTable: string;\n\n\t/**\n\t * The target table that has multiple possible relations.\n\t */\n\treadonly targetTable: string;\n\n\t/**\n\t * Available relation names that can be used to disambiguate.\n\t * Use one of these values with `{ via: 'relationName' }` to resolve the ambiguity.\n\t */\n\treadonly options: readonly string[];\n\n\t/**\n\t * Public-safe message (no schema enumeration).\n\t * Matches the pattern of RelationNotFoundError, TableNotFoundError, ColumnNotFoundError.\n\t */\n\treadonly publicMessage: string;\n\n\tconstructor(\n\t\tsourceTable: string,\n\t\ttargetTable: string,\n\t\toptions: readonly string[],\n\t) {\n\t\t// Generic message for .message — does NOT embed schema details to avoid info leakage.\n\t\t// Detailed developer guidance is available via .sourceTable, .targetTable, .options.\n\t\tconst genericMessage = 'Ambiguous relation';\n\n\t\tsuper(genericMessage);\n\n\t\tthis.sourceTable = sourceTable;\n\t\tthis.targetTable = targetTable;\n\t\tthis.options = options;\n\t\tthis.publicMessage = genericMessage;\n\n\t\t// Required for proper instanceof checks when extending built-in classes\n\t\t// See: https://github.com/microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work\n\t\tObject.setPrototypeOf(this, AmbiguousRelationError.prototype);\n\t}\n}\n\n/**\n * Finds the closest match to a target string from a list of candidates.\n * Uses Levenshtein distance for fuzzy matching.\n *\n * @example\n * ```typescript\n * findClosestMatch('usrs', ['users', 'posts', 'comments']); // 'users'\n * findClosestMatch('xyz', ['users', 'posts']); // undefined (no close match)\n * ```\n */\nexport function findClosestMatch(\n\ttarget: string,\n\tcandidates: readonly string[],\n): string | undefined {\n\tif (candidates.length === 0) return undefined;\n\n\tconst targetLower = target.toLowerCase();\n\tlet bestMatch: string | undefined;\n\tlet bestScore = Number.POSITIVE_INFINITY;\n\n\tfor (const candidate of candidates) {\n\t\tconst candidateLower = candidate.toLowerCase();\n\n\t\t// Exact prefix match is best\n\t\tif (candidateLower.startsWith(targetLower)) {\n\t\t\treturn candidate;\n\t\t}\n\n\t\t// Calculate simple distance (Levenshtein approximation for small strings)\n\t\tconst distance = levenshteinDistance(targetLower, candidateLower);\n\t\tif (distance < bestScore && distance <= Math.max(target.length, 3)) {\n\t\t\tbestScore = distance;\n\t\t\tbestMatch = candidate;\n\t\t}\n\t}\n\n\treturn bestMatch;\n}\n\n/**\n * Simple Levenshtein distance implementation.\n */\nfunction levenshteinDistance(a: string, b: string): number {\n\t// Pre-initialize matrix with zeros\n\tconst rows = b.length + 1;\n\tconst cols = a.length + 1;\n\tconst matrix: number[][] = [];\n\n\tfor (let i = 0; i < rows; i++) {\n\t\tmatrix[i] = new Array<number>(cols).fill(0);\n\t}\n\n\t// Initialize first column\n\tfor (let i = 0; i < rows; i++) {\n\t\tconst row = matrix[i];\n\t\tif (row) row[0] = i;\n\t}\n\t// Initialize first row\n\tconst firstRow = matrix[0];\n\tif (firstRow) {\n\t\tfor (let j = 0; j < cols; j++) {\n\t\t\tfirstRow[j] = j;\n\t\t}\n\t}\n\n\tfor (let i = 1; i < rows; i++) {\n\t\tconst currentRow = matrix[i];\n\t\tconst prevRow = matrix[i - 1];\n\t\tif (!currentRow || !prevRow) continue;\n\n\t\tfor (let j = 1; j < cols; j++) {\n\t\t\tconst prevDiag = prevRow[j - 1] ?? 0;\n\t\t\tconst prevUp = prevRow[j] ?? 0;\n\t\t\tconst prevLeft = currentRow[j - 1] ?? 0;\n\n\t\t\tif (b.charAt(i - 1) === a.charAt(j - 1)) {\n\t\t\t\tcurrentRow[j] = prevDiag;\n\t\t\t} else {\n\t\t\t\tcurrentRow[j] = Math.min(\n\t\t\t\t\tprevDiag + 1, // substitution\n\t\t\t\t\tprevLeft + 1, // insertion\n\t\t\t\t\tprevUp + 1, // deletion\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst lastRow = matrix[b.length];\n\treturn lastRow ? (lastRow[a.length] ?? 0) : 0;\n}\n\n/**\n * Error thrown when a requested relation does not exist.\n *\n * Provides helpful suggestions including available relations and fuzzy-matched\n * \"Did you mean?\" hints.\n *\n * @example\n * ```typescript\n * const err = new RelationNotFoundError({\n * table: 'users',\n * requested: 'comment',\n * available: ['posts', 'profile', 'comments'],\n * });\n * // err.message === 'Relation not found'\n * // err.available === ['posts', 'profile', 'comments']\n * // err.suggestion === 'comments'\n * ```\n */\nexport class RelationNotFoundError extends Error {\n\toverride readonly name = 'RelationNotFoundError' as const;\n\n\t/**\n\t * The table where the relation was requested.\n\t */\n\treadonly table: string;\n\n\t/**\n\t * The relation name that was requested but not found.\n\t */\n\treadonly requested: string;\n\n\t/**\n\t * Available relations on this table.\n\t */\n\treadonly available: readonly string[];\n\n\t/**\n\t * Suggested relation name (fuzzy match), if any.\n\t */\n\treadonly suggestion?: string;\n\n\t/**\n\t * Public-safe message (no schema enumeration).\n\t */\n\treadonly publicMessage: string;\n\n\tconstructor(opts: {\n\t\ttable: string;\n\t\trequested: string;\n\t\tavailable: readonly string[];\n\t}) {\n\t\tconst suggestion = findClosestMatch(opts.requested, opts.available);\n\n\t\t// Generic message — does NOT embed available list to avoid info leakage\n\t\tconst genericMessage = 'Relation not found';\n\n\t\tsuper(genericMessage);\n\n\t\tthis.table = opts.table;\n\t\tthis.requested = opts.requested;\n\t\tthis.available = opts.available;\n\t\tthis.publicMessage = genericMessage;\n\t\tif (suggestion !== undefined) {\n\t\t\tthis.suggestion = suggestion;\n\t\t}\n\n\t\tObject.setPrototypeOf(this, RelationNotFoundError.prototype);\n\t}\n}\n\n/**\n * Error thrown when an operation is invalid or malformed.\n *\n * @example\n * ```typescript\n * orm.insert('users').values([]).execute();\n * // Throws InvalidOperationError: No values provided for insert\n * ```\n */\nexport class InvalidOperationError extends Error {\n\toverride readonly name = 'InvalidOperationError' as const;\n\n\t/**\n\t * The operation that was attempted.\n\t */\n\treadonly operation: string;\n\n\t/**\n\t * The reason the operation is invalid.\n\t */\n\treadonly reason: string;\n\n\tconstructor(operation: string, reason: string) {\n\t\tconst message = `Invalid ${operation}: ${reason}`;\n\t\tsuper(message);\n\t\tthis.operation = operation;\n\t\tthis.reason = reason;\n\t\tObject.setPrototypeOf(this, InvalidOperationError.prototype);\n\t}\n}\n\n/**\n * Error thrown when an operation is potentially unsafe and requires explicit confirmation.\n *\n * @example\n * ```typescript\n * orm.update('users').set({ active: false }).execute();\n * // Throws UnsafeOperationError: WHERE clause required\n * ```\n */\n\n/**\n * Validate that a string is a safe SQL identifier (table, column, schema, alias).\n *\n * Rules:\n * 1. Must not be empty\n * 2. Must not exceed 63 characters (PostgreSQL limit)\n * 3. Must start with a letter or underscore\n * 4. Must contain only alphanumeric, underscore, or dollar sign\n *\n * @param value - The identifier to validate\n * @param type - Type label for error messages (e.g. 'schema', 'table', 'column')\n * @throws InvalidOperationError if validation fails\n */\nexport function validateIdentifier(value: string, type: string): void {\n\tif (!value || value.length === 0) {\n\t\tthrow new InvalidOperationError(type, `${type} name must not be empty`);\n\t}\n\tif (value.length > 63) {\n\t\tthrow new InvalidOperationError(\n\t\t\ttype,\n\t\t\t`${type} name must not exceed 63 characters`,\n\t\t);\n\t}\n\tif (!/^[a-zA-Z_][a-zA-Z0-9_$]{0,62}$/.test(value)) {\n\t\tthrow new InvalidOperationError(\n\t\t\ttype,\n\t\t\t`${type} name contains invalid characters`,\n\t\t);\n\t}\n}\n\nexport class UnsafeOperationError extends Error {\n\toverride readonly name = 'UnsafeOperationError' as const;\n\n\t/**\n\t * The operation that was attempted.\n\t */\n\treadonly operation: string;\n\n\t/**\n\t * How to make the operation safe or explicit.\n\t */\n\treadonly fix: string;\n\n\tconstructor(operation: string, fix: string) {\n\t\tconst message = `Unsafe ${operation}: ${fix}`;\n\t\tsuper(message);\n\t\tthis.operation = operation;\n\t\tthis.fix = fix;\n\t\tObject.setPrototypeOf(this, UnsafeOperationError.prototype);\n\t}\n}\n\n/**\n * Error thrown when a requested table does not exist in the schema.\n *\n * Provides helpful suggestions including available tables and fuzzy-matched\n * \"Did you mean?\" hints.\n *\n * @example\n * ```typescript\n * const err = new TableNotFoundError({\n * requested: 'usrs',\n * available: ['users', 'posts', 'comments'],\n * });\n * // err.message === 'Table not found'\n * // err.available === ['users', 'posts', 'comments']\n * // err.suggestion === 'users'\n * ```\n */\nexport class TableNotFoundError extends Error {\n\toverride readonly name = 'TableNotFoundError' as const;\n\n\t/**\n\t * The table name that was requested but not found.\n\t */\n\treadonly requested: string;\n\n\t/**\n\t * Available tables in the schema.\n\t */\n\treadonly available: readonly string[];\n\n\t/**\n\t * Suggested table name (fuzzy match), if any.\n\t */\n\treadonly suggestion?: string;\n\n\t/**\n\t * Public-safe message (no schema enumeration).\n\t */\n\treadonly publicMessage: string;\n\n\tconstructor(opts: { requested: string; available: readonly string[] }) {\n\t\tconst suggestion = findClosestMatch(opts.requested, opts.available);\n\n\t\t// Generic message — does NOT embed available list to avoid info leakage\n\t\tconst genericMessage = 'Table not found';\n\n\t\tsuper(genericMessage);\n\n\t\tthis.requested = opts.requested;\n\t\tthis.available = opts.available;\n\t\tthis.publicMessage = genericMessage;\n\t\tif (suggestion !== undefined) {\n\t\t\tthis.suggestion = suggestion;\n\t\t}\n\n\t\tObject.setPrototypeOf(this, TableNotFoundError.prototype);\n\t}\n}\n\n/**\n * Error thrown when a requested column does not exist on a table.\n *\n * Provides helpful suggestions including available columns and fuzzy-matched\n * \"Did you mean?\" hints.\n *\n * @example\n * ```typescript\n * const err = new ColumnNotFoundError({\n * table: 'users',\n * requested: 'emial',\n * available: ['id', 'email', 'name', 'createdAt'],\n * });\n * // err.message === 'Column not found'\n * // err.available === ['id', 'email', 'name', 'createdAt']\n * // err.suggestion === 'email'\n * ```\n */\nexport class ColumnNotFoundError extends Error {\n\toverride readonly name = 'ColumnNotFoundError' as const;\n\n\t/**\n\t * The table where the column was requested.\n\t */\n\treadonly table: string;\n\n\t/**\n\t * The column name that was requested but not found.\n\t */\n\treadonly requested: string;\n\n\t/**\n\t * Available columns on this table.\n\t */\n\treadonly available: readonly string[];\n\n\t/**\n\t * Suggested column name (fuzzy match), if any.\n\t */\n\treadonly suggestion?: string;\n\n\t/**\n\t * Public-safe message (no schema enumeration).\n\t */\n\treadonly publicMessage: string;\n\n\tconstructor(opts: {\n\t\ttable: string;\n\t\trequested: string;\n\t\tavailable: readonly string[];\n\t}) {\n\t\tconst suggestion = findClosestMatch(opts.requested, opts.available);\n\n\t\t// Generic message — does NOT embed available list to avoid info leakage\n\t\tconst genericMessage = 'Column not found';\n\n\t\tsuper(genericMessage);\n\n\t\tthis.table = opts.table;\n\t\tthis.requested = opts.requested;\n\t\tthis.available = opts.available;\n\t\tthis.publicMessage = genericMessage;\n\t\tif (suggestion !== undefined) {\n\t\t\tthis.suggestion = suggestion;\n\t\t}\n\n\t\tObject.setPrototypeOf(this, ColumnNotFoundError.prototype);\n\t}\n}\n\n/**\n * Error thrown when schema's naming convention doesn't match adapter's naming convention.\n *\n * This validation prevents subtle bugs where column names in queries don't match\n * the expected database column names due to naming convention mismatch.\n *\n * @example\n * ```typescript\n * const schema = await getSchemaFromDb(adapter); // dbCasing: 'snake_case'\n * const orm = createOrm({\n * schema,\n * adapter: createPgsqlAdapter(pool, { dbCasing: 'preserve' }),\n * });\n * // Throws NamingConventionMismatchError\n * ```\n *\n * @since ARCH-006\n */\nexport class NamingConventionMismatchError extends Error {\n\toverride readonly name = 'NamingConventionMismatchError' as const;\n\n\t/**\n\t * The DB casing used by the schema.\n\t */\n\treadonly schemaCasing: string;\n\n\t/**\n\t * The DB casing used by the adapter.\n\t */\n\treadonly adapterCasing: string;\n\n\tconstructor(opts: { schemaCasing: string; adapterCasing: string }) {\n\t\tconst message =\n\t\t\t`DB casing mismatch: Schema uses '${opts.schemaCasing}' but adapter uses '${opts.adapterCasing}'.\\n` +\n\t\t\t`Either align them or recreate the schema with the same dbCasing as the adapter.`;\n\n\t\tsuper(message);\n\n\t\tthis.schemaCasing = opts.schemaCasing;\n\t\tthis.adapterCasing = opts.adapterCasing;\n\n\t\tObject.setPrototypeOf(this, NamingConventionMismatchError.prototype);\n\t}\n}\n\n// ============================================================================\n// Error Codes\n// ============================================================================\n\n/**\n * Error codes for programmatic error handling.\n *\n * Use these codes to identify error types without relying on `instanceof` checks,\n * which is useful for serialization and cross-boundary error handling.\n *\n * @example\n * ```typescript\n * try {\n * await orm.select('users').all();\n * } catch (error) {\n * if (error.code === ErrorCode.EXECUTION_ERROR) {\n * // Handle execution error\n * }\n * }\n * ```\n */\nexport const ErrorCode = {\n\t/** Query execution failed (no adapter configured) */\n\tEXECUTION_ERROR: 'DBSP_E001',\n\t/** No record found (firstOrThrow) */\n\tNOT_FOUND: 'DBSP_E002',\n\t/** Ambiguous relation detected in strict mode */\n\tAMBIGUOUS_RELATION: 'DBSP_E003',\n\t/** Relation not found in schema */\n\tRELATION_NOT_FOUND: 'DBSP_E004',\n\t/** Invalid operation in current context */\n\tINVALID_OPERATION: 'DBSP_E005',\n\t/** Unsafe operation blocked */\n\tUNSAFE_OPERATION: 'DBSP_E006',\n\t/** Table not found in schema */\n\tTABLE_NOT_FOUND: 'DBSP_E007',\n\t/** Column not found on table */\n\tCOLUMN_NOT_FOUND: 'DBSP_E008',\n\t/** Schema naming convention doesn't match adapter naming convention */\n\tNAMING_CONVENTION_MISMATCH: 'DBSP_E009',\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\n// ============================================================================\n// Error Factory\n// ============================================================================\n\n/**\n * Factory functions for creating DBSP errors with consistent structure.\n *\n * Using the factory provides several benefits:\n * - Consistent error creation across the codebase\n * - Error codes are automatically attached\n * - Type-safe error construction\n * - Centralized error message formatting\n *\n * @example\n * ```typescript\n * import { Errors } from '@dbsp/core';\n *\n * // Create errors with factory\n * throw Errors.tableNotFound({\n * requested: 'userz',\n * available: ['users', 'posts', 'comments'],\n * });\n *\n * // Check error type\n * if (Errors.isTableNotFound(error)) {\n * console.log(error.suggestion); // 'users'\n * }\n * ```\n */\nexport const Errors = {\n\t// -------------------------------------------------------------------------\n\t// Factory functions\n\t// -------------------------------------------------------------------------\n\n\t/**\n\t * Create an execution error (no adapter configured).\n\t */\n\texecution(opts: {\n\t\toperation: string;\n\t\treason: string;\n\t\tfix: string;\n\t}): ExecutionError & { code: typeof ErrorCode.EXECUTION_ERROR } {\n\t\tconst error = new ExecutionError(opts);\n\t\treturn Object.assign(error, { code: ErrorCode.EXECUTION_ERROR });\n\t},\n\n\t/**\n\t * Create a not found error (firstOrThrow returned no results).\n\t */\n\tnotFound(\n\t\ttable: string,\n\t\thint?: string,\n\t): NotFoundError & { code: typeof ErrorCode.NOT_FOUND } {\n\t\tconst error = new NotFoundError(table, hint);\n\t\treturn Object.assign(error, { code: ErrorCode.NOT_FOUND });\n\t},\n\n\t/**\n\t * Create an ambiguous relation error.\n\t */\n\tambiguousRelation(\n\t\tsourceTable: string,\n\t\ttargetTable: string,\n\t\toptions: readonly string[],\n\t): AmbiguousRelationError & { code: typeof ErrorCode.AMBIGUOUS_RELATION } {\n\t\tconst error = new AmbiguousRelationError(sourceTable, targetTable, options);\n\t\treturn Object.assign(error, { code: ErrorCode.AMBIGUOUS_RELATION });\n\t},\n\n\t/**\n\t * Create a relation not found error.\n\t */\n\trelationNotFound(opts: {\n\t\ttable: string;\n\t\trequested: string;\n\t\tavailable: readonly string[];\n\t}): RelationNotFoundError & { code: typeof ErrorCode.RELATION_NOT_FOUND } {\n\t\tconst error = new RelationNotFoundError(opts);\n\t\treturn Object.assign(error, { code: ErrorCode.RELATION_NOT_FOUND });\n\t},\n\n\t/**\n\t * Create an invalid operation error.\n\t */\n\tinvalidOperation(\n\t\toperation: string,\n\t\treason: string,\n\t): InvalidOperationError & { code: typeof ErrorCode.INVALID_OPERATION } {\n\t\tconst error = new InvalidOperationError(operation, reason);\n\t\treturn Object.assign(error, { code: ErrorCode.INVALID_OPERATION });\n\t},\n\n\t/**\n\t * Create an unsafe operation error.\n\t */\n\tunsafeOperation(\n\t\toperation: string,\n\t\tfix: string,\n\t): UnsafeOperationError & { code: typeof ErrorCode.UNSAFE_OPERATION } {\n\t\tconst error = new UnsafeOperationError(operation, fix);\n\t\treturn Object.assign(error, { code: ErrorCode.UNSAFE_OPERATION });\n\t},\n\n\t/**\n\t * Create a table not found error.\n\t */\n\ttableNotFound(opts: {\n\t\trequested: string;\n\t\tavailable: readonly string[];\n\t}): TableNotFoundError & { code: typeof ErrorCode.TABLE_NOT_FOUND } {\n\t\tconst error = new TableNotFoundError(opts);\n\t\treturn Object.assign(error, { code: ErrorCode.TABLE_NOT_FOUND });\n\t},\n\n\t/**\n\t * Create a column not found error.\n\t */\n\tcolumnNotFound(opts: {\n\t\ttable: string;\n\t\trequested: string;\n\t\tavailable: readonly string[];\n\t}): ColumnNotFoundError & { code: typeof ErrorCode.COLUMN_NOT_FOUND } {\n\t\tconst error = new ColumnNotFoundError(opts);\n\t\treturn Object.assign(error, { code: ErrorCode.COLUMN_NOT_FOUND });\n\t},\n\n\t// -------------------------------------------------------------------------\n\t// Type guards\n\t// -------------------------------------------------------------------------\n\n\t/** Check if error is an ExecutionError */\n\tisExecution(error: unknown): error is ExecutionError {\n\t\treturn error instanceof ExecutionError;\n\t},\n\n\t/** Check if error is a NotFoundError */\n\tisNotFound(error: unknown): error is NotFoundError {\n\t\treturn error instanceof NotFoundError;\n\t},\n\n\t/** Check if error is an AmbiguousRelationError */\n\tisAmbiguousRelation(error: unknown): error is AmbiguousRelationError {\n\t\treturn error instanceof AmbiguousRelationError;\n\t},\n\n\t/** Check if error is a RelationNotFoundError */\n\tisRelationNotFound(error: unknown): error is RelationNotFoundError {\n\t\treturn error instanceof RelationNotFoundError;\n\t},\n\n\t/** Check if error is an InvalidOperationError */\n\tisInvalidOperation(error: unknown): error is InvalidOperationError {\n\t\treturn error instanceof InvalidOperationError;\n\t},\n\n\t/** Check if error is an UnsafeOperationError */\n\tisUnsafeOperation(error: unknown): error is UnsafeOperationError {\n\t\treturn error instanceof UnsafeOperationError;\n\t},\n\n\t/** Check if error is a TableNotFoundError */\n\tisTableNotFound(error: unknown): error is TableNotFoundError {\n\t\treturn error instanceof TableNotFoundError;\n\t},\n\n\t/** Check if error is a ColumnNotFoundError */\n\tisColumnNotFound(error: unknown): error is ColumnNotFoundError {\n\t\treturn error instanceof ColumnNotFoundError;\n\t},\n\n\t/** Check if error is a NamingConventionMismatchError */\n\tisNamingConventionMismatch(\n\t\terror: unknown,\n\t): error is NamingConventionMismatchError {\n\t\treturn error instanceof NamingConventionMismatchError;\n\t},\n\n\t/** Check if error is any DBSP error */\n\tisDbspError(\n\t\terror: unknown,\n\t): error is\n\t\t| ExecutionError\n\t\t| NotFoundError\n\t\t| AmbiguousRelationError\n\t\t| RelationNotFoundError\n\t\t| InvalidOperationError\n\t\t| UnsafeOperationError\n\t\t| TableNotFoundError\n\t\t| ColumnNotFoundError\n\t\t| NamingConventionMismatchError {\n\t\treturn (\n\t\t\terror instanceof ExecutionError ||\n\t\t\terror instanceof NotFoundError ||\n\t\t\terror instanceof AmbiguousRelationError ||\n\t\t\terror instanceof RelationNotFoundError ||\n\t\t\terror instanceof InvalidOperationError ||\n\t\t\terror instanceof UnsafeOperationError ||\n\t\t\terror instanceof TableNotFoundError ||\n\t\t\terror instanceof ColumnNotFoundError ||\n\t\t\terror instanceof NamingConventionMismatchError\n\t\t);\n\t},\n\n\t/** Check if error has a DBSP error code */\n\thasCode(error: unknown): error is Error & { code: ErrorCode } {\n\t\treturn (\n\t\t\terror instanceof Error &&\n\t\t\t'code' in error &&\n\t\t\ttypeof (error as Error & { code: unknown }).code === 'string' &&\n\t\t\t(error as Error & { code: string }).code.startsWith('DBSP_E')\n\t\t);\n\t},\n} as const;\n","/**\n * @module planner\n * Semantic Planner - Decision engine for query planning.\n * Transforms QueryIntent + ModelIR into PlanReport with strategic decisions.\n *\n * Type definitions live in @dbsp/types. This module re-exports them\n * and provides runtime functions.\n */\n\nimport type {\n\tCTEDefinition,\n\tDecisionType,\n\tDialectCapabilities,\n\tIncludeStrategy,\n\tPlanDecision,\n\tPlanOptions,\n\tPlanReport,\n\tPlanWarning,\n\tRecursivePlanOptions,\n\tRecursivePlanReport,\n\tResolvedIncludeStrategy,\n} from '@dbsp/types';\nimport { InvalidOperationError } from './dx/errors.js';\nimport {\n\tgetNodeIdAlias,\n\ttype IncludeIntent,\n\tisRawExpression,\n\ttype QueryIntent,\n\ttype RecursiveIntent,\n\ttype WhereAndIntent,\n\ttype WhereExistsIntent,\n\ttype WhereInIntent,\n\ttype WhereIntent,\n\ttype WhereNotIntent,\n\ttype WhereOrIntent,\n} from './intent-ast.js';\nimport type { ModelIR, RelationIR } from './model-ir.js';\n\n// Re-export all planner types from @dbsp/types for backward compatibility\nexport type {\n\tCTEDefinition,\n\tDecisionType,\n\tPlanDecision,\n\tPlanOptions,\n\tPlanReport,\n\tPlanWarning,\n\tPlanWarningCode,\n\tRecursivePlanOptions,\n\tRecursivePlanReport,\n\tResolvedIncludeStrategy,\n} from '@dbsp/types';\n\n// ============================================================================\n// Warning Types\n// ============================================================================\n\n/**\n * Warning codes for planning issues\n */\n\n/**\n * A warning about the query plan\n */\n\n// ============================================================================\n// CTE Types\n// ============================================================================\n\n/**\n * CTE definition for extracted subqueries\n */\n\n// ============================================================================\n// Plan Report\n// ============================================================================\n\n/**\n * Complete plan report\n */\n\n// ============================================================================\n// Plan Options\n// ============================================================================\n\n/**\n * Planning options for customization\n */\n\n// ============================================================================\n// Errors\n// ============================================================================\n\n/**\n * Error thrown when plan cannot be created due to ambiguity\n */\nexport class AmbiguousPlanError extends Error {\n\treadonly sourceTable: string;\n\treadonly targetTable: string;\n\treadonly options: readonly string[];\n\n\tconstructor(\n\t\tsourceTable: string,\n\t\ttargetTable: string,\n\t\toptions: readonly string[],\n\t) {\n\t\tsuper(\n\t\t\t`Ambiguous relation from \"${sourceTable}\" to \"${targetTable}\". ` +\n\t\t\t\t`Use \"via\" to specify one of: ${options.join(', ')}`,\n\t\t);\n\t\tthis.name = 'AmbiguousPlanError';\n\t\tthis.sourceTable = sourceTable;\n\t\tthis.targetTable = targetTable;\n\t\tthis.options = options;\n\t}\n}\n\n/**\n * Error thrown when recursive CTE base/recursive cases have incompatible shapes.\n * Per RFC-001: columns must match in count, order, and be type-compatible.\n */\nexport class RecursiveShapeMismatchError extends Error {\n\treadonly cteName: string;\n\treadonly baseColumns: readonly string[];\n\treadonly recursiveColumns: readonly string[];\n\treadonly mismatchDetails: string;\n\n\tconstructor(\n\t\tcteName: string,\n\t\tbaseColumns: readonly string[],\n\t\trecursiveColumns: readonly string[],\n\t\tmismatchDetails: string,\n\t) {\n\t\tsuper(\n\t\t\t`Recursive CTE \"${cteName}\" shape mismatch: ${mismatchDetails}. ` +\n\t\t\t\t`Base columns: [${baseColumns.join(', ')}], ` +\n\t\t\t\t`Recursive columns: [${recursiveColumns.join(', ')}]`,\n\t\t);\n\t\tthis.name = 'RecursiveShapeMismatchError';\n\t\tthis.cteName = cteName;\n\t\tthis.baseColumns = baseColumns;\n\t\tthis.recursiveColumns = recursiveColumns;\n\t\tthis.mismatchDetails = mismatchDetails;\n\t}\n}\n\n// ============================================================================\n// Recursive CTE Shape Validation Helpers\n// ============================================================================\n\n/**\n * Computes expected base case columns from RecursiveIntent.\n * Order: [node_id_alias, ...select_fields, depth (if track.depth), path (if track.path)]\n */\nfunction computeBaseColumns(intent: RecursiveIntent): readonly string[] {\n\tconst columns: string[] = [];\n\n\t// node_id is always first\n\tcolumns.push(getNodeIdAlias(intent.start.nodeIdExpr));\n\n\t// select fields (if specified)\n\tif (intent.start.select) {\n\t\tcolumns.push(...intent.start.select);\n\t}\n\n\t// tracked columns\n\tif (intent.track?.depth) {\n\t\tcolumns.push('depth');\n\t}\n\tif (intent.track?.path) {\n\t\tcolumns.push('path');\n\t}\n\n\treturn Object.freeze(columns);\n}\n\n/**\n * Computes expected recursive step columns from RecursiveIntent.\n * Must match base columns in count and order.\n */\nfunction computeRecursiveColumns(intent: RecursiveIntent): readonly string[] {\n\tconst columns: string[] = [];\n\n\t// node_id is always first (from traversal)\n\tcolumns.push(getNodeIdAlias(intent.start.nodeIdExpr));\n\n\t// select fields must match base\n\tif (intent.start.select) {\n\t\tcolumns.push(...intent.start.select);\n\t}\n\n\t// tracked columns with expressions\n\tif (intent.track?.depth) {\n\t\tcolumns.push('depth'); // Will be `prev.depth + 1`\n\t}\n\tif (intent.track?.path) {\n\t\tcolumns.push('path'); // Will be `prev.path || id`\n\t}\n\n\treturn Object.freeze(columns);\n}\n\n/**\n * Validates that base and recursive columns are shape-compatible.\n * Throws RecursiveShapeMismatchError if validation fails.\n */\nexport function validateRecursiveShape(intent: RecursiveIntent): void {\n\tconst baseColumns = computeBaseColumns(intent);\n\tconst recursiveColumns = computeRecursiveColumns(intent);\n\n\t// Check column count\n\tif (baseColumns.length !== recursiveColumns.length) {\n\t\tthrow new RecursiveShapeMismatchError(\n\t\t\tintent.cteName,\n\t\t\tbaseColumns,\n\t\t\trecursiveColumns,\n\t\t\t`column count mismatch: base has ${baseColumns.length}, recursive has ${recursiveColumns.length}`,\n\t\t);\n\t}\n\n\t// Check column order (names must match at each position)\n\tfor (let i = 0; i < baseColumns.length; i++) {\n\t\tif (baseColumns[i] !== recursiveColumns[i]) {\n\t\t\tthrow new RecursiveShapeMismatchError(\n\t\t\t\tintent.cteName,\n\t\t\t\tbaseColumns,\n\t\t\t\trecursiveColumns,\n\t\t\t\t`column ${i} name mismatch: base has \"${baseColumns[i]}\", recursive has \"${recursiveColumns[i]}\"`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Planner State (Internal)\n// ============================================================================\n\ninterface PlannerState {\n\tdecisions: PlanDecision[];\n\twarnings: PlanWarning[];\n\tctes: CTEDefinition[];\n\trelationsAnalyzed: number;\n\tdecisionCounters: Record<DecisionType, number>;\n\trelationAccessCounts: Map<string, string[]>; // relation path -> intent paths\n\tvisitedIncludes: Set<string>; // For circular detection\n}\n\n// ============================================================================\n// Planner Implementation\n// ============================================================================\n\n/**\n * Create a query plan from an intent and model\n */\nexport function plan(\n\tintent: QueryIntent,\n\tmodel: ModelIR,\n\toptions: PlanOptions = {},\n): PlanReport {\n\tconst startTime = performance.now();\n\n\tconst state: PlannerState = {\n\t\tdecisions: [],\n\t\twarnings: [],\n\t\tctes: [],\n\t\trelationsAnalyzed: 0,\n\t\tdecisionCounters: {\n\t\t\t'filter-strategy': 0,\n\t\t\t'join-type': 0,\n\t\t\t'include-strategy': 0,\n\t\t\t'cte-extraction': 0,\n\t\t\tambiguity: 0,\n\t\t\t'recursive-cte': 0,\n\t\t\t'bidirectional-edges': 0,\n\t\t},\n\t\trelationAccessCounts: new Map(),\n\t\tvisitedIncludes: new Set(),\n\t};\n\n\tconst opts: Required<PlanOptions> = {\n\t\tforceFilterStrategy: options.forceFilterStrategy as 'exists' | 'join',\n\t\tforceJoinType: options.forceJoinType as 'left' | 'inner',\n\t\tenableCTEs: options.enableCTEs ?? true,\n\t\tcteThreshold: options.cteThreshold ?? 2,\n\t\tmaxIncludeDepth: options.maxIncludeDepth ?? 5,\n\t\tdisambiguate: options.disambiguate ?? {},\n\t\tdefaultIncludeStrategy: options.defaultIncludeStrategy ?? 'auto',\n\t\tdialectCapabilities: options.dialectCapabilities as DialectCapabilities,\n\t};\n\n\t// Validate root table — skip when the FROM is a BatchValues unnest() source\n\t// (the alias is not a real table; schema validation would incorrectly fail)\n\tconst rootTable = intent.batchValuesSource\n\t\t? null\n\t\t: model.getTable(intent.from);\n\tif (!intent.batchValuesSource && !rootTable) {\n\t\tthrow new Error(`Unknown table: ${intent.from}`);\n\t}\n\n\t// Optimize IN-subquery → EXISTS when relation is known in schema\n\tconst optimizedWhere = intent.where\n\t\t? optimizeInToExists(intent.where, intent.from, model)\n\t\t: undefined;\n\n\t// Process where clause\n\tif (optimizedWhere) {\n\t\tprocessWhere(optimizedWhere, intent.from, model, state, opts, 'where');\n\t}\n\n\t// Process includes\n\tif (intent.include) {\n\t\tfor (let i = 0; i < intent.include.length; i++) {\n\t\t\tconst inc = intent.include[i];\n\t\t\tif (inc) {\n\t\t\t\tprocessInclude(\n\t\t\t\t\tinc,\n\t\t\t\t\tintent.from,\n\t\t\t\t\tmodel,\n\t\t\t\t\tstate,\n\t\t\t\t\topts,\n\t\t\t\t\t`include[${i}]`,\n\t\t\t\t\t0,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Extract CTEs if enabled\n\tif (opts.enableCTEs) {\n\t\textractCTEs(state, opts.cteThreshold);\n\t}\n\n\t// Detect raw SQL usage and add security warnings\n\tdetectRawSqlUsage(intent, state);\n\n\tconst planningTimeMs = performance.now() - startTime;\n\n\t// PERF (FIND-051): use .slice() instead of spread ([...arr]) — avoids the extra\n\t// iterable-protocol overhead; semantically identical for plain arrays.\n\tconst ambiguousDecision = state.decisions.find(\n\t\t(d) => d.type === 'ambiguity' && d.choice === 'unresolved',\n\t);\n\n\tconst metadata: PlanReport['metadata'] = ambiguousDecision\n\t\t? Object.freeze({\n\t\t\t\tplanningTimeMs,\n\t\t\t\trelationsAnalyzed: state.relationsAnalyzed,\n\t\t\t\tisAmbiguous: true,\n\t\t\t\tambiguousOptions: ambiguousDecision.alternatives as readonly string[],\n\t\t\t})\n\t\t: Object.freeze({\n\t\t\t\tplanningTimeMs,\n\t\t\t\trelationsAnalyzed: state.relationsAnalyzed,\n\t\t\t\tisAmbiguous: false,\n\t\t\t});\n\n\tconst report: PlanReport = {\n\t\trootTable: intent.from,\n\t\tdecisions: Object.freeze(state.decisions.slice()),\n\t\twarnings: Object.freeze(state.warnings.slice()),\n\t\tctes: Object.freeze(state.ctes.slice()),\n\t\tintent,\n\t\tmetadata,\n\t};\n\n\treturn Object.freeze(report);\n}\n\n// ============================================================================\n// Recursive Intent Planning\n// ============================================================================\n\n/**\n * RecursivePlanReport extends PlanReport with recursive-specific metadata.\n */\n\n/**\n * Options specific to recursive CTE planning.\n */\n\n/**\n * Create a plan for a recursive CTE intent.\n * Per RFC-001: validates shape, generates decisions for traversal strategy.\n */\nexport function planRecursive(\n\tintent: RecursiveIntent,\n\tmodel: ModelIR,\n\toptions: RecursivePlanOptions = {},\n): RecursivePlanReport {\n\tconst startTime = performance.now();\n\n\t// Step 1: Validate shape compatibility\n\tvalidateRecursiveShape(intent);\n\n\tconst state: PlannerState = {\n\t\tdecisions: [],\n\t\twarnings: [],\n\t\tctes: [],\n\t\trelationsAnalyzed: 0,\n\t\tdecisionCounters: {\n\t\t\t'filter-strategy': 0,\n\t\t\t'join-type': 0,\n\t\t\t'include-strategy': 0,\n\t\t\t'cte-extraction': 0,\n\t\t\tambiguity: 0,\n\t\t\t'recursive-cte': 0,\n\t\t\t'bidirectional-edges': 0,\n\t\t},\n\t\trelationAccessCounts: new Map(),\n\t\tvisitedIncludes: new Set(),\n\t};\n\n\t// Validate that start table exists\n\tconst startTable = model.getTable(intent.start.from);\n\tif (!startTable) {\n\t\tthrow new Error(`Unknown table: ${intent.start.from}`);\n\t}\n\n\t// Step 2: Generate recursive-cte decision\n\tconst traversalKind = intent.traversal.kind;\n\n\tconst recursiveCteDecision: PlanDecision = {\n\t\tid: generateDecisionId(state, 'recursive-cte'),\n\t\ttype: 'recursive-cte',\n\t\tcontext: {\n\t\t\tsourceTable: intent.start.from,\n\t\t\tintentPath: `recursive:${intent.cteName}`,\n\t\t},\n\t\tchoice: 'with-recursive',\n\t\treasoning: generateRecursiveReasoning(intent),\n\t\talternatives: ['with-recursive', 'iterative'],\n\t};\n\tstate.decisions.push(recursiveCteDecision);\n\n\t// Step 3: Handle bidirectional edges (for edge-table traversal)\n\tlet usesBidirectional = false;\n\tif (\n\t\ttraversalKind === 'edge-table' &&\n\t\tintent.traversal.kind === 'edge-table'\n\t) {\n\t\tconst edgeTraversal = intent.traversal;\n\t\tif (edgeTraversal.direction === 'both') {\n\t\t\tusesBidirectional = true;\n\n\t\t\tconst storageHint = edgeTraversal.edgeStorageHint ?? 'unknown';\n\t\t\tconst strategy =\n\t\t\t\toptions.forceBidirectionalStrategy ??\n\t\t\t\t(storageHint === 'directed-only' ? 'union-all' : 'union');\n\n\t\t\tconst bidirectionalDecision: PlanDecision = {\n\t\t\t\tid: generateDecisionId(state, 'bidirectional-edges'),\n\t\t\t\ttype: 'bidirectional-edges',\n\t\t\t\tcontext: {\n\t\t\t\t\tsourceTable: intent.start.from,\n\t\t\t\t\ttarget: edgeTraversal.edgeTable,\n\t\t\t\t\tintentPath: `recursive:${intent.cteName}:edges`,\n\t\t\t\t},\n\t\t\t\tchoice: strategy,\n\t\t\t\treasoning: generateBidirectionalReasoning(storageHint, strategy),\n\t\t\t\talternatives: ['union', 'union-all'],\n\t\t\t};\n\t\t\tstate.decisions.push(bidirectionalDecision);\n\n\t\t\t// Add warning if using union-all with unknown storage\n\t\t\tif (strategy === 'union-all' && storageHint === 'unknown') {\n\t\t\t\tstate.warnings.push({\n\t\t\t\t\tcode: 'POTENTIAL_ROW_EXPLOSION',\n\t\t\t\t\tmessage: `Bidirectional edge traversal with UNION ALL on unknown storage hint may produce duplicates`,\n\t\t\t\t\tsuggestion: `Set edgeStorageHint: 'directed-only' if edges are guaranteed uni-directional, or use dedupe: 'final'`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// Step 4: Validate maxDepth\n\tif (intent.maxDepth < 1) {\n\t\tthrow new Error(`maxDepth must be >= 1, got ${intent.maxDepth}`);\n\t}\n\n\tif (intent.maxDepth > 100) {\n\t\tstate.warnings.push({\n\t\t\tcode: 'DEEP_NESTING',\n\t\t\tmessage: `maxDepth of ${intent.maxDepth} is unusually high`,\n\t\t\tsuggestion: `Consider if you really need traversal depth > 100. Large values may cause performance issues.`,\n\t\t});\n\t}\n\n\tconst planningTimeMs = performance.now() - startTime;\n\n\tconst dedupeStrategy = intent.dedupe ?? 'none';\n\n\t// PERF (FIND-051): use .slice() instead of spread — avoids iterable-protocol overhead.\n\tconst report: RecursivePlanReport = {\n\t\trootTable: intent.start.from,\n\t\tdecisions: Object.freeze(state.decisions.slice()),\n\t\twarnings: Object.freeze(state.warnings.slice()),\n\t\tctes: Object.freeze(state.ctes.slice()),\n\t\tintent,\n\t\tmetadata: Object.freeze({\n\t\t\tplanningTimeMs,\n\t\t\trelationsAnalyzed: state.relationsAnalyzed,\n\t\t\tisAmbiguous: false,\n\t\t\tisRecursive: true as const,\n\t\t\ttraversalKind,\n\t\t\tusesBidirectional,\n\t\t\tdedupeStrategy,\n\t\t}),\n\t};\n\n\treturn Object.freeze(report) as RecursivePlanReport;\n}\n\n/**\n * Generate reasoning for recursive CTE decision.\n */\nfunction generateRecursiveReasoning(intent: RecursiveIntent): string {\n\tconst parts: string[] = [];\n\n\tparts.push(\n\t\t`Recursive CTE \"${intent.cteName}\" using ${intent.traversal.kind} traversal`,\n\t);\n\n\tif (intent.traversal.kind === 'adjacency') {\n\t\tparts.push(\n\t\t\t`direction=${intent.traversal.direction}, parentId=${intent.traversal.parentId}`,\n\t\t);\n\t} else if (intent.traversal.kind === 'edge-table') {\n\t\tparts.push(\n\t\t\t`edgeTable=${intent.traversal.edgeTable}, direction=${intent.traversal.direction}`,\n\t\t);\n\t}\n\n\tparts.push(`maxDepth=${intent.maxDepth}`);\n\n\tif (intent.dedupe && intent.dedupe !== 'none') {\n\t\tparts.push(`dedupe=${intent.dedupe}`);\n\t}\n\n\treturn parts.join(', ');\n}\n\n/**\n * Generate reasoning for bidirectional edge decision.\n */\nfunction generateBidirectionalReasoning(\n\tstorageHint: 'unknown' | 'directed-only',\n\tstrategy: 'union' | 'union-all',\n): string {\n\tif (storageHint === 'directed-only') {\n\t\treturn strategy === 'union-all'\n\t\t\t? 'edgeStorageHint=directed-only guarantees no reverse duplicates, UNION ALL is safe'\n\t\t\t: 'UNION used despite directed-only hint (forced or conservative)';\n\t}\n\treturn strategy === 'union'\n\t\t? 'edgeStorageHint=unknown, using UNION to eliminate potential duplicates'\n\t\t: 'UNION ALL used despite unknown storage hint (may produce duplicates)';\n}\n\n// ============================================================================\n// IN → EXISTS Optimization\n// ============================================================================\n\n/**\n * Optimize IN (subquery) → EXISTS when the subquery targets a known relation.\n *\n * Pattern detected:\n * WHERE id IN (SELECT customer_id FROM orders WHERE ...)\n * Rewritten to:\n * WHERE EXISTS (SELECT 1 FROM orders WHERE orders.customer_id = outer.id AND ...)\n *\n * This is a standard SQL optimization: EXISTS short-circuits on first match,\n * while IN materializes the full set. The rewrite is valid when the subquery\n * selects a FK column that references the outer table's PK.\n */\n\n/**\n * Check whether the FK column resolved by a WHERE EXISTS rewrite is provably\n * non-nullable in the ModelIR.\n *\n * Used to guard NOT(IN-subquery) → NOT EXISTS rewrites: SQL's three-valued logic\n * means `x NOT IN (SELECT y ...)` returns UNKNOWN (not TRUE) when y can be NULL,\n * so it excludes the row. NOT EXISTS does not have this behavior — it returns\n * TRUE when the subquery is empty. The rewrite is only semantically equivalent\n * when the FK column is NOT NULL.\n *\n * Returns `false` (conservative) when the relation or column cannot be resolved.\n */\nfunction isSubquerySelectedColumnNonNullable(\n\texistsIntent: { relation: string },\n\tsourceTable: string,\n\tmodel: ModelIR,\n): boolean {\n\tconst rel = model.getRelation(`${sourceTable}.${existsIntent.relation}`);\n\tif (!rel) return false;\n\n\tconst fk =\n\t\ttypeof rel.foreignKey === 'string' ? rel.foreignKey : rel.foreignKey?.[0];\n\tif (!fk) return false;\n\n\tconst targetTableIR = model.getTable(rel.target);\n\tif (!targetTableIR) return false;\n\n\tconst column = targetTableIR.columns.find((c) => c.name === fk);\n\tif (!column) return false;\n\n\treturn !column.nullable;\n}\n\nfunction optimizeInToExists(\n\twhere: WhereIntent,\n\tsourceTable: string,\n\tmodel: ModelIR,\n): WhereIntent {\n\tswitch (where.kind) {\n\t\tcase 'in': {\n\t\t\tconst inWhere = where as WhereInIntent;\n\t\t\tif (!inWhere.subquery) return where;\n\n\t\t\t// Extract the single column from the subquery's select\n\t\t\tconst subSelect = inWhere.subquery.select;\n\t\t\tif (!subSelect || subSelect.type !== 'fields') return where;\n\t\t\tconst fields = 'fields' in subSelect ? subSelect.fields : undefined;\n\t\t\tif (!fields || fields.length !== 1) return where;\n\t\t\tconst subColumn = fields[0];\n\t\t\tif (!subColumn) return where;\n\n\t\t\t// Look for a relation from sourceTable to subquery's table\n\t\t\t// where the FK column matches the subquery's selected column\n\t\t\tconst relationsFrom = model.getRelationsFrom(sourceTable);\n\t\t\tconst sourceTableIR = model.getTable(sourceTable);\n\t\t\t// For composite PKs, only the first column is checked — multi-column\n\t\t\t// IN-subquery optimization is not supported (falls through as-is).\n\t\t\tconst sourcePk =\n\t\t\t\ttypeof sourceTableIR?.primaryKey === 'string'\n\t\t\t\t\t? sourceTableIR.primaryKey\n\t\t\t\t\t: (sourceTableIR?.primaryKey?.[0] ?? 'id');\n\n\t\t\tlet matchedRelation: string | undefined;\n\n\t\t\tfor (const rel of relationsFrom) {\n\t\t\t\tif (rel.target !== inWhere.subquery.from) continue;\n\t\t\t\tconst fk =\n\t\t\t\t\ttypeof rel.foreignKey === 'string'\n\t\t\t\t\t\t? rel.foreignKey\n\t\t\t\t\t\t: rel.foreignKey?.[0];\n\n\t\t\t\t// hasMany: outer.pk IN (SELECT fk FROM target WHERE ...)\n\t\t\t\t// The subquery selects the FK column, outer field is PK\n\t\t\t\tif (\n\t\t\t\t\trel.type === 'hasMany' &&\n\t\t\t\t\tfk === subColumn &&\n\t\t\t\t\tinWhere.field === sourcePk\n\t\t\t\t) {\n\t\t\t\t\tmatchedRelation = rel.name;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!matchedRelation) return where;\n\n\t\t\t// Rewrite to EXISTS (NOT IN is handled by the 'not' case below)\n\t\t\tconst existsWhere: WhereExistsIntent = {\n\t\t\t\tkind: 'exists',\n\t\t\t\trelation: matchedRelation,\n\t\t\t\t// Forward the subquery's inner WHERE conditions\n\t\t\t\t...(inWhere.subquery.where && { where: inWhere.subquery.where }),\n\t\t\t} as WhereExistsIntent;\n\n\t\t\treturn existsWhere;\n\t\t}\n\n\t\tcase 'and': {\n\t\t\tconst andWhere = where as WhereAndIntent;\n\t\t\tconst optimized = andWhere.conditions.map((c) =>\n\t\t\t\toptimizeInToExists(c, sourceTable, model),\n\t\t\t);\n\t\t\tif (optimized.every((c, i) => c === andWhere.conditions[i])) return where;\n\t\t\treturn { kind: 'and', conditions: optimized } as WhereAndIntent;\n\t\t}\n\n\t\tcase 'or': {\n\t\t\tconst orWhere = where as WhereOrIntent;\n\t\t\tconst optimized = orWhere.conditions.map((c) =>\n\t\t\t\toptimizeInToExists(c, sourceTable, model),\n\t\t\t);\n\t\t\tif (optimized.every((c, i) => c === orWhere.conditions[i])) return where;\n\t\t\treturn { kind: 'or', conditions: optimized } as WhereOrIntent;\n\t\t}\n\n\t\tcase 'not': {\n\t\t\tconst notWhere = where as WhereNotIntent;\n\t\t\tconst optimized = optimizeInToExists(\n\t\t\t\tnotWhere.condition,\n\t\t\t\tsourceTable,\n\t\t\t\tmodel,\n\t\t\t);\n\t\t\tif (optimized === notWhere.condition) return where;\n\t\t\t// NOT(EXISTS) → notExists (direct, no wrapper)\n\t\t\t// Guard: only convert when the FK column is provably non-nullable.\n\t\t\t// SQL's three-valued logic means NOT IN returns UNKNOWN (excludes row)\n\t\t\t// when the subquery can produce NULLs, whereas NOT EXISTS always\n\t\t\t// returns TRUE for an empty subquery. The rewrite is only valid when\n\t\t\t// the selected column is NOT NULL.\n\t\t\tif (optimized.kind === 'exists') {\n\t\t\t\tif (\n\t\t\t\t\t!isSubquerySelectedColumnNonNullable(\n\t\t\t\t\t\toptimized as { relation: string },\n\t\t\t\t\t\tsourceTable,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\t// Column is nullable or unknown — preserve NOT(IN) semantics\n\t\t\t\t\treturn where;\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\t...optimized,\n\t\t\t\t\tkind: 'notExists',\n\t\t\t\t} as unknown as WhereIntent;\n\t\t\t}\n\t\t\treturn { kind: 'not', condition: optimized } as WhereNotIntent;\n\t\t}\n\n\t\tdefault:\n\t\t\treturn where;\n\t}\n}\n\n// ============================================================================\n// Where Processing\n// ============================================================================\n\nfunction processWhere(\n\twhere: WhereIntent,\n\tsourceTable: string,\n\tmodel: ModelIR,\n\tstate: PlannerState,\n\topts: Required<PlanOptions>,\n\tintentPath: string,\n): void {\n\tswitch (where.kind) {\n\t\tcase 'exists':\n\t\tcase 'notExists':\n\t\t\tprocessRelationFilter(\n\t\t\t\twhere.relation,\n\t\t\t\tsourceTable,\n\t\t\t\tmodel,\n\t\t\t\tstate,\n\t\t\t\topts,\n\t\t\t\t`${intentPath}.${where.kind}`,\n\t\t\t\twhere.where,\n\t\t\t);\n\t\t\tbreak;\n\n\t\tcase 'relationFilter':\n\t\t\tprocessRelationFilter(\n\t\t\t\twhere.relation,\n\t\t\t\tsourceTable,\n\t\t\t\tmodel,\n\t\t\t\tstate,\n\t\t\t\topts,\n\t\t\t\t`${intentPath}.relationFilter`,\n\t\t\t\twhere.where,\n\t\t\t\twhere.mode,\n\t\t\t);\n\t\t\tbreak;\n\n\t\tcase 'and':\n\t\t\tfor (let i = 0; i < where.conditions.length; i++) {\n\t\t\t\tconst cond = where.conditions[i];\n\t\t\t\tif (cond) {\n\t\t\t\t\tprocessWhere(\n\t\t\t\t\t\tcond,\n\t\t\t\t\t\tsourceTable,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\topts,\n\t\t\t\t\t\t`${intentPath}.and[${i}]`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 'or':\n\t\t\tfor (let i = 0; i < where.conditions.length; i++) {\n\t\t\t\tconst cond = where.conditions[i];\n\t\t\t\tif (cond) {\n\t\t\t\t\tprocessWhere(\n\t\t\t\t\t\tcond,\n\t\t\t\t\t\tsourceTable,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\topts,\n\t\t\t\t\t\t`${intentPath}.or[${i}]`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 'not':\n\t\t\tprocessWhere(\n\t\t\t\twhere.condition,\n\t\t\t\tsourceTable,\n\t\t\t\tmodel,\n\t\t\t\tstate,\n\t\t\t\topts,\n\t\t\t\t`${intentPath}.not`,\n\t\t\t);\n\t\t\tbreak;\n\n\t\t// Scalar conditions don't need relation analysis\n\t\tcase 'comparison':\n\t\tcase 'like':\n\t\tcase 'in':\n\t\tcase 'any':\n\t\tcase 'null':\n\t\t\t// No relation analysis needed\n\t\t\tbreak;\n\n\t\tcase 'expression':\n\t\t\tbreak; // Custom expression — no relation analysis, pass through\n\t}\n}\n\nfunction processRelationFilter(\n\trelationPath: string | readonly string[],\n\tsourceTable: string,\n\tmodel: ModelIR,\n\tstate: PlannerState,\n\topts: Required<PlanOptions>,\n\tintentPath: string,\n\tnestedWhere?: WhereIntent,\n\tmode?: 'some' | 'every' | 'none',\n): void {\n\tstate.relationsAnalyzed++;\n\n\t// Normalize relation path to array (SPEC-002: multi-hop support)\n\tconst relations = Array.isArray(relationPath) ? relationPath : [relationPath];\n\n\t// Process each relation in the chain\n\tlet currentSource = sourceTable;\n\tfor (let i = 0; i < relations.length; i++) {\n\t\tconst relationName = relations[i];\n\t\tif (!relationName) continue;\n\n\t\tconst isLastInChain = i === relations.length - 1;\n\t\tconst chainPath = `${intentPath}[${i}]`;\n\n\t\t// Find the relation\n\t\tconst relation = disambiguateRelation(\n\t\t\trelationName,\n\t\t\tcurrentSource,\n\t\t\tmodel,\n\t\t\tstate,\n\t\t\topts,\n\t\t\tchainPath,\n\t\t);\n\n\t\tif (!relation) {\n\t\t\treturn; // Error already added to warnings or exception thrown\n\t\t}\n\n\t\t// Track relation access for CTE extraction\n\t\tconst relPath = `${currentSource}.${relation.name}`;\n\t\tconst paths = state.relationAccessCounts.get(relPath) ?? [];\n\t\tpaths.push(chainPath);\n\t\tstate.relationAccessCounts.set(relPath, paths);\n\n\t\t// Determine filter strategy (only for last relation in chain)\n\t\tif (isLastInChain) {\n\t\t\tconst filterStrategy = determineFilterStrategy(\n\t\t\t\trelation,\n\t\t\t\topts,\n\t\t\t\tmode ?? 'some',\n\t\t\t);\n\n\t\t\tconst decisionId = generateDecisionId(state, 'filter-strategy');\n\t\t\t// Detect self-referential relation (source === target)\n\t\t\tconst isSelfRef = relation.source === relation.target;\n\t\t\t// SPEC-002: Include full path in context for multi-hop\n\t\t\tconst context: PlanDecision['context'] = {\n\t\t\t\tsourceTable: currentSource,\n\t\t\t\ttarget: relation.target,\n\t\t\t\trelation: relation.name,\n\t\t\t\tintentPath: chainPath,\n\t\t\t\t...(relations.length > 1 && { relationPath: relations.join('.') }),\n\t\t\t\t...(isSelfRef && { isSelfRef }),\n\t\t\t};\n\t\t\tstate.decisions.push({\n\t\t\t\tid: decisionId,\n\t\t\t\ttype: 'filter-strategy',\n\t\t\t\tcontext,\n\t\t\t\tchoice: filterStrategy,\n\t\t\t\treasoning: generateFilterReasoning(\n\t\t\t\t\trelation,\n\t\t\t\t\tfilterStrategy,\n\t\t\t\t\tmode,\n\t\t\t\t\tisSelfRef,\n\t\t\t\t),\n\t\t\t\talternatives: filterStrategy === 'exists' ? ['join'] : ['exists'],\n\t\t\t});\n\n\t\t\t// Check for potential row explosion warning\n\t\t\tif (filterStrategy === 'join' && relation.cardinality === 'many') {\n\t\t\t\tstate.warnings.push({\n\t\t\t\t\tcode: 'POTENTIAL_ROW_EXPLOSION',\n\t\t\t\t\tmessage: `Using JOIN on to-many relation \"${relation.name}\" may cause row multiplication`,\n\t\t\t\t\tsuggestion: `Consider using EXISTS strategy for relation \"${relation.name}\"`,\n\t\t\t\t\trelatedDecision: decisionId,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Process nested where on the final target\n\t\t\tif (nestedWhere) {\n\t\t\t\tprocessWhere(\n\t\t\t\t\tnestedWhere,\n\t\t\t\t\trelation.target,\n\t\t\t\t\tmodel,\n\t\t\t\t\tstate,\n\t\t\t\t\topts,\n\t\t\t\t\t`${intentPath}.where`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Move to next table in chain\n\t\tcurrentSource = relation.target;\n\t}\n}\n\n// ============================================================================\n// Include Processing\n// ============================================================================\n\nfunction processInclude(\n\tinclude: IncludeIntent,\n\tsourceTable: string,\n\tmodel: ModelIR,\n\tstate: PlannerState,\n\topts: Required<PlanOptions>,\n\tintentPath: string,\n\tdepth: number,\n\tancestorIsLeftJoin = false,\n): void {\n\tstate.relationsAnalyzed++;\n\n\t// Check depth\n\tif (depth > opts.maxIncludeDepth) {\n\t\tstate.warnings.push({\n\t\t\tcode: 'DEEP_NESTING',\n\t\t\tmessage: `Include depth ${depth} exceeds maximum ${opts.maxIncludeDepth}`,\n\t\t\tsuggestion: 'Consider flattening the query or increasing maxIncludeDepth',\n\t\t});\n\t}\n\n\t// Use via hint if provided, otherwise use relation name\n\tconst relationName = include.via ?? include.relation;\n\n\t// Resolve the relation\n\tconst relation = disambiguateRelation(\n\t\trelationName,\n\t\tsourceTable,\n\t\tmodel,\n\t\tstate,\n\t\topts,\n\t\tintentPath,\n\t\tinclude.via,\n\t);\n\n\tif (!relation) {\n\t\treturn;\n\t}\n\n\t// Check for circular includes\n\tconst includePath = `${sourceTable}.${relation.name}`;\n\tif (state.visitedIncludes.has(includePath)) {\n\t\tstate.warnings.push({\n\t\t\tcode: 'CIRCULAR_INCLUDE',\n\t\t\tmessage: `Circular include detected: ${includePath}`,\n\t\t\tsuggestion: 'Remove circular include to prevent infinite recursion',\n\t\t});\n\t\treturn;\n\t}\n\tstate.visitedIncludes.add(includePath);\n\n\t// Track relation access for CTE extraction\n\tconst relationPath = `${sourceTable}.${relation.name}`;\n\tconst paths = state.relationAccessCounts.get(relationPath) ?? [];\n\tpaths.push(intentPath);\n\tstate.relationAccessCounts.set(relationPath, paths);\n\n\t// CLI-012c: Check for recursive include on self-referential relations\n\tconst isRecursiveInclude =\n\t\t(!!include.recursive || !!relation.recursive) &&\n\t\trelation.source === relation.target;\n\n\t// Determine include strategy\n\t// Priority: 1) recursive → cte (if dialect supports it), 2) include.join → forces join strategy, 3) include.strategy override, 4) auto-detect\n\tlet includeStrategy: ResolvedIncludeStrategy;\n\tif (isRecursiveInclude) {\n\t\t// FIND-013: Guard recursive → cte against dialect capability.\n\t\t// selectSmartStrategy handles the general case, but processInclude has\n\t\t// an early-exit path that forces 'cte' before reaching it. A dialect\n\t\t// that declared supportsRecursiveCTE=false must not silently receive an\n\t\t// invalid plan.\n\t\tif (opts.dialectCapabilities?.supportsRecursiveCTE === false) {\n\t\t\tthrow new UnsupportedStrategyError(\n\t\t\t\t`Recursive includes require a dialect with supportsRecursiveCTE; ` +\n\t\t\t\t\t`current dialect (${opts.dialectCapabilities.name}) declared it unsupported.`,\n\t\t\t);\n\t\t}\n\t\tincludeStrategy = 'cte';\n\t} else if (include.join !== undefined) {\n\t\t// Explicit join type forces the 'join' strategy (inner or left JOIN)\n\t\tif (include.limit != null) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'include',\n\t\t\t\t`include.limit cannot be applied with the 'join' strategy because join ` +\n\t\t\t\t\t`cannot enforce per-parent-row limits. ` +\n\t\t\t\t\t`Use strategy: 'flat' (→ LATERAL) or strategy: 'cte' explicitly.`,\n\t\t\t);\n\t\t}\n\t\tincludeStrategy = 'join';\n\t} else if (include.strategy === 'flat') {\n\t\t// NQL v2.1: flat = exclude nested output (json_agg), planner picks best flat strategy\n\t\t// lateral only when per-row LIMIT is needed; otherwise join is simpler\n\t\t// Also use lateral when any nested child has a limit (LATERAL cascade required)\n\t\tconst needsLateral = include.limit != null || hasNestedLimit(include);\n\t\tincludeStrategy = selectSmartStrategy(\n\t\t\trelation,\n\t\t\topts.dialectCapabilities,\n\t\t\tfalse,\n\t\t\t/* excludeNested */ true,\n\t\t\t/* hasLimit */ needsLateral,\n\t\t);\n\t} else {\n\t\tincludeStrategy = determineIncludeStrategy(relation, opts);\n\t\t// FIND-014: include.limit cannot be enforced by the join strategy (which\n\t\t// performs a flat JOIN without per-parent-row limiting). Silently\n\t\t// dropping the limit produces unlimited children — incorrect behaviour.\n\t\t// Callers must explicitly request 'flat' (→ lateral) or 'cte' to get\n\t\t// per-parent limiting.\n\t\tif (include.limit != null && includeStrategy === 'join') {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'include',\n\t\t\t\t`include.limit cannot be applied with the 'join' strategy because join ` +\n\t\t\t\t\t`cannot enforce per-parent-row limits. ` +\n\t\t\t\t\t`Use strategy: 'flat' (→ LATERAL) or strategy: 'cte' explicitly.`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Pre-compute join type for include-strategy decision embedding\n\t// (only relevant when strategy is 'join')\n\t// When an ancestor used LEFT JOIN (optional relation), cascade LEFT to preserve\n\t// parent rows — even for relations that would normally be INNER (required).\n\t// An explicit join: 'inner' override on THIS hop resets the cascade for children.\n\tconst autoJoinType = determineJoinType(relation, opts, !!include.where);\n\tconst cascadedJoinType: 'inner' | 'left' =\n\t\tancestorIsLeftJoin && include.join === undefined ? 'left' : autoJoinType;\n\tconst explicitJoinType: 'inner' | 'left' | undefined =\n\t\tincludeStrategy === 'join' ? (include.join ?? cascadedJoinType) : undefined;\n\n\tconst includeDecisionId = generateDecisionId(state, 'include-strategy');\n\n\tstate.decisions.push({\n\t\tid: includeDecisionId,\n\t\ttype: 'include-strategy',\n\t\tcontext: {\n\t\t\tsourceTable,\n\t\t\ttarget: relation.target,\n\t\t\trelation: relation.name,\n\t\t\trelationType: relation.type,\n\t\t\tincludeAlias: include.relation,\n\t\t\tintentPath,\n\t\t\t// Foreign key info for json_agg compilation (Phase 3)\n\t\t\t...(relation.foreignKey !== undefined && {\n\t\t\t\tforeignKey: relation.foreignKey,\n\t\t\t}),\n\t\t},\n\t\tchoice: includeStrategy,\n\t\t// Embed joinType so the adapter's join handler can use it directly\n\t\t...(explicitJoinType !== undefined && { joinType: explicitJoinType }),\n\t\treasoning: isRecursiveInclude\n\t\t\t? `Recursive include on self-referential relation \"${relation.name}\" → forced CTE strategy`\n\t\t\t: generateIncludeReasoning(relation, includeStrategy),\n\t\talternatives: getAlternativeStrategies(\n\t\t\tincludeStrategy,\n\t\t\topts.dialectCapabilities,\n\t\t),\n\t});\n\n\t// CLI-012c: Warn if recursive is set but relation is not self-referential\n\tif (include.recursive && !isRecursiveInclude) {\n\t\tstate.warnings.push({\n\t\t\tcode: 'INVALID_RECURSIVE_INCLUDE',\n\t\t\tmessage: `recursive option on \"${relation.name}\" ignored: relation is not self-referential (source=${relation.source}, target=${relation.target})`,\n\t\t\tsuggestion: `Remove recursive option or use RecursiveIntent for cross-table recursion`,\n\t\t});\n\t}\n\n\t// CLI-012/CLI-012c: Create CTE when strategy is 'cte' (recursive or not)\n\tif (includeStrategy === 'cte') {\n\t\tconst cteName = `cte_${sourceTable}_${relation.name}`;\n\t\t// Check if CTE already exists (avoid duplicates from nested includes)\n\t\tconst existingCte = state.ctes.find((c) => c.name === cteName);\n\t\tif (!existingCte) {\n\t\t\tstate.ctes.push({\n\t\t\t\tname: cteName,\n\t\t\t\tpurpose: isRecursiveInclude\n\t\t\t\t\t? `Recursive include for self-referential \"${relation.name}\"`\n\t\t\t\t\t: `CTE for \"${relation.name}\" include`,\n\t\t\t\treferencedBy: [intentPath],\n\t\t\t\tsourceIntent: `${sourceTable}.${relation.name}`,\n\t\t\t\trecursive: isRecursiveInclude,\n\t\t\t});\n\t\t} else {\n\t\t\t// Add intentPath to existing CTE's referencedBy\n\t\t\t(existingCte.referencedBy as string[]).push(intentPath);\n\t\t}\n\t}\n\n\t// Emit join-type decision (only if using join strategy)\n\tif (includeStrategy === 'join' && explicitJoinType !== undefined) {\n\t\tconst joinDecisionId = generateDecisionId(state, 'join-type');\n\n\t\tstate.decisions.push({\n\t\t\tid: joinDecisionId,\n\t\t\ttype: 'join-type',\n\t\t\tcontext: {\n\t\t\t\tsourceTable,\n\t\t\t\ttarget: relation.target,\n\t\t\t\trelation: relation.name,\n\t\t\t\tintentPath,\n\t\t\t},\n\t\t\tchoice: explicitJoinType,\n\t\t\treasoning: generateJoinReasoning(\n\t\t\t\trelation,\n\t\t\t\texplicitJoinType,\n\t\t\t\t!!include.where,\n\t\t\t),\n\t\t\talternatives: explicitJoinType === 'left' ? ['inner'] : ['left'],\n\t\t});\n\t}\n\n\t// Process nested where\n\tif (include.where) {\n\t\tprocessWhere(\n\t\t\tinclude.where,\n\t\t\trelation.target,\n\t\t\tmodel,\n\t\t\tstate,\n\t\t\topts,\n\t\t\t`${intentPath}.where`,\n\t\t);\n\t}\n\n\t// Process nested includes\n\tif (include.include) {\n\t\t// Propagate LEFT JOIN cascade to children based on THIS hop's actual join type.\n\t\t// - If this hop emits LEFT JOIN → children inherit the cascade\n\t\t// - If this hop emits INNER JOIN (explicit or auto) → cascade resets\n\t\t// When strategy is not 'join' (json_agg, lateral, cte), explicitJoinType is\n\t\t// undefined → false → no cascade (non-join strategies don't affect the chain).\n\t\tconst nextAncestorIsLeftJoin = explicitJoinType === 'left';\n\t\tfor (let i = 0; i < include.include.length; i++) {\n\t\t\tconst nestedInc = include.include[i];\n\t\t\tif (nestedInc) {\n\t\t\t\tprocessInclude(\n\t\t\t\t\tnestedInc,\n\t\t\t\t\trelation.target,\n\t\t\t\t\tmodel,\n\t\t\t\t\tstate,\n\t\t\t\t\topts,\n\t\t\t\t\t`${intentPath}.include[${i}]`,\n\t\t\t\t\tdepth + 1,\n\t\t\t\t\tnextAncestorIsLeftJoin,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove from visited after processing (allow same relation at different depths)\n\tstate.visitedIncludes.delete(includePath);\n}\n\n// ============================================================================\n// Relation Resolution\n// ============================================================================\n\nfunction disambiguateRelation(\n\trelationName: string,\n\tsourceTable: string,\n\tmodel: ModelIR,\n\tstate: PlannerState,\n\topts: Required<PlanOptions>,\n\t_intentPath: string,\n\tviaHint?: string,\n): RelationIR | undefined {\n\t// Try direct lookup first\n\tconst directRelation = model.getRelation(`${sourceTable}.${relationName}`);\n\tif (directRelation) {\n\t\treturn directRelation;\n\t}\n\n\t// Check if this might be a target table name (ambiguous case)\n\tconst relationsToTarget = model\n\t\t.getRelationsFrom(sourceTable)\n\t\t.filter((r) => r.target === relationName);\n\n\tif (relationsToTarget.length === 0) {\n\t\t// Check for virtual recursive relations (ancestors/descendants)\n\t\t// These are auto-inferred from self-referential relations and handled by the compiler\n\t\tif (relationName === 'ancestors' || relationName === 'descendants') {\n\t\t\tconst selfReferentialRelations = model\n\t\t\t\t.getRelationsFrom(sourceTable)\n\t\t\t\t.filter((r) => r.source === r.target);\n\t\t\tif (selfReferentialRelations.length > 0) {\n\t\t\t\t// Virtual recursive relation - return the underlying self-referential relation\n\t\t\t\t// The compiler will handle the actual recursive CTE generation\n\t\t\t\treturn selfReferentialRelations[0];\n\t\t\t}\n\t\t}\n\n\t\t// No relation found\n\t\tstate.warnings.push({\n\t\t\tcode: 'AMBIGUOUS_RELATION',\n\t\t\tmessage: `Unknown relation \"${relationName}\" from table \"${sourceTable}\"`,\n\t\t\tsuggestion: `Check that the relation exists in the schema`,\n\t\t});\n\t\treturn undefined;\n\t}\n\n\tif (relationsToTarget.length === 1) {\n\t\t// Unambiguous - only one relation to target\n\t\treturn relationsToTarget[0];\n\t}\n\n\t// Multiple relations - need disambiguation\n\tconst options = relationsToTarget.map((r) => r.name);\n\n\t// Check for via hint\n\tif (viaHint) {\n\t\tconst resolved = relationsToTarget.find((r) => r.name === viaHint);\n\t\tif (resolved) {\n\t\t\treturn resolved;\n\t\t}\n\t}\n\n\t// Check disambiguate option\n\tconst disambiguateKey = `${sourceTable}.${relationName}`;\n\tconst disambiguated = opts.disambiguate[disambiguateKey];\n\tif (disambiguated) {\n\t\tconst resolved = relationsToTarget.find((r) => r.name === disambiguated);\n\t\tif (resolved) {\n\t\t\treturn resolved;\n\t\t}\n\t}\n\n\t// Ambiguous - throw error\n\tthrow new AmbiguousPlanError(sourceTable, relationName, options);\n}\n\n// ============================================================================\n// Strategy Determination\n// ============================================================================\n\nfunction determineFilterStrategy(\n\trelation: RelationIR,\n\topts: Required<PlanOptions>,\n\t_mode: 'some' | 'every' | 'none',\n): 'exists' | 'join' {\n\t// Forced strategy takes precedence\n\tif (opts.forceFilterStrategy) {\n\t\treturn opts.forceFilterStrategy;\n\t}\n\n\t// Use relation hint if not auto\n\tif (relation.filterStrategy !== 'auto') {\n\t\treturn relation.filterStrategy;\n\t}\n\n\t// Auto-determine based on cardinality and mode\n\tif (relation.cardinality === 'one') {\n\t\treturn 'join';\n\t}\n\n\t// For cardinality 'many', EXISTS is generally better\n\t// (avoids row explosion)\n\treturn 'exists';\n}\n\n/**\n * Resolved include strategy - the actual strategy to use (never 'auto').\n * This is what the compiler receives after planner decision.\n */\n\n/**\n * Determine the include strategy for a relation.\n *\n * Strategy selection logic (CORE-006):\n * 1. If relation has explicit strategy (not 'auto'), use it (after validation)\n * 2. If planner option has explicit strategy (not 'auto'), use it\n * 3. Smart auto selection based on:\n * - Relation type (hasOne/belongsTo → join, hasMany/belongsToMany → depends)\n * - Dialect capabilities (lateral, json_agg support)\n * - Recursive relations → cte\n *\n * @throws {UnsupportedStrategyError} if requested strategy not supported by dialect\n */\nfunction determineIncludeStrategy(\n\trelation: RelationIR,\n\topts: Required<PlanOptions>,\n\tisRecursive = false,\n): ResolvedIncludeStrategy {\n\tconst capabilities = opts.dialectCapabilities;\n\n\t// Helper to validate strategy against dialect capabilities\n\tconst validateStrategy = (\n\t\tstrategy: IncludeStrategy,\n\t): ResolvedIncludeStrategy => {\n\t\tif (strategy === 'auto') {\n\t\t\t// Should not happen, but fallback to join\n\t\t\treturn 'join';\n\t\t}\n\n\t\t// Validate against dialect capabilities if available\n\t\tif (capabilities) {\n\t\t\tif (strategy === 'lateral' && !capabilities.supportsLateralJoin) {\n\t\t\t\tthrow new UnsupportedStrategyError(\n\t\t\t\t\t`Strategy 'lateral' is not supported by ${capabilities.name}. ` +\n\t\t\t\t\t\t`Use 'join', 'subquery', or 'json_agg' instead.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (strategy === 'json_agg' && !capabilities.supportsJsonAgg) {\n\t\t\t\tthrow new UnsupportedStrategyError(\n\t\t\t\t\t`Strategy 'json_agg' is not supported by ${capabilities.name}. ` +\n\t\t\t\t\t\t`Use 'join', 'subquery', or 'lateral' instead.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (strategy === 'cte' && !capabilities.supportsRecursiveCTE) {\n\t\t\t\tthrow new UnsupportedStrategyError(\n\t\t\t\t\t`Strategy 'cte' is not supported by ${capabilities.name}. ` +\n\t\t\t\t\t\t`Use 'join' or 'subquery' instead.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn strategy;\n\t};\n\n\t// 1. Use relation hint if not auto (explicit override)\n\tif (relation.includeStrategy !== 'auto') {\n\t\treturn validateStrategy(relation.includeStrategy);\n\t}\n\n\t// 2. Use planner option if specified (CLI-010: runtime override)\n\tif (opts.defaultIncludeStrategy && opts.defaultIncludeStrategy !== 'auto') {\n\t\treturn validateStrategy(opts.defaultIncludeStrategy);\n\t}\n\n\t// 3. Smart auto selection based on relation type + dialect\n\treturn selectSmartStrategy(relation, capabilities, isRecursive);\n}\n\n/**\n * Check if any nested include (recursively) has a limit set.\n * Used to determine if an intermediate ancestor needs LATERAL for cascade.\n */\nfunction hasNestedLimit(include: IncludeIntent): boolean {\n\tif (!include.include || include.include.length === 0) return false;\n\tfor (const child of include.include) {\n\t\tif (child.limit != null) return true;\n\t\tif (hasNestedLimit(child)) return true;\n\t}\n\treturn false;\n}\n\n/**\n * Smart strategy selection based on relation characteristics and dialect.\n *\n * Selection algorithm:\n * - Recursive relations → 'cte' (if supported) or 'subquery'\n * - hasOne/belongsTo (to-one) → 'join' (always safe, single row)\n * - hasMany/belongsToMany (to-many):\n * - If dialect supports json_agg → 'json_agg' (single row per parent, no explosion)\n * - Else if dialect supports lateral → 'lateral' (good with LIMIT)\n * - Else → 'join' (let DB optimize, user can override to 'subquery' if needed)\n */\nfunction selectSmartStrategy(\n\t_relation: RelationIR,\n\tcapabilities: DialectCapabilities | undefined,\n\tisRecursive: boolean,\n\texcludeNested = false,\n\thasLimit = false,\n): ResolvedIncludeStrategy {\n\t// Recursive relations should use CTE\n\tif (isRecursive) {\n\t\tif (capabilities?.supportsRecursiveCTE !== false) {\n\t\t\treturn 'cte';\n\t\t}\n\t\t// Fallback for dialects without CTE support (rare)\n\t\treturn 'subquery';\n\t}\n\n\t// Default strategy for ALL relation types: json_agg\n\t// Rationale:\n\t// - json_agg: aggregates children into single JSON array, no row explosion\n\t// - Works for both to-one (hasOne, belongsTo) and to-many (hasMany)\n\t// - User can force JOIN via | flat modifier if data is too large for JSON\n\t// - lateral: only when per-row LIMIT is needed (top N children pattern)\n\t// - join: simple flat strategy, well-optimized by the database\n\n\tif (capabilities?.supportsJsonAgg && !excludeNested) {\n\t\treturn 'json_agg';\n\t}\n\n\t// LATERAL only when per-row LIMIT is needed — otherwise join is simpler and faster\n\tif (hasLimit && capabilities?.supportsLateralJoin) {\n\t\treturn 'lateral';\n\t}\n\n\t// Fallback: use join (database optimizer handles it)\n\t// User can explicitly request 'subquery' if row explosion is a concern\n\treturn 'join';\n}\n\n/**\n * Error thrown when requested include strategy is not supported by dialect.\n */\nexport class UnsupportedStrategyError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'UnsupportedStrategyError';\n\t}\n}\n\n/**\n * Get alternative strategies for a given strategy based on dialect capabilities.\n */\nfunction getAlternativeStrategies(\n\tstrategy: ResolvedIncludeStrategy,\n\tcapabilities: DialectCapabilities | undefined,\n): string[] {\n\tconst allStrategies: ResolvedIncludeStrategy[] = [\n\t\t'join',\n\t\t'subquery',\n\t\t'cte',\n\t\t'lateral',\n\t\t'json_agg',\n\t];\n\n\t// Filter out current strategy and unsupported ones\n\treturn allStrategies.filter((s) => {\n\t\tif (s === strategy) return false;\n\t\tif (!capabilities) return s === 'join' || s === 'subquery'; // No capabilities = only basic strategies\n\t\tif (s === 'lateral' && !capabilities.supportsLateralJoin) return false;\n\t\tif (s === 'json_agg' && !capabilities.supportsJsonAgg) return false;\n\t\tif (s === 'cte' && !capabilities.supportsRecursiveCTE) return false;\n\t\treturn true;\n\t});\n}\n\nfunction determineJoinType(\n\trelation: RelationIR,\n\topts: Required<PlanOptions>,\n\thasFilter: boolean,\n): 'left' | 'inner' {\n\t// Forced join type takes precedence\n\tif (opts.forceJoinType) {\n\t\treturn opts.forceJoinType;\n\t}\n\n\t// Use relation hint if not auto\n\tif (relation.joinDefault !== 'auto') {\n\t\treturn relation.joinDefault;\n\t}\n\n\t// Auto-determine based on optionality and filter presence\n\tif (relation.optionality === 'required') {\n\t\treturn 'inner';\n\t}\n\n\t// Optional relation with filter implies existence\n\tif (hasFilter) {\n\t\treturn 'inner';\n\t}\n\n\t// Optional without filter -> LEFT to preserve parent rows\n\treturn 'left';\n}\n\n// ============================================================================\n// Raw SQL Detection (Security Observability)\n// ============================================================================\n\n/**\n * Detects raw SQL expressions in the query intent and adds security warnings.\n * This provides observability for potentially unsafe SQL usage.\n */\nfunction detectRawSqlUsage(intent: QueryIntent, state: PlannerState): void {\n\t// Check SELECT expressions for raw SQL\n\tif (\n\t\tintent.select &&\n\t\t'type' in intent.select &&\n\t\tintent.select.type === 'expressions'\n\t) {\n\t\tfor (const col of intent.select.columns) {\n\t\t\t// Direct ExpressionIntent format - check if it's a raw expression\n\t\t\tif (isRawExpression(col)) {\n\t\t\t\tstate.warnings.push({\n\t\t\t\t\tcode: 'RAW_SQL_USAGE',\n\t\t\t\t\tmessage: `Raw SQL expression detected: \"${col.sql}\" (alias: ${col.as})`,\n\t\t\t\t\tsuggestion:\n\t\t\t\t\t\t'Raw SQL bypasses type safety and SQL injection protection. ' +\n\t\t\t\t\t\t'Ensure the SQL is safe and consider using built-in expression helpers instead.',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ============================================================================\n// CTE Extraction\n// ============================================================================\n\nfunction extractCTEs(state: PlannerState, threshold: number): void {\n\t// PERF (FIND-053): build O(1) lookup structures once before the R-relation loop,\n\t// replacing O(R×D) linear scans (decisions.find + ctes.some) inside the loop.\n\tconst decisionByTableRelation = new Map<string, PlanDecision>();\n\tfor (const d of state.decisions) {\n\t\tif (d.type === 'include-strategy') {\n\t\t\tconst k = `${d.context?.sourceTable ?? ''}:${d.context?.relation ?? ''}`;\n\t\t\t// Keep first match (earliest decision wins)\n\t\t\tif (!decisionByTableRelation.has(k)) {\n\t\t\t\tdecisionByTableRelation.set(k, d);\n\t\t\t}\n\t\t}\n\t}\n\tconst cteNameSet = new Set(state.ctes.map((c) => c.name));\n\n\tfor (const [relationPath, intentPaths] of state.relationAccessCounts) {\n\t\tif (intentPaths.length >= threshold) {\n\t\t\tconst parts = relationPath.split('.');\n\t\t\tconst table = parts[0] ?? 'unknown';\n\t\t\tconst relation = parts[1] ?? 'unknown';\n\t\t\tconst cteName = `cte_${table}_${relation}`;\n\n\t\t\t// SPEC-002: Skip CTE extraction if the include strategy is 'json_agg'.\n\t\t\t// json_agg uses a subquery that doesn't benefit from CTEs and would conflict.\n\t\t\t// Other strategies (join, cte, separate) can still use CTE extraction.\n\t\t\tconst includeStrategyDecision = decisionByTableRelation.get(\n\t\t\t\t`${table}:${relation}`,\n\t\t\t);\n\t\t\tif (includeStrategyDecision?.choice === 'json_agg') {\n\t\t\t\t// json_agg strategy uses its own subquery - CTE extraction not needed\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Skip if CTE already exists (from include processing)\n\t\t\tif (cteNameSet.has(cteName)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tstate.ctes.push({\n\t\t\t\tname: cteName,\n\t\t\t\tpurpose: `${relation} relation accessed ${intentPaths.length} times`,\n\t\t\t\treferencedBy: Object.freeze(intentPaths.slice()),\n\t\t\t\tsourceIntent: relationPath,\n\t\t\t});\n\n\t\t\tconst decisionId = generateDecisionId(state, 'cte-extraction');\n\t\t\tstate.decisions.push({\n\t\t\t\tid: decisionId,\n\t\t\t\ttype: 'cte-extraction',\n\t\t\t\tcontext: {\n\t\t\t\t\tsourceTable: table,\n\t\t\t\t\trelation,\n\t\t\t\t},\n\t\t\t\tchoice: cteName,\n\t\t\t\treasoning: `Extracting ${relationPath} to CTE \"${cteName}\" because it is accessed ${intentPaths.length} times (threshold: ${threshold})`,\n\t\t\t\talternatives: ['inline'],\n\t\t\t});\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\nfunction generateDecisionId(state: PlannerState, type: DecisionType): string {\n\tstate.decisionCounters[type]++;\n\tconst counter = state.decisionCounters[type].toString().padStart(3, '0');\n\treturn `${type.replace('-', '')}-${counter}`;\n}\n\nfunction generateFilterReasoning(\n\trelation: RelationIR,\n\tstrategy: 'exists' | 'join',\n\tmode?: 'some' | 'every' | 'none',\n\tisSelfRef?: boolean,\n): string {\n\tconst modeText = mode ? ` (mode: ${mode})` : '';\n\tconst selfRefText = isSelfRef ? ' [self-referential]' : '';\n\n\tif (strategy === 'exists') {\n\t\treturn (\n\t\t\t`Relation ${relation.source}.${relation.name} has cardinality \"${relation.cardinality}\"${modeText}${selfRefText} - ` +\n\t\t\t`using EXISTS to avoid row explosion`\n\t\t);\n\t}\n\n\treturn (\n\t\t`Relation ${relation.source}.${relation.name} has cardinality \"${relation.cardinality}\"${modeText}${selfRefText} - ` +\n\t\t`using JOIN for efficient single-row access`\n\t);\n}\n\nfunction generateIncludeReasoning(\n\trelation: RelationIR,\n\tstrategy: ResolvedIncludeStrategy,\n): string {\n\tconst prefix = `Relation ${relation.source}.${relation.name} (${relation.type}, cardinality: ${relation.cardinality})`;\n\n\tswitch (strategy) {\n\t\tcase 'join':\n\t\t\treturn `${prefix} - using JOIN for efficient single-query fetch`;\n\t\tcase 'subquery':\n\t\t\treturn `${prefix} - using subquery query to avoid row multiplication`;\n\t\tcase 'cte':\n\t\t\treturn `${prefix} - using CTE for recursive/hierarchical traversal`;\n\t\tcase 'lateral':\n\t\t\treturn `${prefix} - using LATERAL JOIN for per-row correlated subquery (LIMIT per parent)`;\n\t\tcase 'json_agg':\n\t\t\treturn `${prefix} - using JSON aggregation to avoid row explosion`;\n\t}\n}\n\nfunction generateJoinReasoning(\n\trelation: RelationIR,\n\tjoinType: 'left' | 'inner',\n\t_hasFilter: boolean,\n): string {\n\tif (joinType === 'inner') {\n\t\tif (relation.optionality === 'required') {\n\t\t\treturn (\n\t\t\t\t`Relation ${relation.source}.${relation.name} is required - ` +\n\t\t\t\t`using INNER JOIN`\n\t\t\t);\n\t\t}\n\t\treturn (\n\t\t\t`Relation ${relation.source}.${relation.name} has filter - ` +\n\t\t\t`using INNER JOIN (filter implies existence)`\n\t\t);\n\t}\n\n\treturn (\n\t\t`Relation ${relation.source}.${relation.name} is optional without filter - ` +\n\t\t`using LEFT JOIN to preserve parent rows without matches`\n\t);\n}\n","/**\n * Adapter interface for database adapters.\n *\n * Type definitions live in @dbsp/types. This module re-exports them\n * and provides runtime functions and error classes.\n *\n * @module adapter\n */\n\n// Re-export all adapter types from @dbsp/types for backward compatibility\nexport type {\n\tAdapter,\n\tAdapterCapabilities,\n\tAdapterLogger,\n\tAdapterStreamOptions,\n\tAliasIncludedColumnsMode,\n\tAlterColumnOptions,\n\tBaseAdapter,\n\tCompiledQuery,\n\tCompileOnlyAdapter,\n\tCompileOptions,\n\tCompileResultWithIncludes,\n\tCompilingAdapter,\n\tCreateIndexOptions,\n\tDbCasing,\n\tDDLGeneratingAdapter,\n\tDropIndexOptions,\n\tDump,\n\tDumpMeta,\n\tExecutingAdapter,\n\tIndexColumnDef,\n\tIndexInfo,\n\tIndexMethod,\n\tIntrospectingAdapter,\n\tIntrospectionOptions,\n\tIntrospectionResult,\n\tRawSqlAdapter,\n\tStreamingAdapter,\n\tSubqueryIncludeInfo,\n\tTableDDLGeneratorAdapter,\n\tTransactionalAdapter,\n\tTruncateOptions,\n\tVacuumOptions,\n} from '@dbsp/types';\n\nimport type {\n\tAdapter,\n\tAdapterCapabilities,\n\tBaseAdapter,\n\tDDLGeneratingAdapter,\n\tExecutingAdapter,\n\tIntrospectingAdapter,\n\tRawSqlAdapter,\n\tStreamingAdapter,\n\tTransactionalAdapter,\n} from '@dbsp/types';\n\n// ============================================================================\n// Feature Detection Helpers (DX-104)\n// ============================================================================\n\n/**\n * Check if adapter supports execution.\n */\nexport function supportsExecution(\n\tadapter: BaseAdapter,\n): adapter is ExecutingAdapter {\n\treturn (\n\t\t'execute' in adapter &&\n\t\t'executeOne' in adapter &&\n\t\ttypeof (adapter as ExecutingAdapter).execute === 'function'\n\t);\n}\n\n/**\n * Check if adapter supports streaming.\n */\nexport function supportsStreaming(\n\tadapter: BaseAdapter,\n): adapter is StreamingAdapter {\n\treturn (\n\t\t'stream' in adapter &&\n\t\ttypeof (adapter as StreamingAdapter).stream === 'function'\n\t);\n}\n\n/**\n * Check if adapter supports introspection.\n */\nexport function supportsIntrospection(\n\tadapter: BaseAdapter,\n): adapter is IntrospectingAdapter {\n\treturn (\n\t\t'introspect' in adapter &&\n\t\ttypeof (adapter as IntrospectingAdapter).introspect === 'function'\n\t);\n}\n\n/**\n * Check if adapter supports transactions.\n */\nexport function supportsTransactions<DB>(\n\tadapter: BaseAdapter,\n): adapter is TransactionalAdapter<DB> {\n\treturn (\n\t\t'transaction' in adapter &&\n\t\t'withSchema' in adapter &&\n\t\ttypeof (adapter as TransactionalAdapter<DB>).transaction === 'function'\n\t);\n}\n\n/**\n * Check if adapter supports raw SQL execution.\n */\nexport function supportsRawSql(adapter: BaseAdapter): adapter is RawSqlAdapter {\n\treturn (\n\t\t'executeRaw' in adapter &&\n\t\ttypeof (adapter as RawSqlAdapter).executeRaw === 'function'\n\t);\n}\n\n/**\n * Check if adapter supports DDL generation.\n */\nexport function supportsDDLGeneration(\n\tadapter: BaseAdapter,\n): adapter is DDLGeneratingAdapter {\n\treturn (\n\t\t'generateDDL' in adapter &&\n\t\ttypeof (adapter as DDLGeneratingAdapter).generateDDL === 'function'\n\t);\n}\n\n// ============================================================================\n// Errors\n// ============================================================================\n\n/**\n * Error thrown when an operation requires an adapter but none was provided.\n */\nexport class AdapterRequiredError extends Error {\n\tconstructor(operation: string) {\n\t\tsuper(\n\t\t\t`Operation '${operation}' requires an adapter. ` +\n\t\t\t\t'Pass an adapter when creating the ORM: createOrm({ model, adapter })',\n\t\t);\n\t\tthis.name = 'AdapterRequiredError';\n\t}\n}\n\n/**\n * Error thrown when an operation requires a capability the adapter doesn't support.\n */\nexport class UnsupportedCapabilityError extends Error {\n\tconstructor(operation: string, capability: keyof AdapterCapabilities) {\n\t\tsuper(\n\t\t\t`Operation '${operation}' requires capability '${capability}' ` +\n\t\t\t\t'which is not supported by the current adapter.',\n\t\t);\n\t\tthis.name = 'UnsupportedCapabilityError';\n\t}\n}\n\n/**\n * Assert that an adapter supports a required capability.\n */\nexport function assertCapability(\n\tadapter: Adapter,\n\tcapability: keyof AdapterCapabilities,\n\toperation: string,\n): void {\n\tif (!adapter.capabilities[capability]) {\n\t\tthrow new UnsupportedCapabilityError(operation, capability);\n\t}\n}\n","/**\n * BatchValuesRef — a virtual batch data source backed by unnest($1::type[], ...).\n *\n * Created via `orm.batchValues(data, columns, types, opts?)`.\n * Used as a source in `.from()` or `.join()` to operate on a set of\n * parameter-bound arrays without a real table.\n *\n * @example Batch UPDATE\n * ```typescript\n * const batch = orm.batchValues(\n * [ids, calleeIds],\n * ['id', 'callee_id'],\n * ['integer', 'integer'],\n * );\n * await orm.modify(calls)\n * .join(batch, { on: eq('calls.id', ref('batch.id')) })\n * .set({ callee_id: ref('batch.callee_id') })\n * .execute();\n * ```\n *\n * @example Batch lookup with ordinality\n * ```typescript\n * const requested = orm.batchValues(\n * [paths, names],\n * ['path', 'name'],\n * ['text', 'text'],\n * { ordinality: true },\n * );\n * await orm.from(requested)\n * .join('files', { on: eq('files.path', ref('requested.path')) })\n * .orderBy('requested.ord')\n * .all();\n * ```\n */\nexport type BatchValuesOptions = {\n\t/** Add WITH ORDINALITY -- appends an 'ord' column with row numbers */\n\treadonly ordinality?: boolean;\n\t/** Alias for the unnest source in SQL (default: 'batch') */\n\treadonly alias?: string;\n};\n\n/**\n * A virtual batch data source backed by `unnest($1::type[], $2::type[], ...)`.\n *\n * Not a QueryBuilder -- it is a lightweight descriptor passed to `.from()` or\n * `.join()`. The adapter compiles it to a RangeFunction AST node.\n */\nexport type BatchValuesRef = {\n\treadonly __kind: 'batchValues';\n\t/** Column-major data arrays: one array per column */\n\treadonly data: readonly unknown[][];\n\t/** Column names for the unnest alias clause */\n\treadonly columns: readonly string[];\n\t/** PostgreSQL type names for CAST ($1::type[]) -- e.g. 'integer', 'text' */\n\treadonly types: readonly string[];\n\t/** SQL alias used to reference this source (default: 'batch') */\n\treadonly alias: string;\n\t/** When true, WITH ORDINALITY is emitted -- adds an 'ord' column */\n\treadonly ordinality: boolean;\n};\n\n/**\n * Type guard for BatchValuesRef.\n */\nexport function isBatchValuesRef(value: unknown): value is BatchValuesRef {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'__kind' in value &&\n\t\t(value as BatchValuesRef).__kind === 'batchValues'\n\t);\n}\n\n/**\n * Factory function -- create a BatchValuesRef descriptor.\n *\n * @param data Column-major arrays: `[idsArray, namesArray, ...]`\n * @param columns Column names: `['id', 'name', ...]`\n * @param types PG type names: `['integer', 'text', ...]`\n * @param opts Optional: alias and ordinality flag\n */\nexport function batchValues(\n\tdata: readonly unknown[][],\n\tcolumns: readonly string[],\n\ttypes: readonly string[],\n\topts?: BatchValuesOptions,\n): BatchValuesRef {\n\tif (data.length !== columns.length || data.length !== types.length) {\n\t\tthrow new Error(\n\t\t\t'batchValues: data, columns, and types must have the same length ' +\n\t\t\t\t`(got ${data.length}, ${columns.length}, ${types.length})`,\n\t\t);\n\t}\n\tif (columns.length === 0) {\n\t\tthrow new Error('batchValues: at least one column is required');\n\t}\n\t// Security: validate type names to prevent SQL injection via CAST($N AS type[]).\n\t// Only allow identifier characters: letters, digits, underscore.\n\tconst invalidType = types.find((t) => !/^[a-zA-Z0-9_]+$/.test(t));\n\tif (invalidType !== undefined) {\n\t\tthrow new Error(\n\t\t\t`batchValues: invalid type name '${invalidType}'. ` +\n\t\t\t\t'Type names must contain only letters, digits, and underscores.',\n\t\t);\n\t}\n\treturn {\n\t\t__kind: 'batchValues',\n\t\tdata,\n\t\tcolumns,\n\t\ttypes,\n\t\talias: opts?.alias ?? 'batch',\n\t\tordinality: opts?.ordinality ?? false,\n\t};\n}\n","/**\n * @module expressions\n * Dialect-agnostic expression primitives for custom operators, functions, and type casts.\n *\n * These primitives allow constructing arbitrary SQL expressions in a safe, parameterized\n * way — without raw SQL concatenation. Designed as the foundation for dialect extensions\n * (e.g., pgvector, ParadeDB) and advanced query needs.\n *\n * @example\n * ```typescript\n * import { op, ref, param, cast, fn, literal } from '@dbsp/core';\n *\n * // pgvector cosine distance: vector <=> $1::vector\n * const dist = op('<=>', ref('embedding'), cast(param([0.1, 0.2, 0.3]), 'vector'));\n *\n * // Use in SELECT with alias\n * orm.select('items').column(dist.as('score'))\n *\n * // Use in WHERE\n * orm.select('items').where(dist.gte(0.5))\n *\n * // Use in ORDER BY\n * orm.select('items').orderBy(dist, 'asc')\n * ```\n */\n\nimport type {\n\tAggOrderByArg,\n\tArrayExpressionIntent,\n\tCastExpressionIntent,\n\tCustomFnExpressionIntent,\n\tCustomOpExpressionIntent,\n\tExpressionIntent,\n\tLiteralExpressionIntent,\n\tNamedArgExpressionIntent,\n\tParamExpressionIntent,\n\tRefExpressionIntent,\n\tStarExpressionIntent,\n\tUnaryExpressionIntent,\n\tWhereExpressionIntent,\n\tWhereIntent,\n} from '../intent-ast.js';\nimport type { ExpressionSpec } from './types.js';\n\n// ============================================================================\n// Validation patterns\n// ============================================================================\n\nconst OPERATOR_PATTERN = /^[a-zA-Z_<>=!@#%^&|~*+\\-/.]+$/;\nconst FUNCTION_NAME_PATTERN =\n\t/^[a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*$/;\nconst TYPE_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_ ]*(\\[\\])?$/;\n\n// ============================================================================\n// ExprInput type\n// ============================================================================\n\n/**\n * Accepted input types for op() and fn() arguments.\n * - `ExpressionRef` → used as-is\n * - `string` → implicitly converted to ref() (column reference)\n * - `number | boolean | readonly unknown[]` → implicitly converted to param() (bound value)\n *\n * Use `ref()` / `param()` explicitly for ambiguous cases (e.g., a string that is a value,\n * not a column name → use `literal()` instead).\n */\n/**\n * Accepted input types for op() and fn() arguments.\n * - `ExpressionRef` → used as-is\n * - `string` → implicitly converted to ref() (column reference)\n * - `number | boolean | readonly unknown[]` → implicitly converted to param() (bound value)\n * - `AggOrderByArg` → ORDER BY entry inside an aggregate (fn() only)\n *\n * Use `ref()` / `param()` explicitly for ambiguous cases (e.g., a string that is a value,\n * not a column name → use `literal()` instead).\n */\nexport type ExprInput =\n\t| ExpressionRef\n\t| ExpressionSpec\n\t| AggOrderByArg\n\t| string\n\t| number\n\t| boolean\n\t| readonly unknown[];\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\nfunction toExpressionIntent(input: ExprInput): ExpressionIntent {\n\t// ExpressionRef check first — fastest path for the common case.\n\tif (input instanceof ExpressionRef) return input.intent;\n\t// Duck-type check AFTER instanceof: SubqueryExpression.asExpr() returns a plain\n\t// { __expr: true, intent } object (not an ExpressionRef instance), so instanceof\n\t// would miss it. Order matters: instanceof must come first.\n\tif (\n\t\ttypeof input === 'object' &&\n\t\tinput !== null &&\n\t\t'__expr' in input &&\n\t\t(input as { __expr: unknown }).__expr === true &&\n\t\t'intent' in input\n\t) {\n\t\treturn (input as { intent: ExpressionIntent }).intent;\n\t}\n\tif (typeof input === 'string') {\n\t\treturn { kind: 'ref', column: input } satisfies RefExpressionIntent;\n\t}\n\treturn { kind: 'param', value: input } satisfies ParamExpressionIntent;\n}\n\n// ============================================================================\n// ExpressionRef — chainable wrapper around ExpressionIntent\n// ============================================================================\n\n/**\n * A chainable wrapper around an ExpressionIntent.\n *\n * Created by factory functions (`op`, `fn`, `ref`, `param`, `cast`, `literal`, `unary`).\n * Can be used in:\n * - `.column(expr.as('alias'))` — SELECT with alias\n * - `.where(expr.gte(0.5))` — WHERE with comparison\n * - `.orderBy(expr, 'asc')` — ORDER BY expression\n *\n * Implements the `ExpressionSpec` duck-type interface (`__expr: true`, `intent`).\n */\nexport class ExpressionRef {\n\treadonly __expr: true = true;\n\treadonly intent: ExpressionIntent;\n\n\tconstructor(intent: ExpressionIntent) {\n\t\tthis.intent = intent;\n\t}\n\n\t/**\n\t * Set an alias for this expression in SELECT.\n\t * Returns a new ExpressionRef — does not mutate.\n\t */\n\tas(alias: string): ExpressionRef {\n\t\treturn new ExpressionRef({\n\t\t\t...this.intent,\n\t\t\tas: alias,\n\t\t} as ExpressionIntent);\n\t}\n\n\t/** WHERE: expr = value */\n\teq(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'eq', value };\n\t}\n\n\t/** WHERE: expr != value */\n\tneq(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'neq', value };\n\t}\n\n\t/** WHERE: expr > value */\n\tgt(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'gt', value };\n\t}\n\n\t/** WHERE: expr >= value */\n\tgte(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'gte', value };\n\t}\n\n\t/** WHERE: expr < value */\n\tlt(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'lt', value };\n\t}\n\n\t/** WHERE: expr <= value */\n\tlte(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'lte', value };\n\t}\n\n\t/**\n\t * Add a FILTER (WHERE ...) clause to this function expression.\n\t * Only valid on `fn()` expressions (customFn kind).\n\t * Returns a new ExpressionRef — does not mutate.\n\t *\n\t * @example fn('array_agg', ref('name')).filter(eq('active', true))\n\t * → array_agg(\"name\") FILTER (WHERE \"active\" = $1)\n\t * @throws Error if called on non-customFn expressions\n\t */\n\tfilter(condition: WhereIntent): ExpressionRef {\n\t\tif (this.intent.kind !== 'customFn') {\n\t\t\tthrow new Error(\n\t\t\t\t`filter() can only be used on function expressions created with fn(). Got kind: '${this.intent.kind}'`,\n\t\t\t);\n\t\t}\n\t\treturn new ExpressionRef({\n\t\t\t...this.intent,\n\t\t\tfilter: condition,\n\t\t} as CustomFnExpressionIntent);\n\t}\n}\n\n// ============================================================================\n// Factory functions\n// ============================================================================\n\n/**\n * Column reference — refers to a named column (or table.column).\n *\n * @example ref('embedding') → \"embedding\"\n * @example ref('t.score') → \"t\".\"score\"\n */\nexport function ref(column: string): ExpressionRef {\n\treturn new ExpressionRef({\n\t\tkind: 'ref',\n\t\tcolumn,\n\t} satisfies RefExpressionIntent);\n}\n\n/**\n * Parameterized value — automatically bound as $N.\n * Use for user-supplied values, vectors, dynamic data.\n *\n * @example param([0.1, 0.2]) → $1 (with value bound to $1)\n */\nexport function param(value: unknown): ExpressionRef {\n\treturn new ExpressionRef({\n\t\tkind: 'param',\n\t\tvalue,\n\t} satisfies ParamExpressionIntent);\n}\n\n/**\n * Type cast — compiles to expr::typeName or CAST(expr AS typeName).\n *\n * @example cast(param([0.1, 0.2]), 'vector') → $1::vector\n * @throws Error if typeName fails validation (injection guard)\n */\nexport function cast(expr: ExpressionRef, typeName: string): ExpressionRef {\n\tif (!TYPE_NAME_PATTERN.test(typeName)) {\n\t\tthrow new Error(`Invalid type name: ${typeName}`);\n\t}\n\treturn new ExpressionRef({\n\t\tkind: 'cast',\n\t\texpr: expr.intent,\n\t\ttypeName,\n\t} satisfies CastExpressionIntent);\n}\n\n/**\n * Custom binary operator — left OP right.\n * Implicit conversions: string → ref(), number/boolean/array → param().\n *\n * @example op('<=>', ref('embedding'), cast(param([0.1]), 'vector'))\n * @example op('<=>', 'embedding', [0.1, 0.2]) // implicit conversions\n * @throws Error if operator fails validation (injection guard)\n */\nexport function op(\n\toperator: string,\n\tleft: ExprInput,\n\tright: ExprInput,\n): ExpressionRef {\n\tif (!operator || !OPERATOR_PATTERN.test(operator)) {\n\t\tthrow new Error(`Invalid operator: ${operator}`);\n\t}\n\treturn new ExpressionRef({\n\t\tkind: 'customOp',\n\t\toperator,\n\t\tleft: toExpressionIntent(left),\n\t\tright: toExpressionIntent(right),\n\t} satisfies CustomOpExpressionIntent);\n}\n\n/**\n * Custom function call — name(args...).\n * Supports schema-qualified names (e.g., 'paradedb.score', 'ST_Distance').\n * Implicit conversions: string → ref(), number/boolean/array → param().\n *\n * @example fn('now') → now()\n * @example fn('paradedb.score', ref('id')) → paradedb.score(\"id\")\n * @throws Error if name fails validation (injection guard)\n */\n/**\n * Custom function call — name(args...).\n * Supports schema-qualified names (e.g., 'paradedb.score', 'ST_Distance').\n * Implicit conversions: string → ref(), number/boolean/array → param().\n *\n * Pass `aggOrderBy('col', 'asc')` args to add ORDER BY inside aggregates:\n * `fn('array_agg', ref('name'), aggOrderBy('path'))` → array_agg(\"name\" ORDER BY \"path\" ASC)\n *\n * @example fn('now') → now()\n * @example fn('paradedb.score', ref('id')) → paradedb.score(\"id\")\n * @example fn('array_agg', ref('name'), aggOrderBy('path')) → array_agg(\"name\" ORDER BY \"path\" ASC)\n * @throws Error if name fails validation (injection guard)\n */\nexport function fn(name: string, ...args: ExprInput[]): ExpressionRef {\n\tif (!name || !FUNCTION_NAME_PATTERN.test(name)) {\n\t\tthrow new Error(`Invalid function name: ${name}`);\n\t}\n\tconst regularArgs: ExpressionIntent[] = [];\n\tconst orderByArgs: AggOrderByArg[] = [];\n\tfor (const arg of args) {\n\t\tif (isAggOrderByArg(arg)) {\n\t\t\torderByArgs.push(arg);\n\t\t} else {\n\t\t\tregularArgs.push(toExpressionIntent(arg));\n\t\t}\n\t}\n\tconst intent: CustomFnExpressionIntent = {\n\t\tkind: 'customFn',\n\t\tname,\n\t\targs: regularArgs,\n\t\t...(orderByArgs.length > 0 ? { aggOrderBy: orderByArgs } : {}),\n\t};\n\treturn new ExpressionRef(intent);\n}\n\n/**\n * Literal value — inlined directly in SQL (not bound as parameter).\n * Use to distinguish SQL string literals from column references.\n *\n * | Call | SQL |\n * |------|-----|\n * | `literal(42)` | `42` (inline integer) |\n * | `literal('text')` | `'text'` (SQL string literal) |\n * | `literal(null)` | `NULL` |\n *\n * @example literal(1) → 1 (for: 1 - (col <=> vec))\n */\nexport function literal(\n\tvalue: string | number | boolean | null,\n): ExpressionRef {\n\treturn new ExpressionRef({\n\t\tkind: 'literal',\n\t\tvalue,\n\t} satisfies LiteralExpressionIntent);\n}\n\n/**\n * Unary operator — OP expr (prefix form).\n *\n * @example unary('NOT', ref('active')) → NOT \"active\"\n * @example unary('-', ref('score')) → -\"score\"\n * @throws Error if operator fails validation (injection guard)\n */\nexport function unary(operator: string, expr: ExprInput): ExpressionRef {\n\tif (!operator || !OPERATOR_PATTERN.test(operator)) {\n\t\tthrow new Error(`Invalid operator: ${operator}`);\n\t}\n\treturn new ExpressionRef({\n\t\tkind: 'unary',\n\t\toperator,\n\t\toperand: toExpressionIntent(expr),\n\t} satisfies UnaryExpressionIntent);\n}\n\n/**\n * Named argument for function calls: name => value.\n * Use inside fn() args to produce PostgreSQL named-argument syntax.\n *\n * @example namedArg('field', literal('name_searchable'))\n * → field => 'name_searchable'\n * @example namedArg('query_string', param('hello'))\n * → query_string => $1\n */\nexport function namedArg(name: string, value: ExprInput): ExpressionRef {\n\tif (!name || !FUNCTION_NAME_PATTERN.test(name)) {\n\t\tthrow new Error(`namedArg: invalid argument name: ${name}`);\n\t}\n\treturn new ExpressionRef({\n\t\tkind: 'namedArg',\n\t\tname,\n\t\tvalue: toExpressionIntent(value),\n\t} satisfies NamedArgExpressionIntent);\n}\n\n/** SQL wildcard (*) — use in fn('count', star()) for COUNT(*) */\nexport function star(): ExpressionRef {\n\treturn new ExpressionRef({ kind: 'star' } satisfies StarExpressionIntent);\n}\n\n/**\n * PostgreSQL ARRAY constructor: ARRAY[item1, item2, ...]\n *\n * @example array(literal(1), literal(2), literal(3)) → ARRAY[1, 2, 3]\n * @example array(ref('name'), ref('kind')) → ARRAY[\"name\", \"kind\"]\n */\nexport function array(...items: ExprInput[]): ExpressionRef {\n\treturn new ExpressionRef({\n\t\tkind: 'array',\n\t\telements: items.map(toExpressionIntent),\n\t} satisfies ArrayExpressionIntent);\n}\n\n// ============================================================================\n// Aggregate ORDER BY helpers (FR-9)\n// ============================================================================\n\n/**\n * Type guard for AggOrderByArg — distinguishes aggregate ORDER BY markers\n * from regular ExprInput values inside fn() argument lists.\n */\nfunction isAggOrderByArg(input: ExprInput): input is AggOrderByArg {\n\treturn (\n\t\ttypeof input === 'object' &&\n\t\tinput !== null &&\n\t\t!Array.isArray(input) &&\n\t\t!(input instanceof ExpressionRef) &&\n\t\t'__aggOrderBy' in input &&\n\t\t(input as AggOrderByArg).__aggOrderBy === true\n\t);\n}\n\n/**\n * Creates an ORDER BY marker for use as an argument to `fn()`.\n * When passed to `fn()`, the compiler places it in the aggregate's\n * ORDER BY clause instead of in the regular argument list.\n *\n * @example fn('array_agg', ref('name'), aggOrderBy('path')) → array_agg(\"name\" ORDER BY \"path\" ASC)\n * @example fn('array_agg', ref('name'), aggOrderBy('path', 'desc')) → array_agg(\"name\" ORDER BY \"path\" DESC)\n */\nexport function aggOrderBy(\n\tfield: string,\n\tdirection: 'asc' | 'desc' = 'asc',\n): AggOrderByArg {\n\treturn { __aggOrderBy: true, field, direction };\n}\n\n/**\n * Shorthand for `fn('array_agg', col, ...orderByArgs)`.\n *\n * @example arrayAgg(ref('name')) → array_agg(\"name\")\n * @example arrayAgg(ref('name'), aggOrderBy('path')) → array_agg(\"name\" ORDER BY \"path\" ASC)\n * @example arrayAgg('name', aggOrderBy('path', 'desc')) → array_agg(\"name\" ORDER BY \"path\" DESC)\n */\nexport function arrayAgg(\n\tcol: ExpressionRef | string,\n\t...rest: AggOrderByArg[]\n): ExpressionRef {\n\tconst colExpr = typeof col === 'string' ? ref(col) : col;\n\treturn fn('array_agg', colExpr, ...rest);\n}\n\n/**\n * Shorthand for `fn('string_agg', col, separator, ...orderByArgs)`.\n *\n * @example stringAgg(ref('name'), literal(',')) → string_agg(\"name\", ',')\n * @example stringAgg(ref('name'), literal(','), aggOrderBy('name')) → string_agg(\"name\", ',' ORDER BY \"name\" ASC)\n */\nexport function stringAgg(\n\tcol: ExpressionRef | string,\n\tseparator: ExpressionRef,\n\t...rest: AggOrderByArg[]\n): ExpressionRef {\n\tconst colExpr = typeof col === 'string' ? ref(col) : col;\n\treturn fn('string_agg', colExpr, separator, ...rest);\n}\n","import type {\n\tCaseExpressionIntent,\n\tExpressionIntent,\n\tWhereIntent,\n} from '@dbsp/types';\nimport { ExpressionRef } from './expressions.js';\n\nfunction toResultIntent(\n\tvalue: ExpressionRef | string | number | boolean | null | undefined,\n): ExpressionIntent {\n\tif (value instanceof ExpressionRef) {\n\t\treturn value.intent;\n\t}\n\tif (value === null || value === undefined) {\n\t\treturn { kind: 'literal', value: null } satisfies ExpressionIntent;\n\t}\n\tif (typeof value === 'string') {\n\t\treturn { kind: 'ref', column: value } satisfies ExpressionIntent;\n\t}\n\treturn { kind: 'literal', value } satisfies ExpressionIntent;\n}\n\nexport type CaseValue = ExpressionRef | string | number | boolean | null;\n\nexport class CaseBuilder {\n\tprivate readonly branches: ReadonlyArray<{\n\t\treadonly condition: WhereIntent;\n\t\treadonly result: ExpressionIntent;\n\t}>;\n\n\tconstructor(\n\t\tbranches: ReadonlyArray<{\n\t\t\treadonly condition: WhereIntent;\n\t\t\treadonly result: ExpressionIntent;\n\t\t}>,\n\t) {\n\t\tthis.branches = branches;\n\t}\n\n\twhen(condition: WhereIntent, thenValue: CaseValue): CaseBuilder {\n\t\treturn new CaseBuilder([\n\t\t\t...this.branches,\n\t\t\t{ condition, result: toResultIntent(thenValue) },\n\t\t]);\n\t}\n\n\telse(elseValue: CaseValue): ExpressionRef {\n\t\tconst intent: CaseExpressionIntent = {\n\t\t\tkind: 'case',\n\t\t\twhen: this.branches,\n\t\t\telse: toResultIntent(elseValue),\n\t\t};\n\t\treturn new ExpressionRef(intent as ExpressionIntent);\n\t}\n\n\tas(alias: string): ExpressionRef {\n\t\treturn this.toExpr().as(alias);\n\t}\n\n\ttoExpr(): ExpressionRef {\n\t\tconst intent: CaseExpressionIntent = {\n\t\t\tkind: 'case',\n\t\t\twhen: this.branches,\n\t\t};\n\t\treturn new ExpressionRef(intent as ExpressionIntent);\n\t}\n}\n\nexport function caseWhen(\n\tcondition: WhereIntent,\n\tthenValue: CaseValue,\n): CaseBuilder {\n\treturn new CaseBuilder([{ condition, result: toResultIntent(thenValue) }]);\n}\n","/**\n * Shared builder utilities for CTE and recursive query builders.\n */\n\nimport type { Adapter } from '@dbsp/types';\nimport { InvalidOperationError } from './errors.js';\n\n/**\n * Asserts that an adapter is present, throwing a descriptive error if not.\n *\n * @param adapter - The adapter instance (may be undefined)\n * @param operationName - The public API operation name, used in the error message\n * @returns The validated adapter\n */\nexport function requireAdapter(\n\tadapter: Adapter | undefined,\n\toperationName: string,\n): Adapter {\n\tif (!adapter) {\n\t\tthrow new InvalidOperationError(\n\t\t\toperationName,\n\t\t\t'This operation requires an adapter \\u2014 pass an adapter when creating the ORM',\n\t\t);\n\t}\n\treturn adapter;\n}\n","/**\n * CTE builder with unnest() support (BATCH-001 Block 5).\n *\n * Provides a fluent API for building CTE queries backed by unnest() arrays,\n * optionally with WITH ORDINALITY for 0-based indexing.\n *\n * @example\n * ```typescript\n * const result = orm.withCte('lookups')\n * .fromUnnest({ parent_file_id: [1, 2, 3], parent_name: ['Foo', 'Bar', 'Baz'] })\n * .withIndex('idx')\n * .query(orm.select('symbols'))\n * .dump();\n * ```\n */\n\nimport type {\n\tAdapter,\n\tCompiledQuery,\n\tCteQueryIntent,\n\tUnnestCteIntent,\n} from '@dbsp/types';\nimport { requireAdapter as requireAdapterUtil } from './builder-utils.js';\nimport { InvalidOperationError } from './errors.js';\nimport type { QueryBuilderImpl } from './query-builder.js';\nimport type { QueryBuilder } from './query-builder-types.js';\n\n// ============================================================================\n// CteBuilder\n// ============================================================================\n\n/**\n * Fluent builder for constructing a CTE definition backed by unnest() arrays.\n *\n * Obtain via `orm.withCte(name)`.\n */\nexport class CteBuilder {\n\tprivate readonly cteName: string;\n\tprivate readonly adapter: Adapter | undefined;\n\tprivate readonly schemaName: string | undefined;\n\tprivate unnestColumns: Record<string, readonly unknown[]> | undefined;\n\tprivate indexColumnName: string | undefined;\n\n\tconstructor(name: string, adapter?: Adapter, schemaName?: string) {\n\t\tthis.cteName = name;\n\t\tthis.adapter = adapter;\n\t\tthis.schemaName = schemaName;\n\t}\n\n\t/**\n\t * Provide the column arrays for the unnest() CTE.\n\t * All arrays must have the same length.\n\t *\n\t * @param columns - A record of column name → array of values.\n\t */\n\tfromUnnest(columns: Record<string, readonly unknown[]>): this {\n\t\tconst lengths = Object.values(columns).map((arr) => arr.length);\n\t\tif (lengths.length > 1 && !lengths.every((l) => l === lengths[0])) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'withCte',\n\t\t\t\t`Array length mismatch in CTE unnest columns: lengths are [${lengths.join(', ')}]`,\n\t\t\t);\n\t\t}\n\t\tthis.unnestColumns = columns;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a 0-based ordinality index column (uses WITH ORDINALITY).\n\t *\n\t * @param columnName - The name of the index column in the CTE.\n\t */\n\twithIndex(columnName: string): this {\n\t\tthis.indexColumnName = columnName;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Attach an outer query and produce a CteQueryBuilder for execution.\n\t *\n\t * @param selectBuilder - A QueryBuilder (from orm.select(...))\n\t */\n\tquery<TResult = unknown>(\n\t\tselectBuilder: QueryBuilder<TResult>,\n\t): CteQueryBuilder<TResult> {\n\t\tif (!this.unnestColumns) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'withCte',\n\t\t\t\t'CTE requires a data source — call .fromUnnest() first',\n\t\t\t);\n\t\t}\n\n\t\tconst cteIntent: UnnestCteIntent = {\n\t\t\tkind: 'unnestCte',\n\t\t\tname: this.cteName,\n\t\t\tcolumns: this.unnestColumns,\n\t\t\t...(this.indexColumnName !== undefined && {\n\t\t\t\tindexColumn: this.indexColumnName,\n\t\t\t}),\n\t\t};\n\n\t\treturn new CteQueryBuilder<TResult>(\n\t\t\tcteIntent,\n\t\t\tselectBuilder as QueryBuilderImpl<TResult>,\n\t\t\tthis.adapter,\n\t\t\tthis.schemaName,\n\t\t);\n\t}\n}\n\n// ============================================================================\n// CteQueryBuilder\n// ============================================================================\n\n/**\n * Result of compiling a CTE query.\n */\nexport interface CteDump {\n\treadonly sql: string;\n\treadonly params: readonly unknown[];\n\treadonly intent: CteQueryIntent;\n}\n\n/**\n * Fluent builder for executing a WITH ... SELECT query.\n *\n * Produced by `CteBuilder.query()`.\n */\nexport class CteQueryBuilder<TResult = unknown> {\n\tprivate readonly cteIntent: UnnestCteIntent;\n\tprivate readonly outerBuilder: QueryBuilderImpl<TResult>;\n\tprivate readonly adapter: Adapter | undefined;\n\tprivate readonly schemaName: string | undefined;\n\n\tconstructor(\n\t\tcteIntent: UnnestCteIntent,\n\t\touterBuilder: QueryBuilderImpl<TResult>,\n\t\tadapter?: Adapter,\n\t\tschemaName?: string,\n\t) {\n\t\tthis.cteIntent = cteIntent;\n\t\tthis.outerBuilder = outerBuilder;\n\t\tthis.adapter = adapter;\n\t\tthis.schemaName = schemaName;\n\t}\n\n\t/**\n\t * Build the CteQueryIntent AST.\n\t */\n\tbuildIntent(): CteQueryIntent {\n\t\tconst queryIntent = this.outerBuilder.buildIntent();\n\t\treturn {\n\t\t\tkind: 'cteQuery',\n\t\t\tctes: [this.cteIntent],\n\t\t\tquery: queryIntent,\n\t\t};\n\t}\n\n\tprivate requireAdapter(): Adapter {\n\t\treturn requireAdapterUtil(this.adapter, 'withCte');\n\t}\n\n\t/**\n\t * Compile to SQL and return an observability dump.\n\t */\n\tdump(): CteDump {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions = this.schemaName\n\t\t\t? { schemaName: this.schemaName }\n\t\t\t: undefined;\n\n\t\tconst compiled: CompiledQuery = adapter.compileCteQuery(\n\t\t\tintent,\n\t\t\tcompileOptions,\n\t\t);\n\n\t\treturn {\n\t\t\tsql: compiled.sql,\n\t\t\tparams: compiled.parameters,\n\t\t\tintent,\n\t\t};\n\t}\n\n\t/**\n\t * Execute the CTE query and return all results.\n\t */\n\tasync all(): Promise<TResult[]> {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions = this.schemaName\n\t\t\t? { schemaName: this.schemaName }\n\t\t\t: undefined;\n\n\t\tconst compiled = adapter.compileCteQuery(\n\t\t\tintent,\n\t\t\tcompileOptions,\n\t\t) as CompiledQuery<TResult>;\n\n\t\treturn adapter.execute(compiled);\n\t}\n\n\t/**\n\t * Alias for all().\n\t */\n\texecute(): Promise<TResult[]> {\n\t\treturn this.all();\n\t}\n}\n","import type { DDLFeature, DialectCapabilities, ModelIR } from '@dbsp/types';\n\n// ---------------------------------------------------------------------------\n// FeatureChecker interface (OCP-001: Open/Closed for feature negotiation)\n// ---------------------------------------------------------------------------\n\n/**\n * Restricted key type: only keys of DialectCapabilities whose value is boolean\n * (or optional boolean). Prevents custom checkers from targeting non-boolean\n * fields (name, recursivePathStyle, identifierQuote, etc.) where a truthy\n * guard would silently break at runtime.\n */\nexport type DialectCapabilityFlag = Extract<\n\t{\n\t\t[K in keyof DialectCapabilities]: NonNullable<\n\t\t\tDialectCapabilities[K]\n\t\t> extends boolean\n\t\t\t? K\n\t\t\t: never;\n\t}[keyof DialectCapabilities],\n\tstring\n>;\n\n/**\n * A self-contained checker for a single DDL feature.\n * Add a new feature by appending a FeatureChecker to DEFAULT_FEATURE_CHECKERS\n * -- no edits to negotiateFeatures() required.\n *\n * Note: when multiple checkers target the same `capability`, all run in array\n * order and each can emit warnings/errors. Deduplication by capability is the\n * caller's responsibility.\n */\nexport interface FeatureChecker {\n\t/** Capability flag key — restricted to boolean-valued fields of DialectCapabilities. */\n\treadonly capability: DialectCapabilityFlag;\n\t/** DDLFeature name used in warn/error messages and behavior lookup. */\n\treadonly feature: DDLFeature;\n\t/**\n\t * Walk the ModelIR and return locations where this feature is used.\n\t * Return empty array if the feature is not used anywhere.\n\t */\n\tdetectUsage(model: ModelIR): readonly FeatureUsage[];\n}\n\n/** Location descriptor returned by FeatureChecker.detectUsage(). */\nexport interface FeatureUsage {\n\treadonly table?: string;\n\treadonly column?: string;\n\t/** Human-readable element label used in warn/error messages. */\n\treadonly detail: string;\n}\n\n// ---------------------------------------------------------------------------\n// Default registry -- one entry per supportsDDL* capability flag\n// ---------------------------------------------------------------------------\n\n/**\n * Default feature checkers -- mirrors the 15 supportsDDL* flags that\n * negotiateFeatures() previously checked inline.\n *\n * Each checker preserves exactly the same detection logic (same guards,\n * same element label format) that was previously inlined in negotiateFeatures().\n */\nexport const DEFAULT_FEATURE_CHECKERS: readonly FeatureChecker[] =\n\tObject.freeze<readonly FeatureChecker[]>([\n\t\t// -----------------------------------------------------------------------\n\t\t// Schema-level features\n\t\t// -----------------------------------------------------------------------\n\t\t{\n\t\t\tcapability: 'supportsDDLEnumTypes',\n\t\t\tfeature: 'enum',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.enums?.size) return [];\n\t\t\t\treturn [...model.enums.keys()].map((name) => ({ detail: name }));\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLSequences',\n\t\t\tfeature: 'sequence',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.sequences?.size) return [];\n\t\t\t\treturn [...model.sequences.keys()].map((name) => ({ detail: name }));\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLExtensions',\n\t\t\tfeature: 'extension',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.extensions?.length) return [];\n\t\t\t\treturn model.extensions.map((ext) => ({ detail: ext }));\n\t\t\t},\n\t\t},\n\n\t\t// -----------------------------------------------------------------------\n\t\t// Table-level features\n\t\t// -----------------------------------------------------------------------\n\t\t{\n\t\t\tcapability: 'supportsDDLPartitioning',\n\t\t\tfeature: 'partition',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tif (table.partition) {\n\t\t\t\t\t\tusages.push({ table: tableName, detail: tableName });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLComments',\n\t\t\tfeature: 'comment',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tif (table.comment) {\n\t\t\t\t\t\tusages.push({ table: tableName, detail: `${tableName} (table)` });\n\t\t\t\t\t}\n\t\t\t\t\tfor (const col of table.columns) {\n\t\t\t\t\t\tif (col.comment) {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tcolumn: col.name,\n\t\t\t\t\t\t\t\tdetail: `${tableName}.${col.name} (column)`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLCheckConstraints',\n\t\t\tfeature: 'checkConstraint',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tif (table.checkConstraints?.length) {\n\t\t\t\t\t\tfor (const chk of table.checkConstraints) {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tdetail: `${tableName}.${chk.name}`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLOnUpdateFK',\n\t\t\tfeature: 'onUpdateFK',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const fk of table.foreignKeys) {\n\t\t\t\t\t\tif (fk.onUpdate && fk.onUpdate !== 'NO ACTION') {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tdetail: `${tableName} FK → ${fk.references.table}`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLDeferredFK',\n\t\t\tfeature: 'deferredFK',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const fk of table.foreignKeys) {\n\t\t\t\t\t\tif (fk.deferred) {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tdetail: `${tableName} FK → ${fk.references.table}`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\n\t\t// -----------------------------------------------------------------------\n\t\t// Column-level features\n\t\t// -----------------------------------------------------------------------\n\t\t{\n\t\t\tcapability: 'supportsDDLIdentityColumns',\n\t\t\tfeature: 'identity',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const col of table.columns) {\n\t\t\t\t\t\tif (col.identity) {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tcolumn: col.name,\n\t\t\t\t\t\t\t\tdetail: `${tableName}.${col.name}`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLCollation',\n\t\t\tfeature: 'collation',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const col of table.columns) {\n\t\t\t\t\t\tif (col.collation) {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tcolumn: col.name,\n\t\t\t\t\t\t\t\tdetail: `${tableName}.${col.name}`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\n\t\t// -----------------------------------------------------------------------\n\t\t// Index-level features\n\t\t// -----------------------------------------------------------------------\n\t\t{\n\t\t\tcapability: 'supportsDDLIndexMethods',\n\t\t\tfeature: 'indexMethod',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const idx of table.indexes) {\n\t\t\t\t\t\tif (idx.method && idx.method !== 'btree') {\n\t\t\t\t\t\t\tconst idxName = idx.name ?? `idx on ${tableName}`;\n\t\t\t\t\t\t\tusages.push({ table: tableName, detail: idxName });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLIndexOpclass',\n\t\t\tfeature: 'indexOpclass',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const idx of table.indexes) {\n\t\t\t\t\t\tif (idx.opclass && Object.keys(idx.opclass).length > 0) {\n\t\t\t\t\t\t\tconst idxName = idx.name ?? `idx on ${tableName}`;\n\t\t\t\t\t\t\tusages.push({ table: tableName, detail: idxName });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLIndexInclude',\n\t\t\tfeature: 'indexInclude',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const idx of table.indexes) {\n\t\t\t\t\t\tif (idx.include?.length) {\n\t\t\t\t\t\t\tconst idxName = idx.name ?? `idx on ${tableName}`;\n\t\t\t\t\t\t\tusages.push({ table: tableName, detail: idxName });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLPartialIndexes',\n\t\t\tfeature: 'partialIndex',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const idx of table.indexes) {\n\t\t\t\t\t\tif (idx.where) {\n\t\t\t\t\t\t\tconst idxName = idx.name ?? `idx on ${tableName}`;\n\t\t\t\t\t\t\tusages.push({ table: tableName, detail: idxName });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLExpressionIndexes',\n\t\t\tfeature: 'expressionIndex',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const idx of table.indexes) {\n\t\t\t\t\t\tif (idx.expressions?.length) {\n\t\t\t\t\t\t\tconst idxName = idx.name ?? `idx on ${tableName}`;\n\t\t\t\t\t\t\tusages.push({ table: tableName, detail: idxName });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t]);\n","import { COLUMN_META } from './symbols.js';\nimport type { ColumnRef } from './table-ref.js';\n\n/**\n * Extract the column name from a ColumnRef or string.\n * @internal Shared helper — used by filters, functions, window-functions, typed-query-builder.\n */\nexport function getColumnName(\n\tfield: ColumnRef<string, string, unknown> | string,\n): string {\n\tif (typeof field === 'string') {\n\t\treturn field;\n\t}\n\tconst colName = field[COLUMN_META];\n\tif (colName === undefined) {\n\t\tthrow new Error('Invalid ColumnRef: missing COLUMN_META');\n\t}\n\treturn colName;\n}\n","/**\n * @module window-functions\n * Fluent builders for SQL window functions (ROW_NUMBER, RANK, SUM OVER, etc.).\n *\n * Extracted from filters.ts for SRP (Audit #19).\n *\n * @example\n * ```typescript\n * import { rowNumber, wSum, rank } from '@dbsp/core';\n *\n * // Ranking\n * rowNumber().orderBy('created_at', 'desc').as('rn')\n *\n * // Running total with partition\n * wSum('amount').partitionBy('user_id').orderBy('date').as('running_total')\n * ```\n */\n\nimport type { Mutable } from '@dbsp/types/internal';\nimport type { WindowFunction, WindowIntent } from '../intent-ast.js';\nimport { getColumnName } from './column-utils.js';\nimport type { ColumnRef } from './table-ref.js';\nimport type { ExpressionSpec } from './types.js';\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\n// ============================================================================\n// WindowBuilder\n// ============================================================================\n\n/**\n * Internal state for WindowBuilder.\n * Distinguishes between ranking (no field), aggregate (requires field), and offset (requires field).\n */\ntype WindowFunctionKind =\n\t| { type: 'ranking'; fn: 'row_number' | 'rank' | 'dense_rank' }\n\t| {\n\t\t\ttype: 'aggregate';\n\t\t\tfn: 'sum' | 'avg' | 'count' | 'min' | 'max';\n\t\t\tfield?: string;\n\t }\n\t| { type: 'offset'; fn: 'lag' | 'lead'; field: string };\n\n/**\n * Fluent builder for window functions.\n *\n * Create via factory functions: rowNumber(), rank(), sum(field), etc.\n * Chain with .partitionBy(), .orderBy(), then finalize with .as(alias).\n *\n * @example\n * ```typescript\n * // Ranking\n * rowNumber().orderBy('created_at', 'desc').as('rn')\n *\n * // Aggregate with partition\n * sum('amount').partitionBy('user_id').orderBy('date').as('running_total')\n *\n * // Multiple partition/order fields (chaining appends)\n * rank().partitionBy('dept').partitionBy('team').orderBy('salary', 'desc').as('rank')\n * ```\n */\nexport class WindowBuilder {\n\tprivate constructor(\n\t\tprivate readonly fnKind: WindowFunctionKind,\n\t\tprivate readonly partitions: readonly string[] = [],\n\t\tprivate readonly orders: readonly {\n\t\t\tfield: string;\n\t\t\tdirection: 'asc' | 'desc';\n\t\t}[] = [],\n\t) {}\n\n\t/**\n\t * Create a ranking window builder (row_number, rank, dense_rank)\n\t * @internal Use factory functions instead: rowNumber(), rank(), denseRank()\n\t */\n\tstatic ranking(fn: 'row_number' | 'rank' | 'dense_rank'): WindowBuilder {\n\t\treturn new WindowBuilder({ type: 'ranking', fn });\n\t}\n\n\t/**\n\t * Create an aggregate window builder (sum, avg, count, min, max)\n\t * @internal Use factory functions instead: sum(field), avg(field), etc.\n\t */\n\tstatic aggregate(\n\t\tfn: 'sum' | 'avg' | 'count' | 'min' | 'max',\n\t\tfield?: string,\n\t): WindowBuilder {\n\t\treturn new WindowBuilder({\n\t\t\ttype: 'aggregate',\n\t\t\tfn,\n\t\t\t...(field !== undefined ? { field } : {}),\n\t\t});\n\t}\n\n\t/**\n\t * Create an offset window builder (lag, lead)\n\t * @internal Use factory functions instead: lag(field), lead(field)\n\t */\n\tstatic offset(fn: 'lag' | 'lead', field: string): WindowBuilder {\n\t\treturn new WindowBuilder({ type: 'offset', fn, field });\n\t}\n\n\t/**\n\t * Add partition field(s) to the OVER clause.\n\t * Multiple calls APPEND fields (not replace).\n\t * Supports both string field names and ColumnRef (DX-040).\n\t *\n\t * @example\n\t * sum('amount').partitionBy('user_id').partitionBy('category')\n\t * // → PARTITION BY \"user_id\", \"category\"\n\t *\n\t * @example DX-040 with ColumnRef\n\t * rank().partitionBy(users.dept).orderBy(users.salary, 'desc')\n\t */\n\tpartitionBy(\n\t\t...fields: (string | ColumnRef<string, string, unknown>)[]\n\t): WindowBuilder {\n\t\tconst fieldNames = fields.map((f) =>\n\t\t\ttypeof f === 'string' ? f : getColumnName(f),\n\t\t);\n\t\treturn new WindowBuilder(\n\t\t\tthis.fnKind,\n\t\t\t[...this.partitions, ...fieldNames],\n\t\t\tthis.orders,\n\t\t);\n\t}\n\n\t/**\n\t * Add order field to the OVER clause.\n\t * Multiple calls APPEND fields (not replace).\n\t * Supports both string field names and ColumnRef (DX-040).\n\t *\n\t * @param field - Column name or ColumnRef to order by\n\t * @param direction - Sort direction: 'asc' (default) or 'desc'\n\t *\n\t * @example\n\t * rowNumber().orderBy('created_at').orderBy('id', 'desc')\n\t * // → ORDER BY \"created_at\" ASC, \"id\" DESC\n\t *\n\t * @example DX-040 with ColumnRef\n\t * rank().partitionBy(users.dept).orderBy(users.salary, 'desc')\n\t */\n\torderBy(\n\t\tfield: string | ColumnRef<string, string, unknown>,\n\t\tdirection: 'asc' | 'desc' = 'asc',\n\t): WindowBuilder {\n\t\tconst fieldName = typeof field === 'string' ? field : getColumnName(field);\n\t\treturn new WindowBuilder(this.fnKind, this.partitions, [\n\t\t\t...this.orders,\n\t\t\t{ field: fieldName, direction },\n\t\t]);\n\t}\n\n\t/**\n\t * Finalize the window expression with an alias.\n\t * Returns ExpressionSpec for use in columns().\n\t *\n\t * @param alias - Required alias for the result column\n\t *\n\t * @example\n\t * columns(['id', rowNumber().orderBy('date').as('rn')])\n\t */\n\tas(alias: string): ExpressionSpec {\n\t\treturn {\n\t\t\t__expr: true,\n\t\t\tintent: this.toWindowIntent(alias),\n\t\t};\n\t}\n\n\t/**\n\t * Convert builder state to WindowIntent\n\t */\n\tprivate toWindowIntent(alias: string): WindowIntent {\n\t\tconst fn = this.fnKind.fn as WindowFunction;\n\t\tconst field =\n\t\t\tthis.fnKind.type === 'aggregate' || this.fnKind.type === 'offset'\n\t\t\t\t? this.fnKind.field\n\t\t\t\t: undefined;\n\n\t\tconst over: Mutable<WindowIntent['over']> = {};\n\t\tif (this.partitions.length > 0) {\n\t\t\tover.partitionBy = this.partitions;\n\t\t}\n\t\tif (this.orders.length > 0) {\n\t\t\tover.orderBy = this.orders;\n\t\t}\n\n\t\tconst intent: WindowIntent = {\n\t\t\tkind: 'window',\n\t\t\tfunction: fn,\n\t\t\talias,\n\t\t\tover,\n\t\t};\n\n\t\tif (field !== undefined) {\n\t\t\treturn { ...intent, field };\n\t\t}\n\t\treturn intent;\n\t}\n}\n\n// ============================================================================\n// Window Function Factory Functions\n// ============================================================================\n\n/**\n * ROW_NUMBER window function: sequential row number within partition\n *\n * @example\n * rowNumber().orderBy('created_at', 'desc').as('rn')\n * // → ROW_NUMBER() OVER (ORDER BY \"created_at\" DESC) AS \"rn\"\n */\nexport function rowNumber(): WindowBuilder {\n\treturn WindowBuilder.ranking('row_number');\n}\n\n/**\n * RANK window function: rank with gaps for ties\n *\n * @example\n * rank().partitionBy('category').orderBy('price').as('price_rank')\n * // → RANK() OVER (PARTITION BY \"category\" ORDER BY \"price\" ASC) AS \"price_rank\"\n */\nexport function rank(): WindowBuilder {\n\treturn WindowBuilder.ranking('rank');\n}\n\n/**\n * DENSE_RANK window function: rank without gaps\n *\n * @example\n * denseRank().partitionBy('dept').orderBy('salary', 'desc').as('salary_rank')\n * // → DENSE_RANK() OVER (PARTITION BY \"dept\" ORDER BY \"salary\" DESC) AS \"salary_rank\"\n */\nexport function denseRank(): WindowBuilder {\n\treturn WindowBuilder.ranking('dense_rank');\n}\n\n/**\n * SUM window function: running/cumulative sum\n *\n * @param field - Field to sum\n *\n * @example\n * wSum('amount').partitionBy('user_id').orderBy('date').as('running_total')\n * // → SUM(\"amount\") OVER (PARTITION BY \"user_id\" ORDER BY \"date\" ASC) AS \"running_total\"\n */\nexport function wSum(field: string): WindowBuilder {\n\treturn WindowBuilder.aggregate('sum', field);\n}\n\n/**\n * AVG window function: running/cumulative average\n *\n * @param field - Field to average\n *\n * @example\n * wAvg('price').partitionBy('category').as('avg_price')\n * // → AVG(\"price\") OVER (PARTITION BY \"category\") AS \"avg_price\"\n */\nexport function wAvg(field: string): WindowBuilder {\n\treturn WindowBuilder.aggregate('avg', field);\n}\n\n/**\n * COUNT window function: count within partition.\n * When called with no argument, produces COUNT(*) OVER (...).\n *\n * @param field - Optional field to count. Omit for COUNT(*).\n *\n * @example COUNT(*) OVER()\n * wCount().over({ partitionBy: ['project_id'] }).as('total')\n * // → COUNT(*) OVER (PARTITION BY \"project_id\") AS \"total\"\n *\n * @example COUNT(field) OVER()\n * wCount('id').partitionBy('category').as('items_in_category')\n * // → COUNT(\"id\") OVER (PARTITION BY \"category\") AS \"items_in_category\"\n */\nexport function wCount(field?: string): WindowBuilder {\n\treturn WindowBuilder.aggregate('count', field);\n}\n\n/**\n * MIN window function: minimum value within partition\n *\n * @param field - Field to find minimum of\n *\n * @example\n * wMin('price').partitionBy('category').as('min_price')\n * // → MIN(\"price\") OVER (PARTITION BY \"category\") AS \"min_price\"\n */\nexport function wMin(field: string): WindowBuilder {\n\treturn WindowBuilder.aggregate('min', field);\n}\n\n/**\n * MAX window function: maximum value within partition\n *\n * @param field - Field to find maximum of\n *\n * @example\n * wMax('price').partitionBy('category').as('max_price')\n * // → MAX(\"price\") OVER (PARTITION BY \"category\") AS \"max_price\"\n */\nexport function wMax(field: string): WindowBuilder {\n\treturn WindowBuilder.aggregate('max', field);\n}\n\n/**\n * LAG window function: access previous row value\n *\n * @param field - Field to access from previous row\n *\n * @example\n * lag('amount').orderBy('date').as('prev_amount')\n * // → LAG(\"amount\") OVER (ORDER BY \"date\" ASC) AS \"prev_amount\"\n */\nexport function lag(field: string): WindowBuilder {\n\treturn WindowBuilder.offset('lag', field);\n}\n\n/**\n * LEAD window function: access next row value\n *\n * @param field - Field to access from next row\n *\n * @example\n * lead('amount').orderBy('date').as('next_amount')\n * // → LEAD(\"amount\") OVER (ORDER BY \"date\" ASC) AS \"next_amount\"\n */\nexport function lead(field: string): WindowBuilder {\n\treturn WindowBuilder.offset('lead', field);\n}\n","/**\n * @module filters\n * Drizzle-like filter helpers for ergonomic WHERE clause building.\n *\n * These are pure factory functions that return WhereIntent objects.\n * They can be composed with and(), or(), not() for complex conditions.\n *\n * @example\n * ```typescript\n * import { eq, and, gt, like } from '@dbsp/core';\n *\n * // Simple equality\n * orm.select('users').where(eq('status', 'active'))\n *\n * // Combined conditions\n * orm.select('users').where(\n * and(\n * eq('status', 'active'),\n * gt('age', 18),\n * like('email', '%@example.com')\n * )\n * )\n * ```\n */\n\nimport type { Mutable } from '@dbsp/types/internal';\nimport type {\n\tComparisonOperator,\n\tQueryIntent,\n\tRecursiveExistsOptions,\n\tWhereAndIntent,\n\tWhereAnyIntent,\n\tWhereComparisonIntent,\n\tWhereExistsIntent,\n\tWhereInIntent,\n\tWhereIntent,\n\tWhereLikeIntent,\n\tWhereNotExistsIntent,\n\tWhereNotIntent,\n\tWhereNullIntent,\n\tWhereOrIntent,\n\tWhereRangeIntent,\n\tWhereRawExistsIntent,\n\tWhereRawNotExistsIntent,\n\tWhereRelationFilterIntent,\n} from '../intent-ast.js';\nimport { getColumnName } from './column-utils.js';\nimport { validateIdentifier } from './errors.js';\nimport type {\n\tSubqueryBuilder,\n\tSubqueryExpression,\n} from './subquery-builder.js';\nimport {\n\ttype ColumnRef,\n\tRELATION_META,\n\ttype RelationRef,\n} from './table-ref.js';\nimport type { AliasedExprColumn, ExpressionSpec } from './types.js';\n\n// ============================================================================\n// Type-Safe Column Reference Support (DX-040)\n// ============================================================================\n\n// ============================================================================\n// Distinct Field Helper (for aggregates)\n// ============================================================================\n\n/**\n * Represents a field with DISTINCT modifier for aggregate functions.\n *\n * @example\n * ```typescript\n * count(distinct('customerId')) // COUNT(DISTINCT customerId)\n * sum(distinct('amount'), 'uniqueSum') // SUM(DISTINCT amount) AS uniqueSum\n * ```\n */\nexport interface DistinctField {\n\treadonly field: string;\n\treadonly distinct: true;\n}\n\n/**\n * Helper to mark a field as DISTINCT for aggregate functions.\n *\n * @param field - The field name to apply DISTINCT to\n * @returns A DistinctField object that can be passed to aggregate functions\n *\n * @example\n * ```typescript\n * import { distinct } from '@dbsp/core';\n *\n * // COUNT(DISTINCT customerId)\n * orm.select('orders').count(distinct('customerId')).execute();\n *\n * // COUNT(DISTINCT customerId) AS unique_customers\n * orm.select('orders').count(distinct('customerId'), 'unique_customers').execute();\n *\n * // SUM(DISTINCT amount) - rare but valid SQL\n * orm.select('orders').sum(distinct('amount'), 'unique_total').execute();\n * ```\n */\nexport function distinct(field: string): DistinctField {\n\treturn { field, distinct: true };\n}\n\n/**\n * Type guard to check if a value is a DistinctField.\n */\nexport function isDistinctField(value: unknown): value is DistinctField {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'field' in value &&\n\t\t'distinct' in value &&\n\t\t(value as DistinctField).distinct === true\n\t);\n}\n\n// ============================================================================\n// Comparison Operators\n// ============================================================================\n\ntype ComparisonFilter = {\n\t<T extends string, C extends string, V>(\n\t\tfield: ColumnRef<T, C, V>,\n\t\tvalue: V,\n\t): WhereComparisonIntent;\n\t(field: string, value: unknown): WhereComparisonIntent;\n};\n\nfunction createComparisonFilter(\n\toperator: ComparisonOperator,\n): ComparisonFilter {\n\treturn (\n\t\tfield: ColumnRef<string, string, unknown> | string,\n\t\tvalue: unknown,\n\t): WhereComparisonIntent => ({\n\t\tkind: 'comparison',\n\t\tfield: getColumnName(field),\n\t\toperator,\n\t\tvalue,\n\t});\n}\n\n/**\n * Equals comparison: field = value\n *\n * @example eq('status', 'active') → status = 'active'\n * @example eq(users.name, 'John') → type-safe with ColumnRef (DX-040)\n */\nexport const eq: ComparisonFilter = createComparisonFilter('eq');\n\n/**\n * Not equals comparison: field != value\n *\n * @example neq('status', 'deleted') → status != 'deleted'\n * @example neq(users.status, 'deleted') → type-safe with ColumnRef (DX-040)\n */\nexport const neq: ComparisonFilter = createComparisonFilter('neq');\n\n/**\n * Greater than comparison: field > value\n *\n * @example gt('age', 18) → age > 18\n * @example gt(users.age, 18) → type-safe with ColumnRef (DX-040)\n */\nexport const gt: ComparisonFilter = createComparisonFilter('gt');\n\n/**\n * Greater than or equal comparison: field >= value\n *\n * @example gte('age', 18) → age >= 18\n * @example gte(users.age, 18) → type-safe with ColumnRef (DX-040)\n */\nexport const gte: ComparisonFilter = createComparisonFilter('gte');\n\n/**\n * Less than comparison: field < value\n *\n * @example lt('price', 100) → price < 100\n * @example lt(products.price, 100) → type-safe with ColumnRef (DX-040)\n */\nexport const lt: ComparisonFilter = createComparisonFilter('lt');\n\n/**\n * Less than or equal comparison: field <= value\n *\n * @example lte('price', 100) → price <= 100\n * @example lte(products.price, 100) → type-safe with ColumnRef (DX-040)\n */\nexport const lte: ComparisonFilter = createComparisonFilter('lte');\n\n/**\n * Null-safe inequality: field IS DISTINCT FROM value\n *\n * Unlike neq(), returns true when one side is NULL and the other is not.\n * Standard SQL (SQL:2003).\n *\n * @example isDistinctFrom('status', 'active') → status IS DISTINCT FROM 'active'\n * @example isDistinctFrom(users.status, null) → status IS DISTINCT FROM NULL\n */\nexport const isDistinctFrom: ComparisonFilter =\n\tcreateComparisonFilter('isDistinctFrom');\n\n// ============================================================================\n// String Operators\n// ============================================================================\n\n/**\n * LIKE pattern matching: field LIKE pattern\n *\n * @param field - Column name or ColumnRef (must be string type)\n * @param pattern - SQL LIKE pattern (use % for wildcards)\n * @param caseInsensitive - If true, uses ILIKE (PostgreSQL) or LOWER()\n *\n * @example like('name', '%john%') → name LIKE '%john%'\n * @example like('email', '%@example.com', true) → email ILIKE '%@example.com'\n * @example like(users.name, '%John%') → type-safe with ColumnRef (DX-040)\n */\nexport function like<T extends string, C extends string>(\n\tfield: ColumnRef<T, C, string>,\n\tpattern: string,\n\toptions?: boolean | { caseInsensitive?: boolean; escape?: string },\n): WhereLikeIntent;\nexport function like(\n\tfield: string,\n\tpattern: string,\n\toptions?: boolean | { caseInsensitive?: boolean; escape?: string },\n): WhereLikeIntent;\nexport function like(\n\tfield: ColumnRef<string, string, string> | string,\n\tpattern: string,\n\toptions?: boolean | { caseInsensitive?: boolean; escape?: string },\n): WhereLikeIntent {\n\tconst caseInsensitive =\n\t\ttypeof options === 'boolean' ? options : options?.caseInsensitive;\n\tconst escapeChar = typeof options === 'object' ? options.escape : undefined;\n\n\tconst intent: WhereLikeIntent = {\n\t\tkind: 'like',\n\t\tfield: getColumnName(field),\n\t\tpattern,\n\t};\n\tconst withCi =\n\t\tcaseInsensitive !== undefined ? { ...intent, caseInsensitive } : intent;\n\tif (escapeChar !== undefined) {\n\t\treturn { ...withCi, escape: escapeChar };\n\t}\n\treturn withCi;\n}\n\n// ============================================================================\n// Array Operators\n// ============================================================================\n\n/**\n * IN array check: field IN (values)\n *\n * @example inArray('status', ['active', 'pending']) → status IN ('active', 'pending')\n * @example inArray(users.role, ['admin', 'moderator']) → type-safe (DX-040)\n */\nexport function inArray<T extends string, C extends string, V>(\n\tfield: ColumnRef<T, C, V>,\n\tvalues: readonly V[],\n): WhereInIntent;\nexport function inArray(\n\tfield: string,\n\tvalues: readonly unknown[],\n): WhereInIntent;\nexport function inArray(\n\tfield: ColumnRef<string, string, unknown> | string,\n\tvalues: readonly unknown[],\n): WhereInIntent {\n\treturn { kind: 'in', field: getColumnName(field), values };\n}\n\n/**\n * IN subquery: field IN (SELECT ...)\n *\n * Creates a WHERE condition that checks if a field's value exists\n * in the result set of a subquery.\n *\n * @example\n * // Users who have posts\n * orm.select('users').where(inSubquery('id',\n * subquery('posts').select('userId')\n * )).all()\n * // SQL: SELECT * FROM users WHERE id = ANY(SELECT user_id FROM posts)\n */\nexport function inSubquery(\n\tfield: ColumnRef<string, string, unknown> | string,\n\tquery: SubqueryBuilder | SubqueryExpression,\n): WhereInIntent {\n\tconst expr =\n\t\t'build' in query\n\t\t\t? (query as SubqueryBuilder).build()\n\t\t\t: (query as SubqueryExpression);\n\treturn {\n\t\tkind: 'in',\n\t\tfield: getColumnName(field),\n\t\tvalues: [],\n\t\tsubquery: expr.toIntent(),\n\t};\n}\n\n/**\n * Array membership filter using PostgreSQL ANY() operator.\n * Compiles to: \"col\" = ANY($N::type[])\n *\n * Unlike inArray(), any() produces an explicit type-cast in the SQL.\n * Use this when you need guaranteed type safety with array parameters.\n *\n * @example\n * orm.select('symbols').where(any('id', [1, 2, 3])).all()\n * // SQL: SELECT * FROM \"symbols\" WHERE \"id\" = ANY($1::int[])\n */\nexport function any(\n\tfield: ColumnRef<string, string, unknown> | string,\n\tvalues: readonly unknown[],\n): WhereAnyIntent {\n\treturn { kind: 'any', field: getColumnName(field), values };\n}\n\n// ============================================================================\n// Null Operators\n// ============================================================================\n\n/**\n * IS NULL check: field IS NULL\n *\n * @example isNull('deletedAt') → deletedAt IS NULL\n * @example isNull(users.deletedAt) → type-safe (DX-040)\n */\nexport function isNull<T extends string, C extends string, V>(\n\tfield: ColumnRef<T, C, V>,\n): WhereNullIntent;\nexport function isNull(field: string): WhereNullIntent;\nexport function isNull(\n\tfield: ColumnRef<string, string, unknown> | string,\n): WhereNullIntent {\n\treturn { kind: 'null', field: getColumnName(field), operator: 'isNull' };\n}\n\n// ============================================================================\n// Range Operators (PostgreSQL)\n// ============================================================================\n\n/**\n * Range value for PostgreSQL range types.\n * @see WhereRangeIntent\n */\nimport type { RangeValue } from '@dbsp/types';\n\nexport type { RangeValue } from '@dbsp/types';\n\n/**\n * Range OVERLAPS check: field && range (PostgreSQL)\n * Tests if two ranges have any points in common.\n *\n * @example rangeOverlaps('dates', { lower: '2025-01-15', upper: '2025-01-20' })\n * → dates && '[2025-01-15,2025-01-20)'\n *\n * @param field - Column name containing a range type\n * @param value - Range value with lower/upper bounds\n */\nexport function rangeOverlaps(\n\tfield: string,\n\tvalue: RangeValue,\n): WhereRangeIntent {\n\treturn { kind: 'range', field, operator: 'overlaps', value };\n}\n\n/**\n * Range CONTAINS check: field @> value (PostgreSQL)\n * Tests if the range contains a point or another range.\n *\n * @example rangeContains('salary_range', 50000)\n * → salary_range @> 50000\n * @example rangeContains('date_range', { lower: '2025-01-01', upper: '2025-01-05' })\n * → date_range @> '[2025-01-01,2025-01-05)'\n *\n * @param field - Column name containing a range type\n * @param value - Scalar value or range to check containment\n */\nexport function rangeContains(\n\tfield: string,\n\tvalue: RangeValue | unknown,\n): WhereRangeIntent {\n\treturn { kind: 'range', field, operator: 'contains', value };\n}\n\n/**\n * Range CONTAINED BY check: field <@ range (PostgreSQL)\n * Tests if the field's range is fully contained within another range.\n *\n * @example rangeContainedBy('event_dates', { lower: '2025-01-01', upper: '2025-12-31' })\n * → event_dates <@ '[2025-01-01,2025-12-31)'\n *\n * @param field - Column name containing a range type\n * @param value - Range that should contain the field's range\n */\nexport function rangeContainedBy(\n\tfield: string,\n\tvalue: RangeValue,\n): WhereRangeIntent {\n\treturn { kind: 'range', field, operator: 'containedBy', value };\n}\n\n/**\n * IS NOT NULL check: field IS NOT NULL\n *\n * @example isNotNull('email') → email IS NOT NULL\n * @example isNotNull(users.email) → type-safe (DX-040)\n */\nexport function isNotNull<T extends string, C extends string, V>(\n\tfield: ColumnRef<T, C, V>,\n): WhereNullIntent;\nexport function isNotNull(field: string): WhereNullIntent;\nexport function isNotNull(\n\tfield: ColumnRef<string, string, unknown> | string,\n): WhereNullIntent {\n\treturn { kind: 'null', field: getColumnName(field), operator: 'isNotNull' };\n}\n\n// ============================================================================\n// Logical Operators\n// ============================================================================\n\n/**\n * Logical AND: all conditions must match\n *\n * Accepts variadic arguments or a single array.\n *\n * @example and(eq('a', 1), gt('b', 2)) → a = 1 AND b > 2\n * @example and([eq('a', 1), gt('b', 2)]) → a = 1 AND b > 2\n */\nexport function and(\n\t...conditions: WhereIntent[] | [readonly WhereIntent[]]\n): WhereAndIntent {\n\t// Handle both variadic and array forms\n\tconst flatConditions =\n\t\tconditions.length === 1 && Array.isArray(conditions[0])\n\t\t\t? (conditions[0] as readonly WhereIntent[])\n\t\t\t: (conditions as WhereIntent[]);\n\n\treturn { kind: 'and', conditions: flatConditions };\n}\n\n/**\n * Logical OR: at least one condition must match\n *\n * Accepts variadic arguments or a single array.\n *\n * @example or(eq('status', 'active'), eq('status', 'pending'))\n * @example or([eq('status', 'active'), eq('status', 'pending')])\n */\nexport function or(\n\t...conditions: WhereIntent[] | [readonly WhereIntent[]]\n): WhereOrIntent {\n\t// Handle both variadic and array forms\n\tconst flatConditions =\n\t\tconditions.length === 1 && Array.isArray(conditions[0])\n\t\t\t? (conditions[0] as readonly WhereIntent[])\n\t\t\t: (conditions as WhereIntent[]);\n\n\treturn { kind: 'or', conditions: flatConditions };\n}\n\n/**\n * Logical NOT: condition must not match\n *\n * @example not(eq('deleted', true)) → NOT (deleted = true)\n */\nexport function not(condition: WhereIntent): WhereNotIntent {\n\treturn { kind: 'not', condition };\n}\n\n// ============================================================================\n// Relation Operators\n// ============================================================================\n\n/**\n * EXISTS subquery: filter by existence of related records\n *\n * @param relation - Relation name defined in schema\n * @param options - Optional nested filter on related records, with optional recursive options\n *\n * @example exists('posts') → EXISTS (SELECT 1 FROM posts WHERE ...)\n * @example exists('posts', { where: eq('published', true) })\n * @example exists('ancestors', { recursive: { direction: 'up', through: 'parent', maxDepth: 10 }, where: eq('name', 'Electronics') })\n */\nexport function exists(\n\trelation: string,\n\toptions?: {\n\t\twhere?: WhereIntent;\n\t\trecursive?: RecursiveExistsOptions;\n\t\tinclude?: Record<string, { join?: 'inner' | 'left' }>;\n\t},\n): WhereExistsIntent {\n\tconst result: Mutable<WhereExistsIntent> = { kind: 'exists', relation };\n\tif (options?.where !== undefined) {\n\t\tresult.where = options.where;\n\t}\n\tif (options?.recursive !== undefined) {\n\t\tresult.recursive = options.recursive;\n\t}\n\tif (options?.include !== undefined) {\n\t\tresult.include = options.include;\n\t}\n\treturn result;\n}\n\n/**\n * NOT EXISTS subquery: filter by absence of related records\n *\n * @param relation - Relation name defined in schema\n * @param options - Optional nested filter on related records, with optional recursive options\n *\n * @example notExists('comments') → NOT EXISTS (SELECT 1 FROM comments WHERE ...)\n * @example notExists('ancestors', { recursive: { direction: 'up', through: 'parent' }, where: eq('name', 'Obsolete') })\n */\nexport function notExists(\n\trelation: string,\n\toptions?: {\n\t\twhere?: WhereIntent;\n\t\trecursive?: RecursiveExistsOptions;\n\t\tinclude?: Record<string, { join?: 'inner' | 'left' }>;\n\t},\n): WhereNotExistsIntent {\n\tconst result: Mutable<WhereNotExistsIntent> = {\n\t\tkind: 'notExists',\n\t\trelation,\n\t};\n\tif (options?.where !== undefined) {\n\t\tresult.where = options.where;\n\t}\n\tif (options?.recursive !== undefined) {\n\t\tresult.recursive = options.recursive;\n\t}\n\tif (options?.include !== undefined) {\n\t\tresult.include = options.include;\n\t}\n\treturn result;\n}\n\n/**\n * EXISTS with an arbitrary subquery (not FK-resolved).\n *\n * Use when the subquery does not follow a declared schema relation.\n * Accepts a SubqueryBuilder (must have `.build()`) or any builder\n * exposing `buildIntent(): QueryIntent` (e.g. QueryBuilder).\n *\n * @param subquery - A SubqueryBuilder or any object with buildIntent()\n *\n * @example\n * // EXISTS (SELECT 1 FROM audit_log WHERE audit_log.entity_id = users.id)\n * rawExists(subquery('audit_log').select('id').where(eq('entityId', outerRef('id'))))\n *\n * @example\n * // EXISTS with a full query builder\n * rawExists(orm.select('sessions').where(and(eq('userId', outerRef('id')), gt('expiresAt', new Date()))))\n */\nexport function rawExists(\n\tsq: SubqueryBuilder | { buildIntent(): QueryIntent },\n): WhereRawExistsIntent {\n\tconst intent =\n\t\t'buildIntent' in sq\n\t\t\t? (sq as { buildIntent(): QueryIntent }).buildIntent()\n\t\t\t: (sq as SubqueryBuilder).build().toIntent();\n\treturn { kind: 'rawExists', subquery: intent };\n}\n\n/**\n * NOT EXISTS with an arbitrary subquery (not FK-resolved).\n *\n * Use when the subquery does not follow a declared schema relation.\n * Accepts a SubqueryBuilder (must have `.build()`) or any builder\n * exposing `buildIntent(): QueryIntent` (e.g. QueryBuilder).\n *\n * @param subquery - A SubqueryBuilder or any object with buildIntent()\n *\n * @example\n * // NOT EXISTS (SELECT 1 FROM bans WHERE bans.user_id = users.id)\n * rawNotExists(subquery('bans').select('id').where(eq('userId', outerRef('id'))))\n */\nexport function rawNotExists(\n\tsq: SubqueryBuilder | { buildIntent(): QueryIntent },\n): WhereRawNotExistsIntent {\n\tconst intent =\n\t\t'buildIntent' in sq\n\t\t\t? (sq as { buildIntent(): QueryIntent }).buildIntent()\n\t\t\t: (sq as SubqueryBuilder).build().toIntent();\n\treturn { kind: 'rawNotExists', subquery: intent };\n}\n\n// ============================================================================\n// Quantified Relation Filters (DX-040 Block 7)\n// ============================================================================\n\n/**\n * Get relation name from a RelationRef.\n * @internal\n */\nfunction getRelationName(\n\trel: RelationRef<string, unknown, 'belongsTo' | 'hasMany' | 'hasOne'>,\n): string {\n\tconst meta = rel[RELATION_META];\n\tif (!meta) {\n\t\tthrow new Error('Invalid RelationRef: missing RELATION_META');\n\t}\n\treturn meta.target;\n}\n\n/**\n * EVERY quantifier: filter parent by condition that ALL related records must match\n *\n * This generates SQL like: NOT EXISTS (SELECT 1 FROM related WHERE NOT condition)\n *\n * @param relation - RelationRef from schema (e.g., users.posts)\n * @param filter - Callback that receives relation and returns a filter condition\n *\n * @example\n * ```typescript\n * // Find users where ALL their posts are published\n * orm.from(users)\n * .where(every(users.posts, p => eq(p.published, true)))\n *\n * // SQL: ... WHERE NOT EXISTS (\n * // SELECT 1 FROM posts WHERE posts.author_id = users.id AND NOT (posts.published = true)\n * // )\n * ```\n */\nexport function every<TTarget extends string, TTargetType>(\n\trelation: RelationRef<TTarget, TTargetType[], 'hasMany'>,\n\tfilter: (rel: RelationRef<TTarget, TTargetType[], 'hasMany'>) => WhereIntent,\n): WhereRelationFilterIntent {\n\tconst relationName = getRelationName(relation);\n\tconst where = filter(relation);\n\treturn {\n\t\tkind: 'relationFilter',\n\t\trelation: relationName,\n\t\twhere,\n\t\tmode: 'every',\n\t};\n}\n\n/**\n * NONE quantifier: filter parent by condition that NO related records match\n *\n * This is equivalent to: NOT EXISTS (SELECT 1 FROM related WHERE condition)\n *\n * @param relation - RelationRef from schema (e.g., users.posts)\n * @param filter - Callback that receives relation and returns a filter condition\n *\n * @example\n * ```typescript\n * // Find users with no flagged posts\n * orm.from(users)\n * .where(none(users.posts, p => eq(p.flagged, true)))\n *\n * // SQL: ... WHERE NOT EXISTS (\n * // SELECT 1 FROM posts WHERE posts.author_id = users.id AND posts.flagged = true\n * // )\n * ```\n */\nexport function none<TTarget extends string, TTargetType>(\n\trelation: RelationRef<TTarget, TTargetType[], 'hasMany'>,\n\tfilter: (rel: RelationRef<TTarget, TTargetType[], 'hasMany'>) => WhereIntent,\n): WhereRelationFilterIntent {\n\tconst relationName = getRelationName(relation);\n\tconst where = filter(relation);\n\treturn {\n\t\tkind: 'relationFilter',\n\t\trelation: relationName,\n\t\twhere,\n\t\tmode: 'none',\n\t};\n}\n\n/**\n * SOME quantifier: filter parent by condition that at least one related record matches\n *\n * This is the default behavior for relation filters and is equivalent to EXISTS.\n *\n * @param relation - RelationRef from schema (e.g., users.posts)\n * @param filter - Callback that receives relation and returns a filter condition\n *\n * @example\n * ```typescript\n * // Find users with at least one published post\n * orm.from(users)\n * .where(some(users.posts, p => eq(p.published, true)))\n *\n * // SQL: ... WHERE EXISTS (\n * // SELECT 1 FROM posts WHERE posts.author_id = users.id AND posts.published = true\n * // )\n * ```\n */\nexport function some<TTarget extends string, TTargetType>(\n\trelation: RelationRef<TTarget, TTargetType[], 'hasMany'>,\n\tfilter: (rel: RelationRef<TTarget, TTargetType[], 'hasMany'>) => WhereIntent,\n): WhereRelationFilterIntent {\n\tconst relationName = getRelationName(relation);\n\tconst where = filter(relation);\n\treturn {\n\t\tkind: 'relationFilter',\n\t\trelation: relationName,\n\t\twhere,\n\t\tmode: 'some',\n\t};\n}\n\n// ============================================================================\n// Expression Helpers\n// ============================================================================\n\n/**\n * COALESCE expression: returns first non-null value from a list of fields\n *\n * Use this for locale fallback patterns (e.g., FR → EN → default)\n *\n * @param fields - Array of field names to check in order\n * @param as - Required alias for the result column\n *\n * @example\n * ```typescript\n * // Locale fallback: prefer French, fall back to English\n * coalesce(['name_fr', 'name_en'], 'display_name')\n * // → COALESCE(name_fr, name_en) AS display_name\n *\n * // Use in QueryBuilder select with expressions\n * orm.select('products')\n * .selectWithExpressions(['id', 'sku'], [\n * coalesce(['title_fr', 'title_en', 'title_default'], 'title')\n * ])\n * ```\n */\nexport function coalesce(\n\tfields: readonly string[],\n\tas: string,\n): ExpressionSpec {\n\tif (fields.length === 0) {\n\t\tthrow new Error('coalesce() requires at least one field');\n\t}\n\tif (!as || as.trim() === '') {\n\t\tthrow new Error('coalesce() requires a non-empty alias');\n\t}\n\t// FIND-008: Validate all field names and the alias as SQL identifiers\n\tfor (const f of fields) {\n\t\tvalidateIdentifier(f, 'column');\n\t}\n\tvalidateIdentifier(as, 'column');\n\treturn {\n\t\t__expr: true,\n\t\tintent: { kind: 'coalesce', fields, as },\n\t};\n}\n\n/**\n * Raw SQL expression (escape hatch for advanced use cases).\n *\n * @warning **SECURITY RISK: SQL INJECTION VULNERABILITY**\n *\n * This function bypasses ALL SQL injection protections. The SQL fragment\n * is inserted directly into queries without sanitization.\n *\n * **NEVER:**\n * - Interpolate user input: `raw(\\`WHERE name = '\\${userInput}'\\`, 'x')` ❌\n * - Use request parameters: `raw(req.query.field, 'x')` ❌\n * - Trust client-side data: `raw(formData.expression, 'x')` ❌\n *\n * **SAFE USAGE:**\n * - Hardcoded expressions: `raw('NOW()', 'current_time')` ✅\n * - Constants: `raw('price_cents / 100.0', 'price_dollars')` ✅\n * - Server-controlled values only\n *\n * For user-provided values, use parameterized queries via the standard\n * filter functions (eq, gt, like, etc.) which properly escape values.\n *\n * @param sqlFragment - Raw SQL fragment. **Must be safe - no user input!**\n * @param as - Required alias for the result column\n * @returns ExpressionSpec for use in select()\n *\n * @example\n * ```typescript\n * // SAFE: Hardcoded expressions\n * raw('NOW()', 'current_time')\n * // → NOW() AS current_time\n *\n * raw('price_cents / 100.0', 'price_dollars')\n * // → price_cents / 100.0 AS price_dollars\n *\n * // DANGEROUS - SQL INJECTION RISK!\n * // raw(`WHERE name = '${userInput}'`, 'x') // NEVER DO THIS!\n * ```\n *\n * @see {@link https://owasp.org/www-community/attacks/SQL_Injection | OWASP SQL Injection}\n * @see {@link https://cheatsheetseries.owasp.org/cheatsheets/Query_Parameterization_Cheat_Sheet.html | OWASP Parameterization}\n */\nexport function raw(sqlFragment: string, as: string): ExpressionSpec {\n\tif (!as || as.trim() === '') {\n\t\tthrow new Error('raw() requires a non-empty alias');\n\t}\n\treturn {\n\t\t__expr: true,\n\t\tintent: { kind: 'raw', sql: sqlFragment, as },\n\t};\n}\n\n/**\n * Creates a column alias expression using native Kysely API.\n * Preferred over raw() for simple column aliasing as it's type-safe and dialect-portable.\n *\n * Uses Kysely's `eb.ref(column).as(alias)` internally - no raw SQL.\n *\n * @param column - Column name to select\n * @param alias - Alias for the result column\n * @returns ExpressionSpec for use in columns()\n *\n * @example\n * ```typescript\n * // Simple column alias\n * col('name', 'userName')\n * // → SELECT \"name\" AS \"userName\"\n *\n * // Multiple columns with aliases\n * orm.select('users').columns([\n * 'id',\n * col('name', 'userName'),\n * col('email', 'userEmail'),\n * ])\n * ```\n */\nexport function col(column: string, alias: string): ExpressionSpec {\n\tif (!column || column.trim() === '') {\n\t\tthrow new Error('col() requires a non-empty column name');\n\t}\n\tif (!alias || alias.trim() === '') {\n\t\tthrow new Error('col() requires a non-empty alias');\n\t}\n\treturn {\n\t\t__expr: true,\n\t\tintent: { kind: 'columnAlias', column, alias },\n\t};\n}\n\n/**\n * Creates a relation column expression for selecting a column from a related table.\n * Auto-creates JOINs via the include mechanism and selects with custom alias.\n *\n * Uses native Kysely API internally - no raw SQL. The compiler resolves the relation\n * to its join alias and uses `eb.ref(alias.column).as(as)`.\n *\n * @param relation - Relation path to traverse (dot-separated for multi-level)\n * @param column - Column name to select from the target relation\n * @param as - Alias for the result column\n * @returns ExpressionSpec for use in columns()\n *\n * @example\n * ```typescript\n * // Select from direct relation\n * relationColumn('category', 'name', 'categoryName')\n * // → SELECT t1.\"name\" AS \"categoryName\" (with JOIN to categories)\n *\n * // Select from nested relation (multi-level path)\n * relationColumn('category.parent', 'name', 'parentName')\n * // → SELECT t2.\"name\" AS \"parentName\" (with JOINs through category to parent)\n *\n * // In a query\n * orm.select('products').columns([\n * 'name',\n * relationColumn('category', 'name', 'categoryName'),\n * ])\n * ```\n */\nexport function relationColumn<A extends string>(\n\trelation: string,\n\tcolumn: string,\n\tas: A,\n): AliasedExprColumn<A> {\n\tif (!relation || relation.trim() === '') {\n\t\tthrow new Error('relationColumn() requires a non-empty relation path');\n\t}\n\tif (!column || column.trim() === '') {\n\t\tthrow new Error('relationColumn() requires a non-empty column name');\n\t}\n\tif (!as || (as as string).trim() === '') {\n\t\tthrow new Error('relationColumn() requires a non-empty alias');\n\t}\n\treturn {\n\t\t__expr: true,\n\t\tintent: { kind: 'relationColumn', relation, column, as },\n\t} as unknown as AliasedExprColumn<A>;\n}\n\n// ============================================================================\n// Raw SQL Set Expression (for doUpdate() / set() mutations)\n// ============================================================================\n\n/**\n * Symbol to identify raw SQL expression values in set() / doUpdate()\n * @internal\n */\nexport const SQL_RAW_MARKER = Symbol.for('dbsp:raw-sql');\n\n/**\n * A raw SQL expression for use in mutation set values (doUpdate / set).\n * Created by the {@link sql} function.\n */\nexport interface SqlRawExpression {\n\treadonly [SQL_RAW_MARKER]: true;\n\treadonly sql: string;\n}\n\n/**\n * Create a raw SQL expression for use in `doUpdate()` and `set()` mutation values.\n *\n * @warning **SECURITY RISK: SQL INJECTION VULNERABILITY**\n * The SQL fragment is inserted **WITHOUT** parameterization.\n * Only use with hardcoded expressions — **NEVER** with user input.\n *\n * **SAFE USAGE:**\n * - Hardcoded functions: `sql('now()')` ✅\n * - Excluded references: `sql('excluded.count + 1')` ✅\n * - Server-controlled literals: `sql('gen_random_uuid()')` ✅\n *\n * **NEVER:**\n * - Interpolate user input: `` sql(`'${userInput}'`) `` ❌\n * - Use request parameters: `sql(req.query.expr)` ❌\n *\n * @param sqlFragment - Raw SQL fragment (must be safe — no user input!)\n * @returns SqlRawExpression for use in doUpdate() / set()\n *\n * @example\n * ```typescript\n * orm.upsert('files')\n * .values({ id: 1, name: 'test' })\n * .onConflict({ columns: ['id'] })\n * .doUpdate({ last_parsed: sql('now()'), count: sql('excluded.count + 1') })\n * .execute();\n *\n * orm.update('files')\n * .set({ last_parsed: sql('now()') })\n * .where(eq('id', 1))\n * .execute();\n * ```\n *\n * @see {@link https://owasp.org/www-community/attacks/SQL_Injection | OWASP SQL Injection}\n */\nexport function sql(sqlFragment: string): SqlRawExpression {\n\tif (!sqlFragment || sqlFragment.trim() === '') {\n\t\tthrow new Error('sql() requires a non-empty SQL fragment');\n\t}\n\treturn { [SQL_RAW_MARKER]: true, sql: sqlFragment };\n}\n\n/**\n * Type guard: check if a value is a raw SQL expression created by {@link sql}.\n */\nexport function isSqlRaw(value: unknown): value is SqlRawExpression {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tSQL_RAW_MARKER in value &&\n\t\t(value as Record<symbol, unknown>)[SQL_RAW_MARKER] === true\n\t);\n}\n\n// ============================================================================\n// Window Functions (re-exported from window-functions.ts)\n// ============================================================================\n\nexport {\n\tdenseRank,\n\tlag,\n\tlead,\n\trank,\n\trowNumber,\n\tWindowBuilder,\n\twAvg,\n\twCount,\n\twMax,\n\twMin,\n\twSum,\n} from './window-functions.js';\n","/**\n * @dbsp/core — Full-Text Search Helpers (FR-5)\n *\n * High-level cross-DB-friendly helpers that wrap the low-level ParadeDB\n * expression primitives (bm25Search / score from adapter-pgsql) using only\n * core expression building blocks.\n *\n * These helpers are ParadeDB/PostgreSQL-first; other adapters are expected\n * to either support the same SQL or receive a capability error at runtime.\n */\n\nimport type { ExpressionRef } from './expressions.js';\nimport { array, fn, literal, namedArg, op, param, ref } from './expressions.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * A single field to include in a full-text search, with an optional boost weight.\n */\nexport type FullTextSearchField = {\n\t/** Column name in the BM25 index */\n\treadonly name: string;\n\t/** Boost multiplier (higher = more important). Default: 1.0 */\n\treadonly boost: number;\n};\n\n/**\n * Options for fullTextSearch().\n */\nexport type FullTextSearchOptions = {\n\t/** The query string (will be bound as a single $N parameter shared across all fields). */\n\treadonly query: unknown;\n\t/** Fields to search with per-field boost weights. */\n\treadonly fields: readonly FullTextSearchField[];\n\t/**\n\t * Table name or alias to qualify the left side of the @@@ operator.\n\t * Must match the exact table name (or alias) as it appears in the FROM clause.\n\t * In the standard ORM pipeline the root table has no alias, so pass the root table name.\n\t *\n\t * @example\n\t * fullTextSearch({ query, fields, tableAlias: 'symbols' })\n\t * // → \"symbols\" @@@ paradedb.boolean(...)\n\t */\n\treadonly tableAlias: string;\n};\n\n// ============================================================================\n// fullTextSearch()\n// ============================================================================\n\n/**\n * High-level full-text search filter for ParadeDB BM25 index.\n *\n * Produces:\n * ```sql\n * \"tableAlias\" @@@ paradedb.boolean(\n * should => ARRAY[\n * paradedb.boost(weight1, paradedb.parse(field => 'field1', query_string => $N)),\n * paradedb.boost(weight2, paradedb.parse(field => 'field2', query_string => $N)),\n * ...\n * ]\n * )\n * ```\n *\n * The same query value is bound to separate $N parameters, one per field.\n *\n * @param options.query - Query string (bound as a single parameter)\n * @param options.fields - Fields to search with per-field boost weights\n * @param options.tableAlias - Table name or alias as it appears in the FROM clause (required).\n * In the standard ORM pipeline the root table has no alias — pass the root table name directly.\n * @returns ExpressionRef for use in .where()\n *\n * @example\n * ```typescript\n * import { fullTextSearch } from '@dbsp/core';\n *\n * .where(fullTextSearch({\n * query: searchTerm,\n * tableAlias: 'symbols',\n * fields: [\n * { name: 'name', boost: 3.0 },\n * { name: 'doc', boost: 1.0 },\n * ],\n * }))\n * ```\n */\nexport function fullTextSearch({\n\tquery,\n\tfields,\n\ttableAlias,\n}: FullTextSearchOptions): ExpressionRef {\n\tconst queryParam = param(query);\n\tconst boostExprs = fields.map(({ name: fieldName, boost: weight }) =>\n\t\tfn(\n\t\t\t'paradedb.boost',\n\t\t\tliteral(weight),\n\t\t\tfn(\n\t\t\t\t'paradedb.parse',\n\t\t\t\tnamedArg('field', literal(fieldName)),\n\t\t\t\tnamedArg('query_string', queryParam),\n\t\t\t),\n\t\t),\n\t);\n\tconst booleanExpr = fn(\n\t\t'paradedb.boolean',\n\t\tnamedArg('should', array(...boostExprs)),\n\t);\n\treturn op('@@@', ref(tableAlias), booleanExpr);\n}\n\n// ============================================================================\n// textScore()\n// ============================================================================\n\n/**\n * BM25 relevance score expression for ParadeDB.\n *\n * Produces: paradedb.score(\"keyField\")\n *\n * Use in .columns() to include the score in results, and in .orderBy() to rank\n * results by relevance. Requires a BM25 index with the given key field on the table.\n *\n * @param keyField - The primary key field of the BM25 index (default: 'id')\n * @returns ExpressionRef for use in .columns() and .orderBy()\n *\n * @example\n * ```typescript\n * import { textScore } from '@dbsp/core';\n *\n * .columns(['*', textScore().as('score')])\n * .orderBy(textScore(), 'desc')\n * // SQL: SELECT *, paradedb.score(\"id\") AS \"score\" ... ORDER BY paradedb.score(\"id\") DESC\n * ```\n */\nexport function textScore(keyField = 'id'): ExpressionRef {\n\treturn fn('paradedb.score', ref(keyField));\n}\n","/**\n * Hook composition utilities (ARCH-008).\n * Provides compose/pipe for combining multiple hooks into one,\n * and priority-ordered registration helpers.\n */\n\nimport type {\n\tAfterMutationHook,\n\tAfterQueryHook,\n\tBeforeMutationHook,\n\tBeforeQueryHook,\n\tErrorHookContext,\n\tMutationHookContext,\n\tOnErrorHook,\n\tQueryHookContext,\n} from './hooks.js';\n\n// ============================================================================\n// Priority\n// ============================================================================\n\n/**\n * Priority levels for hook ordering.\n * Hooks with higher priority run first when sorted.\n */\nexport type HookPriority = 'critical' | 'high' | 'normal' | 'low';\n\nconst PRIORITY_ORDER: Record<HookPriority, number> = {\n\tcritical: 0,\n\thigh: 1,\n\tnormal: 2,\n\tlow: 3,\n};\n\n/**\n * A hook wrapped with an explicit priority for ordering.\n * Use {@link sortByPriority} to produce an ordered array.\n */\nexport type PrioritizedHook<TFn> = {\n\treadonly hook: TFn;\n\treadonly priority: HookPriority;\n};\n\n/**\n * Wraps a hook with a priority level for use with {@link sortByPriority}.\n *\n * @example\n * ```typescript\n * const hooks = [\n * withPriority(auditHook, 'low'),\n * withPriority(authHook, 'critical'),\n * ];\n * const ordered = sortByPriority(hooks); // authHook runs first\n * ```\n */\nexport function withPriority<TFn>(\n\thook: TFn,\n\tpriority: HookPriority,\n): PrioritizedHook<TFn> {\n\treturn { hook, priority };\n}\n\n/**\n * Sorts an array of prioritized hooks by priority (critical → high → normal → low).\n * Stable: hooks with the same priority retain their original relative order.\n *\n * @returns A new array of unwrapped hook functions in priority order.\n */\nexport function sortByPriority<TFn>(\n\thooks: readonly PrioritizedHook<TFn>[],\n): TFn[] {\n\treturn [...hooks]\n\t\t.sort((a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority])\n\t\t.map((p) => p.hook);\n}\n\n// ============================================================================\n// BeforeQueryHook composition\n// ============================================================================\n\n/**\n * Composes multiple {@link BeforeQueryHook}s into one (right-to-left execution).\n * The rightmost hook runs first; its output feeds into the next.\n * If a hook returns `undefined`, the current context is passed unchanged.\n *\n * @example\n * ```typescript\n * const composed = composeBeforeQueryHooks(loggingHook, tracingHook);\n * // tracingHook runs first, then loggingHook\n * ```\n */\nexport function composeBeforeQueryHooks(\n\t...hooks: BeforeQueryHook[]\n): BeforeQueryHook {\n\t// reverse so rightmost runs first\n\tconst ordered = [...hooks].reverse();\n\treturn async (ctx: QueryHookContext): Promise<QueryHookContext> => {\n\t\tlet current: QueryHookContext = ctx;\n\t\tfor (const hook of ordered) {\n\t\t\tconst result = await hook(current);\n\t\t\tif (result !== undefined) {\n\t\t\t\tcurrent = result;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n/**\n * Pipes multiple {@link BeforeQueryHook}s together (left-to-right execution).\n * The leftmost hook runs first; its output feeds into the next.\n * If a hook returns `undefined`, the current context is passed unchanged.\n *\n * @example\n * ```typescript\n * const piped = pipeBeforeQueryHooks(tracingHook, loggingHook);\n * // tracingHook runs first, then loggingHook\n * ```\n */\nexport function pipeBeforeQueryHooks(\n\t...hooks: BeforeQueryHook[]\n): BeforeQueryHook {\n\treturn async (ctx: QueryHookContext): Promise<QueryHookContext> => {\n\t\tlet current: QueryHookContext = ctx;\n\t\tfor (const hook of hooks) {\n\t\t\tconst result = await hook(current);\n\t\t\tif (result !== undefined) {\n\t\t\t\tcurrent = result;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n// ============================================================================\n// AfterQueryHook composition\n// ============================================================================\n\n/**\n * Composes multiple {@link AfterQueryHook}s into one (right-to-left execution).\n * The rightmost hook runs first; its output becomes the result for the next.\n * If a hook returns `undefined`, the current result is passed unchanged.\n */\nexport function composeAfterQueryHooks(\n\t...hooks: AfterQueryHook[]\n): AfterQueryHook {\n\tconst ordered = [...hooks].reverse();\n\treturn async <R>(ctx: QueryHookContext, result: R): Promise<R> => {\n\t\tlet current: R = result;\n\t\tfor (const hook of ordered) {\n\t\t\tconst next = await hook(ctx, current);\n\t\t\tif (next !== undefined) {\n\t\t\t\tcurrent = next as R;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n/**\n * Pipes multiple {@link AfterQueryHook}s together (left-to-right execution).\n * The leftmost hook runs first; its output becomes the result for the next.\n * If a hook returns `undefined`, the current result is passed unchanged.\n */\nexport function pipeAfterQueryHooks(\n\t...hooks: AfterQueryHook[]\n): AfterQueryHook {\n\treturn async <R>(ctx: QueryHookContext, result: R): Promise<R> => {\n\t\tlet current: R = result;\n\t\tfor (const hook of hooks) {\n\t\t\tconst next = await hook(ctx, current);\n\t\t\tif (next !== undefined) {\n\t\t\t\tcurrent = next as R;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n// ============================================================================\n// BeforeMutationHook composition\n// ============================================================================\n\n/**\n * Composes multiple {@link BeforeMutationHook}s into one (right-to-left execution).\n * If a hook returns `undefined`, the current context is passed unchanged.\n */\nexport function composeBeforeMutationHooks(\n\t...hooks: BeforeMutationHook[]\n): BeforeMutationHook {\n\tconst ordered = [...hooks].reverse();\n\treturn async <T>(\n\t\tctx: MutationHookContext<T>,\n\t): Promise<MutationHookContext<T>> => {\n\t\tlet current: MutationHookContext<T> = ctx;\n\t\tfor (const hook of ordered) {\n\t\t\tconst result = await hook(current);\n\t\t\tif (result !== undefined) {\n\t\t\t\tcurrent = result;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n/**\n * Pipes multiple {@link BeforeMutationHook}s together (left-to-right execution).\n * If a hook returns `undefined`, the current context is passed unchanged.\n */\nexport function pipeBeforeMutationHooks(\n\t...hooks: BeforeMutationHook[]\n): BeforeMutationHook {\n\treturn async <T>(\n\t\tctx: MutationHookContext<T>,\n\t): Promise<MutationHookContext<T>> => {\n\t\tlet current: MutationHookContext<T> = ctx;\n\t\tfor (const hook of hooks) {\n\t\t\tconst result = await hook(current);\n\t\t\tif (result !== undefined) {\n\t\t\t\tcurrent = result;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n// ============================================================================\n// AfterMutationHook composition\n// ============================================================================\n\n/**\n * Composes multiple {@link AfterMutationHook}s into one (right-to-left execution).\n * If a hook returns `undefined`, the current rows are passed unchanged.\n */\nexport function composeAfterMutationHooks(\n\t...hooks: AfterMutationHook[]\n): AfterMutationHook {\n\tconst ordered = [...hooks].reverse();\n\treturn async <T>(ctx: MutationHookContext<T>, result: T[]): Promise<T[]> => {\n\t\tlet current: T[] = result;\n\t\tfor (const hook of ordered) {\n\t\t\tconst next = await hook(ctx, current);\n\t\t\tif (next !== undefined) {\n\t\t\t\tcurrent = next;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n/**\n * Pipes multiple {@link AfterMutationHook}s together (left-to-right execution).\n * If a hook returns `undefined`, the current rows are passed unchanged.\n */\nexport function pipeAfterMutationHooks(\n\t...hooks: AfterMutationHook[]\n): AfterMutationHook {\n\treturn async <T>(ctx: MutationHookContext<T>, result: T[]): Promise<T[]> => {\n\t\tlet current: T[] = result;\n\t\tfor (const hook of hooks) {\n\t\t\tconst next = await hook(ctx, current);\n\t\t\tif (next !== undefined) {\n\t\t\t\tcurrent = next;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n// ============================================================================\n// OnErrorHook composition\n// ============================================================================\n\n/**\n * Composes multiple {@link OnErrorHook}s into one (right-to-left execution).\n * Each hook receives the error from the previous; if a hook returns `undefined`,\n * the current error is passed unchanged.\n */\nexport function composeOnErrorHooks(...hooks: OnErrorHook[]): OnErrorHook {\n\tconst ordered = [...hooks].reverse();\n\treturn async (ctx: ErrorHookContext): Promise<undefined | Error> => {\n\t\tlet currentCtx: ErrorHookContext = ctx;\n\t\tfor (const hook of ordered) {\n\t\t\tconst result = await hook(currentCtx);\n\t\t\tif (result !== undefined) {\n\t\t\t\t// Pass the transformed error forward via a new context\n\t\t\t\tcurrentCtx = { ...currentCtx, error: result };\n\t\t\t}\n\t\t}\n\t\treturn currentCtx.error;\n\t};\n}\n\n/**\n * Pipes multiple {@link OnErrorHook}s together (left-to-right execution).\n * Each hook receives the error from the previous; if a hook returns `undefined`,\n * the current error is passed unchanged.\n */\nexport function pipeOnErrorHooks(...hooks: OnErrorHook[]): OnErrorHook {\n\treturn async (ctx: ErrorHookContext): Promise<undefined | Error> => {\n\t\tlet currentCtx: ErrorHookContext = ctx;\n\t\tfor (const hook of hooks) {\n\t\t\tconst result = await hook(currentCtx);\n\t\t\tif (result !== undefined) {\n\t\t\t\tcurrentCtx = { ...currentCtx, error: result };\n\t\t\t}\n\t\t}\n\t\treturn currentCtx.error;\n\t};\n}\n","/**\n * @module hooks\n * Query/Mutation hook system for cross-cutting concerns.\n * Part of E17b: Query Hooks System.\n *\n * Hooks enable intercepting query/mutation execution for logging,\n * auditing, caching, data transformation, and tenant injection.\n *\n * @example\n * ```typescript\n * const hooks = createHookManager()\n * .beforeQuery(ctx => {\n * console.log(`Query on ${ctx.table}`);\n * return ctx;\n * })\n * .afterQuery((ctx, results) => {\n * console.log(`Got ${results.length} rows in ${ctx.duration}ms`);\n * return results;\n * });\n *\n * const orm = createOrm({ schema, adapter, hooks });\n * ```\n */\n\nimport type {\n\tBatchUpdateIntent,\n\tDeleteIntent,\n\tInsertIntent,\n\tQueryIntent,\n\tUpdateIntent,\n\tUpsertIntent,\n} from '../intent-ast.js';\n\n// ============================================================================\n// Hook Context Types\n// ============================================================================\n\n/** Query execution result types for afterQuery generics */\nexport type QueryResultType =\n\t| 'all'\n\t| 'first'\n\t| 'count'\n\t| 'exists'\n\t| 'aggregate';\n\n/**\n * Context passed to query hooks (beforeQuery/afterQuery).\n * Frozen via Object.freeze — hooks must return new objects to modify.\n */\nexport type QueryHookContext = {\n\treadonly table: string;\n\treadonly operation: 'select';\n\treadonly intent: QueryIntent;\n\treadonly schemaName?: string;\n\treadonly inTransaction?: boolean;\n\treadonly correlationId?: string;\n\treadonly resultType: QueryResultType;\n\treadonly isStreaming?: boolean;\n\t// Available in afterQuery only:\n\treadonly sql?: string;\n\t/** Query parameters. May contain PII — redact before logging. */\n\treadonly parameters?: readonly unknown[];\n\treadonly duration?: number;\n};\n\n/** Union of all mutation intent types */\n/** Union of all mutation intent types */\nexport type MutationIntent =\n\t| InsertIntent\n\t| UpdateIntent\n\t| BatchUpdateIntent\n\t| DeleteIntent\n\t| UpsertIntent;\n\n/** Mutation operation types */\nexport type MutationOperation =\n\t| 'insert'\n\t| 'update'\n\t| 'batchUpdate'\n\t| 'delete'\n\t| 'upsert';\n\n/**\n * Context passed to mutation hooks (beforeMutation/afterMutation).\n * Frozen via Object.freeze — hooks must return new objects to modify.\n */\nexport type MutationHookContext<T = unknown> = {\n\treadonly table: string;\n\treadonly operation: MutationOperation;\n\treadonly intent: MutationIntent;\n\treadonly schemaName?: string;\n\treadonly inTransaction?: boolean;\n\treadonly correlationId?: string;\n\treadonly cardinality: 'single' | 'bulk';\n\treadonly data?: T | T[] | Partial<T>;\n\t// Available in afterMutation only:\n\treadonly sql?: string;\n\t/** Query parameters. May contain PII — redact before logging. */\n\treadonly parameters?: readonly unknown[];\n\treadonly duration?: number;\n\treadonly affectedRows?: number;\n};\n\n/** Hook phase identifier */\nexport type HookPhase =\n\t| 'beforeQuery'\n\t| 'afterQuery'\n\t| 'beforeMutation'\n\t| 'afterMutation';\n\n/**\n * Context passed to onError hooks.\n */\nexport type ErrorHookContext = {\n\treadonly table: string;\n\treadonly operation: string;\n\treadonly error: Error;\n\treadonly intent: QueryIntent | MutationIntent;\n\treadonly phase: HookPhase;\n\treadonly sql?: string;\n\treadonly inTransaction?: boolean;\n};\n\n// ============================================================================\n// Hook Signatures\n// ============================================================================\n\n/** Hook invoked before query execution. Can modify intent via return. */\nexport type BeforeQueryHook = (\n\tctx: QueryHookContext,\n) => QueryHookContext | Promise<QueryHookContext> | undefined;\n\n/** Hook invoked after query execution. Can transform results via return. */\nexport type AfterQueryHook = <R>(\n\tctx: QueryHookContext,\n\tresult: R,\n) => R | Promise<R> | undefined;\n\n/** Hook invoked before mutation execution. Can modify context via return. */\nexport type BeforeMutationHook = <T>(\n\tctx: MutationHookContext<T>,\n) => MutationHookContext<T> | Promise<MutationHookContext<T>> | undefined;\n\n/** Hook invoked after mutation execution. Can transform RETURNING results. */\nexport type AfterMutationHook = <T>(\n\tctx: MutationHookContext<T>,\n\tresult: T[],\n) => T[] | Promise<T[]> | undefined;\n\n/** Hook invoked on query/mutation errors. Can transform the error. */\nexport type OnErrorHook = (\n\tctx: ErrorHookContext,\n) => undefined | Error | Promise<undefined | Error>;\n\n/**\n * Error handler for hook failures.\n * Returns 'continue' to skip failed hook, 'abort' to propagate error.\n */\nexport type HookErrorHandler = (\n\terror: Error,\n\thookName: string,\n\tctx: QueryHookContext | MutationHookContext,\n\tphase: string,\n) => 'continue' | 'abort';\n\n// ============================================================================\n// Hook Manager Interface\n// ============================================================================\n\n/** Immutable builder interface for registering hooks */\nexport interface HookManager {\n\tbeforeQuery(hook: BeforeQueryHook): HookManager;\n\tafterQuery(hook: AfterQueryHook): HookManager;\n\tbeforeMutation(hook: BeforeMutationHook): HookManager;\n\tafterMutation(hook: AfterMutationHook): HookManager;\n\tonError(hook: OnErrorHook): HookManager;\n\tfreeze(): HookManager;\n}\n\n// ============================================================================\n// Internal Hook Storage\n// ============================================================================\n\n/** @internal Hook storage — exposed for runner access */\nexport type HookStore = {\n\treadonly beforeQuery: readonly BeforeQueryHook[];\n\treadonly afterQuery: readonly AfterQueryHook[];\n\treadonly beforeMutation: readonly BeforeMutationHook[];\n\treadonly afterMutation: readonly AfterMutationHook[];\n\treadonly onError: readonly OnErrorHook[];\n\treadonly frozen: boolean;\n};\n\n// ============================================================================\n// Hook Manager Implementation\n// ============================================================================\n\nclass HookManagerImpl implements HookManager {\n\tprivate readonly store: HookStore;\n\n\tconstructor(store?: HookStore) {\n\t\tthis.store = store ?? {\n\t\t\tbeforeQuery: [],\n\t\t\tafterQuery: [],\n\t\t\tbeforeMutation: [],\n\t\t\tafterMutation: [],\n\t\t\tonError: [],\n\t\t\tfrozen: false,\n\t\t};\n\t}\n\n\tbeforeQuery(hook: BeforeQueryHook): HookManager {\n\t\tthis.assertNotFrozen();\n\t\treturn new HookManagerImpl({\n\t\t\t...this.store,\n\t\t\tbeforeQuery: [...this.store.beforeQuery, hook],\n\t\t});\n\t}\n\n\tafterQuery(hook: AfterQueryHook): HookManager {\n\t\tthis.assertNotFrozen();\n\t\treturn new HookManagerImpl({\n\t\t\t...this.store,\n\t\t\tafterQuery: [...this.store.afterQuery, hook],\n\t\t});\n\t}\n\n\tbeforeMutation(hook: BeforeMutationHook): HookManager {\n\t\tthis.assertNotFrozen();\n\t\treturn new HookManagerImpl({\n\t\t\t...this.store,\n\t\t\tbeforeMutation: [...this.store.beforeMutation, hook],\n\t\t});\n\t}\n\n\tafterMutation(hook: AfterMutationHook): HookManager {\n\t\tthis.assertNotFrozen();\n\t\treturn new HookManagerImpl({\n\t\t\t...this.store,\n\t\t\tafterMutation: [...this.store.afterMutation, hook],\n\t\t});\n\t}\n\n\tonError(hook: OnErrorHook): HookManager {\n\t\tthis.assertNotFrozen();\n\t\treturn new HookManagerImpl({\n\t\t\t...this.store,\n\t\t\tonError: [...this.store.onError, hook],\n\t\t});\n\t}\n\n\tfreeze(): HookManager {\n\t\tif (this.store.frozen) return this;\n\t\treturn new HookManagerImpl({ ...this.store, frozen: true });\n\t}\n\n\t/** @internal Access hook store for runner */\n\tgetStore(): HookStore {\n\t\treturn this.store;\n\t}\n\n\tprivate assertNotFrozen(): void {\n\t\tif (this.store.frozen) {\n\t\t\tthrow new Error(\n\t\t\t\t'HookManager is frozen — hooks cannot be added after ORM creation. ' +\n\t\t\t\t\t'Register all hooks before passing to createOrm().',\n\t\t\t);\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Hook Runner\n// ============================================================================\n\n/**\n * @internal\n * Extracts the hook store from a HookManager.\n * Used by ORM internals to access hooks for execution.\n */\nexport function getHookStore(manager: HookManager): HookStore {\n\treturn (manager as HookManagerImpl).getStore();\n}\n\n// ============================================================================\n// Re-entrancy Guard (INV-07)\n// ============================================================================\n\n/**\n * @internal\n * Tracks hook stores that are currently executing hooks.\n * Prevents infinite loops when hooks issue queries/mutations.\n */\nconst activeHookStores = new WeakSet<HookStore>();\n\n/**\n * @internal\n * Marks a hook store as actively executing hooks.\n * Returns a cleanup function to call when done.\n */\nexport function enterHookExecution(store: HookStore): () => void {\n\tactiveHookStores.add(store);\n\treturn () => activeHookStores.delete(store);\n}\n\n/**\n * @internal\n * Executes `fn` within a re-entrancy guard.\n * While `fn` runs, `hasHooks(store)` returns false — preventing infinite loops\n * when hooks issue queries/mutations themselves.\n */\nexport async function withReentrancyGuard<R>(\n\tstore: HookStore,\n\tfn: (store: HookStore) => Promise<R>,\n): Promise<R> {\n\tconst exit = enterHookExecution(store);\n\ttry {\n\t\treturn await fn(store);\n\t} finally {\n\t\texit();\n\t}\n}\n\n/**\n * @internal\n * Checks whether a hook manager has any hooks registered\n * AND is not currently in a re-entrant execution.\n * Used for zero-cost optimization: skip hook execution when no hooks exist\n * or when called from within a hook (preventing infinite loops).\n */\nexport function hasHooks(store: HookStore): boolean {\n\t// Re-entrancy guard: if this store is already executing hooks, skip\n\tif (activeHookStores.has(store)) return false;\n\n\treturn (\n\t\tstore.beforeQuery.length > 0 ||\n\t\tstore.afterQuery.length > 0 ||\n\t\tstore.beforeMutation.length > 0 ||\n\t\tstore.afterMutation.length > 0 ||\n\t\tstore.onError.length > 0\n\t);\n}\n\n/**\n * @internal\n * Runs beforeQuery hooks in registration order (FIFO).\n * Returns the (potentially modified) context.\n * Context is frozen before each hook invocation.\n */\nexport async function runBeforeQueryHooks(\n\thooks: readonly BeforeQueryHook[],\n\tctx: QueryHookContext,\n\tonHookError?: HookErrorHandler,\n): Promise<QueryHookContext> {\n\tlet current = ctx;\n\tfor (const hook of hooks) {\n\t\tconst frozen = Object.freeze({ ...current });\n\t\ttry {\n\t\t\tconst result = await hook(frozen);\n\t\t\tif (result !== undefined && result !== null) {\n\t\t\t\tcurrent = result;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (onHookError) {\n\t\t\t\tconst action = onHookError(\n\t\t\t\t\terror as Error,\n\t\t\t\t\thook.name || 'anonymous',\n\t\t\t\t\tfrozen,\n\t\t\t\t\t'beforeQuery',\n\t\t\t\t);\n\t\t\t\tif (action === 'continue') continue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\treturn current;\n}\n\n/**\n * @internal\n * Runs afterQuery hooks in reverse registration order (LIFO — middleware semantics).\n * Returns the (potentially transformed) result.\n */\nexport async function runAfterQueryHooks<R>(\n\thooks: readonly AfterQueryHook[],\n\tctx: QueryHookContext,\n\tresult: R,\n\tonHookError?: HookErrorHandler,\n): Promise<R> {\n\tlet current = result;\n\t// LIFO order: last registered hook runs first\n\tfor (let i = hooks.length - 1; i >= 0; i--) {\n\t\tconst hook = hooks[i];\n\t\tif (!hook) continue;\n\t\tconst frozen = Object.freeze({ ...ctx });\n\t\ttry {\n\t\t\tconst transformed = await hook(frozen, current);\n\t\t\tif (transformed !== undefined && transformed !== null) {\n\t\t\t\tcurrent = transformed;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (onHookError) {\n\t\t\t\tconst action = onHookError(\n\t\t\t\t\terror as Error,\n\t\t\t\t\thook.name || 'anonymous',\n\t\t\t\t\tfrozen,\n\t\t\t\t\t'afterQuery',\n\t\t\t\t);\n\t\t\t\tif (action === 'continue') continue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\treturn current;\n}\n\n/**\n * @internal\n * Runs beforeMutation hooks in registration order (FIFO).\n */\nexport async function runBeforeMutationHooks<T>(\n\thooks: readonly BeforeMutationHook[],\n\tctx: MutationHookContext<T>,\n\tonHookError?: HookErrorHandler,\n): Promise<MutationHookContext<T>> {\n\tlet current = ctx;\n\tfor (const hook of hooks) {\n\t\tconst frozen = Object.freeze({ ...current });\n\t\ttry {\n\t\t\tconst result = await hook(frozen);\n\t\t\tif (result !== undefined && result !== null) {\n\t\t\t\tcurrent = result as MutationHookContext<T>;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (onHookError) {\n\t\t\t\tconst action = onHookError(\n\t\t\t\t\terror as Error,\n\t\t\t\t\thook.name || 'anonymous',\n\t\t\t\t\tfrozen,\n\t\t\t\t\t'beforeMutation',\n\t\t\t\t);\n\t\t\t\tif (action === 'continue') continue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\treturn current;\n}\n\n/**\n * @internal\n * Runs afterMutation hooks in reverse registration order (LIFO).\n */\nexport async function runAfterMutationHooks<T>(\n\thooks: readonly AfterMutationHook[],\n\tctx: MutationHookContext<T>,\n\tresult: T[],\n\tonHookError?: HookErrorHandler,\n): Promise<T[]> {\n\tlet current = result;\n\tfor (let i = hooks.length - 1; i >= 0; i--) {\n\t\tconst hook = hooks[i];\n\t\tif (!hook) continue;\n\t\tconst frozen = Object.freeze({ ...ctx });\n\t\ttry {\n\t\t\tconst transformed = await hook(frozen, current);\n\t\t\tif (transformed !== undefined && transformed !== null) {\n\t\t\t\tcurrent = transformed as T[];\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (onHookError) {\n\t\t\t\tconst action = onHookError(\n\t\t\t\t\terror as Error,\n\t\t\t\t\thook.name || 'anonymous',\n\t\t\t\t\tfrozen,\n\t\t\t\t\t'beforeMutation',\n\t\t\t\t);\n\t\t\t\tif (action === 'continue') continue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\treturn current;\n}\n\n/**\n * @internal\n * Runs onError hooks. Returns transformed error or original.\n */\nexport async function runOnErrorHooks(\n\thooks: readonly OnErrorHook[],\n\tctx: ErrorHookContext,\n): Promise<Error> {\n\tlet currentError = ctx.error;\n\tfor (const hook of hooks) {\n\t\tconst frozen = Object.freeze({ ...ctx, error: currentError });\n\t\ttry {\n\t\t\tconst result = await hook(frozen);\n\t\t\tif (result instanceof Error) {\n\t\t\t\tcurrentError = result;\n\t\t\t}\n\t\t} catch {\n\t\t\t// onError hooks should not throw; if they do, ignore and continue\n\t\t}\n\t}\n\treturn currentError;\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\n/**\n * Creates a new HookManager instance for registering query/mutation hooks.\n *\n * @example\n * ```typescript\n * const hooks = createHookManager()\n * .beforeQuery(ctx => { console.log(ctx.table); return ctx; })\n * .afterQuery((ctx, results) => results);\n * ```\n */\nexport function createHookManager(): HookManager {\n\treturn new HookManagerImpl();\n}\n","/**\n * @module subquery-builder\n * Subquery builder for scalar subquery expressions in WHERE clauses.\n * DX-012 Block 3\n */\n\nimport type {\n\tComparisonOperator,\n\tQueryIntent,\n\tSubqueryRefIntent,\n\tWhereIntent,\n\tWhereSubqueryIntent,\n} from '../intent-ast.js';\nimport type { ExpressionSpec } from './types.js';\n\n// ============================================================================\n// Subquery Builder\n// ============================================================================\n\n/**\n * Fluent builder for scalar subqueries.\n * Produces a SubqueryExpression that can be used with comparison operators.\n *\n * @example\n * // Basic scalar subquery\n * query('products')\n * .where({ price: { $eq: subquery('prices').select('max_price').where({ categoryId: outerRef('categoryId') }) } })\n *\n * // With aggregate\n * query('products')\n * .where({ avgRating: { $gt: subquery('reviews').where({ productId: outerRef('id') }).avg('rating') } })\n */\nexport class SubqueryBuilder {\n\tprivate readonly _from: string;\n\tprivate _select?: string;\n\tprivate _where?: WhereIntent;\n\tprivate _aggregate?: {\n\t\tfn: 'count' | 'sum' | 'avg' | 'min' | 'max';\n\t\tfield: string;\n\t};\n\n\tconstructor(table: string) {\n\t\tthis._from = table;\n\t}\n\n\t/**\n\t * Specify the field to select from the subquery.\n\t * For scalar subqueries, this should be a single field.\n\t */\n\tselect(field: string): SubqueryBuilder {\n\t\tconst clone = this.clone();\n\t\tclone._select = field;\n\t\treturn clone;\n\t}\n\n\t/**\n\t * Add a WHERE condition to the subquery.\n\t * Can include outerRef() to create correlated subqueries.\n\t */\n\twhere(condition: WhereIntent): SubqueryBuilder {\n\t\tconst clone = this.clone();\n\t\tclone._where = condition;\n\t\treturn clone;\n\t}\n\n\t// ========================================================================\n\t// Aggregate Methods\n\t// ========================================================================\n\n\t/**\n\t * COUNT aggregate - count rows in subquery\n\t */\n\tcount(field = '*'): SubqueryExpression {\n\t\tconst clone = this.clone();\n\t\tclone._aggregate = { fn: 'count', field };\n\t\treturn clone.build();\n\t}\n\n\t/**\n\t * SUM aggregate - sum values in subquery\n\t */\n\tsum(field: string): SubqueryExpression {\n\t\tconst clone = this.clone();\n\t\tclone._aggregate = { fn: 'sum', field };\n\t\treturn clone.build();\n\t}\n\n\t/**\n\t * AVG aggregate - average values in subquery\n\t */\n\tavg(field: string): SubqueryExpression {\n\t\tconst clone = this.clone();\n\t\tclone._aggregate = { fn: 'avg', field };\n\t\treturn clone.build();\n\t}\n\n\t/**\n\t * MIN aggregate - minimum value in subquery\n\t */\n\tmin(field: string): SubqueryExpression {\n\t\tconst clone = this.clone();\n\t\tclone._aggregate = { fn: 'min', field };\n\t\treturn clone.build();\n\t}\n\n\t/**\n\t * MAX aggregate - maximum value in subquery\n\t */\n\tmax(field: string): SubqueryExpression {\n\t\tconst clone = this.clone();\n\t\tclone._aggregate = { fn: 'max', field };\n\t\treturn clone.build();\n\t}\n\n\t// ========================================================================\n\t// Build Methods\n\t// ========================================================================\n\n\t/**\n\t * Build the SubqueryExpression for use in WHERE conditions.\n\t * Called automatically by aggregate methods or explicitly when using select().\n\t */\n\tbuild(): SubqueryExpression {\n\t\tif (!this._select && !this._aggregate) {\n\t\t\tthrow new Error(\n\t\t\t\t'Subquery must have either select() or an aggregate function',\n\t\t\t);\n\t\t}\n\n\t\t// Build a full QueryIntent — subqueries are queries with contextual validation\n\t\tconst selectField = this._select ?? this._aggregate?.field ?? '*';\n\n\t\tconst intent: QueryIntent = {\n\t\t\ttype: 'select',\n\t\t\tfrom: this._from,\n\t\t\t// Aggregate overrides plain field select\n\t\t\tselect: this._aggregate\n\t\t\t\t? {\n\t\t\t\t\t\ttype: 'aggregate',\n\t\t\t\t\t\taggregates: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfunction: this._aggregate.fn,\n\t\t\t\t\t\t\t\tfield: this._aggregate.field,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t}\n\t\t\t\t: { type: 'fields', fields: [selectField] },\n\t\t\t...(this._where && { where: this._where }),\n\t\t};\n\n\t\treturn new SubqueryExpression(intent);\n\t}\n\n\t/**\n\t * Get the intent for debugging/inspection.\n\t */\n\tdump(): QueryIntent {\n\t\treturn this.build().toIntent();\n\t}\n\n\t/**\n\t * Wrap this subquery as an ExpressionSpec for use as a SELECT column.\n\t * Shorthand for `.build().asExpr(alias)`.\n\t *\n\t * @param alias - Column alias for the result\n\t * @returns ExpressionSpec suitable for passing to .columns()\n\t *\n\t * @example\n\t * // SELECT id, (SELECT count(*) FROM calls WHERE symbol_id = s.id) AS call_count\n\t * query('symbols').columns([\n\t * 'id',\n\t * subquery('calls').where({ symbolId: outerRef('id') }).count().asExpr('call_count'),\n\t * ])\n\t */\n\tasExpr(alias: string): ExpressionSpec {\n\t\treturn this.build().asExpr(alias);\n\t}\n\n\t/**\n\t * Create a clone of this builder (immutable pattern).\n\t */\n\tprivate clone(): SubqueryBuilder {\n\t\tconst clone = new SubqueryBuilder(this._from);\n\t\tif (this._select !== undefined) clone._select = this._select;\n\t\tif (this._where !== undefined) clone._where = this._where;\n\t\tif (this._aggregate !== undefined) clone._aggregate = this._aggregate;\n\t\treturn clone;\n\t}\n}\n\n// ============================================================================\n// Subquery Expression\n// ============================================================================\n\n/**\n * Result of building a subquery.\n * This can be used as a value in comparison operations.\n */\nexport class SubqueryExpression {\n\treadonly _type = 'subquery' as const;\n\treadonly intent: QueryIntent;\n\n\tconstructor(intent: QueryIntent) {\n\t\tthis.intent = intent;\n\t}\n\n\t/**\n\t * Get the underlying intent.\n\t */\n\ttoIntent(): QueryIntent {\n\t\treturn this.intent;\n\t}\n\n\t/**\n\t * Create a WhereSubqueryIntent for comparison.\n\t * Used internally by object filter syntax.\n\t */\n\ttoWhereIntent(\n\t\tfield: string,\n\t\toperator: ComparisonOperator,\n\t): WhereSubqueryIntent {\n\t\treturn {\n\t\t\tkind: 'subquery',\n\t\t\tfield,\n\t\t\toperator,\n\t\t\tsubquery: this.intent,\n\t\t};\n\t}\n\n\t/**\n\t * Wrap this subquery as an ExpressionSpec for use as a SELECT column.\n\t *\n\t * @param alias - Column alias for the result (required: SELECT expressions need a name)\n\t * @returns ExpressionSpec suitable for passing to .columns()\n\t *\n\t * @example\n\t * // SELECT id, (SELECT count(*) FROM calls WHERE calls.symbol_id = s.id) AS call_count\n\t * // FROM symbols s\n\t * query('symbols').columns([\n\t * 'id',\n\t * subquery('calls').count().asExpr('call_count'),\n\t * ])\n\t */\n\tasExpr(alias: string): ExpressionSpec {\n\t\treturn {\n\t\t\t__expr: true,\n\t\t\tintent: { kind: 'subquery', query: this.intent, as: alias },\n\t\t};\n\t}\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Create a scalar subquery builder.\n *\n * @param table - Table name for the subquery\n * @returns SubqueryBuilder for method chaining\n *\n * @example\n * // Find products where price equals max price in category\n * query('products').where({\n * price: {\n * $eq: subquery('products')\n * .select('price')\n * .where({ categoryId: outerRef('categoryId') })\n * .max('price')\n * }\n * })\n */\nexport function subquery(table: string): SubqueryBuilder {\n\treturn new SubqueryBuilder(table);\n}\n\n/**\n * Create a reference to a parent query column.\n * Used in subquery WHERE conditions to create correlated subqueries.\n *\n * @param column - Column name (e.g., 'id') or qualified name (e.g., 't0.id')\n * @returns SubqueryRefIntent\n *\n * @example\n * // Reference parent 'id' column in subquery\n * subquery('reviews').where({ productId: outerRef('id') })\n */\nexport function outerRef(column: string): SubqueryRefIntent {\n\treturn {\n\t\tkind: 'ref',\n\t\tcolumn,\n\t};\n}\n\n// ============================================================================\n// Type Guard\n// ============================================================================\n\n/**\n * Check if a value is a SubqueryExpression.\n * Used to detect subqueries in object filter processing.\n */\nexport function isSubqueryExpression(\n\tvalue: unknown,\n): value is SubqueryExpression {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'_type' in value &&\n\t\t(value as Record<string, unknown>)._type === 'subquery'\n\t);\n}\n","/**\n * @module object-filter\n * Object filter syntax for ergonomic WHERE clause building.\n *\n * Converts Prisma/Drizzle-like object syntax to WhereIntent:\n * - `{ status: 'active' }` → `eq('status', 'active')`\n * - `{ age: { $gt: 18 } }` → `gt('age', 18)`\n * - `{ status: 'active', role: 'admin' }` → `and(eq('status', 'active'), eq('role', 'admin'))`\n *\n * @example\n * ```typescript\n * import { createOrm } from '@dbsp/core';\n *\n * // Object syntax (new)\n * orm.select('users').where({ status: 'active', age: { $gte: 18 } })\n *\n * // Equivalent to (legacy)\n * orm.select('users').where(and(eq('status', 'active'), gte('age', 18)))\n * ```\n */\n\nimport type {\n\tComparisonOperator,\n\tWhereAndIntent,\n\tWhereComparisonIntent,\n\tWhereInIntent,\n\tWhereIntent,\n\tWhereLikeIntent,\n\tWhereNullIntent,\n\tWhereSubqueryIntent,\n} from '../intent-ast.js';\nimport { InvalidOperationError } from './errors.js';\nimport {\n\tisSubqueryExpression,\n\ttype SubqueryExpression,\n} from './subquery-builder.js';\n\n// ============================================================================\n// Operator Types\n// ============================================================================\n\n/**\n * Comparison operators for object filter syntax.\n * Use `$` prefix to distinguish from field names.\n * Values can be literal values or SubqueryExpression for scalar subqueries.\n */\nexport interface FilterOperators<T = unknown> {\n\t/** Equals (explicit) - value or subquery */\n\treadonly $eq?: T | SubqueryExpression;\n\t/** Not equals - value or subquery */\n\treadonly $neq?: T | SubqueryExpression;\n\t/** Greater than - value or subquery */\n\treadonly $gt?: T | SubqueryExpression;\n\t/** Greater than or equal - value or subquery */\n\treadonly $gte?: T | SubqueryExpression;\n\t/** Less than - value or subquery */\n\treadonly $lt?: T | SubqueryExpression;\n\t/** Less than or equal - value or subquery */\n\treadonly $lte?: T | SubqueryExpression;\n\t/** In array */\n\treadonly $in?: readonly T[];\n\t/** LIKE pattern matching */\n\treadonly $like?: string;\n\t/** Case-insensitive LIKE (ILIKE in PostgreSQL) */\n\treadonly $ilike?: string;\n\t/** IS NOT NULL check */\n\treadonly $notNull?: true;\n}\n\n/**\n * Filter value for a single field.\n * Can be:\n * - Direct value (equality)\n * - null (IS NULL)\n * - Operator object ({ $gt: 18 })\n */\nexport type FilterValue<T = unknown> = T | null | FilterOperators<T>;\n\n/**\n * Object filter type for WHERE clause.\n * Maps field names to filter values.\n *\n * @typeParam T - The row type for type-safe field names.\n *\n * @example\n * ```typescript\n * // Simple equality\n * const filter: WhereFilter<User> = { status: 'active' };\n *\n * // With operators\n * const filter: WhereFilter<User> = {\n * status: 'active',\n * age: { $gte: 18 },\n * email: { $like: '%@example.com' },\n * };\n * ```\n */\nexport type WhereFilter<T = Record<string, unknown>> = {\n\treadonly [K in keyof T]?: FilterValue<T[K]>;\n};\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Check if a value is a WhereIntent (not an object filter).\n */\nexport function isWhereIntent(value: unknown): value is WhereIntent {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'kind' in value &&\n\t\ttypeof (value as Record<string, unknown>).kind === 'string'\n\t);\n}\n\n/**\n * Check if a value is an operator object (has $-prefixed keys).\n */\nfunction isOperatorObject(value: unknown): value is FilterOperators {\n\tif (typeof value !== 'object' || value === null) {\n\t\treturn false;\n\t}\n\tconst keys = Object.keys(value);\n\treturn keys.length > 0 && keys.every((k) => k.startsWith('$'));\n}\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\n/**\n * Convert a single field-value pair to WhereIntent.\n */\nfunction convertFieldValue(field: string, value: FilterValue): WhereIntent {\n\t// Handle null → isNull\n\tif (value === null) {\n\t\treturn {\n\t\t\tkind: 'null',\n\t\t\tfield,\n\t\t\toperator: 'isNull',\n\t\t} satisfies WhereNullIntent;\n\t}\n\n\t// Handle operator object\n\tif (isOperatorObject(value)) {\n\t\treturn convertOperatorObject(field, value);\n\t}\n\n\t// Handle direct value → equality\n\treturn {\n\t\tkind: 'comparison',\n\t\tfield,\n\t\toperator: 'eq',\n\t\tvalue,\n\t} satisfies WhereComparisonIntent;\n}\n\n/**\n * Create a comparison intent (value or subquery).\n */\nfunction createComparisonIntent(\n\tfield: string,\n\toperator: ComparisonOperator,\n\tvalue: unknown,\n): WhereIntent {\n\tif (isSubqueryExpression(value)) {\n\t\treturn value.toWhereIntent(field, operator) satisfies WhereSubqueryIntent;\n\t}\n\treturn {\n\t\tkind: 'comparison',\n\t\tfield,\n\t\toperator,\n\t\tvalue,\n\t} satisfies WhereComparisonIntent;\n}\n\n/**\n * Convert an operator object to WhereIntent.\n */\nfunction convertOperatorObject(\n\tfield: string,\n\tops: FilterOperators,\n): WhereIntent {\n\tconst conditions: WhereIntent[] = [];\n\n\t// $eq\n\tif (Object.hasOwn(ops, '$eq') && ops.$eq !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'eq', ops.$eq));\n\t}\n\n\t// $neq\n\tif (Object.hasOwn(ops, '$neq') && ops.$neq !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'neq', ops.$neq));\n\t}\n\n\t// $gt\n\tif (Object.hasOwn(ops, '$gt') && ops.$gt !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'gt', ops.$gt));\n\t}\n\n\t// $gte\n\tif (Object.hasOwn(ops, '$gte') && ops.$gte !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'gte', ops.$gte));\n\t}\n\n\t// $lt\n\tif (Object.hasOwn(ops, '$lt') && ops.$lt !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'lt', ops.$lt));\n\t}\n\n\t// $lte\n\tif (Object.hasOwn(ops, '$lte') && ops.$lte !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'lte', ops.$lte));\n\t}\n\n\t// $in\n\tif (Object.hasOwn(ops, '$in') && ops.$in !== undefined) {\n\t\tconditions.push({\n\t\t\tkind: 'in',\n\t\t\tfield,\n\t\t\tvalues: ops.$in,\n\t\t} satisfies WhereInIntent);\n\t}\n\n\t// $like\n\tif (Object.hasOwn(ops, '$like') && ops.$like !== undefined) {\n\t\tconditions.push({\n\t\t\tkind: 'like',\n\t\t\tfield,\n\t\t\tpattern: ops.$like,\n\t\t} satisfies WhereLikeIntent);\n\t}\n\n\t// $ilike (case-insensitive)\n\tif (Object.hasOwn(ops, '$ilike') && ops.$ilike !== undefined) {\n\t\tconditions.push({\n\t\t\tkind: 'like',\n\t\t\tfield,\n\t\t\tpattern: ops.$ilike,\n\t\t\tcaseInsensitive: true,\n\t\t} satisfies WhereLikeIntent);\n\t}\n\n\t// $notNull\n\tif (Object.hasOwn(ops, '$notNull') && ops.$notNull === true) {\n\t\tconditions.push({\n\t\t\tkind: 'null',\n\t\t\tfield,\n\t\t\toperator: 'isNotNull',\n\t\t} satisfies WhereNullIntent);\n\t}\n\n\t// Return single condition or AND\n\tif (conditions.length === 0) {\n\t\tthrow new Error(\n\t\t\t`Invalid filter: operator object for field \"${field}\" has no recognized operators`,\n\t\t);\n\t}\n\n\tif (conditions.length === 1) {\n\t\t// Type assertion safe: length check guarantees element exists\n\t\treturn conditions[0] as WhereIntent;\n\t}\n\n\treturn { kind: 'and', conditions } satisfies WhereAndIntent;\n}\n\n// Keys that must never appear in a filter object — they target prototype slots\n// and can poison object properties on older engines. Defined at module scope\n// so the Set is allocated once, not per call.\nconst FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/**\n * Convert an object filter to WhereIntent.\n *\n * @param filter - Object filter with field-value pairs\n * @returns WhereIntent for use in QueryBuilder.where()\n *\n * @example\n * ```typescript\n * // Single field\n * objectToWhereIntent({ status: 'active' })\n * // → { kind: 'comparison', field: 'status', operator: 'eq', value: 'active' }\n *\n * // Multiple fields (AND)\n * objectToWhereIntent({ status: 'active', role: 'admin' })\n * // → { kind: 'and', conditions: [...] }\n *\n * // With operators\n * objectToWhereIntent({ age: { $gte: 18, $lt: 65 } })\n * // → { kind: 'and', conditions: [gte, lt] }\n * ```\n */\nexport function objectToWhereIntent(\n\tfilter: WhereFilter<Record<string, unknown>>,\n): WhereIntent {\n\t// FIND-005: Reject prototype-poisoning keys before any processing.\n\t// Object.keys() already returns only own enumerable properties — the\n\t// hasOwn check below was redundant and has been removed.\n\tfor (const key of Object.keys(filter)) {\n\t\tif (FORBIDDEN_KEYS.has(key)) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'where',\n\t\t\t\t`Filter key not allowed: ${key}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst entries = Object.entries(filter);\n\n\tif (entries.length === 0) {\n\t\tthrow new Error('Invalid filter: empty object');\n\t}\n\n\tconst conditions: WhereIntent[] = entries.map(([field, value]) =>\n\t\tconvertFieldValue(field, value as FilterValue),\n\t);\n\n\t// Single condition → return directly\n\tif (conditions.length === 1) {\n\t\t// Type assertion safe: length check guarantees element exists\n\t\treturn conditions[0] as WhereIntent;\n\t}\n\n\t// Multiple conditions → AND\n\treturn { kind: 'and', conditions } satisfies WhereAndIntent;\n}\n","/**\n * @fileoverview Core DX layer type definitions.\n *\n * Contains shared types used across the query builder, ORM instance,\n * and other DX components: column specs, ordering, includes, hierarchy, etc.\n *\n * Split files are re-exported for backward compatibility:\n * - pagination-types.ts: Pagination and streaming types\n * - query-builder-types.ts: QueryBuilder interface\n * - orm-instance-types.ts: OrmInstance and OrmOptions\n *\n * @module types\n * @since DX-001\n */\n\nimport type {\n\tExpressionIntent,\n\tSelectIntent,\n\tWhereIntent,\n} from '../intent-ast.js';\n\n// ============================================================================\n// Re-exports from split files (backward compatibility)\n// ============================================================================\n\nexport type {\n\tOrmInstance,\n\tOrmInstanceInternal,\n\tOrmOptions,\n\tOrmOptionsWithAdapter,\n\tOrmOptionsWithModel,\n\tOrmOptionsWithSchema,\n\tSelectExpressionResult,\n} from './orm-instance-types.js';\nexport type {\n\tCursorPaginatedResult,\n\tCursorPaginateOptions,\n\tPaginatedResult,\n\tPaginateOptions,\n\tStreamOptions,\n} from './pagination-types.js';\nexport type { DumpMetaInput, QueryBuilder } from './query-builder-types.js';\n\n// ============================================================================\n// Expression & Column Types\n// ============================================================================\n\n/**\n * A wrapper around an ExpressionIntent that marks it for use in columns().\n * The __expr marker allows runtime detection of expression vs string columns.\n *\n * Create these using helper functions like coalesce() or raw().\n */\nexport interface ExpressionSpec {\n\treadonly __expr: true;\n\treadonly intent: ExpressionIntent;\n}\n\n/**\n * An ExpressionSpec that carries its alias as a phantom type parameter.\n * This allows .columns() to extend the result type with the aliased property.\n *\n * Created by relationColumn(relation, column, alias) when the alias is a\n * string literal — TypeScript captures the exact string type, enabling\n * .columns() to extend TResult with { [alias]: TValue }.\n *\n * @typeParam TAlias - The string literal type of the alias\n * @typeParam TValue - The value type (defaults to unknown)\n */\nexport interface AliasedExprColumn<TAlias extends string, TValue = unknown>\n\textends ExpressionSpec {\n\t/** @internal phantom brand — never set at runtime */\n\treadonly __alias: TAlias;\n\t/** @internal phantom brand — never set at runtime */\n\treadonly __value: TValue;\n}\n\n/**\n * A column specification - either a field name or an expression.\n *\n * @example\n * ```typescript\n * // Simple field\n * 'id'\n *\n * // Expression (via coalesce helper)\n * coalesce(['name_fr', 'name_en'], 'name')\n * ```\n */\nexport type ColumnSpec = string | ExpressionSpec;\n\n/**\n * Type guard to check if a ColumnSpec is an ExpressionSpec.\n */\nexport function isExpressionSpec(spec: ColumnSpec): spec is ExpressionSpec {\n\treturn (\n\t\ttypeof spec === 'object' &&\n\t\tspec !== null &&\n\t\t'__expr' in spec &&\n\t\tspec.__expr === true\n\t);\n}\n\n// ============================================================================\n// Aggregate Types\n// ============================================================================\n\n/**\n * Options for aggregate functions.\n */\nexport interface AggregateOptions {\n\t/**\n\t * Field to aggregate (required for SUM, AVG, MIN, MAX; optional for COUNT).\n\t */\n\treadonly field?: string;\n\t/**\n\t * Alias for the result column.\n\t */\n\treadonly as?: string;\n}\n\n// ============================================================================\n// Relation Hints\n// ============================================================================\n\n/**\n * Mapping of target table to preferred relation name.\n * Used to resolve ambiguous relations automatically.\n *\n * @example\n * ```typescript\n * const hints: RelationHints = {\n * posts: 'authoredPosts', // When including 'posts', use 'authoredPosts' relation\n * };\n * ```\n */\nexport type RelationHints = Readonly<Record<string, string>>;\n\n// ============================================================================\n// OrderBy Shorthand Types (DX-024)\n// ============================================================================\n\n/**\n * Sort direction for orderBy (re-exported from @dbsp/types).\n */\nimport type { SortDirection } from '@dbsp/types';\n\nexport type { SortDirection } from '@dbsp/types';\n\n/**\n * Where to place NULL values in sort order.\n */\nexport type NullsPosition = 'first' | 'last';\n\n/**\n * Object form for orderBy - map of field to direction.\n *\n * @example\n * ```typescript\n * { created_at: 'desc', name: 'asc' }\n * ```\n */\nexport type OrderByRecord = Readonly<Record<string, SortDirection>>;\n\n/**\n * Advanced orderBy specification with nulls handling.\n *\n * @example\n * ```typescript\n * { column: 'created_at', direction: 'desc', nulls: 'last' }\n * ```\n */\nexport interface OrderBySpec {\n\treadonly column: string;\n\treadonly direction?: SortDirection;\n\treadonly nulls?: NullsPosition;\n}\n\n/**\n * All valid orderBy input types.\n */\nexport type OrderByInput =\n\t| string // Simple: 'field'\n\t| OrderByRecord // Object: { field: 'desc' }\n\t| readonly OrderBySpec[]; // Array: [{ column, direction, nulls }]\n\n// ============================================================================\n// Include Types\n// ============================================================================\n\n/**\n * Options for the include() method on QueryBuilder.\n * Maps to IncludeIntent fields with developer-friendly naming.\n */\nexport interface IncludeOptions {\n\t/**\n\t * Explicit relation name for disambiguation.\n\t * Use when multiple relations exist between same tables.\n\t *\n\t * @example\n\t * ```typescript\n\t * // User has authoredPosts and reviewedPosts relations to Post\n\t * query('users').include('posts', { via: 'authoredPosts' })\n\t * ```\n\t */\n\treadonly via?: string;\n\n\t/**\n\t * Filter conditions on related records.\n\t */\n\treadonly where?: WhereIntent;\n\n\t/**\n\t * What columns to select from related records.\n\t */\n\treadonly select?: SelectIntent;\n\n\t/**\n\t * Nested includes for deep loading.\n\t */\n\treadonly include?: readonly NestedInclude[];\n\n\t/**\n\t * Join type for the include when using the 'join' strategy.\n\t * - 'left' (default): LEFT JOIN — all root rows returned, NULL for unmatched relations\n\t * - 'inner': INNER JOIN — only root rows WITH a matching related record are returned\n\t *\n\t * Forces the 'join' include strategy (overrides auto-selection).\n\t *\n\t * @example\n\t * include('file', { join: 'inner' })\n\t * // → INNER JOIN files ON files.id = symbols.file_id\n\t */\n\treadonly join?: 'inner' | 'left';\n}\n\n/**\n * Options for recursive include traversal on self-referential relations.\n *\n * @example\n * ```typescript\n * // Traverse ancestors (nested format)\n * query('categories').where(eq('id', 5)).include('parent', {\n * recursive: true,\n * direction: 'ancestors'\n * })\n *\n * // Traverse descendants (flat format with depth)\n * query('categories').where(eq('id', 1)).include('children', {\n * recursive: true,\n * direction: 'descendants',\n * flat: true,\n * maxDepth: 10\n * })\n * ```\n */\nexport interface RecursiveIncludeOptions extends IncludeOptions {\n\t/**\n\t * Enable recursive CTE traversal.\n\t * MUST be `true` when using recursive options.\n\t */\n\treadonly recursive: true;\n\n\t/**\n\t * Direction of traversal.\n\t * - 'ancestors': Traverse up the hierarchy (parent → grandparent → ...)\n\t * - 'descendants': Traverse down the hierarchy (children → grandchildren → ...)\n\t *\n\t * REQUIRED when `recursive: true`.\n\t */\n\treadonly direction: 'ancestors' | 'descendants';\n\n\t/**\n\t * Output format.\n\t * - false (default): Nested object structure (parent: { parent: { ... } })\n\t * - true: Flat array with depth field ([{ id: 2, depth: 1 }, { id: 1, depth: 2 }])\n\t *\n\t * When flat=true, property is renamed: parent → ancestors, children → descendants\n\t */\n\treadonly flat?: boolean;\n\n\t/**\n\t * Exclude the source node from results.\n\t * @default false\n\t */\n\treadonly omitSelf?: boolean;\n\n\t/**\n\t * Maximum traversal depth.\n\t * @default 100 (safety limit)\n\t */\n\treadonly maxDepth?: number;\n\n\t/**\n\t * Include depth column in results.\n\t * Automatically true when flat=true.\n\t */\n\treadonly includeDepth?: boolean;\n}\n\n/**\n * Union type for include options: regular or recursive.\n */\nexport type IncludeOptionsWithRecursive =\n\t| IncludeOptions\n\t| RecursiveIncludeOptions;\n\n/**\n * Include with relation name for nested includes.\n * Used when building nested include hierarchies.\n */\nexport interface NestedInclude extends IncludeOptions {\n\t/**\n\t * The relation name or target table for this nested include.\n\t */\n\treadonly relation: string;\n}\n\n// ============================================================================\n// Hierarchy Types (DX-022)\n// ============================================================================\n\n/**\n * Options for hierarchy traversal shortcuts (ancestors, descendants, subtree).\n */\nexport interface HierarchyOptions {\n\t/**\n\t * The column that references the parent node (for adjacency list pattern).\n\t * @example 'parentCategoryId', 'parentId', 'managerId'\n\t */\n\treadonly parentId: string;\n\n\t/**\n\t * The column that identifies a node (default: 'id').\n\t */\n\treadonly nodeId?: string;\n\n\t/**\n\t * Optional CTE name (default: auto-generated based on table name).\n\t */\n\treadonly cteName?: string;\n}\n\n/**\n * Options for listAncestors/listDescendants methods (DX-022).\n * These methods execute immediately and return flat arrays.\n */\nexport interface ListHierarchyOptions {\n\t/**\n\t * The column that references the parent node (for adjacency list pattern).\n\t * This is used to auto-detect the self-referential relation.\n\t * @example 'parentCategoryId', 'parentId', 'managerId'\n\t */\n\treadonly parentId: string;\n\n\t/**\n\t * The column that identifies a node (default: 'id').\n\t */\n\treadonly nodeId?: string;\n\n\t/**\n\t * Maximum depth to traverse (default: 100).\n\t */\n\treadonly maxDepth?: number;\n}\n","/**\n * IntentBuilder - Builds QueryIntent AST from builder state.\n *\n * DX-103: Extracted from QueryBuilderImpl to separate intent construction\n * from execution, hydration, and other concerns.\n *\n * @module intent-builder\n */\n\nimport type { Mutable } from '@dbsp/types/internal';\nimport type {\n\tAggregateIntent,\n\tColumnExpressionIntent,\n\tExpressionIntent,\n\tIncludeIntent,\n\tIncludeRecursiveOptions,\n\tOrderByIntent,\n\tQueryIntent,\n\tSelectAggregateIntent,\n\tSelectIntent,\n\tWhereIntent,\n} from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\n\nimport { InvalidOperationError } from './errors.js';\nimport { and } from './filters.js';\nimport {\n\tisWhereIntent,\n\tobjectToWhereIntent,\n\ttype WhereFilter,\n} from './object-filter.js';\nimport {\n\ttype AggregateOptions,\n\ttype ColumnSpec,\n\ttype ExpressionSpec,\n\ttype IncludeOptionsWithRecursive,\n\tisExpressionSpec,\n\ttype NestedInclude,\n\ttype OrderByRecord,\n\ttype OrderBySpec,\n\ttype RecursiveIncludeOptions,\n\ttype RelationHints,\n\ttype SortDirection,\n} from './types.js';\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Check if options indicate a recursive include.\n */\nexport function isRecursiveIncludeOptions(\n\toptions?: IncludeOptionsWithRecursive,\n): options is RecursiveIncludeOptions {\n\treturn (\n\t\toptions !== undefined &&\n\t\t'recursive' in options &&\n\t\toptions.recursive === true\n\t);\n}\n\n/**\n * Convert IncludeOptions to IncludeIntent.\n * Handles exactOptionalPropertyTypes by only including defined properties.\n */\nexport function includeOptionsToIntent(\n\trelation: string,\n\toptions?: IncludeOptionsWithRecursive,\n): IncludeIntent {\n\tif (!options) {\n\t\treturn { relation };\n\t}\n\n\tconst intent: Mutable<IncludeIntent> = { relation };\n\n\tif (options.via !== undefined) {\n\t\tintent.via = options.via;\n\t}\n\tif (options.where !== undefined) {\n\t\tintent.where = options.where;\n\t}\n\tif (options.select !== undefined) {\n\t\tintent.select = options.select;\n\t}\n\tif (options.include !== undefined && options.include.length > 0) {\n\t\tintent.include = options.include.map((nested) =>\n\t\t\tnestedIncludeToIntent(nested),\n\t\t);\n\t}\n\n\tif (options.join !== undefined) {\n\t\tintent.join = options.join;\n\t}\n\n\t// Handle recursive options (DX-017)\n\tif (isRecursiveIncludeOptions(options)) {\n\t\tconst recursiveOpts: Mutable<IncludeRecursiveOptions> = {};\n\t\t// Only set maxDepth if defined\n\t\tif (options.maxDepth !== undefined) {\n\t\t\trecursiveOpts.maxDepth = options.maxDepth;\n\t\t}\n\t\t// Convert includeDepth to track.depth\n\t\tif (options.includeDepth) {\n\t\t\trecursiveOpts.track = { depth: true };\n\t\t}\n\t\tintent.recursive = recursiveOpts;\n\t}\n\n\treturn intent as IncludeIntent;\n}\n\n/**\n * Convert NestedInclude to IncludeIntent.\n */\nexport function nestedIncludeToIntent(nested: NestedInclude): IncludeIntent {\n\tconst intent: Mutable<IncludeIntent> = { relation: nested.relation };\n\n\tif (nested.via !== undefined) {\n\t\tintent.via = nested.via;\n\t}\n\tif (nested.where !== undefined) {\n\t\tintent.where = nested.where;\n\t}\n\tif (nested.select !== undefined) {\n\t\tintent.select = nested.select;\n\t}\n\tif (nested.include !== undefined && nested.include.length > 0) {\n\t\tintent.include = nested.include.map((n) => nestedIncludeToIntent(n));\n\t}\n\n\treturn intent as IncludeIntent;\n}\n\n/**\n * Parse dot notation include into nested IncludeIntent.\n *\n * @example\n * 'posts.comments.author' becomes:\n * { relation: 'posts', include: [{ relation: 'comments', include: [{ relation: 'author' }] }] }\n */\nexport function parseDotNotationInclude(\n\tpath: string,\n\toptions?: IncludeOptionsWithRecursive,\n): IncludeIntent {\n\tconst parts = path.split('.');\n\tif (parts.length === 0) {\n\t\tthrow new Error('Invalid include path');\n\t}\n\n\t// Build from the end (deepest level) to the beginning\n\t// Options apply to the deepest (last) relation\n\tconst lastPart = parts[parts.length - 1];\n\tif (!lastPart) {\n\t\tthrow new Error('Invalid include path: empty segment');\n\t}\n\tlet current: IncludeIntent = includeOptionsToIntent(lastPart, options);\n\n\t// Work backwards through the path, wrapping each level.\n\t// Propagate the `join` option to intermediate wrappers so the planner\n\t// picks the join strategy for ALL hops, not just the leaf.\n\t// Without this, `.include('a.b', {join:'inner'})` produces an outer 'a'\n\t// with no join → json_agg strategy → 'a' table not in outer FROM →\n\t// the leaf 'b' JOIN ON clause references a table missing from outer FROM.\n\tfor (let i = parts.length - 2; i >= 0; i--) {\n\t\tconst part = parts[i];\n\t\tif (!part) continue;\n\t\tcurrent =\n\t\t\toptions?.join !== undefined\n\t\t\t\t? { relation: part, join: options.join, include: [current] }\n\t\t\t\t: { relation: part, include: [current] };\n\t}\n\n\treturn current;\n}\n\n/**\n * Validate recursive include options.\n * Throws InvalidOperationError if:\n * - Relation is not self-referential (source !== target)\n * - Direction is missing\n * - Direction conflicts with relation cardinality\n */\nexport function validateRecursiveInclude(\n\tmodel: ModelIR,\n\tsourceTable: string,\n\trelationName: string,\n\toptions: RecursiveIncludeOptions,\n): void {\n\t// Get the relation from the model\n\tconst qualifiedName = `${sourceTable}.${relationName}`;\n\tconst relation = model.getRelation(qualifiedName);\n\n\tif (!relation) {\n\t\t// Let the planner handle the \"relation not found\" error\n\t\treturn;\n\t}\n\n\t// Check if direction is provided (INV-2)\n\tif (!options.direction) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'recursive include',\n\t\t\t`'direction' is required when using recursive: true. ` +\n\t\t\t\t`Use 'ancestors' for parent traversal or 'descendants' for children traversal.`,\n\t\t);\n\t}\n\n\t// Check if relation is self-referential (INV-1, PRE-1)\n\tif (relation.source !== relation.target) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'recursive include',\n\t\t\t`Recursive include requires a self-referential relation. ` +\n\t\t\t\t`Relation '${relationName}' connects '${relation.source}' to '${relation.target}', ` +\n\t\t\t\t`but both must be the same table for recursive traversal.`,\n\t\t);\n\t}\n\n\t// Check direction vs relation type (PRE-2, PRE-3, ERR-3)\n\t// ancestors requires belongsTo/hasOne (to-one), descendants requires hasMany (to-many)\n\tconst { direction } = options;\n\tconst relType = relation.type;\n\n\tif (direction === 'ancestors') {\n\t\t// ancestors traversal: follow the \"parent\" direction (N:1 or 1:1)\n\t\t// The relation should be belongsTo or hasOne (e.g., category -> parent category)\n\t\tif (relType === 'hasMany' || relType === 'belongsToMany') {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'recursive include',\n\t\t\t\t`Direction 'ancestors' requires a to-one relation (belongsTo or hasOne). ` +\n\t\t\t\t\t`Relation '${relationName}' has type '${relType}'. ` +\n\t\t\t\t\t`Use 'descendants' for hasMany/belongsToMany relations.`,\n\t\t\t);\n\t\t}\n\t} else if (direction === 'descendants') {\n\t\t// descendants traversal: follow the \"children\" direction (1:N)\n\t\t// The relation should be hasMany (e.g., category -> child categories)\n\t\tif (relType === 'belongsTo' || relType === 'hasOne') {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'recursive include',\n\t\t\t\t`Direction 'descendants' requires a to-many relation (hasMany). ` +\n\t\t\t\t\t`Relation '${relationName}' has type '${relType}'. ` +\n\t\t\t\t\t`Use 'ancestors' for belongsTo/hasOne relations.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n// ============================================================================\n// RecursiveIncludeConfig\n// ============================================================================\n\n/**\n * Configuration for a recursive include.\n * Stores the relation name and recursive options for later processing.\n */\nexport interface RecursiveIncludeConfig {\n\treadonly relation: string;\n\treadonly options: RecursiveIncludeOptions;\n}\n\n// ============================================================================\n// IntentBuilderState\n// ============================================================================\n\n/**\n * Internal state for intent building.\n * Encapsulates all the mutable state that gets accumulated via builder methods.\n * Note: Optional properties explicitly allow undefined for exactOptionalPropertyTypes compliance.\n */\nexport interface IntentBuilderState {\n\treadonly from: string;\n\tselectIntent?: SelectIntent | undefined;\n\twhereIntents: WhereIntent[];\n\thavingIntents: WhereIntent[];\n\tincludes: IncludeIntent[];\n\trecursiveIncludes: RecursiveIncludeConfig[];\n\taggregates: AggregateIntent[];\n\tgroupByFields: string[];\n\torderByIntents: OrderByIntent[];\n\tlimitValue?: number | undefined;\n\toffsetValue?: number | undefined;\n\tisDistinct?: boolean | undefined;\n}\n\n// ============================================================================\n// IntentBuilder\n// ============================================================================\n\n/**\n * Builds QueryIntent AST from accumulated state.\n *\n * This class is responsible for:\n * - Accumulating filter, select, include, and ordering state\n * - Converting builder method calls to intent AST nodes\n * - Building the final QueryIntent for planning\n *\n * @typeParam TResult - The expected result type (for type inference)\n */\nexport class IntentBuilder<TResult = unknown> {\n\tprivate readonly model: ModelIR;\n\tprivate readonly relationHints: RelationHints;\n\treadonly state: IntentBuilderState;\n\n\tconstructor(\n\t\tmodel: ModelIR,\n\t\tfrom: string,\n\t\trelationHints: RelationHints = {},\n\t\tinitialState?: Partial<IntentBuilderState>,\n\t) {\n\t\tthis.model = model;\n\t\tthis.relationHints = relationHints;\n\t\tthis.state = {\n\t\t\tfrom,\n\t\t\twhereIntents: initialState?.whereIntents\n\t\t\t\t? [...initialState.whereIntents]\n\t\t\t\t: [],\n\t\t\thavingIntents: initialState?.havingIntents\n\t\t\t\t? [...initialState.havingIntents]\n\t\t\t\t: [],\n\t\t\tincludes: initialState?.includes ? [...initialState.includes] : [],\n\t\t\trecursiveIncludes: initialState?.recursiveIncludes\n\t\t\t\t? [...initialState.recursiveIncludes]\n\t\t\t\t: [],\n\t\t\taggregates: initialState?.aggregates ? [...initialState.aggregates] : [],\n\t\t\tgroupByFields: initialState?.groupByFields\n\t\t\t\t? [...initialState.groupByFields]\n\t\t\t\t: [],\n\t\t\torderByIntents: initialState?.orderByIntents\n\t\t\t\t? [...initialState.orderByIntents]\n\t\t\t\t: [],\n\t\t\tselectIntent: initialState?.selectIntent,\n\t\t\tlimitValue: initialState?.limitValue,\n\t\t\toffsetValue: initialState?.offsetValue,\n\t\t\tisDistinct: initialState?.isDistinct,\n\t\t};\n\t}\n\n\t/**\n\t * Add an include to the builder.\n\t */\n\taddInclude(relation: string, options?: IncludeOptionsWithRecursive): void {\n\t\t// Validate recursive includes (self-referential relations)\n\t\tif (isRecursiveIncludeOptions(options)) {\n\t\t\tvalidateRecursiveInclude(this.model, this.state.from, relation, options);\n\t\t\t// Note: recursive options are now converted to IncludeIntent.recursive\n\t\t\t// by includeOptionsToIntent, no longer stored separately\n\t\t}\n\n\t\t// Support dot notation for nested includes: 'posts.comments.author'\n\t\tif (relation.includes('.')) {\n\t\t\tthis.state.includes.push(parseDotNotationInclude(relation, options));\n\t\t} else {\n\t\t\tthis.state.includes.push(includeOptionsToIntent(relation, options));\n\t\t}\n\t}\n\n\t/**\n\t * Set column selection.\n\t */\n\tsetColumns(columns: readonly ColumnSpec[]): void {\n\t\t// Build columns array (direct ExpressionIntent format - NQL compatible)\n\t\tconst expressionColumns: ExpressionIntent[] = [];\n\t\tlet hasExpressions = false;\n\n\t\tfor (const col of columns) {\n\t\t\tif (isExpressionSpec(col)) {\n\t\t\t\thasExpressions = true;\n\t\t\t\texpressionColumns.push((col as ExpressionSpec).intent);\n\t\t\t} else {\n\t\t\t\t// Simple field → ColumnExpressionIntent (kind: 'column')\n\t\t\t\texpressionColumns.push({ kind: 'column', column: col as string });\n\t\t\t}\n\t\t}\n\n\t\t// Use SelectWithExpressionsIntent if we have any expressions\n\t\tif (hasExpressions) {\n\t\t\tthis.state.selectIntent = {\n\t\t\t\ttype: 'expressions',\n\t\t\t\tcolumns: expressionColumns,\n\t\t\t};\n\t\t} else {\n\t\t\t// Simple fields only - extract field names\n\t\t\tconst fields = expressionColumns.map(\n\t\t\t\t(c) => (c as ColumnExpressionIntent).column,\n\t\t\t);\n\t\t\tthis.state.selectIntent = { type: 'fields', fields };\n\t\t}\n\t}\n\n\t/**\n\t * Add a WHERE condition.\n\t */\n\taddWhere(condition: WhereIntent | WhereFilter<TResult>): void {\n\t\t// Convert object filter to WhereIntent if needed\n\t\tconst intent = isWhereIntent(condition)\n\t\t\t? condition\n\t\t\t: objectToWhereIntent(condition as WhereFilter<Record<string, unknown>>);\n\t\tthis.state.whereIntents.push(intent);\n\t}\n\n\t/**\n\t * Add an aggregate function.\n\t * DX-034: Now supports distinct flag for COUNT(DISTINCT field), etc.\n\t */\n\taddAggregate(\n\t\tfunc: 'count' | 'sum' | 'avg' | 'min' | 'max',\n\t\tfield?: string,\n\t\toptions?: AggregateOptions & { distinct?: boolean },\n\t): void {\n\t\tconst agg: Mutable<AggregateIntent> = { function: func };\n\t\tif (field !== undefined) {\n\t\t\tagg.field = field;\n\t\t} else if (options?.field !== undefined) {\n\t\t\tagg.field = options.field;\n\t\t}\n\t\tif (options?.as !== undefined) {\n\t\t\tagg.as = options.as;\n\t\t}\n\t\t// DX-034: Support distinct aggregates\n\t\tif (options?.distinct) {\n\t\t\tagg.distinct = true;\n\t\t}\n\t\tthis.state.aggregates.push(agg as AggregateIntent);\n\t}\n\n\t/**\n\t * Add GROUP BY fields.\n\t */\n\taddGroupBy(fields: readonly string[]): void {\n\t\tthis.state.groupByFields.push(...fields);\n\t}\n\n\t/**\n\t * Add a HAVING condition for filtering on aggregates.\n\t * DX-034: HAVING is applied after GROUP BY.\n\t */\n\taddHaving(condition: WhereIntent): void {\n\t\tthis.state.havingIntents.push(condition);\n\t}\n\n\t/**\n\t * Set SELECT DISTINCT mode.\n\t * DX-034: Deduplicates result rows.\n\t */\n\tsetDistinct(value: boolean = true): void {\n\t\tthis.state.isDistinct = value;\n\t}\n\n\t/**\n\t * Add ORDER BY clauses.\n\t */\n\taddOrderBy(\n\t\tfieldOrRecordOrSpecs: string | OrderByRecord | readonly OrderBySpec[],\n\t\tdirection?: SortDirection,\n\t): void {\n\t\t// String form: orderBy('field') or orderBy('field', 'desc')\n\t\tif (typeof fieldOrRecordOrSpecs === 'string') {\n\t\t\tthis.state.orderByIntents.push({\n\t\t\t\tfield: fieldOrRecordOrSpecs,\n\t\t\t\tdirection: direction ?? 'asc',\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Array form: orderBy([{ column, direction, nulls }])\n\t\tif (Array.isArray(fieldOrRecordOrSpecs)) {\n\t\t\tfor (const spec of fieldOrRecordOrSpecs) {\n\t\t\t\tthis.state.orderByIntents.push({\n\t\t\t\t\tfield: spec.column,\n\t\t\t\t\tdirection: spec.direction ?? 'asc',\n\t\t\t\t\tnulls: spec.nulls,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Object form: orderBy({ field1: 'desc', field2: 'asc' })\n\t\tfor (const [field, dir] of Object.entries(fieldOrRecordOrSpecs)) {\n\t\t\tthis.state.orderByIntents.push({\n\t\t\t\tfield,\n\t\t\t\tdirection: dir,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Set LIMIT value.\n\t */\n\tsetLimit(count: number): void {\n\t\tthis.state.limitValue = count;\n\t}\n\n\t/**\n\t * Set OFFSET value.\n\t */\n\tsetOffset(count: number): void {\n\t\tthis.state.offsetValue = count;\n\t}\n\n\t/**\n\t * Build the QueryIntent from accumulated state.\n\t * Handles exactOptionalPropertyTypes by only including defined properties.\n\t */\n\tbuildIntent(): QueryIntent {\n\t\tconst intent: Mutable<QueryIntent> = {\n\t\t\ttype: 'select',\n\t\t\tfrom: this.state.from,\n\t\t};\n\n\t\t// Handle aggregates - convert to SelectAggregateIntent\n\t\tif (this.state.aggregates.length > 0) {\n\t\t\tconst aggregateSelect: Mutable<SelectAggregateIntent> = {\n\t\t\t\ttype: 'aggregate',\n\t\t\t\taggregates: [...this.state.aggregates],\n\t\t\t};\n\t\t\t// Add group by fields to the select for projection\n\t\t\tif (this.state.groupByFields.length > 0) {\n\t\t\t\taggregateSelect.fields = [...this.state.groupByFields];\n\t\t\t}\n\t\t\tintent.select = aggregateSelect as SelectAggregateIntent;\n\t\t} else if (this.state.selectIntent !== undefined) {\n\t\t\tintent.select = this.state.selectIntent;\n\t\t}\n\n\t\t// Combine multiple where conditions with AND\n\t\tif (this.state.whereIntents.length === 1) {\n\t\t\tconst singleWhere = this.state.whereIntents[0];\n\t\t\tif (singleWhere !== undefined) {\n\t\t\t\tintent.where = singleWhere;\n\t\t\t}\n\t\t} else if (this.state.whereIntents.length > 1) {\n\t\t\tintent.where = and(...this.state.whereIntents);\n\t\t}\n\n\t\tif (this.state.includes.length > 0) {\n\t\t\tintent.include = this.state.includes;\n\t\t}\n\n\t\tif (this.state.groupByFields.length > 0) {\n\t\t\tintent.groupBy = [...this.state.groupByFields];\n\t\t}\n\n\t\t// DX-034: HAVING clause for filtering on aggregates\n\t\tif (this.state.havingIntents.length === 1) {\n\t\t\tconst singleHaving = this.state.havingIntents[0];\n\t\t\tif (singleHaving !== undefined) {\n\t\t\t\tintent.having = singleHaving;\n\t\t\t}\n\t\t} else if (this.state.havingIntents.length > 1) {\n\t\t\tintent.having = and(...this.state.havingIntents);\n\t\t}\n\n\t\t// DX-034: SELECT DISTINCT\n\t\tif (this.state.isDistinct) {\n\t\t\tintent.distinct = true;\n\t\t}\n\n\t\tif (this.state.orderByIntents.length > 0) {\n\t\t\tintent.orderBy = [...this.state.orderByIntents];\n\t\t}\n\n\t\tif (this.state.limitValue !== undefined) {\n\t\t\tintent.limit = this.state.limitValue;\n\t\t}\n\n\t\tif (this.state.offsetValue !== undefined) {\n\t\t\tintent.offset = this.state.offsetValue;\n\t\t}\n\n\t\treturn intent as QueryIntent;\n\t}\n\n\t/**\n\t * Apply relation hints to includes that don't have explicit `via`.\n\t */\n\tapplyRelationHints(intent: QueryIntent): QueryIntent {\n\t\tif (!intent.include || Object.keys(this.relationHints).length === 0) {\n\t\t\treturn intent;\n\t\t}\n\n\t\tconst updatedIncludes = intent.include.map((inc) =>\n\t\t\tthis.applyHintToInclude(inc),\n\t\t);\n\n\t\treturn {\n\t\t\t...intent,\n\t\t\tinclude: updatedIncludes,\n\t\t};\n\t}\n\n\t/**\n\t * Apply relation hint to a single include (recursively).\n\t */\n\tprivate applyHintToInclude(inc: IncludeIntent): IncludeIntent {\n\t\t// If already has explicit via, don't override\n\t\tif (inc.via !== undefined) {\n\t\t\t// But still process nested includes\n\t\t\tif (inc.include && inc.include.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\t...inc,\n\t\t\t\t\tinclude: inc.include.map((nested) => this.applyHintToInclude(nested)),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn inc;\n\t\t}\n\n\t\t// Check if we have a hint for this target\n\t\tconst hint = this.relationHints[inc.relation];\n\t\tconst result: IncludeIntent = hint ? { ...inc, via: hint } : inc;\n\n\t\t// Process nested includes\n\t\tif (result.include && result.include.length > 0) {\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tinclude: result.include.map((nested) =>\n\t\t\t\t\tthis.applyHintToInclude(nested),\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Clone the current state for immutable builder pattern.\n\t */\n\tclone(): IntentBuilder<TResult> {\n\t\treturn new IntentBuilder<TResult>(\n\t\t\tthis.model,\n\t\t\tthis.state.from,\n\t\t\t{ ...this.relationHints },\n\t\t\t{\n\t\t\t\tselectIntent: this.state.selectIntent,\n\t\t\t\twhereIntents: [...this.state.whereIntents],\n\t\t\t\thavingIntents: [...this.state.havingIntents],\n\t\t\t\tincludes: [...this.state.includes],\n\t\t\t\trecursiveIncludes: [...this.state.recursiveIncludes],\n\t\t\t\taggregates: [...this.state.aggregates],\n\t\t\t\tgroupByFields: [...this.state.groupByFields],\n\t\t\t\torderByIntents: [...this.state.orderByIntents],\n\t\t\t\tlimitValue: this.state.limitValue,\n\t\t\t\toffsetValue: this.state.offsetValue,\n\t\t\t\tisDistinct: this.state.isDistinct,\n\t\t\t},\n\t\t);\n\t}\n}\n","/**\n * DX-023: Lightweight ModelIR Definition\n *\n * Provides a simplified API for defining relations when using Kysely's Database type.\n * Instead of verbose column definitions, developers can focus solely on relations\n * using shorthand syntax with automatic FK inference.\n *\n * @example\n * ```typescript\n * import { defineModel } from '@dbsp/core';\n *\n * interface Database {\n * users: { id: number; name: string; };\n * posts: { id: number; user_id: number; title: string; };\n * }\n *\n * const model = defineModel<Database>({\n * relations: {\n * 'users.posts': '1:N',\n * 'posts.author': ['N:1', 'users'],\n * },\n * });\n * ```\n */\n\nimport { singularize } from '../conventions.js';\nimport type {\n\tCardinality as ModelCardinality,\n\tModelIR,\n\tOptionality,\n\tRelationIR,\n\tRelationType,\n\tTableIR,\n} from '../index.js';\n\n// Re-export for backwards compatibility\nexport { singularize };\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Cardinality shorthand notation.\n *\n * | Shorthand | Relation Type | Source Side | Target Side |\n * |-----------|---------------|-------------|-------------|\n * | `'1:N'` | hasMany | one | many |\n * | `'N:1'` | belongsTo | many | one |\n * | `'1:1'` | hasOne | one | one |\n * | `'M:N'` | belongsToMany | many | many |\n */\nexport type CardinalityShorthand = '1:N' | 'N:1' | '1:1' | 'M:N';\n\n/**\n * Object form for relation definition with full control.\n */\nexport interface RelationObjectDef {\n\t/** Cardinality shorthand */\n\treadonly cardinality: CardinalityShorthand;\n\t/** Explicit foreign key column(s) */\n\treadonly fk?: string | readonly string[];\n\t/** Explicit target table (if different from inferred) */\n\treadonly target?: string;\n\t/** Junction table for M:N relations */\n\treadonly through?: string;\n}\n\n/**\n * Tuple form for relation definition: [cardinality, target]\n */\nexport type RelationTupleDef = readonly [CardinalityShorthand, string];\n\n/**\n * All supported forms for relation definition.\n *\n * - **Simple:** `'1:N'` - target inferred from relation name\n * - **Tuple:** `['N:1', 'users']` - explicit target\n * - **Object:** `{ cardinality: '1:N', fk: 'order_uuid' }` - full control\n */\nexport type RelationShorthand =\n\t| CardinalityShorthand\n\t| RelationTupleDef\n\t| RelationObjectDef;\n\n/**\n * Relation key format: `'sourceTable.relationName'`\n */\nexport type RelationKey<DB> =\n\tDB extends Record<string, unknown>\n\t\t? `${Extract<keyof DB, string>}.${string}`\n\t\t: string;\n\n/**\n * Lightweight relations definition with type-safe keys.\n */\nexport type LightweightRelationsDef<DB> = {\n\treadonly [K in RelationKey<DB>]?: RelationShorthand;\n};\n\n/**\n * Options for defineModel function.\n */\nexport interface DefineModelOptions<DB> {\n\t/** Relation definitions using shorthand syntax */\n\treadonly relations: LightweightRelationsDef<DB>;\n}\n\n// ============================================================================\n// Errors\n// ============================================================================\n\n/**\n * Error thrown when a relation definition is invalid.\n *\n * @example\n * ```typescript\n * defineModel<DB>({ relations: { 'users.posts': '2:N' } });\n * // Throws: InvalidRelationDefinitionError: Invalid cardinality '2:N'\n * ```\n */\nexport class InvalidRelationDefinitionError extends Error {\n\toverride readonly name = 'InvalidRelationDefinitionError' as const;\n\n\t/** The relation key that caused the error */\n\treadonly relationKey: string;\n\n\t/** Specific reason for the error */\n\treadonly reason: string;\n\n\t/** Suggested fix, if available */\n\treadonly suggestion?: string;\n\n\tconstructor(opts: {\n\t\trelationKey: string;\n\t\treason: string;\n\t\tsuggestion?: string;\n\t}) {\n\t\tlet message = `Invalid relation definition for '${opts.relationKey}': ${opts.reason}`;\n\t\tif (opts.suggestion) {\n\t\t\tmessage += `\\n\\nSuggestion: ${opts.suggestion}`;\n\t\t}\n\n\t\tsuper(message);\n\t\tthis.relationKey = opts.relationKey;\n\t\tthis.reason = opts.reason;\n\t\tif (opts.suggestion) {\n\t\t\tthis.suggestion = opts.suggestion;\n\t\t}\n\n\t\tObject.setPrototypeOf(this, InvalidRelationDefinitionError.prototype);\n\t}\n}\n\n// ============================================================================\n// Parsing\n// ============================================================================\n\n/**\n * Valid cardinality values.\n */\nconst VALID_CARDINALITIES = new Set<string>(['1:N', 'N:1', '1:1', 'M:N']);\n\n/**\n * Maps cardinality shorthand to relation type.\n */\nconst CARDINALITY_TO_TYPE: Record<CardinalityShorthand, RelationType> = {\n\t'1:N': 'hasMany',\n\t'N:1': 'belongsTo',\n\t'1:1': 'hasOne',\n\t'M:N': 'belongsToMany',\n};\n\n/**\n * Maps cardinality shorthand to ModelIR cardinality.\n * ModelIR uses 'one' or 'many' to describe the target side cardinality.\n */\nconst CARDINALITY_TO_MODEL: Record<CardinalityShorthand, ModelCardinality> = {\n\t'1:N': 'many', // Target side is many\n\t'N:1': 'one', // Target side is one\n\t'1:1': 'one', // Target side is one\n\t'M:N': 'many', // Target side is many\n};\n\n/**\n * Type guard for CardinalityShorthand.\n */\nexport function isCardinalityShorthand(\n\tvalue: unknown,\n): value is CardinalityShorthand {\n\treturn typeof value === 'string' && VALID_CARDINALITIES.has(value);\n}\n\n/**\n * Type guard for RelationTupleDef.\n */\nexport function isRelationTupleDef(value: unknown): value is RelationTupleDef {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length === 2 &&\n\t\tisCardinalityShorthand(value[0]) &&\n\t\ttypeof value[1] === 'string'\n\t);\n}\n\n/**\n * Type guard for RelationObjectDef.\n */\nexport function isRelationObjectDef(\n\tvalue: unknown,\n): value is RelationObjectDef {\n\tif (typeof value !== 'object' || value === null || Array.isArray(value)) {\n\t\treturn false;\n\t}\n\tconst obj = value as Record<string, unknown>;\n\treturn isCardinalityShorthand(obj.cardinality);\n}\n\n/**\n * Parsed relation key information.\n */\nexport interface ParsedRelationKey {\n\treadonly sourceTable: string;\n\treadonly relationName: string;\n}\n\n/**\n * Parses a relation key into source table and relation name.\n *\n * @param key - The relation key in format 'sourceTable.relationName'\n * @returns Parsed key components\n * @throws InvalidRelationDefinitionError if key format is invalid\n */\nexport function parseRelationKey(key: string): ParsedRelationKey {\n\tconst dotIndex = key.indexOf('.');\n\tif (dotIndex === -1 || dotIndex === 0 || dotIndex === key.length - 1) {\n\t\tthrow new InvalidRelationDefinitionError({\n\t\t\trelationKey: key,\n\t\t\treason: \"Invalid key format. Expected 'sourceTable.relationName'\",\n\t\t\tsuggestion: \"Use format like 'users.posts' or 'posts.author'\",\n\t\t});\n\t}\n\n\treturn {\n\t\tsourceTable: key.slice(0, dotIndex),\n\t\trelationName: key.slice(dotIndex + 1),\n\t};\n}\n\n/**\n * Parsed relation definition.\n */\nexport interface ParsedRelationDef {\n\treadonly cardinality: CardinalityShorthand;\n\treadonly relationType: RelationType;\n\treadonly modelCardinality: ModelCardinality;\n\treadonly target: string | undefined;\n\treadonly fk: string | readonly string[] | undefined;\n\treadonly through: string | undefined;\n}\n\n/**\n * Parses a relation shorthand value into its components.\n *\n * @param key - The relation key for error messages\n * @param value - The relation shorthand value\n * @returns Parsed relation definition\n * @throws InvalidRelationDefinitionError if value is invalid\n */\nexport function parseRelationDef(\n\tkey: string,\n\tvalue: RelationShorthand,\n): ParsedRelationDef {\n\t// Form 1: Simple shorthand - '1:N'\n\tif (isCardinalityShorthand(value)) {\n\t\treturn {\n\t\t\tcardinality: value,\n\t\t\trelationType: CARDINALITY_TO_TYPE[value],\n\t\t\tmodelCardinality: CARDINALITY_TO_MODEL[value],\n\t\t\ttarget: undefined,\n\t\t\tfk: undefined,\n\t\t\tthrough: undefined,\n\t\t};\n\t}\n\n\t// Form 2: Tuple - ['N:1', 'users']\n\tif (isRelationTupleDef(value)) {\n\t\tconst [cardinality, target] = value;\n\t\treturn {\n\t\t\tcardinality,\n\t\t\trelationType: CARDINALITY_TO_TYPE[cardinality],\n\t\t\tmodelCardinality: CARDINALITY_TO_MODEL[cardinality],\n\t\t\ttarget,\n\t\t\tfk: undefined,\n\t\t\tthrough: undefined,\n\t\t};\n\t}\n\n\t// Form 3: Object - { cardinality: '1:N', fk: 'order_uuid' }\n\tif (isRelationObjectDef(value)) {\n\t\tconst { cardinality, fk, target, through } = value;\n\t\treturn {\n\t\t\tcardinality,\n\t\t\trelationType: CARDINALITY_TO_TYPE[cardinality],\n\t\t\tmodelCardinality: CARDINALITY_TO_MODEL[cardinality],\n\t\t\ttarget,\n\t\t\tfk,\n\t\t\tthrough,\n\t\t};\n\t}\n\n\t// Invalid format\n\tconst valueStr =\n\t\ttypeof value === 'object' ? JSON.stringify(value) : String(value);\n\tthrow new InvalidRelationDefinitionError({\n\t\trelationKey: key,\n\t\treason: `Invalid relation definition format: ${valueStr}`,\n\t\tsuggestion:\n\t\t\t\"Use one of: '1:N', ['N:1', 'targetTable'], or { cardinality: '1:N', fk: 'column' }\",\n\t});\n}\n\n// ============================================================================\n// FK Inference\n// ============================================================================\n\n/**\n * Infers the foreign key column name based on convention.\n *\n * Convention: `{singular_table_name}_id`\n *\n * For hasMany/hasOne (1:N, 1:1): FK is on target table, named after source\n * For belongsTo (N:1): FK is on source table, named after target\n * For belongsToMany (M:N): FKs are on junction table\n *\n * @param tableName - The table name to base the FK on\n * @returns Inferred FK column name\n */\nexport function inferForeignKey(tableName: string): string {\n\tconst singular = singularize(tableName);\n\t// Convert to snake_case if needed (handle camelCase table names)\n\tconst snakeCase = singular.replace(/([A-Z])/g, '_$1').toLowerCase();\n\t// Remove leading underscore if present\n\tconst cleanSnakeCase = snakeCase.startsWith('_')\n\t\t? snakeCase.slice(1)\n\t\t: snakeCase;\n\treturn `${cleanSnakeCase}_id`;\n}\n\n// ============================================================================\n// ModelIR Builder\n// ============================================================================\n\n/**\n * Builds a ModelIR from lightweight relation definitions.\n *\n * @param options - The defineModel options\n * @returns A ModelIR instance\n */\nexport function defineModel<DB = Record<string, unknown>>(\n\toptions: DefineModelOptions<DB>,\n): ModelIR {\n\tconst { relations } = options;\n\n\t// Collect all tables from relation keys\n\tconst tableNames = new Set<string>();\n\tconst relationEntries: Array<{\n\t\tkey: string;\n\t\tparsed: ParsedRelationKey;\n\t\tdef: ParsedRelationDef;\n\t}> = [];\n\n\t// First pass: parse all relation definitions and collect table names\n\tfor (const [key, value] of Object.entries(relations)) {\n\t\tif (value === undefined) continue;\n\n\t\tconst parsed = parseRelationKey(key);\n\t\tconst def = parseRelationDef(key, value as RelationShorthand);\n\n\t\ttableNames.add(parsed.sourceTable);\n\n\t\t// Determine target table\n\t\tlet target = def.target;\n\t\tif (target === undefined) {\n\t\t\t// Infer target from relation name\n\t\t\ttarget = parsed.relationName;\n\t\t}\n\t\ttableNames.add(target);\n\n\t\t// Validate M:N has through\n\t\tif (def.cardinality === 'M:N' && def.through === undefined) {\n\t\t\tthrow new InvalidRelationDefinitionError({\n\t\t\t\trelationKey: key,\n\t\t\t\treason:\n\t\t\t\t\t\"M:N relations require a 'through' option specifying the junction table\",\n\t\t\t\tsuggestion: `Use { cardinality: 'M:N', through: 'junction_table' }`,\n\t\t\t});\n\t\t}\n\n\t\t// Add junction table if M:N\n\t\tif (def.through !== undefined) {\n\t\t\ttableNames.add(def.through);\n\t\t}\n\n\t\trelationEntries.push({ key, parsed, def });\n\t}\n\n\t// Build tables map (minimal: just table name, no columns)\n\t// We infer that each table has an 'id' primary key by convention\n\tconst tables = new Map<string, TableIR>();\n\tfor (const name of tableNames) {\n\t\ttables.set(name, {\n\t\t\tname,\n\t\t\tcolumns: [],\n\t\t\tprimaryKey: 'id',\n\t\t\tforeignKeys: [],\n\t\t\tindexes: [],\n\t\t});\n\t}\n\n\t// Build relations map\n\tconst relationsMap = new Map<string, RelationIR>();\n\n\tfor (const { key, parsed, def } of relationEntries) {\n\t\t// Determine target\n\t\tconst target = def.target ?? parsed.relationName;\n\n\t\t// Determine FK\n\t\tlet foreignKey = def.fk;\n\t\tif (foreignKey === undefined) {\n\t\t\t// Infer FK based on relation type\n\t\t\tif (def.relationType === 'belongsTo') {\n\t\t\t\t// FK is on source table, named after target\n\t\t\t\tforeignKey = inferForeignKey(target);\n\t\t\t} else if (\n\t\t\t\tdef.relationType === 'hasMany' ||\n\t\t\t\tdef.relationType === 'hasOne'\n\t\t\t) {\n\t\t\t\t// FK is on target table, named after source\n\t\t\t\tforeignKey = inferForeignKey(parsed.sourceTable);\n\t\t\t}\n\t\t\t// For belongsToMany, FKs are typically inferred from the junction table\n\t\t\t// and would need explicit definition\n\t\t}\n\n\t\t// Determine optionality (default to optional for now)\n\t\tconst optionality: Optionality =\n\t\t\tdef.relationType === 'belongsTo' ? 'optional' : 'required';\n\n\t\tconst qualifiedName = key;\n\t\tconst relation: RelationIR = {\n\t\t\tname: parsed.relationName,\n\t\t\ttype: def.relationType,\n\t\t\tsource: parsed.sourceTable,\n\t\t\ttarget,\n\t\t\tthrough: def.through,\n\t\t\tforeignKey: foreignKey,\n\t\t\tcardinality: def.modelCardinality,\n\t\t\toptionality,\n\t\t\tincludeStrategy: 'auto',\n\t\t\tfilterStrategy: 'auto',\n\t\t\tjoinDefault: 'auto',\n\t\t};\n\n\t\trelationsMap.set(qualifiedName, relation);\n\t}\n\n\t// Create ModelIR implementation\n\treturn new LightweightModelIR(tables, relationsMap);\n}\n\n/**\n * Lightweight ModelIR implementation.\n */\nclass LightweightModelIR implements ModelIR {\n\treadonly tables: ReadonlyMap<string, TableIR>;\n\treadonly relations: ReadonlyMap<string, RelationIR>;\n\n\tconstructor(\n\t\ttables: ReadonlyMap<string, TableIR>,\n\t\trelations: ReadonlyMap<string, RelationIR>,\n\t) {\n\t\tthis.tables = tables;\n\t\tthis.relations = relations;\n\t}\n\n\tgetTable(name: string): TableIR | undefined {\n\t\treturn this.tables.get(name);\n\t}\n\n\tgetRelation(qualifiedName: string): RelationIR | undefined {\n\t\treturn this.relations.get(qualifiedName);\n\t}\n\n\tgetRelationsFrom(sourceTable: string): readonly RelationIR[] {\n\t\tconst result: RelationIR[] = [];\n\t\tfor (const [key, relation] of this.relations) {\n\t\t\tif (key.startsWith(`${sourceTable}.`)) {\n\t\t\t\tresult.push(relation);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tgetRelationsTo(targetTable: string): readonly RelationIR[] {\n\t\tconst result: RelationIR[] = [];\n\t\tfor (const relation of this.relations.values()) {\n\t\t\tif (relation.target === targetTable) {\n\t\t\t\tresult.push(relation);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tisAmbiguous(\n\t\tsourceTable: string,\n\t\ttargetTable: string,\n\t): { ambiguous: boolean; options: readonly string[] } {\n\t\tconst relationsToTarget: string[] = [];\n\t\tfor (const [key, relation] of this.relations) {\n\t\t\tif (\n\t\t\t\tkey.startsWith(`${sourceTable}.`) &&\n\t\t\t\trelation.target === targetTable\n\t\t\t) {\n\t\t\t\trelationsToTarget.push(relation.name);\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tambiguous: relationsToTarget.length > 1,\n\t\t\toptions: relationsToTarget,\n\t\t};\n\t}\n}\n","/**\n * @module mutation-builders\n * Mutation builders for insert, update, and delete operations.\n * Part of DX-010: Mutations.\n */\n\nimport type { Adapter, CompiledQuery, CompileOptions } from '../adapter.js';\nimport type {\n\tBatchUpdateIntent,\n\tDeleteIntent,\n\tInsertIntent,\n\tUpdateIntent,\n\tUpsertConflictAction,\n\tUpsertConflictTarget,\n\tUpsertIntent,\n\tWhereIntent,\n} from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport {\n\tExecutionError,\n\tInvalidOperationError,\n\tUnsafeOperationError,\n} from './errors.js';\nimport type {\n\tHookErrorHandler,\n\tHookStore,\n\tMutationHookContext,\n\tMutationOperation,\n} from './hooks.js';\nimport {\n\thasHooks,\n\trunAfterMutationHooks,\n\trunBeforeMutationHooks,\n\trunOnErrorHooks,\n\twithReentrancyGuard,\n} from './hooks.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Dump output for mutations.\n * Similar to query Dump but without plan (mutations don't use the planner).\n */\nexport interface MutationDump {\n\t/** Compiled SQL string */\n\treadonly sql: string;\n\t/** Bound parameter values */\n\treadonly parameters: readonly unknown[];\n\t/** The mutation intent */\n\treadonly intent:\n\t\t| InsertIntent\n\t\t| UpdateIntent\n\t\t| BatchUpdateIntent\n\t\t| DeleteIntent\n\t\t| UpsertIntent;\n\t/** Optional metadata */\n\treadonly meta?: {\n\t\treadonly schema?: string;\n\t\treadonly compiledAt?: Date;\n\t};\n}\n\n/** Shared base options for all mutation builders */\ntype MutationBaseOpts = {\n\ttable: string;\n\tmodel: ModelIR;\n\tadapter?: Adapter | undefined;\n\tschemaName?: string | undefined;\n\thookStore?: HookStore | undefined;\n\tonHookError?: HookErrorHandler | undefined;\n\tinTransaction?: boolean | undefined;\n};\n\n// ============================================================================\n// Abstract Base\n// ============================================================================\n\n/**\n * Abstract base class for mutation builders.\n * Consolidates shared fields, adapter validation, dump(), and execute() logic.\n *\n * Subclasses implement:\n * - `buildIntent()`: construct the mutation-specific intent\n * - `compileIntent()`: call the correct adapter.compile* method\n * - `operationName`: label used in error messages\n */\nabstract class MutationBuilderBase<\n\tT,\n\tTIntent extends\n\t\t| InsertIntent\n\t\t| UpdateIntent\n\t\t| BatchUpdateIntent\n\t\t| DeleteIntent\n\t\t| UpsertIntent,\n> {\n\tprotected readonly table: string;\n\tprotected readonly model: ModelIR;\n\tprotected readonly adapter: Adapter | undefined;\n\tprotected readonly schemaName: string | undefined;\n\tprotected readonly returningColumns: readonly string[] | undefined;\n\tprotected readonly hookStore: HookStore | undefined;\n\tprotected readonly onHookError: HookErrorHandler | undefined;\n\tprotected readonly inTransaction: boolean | undefined;\n\n\tprotected constructor(\n\t\topts: MutationBaseOpts & {\n\t\t\treturning?: readonly string[] | undefined;\n\t\t},\n\t) {\n\t\tthis.table = opts.table;\n\t\tthis.model = opts.model;\n\t\tthis.adapter = opts.adapter;\n\t\tthis.schemaName = opts.schemaName;\n\t\tthis.returningColumns = opts.returning;\n\t\tthis.hookStore = opts.hookStore;\n\t\tthis.onHookError = opts.onHookError;\n\t\tthis.inTransaction = opts.inTransaction;\n\t}\n\n\t/** Label used in ExecutionError messages (e.g. 'insert', 'update'). */\n\tprotected abstract readonly operationName: string;\n\n\t/** Construct the mutation-specific intent AST node. */\n\tprotected abstract buildIntent(): TIntent;\n\n\t/** Delegate to the adapter's mutation-specific compile method. */\n\tprotected abstract compileIntent(\n\t\tadapter: Adapter,\n\t\tintent: TIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery;\n\n\tprotected get baseOpts(): MutationBaseOpts {\n\t\treturn {\n\t\t\ttable: this.table,\n\t\t\tmodel: this.model,\n\t\t\tadapter: this.adapter,\n\t\t\tschemaName: this.schemaName,\n\t\t\thookStore: this.hookStore,\n\t\t\tonHookError: this.onHookError,\n\t\t\tinTransaction: this.inTransaction,\n\t\t};\n\t}\n\n\t/** Require a configured adapter or throw. */\n\tprotected requireAdapter(operation: string): Adapter {\n\t\tif (!this.adapter) {\n\t\t\tthrow new ExecutionError({\n\t\t\t\toperation,\n\t\t\t\treason: 'Adapter not configured',\n\t\t\t\tfix: 'Pass adapter option when creating ORM: createOrm({ model, adapter })',\n\t\t\t});\n\t\t}\n\t\treturn this.adapter;\n\t}\n\n\tdump(extraOptions?: CompileOptions): MutationDump {\n\t\tconst adapter = this.requireAdapter('dump');\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions: CompileOptions = {\n\t\t\t...(this.schemaName !== undefined && { schemaName: this.schemaName }),\n\t\t\t...extraOptions,\n\t\t};\n\t\tconst compiled = this.compileIntent(\n\t\t\tadapter,\n\t\t\tintent,\n\t\t\tObject.keys(compileOptions).length > 0 ? compileOptions : undefined,\n\t\t);\n\n\t\tconst meta: { compiledAt: Date; schema?: string } = {\n\t\t\tcompiledAt: new Date(),\n\t\t};\n\t\tif (this.schemaName !== undefined) {\n\t\t\tmeta.schema = this.schemaName;\n\t\t}\n\n\t\treturn {\n\t\t\tsql: compiled.sql,\n\t\t\tparameters: compiled.parameters,\n\t\t\tintent,\n\t\t\tmeta,\n\t\t};\n\t}\n\n\tasync execute(): Promise<T> {\n\t\tconst adapter = this.requireAdapter(this.operationName);\n\n\t\t// Fast path: no hooks registered\n\t\tif (!this.hookStore || !hasHooks(this.hookStore)) {\n\t\t\treturn this.executeWithoutHooks(adapter);\n\t\t}\n\n\t\treturn this.executeWithHooks(adapter);\n\t}\n\n\tprivate async executeWithoutHooks(adapter: Adapter): Promise<T> {\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions = this.schemaName\n\t\t\t? { schemaName: this.schemaName }\n\t\t\t: undefined;\n\t\tconst compiled = this.compileIntent(adapter, intent, compileOptions);\n\n\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\tconst result = await adapter.execute(compiled);\n\t\t\treturn result as T;\n\t\t}\n\t\tawait adapter.execute(compiled);\n\t\treturn undefined as T;\n\t}\n\n\tprivate async executeWithHooks(adapter: Adapter): Promise<T> {\n\t\tconst store = this.hookStore;\n\t\tif (!store) throw new Error('executeWithHooks called without hookStore');\n\t\t// INV-07: Re-entrancy guard\n\t\treturn withReentrancyGuard(store, (s) =>\n\t\t\tthis.executeWithHooksInner(adapter, s),\n\t\t);\n\t}\n\n\tprivate async executeWithHooksInner(\n\t\tadapter: Adapter,\n\t\tstore: HookStore,\n\t): Promise<T> {\n\t\tconst intent = this.buildIntent();\n\t\tconst operation = intent.type as MutationOperation;\n\t\tconst startTime = Date.now();\n\n\t\t// Determine cardinality and data from intent\n\t\tconst { cardinality, data } = this.extractIntentData(intent);\n\n\t\t// Build before-mutation context (no sql/duration yet)\n\t\tlet ctx: MutationHookContext = Object.freeze({\n\t\t\ttable: this.table,\n\t\t\toperation,\n\t\t\tintent,\n\t\t\tcardinality,\n\t\t\tdata,\n\t\t\t...(this.schemaName !== undefined ? { schemaName: this.schemaName } : {}),\n\t\t\t...(this.inTransaction ? { inTransaction: true } : {}),\n\t\t});\n\n\t\ttry {\n\t\t\t// Run beforeMutation hooks (FIFO)\n\t\t\tif (store.beforeMutation.length > 0) {\n\t\t\t\tctx = await runBeforeMutationHooks(\n\t\t\t\t\tstore.beforeMutation,\n\t\t\t\t\tctx,\n\t\t\t\t\tthis.onHookError,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Compile and execute\n\t\t\tconst compileOptions = this.schemaName\n\t\t\t\t? { schemaName: this.schemaName }\n\t\t\t\t: undefined;\n\t\t\tconst compiled = this.compileIntent(adapter, intent, compileOptions);\n\t\t\tconst duration = Date.now() - startTime;\n\n\t\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\t\tconst result = await adapter.execute(compiled);\n\n\t\t\t\t// Build after-mutation context with sql/duration\n\t\t\t\tconst afterCtx: MutationHookContext = Object.freeze({\n\t\t\t\t\t...ctx,\n\t\t\t\t\tsql: compiled.sql,\n\t\t\t\t\tparameters: compiled.parameters,\n\t\t\t\t\tduration,\n\t\t\t\t});\n\n\t\t\t\t// Run afterMutation hooks (LIFO)\n\t\t\t\tif (store.afterMutation.length > 0) {\n\t\t\t\t\tconst transformed = await runAfterMutationHooks(\n\t\t\t\t\t\tstore.afterMutation,\n\t\t\t\t\t\tafterCtx,\n\t\t\t\t\t\tresult as unknown[],\n\t\t\t\t\t\tthis.onHookError,\n\t\t\t\t\t);\n\t\t\t\t\treturn transformed as T;\n\t\t\t\t}\n\t\t\t\treturn result as T;\n\t\t\t}\n\n\t\t\tawait adapter.execute(compiled);\n\n\t\t\t// Even without RETURNING, fire afterMutation with empty results\n\t\t\tif (store.afterMutation.length > 0) {\n\t\t\t\tconst afterCtx: MutationHookContext = Object.freeze({\n\t\t\t\t\t...ctx,\n\t\t\t\t\tsql: compiled.sql,\n\t\t\t\t\tparameters: compiled.parameters,\n\t\t\t\t\tduration,\n\t\t\t\t});\n\t\t\t\tawait runAfterMutationHooks(\n\t\t\t\t\tstore.afterMutation,\n\t\t\t\t\tafterCtx,\n\t\t\t\t\t[],\n\t\t\t\t\tthis.onHookError,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn undefined as T;\n\t\t} catch (error) {\n\t\t\t// Run onError hooks\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tconst errorCtx = {\n\t\t\t\t\ttable: this.table,\n\t\t\t\t\toperation,\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent,\n\t\t\t\t\tphase: 'beforeMutation' as const,\n\t\t\t\t\t...(this.schemaName !== undefined\n\t\t\t\t\t\t? { schemaName: this.schemaName }\n\t\t\t\t\t\t: {}),\n\t\t\t\t};\n\t\t\t\tconst transformed = await runOnErrorHooks(store.onError, errorCtx);\n\t\t\t\tthrow transformed;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/** Extract cardinality and data from mutation intent */\n\tprivate extractIntentData(intent: TIntent): {\n\t\tcardinality: 'single' | 'bulk';\n\t\tdata: unknown;\n\t} {\n\t\tif (intent.type === 'insert' || intent.type === 'upsert') {\n\t\t\tconst values = (intent as InsertIntent | UpsertIntent).values;\n\t\t\treturn {\n\t\t\t\tcardinality: values.length > 1 ? 'bulk' : 'single',\n\t\t\t\tdata: values.length > 1 ? values : values[0],\n\t\t\t};\n\t\t}\n\t\tif (intent.type === 'update') {\n\t\t\treturn {\n\t\t\t\tcardinality: 'single',\n\t\t\t\tdata: (intent as UpdateIntent).set,\n\t\t\t};\n\t\t}\n\t\tif (intent.type === 'batchUpdate') {\n\t\t\tconst updates = (intent as BatchUpdateIntent).updates;\n\t\t\treturn {\n\t\t\t\tcardinality: 'bulk',\n\t\t\t\tdata: updates,\n\t\t\t};\n\t\t}\n\t\t// delete — no data\n\t\treturn { cardinality: 'single', data: undefined };\n\t}\n}\n\n// ============================================================================\n// Insert Builder\n// ============================================================================\n\n/**\n * Builder for INSERT operations.\n * Immutable - each method returns a new builder instance.\n */\nexport class InsertBuilder<T = void> extends MutationBuilderBase<\n\tT,\n\tInsertIntent\n> {\n\tprivate readonly valuesData: readonly Record<string, unknown>[];\n\n\tprotected readonly operationName = 'insert';\n\n\tconstructor(\n\t\topts: MutationBaseOpts & {\n\t\t\tvalues?: readonly Record<string, unknown>[] | undefined;\n\t\t\treturning?: readonly string[] | undefined;\n\t\t},\n\t) {\n\t\tsuper(opts);\n\t\tthis.valuesData = opts.values ?? [];\n\t}\n\n\t/**\n\t * Set values to insert.\n\t * Accepts a single object or an array for bulk insert.\n\t */\n\tvalues(\n\t\tdata: Record<string, unknown> | readonly Record<string, unknown>[],\n\t): InsertBuilder<T> {\n\t\tconst valueArray = Array.isArray(data) ? data : [data];\n\t\treturn new InsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: valueArray,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Specify columns to return after insert (DX-026).\n\t * Requires adapter support for RETURNING clause.\n\t *\n\t * @example\n\t * ```typescript\n\t * const inserted = await orm.insert(User)\n\t * .values({ name: 'Alice', email: 'alice@example.com' })\n\t * .returning(['id', 'created_at'])\n\t * .execute();\n\t * // inserted = [{ id: 1, created_at: '2024-01-01T00:00:00Z' }]\n\t * ```\n\t */\n\treturning<R = Record<string, unknown>>(\n\t\tcolumns: readonly (keyof R & string)[],\n\t): InsertBuilder<R[]> {\n\t\treturn new InsertBuilder<R[]>({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\treturning: columns,\n\t\t});\n\t}\n\n\tprotected buildIntent(): InsertIntent {\n\t\tif (this.valuesData.length === 0) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'insert',\n\t\t\t\t'No values provided for insert',\n\t\t\t);\n\t\t}\n\n\t\tconst intent: InsertIntent = {\n\t\t\ttype: 'insert',\n\t\t\ttable: this.table,\n\t\t\tvalues: this.valuesData,\n\t\t};\n\n\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\treturn { ...intent, returning: this.returningColumns };\n\t\t}\n\n\t\treturn intent;\n\t}\n\n\tprotected compileIntent(\n\t\tadapter: Adapter,\n\t\tintent: InsertIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn adapter.compileInsert(intent, options);\n\t}\n}\n\n// ============================================================================\n// Update Builder\n// ============================================================================\n\n/**\n * Builder for UPDATE operations.\n * Immutable - each method returns a new builder instance.\n */\nexport class UpdateBuilder<T = void> extends MutationBuilderBase<\n\tT,\n\tUpdateIntent | BatchUpdateIntent\n> {\n\tprivate readonly setData: Record<string, unknown>;\n\tprivate readonly whereIntent: WhereIntent | undefined;\n\tprivate readonly allowAllFlag: boolean;\n\tprivate readonly batchMatchColumns: readonly string[] | undefined;\n\tprivate readonly batchData: readonly Record<string, unknown>[] | undefined;\n\n\tprotected readonly operationName = 'update';\n\n\tconstructor(\n\t\topts: MutationBaseOpts & {\n\t\t\tset?: Record<string, unknown> | undefined;\n\t\t\twhere?: WhereIntent | undefined;\n\t\t\tallowAll?: boolean | undefined;\n\t\t\treturning?: readonly string[] | undefined;\n\t\t\tbatchMatchColumns?: readonly string[] | undefined;\n\t\t\tbatchData?: readonly Record<string, unknown>[] | undefined;\n\t\t},\n\t) {\n\t\tsuper(opts);\n\t\tthis.setData = opts.set ?? {};\n\t\tthis.whereIntent = opts.where;\n\t\tthis.allowAllFlag = opts.allowAll ?? false;\n\t\tthis.batchMatchColumns = opts.batchMatchColumns;\n\t\tthis.batchData = opts.batchData;\n\t}\n\n\t/**\n\t * Set fields to update.\n\t * Multiple calls merge fields (last value wins).\n\t * When combined with batchSet(), these become scalar SET assignments applied to all rows.\n\t */\n\tset(data: Record<string, unknown>): UpdateBuilder<T> {\n\t\treturn new UpdateBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tset: { ...this.setData, ...data },\n\t\t\twhere: this.whereIntent,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\treturning: this.returningColumns,\n\t\t\tbatchMatchColumns: this.batchMatchColumns,\n\t\t\tbatchData: this.batchData,\n\t\t});\n\t}\n\n\t/**\n\t * Add WHERE condition.\n\t */\n\twhere(condition: WhereIntent): UpdateBuilder<T> {\n\t\treturn new UpdateBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tset: this.setData,\n\t\t\twhere: condition,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\treturning: this.returningColumns,\n\t\t\tbatchMatchColumns: this.batchMatchColumns,\n\t\t\tbatchData: this.batchData,\n\t\t});\n\t}\n\n\t/**\n\t * Specify columns to return after update (DX-026).\n\t * Requires adapter support for RETURNING clause.\n\t *\n\t * @example\n\t * ```typescript\n\t * const updated = await orm.update(User)\n\t * .set({ status: 'active' })\n\t * .where({ type: 'comparison', field: 'id', operator: '=', value: 1 })\n\t * .returning(['id', 'status', 'updated_at'])\n\t * .execute();\n\t * ```\n\t */\n\treturning<R = Record<string, unknown>>(\n\t\tcolumns: readonly (keyof R & string)[],\n\t): UpdateBuilder<R[]> {\n\t\treturn new UpdateBuilder<R[]>({\n\t\t\t...this.baseOpts,\n\t\t\tset: this.setData,\n\t\t\twhere: this.whereIntent,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\treturning: columns,\n\t\t\tbatchMatchColumns: this.batchMatchColumns,\n\t\t\tbatchData: this.batchData,\n\t\t});\n\t}\n\n\t/**\n\t * Batch update multiple rows using unnest FROM strategy (BATCH-001).\n\t *\n\t * Generates:\n\t * UPDATE \"table\" SET \"col\" = t.\"col\"\n\t * FROM unnest(CAST($1 AS type[]), CAST($2 AS type[])) AS t(\"match_col\", \"col\")\n\t * WHERE \"table\".\"match_col\" = t.\"match_col\"\n\t *\n\t * Can be chained with .set() for scalar values applied to all rows.\n\t *\n\t * @param matchColumn - Column(s) used to identify rows to update\n\t * @param data - Array of row objects containing match + update column values\n\t *\n\t * @example\n\t * ```typescript\n\t * await orm.update('calls')\n\t * .batchSet('id', [{ id: 10, callee_id: 42 }, { id: 20, callee_id: 43 }])\n\t * .execute();\n\t * ```\n\t */\n\tbatchSet(\n\t\tmatchColumn: string | string[],\n\t\tdata: Record<string, unknown>[],\n\t): UpdateBuilder<T> {\n\t\tconst matchColumns = Array.isArray(matchColumn)\n\t\t\t? matchColumn\n\t\t\t: [matchColumn];\n\t\treturn new UpdateBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tset: this.setData,\n\t\t\twhere: this.whereIntent,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\treturning: this.returningColumns,\n\t\t\tbatchMatchColumns: matchColumns,\n\t\t\tbatchData: data,\n\t\t});\n\t}\n\n\tprotected buildIntent(): UpdateIntent | BatchUpdateIntent {\n\t\t// Batch path\n\t\tif (this.batchMatchColumns && this.batchData) {\n\t\t\tif (this.batchData.length === 0) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'update',\n\t\t\t\t\t'batchSet requires at least one row',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst intent: BatchUpdateIntent = {\n\t\t\t\ttype: 'batchUpdate',\n\t\t\t\ttable: this.table,\n\t\t\t\tmatchColumns: this.batchMatchColumns,\n\t\t\t\tupdates: this.batchData,\n\t\t\t};\n\n\t\t\tif (Object.keys(this.setData).length > 0) {\n\t\t\t\tObject.assign(intent, { scalarSet: this.setData });\n\t\t\t}\n\t\t\tif (this.whereIntent) {\n\t\t\t\tObject.assign(intent, { where: this.whereIntent });\n\t\t\t}\n\t\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\t\tObject.assign(intent, { returning: this.returningColumns });\n\t\t\t}\n\n\t\t\treturn intent;\n\t\t}\n\n\t\t// Regular update path\n\t\tif (Object.keys(this.setData).length === 0) {\n\t\t\tthrow new InvalidOperationError('update', 'No fields to update');\n\t\t}\n\n\t\tif (!this.whereIntent && !this.allowAllFlag) {\n\t\t\tthrow new UnsafeOperationError(\n\t\t\t\t'update',\n\t\t\t\t'WHERE clause required. Use updateAll() for full-table updates.',\n\t\t\t);\n\t\t}\n\n\t\tconst intent: UpdateIntent = {\n\t\t\ttype: 'update',\n\t\t\ttable: this.table,\n\t\t\tset: this.setData,\n\t\t};\n\n\t\tif (this.whereIntent) {\n\t\t\tObject.assign(intent, { where: this.whereIntent });\n\t\t}\n\t\tif (this.allowAllFlag) {\n\t\t\tObject.assign(intent, { allowAll: true });\n\t\t}\n\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\tObject.assign(intent, { returning: this.returningColumns });\n\t\t}\n\n\t\treturn intent;\n\t}\n\n\tprotected compileIntent(\n\t\tadapter: Adapter,\n\t\tintent: UpdateIntent | BatchUpdateIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\tif (intent.type === 'batchUpdate') {\n\t\t\treturn adapter.compileBatchUpdate(intent, options);\n\t\t}\n\t\treturn adapter.compileUpdate(intent, options);\n\t}\n}\n\n// ============================================================================\n// Delete Builder\n// ============================================================================\n\n/**\n * Builder for DELETE operations.\n * Immutable - each method returns a new builder instance.\n */\nexport class DeleteBuilder<T = void> extends MutationBuilderBase<\n\tT,\n\tDeleteIntent\n> {\n\tprivate readonly whereIntent: WhereIntent | undefined;\n\tprivate readonly allowAllFlag: boolean;\n\tprivate readonly cascadeRelations: boolean | readonly string[] | undefined;\n\n\tprotected readonly operationName = 'delete';\n\n\tconstructor(\n\t\topts: MutationBaseOpts & {\n\t\t\twhere?: WhereIntent | undefined;\n\t\t\tallowAll?: boolean | undefined;\n\t\t\tcascade?: boolean | readonly string[] | undefined;\n\t\t\treturning?: readonly string[] | undefined;\n\t\t},\n\t) {\n\t\tsuper(opts);\n\t\tthis.whereIntent = opts.where;\n\t\tthis.allowAllFlag = opts.allowAll ?? false;\n\t\tthis.cascadeRelations = opts.cascade;\n\t}\n\n\t/**\n\t * Add WHERE condition.\n\t */\n\twhere(condition: WhereIntent): DeleteBuilder<T> {\n\t\treturn new DeleteBuilder({\n\t\t\t...this.baseOpts,\n\t\t\twhere: condition,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\tcascade: this.cascadeRelations,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Enable cascade delete.\n\t * Without arguments: deletes ALL related records.\n\t * With array: deletes only specified relations.\n\t */\n\tcascade(relations?: readonly string[]): DeleteBuilder<T> {\n\t\treturn new DeleteBuilder({\n\t\t\t...this.baseOpts,\n\t\t\twhere: this.whereIntent,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\tcascade: relations ?? true,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Specify columns to return after delete (DX-026).\n\t * Requires adapter support for RETURNING clause.\n\t *\n\t * @example\n\t * ```typescript\n\t * const deleted = await orm.delete(User)\n\t * .where({ type: 'comparison', field: 'id', operator: '=', value: 1 })\n\t * .returning(['id', 'email'])\n\t * .execute();\n\t * ```\n\t */\n\treturning<R = Record<string, unknown>>(\n\t\tcolumns: readonly (keyof R & string)[],\n\t): DeleteBuilder<R[]> {\n\t\treturn new DeleteBuilder<R[]>({\n\t\t\t...this.baseOpts,\n\t\t\twhere: this.whereIntent,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\tcascade: this.cascadeRelations,\n\t\t\treturning: columns,\n\t\t});\n\t}\n\n\tprotected buildIntent(): DeleteIntent {\n\t\tif (!this.whereIntent && !this.allowAllFlag) {\n\t\t\tthrow new UnsafeOperationError(\n\t\t\t\t'delete',\n\t\t\t\t'WHERE clause required. Use deleteAll() for full-table deletes.',\n\t\t\t);\n\t\t}\n\n\t\tconst intent: DeleteIntent = {\n\t\t\ttype: 'delete',\n\t\t\ttable: this.table,\n\t\t};\n\n\t\tif (this.whereIntent) {\n\t\t\tObject.assign(intent, { where: this.whereIntent });\n\t\t}\n\t\tif (this.allowAllFlag) {\n\t\t\tObject.assign(intent, { allowAll: true });\n\t\t}\n\t\tif (this.cascadeRelations !== undefined) {\n\t\t\tObject.assign(intent, { cascade: this.cascadeRelations });\n\t\t}\n\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\tObject.assign(intent, { returning: this.returningColumns });\n\t\t}\n\n\t\treturn intent;\n\t}\n\n\tprotected compileIntent(\n\t\tadapter: Adapter,\n\t\tintent: DeleteIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn adapter.compileDelete(intent, options);\n\t}\n}\n\n// ============================================================================\n// Upsert Builder (DX-026)\n// ============================================================================\n\n/**\n * Builder for UPSERT operations (INSERT ... ON CONFLICT ... DO UPDATE/NOTHING).\n * Immutable - each method returns a new builder instance.\n *\n * @example\n * ```typescript\n * // Basic upsert with doUpdate\n * await orm.upsert(User)\n * .values({ id: 1, name: 'Alice', email: 'alice@example.com' })\n * .onConflict(['id'])\n * .doUpdate({ name: 'Alice Updated' })\n * .execute();\n *\n * // Upsert with doNothing\n * await orm.upsert(User)\n * .values({ id: 1, name: 'Alice' })\n * .onConflict(['id'])\n * .doNothing()\n * .execute();\n *\n * // Upsert with constraint name\n * await orm.upsert(User)\n * .values({ id: 1, name: 'Alice' })\n * .onConflictConstraint('users_pkey')\n * .doUpdate() // Auto-update non-conflict columns\n * .returning(['id', 'updated_at'])\n * .execute();\n * ```\n */\nexport class UpsertBuilder<T = void> extends MutationBuilderBase<\n\tT,\n\tUpsertIntent\n> {\n\tprivate readonly valuesData: readonly Record<string, unknown>[];\n\tprivate readonly conflictTarget: UpsertConflictTarget | undefined;\n\tprivate readonly conflictAction: UpsertConflictAction | undefined;\n\n\tprotected readonly operationName = 'upsert';\n\n\tconstructor(\n\t\topts: MutationBaseOpts & {\n\t\t\tvalues?: readonly Record<string, unknown>[] | undefined;\n\t\t\tonConflict?: UpsertConflictTarget | undefined;\n\t\t\taction?: UpsertConflictAction | undefined;\n\t\t\treturning?: readonly string[] | undefined;\n\t\t},\n\t) {\n\t\tsuper(opts);\n\t\tthis.valuesData = opts.values ?? [];\n\t\tthis.conflictTarget = opts.onConflict;\n\t\tthis.conflictAction = opts.action;\n\t}\n\n\t/**\n\t * Set values to insert.\n\t * Accepts a single object or an array for bulk upsert.\n\t */\n\tvalues(\n\t\tdata: Record<string, unknown> | readonly Record<string, unknown>[],\n\t): UpsertBuilder<T> {\n\t\tconst valueArray = Array.isArray(data) ? data : [data];\n\t\treturn new UpsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: valueArray,\n\t\t\tonConflict: this.conflictTarget,\n\t\t\taction: this.conflictAction,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Specify conflict target by column names.\n\t * These columns determine conflict detection.\n\t */\n\tonConflict(columns: readonly string[]): UpsertBuilder<T> {\n\t\treturn new UpsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: { columns },\n\t\t\taction: this.conflictAction,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Specify conflict target by constraint name.\n\t * Alternative to onConflict() for named constraints.\n\t */\n\tonConflictConstraint(constraintName: string): UpsertBuilder<T> {\n\t\treturn new UpsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: { constraint: constraintName },\n\t\t\taction: this.conflictAction,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * On conflict, update the specified fields.\n\t * If no fields specified, auto-updates all non-conflict columns.\n\t *\n\t * @param set - Optional fields to update on conflict\n\t * @param where - Optional condition for the update\n\t */\n\tdoUpdate(\n\t\tset?: Record<string, unknown>,\n\t\twhere?: WhereIntent,\n\t): UpsertBuilder<T> {\n\t\tconst action: UpsertConflictAction = {\n\t\t\ttype: 'doUpdate',\n\t\t\t...(set && { set }),\n\t\t\t...(where && { where }),\n\t\t};\n\t\treturn new UpsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: this.conflictTarget,\n\t\t\taction,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * On conflict, do nothing (skip the insert).\n\t */\n\tdoNothing(): UpsertBuilder<T> {\n\t\treturn new UpsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: this.conflictTarget,\n\t\t\taction: { type: 'doNothing' },\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Specify columns to return after upsert (DX-026).\n\t * Requires adapter support for RETURNING clause.\n\t */\n\treturning<R = Record<string, unknown>>(\n\t\tcolumns: readonly (keyof R & string)[],\n\t): UpsertBuilder<R[]> {\n\t\treturn new UpsertBuilder<R[]>({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: this.conflictTarget,\n\t\t\taction: this.conflictAction,\n\t\t\treturning: columns,\n\t\t});\n\t}\n\n\tprotected buildIntent(): UpsertIntent {\n\t\tif (this.valuesData.length === 0) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'upsert',\n\t\t\t\t'No values provided for upsert',\n\t\t\t);\n\t\t}\n\n\t\tif (!this.conflictTarget) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'upsert',\n\t\t\t\t'No conflict target specified. Use onConflict() or onConflictConstraint().',\n\t\t\t);\n\t\t}\n\n\t\tif (!this.conflictAction) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'upsert',\n\t\t\t\t'No conflict action specified. Use doUpdate() or doNothing().',\n\t\t\t);\n\t\t}\n\n\t\tconst intent: UpsertIntent = {\n\t\t\ttype: 'upsert',\n\t\t\ttable: this.table,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: this.conflictTarget,\n\t\t\taction: this.conflictAction,\n\t\t};\n\n\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\treturn { ...intent, returning: this.returningColumns };\n\t\t}\n\n\t\treturn intent;\n\t}\n\n\tprotected compileIntent(\n\t\tadapter: Adapter,\n\t\tintent: UpsertIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn adapter.compileUpsert(intent, options);\n\t}\n}\n","import type {\n\tDDLFeature,\n\tDialectCapabilities,\n\tFeatureBehaviorConfig,\n\tFeatureWarning,\n\tModelIR,\n\tUnsupportedFeatureBehavior,\n} from '@dbsp/types';\nimport { UnsupportedFeatureError } from '@dbsp/types';\nimport {\n\tDEFAULT_FEATURE_CHECKERS,\n\ttype FeatureChecker,\n} from './feature-checkers.js';\n\nexport type { FeatureChecker, FeatureUsage } from './feature-checkers.js';\nexport { DEFAULT_FEATURE_CHECKERS } from './feature-checkers.js';\n\nexport interface NegotiationResult {\n\treadonly warnings: readonly FeatureWarning[];\n}\n\n/** Resolve effective behavior for a specific feature */\nfunction resolveBehavior(\n\tfeature: DDLFeature,\n\tconfig: UnsupportedFeatureBehavior | FeatureBehaviorConfig,\n): UnsupportedFeatureBehavior {\n\tif (typeof config === 'string') return config;\n\treturn config.overrides?.[feature] ?? config.default;\n}\n\n/**\n * Cross-check ModelIR features against DialectCapabilities.\n * Emits warnings or throws based on UnsupportedFeatureBehavior.\n *\n * INV-06: MUST NOT modify the ModelIR.\n * ERR-02: error mode throws on FIRST unsupported feature (fail-fast).\n * ERR-03: warning mode collects ALL warnings.\n *\n * OCP-001: extend by adding FeatureChecker entries to DEFAULT_FEATURE_CHECKERS\n * (or pass a custom checkers array) -- no edits to this function required.\n */\nexport function negotiateFeatures(\n\tmodel: ModelIR,\n\tcapabilities: DialectCapabilities,\n\tbehavior: UnsupportedFeatureBehavior | FeatureBehaviorConfig = 'warning',\n\tcheckers: readonly FeatureChecker[] = DEFAULT_FEATURE_CHECKERS,\n): NegotiationResult {\n\tconst warnings: FeatureWarning[] = [];\n\tconst adapterName = capabilities.name;\n\n\tfor (const checker of checkers) {\n\t\tif (capabilities[checker.capability]) continue; // supported\n\t\tconst usages = checker.detectUsage(model);\n\t\tif (usages.length === 0) continue; // not used\n\t\tconst effectiveBehavior = resolveBehavior(checker.feature, behavior);\n\t\tif (effectiveBehavior === 'ignore') continue;\n\t\tfor (const usage of usages) {\n\t\t\tif (effectiveBehavior === 'error') {\n\t\t\t\tthrow new UnsupportedFeatureError(\n\t\t\t\t\tchecker.feature,\n\t\t\t\t\tadapterName,\n\t\t\t\t\tusage.detail,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// warning mode\n\t\t\tconst message = `Unsupported feature \"${checker.feature}\" on adapter \"${adapterName}\" for \"${usage.detail}\"`;\n\t\t\twarnings.push({\n\t\t\t\tfeature: checker.feature,\n\t\t\t\tadapter: adapterName,\n\t\t\t\telement: usage.detail,\n\t\t\t\tmessage,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { warnings };\n}\n","/**\n * @fileoverview NQL template literal integration for type-safe queries (DX-040 Block 8).\n *\n * Provides a type-safe way to use NQL queries with explicit type annotation:\n * ```typescript\n * const users = await orm.nql<{ name: string; email: string }>`users | select name, email`.all();\n * ```\n *\n * Each `${value}` interpolation is escaped into a safe NQL literal (string/number/boolean/null).\n * Untrusted string input cannot inject NQL structure because it is always quoted and\n * single-quotes inside are doubled (`''`). For dynamic structural fragments (table names,\n * column names, ORDER BY direction) use the builder API (`orm.select()`). See #134 for\n * upcoming `:param` binding and a `nqlRaw()` escape hatch.\n *\n * @module nql\n * @since DX-040\n */\n\nimport { type NqlCompilerOptions, compile as nqlCompile } from '@dbsp/nql';\nimport type { Adapter, Dump } from '../adapter.js';\nimport type { QueryIntent } from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanReport } from '../planner.js';\nimport { plan as executePlan } from '../planner.js';\nimport type { DumpMetaInput } from './query-builder-types.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * NQL query builder with type-safe result.\n *\n * @typeParam T - The expected result row type\n */\nexport interface NqlBuilder<T> {\n\t/** Execute query and return all results */\n\tall(): Promise<T[]>;\n\t/** Execute query and return first result or null */\n\tfirst(): Promise<T | null>;\n\t/** Get the IntentIR for debugging */\n\ttoIntentIR(): QueryIntent;\n\t/** Get the execution plan */\n\tplan(): PlanReport;\n\t/** Get full dump (plan + SQL + params) */\n\tdump(meta?: DumpMetaInput): Dump;\n}\n\n/**\n * NQL template tag function type.\n *\n * @example\n * ```typescript\n * orm.nql<{ name: string }>`users | select name`\n * ```\n */\nexport type NqlTag = <T>(\n\tstrings: TemplateStringsArray,\n\t...values: unknown[]\n) => NqlBuilder<T>;\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Convert a JS value into a safe NQL literal token string.\n *\n * Supported types:\n * - `string` → single-quoted NQL string literal; embedded single-quotes are doubled (`''`),\n * matching the NQL StringLiteral token pattern `/'(?:[^']|'')*'/`.\n * Values containing a raw newline are rejected (Chevrotain StringLiteral\n * has no `line_breaks: true`, so newlines would produce a lex error).\n * - finite, non-exponential `number` → bare numeric literal (e.g. `42`, `3.14`, `-5`).\n * Negative numbers are emitted as a leading minus followed by the absolute\n * value, which NQL parses as unary-minus + number. Note: negative numbers\n * are only valid in comparison/value positions — `limit`/`offset` expect a\n * bare NumberLiteral and will parse-error on a leading minus.\n * `NaN`, `Infinity`, and numbers whose JS string form uses exponential\n * notation (magnitude ≥ 1e21 or absolute value < ~1e-6, e.g. `1e21`,\n * `1e-7`) are rejected — NQL NumberLiteral is `/\\d+(\\.\\d+)?/` (no exponent).\n * - `boolean` → `true` or `false` (matches NQL True/False tokens, case-insensitive).\n * - `null` → `null` (matches NQL Null token).\n * - All other types throw a descriptive Error.\n *\n * @param value - The JS value to convert\n * @param index - Zero-based interpolation position (for error messages)\n * @returns Safe NQL literal string\n * @internal\n */\nexport function toNqlLiteral(value: unknown, index: number): string {\n\tif (value === null) {\n\t\treturn 'null';\n\t}\n\tswitch (typeof value) {\n\t\tcase 'boolean':\n\t\t\treturn value ? 'true' : 'false';\n\t\tcase 'number': {\n\t\t\tif (!Number.isFinite(value)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`nql\\`...\\`: cannot interpolate non-finite number (${value}) at position ${index}. ` +\n\t\t\t\t\t\t'Only finite numbers are supported. ' +\n\t\t\t\t\t\t'For dynamic NQL structure use the builder API (orm.select()). See issue #134.',\n\t\t\t\t);\n\t\t\t}\n\t\t\t// NQL NumberLiteral is digits-only; negatives are parsed as unary minus + number.\n\t\t\t// Emit the minus separately so the lexer tokenises it correctly.\n\t\t\tconst s = value < 0 ? `-${Math.abs(value)}` : String(value);\n\t\t\t// Reject any value whose string form uses exponential notation (e.g. 1e21, 1e-7).\n\t\t\t// NQL NumberLiteral pattern /\\d+(\\.\\d+)?/ has no exponent support; emitting\n\t\t\t// such a token produces an opaque downstream parse error.\n\t\t\tif (/[eE]/.test(s)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`nql\\`...\\`: number ${value} at position ${index} has no exact NQL numeric literal form (exponential notation). ` +\n\t\t\t\t\t\t'Convert it yourself or use the builder API (orm.select()). See issue #134.',\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn s;\n\t\t}\n\t\tcase 'string': {\n\t\t\tif (value.includes('\\n') || value.includes('\\r')) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`nql\\`...\\`: cannot interpolate a string containing a newline at position ${index}. ` +\n\t\t\t\t\t\t'NQL string literals do not support raw newline characters. ' +\n\t\t\t\t\t\t'For dynamic NQL structure use the builder API (orm.select()). See issue #134.',\n\t\t\t\t);\n\t\t\t}\n\t\t\t// SQL-style quoting: wrap in single-quotes, double any embedded single-quote.\n\t\t\t// Matches NQL StringLiteral pattern: /'(?:[^']|'')*'/\n\t\t\tconst escaped = value.replaceAll(\"'\", \"''\");\n\t\t\treturn `'${escaped}'`;\n\t\t}\n\t\tdefault: {\n\t\t\tconst typeName = value === undefined ? 'undefined' : typeof value;\n\t\t\tthrow new Error(\n\t\t\t\t`nql\\`...\\`: cannot interpolate value of type \"${typeName}\" at position ${index}. ` +\n\t\t\t\t\t'Only string, number, boolean, and null are supported; ' +\n\t\t\t\t\t'for dynamic NQL fragments use the builder API (orm.select()). See issue #134.',\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Create an NQL template tag function.\n *\n * Each `${value}` in the template is escaped into a safe NQL literal before parsing.\n * Supported interpolation types: `string`, `number`, `boolean`, `null`.\n * Untrusted string input is therefore safe from NQL-syntax injection — it is always\n * wrapped in single-quotes with embedded quotes doubled (`''`).\n * For dynamic structural fragments (table names, column names, ORDER BY direction)\n * use the builder API (`orm.select()`). See issue #134 for upcoming `:param` binding.\n *\n * @param schemaDefinition - Schema definition for validation\n * @param model - ModelIR for plan execution\n * @param adapter - Optional adapter for query execution\n * @param schemaName - Optional schema name for multi-tenant queries\n * @returns NQL template tag function\n */\nexport function createNqlTag(\n\tschemaDefinition: unknown,\n\tmodel: ModelIR,\n\tadapter?: Adapter<unknown>,\n\tschemaName?: string,\n): NqlTag {\n\treturn function nql<T>(\n\t\tstrings: TemplateStringsArray,\n\t\t...values: unknown[]\n\t): NqlBuilder<T> {\n\t\t// Reconstruct the query string from template literal, escaping each\n\t\t// interpolated value into a safe NQL literal via toNqlLiteral.\n\t\t// Note: strings[0] is always defined for template literals.\n\t\tlet query: string = strings[0] ?? '';\n\t\tfor (let i = 0; i < values.length; i++) {\n\t\t\tquery += toNqlLiteral(values[i], i) + (strings[i + 1] ?? '');\n\t\t}\n\n\t\treturn new NqlBuilderImpl<T>(\n\t\t\tquery,\n\t\t\tschemaDefinition,\n\t\t\tmodel,\n\t\t\tadapter,\n\t\t\tschemaName,\n\t\t);\n\t};\n}\n\n/**\n * NQL builder implementation.\n * @internal\n */\nclass NqlBuilderImpl<T> implements NqlBuilder<T> {\n\tprivate _intent: QueryIntent | undefined;\n\tprivate readonly query: string;\n\tprivate readonly schemaDefinition: unknown;\n\tprivate readonly model: ModelIR;\n\t// biome-ignore lint/correctness/noUnusedPrivateClassMembers: Reserved for future schema-scoping support\n\tprivate readonly _schemaName: string | undefined;\n\tprivate readonly adapter: Adapter<unknown> | undefined;\n\n\tconstructor(\n\t\tquery: string,\n\t\tschemaDefinition: unknown,\n\t\tmodel: ModelIR,\n\t\tadapter: Adapter<unknown> | undefined,\n\t\tschemaName: string | undefined,\n\t) {\n\t\tthis.query = query;\n\t\tthis.schemaDefinition = schemaDefinition;\n\t\tthis.model = model;\n\t\tthis.adapter = adapter;\n\t\tthis._schemaName = schemaName;\n\t}\n\n\tprivate compile(): QueryIntent {\n\t\tif (this._intent) {\n\t\t\treturn this._intent;\n\t\t}\n\n\t\t// Extract dynamic pseudo-column keywords from model configuration\n\t\tconst compilerOptions = extractPseudoColumnKeywords(this.model);\n\n\t\t// Use integrated @dbsp/nql compiler with dynamic keywords\n\t\tconst result = nqlCompile(\n\t\t\tthis.query,\n\t\t\tthis.schemaDefinition,\n\t\t\tundefined,\n\t\t\tcompilerOptions,\n\t\t);\n\t\tif (!result.success) {\n\t\t\tconst errors =\n\t\t\t\tresult.errors?.map((e) => e.message).join(', ') ?? 'Unknown error';\n\t\t\tthrow new Error(`NQL compilation failed: ${errors}`);\n\t\t}\n\t\tif (result.ast?.mutation && !result.ast?.query) {\n\t\t\tthrow new Error(\n\t\t\t\t'INSERT/UPDATE/DELETE/UPSERT not yet supported via the nql`...` tagged template. ' +\n\t\t\t\t\t'Use orm.insert(table, data) / orm.update(table, set) / orm.delete(table) / orm.upsert(table, data) instead. ' +\n\t\t\t\t\t'Tracking: https://github.com/oorabona/db-semantic-planner/issues/113',\n\t\t\t);\n\t\t}\n\t\tif (!result.ast?.query) {\n\t\t\tthrow new Error('NQL compilation failed: no query AST produced');\n\t\t}\n\n\t\t// Type assertion: NQL imports QueryIntent from @dbsp/types (ARCH-007),\n\t\t// structurally identical to core's re-export.\n\t\tthis._intent = result.ast.query as QueryIntent;\n\t\treturn this._intent;\n\t}\n\n\ttoIntentIR(): QueryIntent {\n\t\treturn this.compile();\n\t}\n\n\tplan(): PlanReport {\n\t\tconst intent = this.compile();\n\t\treturn executePlan(intent, this.model);\n\t}\n\n\tdump(meta?: DumpMetaInput): Dump {\n\t\tconst planReport = this.plan();\n\n\t\tif (!this.adapter) {\n\t\t\treturn {\n\t\t\t\tplan: planReport,\n\t\t\t\tsql: '[No adapter - SQL not available]',\n\t\t\t\tparams: [],\n\t\t\t\t...(meta !== undefined && { meta }),\n\t\t\t};\n\t\t}\n\n\t\tconst compiled = this.adapter.compile<T>(planReport);\n\n\t\ttry {\n\t\t\treturn this.adapter.createDump(planReport, compiled, meta);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\terr instanceof Error &&\n\t\t\t\terr.message.toLowerCase().includes('not implemented')\n\t\t\t) {\n\t\t\t\t// Fallback for mock adapters that don't implement createDump\n\t\t\t\tconst base: Dump = {\n\t\t\t\t\tplan: planReport,\n\t\t\t\t\tsql: compiled.sql,\n\t\t\t\t\tparams: compiled.parameters as readonly unknown[],\n\t\t\t\t};\n\t\t\t\tif (meta !== undefined) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...base,\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\t...(meta.queryName !== undefined && {\n\t\t\t\t\t\t\t\tqueryName: meta.queryName,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(meta.correlationId !== undefined && {\n\t\t\t\t\t\t\t\tcorrelationId: meta.correlationId,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn base;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync all(): Promise<T[]> {\n\t\tif (!this.adapter) {\n\t\t\tthrow new Error(\n\t\t\t\t'Cannot execute query: no adapter configured. ' +\n\t\t\t\t\t'Pass an adapter to createOrm() or use .toIntentIR() / .plan() for debugging.',\n\t\t\t);\n\t\t}\n\n\t\tconst planReport = this.plan();\n\t\tconst compiled = this.adapter.compile<T>(planReport);\n\t\treturn this.adapter.execute(compiled);\n\t}\n\n\tasync first(): Promise<T | null> {\n\t\tconst rows = await this.all();\n\t\treturn rows[0] ?? null;\n\t}\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Extract pseudo-column keywords from model configuration.\n * Collects all configured roles and recursive keywords from all tables'\n * pseudoColumns metadata, falling back to defaults if no configuration exists.\n */\nexport function extractPseudoColumnKeywords(\n\tmodel: ModelIR,\n): NqlCompilerOptions | undefined {\n\tconst allKeywords = new Set<string>();\n\tconst recursiveKeywords = new Set<string>();\n\n\tfor (const table of model.tables.values()) {\n\t\tif (!table.pseudoColumns) continue;\n\t\tfor (const pc of table.pseudoColumns) {\n\t\t\tallKeywords.add(pc.parentRole.toLowerCase());\n\t\t\tallKeywords.add(pc.childRole.toLowerCase());\n\t\t\tallKeywords.add(pc.ascendantKeyword.toLowerCase());\n\t\t\tallKeywords.add(pc.descendantKeyword.toLowerCase());\n\t\t\trecursiveKeywords.add(pc.ascendantKeyword.toLowerCase());\n\t\t\trecursiveKeywords.add(pc.descendantKeyword.toLowerCase());\n\t\t}\n\t}\n\n\t// No pseudo-columns configured → let compiler use defaults\n\tif (allKeywords.size === 0) return undefined;\n\n\treturn {\n\t\tpseudoColumnKeywords: [...allKeywords],\n\t\trecursiveKeywords: [...recursiveKeywords],\n\t};\n}\n","/**\n * @module dx/hierarchy-helpers\n * Pure helper functions for recursive/hierarchical query support.\n */\n\nimport type { ModelIR } from '../model-ir.js';\n\n/**\n * Extract a named field from a recursive query result.\n *\n * Recursive includes (`ancestors` / `descendants`) add a dynamic property to each row.\n * This helper safely extracts that property without `as any` casts.\n *\n * @internal\n */\nexport function extractRecursiveField<T>(\n\tresult: T | null | undefined,\n\tfield: 'ancestors' | 'descendants',\n): T[] {\n\tif (result == null) return [];\n\tconst row = result as Record<string, unknown>;\n\treturn (row[field] as T[]) ?? [];\n}\n\n/**\n * Find a self-referential relation on a table that matches the desired direction.\n *\n * @param model - The model IR\n * @param table - The table name\n * @param direction - 'ancestors' (needs belongsTo/hasOne) or 'descendants' (needs hasMany)\n * @returns The matching relation or null if not found\n */\nexport function findSelfRefRelation(\n\tmodel: ModelIR,\n\ttable: string,\n\tdirection: 'ancestors' | 'descendants',\n): { name: string; type: string } | null {\n\t// Get all relations from this table\n\tconst tableRelations = model.getRelationsFrom(table);\n\tif (!tableRelations || tableRelations.length === 0) {\n\t\treturn null;\n\t}\n\n\t// Find self-referential relations that match the direction\n\tfor (const relation of tableRelations) {\n\t\t// Must be self-referential\n\t\tif (relation.source !== relation.target) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check if direction matches relation type\n\t\tif (direction === 'ancestors') {\n\t\t\t// Need belongsTo or hasOne for ancestor traversal\n\t\t\tif (relation.type === 'belongsTo' || relation.type === 'hasOne') {\n\t\t\t\treturn { name: relation.name, type: relation.type };\n\t\t\t}\n\t\t} else {\n\t\t\t// Need hasMany for descendant traversal\n\t\t\tif (relation.type === 'hasMany') {\n\t\t\t\treturn { name: relation.name, type: relation.type };\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n","/**\n * Pagination implementation extracted from QueryBuilderImpl.\n *\n * Free functions that accept a QueryBuilderImpl instance and implement the\n * paginate / cursorPaginate logic. They access only fields and methods\n * declared @internal public on QueryBuilderImpl.\n *\n * @internal\n */\n\nimport type { OrderByIntent, WhereIntent } from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport { InvalidOperationError } from './errors.js';\nimport type { QueryBuilderImpl } from './query-builder.js';\nimport type {\n\tCursorPaginatedResult,\n\tCursorPaginateOptions,\n\tPaginatedResult,\n\tPaginateOptions,\n\tSortDirection,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// Internal cursor key resolver\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the cursor key for an orderBy entry.\n * Returns null for expression-based entries without an alias (FIND-019).\n */\nfunction resolveCursorKey(orderBy: OrderByIntent): string | null {\n\tif (typeof orderBy === 'string') return orderBy;\n\tif (typeof orderBy.field === 'string') return orderBy.field;\n\tconst alias = (orderBy as { alias?: string }).alias;\n\treturn alias ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// buildCursorConditions\n// ---------------------------------------------------------------------------\n\n/**\n * Build cursor conditions for cursor pagination.\n * FIND-019: expression-based orderBy (fn(), caseWhen()) has no .field — require\n * alias or return null so the caller skips the condition gracefully.\n *\n * @internal\n */\nexport function buildCursorConditions<TResult>(\n\tbuilder: QueryBuilderImpl<TResult>,\n\tcursorValues: Record<string, unknown>,\n\tdirection: 'forward' | 'backward',\n): WhereIntent | null {\n\tif (builder.orderByIntents.length === 1) {\n\t\tconst orderBy = builder.orderByIntents[0];\n\t\tif (!orderBy) return null;\n\n\t\tconst field = resolveCursorKey(orderBy);\n\t\tif (field === null) return null;\n\n\t\tconst sortDir =\n\t\t\ttypeof orderBy === 'string'\n\t\t\t\t? 'asc'\n\t\t\t\t: ((orderBy.direction as string) ?? 'asc');\n\t\tconst cursorValue = cursorValues[field];\n\n\t\tif (cursorValue === undefined) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst isAsc =\n\t\t\tsortDir === 'asc' ? direction === 'forward' : direction === 'backward';\n\t\treturn {\n\t\t\tkind: 'comparison',\n\t\t\tfield,\n\t\t\toperator: isAsc ? 'gt' : 'lt',\n\t\t\tvalue: cursorValue,\n\t\t};\n\t}\n\n\tconst conditions: WhereIntent[] = [];\n\n\tfor (let i = 0; i < builder.orderByIntents.length; i++) {\n\t\tconst parts: WhereIntent[] = [];\n\n\t\tfor (let j = 0; j <= i; j++) {\n\t\t\tconst orderBy = builder.orderByIntents[j];\n\t\t\tif (!orderBy) continue;\n\n\t\t\tconst field = resolveCursorKey(orderBy);\n\t\t\tif (field === null) continue;\n\n\t\t\tconst sortDir =\n\t\t\t\ttypeof orderBy === 'string'\n\t\t\t\t\t? 'asc'\n\t\t\t\t\t: ((orderBy.direction as string) ?? 'asc');\n\t\t\tconst cursorValue = cursorValues[field];\n\n\t\t\tif (cursorValue === undefined) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (j < i) {\n\t\t\t\tparts.push({\n\t\t\t\t\tkind: 'comparison',\n\t\t\t\t\tfield,\n\t\t\t\t\toperator: 'eq',\n\t\t\t\t\tvalue: cursorValue,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst isAsc =\n\t\t\t\t\tsortDir === 'asc'\n\t\t\t\t\t\t? direction === 'forward'\n\t\t\t\t\t\t: direction === 'backward';\n\t\t\t\tparts.push({\n\t\t\t\t\tkind: 'comparison',\n\t\t\t\t\tfield,\n\t\t\t\t\toperator: isAsc ? 'gt' : 'lt',\n\t\t\t\t\tvalue: cursorValue,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (parts.length > 0) {\n\t\t\tconditions.push(\n\t\t\t\tparts.length === 1\n\t\t\t\t\t? (parts[0] as WhereIntent)\n\t\t\t\t\t: { kind: 'and', conditions: parts },\n\t\t\t);\n\t\t}\n\t}\n\n\tif (conditions.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst firstCondition = conditions[0];\n\treturn conditions.length === 1 && firstCondition !== undefined\n\t\t? firstCondition\n\t\t: { kind: 'or', conditions };\n}\n\n// ---------------------------------------------------------------------------\n// buildCursor\n// ---------------------------------------------------------------------------\n\n/**\n * Build cursor from a row using orderBy fields.\n * FIND-019: expression-based orderBy entries (fn(), caseWhen(), etc.) have no\n * .field string. Require an explicit alias or throw.\n *\n * @internal\n */\nexport function buildCursor<TResult>(\n\tbuilder: QueryBuilderImpl<TResult>,\n\trow: Record<string, unknown>,\n): string {\n\tconst cursorData: Record<string, unknown> = Object.create(null);\n\n\tfor (const orderBy of builder.orderByIntents) {\n\t\tif (!orderBy) continue;\n\t\tif (typeof orderBy === 'string') {\n\t\t\tcursorData[orderBy] = row[orderBy];\n\t\t} else {\n\t\t\tconst field = orderBy.field;\n\t\t\tif (typeof field === 'string') {\n\t\t\t\tcursorData[field] = row[field];\n\t\t\t} else {\n\t\t\t\tconst alias = (orderBy as { alias?: string }).alias;\n\t\t\t\tif (!alias) {\n\t\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t\t'cursorPaginate',\n\t\t\t\t\t\t'cursorPaginate requires orderBy entries with a string column name or an explicit alias. ' +\n\t\t\t\t\t\t\t'Use .orderBy(fn(...).as(\"alias\")) or .orderBy(\"column\") to enable cursor-based pagination.',\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcursorData[alias] = row[alias];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn Buffer.from(JSON.stringify(cursorData), 'utf-8').toString('base64');\n}\n\n// ---------------------------------------------------------------------------\n// paginate\n// ---------------------------------------------------------------------------\n\n/**\n * Execute offset-based pagination for a QueryBuilderImpl.\n *\n * @internal\n */\nexport async function paginate<TResult>(\n\tbuilder: QueryBuilderImpl<TResult>,\n\toptions?: PaginateOptions,\n): Promise<PaginatedResult<TResult>> {\n\tconst page = options?.page ?? 1;\n\tconst perPage = options?.perPage ?? 20;\n\tconst withCount = options?.withCount ?? true;\n\n\tif (!Number.isSafeInteger(page) || page < 1) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'paginate',\n\t\t\t'page must be a positive safe integer. Use page: 1 for the first page',\n\t\t);\n\t}\n\tif (!Number.isSafeInteger(perPage) || perPage < 1) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'paginate',\n\t\t\t'perPage must be a positive safe integer',\n\t\t);\n\t}\n\n\tconst offset = (page - 1) * perPage;\n\n\tconst paginatedBuilder = builder.clone();\n\tpaginatedBuilder.limitValue = perPage;\n\tpaginatedBuilder.offsetValue = offset;\n\n\tconst data = await paginatedBuilder.all();\n\n\tlet total: number | undefined;\n\tlet totalPages: number | undefined;\n\n\tif (withCount) {\n\t\t// FIND-018 (M-1 fix): when groupBy or explicit joins are present, compile\n\t\t// the base query as a subquery and wrap it with SELECT COUNT(*) FROM (...)\n\t\t// to always get a single scalar regardless of query shape.\n\t\t// For simple queries (no groupBy, no joins), the direct COUNT(*) path\n\t\t// is retained for efficiency.\n\t\tconst adapter = builder.getConfiguredAdapter();\n\t\tconst compileOptions: { schemaName?: string; model: ModelIR } = {\n\t\t\tmodel: builder.ctx.model,\n\t\t};\n\t\tif (builder.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = builder.ctx.schemaName;\n\t\t}\n\n\t\tconst hasGroupBy = builder.groupByFields.length > 0;\n\t\tconst hasJoins = builder.joinIntents.length > 0;\n\n\t\tif (hasGroupBy || hasJoins) {\n\t\t\tconst baseBuilder = builder.clone();\n\t\t\tbaseBuilder.limitValue = undefined;\n\t\t\tbaseBuilder.offsetValue = undefined;\n\t\t\tbaseBuilder.orderByIntents.splice(0);\n\t\t\tbaseBuilder.includes.splice(0);\n\t\t\tbaseBuilder.recursiveIncludes.splice(0);\n\t\t\tbaseBuilder.aggregates.splice(0);\n\t\t\tbaseBuilder.selectIntent = undefined;\n\n\t\t\tconst basePlan = baseBuilder.plan();\n\t\t\tconst baseCompiled = adapter.compile(basePlan, compileOptions);\n\n\t\t\tconst wrapSql = `SELECT COUNT(*) AS \"_count\" FROM (${baseCompiled.sql}) _count_subq`;\n\t\t\tconst wrapResult = (await adapter.execute({\n\t\t\t\tsql: wrapSql,\n\t\t\t\tparameters: baseCompiled.parameters,\n\t\t\t})) as Array<{ _count: string | number }>;\n\t\t\ttotal = Number(wrapResult[0]?._count ?? 0);\n\t\t} else {\n\t\t\tconst countBuilder = builder.clone() as unknown as QueryBuilderImpl<{\n\t\t\t\t_count: number;\n\t\t\t}>;\n\t\t\tcountBuilder.limitValue = undefined;\n\t\t\tcountBuilder.offsetValue = undefined;\n\t\t\tcountBuilder.orderByIntents.splice(0);\n\t\t\tcountBuilder.aggregates.splice(0, countBuilder.aggregates.length, {\n\t\t\t\tfunction: 'count',\n\t\t\t\tas: '_count',\n\t\t\t});\n\t\t\tcountBuilder.includes.splice(0);\n\t\t\tcountBuilder.recursiveIncludes.splice(0);\n\t\t\tcountBuilder.selectIntent = undefined;\n\n\t\t\tconst countResult = await countBuilder.all();\n\t\t\ttotal = Number(countResult[0]?._count ?? 0);\n\t\t}\n\t\ttotalPages = Math.ceil(total / perPage);\n\t}\n\n\tconst hasNextPage = withCount\n\t\t? page < (totalPages ?? 1)\n\t\t: data.length === perPage;\n\tconst hasPrevPage = page > 1;\n\n\treturn {\n\t\tdata,\n\t\tpagination: {\n\t\t\tpage,\n\t\t\tperPage,\n\t\t\t...(total !== undefined && { total }),\n\t\t\t...(totalPages !== undefined && { totalPages }),\n\t\t\thasNextPage,\n\t\t\thasPrevPage,\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// cursorPaginate\n// ---------------------------------------------------------------------------\n\n/**\n * Execute cursor-based pagination for a QueryBuilderImpl.\n *\n * @internal\n */\nexport async function cursorPaginate<TResult>(\n\tbuilder: QueryBuilderImpl<TResult>,\n\toptions?: CursorPaginateOptions,\n): Promise<CursorPaginatedResult<TResult>> {\n\tconst limit = options?.limit ?? 20;\n\tconst cursor = options?.cursor ?? null;\n\tconst direction = options?.direction ?? 'forward';\n\n\t// FIND-021: Validate limit is a safe non-negative integer (0 is accepted — returns empty page)\n\tif (!Number.isSafeInteger(limit) || limit < 0) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'cursorPaginate',\n\t\t\t'limit must be a non-negative safe integer',\n\t\t);\n\t}\n\n\t// Require orderBy for stable cursor pagination\n\tif (builder.orderByIntents.length === 0) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'cursorPaginate',\n\t\t\t'Cursor pagination requires an orderBy clause. Add .orderBy(\"id\") or similar before .cursorPaginate()',\n\t\t);\n\t}\n\n\t// Decode cursor if provided\n\tlet cursorValues: Record<string, unknown> | null = null;\n\tif (cursor) {\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(Buffer.from(cursor, 'base64').toString('utf-8'));\n\t\t} catch {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'cursorPaginate',\n\t\t\t\t'Invalid cursor format. Use a cursor returned from a previous cursorPaginate() call',\n\t\t\t);\n\t\t}\n\t\t// FIND-004: Validate cursor decodes to a plain object (not array/primitive)\n\t\tif (\n\t\t\ttypeof parsed !== 'object' ||\n\t\t\tparsed === null ||\n\t\t\tArray.isArray(parsed)\n\t\t) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'cursorPaginate',\n\t\t\t\t'Invalid cursor: must decode to an object',\n\t\t\t);\n\t\t}\n\t\t// Use Object.create(null)-safe iteration to avoid prototype pollution\n\t\tconst safeValues: Record<string, unknown> = Object.create(null);\n\t\tfor (const key of Object.keys(parsed)) {\n\t\t\tif (Object.hasOwn(parsed as Record<string, unknown>, key)) {\n\t\t\t\t(safeValues as Record<string, unknown>)[key] = (\n\t\t\t\t\tparsed as Record<string, unknown>\n\t\t\t\t)[key];\n\t\t\t}\n\t\t}\n\t\tcursorValues = safeValues;\n\t}\n\n\t// Build cursor conditions based on orderBy fields\n\tconst paginatedBuilder = builder.clone();\n\tif (cursorValues) {\n\t\tconst cursorConditions = buildCursorConditions(\n\t\t\tbuilder,\n\t\t\tcursorValues,\n\t\t\tdirection,\n\t\t);\n\t\tif (cursorConditions) {\n\t\t\tpaginatedBuilder.whereIntents.push(cursorConditions);\n\t\t}\n\t}\n\n\t// FIND-020: For backward pagination, invert every ORDER BY direction so the\n\t// DB returns rows immediately BEFORE the cursor. We then reverse the result\n\t// slice to restore the original ordering for the caller.\n\tif (direction === 'backward') {\n\t\tpaginatedBuilder.orderByIntents.splice(\n\t\t\t0,\n\t\t\tpaginatedBuilder.orderByIntents.length,\n\t\t\t...paginatedBuilder.orderByIntents.map((ob) => ({\n\t\t\t\t...ob,\n\t\t\t\tdirection: (ob.direction === 'asc' ? 'desc' : 'asc') as SortDirection,\n\t\t\t})),\n\t\t);\n\t}\n\n\t// Fetch one extra to determine if there's a next page\n\tpaginatedBuilder.limitValue = limit + 1;\n\n\t// Execute query\n\tconst rawResults = await paginatedBuilder.all();\n\n\tconst hasMore = rawResults.length > limit;\n\tconst sliced = hasMore ? rawResults.slice(0, limit) : rawResults;\n\n\t// For backward direction, reverse results to restore original ordering\n\tconst data = direction === 'backward' ? sliced.slice().reverse() : sliced;\n\n\tconst nextCursor =\n\t\thasMore && data.length > 0\n\t\t\t? buildCursor(builder, data[data.length - 1] as Record<string, unknown>)\n\t\t\t: null;\n\tconst prevCursor =\n\t\tdata.length > 0\n\t\t\t? buildCursor(builder, data[0] as Record<string, unknown>)\n\t\t\t: null;\n\n\treturn {\n\t\tdata,\n\t\tnextCursor,\n\t\tprevCursor:\n\t\t\tdirection === 'forward' ? (cursor ? prevCursor : null) : prevCursor,\n\t\thasNextPage: direction === 'forward' ? hasMore : cursor !== null,\n\t\thasPrevPage: direction === 'forward' ? cursor !== null : hasMore,\n\t};\n}\n","/**\n * Shared hydration utilities for json_agg include results.\n *\n * Extracted from ResultHydrator and QueryBuilderImpl to avoid duplication (DRY).\n */\nimport type { PlanReport } from '../planner.js';\n\n/**\n * Hydrate json_agg include columns in query results.\n *\n * Parses `{relation}_json` columns from json_agg subqueries into proper\n * nested objects/arrays, handles CamelCasePlugin column name transforms,\n * and unwraps to-one relations from arrays to single objects.\n */\nexport function hydrateJsonAggIncludes<T>(\n\tresults: T[],\n\tplanReport: PlanReport,\n): void {\n\t// Find all json_agg include decisions\n\tconst jsonAggDecisions = planReport.decisions.filter(\n\t\t(d) => d.type === 'include-strategy' && d.choice === 'json_agg',\n\t);\n\n\tif (jsonAggDecisions.length === 0) {\n\t\treturn;\n\t}\n\n\t// Build map of relation names -> relation type\n\t// The adapter compiler uses the canonical relation name (context.relation) for\n\t// the JSON column alias (e.g., 'author_posts' → 'author_posts_json').\n\t// We also track the includeAlias (user-provided name) for fallback matching.\n\t// STRAT-SIMPLIFY: Track to-one relations for [0] extraction\n\tconst relationInfo = new Map<\n\t\tstring,\n\t\t{ isToOne: boolean; includeAlias?: string; canonicalName?: string }\n\t>();\n\tfor (const decision of jsonAggDecisions) {\n\t\tconst canonicalName = decision.context?.relation;\n\t\tconst includeAlias = decision.context?.includeAlias;\n\t\tconst relationType = decision.context?.relationType;\n\t\tconst isToOne = relationType === 'belongsTo' || relationType === 'hasOne';\n\n\t\t// Primary key: canonical relation name (matches adapter SQL alias)\n\t\tif (typeof canonicalName === 'string') {\n\t\t\trelationInfo.set(canonicalName, {\n\t\t\t\tisToOne,\n\t\t\t\tincludeAlias:\n\t\t\t\t\ttypeof includeAlias === 'string' ? includeAlias : canonicalName,\n\t\t\t\tcanonicalName,\n\t\t\t});\n\t\t} else if (typeof includeAlias === 'string') {\n\t\t\t// Fallback: use includeAlias if no canonical name\n\t\t\trelationInfo.set(includeAlias, { isToOne, includeAlias });\n\t\t}\n\t}\n\n\tif (relationInfo.size === 0) {\n\t\treturn;\n\t}\n\n\t// Process each result row\n\tfor (const row of results) {\n\t\tif (typeof row !== 'object' || row === null) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst record = row as Record<string, unknown>;\n\n\t\tfor (const [relationName, info] of relationInfo) {\n\t\t\t// The adapter generates the JSON column alias from the canonical relation name\n\t\t\t// (e.g., 'author_posts' → 'author_posts_json'). The naming plugin may\n\t\t\t// transform it to camelCase (e.g., 'authorPostsJson').\n\t\t\t// We try both the canonical name and the includeAlias as base names.\n\t\t\tconst candidates = [relationName];\n\t\t\tif (info.includeAlias && info.includeAlias !== relationName) {\n\t\t\t\tcandidates.push(info.includeAlias);\n\t\t\t}\n\n\t\t\tlet actualColumnName: string | null = null;\n\t\t\tfor (const baseName of candidates) {\n\t\t\t\tconst snakeJson = `${baseName}_json`;\n\t\t\t\tconst camelJson = snakeJson.replace(/_([a-z])/g, (_, c: string) =>\n\t\t\t\t\tc.toUpperCase(),\n\t\t\t\t);\n\t\t\t\tif (snakeJson in record) {\n\t\t\t\t\tactualColumnName = snakeJson;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (camelJson in record) {\n\t\t\t\t\tactualColumnName = camelJson;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (actualColumnName) {\n\t\t\t\tconst jsonValue = record[actualColumnName];\n\n\t\t\t\t// Parse JSON if it's a string\n\t\t\t\tlet parsed: unknown;\n\t\t\t\tif (typeof jsonValue === 'string') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tparsed = JSON.parse(jsonValue);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tparsed = info.isToOne ? null : [];\n\t\t\t\t\t}\n\t\t\t\t} else if (Array.isArray(jsonValue)) {\n\t\t\t\t\tparsed = jsonValue;\n\t\t\t\t} else if (jsonValue === null || jsonValue === undefined) {\n\t\t\t\t\tparsed = info.isToOne ? null : [];\n\t\t\t\t} else {\n\t\t\t\t\tparsed = jsonValue;\n\t\t\t\t}\n\n\t\t\t\t// STRAT-SIMPLIFY: For to-one relations, unwrap array to single object\n\t\t\t\tif (info.isToOne && Array.isArray(parsed)) {\n\t\t\t\t\tparsed = parsed.length > 0 ? parsed[0] : null;\n\t\t\t\t}\n\n\t\t\t\t// Set property using includeAlias (user-facing name, e.g., 'posts')\n\t\t\t\t// and remove the raw JSON column\n\t\t\t\tconst outputKey = info.includeAlias ?? relationName;\n\t\t\t\trecord[outputKey] = parsed;\n\t\t\t\tdelete record[actualColumnName];\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * ResultHydrator - Handles result hydration and recursive include processing.\n *\n * DX-103: Extracted from QueryBuilderImpl to subquery hydration logic\n * from intent building and query execution.\n *\n * @module result-hydrator\n */\n\nimport type { Mutable } from '@dbsp/types/internal';\nimport type {\n\tAdapter,\n\tCompileOptions,\n\tSubqueryIncludeInfo,\n} from '../adapter.js';\nimport type { RecursiveIntent, WhereIntent } from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanReport } from '../planner.js';\nimport { planRecursive } from '../planner.js';\nimport { RelationNotFoundError } from './errors.js';\nimport { hydrateJsonAggIncludes as hydrateJsonAggIncludesShared } from './hydration-utils.js';\nimport type { RecursiveIncludeConfig } from './intent-builder.js';\n\n// ============================================================================\n// Helper Types\n// ============================================================================\n\n/** A database result row — typed loosely since row shapes are dynamic. */\ntype ResultRow = Record<string, unknown>;\n\n/**\n * Options for hydrating includes.\n * Requires model (unlike CompileOptions where it's optional).\n */\nexport type HydrateOptions = Omit<CompileOptions, 'model'> & { model: ModelIR };\n\n// ============================================================================\n// ResultHydrator\n// ============================================================================\n\n/**\n * Handles result hydration including:\n * - Subquery include hydration for hasMany relations\n * - Recursive include processing via CTEs\n * - Building nested hierarchies from flat results\n *\n * @typeParam TResult - The expected result type\n */\n\n/**\n * NUL byte (U+0000) used as the composite-key separator. Kept as a named\n * constant because literal control characters are invisible in diffs and\n * can be corrupted by editor normalization.\n */\nconst COMPOSITE_KEY_SEP = '\\0';\n\nexport class ResultHydrator<TResult = unknown> {\n\tprivate readonly model: ModelIR;\n\tprivate readonly from: string;\n\tprivate readonly schemaName: string | undefined;\n\n\tconstructor(model: ModelIR, from: string, schemaName?: string) {\n\t\tthis.model = model;\n\t\tthis.from = from;\n\t\tthis.schemaName = schemaName;\n\t}\n\n\t/**\n\t * Hydrate subquery includes (hasMany relations) into main results.\n\t */\n\tasync hydrateIncludes(\n\t\tresults: TResult[],\n\t\tsubqueryIncludes: readonly SubqueryIncludeInfo[],\n\t\tadapter: Adapter,\n\t\tcompileOptions: HydrateOptions,\n\t): Promise<void> {\n\t\tif (results.length === 0) return;\n\n\t\tfor (const includeInfo of subqueryIncludes) {\n\t\t\t// Extract parent IDs from results using sourceKey.\n\t\t\t// PERF (FIND-054): single-pass for-loop avoids the intermediate array\n\t\t\t// that .map().filter() allocates (2 passes + length-N temp array).\n\t\t\tconst parentIds: unknown[] = [];\n\t\t\tfor (const r of results) {\n\t\t\t\tconst id = this.extractKeyValue(\n\t\t\t\t\tr as Record<string, unknown>,\n\t\t\t\t\tincludeInfo.sourceKey,\n\t\t\t\t);\n\t\t\t\tif (id !== undefined && id !== null) parentIds.push(id);\n\t\t\t}\n\n\t\t\tif (parentIds.length === 0) continue;\n\n\t\t\t// Compile and execute the include query\n\t\t\tconst includeQuery = adapter.compileSubqueryInclude(\n\t\t\t\tincludeInfo,\n\t\t\t\tparentIds,\n\t\t\t\tcompileOptions,\n\t\t\t);\n\t\t\tconst childResults = await adapter.execute(includeQuery);\n\n\t\t\t// Group children by foreign key\n\t\t\tconst childrenByParentId = new Map<unknown, unknown[]>();\n\t\t\tfor (const child of childResults) {\n\t\t\t\tconst parentId = this.extractKeyValue(\n\t\t\t\t\tchild as Record<string, unknown>,\n\t\t\t\t\tincludeInfo.foreignKey,\n\t\t\t\t);\n\t\t\t\tif (parentId !== undefined) {\n\t\t\t\t\tconst existing = childrenByParentId.get(parentId);\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\texisting.push(child);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tchildrenByParentId.set(parentId, [child]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Attach children to parent objects\n\t\t\t// For to-one relations (belongsTo/hasOne), unwrap to single object\n\t\t\tconst isToOne =\n\t\t\t\tincludeInfo.relationType === 'belongsTo' ||\n\t\t\t\tincludeInfo.relationType === 'hasOne';\n\t\t\tfor (const result of results) {\n\t\t\t\tconst parentId = this.extractKeyValue(\n\t\t\t\t\tresult as Record<string, unknown>,\n\t\t\t\t\tincludeInfo.sourceKey,\n\t\t\t\t);\n\t\t\t\tconst children = childrenByParentId.get(parentId) ?? [];\n\t\t\t\t(result as Record<string, unknown>)[includeInfo.relationName] = isToOne\n\t\t\t\t\t? (children[0] ?? null)\n\t\t\t\t\t: children;\n\t\t\t}\n\n\t\t\t// Process nested includes recursively if present\n\t\t\tif (includeInfo.nestedIncludes && includeInfo.nestedIncludes.length > 0) {\n\t\t\t\t// Flatten all children for nested hydration.\n\t\t\t\t// PERF (FIND-055): avoid Array.from().flat() which allocates an array-of-arrays\n\t\t\t\t// then flattens it; a double for-loop uses a single allocation.\n\t\t\t\tconst allChildren: Record<string, unknown>[] = [];\n\t\t\t\tfor (const arr of childrenByParentId.values()) {\n\t\t\t\t\tfor (const item of arr)\n\t\t\t\t\t\tallChildren.push(item as Record<string, unknown>);\n\t\t\t\t}\n\t\t\t\tif (allChildren.length > 0) {\n\t\t\t\t\tawait this.hydrateIncludes(\n\t\t\t\t\t\tallChildren as TResult[],\n\t\t\t\t\t\tincludeInfo.nestedIncludes,\n\t\t\t\t\t\tadapter,\n\t\t\t\t\t\tcompileOptions,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Hydrate JOIN includes by grouping dot-prefixed columns into nested objects.\n\t * E2E-004: JOIN strategy for to-one relations returns columns like \"author.id\", \"author.name\".\n\t */\n\thydrateJoinIncludes(results: TResult[], planReport: PlanReport): void {\n\t\t// Find all JOIN include decisions (to-one relations)\n\t\tconst joinDecisions = planReport.decisions.filter(\n\t\t\t(d) => d.type === 'include-strategy' && d.choice === 'join',\n\t\t);\n\n\t\tif (joinDecisions.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Get relation names from decisions\n\t\tconst joinInfos = joinDecisions\n\t\t\t.map((d) => d.context?.relation)\n\t\t\t.filter((r): r is string => typeof r === 'string')\n\t\t\t.map((relation) => ({ relation, prefix: `${relation}.` }));\n\n\t\tif (joinInfos.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// PERF (FIND-050): build the key index ONCE per relation from the first valid row,\n\t\t// rather than scanning Object.keys() on every row × every relation (O(N×R×K)).\n\t\t// Assumption: all rows share the same projection (fixed SELECT list) — safe for\n\t\t// SQL queries where the column set is determined at compile time.\n\t\t// Guard: if a key from the cache is absent on a given row, it is silently skipped.\n\t\ttype JoinInfo = {\n\t\t\trelation: string;\n\t\t\tprefix: string;\n\t\t\tcachedKeys: string[] | null;\n\t\t};\n\t\tconst joinInfosWithCache: JoinInfo[] = joinInfos.map((info) => ({\n\t\t\t...info,\n\t\t\tcachedKeys: null,\n\t\t}));\n\n\t\tif (results.length > 0) {\n\t\t\t// Find first non-null row to build the key cache\n\t\t\tconst firstRow = results.find(\n\t\t\t\t(r): r is TResult & object => typeof r === 'object' && r !== null,\n\t\t\t);\n\t\t\tif (firstRow) {\n\t\t\t\tconst firstRecord = firstRow as Record<string, unknown>;\n\t\t\t\tconst allKeys = Object.keys(firstRecord);\n\t\t\t\tfor (const info of joinInfosWithCache) {\n\t\t\t\t\tinfo.cachedKeys = allKeys.filter((k) => k.startsWith(info.prefix));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Process each result row\n\t\tfor (const row of results) {\n\t\t\tif (typeof row !== 'object' || row === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst record = row as Record<string, unknown>;\n\n\t\t\tfor (const info of joinInfosWithCache) {\n\t\t\t\t// Use cached keys; fall back to live scan if cache is empty (heterogeneous rows)\n\t\t\t\tconst keys =\n\t\t\t\t\tinfo.cachedKeys && info.cachedKeys.length > 0\n\t\t\t\t\t\t? info.cachedKeys\n\t\t\t\t\t\t: Object.keys(record).filter((k) => k.startsWith(info.prefix));\n\n\t\t\t\tif (keys.length === 0) continue;\n\n\t\t\t\tconst nestedObj: Record<string, unknown> = {};\n\t\t\t\tlet allNull = true;\n\n\t\t\t\t// Build nested object and delete prefixed keys in a single pass —\n\t\t\t\t// no keysToDelete array needed.\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\tconst val = record[key];\n\t\t\t\t\tif (val !== undefined) {\n\t\t\t\t\t\t// Guard: key present on this row\n\t\t\t\t\t\tnestedObj[key.slice(info.prefix.length)] = val;\n\t\t\t\t\t\tdelete record[key];\n\t\t\t\t\t\tif (val !== null) allNull = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If all values are null, the related entity doesn't exist (LEFT JOIN returned no match)\n\t\t\t\trecord[info.relation] = allNull ? null : nestedObj;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Hydrate json_agg includes by parsing JSON columns and renaming them.\n\t * E2E-004: json_agg strategy returns data as JSON string in *_json columns.\n\t * STRAT-SIMPLIFY: For to-one relations (belongsTo/hasOne), unwrap array to single object.\n\t */\n\thydrateJsonAggIncludes(results: TResult[], planReport: PlanReport): void {\n\t\thydrateJsonAggIncludesShared(results, planReport);\n\t}\n\n\t/**\n\t * Process recursive includes via CTEs.\n\t */\n\tasync processRecursiveIncludes(\n\t\tresults: unknown[],\n\t\trecursiveIncludes: readonly RecursiveIncludeConfig[],\n\t\tadapter: Adapter,\n\t): Promise<void> {\n\t\tif (results.length === 0) return;\n\n\t\tfor (const config of recursiveIncludes) {\n\t\t\tawait this.processOneRecursiveInclude(\n\t\t\t\tresults as ResultRow[],\n\t\t\t\tconfig,\n\t\t\t\tadapter,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Process a single recursive include.\n\t */\n\tprivate async processOneRecursiveInclude(\n\t\tresults: ResultRow[],\n\t\tconfig: RecursiveIncludeConfig,\n\t\tadapter: Adapter,\n\t): Promise<void> {\n\t\tconst { relation, options } = config;\n\t\tconst {\n\t\t\tdirection,\n\t\t\tflat = false,\n\t\t\tomitSelf = false,\n\t\t\tmaxDepth = 100,\n\t\t\tincludeDepth = false,\n\t\t} = options;\n\n\t\t// Get relation metadata\n\t\tconst qualifiedName = `${this.from}.${relation}`;\n\t\tconst relationMeta = this.model.getRelation(qualifiedName);\n\t\tif (!relationMeta) {\n\t\t\t// Get available relations for helpful error message\n\t\t\tconst tableRelations = this.model.getRelationsFrom(this.from);\n\t\t\tconst available = tableRelations?.map((r) => r.name) ?? [];\n\t\t\tthrow new RelationNotFoundError({\n\t\t\t\ttable: this.from,\n\t\t\t\trequested: relation,\n\t\t\t\tavailable,\n\t\t\t});\n\t\t}\n\n\t\t// Determine the foreign key column from relation metadata\n\t\tconst fkColumn = this.getForeignKeyColumn(relationMeta.foreignKey);\n\n\t\t// Collect IDs from the main results (primary key values)\n\t\t// For ancestors: we start from the record's own ID and traverse up via parent\n\t\t// For descendants: we start from the record's own ID and traverse down via children\n\t\tconst startIds = results\n\t\t\t.map((r) => r.id as unknown)\n\t\t\t.filter((id) => id !== undefined && id !== null);\n\n\t\tif (startIds.length === 0) return;\n\n\t\t// Build RecursiveIntent\n\t\tconst cteName = `_recursive_${relation}_${direction}`;\n\t\tconst recursiveIntent = this.buildRecursiveIntent(\n\t\t\tcteName,\n\t\t\trelationMeta,\n\t\t\tstartIds,\n\t\t\tdirection,\n\t\t\tmaxDepth,\n\t\t\tincludeDepth,\n\t\t);\n\n\t\t// Plan and compile the recursive query\n\t\tconst report = planRecursive(recursiveIntent, this.model);\n\n\t\t// Build compile options with exactOptionalPropertyTypes compliance\n\t\tconst compileOptions: { schemaName?: string } = {};\n\t\tif (this.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.schemaName;\n\t\t}\n\n\t\tconst compiledRecursive = adapter.compileRecursive(\n\t\t\treport,\n\t\t\tthis.model,\n\t\t\tcompileOptions,\n\t\t);\n\n\t\t// Execute\n\t\tconst recursiveRows = (await adapter.execute(compiledRecursive)) as Record<\n\t\t\tstring,\n\t\t\tunknown\n\t\t>[];\n\n\t\t// Merge results back into main results\n\t\tthis.mergeRecursiveResults(\n\t\t\tresults,\n\t\t\trecursiveRows,\n\t\t\trelation,\n\t\t\tdirection,\n\t\t\tfkColumn,\n\t\t\tflat,\n\t\t\tomitSelf,\n\t\t);\n\t}\n\n\t/**\n\t * Build a RecursiveIntent for CTE execution.\n\t */\n\tprivate buildRecursiveIntent(\n\t\tcteName: string,\n\t\trelationMeta: ReturnType<ModelIR['getRelation']> & object,\n\t\tstartIds: unknown[],\n\t\tdirection: 'ancestors' | 'descendants',\n\t\tmaxDepth: number,\n\t\tincludeDepth: boolean,\n\t): RecursiveIntent {\n\t\tconst { source, foreignKey } = relationMeta;\n\n\t\t// Get the foreign key as a string (use first element if array)\n\t\tconst fkColumn = this.getForeignKeyColumn(foreignKey);\n\n\t\t// For self-referential relations:\n\t\t// - ancestors: traverse via parent (belongsTo) - follow foreignKey to parent\n\t\t// - descendants: traverse via children (hasMany) - find rows where foreignKey = our id\n\n\t\t// Build the start WHERE clause to filter by the starting IDs\n\t\tconst startWhere: WhereIntent =\n\t\t\tstartIds.length === 1\n\t\t\t\t? {\n\t\t\t\t\t\tkind: 'comparison',\n\t\t\t\t\t\tfield: 'id',\n\t\t\t\t\t\toperator: 'eq',\n\t\t\t\t\t\tvalue: startIds[0],\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tkind: 'in',\n\t\t\t\t\t\tfield: 'id',\n\t\t\t\t\t\tvalues: startIds as (string | number | boolean)[],\n\t\t\t\t\t};\n\n\t\t// Build traversal config based on direction\n\t\tconst traversal = this.buildTraversalConfig(source, fkColumn, direction);\n\n\t\t// Build the intent\n\t\tconst intent: Mutable<RecursiveIntent> = {\n\t\t\ttype: 'recursive',\n\t\t\tcteName,\n\t\t\tstart: {\n\t\t\t\tfrom: source,\n\t\t\t\tnodeIdExpr: { kind: 'column', name: 'id' },\n\t\t\t\twhere: startWhere,\n\t\t\t},\n\t\t\ttraversal,\n\t\t\tmaxDepth,\n\t\t};\n\n\t\t// Add depth tracking if requested\n\t\tif (includeDepth) {\n\t\t\tintent.track = { depth: {} };\n\t\t}\n\n\t\treturn intent as RecursiveIntent;\n\t}\n\n\t/**\n\t * Get the foreign key column name from relation metadata.\n\t */\n\tprivate getForeignKeyColumn(\n\t\tforeignKey: string | readonly string[] | undefined,\n\t): string {\n\t\tif (!foreignKey) {\n\t\t\treturn 'parent_id'; // Default convention for self-referential\n\t\t}\n\t\tif (typeof foreignKey === 'string') {\n\t\t\treturn foreignKey;\n\t\t}\n\t\t// It's a readonly array - use first column for composite FK\n\t\tconst first = foreignKey[0];\n\t\treturn first ?? 'parent_id'; // Fallback for empty array\n\t}\n\n\t/**\n\t * Build traversal config for recursive CTE.\n\t */\n\tprivate buildTraversalConfig(\n\t\tnodeTable: string,\n\t\tparentIdColumn: string,\n\t\tdirection: 'ancestors' | 'descendants',\n\t): RecursiveIntent['traversal'] {\n\t\t// For self-referential adjacency list:\n\t\t// - ancestors: currentRow.foreignKey = nextRow.id (follow parent pointer)\n\t\t// - descendants: currentRow.id = nextRow.foreignKey (find children)\n\t\treturn {\n\t\t\tkind: 'adjacency',\n\t\t\tnodeTable,\n\t\t\tnodeId: 'id',\n\t\t\tparentId: parentIdColumn,\n\t\t\tdirection,\n\t\t};\n\t}\n\n\t/**\n\t * Merge recursive results back into main results.\n\t */\n\tprivate mergeRecursiveResults(\n\t\tresults: ResultRow[],\n\t\trecursiveRows: ResultRow[],\n\t\trelation: string,\n\t\tdirection: 'ancestors' | 'descendants',\n\t\tforeignKey: string,\n\t\tflat: boolean,\n\t\tomitSelf: boolean,\n\t): void {\n\t\t// Build a map from start ID to recursive results\n\t\tconst resultsByStartId = new Map<unknown, ResultRow[]>();\n\n\t\tfor (const row of recursiveRows) {\n\t\t\t// The recursive CTE returns rows with a _start_id or similar marker\n\t\t\t// For now, we group by the root ID that started the traversal\n\t\t\tconst startId = row._root_id ?? row.id;\n\t\t\tconst existing = resultsByStartId.get(startId) ?? [];\n\n\t\t\t// Apply omitSelf filter\n\t\t\tif (omitSelf && row.depth === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\texisting.push(row);\n\t\t\tresultsByStartId.set(startId, existing);\n\t\t}\n\n\t\t// Determine output property name based on direction\n\t\tconst outputProperty =\n\t\t\tdirection === 'ancestors'\n\t\t\t\t? relation === 'parent'\n\t\t\t\t\t? 'ancestors'\n\t\t\t\t\t: `${relation}_ancestors`\n\t\t\t\t: relation === 'children'\n\t\t\t\t\t? 'descendants'\n\t\t\t\t\t: `${relation}_descendants`;\n\n\t\t// Attach to main results\n\t\tfor (const result of results) {\n\t\t\tconst id = result.id as unknown;\n\t\t\tconst recursiveData = resultsByStartId.get(id) ?? [];\n\n\t\t\tif (flat) {\n\t\t\t\t// Flat: array of all results\n\t\t\t\tresult[outputProperty] = recursiveData;\n\t\t\t} else {\n\t\t\t\t// Nested: build tree structure\n\t\t\t\tresult[outputProperty] = this.buildNestedHierarchy(\n\t\t\t\t\trecursiveData,\n\t\t\t\t\tdirection,\n\t\t\t\t\tforeignKey,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Build nested hierarchy from flat recursive results.\n\t */\n\tprivate buildNestedHierarchy(\n\t\trows: ResultRow[],\n\t\tdirection: 'ancestors' | 'descendants',\n\t\tforeignKey: string,\n\t): ResultRow | ResultRow[] | null {\n\t\tif (rows.length === 0) return direction === 'ancestors' ? null : [];\n\n\t\t// Sort by depth\n\t\tconst sorted = [...rows].sort(\n\t\t\t(a, b) => ((a.depth as number) ?? 0) - ((b.depth as number) ?? 0),\n\t\t);\n\n\t\tif (direction === 'ancestors') {\n\t\t\t// For ancestors, build a chain: self -> parent -> grandparent\n\t\t\t// Return the immediate parent with nested ancestors\n\t\t\tlet current = null;\n\t\t\tfor (let i = sorted.length - 1; i >= 0; i--) {\n\t\t\t\tconst row = sorted[i];\n\t\t\t\tconst node = { ...row };\n\t\t\t\tif (current !== null) {\n\t\t\t\t\tnode[direction === 'ancestors' ? 'parent' : 'children'] = current;\n\t\t\t\t}\n\t\t\t\tcurrent = node;\n\t\t\t}\n\t\t\treturn current;\n\t\t}\n\n\t\t// For descendants, build a tree structure\n\t\tconst nodeMap = new Map<unknown, ResultRow>();\n\t\tconst roots: ResultRow[] = [];\n\n\t\tfor (const row of sorted) {\n\t\t\tconst node = { ...row, children: [] };\n\t\t\tnodeMap.set(row.id, node);\n\n\t\t\tconst parentId = row[foreignKey] as unknown;\n\t\t\tif (parentId !== null && parentId !== undefined) {\n\t\t\t\tconst parent = nodeMap.get(parentId);\n\t\t\t\tif (parent) {\n\t\t\t\t\t(parent.children as ResultRow[]).push(node);\n\t\t\t\t} else {\n\t\t\t\t\troots.push(node);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\troots.push(node);\n\t\t\t}\n\t\t}\n\n\t\treturn roots;\n\t}\n\n\t/**\n\t * Extract a key value from an object, handling composite keys.\n\t *\n\t * Fast path: NUL-byte separator for the common case of string/number PKs\n\t * (~5× faster than JSON.stringify). Fallback: if any serialized part\n\t * contains a NUL byte (e.g. bytea PKs stored as strings), two distinct\n\t * keys could collide under the fast path — use JSON.stringify in that\n\t * case (slower but collision-safe for any value content).\n\t */\n\tprivate extractKeyValue(\n\t\tobj: Record<string, unknown>,\n\t\tkey: string | readonly string[],\n\t): unknown {\n\t\tif (typeof key === 'string') {\n\t\t\treturn obj[key];\n\t\t}\n\t\t// Composite key: build a string key for Map grouping.\n\t\tconst values = key.map((k) => obj[k]);\n\t\t// Return undefined if any component is missing\n\t\tif (values.some((v) => v === undefined || v === null)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst parts = values.map((v) => String(v));\n\t\tif (parts.some((p) => p.includes(COMPOSITE_KEY_SEP))) {\n\t\t\t// Collision-safe fallback — slower but correct for any value content.\n\t\t\t// Stringify `parts` (already normalized to strings via String(v))\n\t\t\t// rather than `values` because JSON.stringify throws on bigint,\n\t\t\t// and composite PKs may legitimately contain bigint values.\n\t\t\treturn JSON.stringify(parts);\n\t\t}\n\t\treturn parts.join(COMPOSITE_KEY_SEP);\n\t}\n}\n","/**\n * @fileoverview SetOperationBuilder — fluent API for UNION / INTERSECT / EXCEPT.\n *\n * Returned by `.union()`, `.unionAll()`, `.intersect()`, `.except()` on QueryBuilder.\n * Stores a SetOperationIntent tree and provides dump() + execute helpers.\n *\n * Architecture note: SQL compilation is delegated to the adapter via\n * `adapter.compileSetOperation()` so that `@dbsp/core` remains DB-agnostic.\n */\n\nimport type { Adapter, Dump, DumpMeta } from '../adapter.js';\nimport type {\n\tQueryIntent,\n\tSetOperationIntent,\n\tSetOperationType,\n} from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport { ExecutionError } from './errors.js';\nimport type { QueryBuilder } from './types.js';\n\n// ============================================================================\n// Public interface\n// ============================================================================\n\n/**\n * Fluent builder for set operations (UNION / INTERSECT / EXCEPT).\n *\n * @typeParam TResult - Result row type\n *\n * @example\n * ```typescript\n * const q1 = orm.select('employees').where(eq('active', true));\n * const q2 = orm.select('contractors').where(eq('active', true));\n *\n * // UNION (deduplicates rows)\n * const dump = q1.union(q2).dump();\n *\n * // UNION ALL (keeps duplicates)\n * const rows = await q1.unionAll(q2).all();\n *\n * // Chain: (q1 UNION q2) INTERSECT q3\n * const nested = q1.union(q2).intersect(q3);\n * ```\n */\nexport interface SetOperationBuilder<TResult = unknown> {\n\t/** Combine via UNION (deduplicates rows). */\n\tunion(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Combine via UNION ALL (keeps duplicates). */\n\tunionAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Combine via INTERSECT (rows in both). */\n\tintersect(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Combine via INTERSECT ALL (rows in both, with duplicates). */\n\tintersectAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Combine via EXCEPT (rows in left but not right). */\n\texcept(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Combine via EXCEPT ALL (rows in left but not right, with duplicates). */\n\texceptAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Compile to SQL and return a Dump (no execution). Requires adapter. */\n\tdump(): Dump;\n\n\t/** Execute and return all rows. Requires adapter. */\n\tall(): Promise<TResult[]>;\n\n\t/** Execute and return first row. Requires adapter. */\n\tfirst(): Promise<TResult | undefined>;\n\n\t/** The underlying SetOperationIntent (for inspection / testing). */\n\treadonly intent: SetOperationIntent;\n}\n\n// ============================================================================\n// Builder context interface\n// ============================================================================\n\n/** Minimal interface to extract a QueryIntent from a builder. @internal */\nexport interface QueryIntentSource {\n\tbuildIntent(): QueryIntent;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/** @internal */\nexport class SetOperationBuilderImpl<TResult = unknown>\n\timplements SetOperationBuilder<TResult>\n{\n\treadonly intent: SetOperationIntent;\n\tprivate readonly model: ModelIR;\n\tprivate readonly adapter: Adapter | undefined;\n\tprivate readonly schemaName: string | undefined;\n\n\tconstructor(\n\t\tintent: SetOperationIntent,\n\t\tmodel: ModelIR,\n\t\tadapter?: Adapter,\n\t\tschemaName?: string,\n\t) {\n\t\tthis.intent = intent;\n\t\tthis.model = model;\n\t\tthis.adapter = adapter;\n\t\tthis.schemaName = schemaName;\n\t}\n\n\tunion(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('union', false, other);\n\t}\n\n\tunionAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('union', true, other);\n\t}\n\n\tintersect(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('intersect', false, other);\n\t}\n\n\tintersectAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('intersect', true, other);\n\t}\n\n\texcept(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('except', false, other);\n\t}\n\n\texceptAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('except', true, other);\n\t}\n\n\tprivate combine(\n\t\top: SetOperationType,\n\t\tall: boolean,\n\t\tother: QueryBuilder<TResult>,\n\t): SetOperationBuilder<TResult> {\n\t\tconst rightIntent = (other as unknown as QueryIntentSource).buildIntent();\n\t\tconst newIntent: SetOperationIntent = {\n\t\t\tkind: 'setOperation',\n\t\t\top,\n\t\t\tall,\n\t\t\tleft: this.intent,\n\t\t\tright: rightIntent,\n\t\t};\n\t\treturn new SetOperationBuilderImpl<TResult>(\n\t\t\tnewIntent,\n\t\t\tthis.model,\n\t\t\tthis.adapter,\n\t\t\tthis.schemaName,\n\t\t);\n\t}\n\n\tdump(): Dump {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst compiled = adapter.compileSetOperation(this.intent, this.model);\n\t\t// Set operations bypass the semantic planner — no PlanReport is produced.\n\t\t// compiledAt is always included so observability hooks that read\n\t\t// dump.meta?.compiledAt receive a consistent shape regardless of query type.\n\t\tconst meta: DumpMeta = {\n\t\t\tcompiledAt: new Date(),\n\t\t\t...(this.schemaName !== undefined ? { schema: this.schemaName } : {}),\n\t\t};\n\t\treturn {\n\t\t\tsql: compiled.sql,\n\t\t\tparams: compiled.parameters,\n\t\t\tmeta,\n\t\t};\n\t}\n\n\tasync all(): Promise<TResult[]> {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst compiled = adapter.compileSetOperation(this.intent, this.model);\n\t\treturn adapter.execute(compiled) as Promise<TResult[]>;\n\t}\n\n\tasync first(): Promise<TResult | undefined> {\n\t\tconst rows = await this.all();\n\t\treturn rows[0];\n\t}\n\n\tprivate requireAdapter(): Adapter {\n\t\tif (!this.adapter) {\n\t\t\tthrow new ExecutionError({\n\t\t\t\toperation: 'set operation execution',\n\t\t\t\treason: 'Adapter not configured',\n\t\t\t\tfix: 'Pass an adapter to createOrm({ adapter: yourAdapter })',\n\t\t\t});\n\t\t}\n\t\treturn this.adapter;\n\t}\n}\n\n// ============================================================================\n// Factory helper\n// ============================================================================\n\n/**\n * Build a SetOperationIntent from two query intent sources.\n * @internal\n */\nexport function buildSetOperationIntent(\n\top: SetOperationType,\n\tall: boolean,\n\tleft: QueryIntentSource,\n\tright: QueryIntentSource,\n): SetOperationIntent {\n\treturn {\n\t\tkind: 'setOperation',\n\t\top,\n\t\tall,\n\t\tleft: left.buildIntent(),\n\t\tright: right.buildIntent(),\n\t};\n}\n","/**\n * Stream implementation extracted from QueryBuilderImpl.\n *\n * Free function that accepts a QueryBuilderImpl instance and implements the\n * stream() logic. It accesses only fields and methods declared\n * @internal public on QueryBuilderImpl.\n *\n * @internal\n */\n\nimport type { Dump } from '../adapter.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanOptions } from '../planner.js';\nimport type { QueryHookContext } from './hooks.js';\nimport { hasHooks, runBeforeQueryHooks, runOnErrorHooks } from './hooks.js';\nimport type { QueryBuilderImpl } from './query-builder.js';\nimport type { StreamOptions } from './types.js';\n\n/**\n * Create a lazy AsyncIterableIterator for streaming query results.\n *\n * Extracted from QueryBuilderImpl.stream(). All hook semantics, lazy\n * compilation, and onStart callback behaviour are preserved identically.\n *\n * @internal\n */\nexport function stream<TResult>(\n\tbuilder: QueryBuilderImpl<TResult>,\n\toptions?: StreamOptions,\n): AsyncIterableIterator<TResult> {\n\tconst adapter = builder.getConfiguredAdapter();\n\n\t// Only pass chunkSize to adapter; onStart is handled in the wrapper\n\tconst adapterOptions =\n\t\toptions?.chunkSize !== undefined\n\t\t\t? { chunkSize: options.chunkSize }\n\t\t\t: undefined;\n\n\t// E17b: Fire beforeQuery hook with isStreaming=true (afterQuery does NOT fire for streams)\n\tconst hookStore = builder.ctx.hookStore;\n\tconst onHookError = builder.ctx.onHookError;\n\tconst table = builder.from;\n\tconst schemaName = builder.ctx.schemaName;\n\tconst txFlag = builder.ctx.inTransaction;\n\n\t// Capture builder references needed inside the lazy iterator closure.\n\t// These are captured once to avoid re-reading mutable builder state on\n\t// every next() call (the builder could theoretically be modified between\n\t// iterator creation and first consumption).\n\tconst onStartCallback = options?.onStart;\n\n\t// FIND-017: dumpResult (planning + compilation) MUST happen AFTER\n\t// beforeQuery hooks run, because hooks can modify the intent (e.g. inject\n\t// a tenant WHERE clause). Moving compilation inside the lazy iterator's\n\t// first-next guard ensures hook changes are reflected in the executed SQL.\n\tlet compiledQuery: { sql: string; parameters: readonly unknown[] } | null =\n\t\tnull;\n\tlet capturedDump: Dump | null = null;\n\tlet adapterIterator: AsyncIterableIterator<TResult> | null = null;\n\tlet onStartCalled = false;\n\tlet hooksFired = false;\n\n\tconst lazyIterator: AsyncIterableIterator<TResult> = {\n\t\t[Symbol.asyncIterator]() {\n\t\t\treturn this;\n\t\t},\n\t\tasync next() {\n\t\t\t// E17b: Fire beforeQuery on first iteration (lazy), then compile with\n\t\t\t// the hook-modified intent.\n\t\t\tif (!hooksFired) {\n\t\t\t\thooksFired = true;\n\n\t\t\t\tif (hookStore && hasHooks(hookStore)) {\n\t\t\t\t\t// Build raw intent (without defaultFilters) — hooks see raw intent\n\t\t\t\t\tconst rawIntent = builder.buildIntent(false);\n\t\t\t\t\tconst ctx: QueryHookContext = {\n\t\t\t\t\t\ttable,\n\t\t\t\t\t\toperation: 'select',\n\t\t\t\t\t\tintent: rawIntent,\n\t\t\t\t\t\tresultType: 'all',\n\t\t\t\t\t\tisStreaming: true,\n\t\t\t\t\t\t...(schemaName !== undefined && { schemaName }),\n\t\t\t\t\t\t...(txFlag && { inTransaction: true }),\n\t\t\t\t\t};\n\n\t\t\t\t\tlet hookIntent = rawIntent;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst afterHookCtx = await runBeforeQueryHooks(\n\t\t\t\t\t\t\thookStore.beforeQuery,\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\tonHookError,\n\t\t\t\t\t\t);\n\t\t\t\t\t\thookIntent = afterHookCtx.intent;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (hookStore.onError.length > 0) {\n\t\t\t\t\t\t\tthrow await runOnErrorHooks(hookStore.onError, {\n\t\t\t\t\t\t\t\ttable,\n\t\t\t\t\t\t\t\toperation: 'select',\n\t\t\t\t\t\t\t\terror: error as Error,\n\t\t\t\t\t\t\t\tintent: rawIntent,\n\t\t\t\t\t\t\t\tphase: 'beforeQuery',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply defaultFilters AFTER hooks (INV-01: cannot be bypassed)\n\t\t\t\t\tconst intentAfterDefaults =\n\t\t\t\t\t\tbuilder.applyDefaultFiltersToIntent(hookIntent);\n\t\t\t\t\tconst intentWithHints =\n\t\t\t\t\t\tbuilder.applyRelationHints(intentAfterDefaults);\n\t\t\t\t\tconst planOptions: PlanOptions = {\n\t\t\t\t\t\t...(builder.ctx.dialectCapabilities && {\n\t\t\t\t\t\t\tdialectCapabilities: builder.ctx.dialectCapabilities,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t...builder.ctx.planOptionsOverride,\n\t\t\t\t\t};\n\t\t\t\t\tconst planReport = builder.planWithAmbiguityHandling(\n\t\t\t\t\t\tintentWithHints,\n\t\t\t\t\t\tplanOptions,\n\t\t\t\t\t);\n\t\t\t\t\tconst compileOptions: { schemaName?: string; model: ModelIR } = {\n\t\t\t\t\t\tmodel: builder.ctx.model,\n\t\t\t\t\t};\n\t\t\t\t\tif (schemaName !== undefined) {\n\t\t\t\t\t\tcompileOptions.schemaName = schemaName;\n\t\t\t\t\t}\n\t\t\t\t\tconst compiled = adapter.compile(planReport, compileOptions);\n\t\t\t\t\tcompiledQuery = compiled;\n\t\t\t\t\tcapturedDump = adapter.createDump(planReport, compiled);\n\t\t\t\t\tif (\n\t\t\t\t\t\tcapturedDump.meta?.schema === undefined &&\n\t\t\t\t\t\tschemaName !== undefined\n\t\t\t\t\t) {\n\t\t\t\t\t\tcapturedDump = {\n\t\t\t\t\t\t\t...capturedDump,\n\t\t\t\t\t\t\tmeta: { ...capturedDump.meta, schema: schemaName },\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// No hooks: compute dump eagerly (same as original fast path)\n\t\t\t\t\tconst dumpResult = builder.dump();\n\t\t\t\t\tcompiledQuery = {\n\t\t\t\t\t\tsql: dumpResult.sql,\n\t\t\t\t\t\tparameters: dumpResult.params as readonly unknown[],\n\t\t\t\t\t};\n\t\t\t\t\tcapturedDump = dumpResult;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Initialize adapter iterator lazily (compiledQuery is now set)\n\t\t\tif (!adapterIterator) {\n\t\t\t\t// compiledQuery is guaranteed non-null: hooksFired is true at this\n\t\t\t\t// point, meaning the block above has completed and set compiledQuery.\n\t\t\t\tadapterIterator = adapter.stream<TResult>(\n\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: invariant — hooksFired=true means the block above set compiledQuery before reaching this branch\n\t\t\t\t\tcompiledQuery!,\n\t\t\t\t\tadapterOptions,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Call onStart only once, on first next() call\n\t\t\tif (!onStartCalled && onStartCallback && capturedDump) {\n\t\t\t\tonStartCalled = true;\n\t\t\t\tonStartCallback(capturedDump);\n\t\t\t}\n\n\t\t\treturn adapterIterator.next();\n\t\t},\n\t\tasync return(value?: TResult) {\n\t\t\tif (adapterIterator?.return) {\n\t\t\t\treturn adapterIterator.return(value);\n\t\t\t}\n\t\t\treturn { done: true as const, value: undefined };\n\t\t},\n\t\tasync throw(error?: unknown) {\n\t\t\t// E17b: Fire onError for stream errors\n\t\t\tif (hookStore && hookStore.onError.length > 0 && error instanceof Error) {\n\t\t\t\tconst rawIntent = builder.buildIntent(false);\n\t\t\t\tconst finalError = await runOnErrorHooks(hookStore.onError, {\n\t\t\t\t\ttable,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror,\n\t\t\t\t\tintent: rawIntent,\n\t\t\t\t\tphase: 'afterQuery',\n\t\t\t\t});\n\t\t\t\tthrow finalError;\n\t\t\t}\n\t\t\tif (adapterIterator?.throw) {\n\t\t\t\treturn adapterIterator.throw(error);\n\t\t\t}\n\t\t\tthrow error;\n\t\t},\n\t};\n\n\treturn lazyIterator;\n}\n","/* biome-ignore-all lint/style/noNonNullAssertion: Builder internals use non-null assertions on validated state */\nimport type { Mutable } from '@dbsp/types/internal';\nimport type { Adapter, Dump } from '../adapter.js';\nimport type {\n\tAggregateIntent,\n\tColumnExpressionIntent,\n\tExpressionIntent,\n\tIncludeIntent,\n\tJoinIntent,\n\tOrderByIntent,\n\tQueryIntent,\n\tSelectAggregateIntent,\n\tSelectIntent,\n\tWhereIntent,\n} from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanOptions, PlanReport } from '../planner.js';\nimport { AmbiguousPlanError, plan } from '../planner.js';\nimport type { BatchValuesRef } from './batch-values.js';\nimport { isBatchValuesRef } from './batch-values.js';\nimport {\n\tAmbiguousRelationError,\n\tExecutionError,\n\tInvalidOperationError,\n\tNotFoundError,\n\tvalidateIdentifier,\n} from './errors.js';\nimport { ExpressionRef } from './expressions.js';\nimport {\n\tand,\n\ttype DistinctField,\n\teq,\n\tinArray,\n\tisDistinctField,\n} from './filters.js';\nimport {\n\ttype HookStore,\n\thasHooks,\n\ttype QueryHookContext,\n\ttype QueryResultType,\n\trunAfterQueryHooks,\n\trunBeforeQueryHooks,\n\trunOnErrorHooks,\n\twithReentrancyGuard,\n} from './hooks.js';\nimport {\n\tincludeOptionsToIntent,\n\tisRecursiveIncludeOptions,\n\tparseDotNotationInclude,\n\ttype RecursiveIncludeConfig,\n\tvalidateRecursiveInclude,\n} from './intent-builder.js';\nimport {\n\tisWhereIntent,\n\tobjectToWhereIntent,\n\ttype WhereFilter,\n} from './object-filter.js';\nimport * as paginationImpl from './pagination-impl.js';\nimport type { QueryBuilderContext } from './query-builder-context.js';\nimport type { DumpMetaInput } from './query-builder-types.js';\nimport { ResultHydrator } from './result-hydrator.js';\nimport {\n\tbuildSetOperationIntent,\n\ttype QueryIntentSource,\n\ttype SetOperationBuilder,\n\tSetOperationBuilderImpl,\n} from './set-operation-builder.js';\nimport * as streamImpl from './stream-impl.js';\nimport {\n\ttype AggregateOptions,\n\ttype AliasedExprColumn,\n\ttype ColumnSpec,\n\ttype CursorPaginatedResult,\n\ttype CursorPaginateOptions,\n\ttype ExpressionSpec,\n\ttype IncludeOptionsWithRecursive,\n\tisExpressionSpec,\n\ttype OrderByRecord,\n\ttype OrderBySpec,\n\ttype PaginatedResult,\n\ttype PaginateOptions,\n\ttype QueryBuilder,\n\ttype RelationHints,\n\ttype SortDirection,\n\ttype StreamOptions,\n} from './types.js';\n/**\n * Internal query builder implementation.\n */\nexport class QueryBuilderImpl<TResult = unknown>\n\timplements QueryBuilder<TResult>\n{\n\t/** @internal — read by stream-impl and pagination-impl */\n\treadonly ctx: QueryBuilderContext;\n\t/** @internal — read by stream-impl */\n\treadonly from: string;\n\t/** @internal — mutated by pagination-impl on clones */\n\treadonly includes: IncludeIntent[] = [];\n\t/** @internal — mutated by pagination-impl on clones */\n\treadonly recursiveIncludes: RecursiveIncludeConfig[] = [];\n\tprivate readonly relationHints: RelationHints;\n\t/** @internal — mutated by pagination-impl on clones */\n\tselectIntent: SelectIntent | undefined = undefined;\n\t/** @internal — mutated by pagination-impl on clones */\n\twhereIntents: WhereIntent[] = [];\n\tprivate strictModeOverride: boolean | undefined = undefined;\n\t/** @internal — mutated by pagination-impl on clones */\n\taggregates: AggregateIntent[] = [];\n\t/** @internal — read by pagination-impl */\n\tgroupByFields: string[] = [];\n\t/** @internal — read by pagination-impl and cursor helpers */\n\torderByIntents: OrderByIntent[] = [];\n\t/** @internal — mutated by pagination-impl on clones */\n\tlimitValue: number | undefined = undefined;\n\t/** @internal — mutated by pagination-impl on clones */\n\toffsetValue: number | undefined = undefined;\n\tprivate havingIntents: WhereIntent[] = [];\n\tprivate isDistinctQuery = false;\n\tprivate distinctOnColumns: string[] = [];\n\tprivate skipDefaultFilters = false;\n\tprivate lockIntent: import('@dbsp/types').LockIntent | undefined = undefined;\n\t/** @internal — read by pagination-impl */\n\tjoinIntents: JoinIntent[] = [];\n\t/** When set, FROM clause is a BatchValues unnest() source, not a table */\n\tbatchValuesSource?: import('@dbsp/types').BatchValuesJoinPayload;\n\n\tconstructor(\n\t\tctx: QueryBuilderContext,\n\t\tfrom: string,\n\t\trelationHints: RelationHints = {},\n\t) {\n\t\tthis.ctx = ctx;\n\t\tthis.from = from;\n\t\tthis.relationHints = relationHints;\n\t}\n\n\tinclude(\n\t\trelation: string,\n\t\toptions?: IncludeOptionsWithRecursive,\n\t): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\n\t\t// Validate recursive includes (DX-017)\n\t\tif (isRecursiveIncludeOptions(options)) {\n\t\t\tvalidateRecursiveInclude(this.ctx.model, this.from, relation, options);\n\t\t\t// DX-017: No longer store separately - let includeOptionsToIntent handle conversion\n\t\t}\n\n\t\t// Support dot notation for nested includes: 'posts.comments.author'\n\t\tif (relation.includes('.')) {\n\t\t\tbuilder.includes.push(parseDotNotationInclude(relation, options));\n\t\t} else {\n\t\t\tbuilder.includes.push(includeOptionsToIntent(relation, options));\n\t\t}\n\t\treturn builder;\n\t}\n\n\t// Overload: typed columns (string keys only) → Pick<TResult, K>\n\tcolumns<K extends keyof TResult & string>(\n\t\tcolumns: readonly K[],\n\t): QueryBuilder<Pick<TResult, K>>;\n\t// Overload: mixed strings + AliasedExprColumn → extends result type with aliased props\n\tcolumns<\n\t\tconst T extends readonly (\n\t\t\t| (keyof TResult & string)\n\t\t\t| AliasedExprColumn<string>\n\t\t)[],\n\t>(\n\t\tcolumns: T,\n\t): QueryBuilder<\n\t\tPick<TResult, Extract<T[number], keyof TResult & string>> & {\n\t\t\t[E in Extract<\n\t\t\t\tT[number],\n\t\t\t\tAliasedExprColumn<string>\n\t\t\t> as E['__alias']]: E['__value'];\n\t\t}\n\t>;\n\t// Overload: mixed columns (strings + expressions) → TResult\n\tcolumns(columns: readonly ColumnSpec[]): QueryBuilder<TResult>;\n\t// Implementation — cast to TResult to match the most general overload signature.\n\t// The overloads above refine the type; the implementation signature is intentionally\n\t// broad to satisfy all three overloads (TypeScript requires an assignable\n\t// implementation signature).\n\t// biome-ignore lint/suspicious/noExplicitAny: implementation signature accepts erased type — public overloads above guarantee the correct narrowed return type for callers\n\tcolumns(columns: readonly ColumnSpec[]): QueryBuilder<any> {\n\t\tconst builder = this.clone();\n\n\t\t// Build columns array (direct ExpressionIntent format - NQL compatible)\n\t\tconst expressionColumns: ExpressionIntent[] = [];\n\t\tlet hasExpressions = false;\n\n\t\tfor (const col of columns) {\n\t\t\tif (isExpressionSpec(col)) {\n\t\t\t\thasExpressions = true;\n\t\t\t\texpressionColumns.push(col.intent);\n\t\t\t} else {\n\t\t\t\t// Simple field → ColumnExpressionIntent (kind: 'column')\n\t\t\t\texpressionColumns.push({ kind: 'column', column: col });\n\t\t\t}\n\t\t}\n\n\t\t// Use SelectWithExpressionsIntent if we have any expressions\n\t\tif (hasExpressions) {\n\t\t\tbuilder.selectIntent = {\n\t\t\t\ttype: 'expressions',\n\t\t\t\tcolumns: expressionColumns,\n\t\t\t};\n\t\t} else {\n\t\t\t// Simple fields only - extract field names\n\t\t\tconst fields = expressionColumns.map(\n\t\t\t\t(c) => (c as ColumnExpressionIntent).column,\n\t\t\t);\n\t\t\tbuilder.selectIntent = { type: 'fields', fields };\n\t\t}\n\n\t\t// Cast is safe: the public overloads above guarantee the correct narrowed type.\n\t\t// biome-ignore lint/suspicious/noExplicitAny: implementation signature cast — public overloads above guarantee the correct narrowed type for callers\n\t\treturn builder as QueryBuilder<any>;\n\t}\n\n\tcoalesce<K extends keyof TResult & string, Alias extends string>(\n\t\tfields: readonly K[],\n\t\tas: Alias,\n\t): QueryBuilder<TResult & { [P in Alias]: NonNullable<TResult[K]> }> {\n\t\tconst builder = this.clone();\n\n\t\t// Create CoalesceExpressionIntent\n\t\tconst coalesceIntent: ExpressionIntent = {\n\t\t\tkind: 'coalesce',\n\t\t\tfields: fields as readonly string[],\n\t\t\tas,\n\t\t};\n\n\t\t// If we already have a SelectWithExpressionsIntent, add to it\n\t\tif (builder.selectIntent?.type === 'expressions') {\n\t\t\tbuilder.selectIntent = {\n\t\t\t\ttype: 'expressions',\n\t\t\t\tcolumns: [...builder.selectIntent.columns, coalesceIntent],\n\t\t\t};\n\t\t} else if (builder.selectIntent?.type === 'fields') {\n\t\t\t// Convert fields to expressions and add coalesce\n\t\t\tconst fieldExpressions: ExpressionIntent[] =\n\t\t\t\tbuilder.selectIntent.fields.map(\n\t\t\t\t\t(field) => ({ kind: 'column', column: field }) as ExpressionIntent,\n\t\t\t\t);\n\t\t\tbuilder.selectIntent = {\n\t\t\t\ttype: 'expressions',\n\t\t\t\tcolumns: [...fieldExpressions, coalesceIntent],\n\t\t\t};\n\t\t} else {\n\t\t\t// No select intent yet - start with coalesce only\n\t\t\t// This means SELECT * plus the coalesce column\n\t\t\tbuilder.selectIntent = {\n\t\t\t\ttype: 'expressions',\n\t\t\t\tcolumns: [coalesceIntent],\n\t\t\t};\n\t\t}\n\n\t\t// SAFETY: coalesce() adds a computed column to the result type.\n\t\t// The runtime value is identical (same QueryBuilderImpl), only the\n\t\t// phantom TResult type parameter changes — invariant in QueryBuilder,\n\t\t// hence the double cast.\n\t\treturn builder as unknown as QueryBuilder<\n\t\t\tTResult & { [P in Alias]: NonNullable<TResult[K]> }\n\t\t>;\n\t}\n\n\tcount(\n\t\tfieldOrOptions?: AggregateOptions | string | DistinctField,\n\t\tas?: string,\n\t): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tconst agg: Mutable<AggregateIntent> = { function: 'count' };\n\n\t\tif (fieldOrOptions === undefined) {\n\t\t\t// count() - COUNT(*)\n\t\t} else if (typeof fieldOrOptions === 'string') {\n\t\t\t// count('field', 'alias') - COUNT(field)\n\t\t\tagg.field = fieldOrOptions;\n\t\t\tif (as !== undefined) {\n\t\t\t\tagg.as = as;\n\t\t\t}\n\t\t} else if (isDistinctField(fieldOrOptions)) {\n\t\t\t// count(distinct('field'), 'alias') - COUNT(DISTINCT field)\n\t\t\tagg.field = fieldOrOptions.field;\n\t\t\tagg.distinct = true;\n\t\t\tif (as !== undefined) {\n\t\t\t\tagg.as = as;\n\t\t\t}\n\t\t} else {\n\t\t\t// count({ field, as }) - AggregateOptions\n\t\t\tif (fieldOrOptions.field !== undefined) {\n\t\t\t\tagg.field = fieldOrOptions.field;\n\t\t\t}\n\t\t\tif (fieldOrOptions.as !== undefined) {\n\t\t\t\tagg.as = fieldOrOptions.as;\n\t\t\t}\n\t\t}\n\n\t\tbuilder.aggregates.push(agg as AggregateIntent);\n\t\treturn builder;\n\t}\n\n\tsum(field: string | DistinctField, as?: string): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tconst isDistinct = isDistinctField(field);\n\t\tconst fieldName = isDistinct ? field.field : field;\n\t\tconst agg: Mutable<AggregateIntent> = { function: 'sum', field: fieldName };\n\t\tif (isDistinct) {\n\t\t\tagg.distinct = true;\n\t\t}\n\t\tif (as !== undefined) {\n\t\t\tagg.as = as;\n\t\t}\n\t\tbuilder.aggregates.push(agg as AggregateIntent);\n\t\treturn builder;\n\t}\n\n\tavg(field: string | DistinctField, as?: string): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tconst isDistinct = isDistinctField(field);\n\t\tconst fieldName = isDistinct ? field.field : field;\n\t\tconst agg: Mutable<AggregateIntent> = { function: 'avg', field: fieldName };\n\t\tif (isDistinct) {\n\t\t\tagg.distinct = true;\n\t\t}\n\t\tif (as !== undefined) {\n\t\t\tagg.as = as;\n\t\t}\n\t\tbuilder.aggregates.push(agg as AggregateIntent);\n\t\treturn builder;\n\t}\n\n\tmin(field: string, as?: string): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tconst agg: Mutable<AggregateIntent> = { function: 'min', field };\n\t\tif (as !== undefined) {\n\t\t\tagg.as = as;\n\t\t}\n\t\tbuilder.aggregates.push(agg as AggregateIntent);\n\t\treturn builder;\n\t}\n\n\tmax(field: string, as?: string): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tconst agg: Mutable<AggregateIntent> = { function: 'max', field };\n\t\tif (as !== undefined) {\n\t\t\tagg.as = as;\n\t\t}\n\t\tbuilder.aggregates.push(agg as AggregateIntent);\n\t\treturn builder;\n\t}\n\n\tgroupBy(fields: readonly string[]): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.groupByFields.push(...fields);\n\t\treturn builder;\n\t}\n\n\thaving(condition: WhereIntent): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.havingIntents.push(condition);\n\t\treturn builder;\n\t}\n\n\tdistinct(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.isDistinctQuery = true;\n\t\treturn builder;\n\t}\n\n\t/**\n\t * Apply PostgreSQL DISTINCT ON (...) to the query.\n\t *\n\t * @param columns - One or more column names to deduplicate on\n\t * @returns A new QueryBuilder with DISTINCT ON applied\n\t *\n\t * @example\n\t * ```typescript\n\t * orm.select('users').distinctOn('department').all();\n\t * // SQL: SELECT DISTINCT ON (\"department\") * FROM \"users\"\n\t *\n\t * orm.select('logs').distinctOn('user_id', 'action').all();\n\t * // SQL: SELECT DISTINCT ON (\"user_id\", \"action\") * FROM \"logs\"\n\t * ```\n\t */\n\tdistinctOn(...columns: string[]): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.distinctOnColumns = columns;\n\t\treturn builder;\n\t}\n\n\t// --------------------------------------------------------------------------\n\t// Row-level locking (E15)\n\t// --------------------------------------------------------------------------\n\n\tforUpdate(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = {\n\t\t\tstrength: 'forUpdate',\n\t\t\twaitPolicy: builder.lockIntent?.waitPolicy ?? 'block',\n\t\t};\n\t\treturn builder;\n\t}\n\n\tforShare(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = {\n\t\t\tstrength: 'forShare',\n\t\t\twaitPolicy: builder.lockIntent?.waitPolicy ?? 'block',\n\t\t};\n\t\treturn builder;\n\t}\n\n\tforNoKeyUpdate(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = {\n\t\t\tstrength: 'forNoKeyUpdate',\n\t\t\twaitPolicy: builder.lockIntent?.waitPolicy ?? 'block',\n\t\t};\n\t\treturn builder;\n\t}\n\n\tforKeyShare(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = {\n\t\t\tstrength: 'forKeyShare',\n\t\t\twaitPolicy: builder.lockIntent?.waitPolicy ?? 'block',\n\t\t};\n\t\treturn builder;\n\t}\n\n\tlock(\n\t\tstrength: import('@dbsp/types').LockStrength,\n\t\twaitPolicy?: import('@dbsp/types').LockWaitPolicy,\n\t): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = { strength, waitPolicy: waitPolicy ?? 'block' };\n\t\treturn builder;\n\t}\n\n\tskipLocked(): QueryBuilder<TResult> {\n\t\tif (!this.lockIntent) {\n\t\t\tthrow new Error(\n\t\t\t\t'skipLocked() requires a preceding lock method (forUpdate, forShare, etc.)',\n\t\t\t);\n\t\t}\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = { ...this.lockIntent, waitPolicy: 'skipLocked' };\n\t\treturn builder;\n\t}\n\n\tnoWait(): QueryBuilder<TResult> {\n\t\tif (!this.lockIntent) {\n\t\t\tthrow new Error(\n\t\t\t\t'noWait() requires a preceding lock method (forUpdate, forShare, etc.)',\n\t\t\t);\n\t\t}\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = { ...this.lockIntent, waitPolicy: 'noWait' };\n\t\treturn builder;\n\t}\n\n\torderBy(\n\t\tfieldOrRecordOrSpecs:\n\t\t\t| string\n\t\t\t| OrderByRecord\n\t\t\t| readonly OrderBySpec[]\n\t\t\t| ExpressionRef\n\t\t\t| ExpressionSpec,\n\t\tdirection?: SortDirection,\n\t\toptions?: { nulls?: import('./types.js').NullsPosition },\n\t): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\n\t\t// ExpressionRef form: orderBy(expr) or orderBy(expr, 'desc') or orderBy(expr, 'desc', { nulls: 'last' })\n\t\tif (fieldOrRecordOrSpecs instanceof ExpressionRef) {\n\t\t\tbuilder.orderByIntents.push({\n\t\t\t\texpression: fieldOrRecordOrSpecs.intent,\n\t\t\t\tdirection: direction ?? 'asc',\n\t\t\t\t...(options?.nulls !== undefined ? { nulls: options.nulls } : {}),\n\t\t\t});\n\t\t\treturn builder;\n\t\t}\n\n\t\t// ExpressionSpec form: orderBy(relationColumn(...)) or other plain ExpressionSpec objects\n\t\tif (isExpressionSpec(fieldOrRecordOrSpecs as ColumnSpec)) {\n\t\t\tbuilder.orderByIntents.push({\n\t\t\t\texpression: (fieldOrRecordOrSpecs as { intent: ExpressionIntent })\n\t\t\t\t\t.intent,\n\t\t\t\tdirection: direction ?? 'asc',\n\t\t\t\t...(options?.nulls !== undefined ? { nulls: options.nulls } : {}),\n\t\t\t});\n\t\t\treturn builder;\n\t\t}\n\n\t\t// String form: orderBy('field') or orderBy('field', 'desc') or orderBy('field', 'desc', { nulls: 'last' })\n\t\tif (typeof fieldOrRecordOrSpecs === 'string') {\n\t\t\tbuilder.orderByIntents.push({\n\t\t\t\tfield: fieldOrRecordOrSpecs,\n\t\t\t\tdirection: direction ?? 'asc',\n\t\t\t\t...(options?.nulls !== undefined ? { nulls: options.nulls } : {}),\n\t\t\t});\n\t\t\treturn builder;\n\t\t}\n\n\t\t// Array form: orderBy([{ column, direction, nulls }])\n\t\tif (Array.isArray(fieldOrRecordOrSpecs)) {\n\t\t\tfor (const spec of fieldOrRecordOrSpecs) {\n\t\t\t\tbuilder.orderByIntents.push({\n\t\t\t\t\tfield: spec.column,\n\t\t\t\t\tdirection: spec.direction ?? 'asc',\n\t\t\t\t\tnulls: spec.nulls,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn builder;\n\t\t}\n\n\t\t// Object form: orderBy({ field1: 'desc', field2: 'asc' })\n\t\tfor (const [field, dir] of Object.entries(fieldOrRecordOrSpecs)) {\n\t\t\tbuilder.orderByIntents.push({\n\t\t\t\tfield,\n\t\t\t\tdirection: dir,\n\t\t\t});\n\t\t}\n\t\treturn builder;\n\t}\n\n\tlimit(count: number): QueryBuilder<TResult> {\n\t\tif (!Number.isSafeInteger(count) || count < 0) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'limit',\n\t\t\t\t'limit must be a non-negative safe integer',\n\t\t\t);\n\t\t}\n\t\tconst builder = this.clone();\n\t\tbuilder.limitValue = count;\n\t\treturn builder;\n\t}\n\n\toffset(count: number): QueryBuilder<TResult> {\n\t\tif (!Number.isSafeInteger(count) || count < 0) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'offset',\n\t\t\t\t'offset must be a non-negative safe integer',\n\t\t\t);\n\t\t}\n\t\tconst builder = this.clone();\n\t\tbuilder.offsetValue = count;\n\t\treturn builder;\n\t}\n\n\twhere(condition: WhereIntent | WhereFilter<TResult>): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\t// Detect ExpressionRef used as a standalone boolean WHERE predicate.\n\t\t// op('!=', exprRef('a'), exprRef('b')) returns ExpressionRef which has __expr:true\n\t\t// but no `kind` property, so isWhereIntent() returns false and objectToWhereIntent()\n\t\t// would map `__expr: true` as a column field. Handle this before the WhereIntent check.\n\t\tif (condition instanceof ExpressionRef) {\n\t\t\t// Wrap the expression intent in a WhereExpressionIntent with no value/operator.\n\t\t\t// The WHERE handler detects this and emits the expression node directly.\n\t\t\tconst whereExpr = {\n\t\t\t\tkind: 'expression',\n\t\t\t\texpr: condition.intent,\n\t\t\t} as unknown as WhereIntent;\n\t\t\tbuilder.whereIntents.push(whereExpr);\n\t\t\treturn builder;\n\t\t}\n\t\t// Convert object filter to WhereIntent if needed\n\t\tconst intent = isWhereIntent(condition)\n\t\t\t? condition\n\t\t\t: objectToWhereIntent(condition as WhereFilter<Record<string, unknown>>);\n\t\tbuilder.whereIntents.push(intent);\n\t\treturn builder;\n\t}\n\n\tjoin(\n\t\trelationOrTableOrBatch: string | BatchValuesRef,\n\t\topts?: { type?: 'inner' | 'left'; on?: WhereIntent; as?: string },\n\t): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tconst type = opts?.type ?? 'inner';\n\n\t\tif (isBatchValuesRef(relationOrTableOrBatch)) {\n\t\t\tconst bv = relationOrTableOrBatch;\n\t\t\tif (!opts?.on) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'join(batchValuesRef): an `on` condition is required for BatchValues joins',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst joinIntent: JoinIntent = {\n\t\t\t\tbatchValues: {\n\t\t\t\t\tdata: bv.data,\n\t\t\t\t\tcolumns: bv.columns,\n\t\t\t\t\ttypes: bv.types,\n\t\t\t\t\talias: bv.alias,\n\t\t\t\t\tordinality: bv.ordinality,\n\t\t\t\t},\n\t\t\t\ton: opts.on,\n\t\t\t\ttype,\n\t\t\t\t...(opts.as !== undefined ? { alias: opts.as } : { alias: bv.alias }),\n\t\t\t};\n\t\t\tbuilder.joinIntents.push(joinIntent);\n\t\t} else {\n\t\t\t// FIND-011: Validate string table/relation argument\n\t\t\tvalidateIdentifier(relationOrTableOrBatch, 'table');\n\t\t\tconst joinIntent: JoinIntent = opts?.on\n\t\t\t\t? {\n\t\t\t\t\t\ttable: relationOrTableOrBatch,\n\t\t\t\t\t\ton: opts.on,\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\t...(opts.as !== undefined && { alias: opts.as }),\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\trelation: relationOrTableOrBatch,\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\t...(opts?.as !== undefined && { alias: opts.as }),\n\t\t\t\t\t};\n\t\t\tbuilder.joinIntents.push(joinIntent);\n\t\t}\n\t\treturn builder;\n\t}\n\n\twithStrictMode(strict: boolean): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.strictModeOverride = strict;\n\t\treturn builder;\n\t}\n\n\twithRelationHint(target: string, relation: string): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\t(builder.relationHints as Record<string, string>)[target] = relation;\n\t\treturn builder;\n\t}\n\n\twithPlanOptions(options: PlanOptions): QueryBuilder<TResult> {\n\t\treturn this.cloneWithCtxOverride({\n\t\t\tplanOptionsOverride: {\n\t\t\t\t...this.ctx.planOptionsOverride,\n\t\t\t\t...options,\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Get effective strict mode (override takes precedence over ORM-level).\n\t */\n\tprivate getEffectiveStrictMode(): boolean {\n\t\treturn this.strictModeOverride !== undefined\n\t\t\t? this.strictModeOverride\n\t\t\t: this.ctx.strictMode;\n\t}\n\n\tplan(): PlanReport {\n\t\tconst intent = this.buildIntent();\n\n\t\t// E15: Warn when lock is used outside a transaction context\n\t\tif (intent.lock && !this.ctx.inTransaction) {\n\t\t\tconsole.warn(\n\t\t\t\t'[dbsp] Row-level lock (FOR UPDATE/SHARE) used outside a transaction. ' +\n\t\t\t\t\t'Locks are only effective within a transaction.',\n\t\t\t);\n\t\t}\n\n\t\t// Apply relation hints to includes before planning\n\t\tconst intentWithHints = this.applyRelationHints(intent);\n\n\t\t// Build plan options: dialectCapabilities + per-query overrides\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...(this.ctx.dialectCapabilities && {\n\t\t\t\tdialectCapabilities: this.ctx.dialectCapabilities,\n\t\t\t}),\n\t\t\t// planOptions (global + per-query) take highest precedence\n\t\t\t...this.ctx.planOptionsOverride,\n\t\t};\n\n\t\ttry {\n\t\t\treturn plan(intentWithHints, this.ctx.model, planOptions);\n\t\t} catch (error) {\n\t\t\tif (error instanceof AmbiguousPlanError) {\n\t\t\t\treturn this.handleAmbiguity(error, intentWithHints, planOptions);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync all(): Promise<TResult[]> {\n\t\tconst adapter = this.getConfiguredAdapter();\n\n\t\t// E17b: Hook-aware execution path\n\t\tif (this.ctx.hookStore && hasHooks(this.ctx.hookStore)) {\n\t\t\treturn this.executeWithHooks(adapter, 'all');\n\t\t}\n\n\t\t// Fast path: no hooks — existing behavior, zero overhead\n\t\tconst planReport = this.plan();\n\n\t\t// Build compile options with exactOptionalPropertyTypes compliance\n\t\tconst compileOptions: {\n\t\t\tschemaName?: string;\n\t\t\tmodel: ModelIR;\n\t\t} = { model: this.ctx.model };\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\n\t\t// Use compileWithIncludes to get subquery include info for hasMany relations\n\t\tconst compiledWithIncludes = adapter.compileWithIncludes(\n\t\t\tplanReport,\n\t\t\tcompileOptions,\n\t\t);\n\t\tconst mainResults = (await adapter.execute(\n\t\t\tcompiledWithIncludes.main,\n\t\t)) as TResult[];\n\n\t\t// Create hydrator for result transformation (AUD-005)\n\t\tconst hydrator = new ResultHydrator<TResult>(\n\t\t\tthis.ctx.model,\n\t\t\tthis.from,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\n\t\t// E2E-004: Hydrate json_agg includes by parsing JSON columns\n\t\thydrator.hydrateJsonAggIncludes(mainResults, planReport);\n\n\t\t// E2E-004: Hydrate JOIN includes by grouping dot-prefixed columns\n\t\thydrator.hydrateJoinIncludes(mainResults, planReport);\n\n\t\t// Process subquery includes (hasMany hydration - DX-033)\n\t\tif (compiledWithIncludes.subqueryIncludes.length > 0) {\n\t\t\tawait hydrator.hydrateIncludes(\n\t\t\t\tmainResults,\n\t\t\t\tcompiledWithIncludes.subqueryIncludes,\n\t\t\t\tadapter,\n\t\t\t\tcompileOptions,\n\t\t\t);\n\t\t}\n\n\t\t// Process recursive includes if any\n\t\tif (this.recursiveIncludes.length > 0) {\n\t\t\tawait hydrator.processRecursiveIncludes(\n\t\t\t\tmainResults,\n\t\t\t\tthis.recursiveIncludes,\n\t\t\t\tadapter,\n\t\t\t);\n\t\t}\n\n\t\treturn mainResults;\n\t}\n\n\tasync first(): Promise<TResult | undefined> {\n\t\t// E17b: Hook-aware path — hooks see resultType='first'\n\t\tif (this.ctx.hookStore && hasHooks(this.ctx.hookStore)) {\n\t\t\tconst adapter = this.getConfiguredAdapter();\n\t\t\tconst rows = await this.executeWithHooks<TResult[]>(adapter, 'first');\n\t\t\treturn rows[0];\n\t\t}\n\t\tconst rows = await this.all();\n\t\treturn rows[0];\n\t}\n\n\tasync firstOrThrow(): Promise<TResult> {\n\t\tconst result = await this.first();\n\t\tif (result === undefined) {\n\t\t\tthrow new NotFoundError(this.from);\n\t\t}\n\t\treturn result;\n\t}\n\n\tasync byId(\n\t\tvalue: string | number | Record<string, unknown>,\n\t): Promise<TResult | undefined> {\n\t\tconst condition = this.buildPkCondition(value);\n\t\treturn this.where(condition).first();\n\t}\n\n\tasync byIdOrThrow(\n\t\tvalue: string | number | Record<string, unknown>,\n\t): Promise<TResult> {\n\t\tconst result = await this.byId(value);\n\t\tif (result === undefined) {\n\t\t\tthrow new NotFoundError(\n\t\t\t\tthis.from,\n\t\t\t\t`No record found with the specified primary key`,\n\t\t\t);\n\t\t}\n\t\treturn result;\n\t}\n\n\tasync byIds(values: readonly (string | number)[]): Promise<TResult[]> {\n\t\tif (values.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t\treturn this.where(inArray(this.getSimplePkColumn(), [...values])).all();\n\t}\n\n\t/**\n\t * Get the simple primary key column name for the current table.\n\t * Returns the first PK column if composite, falls back to 'id' if undefined.\n\t */\n\tprivate getSimplePkColumn(): string {\n\t\tconst table = this.ctx.model.getTable(this.from);\n\t\tconst pk = table?.primaryKey;\n\t\tif (typeof pk === 'string') {\n\t\t\treturn pk;\n\t\t}\n\t\tif (Array.isArray(pk) && pk.length > 0) {\n\t\t\treturn pk[0]!;\n\t\t}\n\t\treturn 'id'; // fallback for legacy schemas without explicit PK\n\t}\n\n\t/**\n\t * Build a where condition for a primary key lookup.\n\t * Supports simple PKs (string | number) and composite PKs (object).\n\t */\n\tprivate buildPkCondition(\n\t\tvalue: string | number | Record<string, unknown>,\n\t): WhereIntent {\n\t\tif (typeof value === 'string' || typeof value === 'number') {\n\t\t\t// Simple PK - use schema-defined PK column\n\t\t\treturn eq(this.getSimplePkColumn(), value);\n\t\t}\n\t\t// FIND-009: Validate composite PK keys against schema-defined primary key columns\n\t\tconst table = this.ctx.model.getTable(this.from);\n\t\tif (!table) {\n\t\t\tthrow new InvalidOperationError('byId', 'Unknown table');\n\t\t}\n\t\tconst rawPk = table.primaryKey ?? [];\n\t\tconst knownPkCols = new Set(typeof rawPk === 'string' ? [rawPk] : rawPk);\n\t\t// Composite PK - validate keys then build AND condition\n\t\tconst entries = Object.entries(value);\n\t\tif (entries.length === 0) {\n\t\t\tthrow new Error('Composite primary key cannot be empty');\n\t\t}\n\t\tif (knownPkCols.size > 0) {\n\t\t\tfor (const key of Object.keys(value)) {\n\t\t\t\tif (!knownPkCols.has(key)) {\n\t\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t\t'byId',\n\t\t\t\t\t\t`Unknown primary key column: ${key}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (entries.length === 1) {\n\t\t\tconst entry = entries[0];\n\t\t\tif (!entry) {\n\t\t\t\tthrow new Error('Composite primary key entry missing');\n\t\t\t}\n\t\t\tconst [field, fieldValue] = entry;\n\t\t\treturn eq(field, fieldValue);\n\t\t}\n\t\tconst conditions = entries.map(([field, fieldValue]) =>\n\t\t\teq(field, fieldValue),\n\t\t);\n\t\treturn and(...conditions);\n\t}\n\n\tdump(meta?: DumpMetaInput): Dump {\n\t\tconst adapter = this.getConfiguredAdapter();\n\t\tconst planReport = this.plan();\n\n\t\t// Build compile options with exactOptionalPropertyTypes compliance\n\t\tconst compileOptions: {\n\t\t\tschemaName?: string;\n\t\t\tmodel: ModelIR;\n\t\t} = { model: this.ctx.model };\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\n\t\tconst compiled = adapter.compile(planReport, compileOptions);\n\n\t\t// Build DumpMeta: adapter-level schema + caller-supplied queryName/correlationId\n\t\tconst dumpMeta: DumpMetaInput = {\n\t\t\t...(meta?.queryName !== undefined && { queryName: meta.queryName }),\n\t\t\t...(meta?.correlationId !== undefined && {\n\t\t\t\tcorrelationId: meta.correlationId,\n\t\t\t}),\n\t\t};\n\n\t\t// Use adapter.createDump() to properly capture adapter's schema\n\t\t// Then merge with context schema if needed\n\t\tconst dump = adapter.createDump(planReport, compiled, dumpMeta);\n\n\t\t// If adapter didn't set schema but context has one, add it\n\t\tif (dump.meta?.schema === undefined && this.ctx.schemaName !== undefined) {\n\t\t\treturn {\n\t\t\t\t...dump,\n\t\t\t\tmeta: {\n\t\t\t\t\t...dump.meta,\n\t\t\t\t\tschema: this.ctx.schemaName,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn dump;\n\t}\n\n\tasync exists(): Promise<boolean> {\n\t\tconst adapter = this.getConfiguredAdapter();\n\n\t\t// E17b: Hook-aware path for exists()\n\t\tif (this.ctx.hookStore && hasHooks(this.ctx.hookStore)) {\n\t\t\t// INV-07: Re-entrancy guard\n\t\t\treturn withReentrancyGuard(this.ctx.hookStore, (s) =>\n\t\t\t\tthis.existsWithHooks(adapter, s),\n\t\t\t);\n\t\t}\n\n\t\t// Fast path: no hooks\n\t\tconst existsIntent = this.buildExistsIntent();\n\t\tconst intentWithHints = this.applyRelationHints(existsIntent);\n\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...(this.ctx.dialectCapabilities && {\n\t\t\t\tdialectCapabilities: this.ctx.dialectCapabilities,\n\t\t\t}),\n\t\t\t...this.ctx.planOptionsOverride,\n\t\t};\n\n\t\tconst planReport = this.planWithAmbiguityHandling(\n\t\t\tintentWithHints,\n\t\t\tplanOptions,\n\t\t);\n\n\t\tconst compileOptions: {\n\t\t\tschemaName?: string;\n\t\t\tmodel: ModelIR;\n\t\t} = { model: this.ctx.model };\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\n\t\tconst compiled = adapter.compile(planReport, compileOptions);\n\t\tconst rows = await adapter.execute(compiled);\n\t\treturn (\n\t\t\trows.length > 0 && (rows[0] as Record<string, unknown>).exists === true\n\t\t);\n\t}\n\n\tprivate async existsWithHooks(\n\t\tadapter: Adapter,\n\t\tstore: HookStore,\n\t): Promise<boolean> {\n\t\tconst startTime = Date.now();\n\n\t\t// Build raw intent (without defaultFilters) for hooks\n\t\tconst rawIntent = this.buildIntent(false);\n\t\tconst beforeCtx: QueryHookContext = {\n\t\t\ttable: this.from,\n\t\t\toperation: 'select',\n\t\t\tintent: rawIntent,\n\t\t\tresultType: 'exists',\n\t\t\t...(this.ctx.schemaName !== undefined && {\n\t\t\t\tschemaName: this.ctx.schemaName,\n\t\t\t}),\n\t\t\t...(this.ctx.inTransaction && { inTransaction: true }),\n\t\t};\n\n\t\t// Run beforeQuery hooks\n\t\tlet intent: QueryIntent;\n\t\ttry {\n\t\t\tconst afterHookCtx = await runBeforeQueryHooks(\n\t\t\t\tstore.beforeQuery,\n\t\t\t\tbeforeCtx,\n\t\t\t\tthis.ctx.onHookError,\n\t\t\t);\n\t\t\tintent = afterHookCtx.intent;\n\t\t} catch (error) {\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tthrow await runOnErrorHooks(store.onError, {\n\t\t\t\t\ttable: this.from,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent: rawIntent,\n\t\t\t\t\tphase: 'beforeQuery',\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\t// Apply defaultFilters AFTER hooks (INV-01)\n\t\tintent = this.applyDefaultFiltersToIntent(intent);\n\n\t\t// Build exists-wrapped intent from the (potentially modified) intent\n\t\tconst existsIntent = this.buildExistsIntentFromIntent(intent);\n\t\tconst intentWithHints = this.applyRelationHints(existsIntent);\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...(this.ctx.dialectCapabilities && {\n\t\t\t\tdialectCapabilities: this.ctx.dialectCapabilities,\n\t\t\t}),\n\t\t\t...this.ctx.planOptionsOverride,\n\t\t};\n\t\tconst planReport = this.planWithAmbiguityHandling(\n\t\t\tintentWithHints,\n\t\t\tplanOptions,\n\t\t);\n\t\tconst compileOptions: { schemaName?: string; model: ModelIR } = {\n\t\t\tmodel: this.ctx.model,\n\t\t};\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\t\tconst compiled = adapter.compile(planReport, compileOptions);\n\t\tconst rows = await adapter.execute(compiled);\n\t\tconst result =\n\t\t\trows.length > 0 && (rows[0] as Record<string, unknown>).exists === true;\n\n\t\t// afterQuery with boolean result\n\t\tconst afterCtx: QueryHookContext = {\n\t\t\ttable: this.from,\n\t\t\toperation: 'select',\n\t\t\tintent,\n\t\t\tresultType: 'exists',\n\t\t\tsql: compiled.sql,\n\t\t\tparameters: compiled.parameters,\n\t\t\tduration: Date.now() - startTime,\n\t\t\t...(this.ctx.schemaName !== undefined && {\n\t\t\t\tschemaName: this.ctx.schemaName,\n\t\t\t}),\n\t\t};\n\t\ttry {\n\t\t\treturn await runAfterQueryHooks(\n\t\t\t\tstore.afterQuery,\n\t\t\t\tafterCtx,\n\t\t\t\tresult,\n\t\t\t\tthis.ctx.onHookError,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tthrow await runOnErrorHooks(store.onError, {\n\t\t\t\t\ttable: this.from,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent,\n\t\t\t\t\tphase: 'afterQuery',\n\t\t\t\t\tsql: compiled.sql,\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\texistsDump(): Dump {\n\t\tconst adapter = this.getConfiguredAdapter();\n\t\tconst existsIntent = this.buildExistsIntent();\n\t\tconst intentWithHints = this.applyRelationHints(existsIntent);\n\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...(this.ctx.dialectCapabilities && {\n\t\t\t\tdialectCapabilities: this.ctx.dialectCapabilities,\n\t\t\t}),\n\t\t\t...this.ctx.planOptionsOverride,\n\t\t};\n\n\t\tconst planReport = this.planWithAmbiguityHandling(\n\t\t\tintentWithHints,\n\t\t\tplanOptions,\n\t\t);\n\n\t\tconst compileOptions: {\n\t\t\tschemaName?: string;\n\t\t\tmodel: ModelIR;\n\t\t} = { model: this.ctx.model };\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\n\t\tconst compiled = adapter.compile(planReport, compileOptions);\n\t\tconst dump = adapter.createDump(planReport, compiled);\n\n\t\tif (dump.meta?.schema === undefined && this.ctx.schemaName !== undefined) {\n\t\t\treturn {\n\t\t\t\t...dump,\n\t\t\t\tmeta: {\n\t\t\t\t\t...dump.meta,\n\t\t\t\t\tschema: this.ctx.schemaName,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn dump;\n\t}\n\n\texecute(): Promise<TResult[]> {\n\t\treturn this.all();\n\t}\n\n\tstream(options?: StreamOptions): AsyncIterableIterator<TResult> {\n\t\treturn streamImpl.stream(this, options);\n\t}\n\n\t/**\n\t * Execute the query with offset-based pagination.\n\t */\n\tasync paginate(options?: PaginateOptions): Promise<PaginatedResult<TResult>> {\n\t\treturn paginationImpl.paginate(this, options);\n\t}\n\n\t/**\n\t * Execute the query with cursor-based pagination.\n\t */\n\tasync cursorPaginate(\n\t\toptions?: CursorPaginateOptions,\n\t): Promise<CursorPaginatedResult<TResult>> {\n\t\treturn paginationImpl.cursorPaginate(this, options);\n\t}\n\n\t/**\n\t * Get configured adapter, throwing if not configured.\n\t * @throws {ExecutionError} If adapter is not configured\n\t * @returns The configured adapter instance\n\t */\n\t/** @internal — called by pagination-impl and stream-impl */\n\tgetConfiguredAdapter(): Adapter {\n\t\tif (!this.ctx.adapter) {\n\t\t\tthrow new ExecutionError({\n\t\t\t\toperation: 'query execution',\n\t\t\t\treason: 'Adapter not configured',\n\t\t\t\tfix: 'Pass an adapter to createOrm({ adapter: yourAdapter })',\n\t\t\t});\n\t\t}\n\t\treturn this.ctx.adapter;\n\t}\n\n\t/**\n\t * Apply relation hints to includes that don't have explicit `via`.\n\t */\n\t/** @internal — called by stream-impl */\n\tapplyRelationHints(intent: QueryIntent): QueryIntent {\n\t\tif (!intent.include || Object.keys(this.relationHints).length === 0) {\n\t\t\treturn intent;\n\t\t}\n\n\t\tconst updatedIncludes = intent.include.map((inc) =>\n\t\t\tthis.applyHintToInclude(inc),\n\t\t);\n\n\t\treturn {\n\t\t\t...intent,\n\t\t\tinclude: updatedIncludes,\n\t\t};\n\t}\n\n\t/**\n\t * Apply relation hint to a single include (recursively).\n\t */\n\tprivate applyHintToInclude(inc: IncludeIntent): IncludeIntent {\n\t\t// If already has explicit via, don't override\n\t\tif (inc.via !== undefined) {\n\t\t\t// But still process nested includes\n\t\t\tif (inc.include && inc.include.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\t...inc,\n\t\t\t\t\tinclude: inc.include.map((nested) => this.applyHintToInclude(nested)),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn inc;\n\t\t}\n\n\t\t// Check if we have a hint for this target\n\t\tconst hint = this.relationHints[inc.relation];\n\t\tconst result: IncludeIntent = hint ? { ...inc, via: hint } : inc;\n\n\t\t// Process nested includes\n\t\tif (result.include && result.include.length > 0) {\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tinclude: result.include.map((nested) =>\n\t\t\t\t\tthis.applyHintToInclude(nested),\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Build the QueryIntent from current state.\n\t * Handles exactOptionalPropertyTypes by only including defined properties.\n\t */\n\t/** @internal Used by CteQueryBuilder to access query intent without executing. */\n\tbuildIntent(applyDefaultFilters = true): QueryIntent {\n\t\tconst intent: Mutable<QueryIntent> = {\n\t\t\ttype: 'select',\n\t\t\tfrom: this.from,\n\t\t};\n\n\t\t// Handle aggregates - convert to SelectAggregateIntent\n\t\tif (this.aggregates.length > 0) {\n\t\t\tconst aggregateSelect: Mutable<SelectAggregateIntent> = {\n\t\t\t\ttype: 'aggregate',\n\t\t\t\taggregates: [...this.aggregates],\n\t\t\t};\n\t\t\t// Add group by fields to the select for projection\n\t\t\tif (this.groupByFields.length > 0) {\n\t\t\t\taggregateSelect.fields = [...this.groupByFields];\n\t\t\t}\n\t\t\tintent.select = aggregateSelect as SelectAggregateIntent;\n\t\t} else if (this.selectIntent !== undefined) {\n\t\t\tintent.select = this.selectIntent;\n\t\t}\n\n\t\t// Combine default filter (soft delete) with user-provided where conditions\n\t\tconst allWhereIntents: WhereIntent[] = [];\n\n\t\t// Prepend default filter for this table (if configured and not skipped)\n\t\tif (applyDefaultFilters) {\n\t\t\tconst tableDefaultFilter =\n\t\t\t\t!this.skipDefaultFilters && this.ctx.defaultFilters\n\t\t\t\t\t? this.ctx.defaultFilters[this.from]\n\t\t\t\t\t: undefined;\n\t\t\tif (tableDefaultFilter) {\n\t\t\t\tallWhereIntents.push(tableDefaultFilter);\n\t\t\t}\n\t\t}\n\n\t\t// Add user-provided filters\n\t\tallWhereIntents.push(...this.whereIntents);\n\n\t\t// Combine with AND\n\t\tif (allWhereIntents.length === 1) {\n\t\t\tconst singleWhere = allWhereIntents[0];\n\t\t\tif (singleWhere !== undefined) {\n\t\t\t\tintent.where = singleWhere;\n\t\t\t}\n\t\t} else if (allWhereIntents.length > 1) {\n\t\t\tintent.where = and(...allWhereIntents);\n\t\t}\n\n\t\t// Combine multiple having conditions with AND (DX-034)\n\t\tif (this.havingIntents.length === 1) {\n\t\t\tconst singleHaving = this.havingIntents[0];\n\t\t\tif (singleHaving !== undefined) {\n\t\t\t\tintent.having = singleHaving;\n\t\t\t}\n\t\t} else if (this.havingIntents.length > 1) {\n\t\t\tintent.having = and(...this.havingIntents);\n\t\t}\n\n\t\t// Add SELECT DISTINCT flag (DX-034)\n\t\tif (this.isDistinctQuery) {\n\t\t\tintent.distinct = true;\n\t\t}\n\n\t\t// Add DISTINCT ON columns (PostgreSQL-specific)\n\t\tif (this.distinctOnColumns.length > 0) {\n\t\t\tintent.distinctOn = [...this.distinctOnColumns];\n\t\t}\n\n\t\tif (this.includes.length > 0) {\n\t\t\tintent.include = this.includes;\n\t\t}\n\t\tif (this.groupByFields.length > 0) {\n\t\t\tintent.groupBy = [...this.groupByFields];\n\t\t}\n\t\tif (this.orderByIntents.length > 0) {\n\t\t\tintent.orderBy = [...this.orderByIntents];\n\t\t}\n\t\tif (this.limitValue !== undefined) {\n\t\t\tintent.limit = this.limitValue;\n\t\t}\n\t\tif (this.offsetValue !== undefined) {\n\t\t\tintent.offset = this.offsetValue;\n\t\t}\n\n\t\t// Lock clause (E15)\n\t\tif (this.lockIntent) {\n\t\t\tif (this.groupByFields.length > 0) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'lock',\n\t\t\t\t\t'FOR UPDATE/SHARE is incompatible with GROUP BY',\n\t\t\t\t);\n\t\t\t}\n\t\t\tintent.lock = this.lockIntent;\n\t\t}\n\n\t\t// JOIN clauses (FR-10)\n\t\tif (this.joinIntents.length > 0) {\n\t\t\tintent.joins = [...this.joinIntents];\n\t\t}\n\n\t\t// BatchValues as primary FROM source\n\t\tif (this.batchValuesSource) {\n\t\t\tintent.batchValuesSource = this.batchValuesSource;\n\t\t}\n\n\t\treturn intent as QueryIntent;\n\t}\n\n\t/**\n\t * Apply defaultFilters to an intent (E17b: applied AFTER hooks for INV-01).\n\t * @internal\n\t */\n\t/** @internal — called by stream-impl */\n\tapplyDefaultFiltersToIntent(intent: QueryIntent): QueryIntent {\n\t\tif (this.skipDefaultFilters || !this.ctx.defaultFilters) return intent;\n\t\tconst tableDefaultFilter = this.ctx.defaultFilters[this.from];\n\t\tif (!tableDefaultFilter) return intent;\n\n\t\tconst existingWhere = intent.where;\n\t\tconst newWhere = existingWhere\n\t\t\t? and(tableDefaultFilter, existingWhere)\n\t\t\t: tableDefaultFilter;\n\n\t\treturn { ...intent, where: newWhere };\n\t}\n\n\t/**\n\t * Execute a query with hook interception (E17b).\n\t * Flow: buildIntent(raw) → beforeQuery → defaultFilters → plan → execute → hydrate → afterQuery\n\t * @internal\n\t */\n\tprivate async executeWithHooks<R>(\n\t\tadapter: Adapter,\n\t\tresultType: QueryResultType,\n\t): Promise<R> {\n\t\tconst store = this.ctx.hookStore;\n\t\tif (!store) throw new Error('executeWithHooks called without hookStore');\n\t\t// INV-07: Re-entrancy guard — prevent infinite loops from hooks issuing queries\n\t\treturn withReentrancyGuard(store, (s) =>\n\t\t\tthis.executeWithHooksInner<R>(adapter, resultType, s),\n\t\t);\n\t}\n\n\tprivate async executeWithHooksInner<R>(\n\t\tadapter: Adapter,\n\t\tresultType: QueryResultType,\n\t\tstore: HookStore,\n\t): Promise<R> {\n\t\tconst startTime = Date.now();\n\n\t\t// 1. Build intent WITHOUT defaultFilters — hooks see raw intent\n\t\tconst rawIntent = this.buildIntent(false);\n\n\t\t// 2. Build beforeQuery context\n\t\tconst beforeCtx: QueryHookContext = {\n\t\t\ttable: this.from,\n\t\t\toperation: 'select',\n\t\t\tintent: rawIntent,\n\t\t\tresultType,\n\t\t\t...(this.ctx.schemaName !== undefined && {\n\t\t\t\tschemaName: this.ctx.schemaName,\n\t\t\t}),\n\t\t\t...(this.ctx.inTransaction && { inTransaction: true }),\n\t\t};\n\n\t\t// 3. Run beforeQuery hooks (FIFO) — may modify intent\n\t\tlet intent: QueryIntent;\n\t\ttry {\n\t\t\tconst afterHookCtx = await runBeforeQueryHooks(\n\t\t\t\tstore.beforeQuery,\n\t\t\t\tbeforeCtx,\n\t\t\t\tthis.ctx.onHookError,\n\t\t\t);\n\t\t\tintent = afterHookCtx.intent;\n\t\t} catch (error) {\n\t\t\t// Run onError hooks for beforeQuery failures\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tconst finalError = await runOnErrorHooks(store.onError, {\n\t\t\t\t\ttable: this.from,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent: rawIntent,\n\t\t\t\t\tphase: 'beforeQuery',\n\t\t\t\t});\n\t\t\t\tthrow finalError;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\t// 4. Apply defaultFilters AFTER hooks (INV-01: cannot be bypassed)\n\t\tintent = this.applyDefaultFiltersToIntent(intent);\n\n\t\t// 5. Apply relation hints and plan\n\t\tconst intentWithHints = this.applyRelationHints(intent);\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...(this.ctx.dialectCapabilities && {\n\t\t\t\tdialectCapabilities: this.ctx.dialectCapabilities,\n\t\t\t}),\n\t\t\t...this.ctx.planOptionsOverride,\n\t\t};\n\n\t\tconst planReport = this.planWithAmbiguityHandling(\n\t\t\tintentWithHints,\n\t\t\tplanOptions,\n\t\t);\n\n\t\t// 6. Compile and execute\n\t\tconst compileOptions: { schemaName?: string; model: ModelIR } = {\n\t\t\tmodel: this.ctx.model,\n\t\t};\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\n\t\tconst compiledWithIncludes = adapter.compileWithIncludes(\n\t\t\tplanReport,\n\t\t\tcompileOptions,\n\t\t);\n\n\t\tlet mainResults: TResult[];\n\t\ttry {\n\t\t\tmainResults = (await adapter.execute(\n\t\t\t\tcompiledWithIncludes.main,\n\t\t\t)) as TResult[];\n\t\t} catch (error) {\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tconst finalError = await runOnErrorHooks(store.onError, {\n\t\t\t\t\ttable: this.from,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent,\n\t\t\t\t\tphase: 'afterQuery',\n\t\t\t\t\tsql: compiledWithIncludes.main.sql,\n\t\t\t\t});\n\t\t\t\tthrow finalError;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\t// 7. Hydrate\n\t\tconst hydrator = new ResultHydrator<TResult>(\n\t\t\tthis.ctx.model,\n\t\t\tthis.from,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t\thydrator.hydrateJsonAggIncludes(mainResults, planReport);\n\t\thydrator.hydrateJoinIncludes(mainResults, planReport);\n\t\tif (compiledWithIncludes.subqueryIncludes.length > 0) {\n\t\t\tawait hydrator.hydrateIncludes(\n\t\t\t\tmainResults,\n\t\t\t\tcompiledWithIncludes.subqueryIncludes,\n\t\t\t\tadapter,\n\t\t\t\tcompileOptions,\n\t\t\t);\n\t\t}\n\t\tif (this.recursiveIncludes.length > 0) {\n\t\t\tawait hydrator.processRecursiveIncludes(\n\t\t\t\tmainResults,\n\t\t\t\tthis.recursiveIncludes,\n\t\t\t\tadapter,\n\t\t\t);\n\t\t}\n\n\t\t// 8. Build afterQuery context with timing + SQL info\n\t\tconst duration = Date.now() - startTime;\n\t\tconst afterCtx: QueryHookContext = {\n\t\t\ttable: this.from,\n\t\t\toperation: 'select',\n\t\t\tintent,\n\t\t\tresultType,\n\t\t\tsql: compiledWithIncludes.main.sql,\n\t\t\tparameters: compiledWithIncludes.main.parameters,\n\t\t\tduration,\n\t\t\t...(this.ctx.schemaName !== undefined && {\n\t\t\t\tschemaName: this.ctx.schemaName,\n\t\t\t}),\n\t\t};\n\n\t\t// 9. Run afterQuery hooks (LIFO) — may transform results\n\t\ttry {\n\t\t\t// SAFETY: R defaults to TResult[] from callers; afterQuery hooks may\n\t\t\t// transform the shape, hence the generic. The double cast bridges\n\t\t\t// the gap between the concrete TResult[] and the generic R.\n\t\t\tconst finalResults = await runAfterQueryHooks(\n\t\t\t\tstore.afterQuery,\n\t\t\t\tafterCtx,\n\t\t\t\tmainResults as unknown as R,\n\t\t\t\tthis.ctx.onHookError,\n\t\t\t);\n\t\t\treturn finalResults;\n\t\t} catch (error) {\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tconst finalError = await runOnErrorHooks(store.onError, {\n\t\t\t\t\ttable: this.from,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent,\n\t\t\t\t\tphase: 'afterQuery',\n\t\t\t\t\tsql: compiledWithIncludes.main.sql,\n\t\t\t\t});\n\t\t\t\tthrow finalError;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Build an existence-check intent from current state.\n\t * Strips orderBy and include (irrelevant), preserves groupBy/having/offset.\n\t */\n\tprivate buildExistsIntent(): QueryIntent {\n\t\tconst baseIntent = this.buildIntent();\n\t\tconst {\n\t\t\torderBy: _orderBy,\n\t\t\tinclude: _include,\n\t\t\t...rest\n\t\t} = baseIntent as QueryIntent & {\n\t\t\torderBy?: unknown;\n\t\t\tinclude?: unknown;\n\t\t};\n\t\treturn {\n\t\t\t...rest,\n\t\t\texistsWrap: true,\n\t\t\tlimit: 1,\n\t\t};\n\t}\n\n\t/**\n\t * Build exists-wrapped intent from a pre-built intent (E17b: for hook-aware path).\n\t * @internal\n\t */\n\tprivate buildExistsIntentFromIntent(baseIntent: QueryIntent): QueryIntent {\n\t\tconst {\n\t\t\torderBy: _orderBy,\n\t\t\tinclude: _include,\n\t\t\t...rest\n\t\t} = baseIntent as QueryIntent & {\n\t\t\torderBy?: unknown;\n\t\t\tinclude?: unknown;\n\t\t};\n\t\treturn {\n\t\t\t...rest,\n\t\t\texistsWrap: true,\n\t\t\tlimit: 1,\n\t\t};\n\t}\n\n\t/**\n\t * Handle ambiguity based on strict mode setting.\n\t */\n\n\t/**\n\t * Thin wrapper around the planner that applies the same ambiguity-handling\n\t * logic as `plan()` (the builder method). Used by exists/existsDump paths\n\t * which build their own planOptions and therefore cannot call `this.plan()`\n\t * directly (which would rebuild the intent from scratch).\n\t *\n\t * FIND-016: exists() / existsDump() called the raw planner function directly,\n\t * bypassing the ambiguity catch that lives in the builder's plan() wrapper.\n\t */\n\t/** @internal — called by stream-impl */\n\tplanWithAmbiguityHandling(\n\t\tintent: QueryIntent,\n\t\tplanOptions: PlanOptions,\n\t): PlanReport {\n\t\ttry {\n\t\t\treturn plan(intent, this.ctx.model, planOptions);\n\t\t} catch (error) {\n\t\t\tif (error instanceof AmbiguousPlanError) {\n\t\t\t\treturn this.handleAmbiguity(error, intent, planOptions);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate handleAmbiguity(\n\t\terror: AmbiguousPlanError,\n\t\tintent: QueryIntent,\n\t\tbasePlanOptions: PlanOptions = {},\n\t): PlanReport {\n\t\tif (this.getEffectiveStrictMode()) {\n\t\t\t// Strict mode: convert to AmbiguousRelationError and throw\n\t\t\tthrow new AmbiguousRelationError(\n\t\t\t\terror.sourceTable,\n\t\t\t\terror.targetTable,\n\t\t\t\terror.options,\n\t\t\t);\n\t\t}\n\n\t\t// Lenient mode: deterministic tie-break — sort alphabetically so that\n\t\t// schema definition order does not influence which relation is chosen.\n\t\t// This ensures stable query results across schema refactoring.\n\t\t// FIND-015: picking options[0] without sorting is non-deterministic.\n\t\tconst sortedOptions = error.options.slice().sort();\n\t\tconst firstRelation = sortedOptions[0];\n\t\tif (!firstRelation) {\n\t\t\tthrow error; // Safety: should never happen\n\t\t}\n\n\t\tconst disambiguateKey = `${error.sourceTable}.${error.targetTable}`;\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...basePlanOptions,\n\t\t\tdisambiguate: {\n\t\t\t\t...basePlanOptions.disambiguate,\n\t\t\t\t[disambiguateKey]: firstRelation, // alphabetically-first (see sortedOptions)\n\t\t\t},\n\t\t};\n\n\t\t// Re-plan with disambiguation\n\t\tconst result = plan(intent, this.ctx.model, planOptions);\n\n\t\t// Add warning about automatic disambiguation.\n\t\t// The chosen relation is the alphabetically-first name (deterministic\n\t\t// tie-break), not insertion order, so schema refactoring cannot silently\n\t\t// change query results.\n\t\tconst warning = {\n\t\t\tcode: 'AMBIGUOUS_RELATION' as const,\n\t\t\tmessage:\n\t\t\t\t`Ambiguous relation to '${error.targetTable}' from '${error.sourceTable}' ` +\n\t\t\t\t`was automatically resolved to '${firstRelation}' (alphabetical tie-break). ` +\n\t\t\t\t`Available options: ${sortedOptions.join(', ')}.`,\n\t\t\tsuggestion: `Use { via: '${firstRelation}' } or another option to make this explicit.`,\n\t\t};\n\n\t\treturn {\n\t\t\t...result,\n\t\t\twarnings: [...result.warnings, warning],\n\t\t};\n\t}\n\n\t/**\n\t * Create a shallow clone of this builder.\n\t *\n\t * The cloned builder owns its own `planOptionsOverride` object reference so\n\t * per-builder overrides do not leak across clones; all other ctx fields are\n\t * intentionally shared by reference — model / adapter / hookStore are part\n\t * of the ORM instance's stable configuration and are treated as read-only\n\t * for the lifetime of the builder chain.\n\t *\n\t * @internal — called by pagination-impl and stream-impl\n\t */\n\tclone(): QueryBuilderImpl<TResult> {\n\t\t// Shallow-clone planOptionsOverride so the cloned builder owns its own\n\t\t// reference and per-builder overrides do not leak across clones.\n\t\treturn this.cloneWithCtxOverride(\n\t\t\tthis.ctx.planOptionsOverride !== undefined\n\t\t\t\t? { planOptionsOverride: { ...this.ctx.planOptionsOverride } }\n\t\t\t\t: {},\n\t\t);\n\t}\n\n\t/**\n\t * Build a new builder whose ctx merges `ctxOverride` over the source ctx.\n\t * Pure merge: callers own the policy of what to spread/clone.\n\t *\n\t * @internal — used by clone() and withPlanOptions().\n\t */\n\tprivate cloneWithCtxOverride(\n\t\tctxOverride: Partial<QueryBuilderContext>,\n\t): QueryBuilderImpl<TResult> {\n\t\tconst builder = new QueryBuilderImpl<TResult>(\n\t\t\t{ ...this.ctx, ...ctxOverride },\n\t\t\tthis.from,\n\t\t\t{ ...this.relationHints },\n\t\t);\n\t\t// Clone array state\n\t\tbuilder.includes.push(...this.includes);\n\t\tbuilder.recursiveIncludes.push(...this.recursiveIncludes);\n\t\tbuilder.whereIntents.push(...this.whereIntents);\n\t\tbuilder.havingIntents.push(...this.havingIntents);\n\t\tbuilder.aggregates.push(...this.aggregates);\n\t\tbuilder.groupByFields.push(...this.groupByFields);\n\t\tbuilder.orderByIntents.push(...this.orderByIntents);\n\t\t// Clone scalar state\n\t\tbuilder.selectIntent = this.selectIntent;\n\t\tbuilder.isDistinctQuery = this.isDistinctQuery;\n\t\tbuilder.distinctOnColumns = [...this.distinctOnColumns];\n\t\tbuilder.skipDefaultFilters = this.skipDefaultFilters;\n\t\tbuilder.strictModeOverride = this.strictModeOverride;\n\t\tbuilder.limitValue = this.limitValue;\n\t\tbuilder.offsetValue = this.offsetValue;\n\t\tbuilder.lockIntent = this.lockIntent;\n\t\tbuilder.joinIntents.push(...this.joinIntents);\n\t\tif (this.batchValuesSource) {\n\t\t\tbuilder.batchValuesSource = this.batchValuesSource;\n\t\t}\n\t\treturn builder;\n\t}\n\n\t/**\n\t * Disable default filters (e.g., soft delete) for this query.\n\t * Use when you need to query deleted/inactive records.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Query all products including soft-deleted ones\n\t * const allProducts = await orm\n\t * .select('products')\n\t * .withoutDefaultFilters()\n\t * .all();\n\t * ```\n\t */\n\t// --------------------------------------------------------------------------\n\t// Set operations (UNION / INTERSECT / EXCEPT)\n\t// --------------------------------------------------------------------------\n\n\tunion(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'union',\n\t\t\t\tfalse,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\tunionAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'union',\n\t\t\t\ttrue,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\tintersect(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'intersect',\n\t\t\t\tfalse,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\tintersectAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'intersect',\n\t\t\t\ttrue,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\texcept(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'except',\n\t\t\t\tfalse,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\texceptAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'except',\n\t\t\t\ttrue,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\twithoutDefaultFilters(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.skipDefaultFilters = true;\n\t\treturn builder;\n\t}\n}\n","/**\n * Raw CTE builder — WITH RECURSIVE support via explicit base/step query builders (FR-8).\n *\n * Provides a fluent API for building arbitrary WITH RECURSIVE queries from\n * a base (anchor) QueryBuilder and a step (recursive) QueryBuilder.\n *\n * @example\n * ```typescript\n * const chain = orm.recursive('parent_chain', {\n * base: orm.select('symbols').where(eq('id', rootId)),\n * step: orm.select('parent_chain'),\n * maxDepth: 10,\n * unionAll: true,\n * });\n * const results = await chain.columns(['id', 'name', 'depth']).orderBy('depth').all();\n * ```\n */\n\nimport type {\n\tAdapter,\n\tCompiledQuery,\n\tCteQueryIntent,\n\tOrderByIntent,\n\tQueryIntent,\n\tRawCteIntent,\n\tSelectWithExpressionsIntent,\n\tWhereIntent,\n} from '@dbsp/types';\nimport { requireAdapter as requireAdapterUtil } from './builder-utils.js';\nimport type { QueryBuilderImpl } from './query-builder.js';\nimport type { QueryBuilder } from './query-builder-types.js';\n\n/**\n * Options for `orm.recursive()`.\n */\nexport interface RecursiveOptions {\n\t/** Base (anchor) query — produces the starting rows. */\n\treadonly base: QueryBuilder<unknown>;\n\t/** Recursive step query — references the CTE name as its FROM table. */\n\treadonly step: QueryBuilder<unknown>;\n\t/** Maximum recursion depth (guards against infinite loops). */\n\treadonly maxDepth?: number;\n\t/**\n\t * Column name in the step query that tracks depth (used with maxDepth).\n\t * When set, injects WHERE <depthColumn> < maxDepth into the step during compilation.\n\t * @default 'depth'\n\t */\n\treadonly depthColumn?: string;\n\t/** When true (default), use UNION ALL. When false, use UNION (deduplicates). */\n\treadonly unionAll?: boolean;\n}\n\n/**\n * Result of compiling a recursive CTE query.\n */\nexport interface RecursiveDump {\n\treadonly sql: string;\n\treadonly params: readonly unknown[];\n\treadonly intent: CteQueryIntent;\n}\n\n/**\n * Fluent builder for constructing and executing a WITH RECURSIVE query.\n *\n * Obtain via `orm.recursive(name, options)`.\n */\nexport class RawCteQueryBuilder<TResult = unknown> {\n\tprivate readonly cteName: string;\n\tprivate readonly rawCteIntent: RawCteIntent;\n\tprivate readonly adapter: Adapter | undefined;\n\tprivate readonly schemaName: string | undefined;\n\n\tprivate outerSelect: SelectWithExpressionsIntent | undefined;\n\tprivate outerWhere: WhereIntent | undefined;\n\tprivate outerOrderBy: OrderByIntent[] | undefined;\n\tprivate outerLimit: number | undefined;\n\tprivate outerOffset: number | undefined;\n\n\tconstructor(\n\t\tcteName: string,\n\t\trawCteIntent: RawCteIntent,\n\t\tadapter?: Adapter,\n\t\tschemaName?: string,\n\t) {\n\t\tthis.cteName = cteName;\n\t\tthis.rawCteIntent = rawCteIntent;\n\t\tthis.adapter = adapter;\n\t\tthis.schemaName = schemaName;\n\t}\n\n\t/**\n\t * Select specific columns from the CTE result.\n\t */\n\tcolumns(cols: readonly string[]): this {\n\t\tthis.outerSelect = {\n\t\t\ttype: 'expressions',\n\t\t\tcolumns: cols.map((column) => ({ kind: 'column', column })),\n\t\t};\n\t\treturn this;\n\t}\n\n\t/**\n\t * Filter the outer query result.\n\t */\n\twhere(condition: WhereIntent): this {\n\t\tthis.outerWhere = condition;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Order the outer query result.\n\t */\n\torderBy(column: string, direction: 'asc' | 'desc' = 'asc'): this {\n\t\tconst clause: OrderByIntent = { field: column, direction };\n\t\tthis.outerOrderBy = [...(this.outerOrderBy ?? []), clause];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Limit the number of rows returned.\n\t */\n\tlimit(n: number): this {\n\t\tthis.outerLimit = n;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Skip the first N rows.\n\t */\n\toffset(n: number): this {\n\t\tthis.outerOffset = n;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Build the CteQueryIntent AST.\n\t */\n\tbuildIntent(): CteQueryIntent {\n\t\tconst outerIntent: QueryIntent = {\n\t\t\ttype: 'select',\n\t\t\tfrom: this.cteName,\n\t\t\t...(this.outerSelect !== undefined && { select: this.outerSelect }),\n\t\t\t...(this.outerWhere !== undefined && { where: this.outerWhere }),\n\t\t\t...(this.outerOrderBy !== undefined && { orderBy: this.outerOrderBy }),\n\t\t\t...(this.outerLimit !== undefined && { limit: this.outerLimit }),\n\t\t\t...(this.outerOffset !== undefined && { offset: this.outerOffset }),\n\t\t};\n\n\t\treturn {\n\t\t\tkind: 'cteQuery',\n\t\t\tctes: [this.rawCteIntent],\n\t\t\tquery: outerIntent,\n\t\t};\n\t}\n\n\tprivate requireAdapter(): Adapter {\n\t\treturn requireAdapterUtil(this.adapter, 'recursive');\n\t}\n\n\t/**\n\t * Compile to SQL and return an observability dump.\n\t */\n\tdump(): RecursiveDump {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions = this.schemaName\n\t\t\t? { schemaName: this.schemaName }\n\t\t\t: undefined;\n\t\tconst compiled: CompiledQuery = adapter.compileCteQuery(\n\t\t\tintent,\n\t\t\tcompileOptions,\n\t\t);\n\t\treturn {\n\t\t\tsql: compiled.sql,\n\t\t\tparams: compiled.parameters,\n\t\t\tintent,\n\t\t};\n\t}\n\n\t/**\n\t * Execute the recursive CTE query and return all matching rows.\n\t */\n\tasync all(): Promise<TResult[]> {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions = this.schemaName\n\t\t\t? { schemaName: this.schemaName }\n\t\t\t: undefined;\n\t\tconst compiled = adapter.compileCteQuery(\n\t\t\tintent,\n\t\t\tcompileOptions,\n\t\t) as CompiledQuery<TResult>;\n\t\treturn adapter.execute(compiled);\n\t}\n\n\t/**\n\t * Alias for `all()`.\n\t */\n\texecute(): Promise<TResult[]> {\n\t\treturn this.all();\n\t}\n}\n\n/**\n * Create a RawCteQueryBuilder from named builder instances.\n */\nexport function createRawCteBuilder<TResult = unknown>(\n\tcteName: string,\n\toptions: RecursiveOptions,\n\tadapter?: Adapter,\n\tschemaName?: string,\n): RawCteQueryBuilder<TResult> {\n\tconst baseIntent = (\n\t\toptions.base as unknown as QueryBuilderImpl<unknown>\n\t).buildIntent();\n\tconst stepIntent = (\n\t\toptions.step as unknown as QueryBuilderImpl<unknown>\n\t).buildIntent();\n\n\tconst rawCteIntent: RawCteIntent = {\n\t\tkind: 'rawCte',\n\t\tname: cteName,\n\t\tbase: baseIntent,\n\t\tstep: stepIntent,\n\t\tunionAll: options.unionAll ?? true,\n\t\t...(options.maxDepth !== undefined && { maxDepth: options.maxDepth }),\n\t\t...(options.depthColumn !== undefined && {\n\t\t\tdepthColumn: options.depthColumn,\n\t\t}),\n\t};\n\n\treturn new RawCteQueryBuilder<TResult>(\n\t\tcteName,\n\t\trawCteIntent,\n\t\tadapter,\n\t\tschemaName,\n\t);\n}\n","import type { Adapter } from '../adapter.js';\nimport type { DialectCapabilities } from '../dialects/index.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanOptions } from '../planner.js';\nimport type { BatchValuesOptions, BatchValuesRef } from './batch-values.js';\nimport { batchValues } from './batch-values.js';\nimport { CteBuilder } from './cte-builder.js';\nimport { InvalidOperationError, validateIdentifier } from './errors.js';\nimport { eq } from './filters.js';\nimport {\n\textractRecursiveField,\n\tfindSelfRefRelation,\n} from './hierarchy-helpers.js';\nimport type { HookErrorHandler, HookStore } from './hooks.js';\nimport {\n\tDeleteBuilder,\n\tInsertBuilder,\n\tUpdateBuilder,\n\tUpsertBuilder,\n} from './mutation-builders.js';\nimport { createNqlTag, type NqlTag } from './nql.js';\nimport type { SelectExpressionResult } from './orm-instance-types.js';\nimport { QueryBuilderImpl } from './query-builder.js';\nimport type { QueryBuilderContext } from './query-builder-context.js';\nimport {\n\tcreateRawCteBuilder,\n\ttype RawCteQueryBuilder,\n\ttype RecursiveOptions,\n} from './raw-cte-builder.js';\nimport type { DefaultFilters } from './schema.js';\nimport { TABLE_META } from './symbols.js';\nimport type {\n\tAlterColumnOptions,\n\tCreateIndexOptions,\n\tDropIndexOptions,\n\tIndexInfo,\n\tTableDDL,\n\tTruncateOptions,\n\tVacuumOptions,\n} from './table-ddl-types.js';\nimport type { InferTableRow, TableRef } from './table-ref.js';\nimport type {\n\tExpressionSpec,\n\tListHierarchyOptions,\n\tOrmInstance,\n\tOrmInstanceInternal,\n\tQueryBuilder,\n\tRelationHints,\n} from './types.js';\n\n/**\n * Quote a PostgreSQL identifier (table/schema/column name).\n * Simple double-quoting — no validation, validation is caller's responsibility.\n */\n\n/**\n * Build the qualified table reference string for DDL statements.\n */\n\n/**\n * Build the DDL methods object for a specific table.\n */\n// ─── DDL SQL generation helpers ──────────────────────────────────────────────\n\n/** Double-quote a PostgreSQL identifier. */\nfunction quoteIdent(name: string): string {\n\treturn `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\n/** Build a qualified `\"schema\".\"table\"` or `\"table\"` reference. */\nfunction buildQualifiedTable(\n\ttableName: string,\n\tschemaName: string | undefined,\n): string {\n\treturn schemaName\n\t\t? `${quoteIdent(schemaName)}.${quoteIdent(tableName)}`\n\t\t: quoteIdent(tableName);\n}\n\nfunction generateTruncateSQL(\n\ttableName: string,\n\tschemaName: string | undefined,\n\toptions: TruncateOptions | undefined,\n): string {\n\tconst parts = [`TRUNCATE ${buildQualifiedTable(tableName, schemaName)}`];\n\tif (options?.restartIdentity) parts.push('RESTART IDENTITY');\n\tif (options?.cascade) parts.push('CASCADE');\n\treturn parts.join(' ');\n}\n\nfunction generateVacuumSQL(\n\ttableName: string,\n\tschemaName: string | undefined,\n\toptions: VacuumOptions | undefined,\n): string {\n\tconst modifiers: string[] = [];\n\tif (options?.full) modifiers.push('FULL');\n\tif (options?.analyze) modifiers.push('ANALYZE');\n\tconst mod = modifiers.length > 0 ? `(${modifiers.join(', ')}) ` : '';\n\treturn `VACUUM ${mod}${buildQualifiedTable(tableName, schemaName)}`;\n}\n\nfunction generateAlterColumnSQL(\n\ttableName: string,\n\tcolumn: string,\n\tschemaName: string | undefined,\n\toptions: AlterColumnOptions,\n): string {\n\tconst tbl = buildQualifiedTable(tableName, schemaName);\n\tconst col = quoteIdent(column);\n\tconst clauses: string[] = [];\n\n\tif (options.type !== undefined) {\n\t\tlet clause = `ALTER COLUMN ${col} TYPE ${options.type}`;\n\t\tif (options.using !== undefined) {\n\t\t\tclause += ` USING ${options.using}`;\n\t\t}\n\t\tclauses.push(clause);\n\t}\n\tif (options.setNotNull === true) {\n\t\tclauses.push(`ALTER COLUMN ${col} SET NOT NULL`);\n\t} else if (options.setNotNull === false) {\n\t\tclauses.push(`ALTER COLUMN ${col} DROP NOT NULL`);\n\t}\n\tif (options.dropDefault === true) {\n\t\tclauses.push(`ALTER COLUMN ${col} DROP DEFAULT`);\n\t} else if (options.setDefault !== undefined) {\n\t\tclauses.push(`ALTER COLUMN ${col} SET DEFAULT ${options.setDefault}`);\n\t}\n\tif (clauses.length === 0) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'alterColumn',\n\t\t\t'At least one alteration option must be specified.',\n\t\t);\n\t}\n\treturn `ALTER TABLE ${tbl} ${clauses.join(', ')}`;\n}\n\nfunction generateCreateIndexSQL(\n\ttableName: string,\n\tschemaName: string | undefined,\n\topts: CreateIndexOptions,\n): string {\n\tconst tbl = buildQualifiedTable(tableName, schemaName);\n\tconst parts: string[] = ['CREATE'];\n\tif (opts.unique) parts.push('UNIQUE');\n\tparts.push('INDEX');\n\tif (opts.concurrently) parts.push('CONCURRENTLY');\n\tif (opts.ifNotExists) parts.push('IF NOT EXISTS');\n\tparts.push(quoteIdent(opts.name));\n\tparts.push('ON');\n\tparts.push(tbl);\n\tif (opts.method) parts.push(`USING ${opts.method}`);\n\n\tconst colDefs = opts.columns.map((col) => {\n\t\tif (typeof col === 'string') {\n\t\t\tconst quotedCol = quoteIdent(col);\n\t\t\tconst op = opts.opclass?.[col] != null ? ` ${opts.opclass[col]}` : '';\n\t\t\treturn `${quotedCol}${op}`;\n\t\t}\n\t\tconst op = col.opclass != null ? ` ${col.opclass}` : '';\n\t\treturn `(${col.expression})${op}`;\n\t});\n\tparts.push(`(${colDefs.join(', ')})`);\n\n\tif (opts.include && opts.include.length > 0) {\n\t\tparts.push(\n\t\t\t`INCLUDE (${opts.include.map((c) => quoteIdent(c)).join(', ')})`,\n\t\t);\n\t}\n\tif (opts.with && Object.keys(opts.with).length > 0) {\n\t\tconst withClauses = Object.entries(opts.with)\n\t\t\t.map(([k, v]) => `${k} = ${v}`)\n\t\t\t.join(', ');\n\t\tparts.push(`WITH (${withClauses})`);\n\t}\n\tif (opts.where) parts.push(`WHERE ${opts.where}`);\n\treturn parts.join(' ');\n}\n\nfunction generateDropIndexSQL(\n\tname: string,\n\tschemaName: string | undefined,\n\toptions: DropIndexOptions | undefined,\n): string {\n\tconst parts: string[] = ['DROP INDEX'];\n\tif (options?.concurrently) parts.push('CONCURRENTLY');\n\tif (options?.ifExists) parts.push('IF EXISTS');\n\tconst sc = options?.schema ?? schemaName;\n\tparts.push(sc ? `${quoteIdent(sc)}.${quoteIdent(name)}` : quoteIdent(name));\n\tif (options?.cascade) parts.push('CASCADE');\n\treturn parts.join(' ');\n}\n\n// ─── indexes sub-API builder ──────────────────────────────────────────────────\n\nfunction buildIndexAPI(\n\ttableName: string,\n\tschemaName: string | undefined,\n\tadapter: Adapter<unknown> | undefined,\n\trequireAdapter: () => Adapter<unknown>,\n): TableDDL['indexes'] {\n\treturn {\n\t\tasync create(opts: CreateIndexOptions): Promise<void> {\n\t\t\tconst a = requireAdapter();\n\t\t\tif (opts.concurrently && a.inTransaction) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'createIndex',\n\t\t\t\t\t'CREATE INDEX CONCURRENTLY cannot run inside a transaction block',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst sql = a.generateCreateIndex\n\t\t\t\t? a.generateCreateIndex(tableName, opts, schemaName)\n\t\t\t\t: generateCreateIndexSQL(tableName, schemaName, opts);\n\t\t\tawait a.executeDDL?.(sql);\n\t\t},\n\n\t\tasync drop(name: string, options?: DropIndexOptions): Promise<void> {\n\t\t\tconst a = requireAdapter();\n\t\t\tif (options?.concurrently && a.inTransaction) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'dropIndex',\n\t\t\t\t\t'DROP INDEX CONCURRENTLY cannot run inside a transaction block',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst sql = a.generateDropIndex\n\t\t\t\t? a.generateDropIndex(name, options)\n\t\t\t\t: generateDropIndexSQL(name, schemaName, options);\n\t\t\tawait a.executeDDL?.(sql);\n\t\t},\n\n\t\tasync list(options?: { namePattern?: string }): Promise<IndexInfo[]> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'indexes.list',\n\t\t\t\t\t'indexes.list() requires an adapter.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (adapter.listIndexes) {\n\t\t\t\treturn adapter.listIndexes(tableName, schemaName, options);\n\t\t\t}\n\t\t\t// Fallback for adapters without listIndexes: use executeRaw if available\n\t\t\tconst sql =\n\t\t\t\t`SELECT indexname AS name, indexdef AS definition, ` +\n\t\t\t\t`(SELECT indisunique FROM pg_index WHERE indexrelid = (SELECT oid FROM pg_class WHERE relname = indexname)) AS unique, ` +\n\t\t\t\t`CASE WHEN indexdef LIKE '%USING %' THEN split_part(indexdef, 'USING ', 2) ELSE 'btree' END AS method ` +\n\t\t\t\t`FROM pg_indexes WHERE tablename = '${tableName.replace(/'/g, \"''\")}' ` +\n\t\t\t\t(schemaName\n\t\t\t\t\t? `AND schemaname = '${schemaName.replace(/'/g, \"''\")}' `\n\t\t\t\t\t: '') +\n\t\t\t\t`ORDER BY indexname`;\n\t\t\tif ('executeRaw' in adapter && typeof adapter.executeRaw === 'function') {\n\t\t\t\tconst rows = await (\n\t\t\t\t\tadapter.executeRaw as (\n\t\t\t\t\t\tsql: string,\n\t\t\t\t\t\tparams: unknown[],\n\t\t\t\t\t) => Promise<unknown[]>\n\t\t\t\t)(sql, []);\n\t\t\t\treturn rows as IndexInfo[];\n\t\t\t}\n\t\t\t// Fallback: use executeDDL (adapter must handle SELECT)\n\t\t\tif (adapter.executeDDL) await adapter.executeDDL(sql);\n\t\t\treturn [];\n\t\t},\n\n\t\tasync exists(name: string): Promise<boolean> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'indexes.exists',\n\t\t\t\t\t'indexes.exists() requires an adapter.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!adapter.indexExists) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'indexes.exists',\n\t\t\t\t\t'indexes.exists() requires an adapter that implements indexExists().',\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn adapter.indexExists(name, tableName, schemaName);\n\t\t},\n\t};\n}\n\n// ─── Public assembler ─────────────────────────────────────────────────────────\n\n/**\n * Build the DDL methods object for a specific table.\n */\nfunction buildTableDDL(\n\ttableName: string,\n\tschemaName: string | undefined,\n\tadapter: Adapter<unknown> | undefined,\n): TableDDL {\n\tfunction requireAdapter(): Adapter<unknown> {\n\t\tif (!adapter?.executeDDL) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'table DDL',\n\t\t\t\t'executeDDL() requires an adapter that supports DDL execution. ' +\n\t\t\t\t\t'Pass an adapter with executeDDL when creating the ORM.',\n\t\t\t);\n\t\t}\n\t\treturn adapter;\n\t}\n\n\treturn {\n\t\tasync truncate(options?: TruncateOptions): Promise<void> {\n\t\t\tconst a = requireAdapter();\n\t\t\tconst sql = a.generateTruncate\n\t\t\t\t? a.generateTruncate(tableName, schemaName, options)\n\t\t\t\t: generateTruncateSQL(tableName, schemaName, options);\n\t\t\tawait a.executeDDL?.(sql);\n\t\t},\n\n\t\tasync vacuum(options?: VacuumOptions): Promise<void> {\n\t\t\tconst a = requireAdapter();\n\t\t\tif (a.inTransaction) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'vacuum',\n\t\t\t\t\t'VACUUM cannot run inside a transaction block',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst sql = a.generateVacuum\n\t\t\t\t? a.generateVacuum(tableName, schemaName, options)\n\t\t\t\t: generateVacuumSQL(tableName, schemaName, options);\n\t\t\tawait a.executeDDL?.(sql);\n\t\t},\n\n\t\tasync alterColumn(\n\t\t\tcolumn: string,\n\t\t\toptions: AlterColumnOptions,\n\t\t): Promise<void> {\n\t\t\tvalidateIdentifier(tableName, 'table');\n\t\t\tvalidateIdentifier(column, 'column');\n\t\t\tconst a = requireAdapter();\n\t\t\tconst sql = a.generateAlterColumn\n\t\t\t\t? a.generateAlterColumn(tableName, column, options, schemaName)\n\t\t\t\t: generateAlterColumnSQL(tableName, column, schemaName, options);\n\t\t\tawait a.executeDDL?.(sql);\n\t\t},\n\n\t\tindexes: buildIndexAPI(tableName, schemaName, adapter, requireAdapter),\n\n\t\tasync storageSize(): Promise<number> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'storageSize',\n\t\t\t\t\t'storageSize() requires an adapter.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!adapter.storageSize) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'storageSize',\n\t\t\t\t\t'storageSize() requires an adapter that implements storageSize().',\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn adapter.storageSize(tableName, schemaName);\n\t\t},\n\t};\n}\n\n/**\n * Wrap a tables proxy (from createTablesProxy or schema.tables) with DDL methods.\n * The returned proxy intercepts property access on each table name and augments\n * the returned TableRef object with a `TableDDL` mixin.\n */\nexport function wrapTablesProxyWithDDL(\n\ttablesProxy: object,\n\tadapter: Adapter<unknown> | undefined,\n\tschemaName: string | undefined,\n): object {\n\t// Cache augmented table objects to preserve referential equality\n\tconst cache = new Map<string, object>();\n\n\treturn new Proxy(tablesProxy, {\n\t\tget(target, prop, receiver) {\n\t\t\t// Pass through Symbol and non-string properties unchanged\n\t\t\tif (typeof prop !== 'string') {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\tif (cache.has(prop)) {\n\t\t\t\treturn cache.get(prop);\n\t\t\t}\n\n\t\t\tconst tableRef = Reflect.get(target, prop, receiver);\n\t\t\tif (tableRef === undefined || tableRef === null) {\n\t\t\t\treturn tableRef;\n\t\t\t}\n\n\t\t\t// Augment the TableRef with DDL methods\n\t\t\tconst ddl = buildTableDDL(prop, schemaName, adapter);\n\t\t\tconst augmented = Object.assign(Object.create(null), tableRef, ddl);\n\t\t\tcache.set(prop, augmented);\n\t\t\treturn augmented;\n\t\t},\n\t});\n}\n\n/**\n * Internal factory for creating ORM instances.\n * Supports optional schema name for multi-tenant scenarios.\n *\n * @typeParam DB - Database schema type (passed through from createOrm)\n */\nexport function createOrmInstance<DB = Record<string, unknown>>(\n\tmodel: ModelIR,\n\tstrictMode: boolean,\n\trelationHints: RelationHints,\n\tadapter?: Adapter<DB>,\n\tschemaName?: string,\n\tdialectCapabilities?: DialectCapabilities,\n\tschemaDefinition?: unknown,\n\tglobalPlanOptions?: PlanOptions,\n\tdefaultFilters?: DefaultFilters,\n\thookStore?: HookStore,\n\tonHookError?: HookErrorHandler,\n\tinTransaction?: boolean,\n\ttablesProxy?: object,\n): OrmInstanceInternal<DB> {\n\t// Create NQL template tag (DX-040)\n\t// NQL compiler is now integrated directly - @dbsp/nql is imported in nql.ts\n\tconst nql: NqlTag = createNqlTag(\n\t\tschemaDefinition,\n\t\tmodel,\n\t\tadapter as Adapter<unknown> | undefined,\n\t\tschemaName,\n\t);\n\n\t// Helper: build a MutationBuilder options object (shared across mutation methods)\n\tconst mutationOpts = {\n\t\tmodel,\n\t\tadapter,\n\t\tschemaName,\n\t\thookStore,\n\t\tonHookError,\n\t\tinTransaction,\n\t} as const;\n\n\t// Context bag for QueryBuilderImpl — eliminates the 12-param positional constructor\n\tconst queryCtx: QueryBuilderContext = {\n\t\tmodel,\n\t\tstrictMode,\n\t\t...(adapter !== undefined ? { adapter: adapter as Adapter<unknown> } : {}),\n\t\t...(schemaName !== undefined ? { schemaName } : {}),\n\t\t...(dialectCapabilities !== undefined ? { dialectCapabilities } : {}),\n\t\t...(globalPlanOptions !== undefined\n\t\t\t? { planOptionsOverride: globalPlanOptions }\n\t\t\t: {}),\n\t\t...(defaultFilters !== undefined ? { defaultFilters } : {}),\n\t\t...(hookStore !== undefined ? { hookStore } : {}),\n\t\t...(onHookError !== undefined ? { onHookError } : {}),\n\t\t...(inTransaction !== undefined ? { inTransaction } : {}),\n\t};\n\n\t// Wrap the tables proxy to augment each table access with DDL methods\n\tconst tablesDDLProxy = wrapTablesProxyWithDDL(\n\t\ttablesProxy ?? {},\n\t\tadapter as Adapter<unknown> | undefined,\n\t\tschemaName,\n\t);\n\n\treturn {\n\t\tstrictMode,\n\t\tnql,\n\t\ttables: tablesDDLProxy as OrmInstance<DB>['tables'],\n\t\t// biome-ignore lint/suspicious/noExplicitAny: polymorphic constraint — TTable is inferred by callers; TableRef generics are statically erased in this implementation signature\n\t\tfrom<TTable extends TableRef<any, any, any>>(\n\t\t\ttable: TTable | BatchValuesRef,\n\t\t):\n\t\t\t| QueryBuilder<InferTableRow<TTable>>\n\t\t\t| QueryBuilder<Record<string, unknown>> {\n\t\t\t// BatchValuesRef path\n\t\t\tif (\n\t\t\t\ttypeof table === 'object' &&\n\t\t\t\ttable !== null &&\n\t\t\t\t'__kind' in table &&\n\t\t\t\t(table as unknown as BatchValuesRef).__kind === 'batchValues'\n\t\t\t) {\n\t\t\t\tconst bv = table as unknown as BatchValuesRef;\n\t\t\t\tconst builder = new QueryBuilderImpl<Record<string, unknown>>(\n\t\t\t\t\tqueryCtx,\n\t\t\t\t\tbv.alias,\n\t\t\t\t\trelationHints,\n\t\t\t\t);\n\t\t\t\tbuilder.batchValuesSource = {\n\t\t\t\t\tdata: bv.data,\n\t\t\t\t\tcolumns: bv.columns,\n\t\t\t\t\ttypes: bv.types,\n\t\t\t\t\talias: bv.alias,\n\t\t\t\t\tordinality: bv.ordinality,\n\t\t\t\t};\n\t\t\t\treturn builder;\n\t\t\t}\n\t\t\tconst tableRef = table as TTable;\n\t\t\tconst tableName = tableRef[TABLE_META];\n\t\t\tif (tableName === undefined) {\n\t\t\t\tthrow new Error('Invalid TableRef: missing TABLE_META symbol');\n\t\t\t}\n\t\t\treturn new QueryBuilderImpl<InferTableRow<TTable>>(\n\t\t\t\tqueryCtx,\n\t\t\t\ttableName as string,\n\t\t\t\trelationHints,\n\t\t\t);\n\t\t},\n\t\tselect<K extends keyof DB & string, TResult = DB[K]>(\n\t\t\tfrom: K,\n\t\t): QueryBuilder<TResult> {\n\t\t\treturn new QueryBuilderImpl<TResult>(\n\t\t\t\tqueryCtx,\n\t\t\t\tfrom as string,\n\t\t\t\trelationHints,\n\t\t\t);\n\t\t},\n\t\twithSchema(schemaName: string): OrmInstanceInternal<DB> {\n\t\t\t// Always validate schema name — even without an adapter — to prevent injection\n\t\t\tvalidateIdentifier(schemaName, 'schema');\n\t\t\tif (adapter) {\n\t\t\t\tadapter.validateIdentifier(schemaName, 'schema');\n\t\t\t}\n\t\t\t// Create a schema-scoped adapter if we have one\n\t\t\tconst scopedAdapter = adapter?.withSchema(schemaName);\n\t\t\treturn createOrmInstance(\n\t\t\t\tmodel,\n\t\t\t\tstrictMode,\n\t\t\t\trelationHints,\n\t\t\t\tscopedAdapter as Adapter<DB> | undefined,\n\t\t\t\tschemaName,\n\t\t\t\tdialectCapabilities,\n\t\t\t\tschemaDefinition,\n\t\t\t\tglobalPlanOptions,\n\t\t\t\tdefaultFilters,\n\t\t\t\thookStore,\n\t\t\t\tonHookError,\n\t\t\t\tinTransaction,\n\t\t\t\ttablesProxy,\n\t\t\t);\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Hierarchy List Methods (DX-022)\n\t\t// Returns flat arrays, uses include() with recursive: true internally\n\t\t// =====================================================================\n\n\t\t/**\n\t\t * List all ancestors of a node as a flat array.\n\t\t * Uses the new include({ recursive: true }) API internally.\n\t\t *\n\t\t * @param table - The table name\n\t\t * @param nodeIdValue - The starting node's ID value\n\t\t * @param options - Options including parentId column name\n\t\t * @returns Promise resolving to array of ancestor records\n\t\t */\n\t\tasync listAncestors<TResult = unknown>(\n\t\t\ttable: string,\n\t\t\tnodeIdValue: unknown,\n\t\t\toptions: ListHierarchyOptions,\n\t\t): Promise<TResult[]> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'listAncestors() requires an adapter. ' +\n\t\t\t\t\t\t'Pass an adapter when creating the ORM.',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// FIND-001: Validate table against known tables before use in error messages\n\t\t\tif (!model.getTable(table)) {\n\t\t\t\tthrow new InvalidOperationError('listAncestors', 'Table not found');\n\t\t\t}\n\n\t\t\t// FIND-007: Cap maxDepth to prevent infinite/excessive recursion.\n\t\t\t// Use isSafeInteger to reject fractional values (e.g. 1.5) that\n\t\t\t// Number.isFinite would accept.\n\t\t\tconst MAX_RECURSION_DEPTH = 1000;\n\t\t\tconst rawMaxDepth = options.maxDepth ?? 100;\n\t\t\tif (!Number.isSafeInteger(rawMaxDepth) || rawMaxDepth < 1) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'listAncestors',\n\t\t\t\t\t'maxDepth must be a positive safe integer',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst safeMaxDepth = Math.min(rawMaxDepth, MAX_RECURSION_DEPTH);\n\n\t\t\t// Find the self-referential relation that matches the parent direction\n\t\t\tconst selfRefRelation = findSelfRefRelation(model, table, 'ancestors');\n\t\t\tif (!selfRefRelation) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'listAncestors',\n\t\t\t\t\t'Table has no self-referential belongsTo/hasOne relation for ancestor traversal',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst nodeIdCol = options.nodeId ?? 'id';\n\n\t\t\t// Hierarchy helpers historically did NOT propagate inTransaction. Preserve that behavior.\n\t\t\tconst { inTransaction: _ignored, ...hierarchyCtxBase } = queryCtx;\n\t\t\tconst hierarchyCtx: QueryBuilderContext = hierarchyCtxBase;\n\n\t\t\tconst builder = new QueryBuilderImpl<TResult>(\n\t\t\t\thierarchyCtx,\n\t\t\t\ttable,\n\t\t\t\trelationHints,\n\t\t\t);\n\n\t\t\tconst result = await builder\n\t\t\t\t.where(eq(nodeIdCol, nodeIdValue))\n\t\t\t\t.include(selfRefRelation.name, {\n\t\t\t\t\trecursive: true,\n\t\t\t\t\tdirection: 'ancestors',\n\t\t\t\t\tflat: true,\n\t\t\t\t\tomitSelf: true,\n\t\t\t\t\tmaxDepth: safeMaxDepth,\n\t\t\t\t})\n\t\t\t\t.first();\n\n\t\t\t// Result shape from include({ recursive, direction: 'ancestors' }):\n\t\t\t// { id, ..., ancestors: [...] }\n\t\t\treturn extractRecursiveField<TResult>(result, 'ancestors');\n\t\t},\n\n\t\t/**\n\t\t * List all descendants of a node as a flat array.\n\t\t * Uses the new include({ recursive: true }) API internally.\n\t\t *\n\t\t * @param table - The table name\n\t\t * @param nodeIdValue - The starting node's ID value\n\t\t * @param options - Options including parentId column name\n\t\t * @returns Promise resolving to array of descendant records\n\t\t */\n\t\tasync listDescendants<TResult = unknown>(\n\t\t\ttable: string,\n\t\t\tnodeIdValue: unknown,\n\t\t\toptions: ListHierarchyOptions,\n\t\t): Promise<TResult[]> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'listDescendants() requires an adapter. ' +\n\t\t\t\t\t\t'Pass an adapter when creating the ORM.',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// FIND-001: Validate table against known tables before use in error messages\n\t\t\tif (!model.getTable(table)) {\n\t\t\t\tthrow new InvalidOperationError('listDescendants', 'Table not found');\n\t\t\t}\n\n\t\t\t// FIND-007: Cap maxDepth to prevent infinite/excessive recursion.\n\t\t\t// Use isSafeInteger to reject fractional values (e.g. 1.5) that\n\t\t\t// Number.isFinite would accept.\n\t\t\tconst MAX_RECURSION_DEPTH = 1000;\n\t\t\tconst rawMaxDepth = options.maxDepth ?? 100;\n\t\t\tif (!Number.isSafeInteger(rawMaxDepth) || rawMaxDepth < 1) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'listDescendants',\n\t\t\t\t\t'maxDepth must be a positive safe integer',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst safeMaxDepth = Math.min(rawMaxDepth, MAX_RECURSION_DEPTH);\n\n\t\t\t// Find the self-referential relation that matches the children direction\n\t\t\tconst selfRefRelation = findSelfRefRelation(model, table, 'descendants');\n\t\t\tif (!selfRefRelation) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'listDescendants',\n\t\t\t\t\t'Table has no self-referential hasMany relation for descendant traversal',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst nodeIdCol = options.nodeId ?? 'id';\n\n\t\t\t// Hierarchy helpers historically did NOT propagate inTransaction. Preserve that behavior.\n\t\t\tconst { inTransaction: _ignored, ...hierarchyCtxBase } = queryCtx;\n\t\t\tconst hierarchyCtx: QueryBuilderContext = hierarchyCtxBase;\n\n\t\t\tconst builder = new QueryBuilderImpl<TResult>(\n\t\t\t\thierarchyCtx,\n\t\t\t\ttable,\n\t\t\t\trelationHints,\n\t\t\t);\n\n\t\t\tconst result = await builder\n\t\t\t\t.where(eq(nodeIdCol, nodeIdValue))\n\t\t\t\t.include(selfRefRelation.name, {\n\t\t\t\t\trecursive: true,\n\t\t\t\t\tdirection: 'descendants',\n\t\t\t\t\tflat: true,\n\t\t\t\t\tomitSelf: true,\n\t\t\t\t\tmaxDepth: safeMaxDepth,\n\t\t\t\t})\n\t\t\t\t.first();\n\n\t\t\t// Result shape from include({ recursive, direction: 'descendants' }):\n\t\t\t// { id, ..., descendants: [...] }\n\t\t\treturn extractRecursiveField<TResult>(result, 'descendants');\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Typed Mutation Entry Points (DX-040-SURFACE)\n\t\t// Extract table name from TableRef metadata and delegate to string methods\n\t\t// =====================================================================\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: polymorphic constraint — TTable is inferred by callers; TableRef generics are statically erased in this implementation signature\n\t\tinto<TTable extends TableRef<any, any, any>>(\n\t\t\ttableRef: TTable,\n\t\t): InsertBuilder<InferTableRow<TTable>> {\n\t\t\tconst tableName = tableRef[TABLE_META];\n\t\t\tif (tableName === undefined) {\n\t\t\t\tthrow new Error('Invalid TableRef: missing TABLE_META symbol');\n\t\t\t}\n\t\t\treturn new InsertBuilder({\n\t\t\t\ttable: tableName as string,\n\t\t\t\t...mutationOpts,\n\t\t\t}) as InsertBuilder<InferTableRow<TTable>>;\n\t\t},\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: polymorphic constraint — TTable is inferred by callers; TableRef generics are statically erased in this implementation signature\n\t\tmodify<TTable extends TableRef<any, any, any>>(\n\t\t\ttableRef: TTable,\n\t\t): UpdateBuilder<InferTableRow<TTable>> {\n\t\t\tconst tableName = tableRef[TABLE_META];\n\t\t\tif (tableName === undefined) {\n\t\t\t\tthrow new Error('Invalid TableRef: missing TABLE_META symbol');\n\t\t\t}\n\t\t\treturn new UpdateBuilder({\n\t\t\t\ttable: tableName as string,\n\t\t\t\t...mutationOpts,\n\t\t\t}) as UpdateBuilder<InferTableRow<TTable>>;\n\t\t},\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: polymorphic constraint — TTable is inferred by callers; TableRef generics are statically erased in this implementation signature\n\t\tremoveFrom<TTable extends TableRef<any, any, any>>(\n\t\t\ttableRef: TTable,\n\t\t): DeleteBuilder<InferTableRow<TTable>> {\n\t\t\tconst tableName = tableRef[TABLE_META];\n\t\t\tif (tableName === undefined) {\n\t\t\t\tthrow new Error('Invalid TableRef: missing TABLE_META symbol');\n\t\t\t}\n\t\t\treturn new DeleteBuilder({\n\t\t\t\ttable: tableName as string,\n\t\t\t\t...mutationOpts,\n\t\t\t}) as DeleteBuilder<InferTableRow<TTable>>;\n\t\t},\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: polymorphic constraint — TTable is inferred by callers; TableRef generics are statically erased in this implementation signature\n\t\tupsertInto<TTable extends TableRef<any, any, any>>(\n\t\t\ttableRef: TTable,\n\t\t): UpsertBuilder<InferTableRow<TTable>> {\n\t\t\tconst tableName = tableRef[TABLE_META];\n\t\t\tif (tableName === undefined) {\n\t\t\t\tthrow new Error('Invalid TableRef: missing TABLE_META symbol');\n\t\t\t}\n\t\t\treturn new UpsertBuilder({\n\t\t\t\ttable: tableName as string,\n\t\t\t\t...mutationOpts,\n\t\t\t}) as UpsertBuilder<InferTableRow<TTable>>;\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Mutation Methods (DX-010)\n\t\t// =====================================================================\n\n\t\tinsert(table: string): InsertBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new InsertBuilder({ table, ...mutationOpts });\n\t\t},\n\n\t\tupdate(table: string): UpdateBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new UpdateBuilder({ table, ...mutationOpts });\n\t\t},\n\n\t\tdelete(table: string): DeleteBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new DeleteBuilder({ table, ...mutationOpts });\n\t\t},\n\n\t\tupdateAll(table: string): UpdateBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new UpdateBuilder({ table, allowAll: true, ...mutationOpts });\n\t\t},\n\n\t\tdeleteAll(table: string): DeleteBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new DeleteBuilder({ table, allowAll: true, ...mutationOpts });\n\t\t},\n\n\t\t// DX-026: Upsert support\n\t\tupsert(table: string): UpsertBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new UpsertBuilder({ table, ...mutationOpts });\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Transaction Methods (DX-025)\n\t\t// =====================================================================\n\n\t\tasync transaction<T>(fn: (tx: OrmInstance<DB>) => Promise<T>): Promise<T> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'transaction() requires an adapter. ' +\n\t\t\t\t\t\t'Pass an adapter when creating the ORM.',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Passthrough to adapter's transaction API\n\t\t\treturn adapter.transaction(async (txAdapter) => {\n\t\t\t\t// Create a transaction-scoped ORM instance with inTransaction=true\n\t\t\t\tconst txOrm = createOrmInstance<DB>(\n\t\t\t\t\tmodel,\n\t\t\t\t\tstrictMode,\n\t\t\t\t\trelationHints,\n\t\t\t\t\ttxAdapter as Adapter<DB>,\n\t\t\t\t\tschemaName,\n\t\t\t\t\tdialectCapabilities,\n\t\t\t\t\tschemaDefinition,\n\t\t\t\t\tglobalPlanOptions,\n\t\t\t\t\tdefaultFilters,\n\t\t\t\t\thookStore,\n\t\t\t\t\tonHookError,\n\t\t\t\t\ttrue, // inTransaction\n\t\t\t\t\ttablesProxy,\n\t\t\t\t);\n\t\t\t\treturn fn(txOrm);\n\t\t\t});\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Raw SQL Execution (DX-027)\n\t\t// =====================================================================\n\n\t\t/**\n\t\t * Execute raw SQL directly - escape hatch for queries that cannot\n\t\t * be expressed via the intent system.\n\t\t *\n\t\t * @warning **SECURITY RISK: POTENTIAL SQL INJECTION**\n\t\t *\n\t\t * This method bypasses the semantic planner and all type safety.\n\t\t * Always use parameter placeholders ($1, $2, etc.) for values.\n\t\t *\n\t\t * **SAFE:**\n\t\t * ```typescript\n\t\t * orm.raw('SELECT * FROM users WHERE id = $1', [userId]);\n\t\t * ```\n\t\t *\n\t\t * **DANGEROUS - NEVER DO THIS:**\n\t\t * ```typescript\n\t\t * orm.raw(`SELECT * FROM users WHERE id = ${userId}`);\n\t\t * ```\n\t\t *\n\t\t * @param sqlString - SQL with parameter placeholders ($1, $2, etc.)\n\t\t * @param parameters - Values to bind (safely escaped by driver)\n\t\t * @returns Promise resolving to typed results\n\t\t *\n\t\t * @see {@link https://owasp.org/www-community/attacks/SQL_Injection | OWASP SQL Injection}\n\t\t */\n\t\tasync raw<T = unknown>(\n\t\t\tsqlString: string,\n\t\t\tparameters: readonly unknown[] = [],\n\t\t): Promise<T[]> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'raw() requires an adapter. ' +\n\t\t\t\t\t\t'Pass an adapter when creating the ORM.',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Passthrough to adapter's executeRaw API\n\t\t\treturn adapter.executeRaw<T>(sqlString, parameters);\n\t\t},\n\n\t\tbatchValues(\n\t\t\tdata: readonly unknown[][],\n\t\t\tcolumns: readonly string[],\n\t\t\ttypes: readonly string[],\n\t\t\topts?: BatchValuesOptions,\n\t\t): BatchValuesRef {\n\t\t\treturn batchValues(data, columns, types, opts);\n\t\t},\n\n\t\tselectExpression(expr: ExpressionSpec): SelectExpressionResult {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'selectExpression() requires an adapter. ' +\n\t\t\t\t\t\t'Pass an adapter when creating the ORM.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst compiled = adapter.compileSelectExpression(expr.intent);\n\t\t\treturn {\n\t\t\t\tsql: compiled.sql,\n\t\t\t\tparameters: compiled.parameters,\n\t\t\t\texecute<T = unknown>(): Promise<T[]> {\n\t\t\t\t\treturn adapter?.executeRaw<T>(compiled.sql, compiled.parameters);\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\n\t\twithCte(name: string): CteBuilder {\n\t\t\treturn new CteBuilder(name, adapter, schemaName);\n\t\t},\n\n\t\trecursive<TResult = unknown>(\n\t\t\tname: string,\n\t\t\toptions: RecursiveOptions,\n\t\t): RawCteQueryBuilder<TResult> {\n\t\t\treturn createRawCteBuilder<TResult>(name, options, adapter, schemaName);\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Global DDL Shortcuts (F-005)\n\t\t// =====================================================================\n\n\t\tddl: {\n\t\t\t/**\n\t\t\t * Drop an index by name (not table-scoped).\n\t\t\t *\n\t\t\t * @param name - Index name to drop\n\t\t\t * @param options - Optional DROP INDEX options\n\t\t\t */\n\t\t\tasync dropIndex(name: string, options?: DropIndexOptions): Promise<void> {\n\t\t\t\tif (!adapter?.executeDDL) {\n\t\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t\t'ddl.dropIndex',\n\t\t\t\t\t\t'executeDDL() requires an adapter that supports DDL execution.',\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// FIND-003: Validate index name and optional schema before building SQL\n\t\t\t\tvalidateIdentifier(name, 'index');\n\t\t\t\tconst sc = options?.schema ?? schemaName;\n\t\t\t\tif (sc) {\n\t\t\t\t\tvalidateIdentifier(sc, 'schema');\n\t\t\t\t}\n\t\t\t\tconst sql = adapter.generateDropIndex\n\t\t\t\t\t? adapter.generateDropIndex(name, options)\n\t\t\t\t\t: (() => {\n\t\t\t\t\t\t\tconst parts: string[] = ['DROP INDEX'];\n\t\t\t\t\t\t\tif (options?.concurrently) parts.push('CONCURRENTLY');\n\t\t\t\t\t\t\tif (options?.ifExists) parts.push('IF EXISTS');\n\t\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t\tsc\n\t\t\t\t\t\t\t\t\t? `\"${sc.replace(/\"/g, '\"\"')}\".\"${name.replace(/\"/g, '\"\"')}\"`\n\t\t\t\t\t\t\t\t\t: `\"${name.replace(/\"/g, '\"\"')}\"`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (options?.cascade) parts.push('CASCADE');\n\t\t\t\t\t\t\treturn parts.join(' ');\n\t\t\t\t\t\t})();\n\t\t\t\tawait adapter.executeDDL(sql);\n\t\t\t},\n\t\t},\n\t};\n}\n","import type {\n\tFeatureBehaviorConfig,\n\tUnsupportedFeatureBehavior,\n} from '@dbsp/types';\nimport type { Adapter } from '../adapter.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanOptions } from '../planner.js';\nimport { NamingConventionMismatchError } from './errors.js';\nimport {\n\tgetHookStore,\n\ttype HookErrorHandler,\n\ttype HookManager,\n} from './hooks.js';\nimport { negotiateFeatures } from './negotiate-features.js';\nimport { createOrmInstance } from './orm-instance.js';\nimport type {\n\tDefaultFilters,\n\tInferDB,\n\tSchema,\n\tSchemaDefinition,\n} from './schema.js';\nimport { createTablesProxy } from './table-ref-factory.js';\nimport type { OrmInstance } from './types.js';\n\n// ============================================================================\n// ARCH-006: Simplified ORM Entry Point\n// ============================================================================\n\n/**\n * ARCH-006: Simplified ORM options.\n *\n * Uses the unified Schema API with required schema and adapter.\n * The schema must be created with `schema()` + `ref()`.\n *\n * @example Full ORM with adapter\n * ```typescript\n * const orm = createOrm({ schema: mySchema, adapter });\n * const users = await orm.select('users').all();\n * ```\n *\n * @example Tests with mock adapter\n * ```typescript\n * import { createMockAdapter } from './test-utils.js';\n * const orm = createOrm({ schema: mySchema, adapter: createMockAdapter() });\n * ```\n */\nexport interface SimplifiedOrmOptions<\n\tT extends SchemaDefinition = SchemaDefinition,\n> {\n\t/**\n\t * Schema created with schema() + ref().\n\t * Either schema or model is required.\n\t */\n\treadonly schema?: Schema<T>;\n\n\t/**\n\t * ModelIR directly (alternative to schema).\n\t * Use this when you have ModelIR from introspection or external source.\n\t * Either schema or model is required.\n\t */\n\treadonly model?: ModelIR;\n\n\t/**\n\t * Adapter for database operations.\n\t *\n\t * Required — provides dialect capabilities for planner strategy selection.\n\t * For compile-only usage (no DB), use `createMockAdapter()` from test-utils\n\t * or `createPgsqlCompileOnlyAdapter()` from adapter-pgsql.\n\t */\n\treadonly adapter: Adapter<unknown>;\n\n\t/**\n\t * Enable strict mode validation (default: false).\n\t */\n\treadonly strictMode?: boolean;\n\n\t// ============================================================\n\t// Global Limits (NQL-ALIGN Block 3)\n\t// ============================================================\n\n\t/**\n\t * Maximum depth for recursive CTE queries.\n\t * Prevents infinite recursion in tree/graph traversals.\n\t * @default 10\n\t */\n\treadonly maxDepth?: number;\n\n\t/**\n\t * Maximum number of relation hops in a single query.\n\t * Limits paths like `user.posts.comments.author.profile`.\n\t * @default 5\n\t */\n\treadonly maxTableHops?: number;\n\n\t/**\n\t * Maximum nesting depth for CASE expressions.\n\t * Prevents overly complex conditional logic.\n\t * @default 10\n\t */\n\treadonly maxNestedCase?: number;\n\n\t/**\n\t * Global plan options passed to the semantic planner for every query.\n\t * Per-query overrides via `.withPlanOptions()` take precedence.\n\t *\n\t * @example\n\t * ```typescript\n\t * const orm = createOrm({\n\t * schema,\n\t * adapter,\n\t * planOptions: {\n\t * defaultIncludeStrategy: 'subquery',\n\t * enableCTEs: true,\n\t * maxIncludeDepth: 3,\n\t * },\n\t * });\n\t * ```\n\t */\n\treadonly planOptions?: PlanOptions;\n\n\t/**\n\t * Hook manager for query/mutation interception (E17b).\n\t * Created via `createHookManager()`.\n\t * Hooks are frozen on ORM creation — no hooks can be added after.\n\t */\n\treadonly hooks?: HookManager;\n\n\t/**\n\t * Error handler for hook failures (E17b).\n\t * Called when a hook throws. Returns 'continue' to skip the failed hook,\n\t * or 'abort' to propagate the error.\n\t */\n\treadonly onHookError?: HookErrorHandler;\n\n\t/**\n\t * Behavior when schema uses features the adapter doesn't support.\n\t * Default: 'warning' (emit warning + skip).\n\t * Use 'error' for strict environments, 'ignore' to suppress.\n\t * Pass FeatureBehaviorConfig for per-feature overrides.\n\t */\n\treadonly unsupportedFeatures?:\n\t\t| UnsupportedFeatureBehavior\n\t\t| FeatureBehaviorConfig;\n}\n\n/**\n * Create an ORM instance with the specified configuration.\n *\n * @typeParam DB - Database schema type (Kysely-like).\n * Keys are table names, values are row types.\n * When provided, query() provides autocomplete and type inference.\n *\n * @param options - Configuration options including model and strictMode\n * @returns An ORM instance for building and planning queries\n *\n * @example With schema() + ref() API (recommended)\n * ```typescript\n * import { schema, ref, createOrm } from '@dbsp/core';\n *\n * const mySchema = schema({\n * users: {\n * id: 'uuid',\n * name: 'string',\n * },\n * posts: {\n * id: 'uuid',\n * title: 'string',\n * authorId: ref('users.id'),\n * },\n * });\n *\n * const orm = createOrm({ schema: mySchema, adapter });\n *\n * // Table names autocomplete, results are typed!\n * const users = await orm.select('users').all();\n *\n * // Include relations with type inference\n * const usersWithPosts = await orm.select('users').include('posts').all();\n * ```\n */\n/**\n * ARCH-006: Creates an ORM instance from a schema.\n *\n * This is the single entry point for creating ORM instances.\n * The schema must be created with `schema()` + `ref()`.\n *\n * For database introspection (when available), use the adapter's introspect method:\n * ```typescript\n * const model = await adapter.introspect({ schema: 'public' });\n * const orm = createOrm({ schema: model, adapter });\n * ```\n *\n * @param options - ORM options with required schema\n * @returns ORM instance for querying\n *\n * @example With database adapter\n * ```typescript\n * const orm = createOrm({ schema: mySchema, adapter });\n * const users = await orm.select('users').all();\n * ```\n */\nexport function createOrm<T extends SchemaDefinition>(\n\toptions: SimplifiedOrmOptions<T>,\n): OrmInstance<InferDB<T>> {\n\tconst {\n\t\tschema: schemaObj,\n\t\tmodel: modelDirect,\n\t\tadapter,\n\t\tstrictMode = false,\n\t\tplanOptions: globalPlanOptions,\n\t\thooks: hookManager,\n\t\tonHookError,\n\t\tunsupportedFeatures,\n\t} = options;\n\n\t// ARCH-006: Either schema or model is required\n\t// Schema provides full type inference; model is simpler for introspection/tests\n\tlet model: ModelIR;\n\tlet schemaDefinition: unknown;\n\tlet defaultFilters: DefaultFilters | undefined;\n\n\tif (schemaObj && 'model' in schemaObj) {\n\t\t// Full schema object provided\n\t\tmodel = schemaObj.model;\n\t\tschemaDefinition = schemaObj.definition;\n\t\tdefaultFilters = schemaObj.defaultFilters;\n\n\t\t// ARCH-006: Validate casing consistency\n\t\tif (\n\t\t\tadapter &&\n\t\t\tschemaObj.dbCasing &&\n\t\t\tadapter.dbCasing &&\n\t\t\tschemaObj.dbCasing !== adapter.dbCasing\n\t\t) {\n\t\t\tthrow new NamingConventionMismatchError({\n\t\t\t\tschemaCasing: schemaObj.dbCasing,\n\t\t\t\tadapterCasing: adapter.dbCasing,\n\t\t\t});\n\t\t}\n\t} else if (modelDirect) {\n\t\t// ModelIR provided directly (simpler API for introspection/tests)\n\t\tmodel = modelDirect;\n\t\tschemaDefinition = undefined; // NQL will work without schema validation\n\t\tdefaultFilters = undefined;\n\t} else {\n\t\tthrow new Error(\n\t\t\t'Invalid options: must provide either schema (from schema() function) ' +\n\t\t\t\t'or model (ModelIR). For database introspection, use getSchemaFromDb() ' +\n\t\t\t\t'from the adapter (e.g. adapter.introspect()).',\n\t\t);\n\t}\n\n\t// CAPS-003: Feature negotiation — cross-check ModelIR against adapter capabilities\n\tif (adapter?.dialectCapabilities) {\n\t\tconst result = negotiateFeatures(\n\t\t\tmodel,\n\t\t\tadapter.dialectCapabilities,\n\t\t\tunsupportedFeatures ?? 'warning',\n\t\t);\n\t\tfor (const w of result.warnings) {\n\t\t\tconsole.warn(`[dbsp] ${w.message}`);\n\t\t}\n\t}\n\n\t// E17b: Freeze hook manager on ORM creation — no hooks can be added after\n\tconst frozenHookStore = hookManager\n\t\t? getHookStore(hookManager.freeze())\n\t\t: undefined;\n\n\t// DX-040-SURFACE: Build tables proxy for type-safe table access\n\t// Use schema's pre-built proxy if available, otherwise build from model\n\tconst tablesProxy: object =\n\t\tschemaObj && 'tables' in schemaObj\n\t\t\t? (schemaObj.tables as object)\n\t\t\t: createTablesProxy(model, model.tables ? [...model.tables.keys()] : []);\n\n\t// Create ORM instance with ModelIR\n\t// Cast to InferDB<T> since createOrmInstance uses internal types\n\treturn createOrmInstance(\n\t\tmodel,\n\t\tstrictMode,\n\t\t{}, // relationHints removed in ARCH-006\n\t\tadapter,\n\t\tundefined, // schemaName\n\t\tadapter.dialectCapabilities,\n\t\tschemaDefinition,\n\t\tglobalPlanOptions,\n\t\tdefaultFilters,\n\t\tfrozenHookStore,\n\t\tonHookError,\n\t\tundefined, // inTransaction\n\t\ttablesProxy,\n\t) as unknown as OrmInstance<InferDB<T>>;\n}\n","/**\n * @module range\n * PostgreSQL range operator helpers — expression-level (ExpressionRef) API.\n *\n * Provides three operators for PostgreSQL range types:\n * - `rangeOverlaps` — `&&` (any points in common)\n * - `rangeContains` — `@>` (range contains range or element)\n * - `rangeContainedBy` — `<@` (range is contained by another range)\n *\n * Tuple form: `rangeOverlaps('period', ['2024-01-01', '2024-01-31'])` → ExpressionRef\n * Compiles to: `\"period\" && daterange($1, $2)`\n *\n * Object form: `rangeOverlaps('period', { lower: '2024-01-01', upper: '2024-01-31' })` → WhereRangeIntent\n * Handled by the planner's range pipeline (backward-compatible path).\n *\n * @example\n * ```typescript\n * import { rangeOverlaps, rangeContains, rangeContainedBy } from '@dbsp/core';\n *\n * orm.select('bookings').where(rangeOverlaps('period', ['2024-01-01', '2024-01-31']))\n * orm.select('events').where(rangeContains('dateRange', ['2024-06-15', '2024-06-15']))\n * orm.select('events').where(rangeContainedBy('dateRange', ['2024-01-01', '2024-12-31']))\n * ```\n */\n\nimport type { RangeValue } from '@dbsp/types';\nimport type { WhereRangeIntent } from '../intent-ast.js';\nimport { type ExpressionRef, fn, op, param, ref } from './expressions.js';\n\nexport type { RangeValue } from '@dbsp/types';\n\n// ============================================================================\n// RangeType\n// ============================================================================\n\n/**\n * PostgreSQL range type names.\n *\n * Used as the third argument to range helpers to control the constructor\n * function emitted in SQL (e.g. `daterange($1, $2)`, `int4range($1, $2)`).\n *\n * Defaults to `'daterange'` when omitted.\n */\nexport type RangeType =\n\t| 'int4range'\n\t| 'int8range'\n\t| 'numrange'\n\t| 'tsrange'\n\t| 'tstzrange'\n\t| 'daterange';\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\n/**\n * Build the range constructor call: `rangeType(param(lower), param(upper))`\n */\nfunction makeRangeFn(\n\trange: readonly [unknown, unknown],\n\trangeType: RangeType,\n): ExpressionRef {\n\treturn fn(rangeType, param(range[0]), param(range[1]));\n}\n\n/**\n * Assert that `arr` is a 2-element tuple.\n * Throws a clear error for 0-, 1-, or 3+-element arrays so callers get\n * actionable feedback instead of silently producing bad SQL.\n */\nfunction assertTupleLength(arr: unknown[]): void {\n\tif (arr.length !== 2) {\n\t\tthrow new Error(\n\t\t\t`range tuple must have exactly 2 elements (got ${arr.length}); use [lower, upper] or pass a RangeValue object`,\n\t\t);\n\t}\n}\n\n// ============================================================================\n// rangeOverlaps — &&\n// ============================================================================\n\n/**\n * Range OVERLAPS — tuple API: `\"column\" && rangeType($1, $2)` (ExpressionRef)\n *\n * @example rangeOverlaps('period', ['2024-01-01', '2024-01-31'])\n * → \"period\" && daterange($1, $2)\n * @example rangeOverlaps('span', [1, 100], 'int4range')\n * → \"span\" && int4range($1, $2)\n */\nexport function rangeOverlaps(\n\tcolumn: string,\n\trange: readonly [unknown, unknown],\n\trangeType?: RangeType,\n): ExpressionRef;\n\n/**\n * Range OVERLAPS — object API: delegates to WhereRangeIntent (planner path)\n *\n * @example rangeOverlaps('dates', { lower: '2025-01-15', upper: '2025-01-20' })\n */\nexport function rangeOverlaps(\n\tfield: string,\n\tvalue: RangeValue,\n): WhereRangeIntent;\n\nexport function rangeOverlaps(\n\tfieldOrColumn: string,\n\tvalueOrRange: RangeValue | readonly [unknown, unknown],\n\trangeType: RangeType = 'daterange',\n): ExpressionRef | WhereRangeIntent {\n\tif (Array.isArray(valueOrRange)) {\n\t\tassertTupleLength(valueOrRange);\n\t\tconst tuple = valueOrRange as unknown as readonly [unknown, unknown];\n\t\treturn op('&&', ref(fieldOrColumn), makeRangeFn(tuple, rangeType));\n\t}\n\treturn {\n\t\tkind: 'range',\n\t\tfield: fieldOrColumn,\n\t\toperator: 'overlaps',\n\t\tvalue: valueOrRange,\n\t};\n}\n\n// ============================================================================\n// rangeContains — @>\n// ============================================================================\n\n/**\n * Range CONTAINS — tuple API: `\"column\" @> rangeType($1, $2)` (ExpressionRef)\n *\n * @example rangeContains('dateRange', ['2024-06-15', '2024-06-15'])\n * → \"dateRange\" @> daterange($1, $2)\n */\nexport function rangeContains(\n\tcolumn: string,\n\trange: readonly [unknown, unknown],\n\trangeType?: RangeType,\n): ExpressionRef;\n\n/**\n * Range CONTAINS — object API: delegates to WhereRangeIntent (planner path)\n *\n * @example rangeContains('date_range', { lower: '2025-01-01', upper: '2025-01-05' })\n */\nexport function rangeContains(\n\tfield: string,\n\tvalue: RangeValue,\n): WhereRangeIntent;\n\nexport function rangeContains(\n\tfieldOrColumn: string,\n\tvalueOrRange: RangeValue | readonly [unknown, unknown],\n\trangeType: RangeType = 'daterange',\n): ExpressionRef | WhereRangeIntent {\n\tif (Array.isArray(valueOrRange)) {\n\t\tassertTupleLength(valueOrRange);\n\t\tconst tuple = valueOrRange as unknown as readonly [unknown, unknown];\n\t\treturn op('@>', ref(fieldOrColumn), makeRangeFn(tuple, rangeType));\n\t}\n\treturn {\n\t\tkind: 'range',\n\t\tfield: fieldOrColumn,\n\t\toperator: 'contains',\n\t\tvalue: valueOrRange,\n\t};\n}\n\n// ============================================================================\n// rangeContainedBy — <@\n// ============================================================================\n\n/**\n * Range CONTAINED BY — tuple API: `\"column\" <@ rangeType($1, $2)` (ExpressionRef)\n *\n * @example rangeContainedBy('dateRange', ['2024-01-01', '2024-12-31'])\n * → \"dateRange\" <@ daterange($1, $2)\n */\nexport function rangeContainedBy(\n\tcolumn: string,\n\trange: readonly [unknown, unknown],\n\trangeType?: RangeType,\n): ExpressionRef;\n\n/**\n * Range CONTAINED BY — object API: delegates to WhereRangeIntent (planner path)\n *\n * @example rangeContainedBy('event_dates', { lower: '2025-01-01', upper: '2025-12-31' })\n */\nexport function rangeContainedBy(\n\tfield: string,\n\tvalue: RangeValue,\n): WhereRangeIntent;\n\nexport function rangeContainedBy(\n\tfieldOrColumn: string,\n\tvalueOrRange: RangeValue | readonly [unknown, unknown],\n\trangeType: RangeType = 'daterange',\n): ExpressionRef | WhereRangeIntent {\n\tif (Array.isArray(valueOrRange)) {\n\t\tassertTupleLength(valueOrRange);\n\t\tconst tuple = valueOrRange as unknown as readonly [unknown, unknown];\n\t\treturn op('<@', ref(fieldOrColumn), makeRangeFn(tuple, rangeType));\n\t}\n\treturn {\n\t\tkind: 'range',\n\t\tfield: fieldOrColumn,\n\t\toperator: 'containedBy',\n\t\tvalue: valueOrRange,\n\t};\n}\n","/**\n * ARCH-002 Block 6: Schema Bridge\n *\n * Converts generated schema (from dbsp generate manifest) to ModelIR.\n * This enables sync createOrm usage with codegen-first schemas.\n */\n\nimport type { Mutable } from '@dbsp/types/internal';\nimport * as v from 'valibot';\nimport { ModelIRImpl } from '../model-impl.js';\nimport {\n\ttype Cardinality,\n\ttype ColumnIR,\n\ttype ColumnType,\n\tcreatePseudoColumnMetadata,\n\ttype FilterStrategy,\n\ttype ForeignKeyIR,\n\ttype IncludeStrategy,\n\ttype IndexIR,\n\ttype JoinDefault,\n\ttype ModelIR,\n\ttype Optionality,\n\ttype PseudoColumnMetadata,\n\ttype RelationIR,\n\ttype RelationType,\n\ttype TableIR,\n} from '../model-ir.js';\nimport type { ResolvedSchema } from '../schema-dsl-types.js';\n\n// ============================================================================\n// Generated Schema Types (from dbsp generate manifest)\n// ============================================================================\n\n/**\n * Column type in generated schema.\n */\nexport type GeneratedColumnType =\n\t| 'string'\n\t| 'text'\n\t| 'number'\n\t| 'integer'\n\t| 'bigint'\n\t| 'decimal'\n\t| 'boolean'\n\t| 'date'\n\t| 'timestamp'\n\t| 'datetime'\n\t| 'time'\n\t| 'json'\n\t| 'jsonb'\n\t| 'uuid'\n\t| 'daterange'\n\t| 'tstzrange'\n\t| 'int4range'\n\t| 'tsrange'\n\t| 'int8range'\n\t| 'numrange';\n\n/**\n * Column definition in generated schema.\n */\nexport interface GeneratedColumn {\n\treadonly type: GeneratedColumnType;\n\treadonly primaryKey?: boolean;\n\treadonly nullable?: boolean;\n\treadonly unique?: boolean;\n\treadonly autoIncrement?: boolean;\n\treadonly default?: string;\n\treadonly references?: {\n\t\treadonly table: string;\n\t\treadonly column?: string;\n\t\treadonly onDelete?: 'CASCADE' | 'SET NULL' | 'RESTRICT' | 'NO ACTION';\n\t\t/** Create an index on this FK column (matches ColumnDefinitionSchema index field) */\n\t\treadonly index?: boolean;\n\t\t/** Role name for parent traversal in self-ref hierarchies (e.g., 'parent') */\n\t\treadonly parentRole?: string;\n\t\t/** Role name for child traversal in self-ref hierarchies (e.g., 'children') */\n\t\treadonly childRole?: string;\n\t};\n\t/** Create an index on this column (true for auto-name, string for custom name) */\n\treadonly index?: boolean | string;\n}\n\n/**\n * Table definition in generated schema.\n */\nexport type GeneratedTable = Record<string, GeneratedColumn>;\n\n/**\n * Relation kind in generated schema (discriminated union).\n */\nexport type GeneratedRelationKind = 'belongsTo' | 'hasMany' | 'manyToMany';\n\n/**\n * Include strategy for relations.\n */\ntype GeneratedIncludeStrategy =\n\t| 'join'\n\t| 'subquery'\n\t| 'cte'\n\t| 'lateral'\n\t| 'json_agg'\n\t| 'auto';\n\n/**\n * BelongsTo relation in generated schema.\n */\nexport interface GeneratedBelongsTo {\n\treadonly kind: 'belongsTo';\n\treadonly target: string;\n\treadonly foreignKey: string;\n\treadonly targetKey?: string;\n\treadonly includeStrategy?: GeneratedIncludeStrategy;\n}\n\n/**\n * HasMany relation in generated schema.\n */\nexport interface GeneratedHasMany {\n\treadonly kind: 'hasMany';\n\treadonly target: string;\n\treadonly foreignKey: string;\n\treadonly sourceKey?: string;\n\treadonly includeStrategy?: GeneratedIncludeStrategy;\n\treadonly cardinality?: 'one' | 'many';\n}\n\n/**\n * ManyToMany relation in generated schema.\n */\nexport interface GeneratedManyToMany {\n\treadonly kind: 'manyToMany';\n\treadonly target: string;\n\treadonly through: string;\n\treadonly sourceFk: string;\n\treadonly targetFk: string;\n\treadonly includeStrategy?: GeneratedIncludeStrategy;\n}\n\n/**\n * Relation definition in generated schema.\n */\nexport type GeneratedRelation =\n\t| GeneratedBelongsTo\n\t| GeneratedHasMany\n\t| GeneratedManyToMany;\n\n/**\n * Hint definition in generated schema.\n */\nexport interface GeneratedHint {\n\treadonly defaultStrategy?: 'exists' | 'join';\n\treadonly cardinality?: 'one' | 'many';\n}\n\n/**\n * Conventions in generated schema.\n */\nexport interface GeneratedConventions {\n\treadonly fkPattern: string;\n\treadonly pluralize: boolean;\n\treadonly timestamps: readonly string[];\n\treadonly fkAutoIndex: boolean;\n}\n\n/**\n * Complete generated schema (output of dbsp generate manifest).\n *\n * @typeParam TTables - The tables type, preserving literal table names for autocomplete.\n * When using `as const` on your schema definition, table names will be preserved.\n *\n * @example\n * ```typescript\n * const schema = {\n * tables: {\n * users: { id: { type: 'uuid', primaryKey: true }, name: { type: 'string' } },\n * posts: { id: { type: 'uuid', primaryKey: true }, title: { type: 'string' } },\n * },\n * relations: {},\n * hints: {},\n * conventions: { fkPattern: '{singular}Id', pluralize: true, timestamps: [], fkAutoIndex: true },\n * } as const satisfies GeneratedSchema;\n *\n * // TypeScript knows: keyof typeof schema.tables = 'users' | 'posts'\n * ```\n */\nexport interface GeneratedSchema<\n\tTTables extends Record<string, GeneratedTable> = Record<\n\t\tstring,\n\t\tGeneratedTable\n\t>,\n> {\n\treadonly tables: TTables;\n\treadonly relations: Record<string, GeneratedRelation>;\n\treadonly hints: Record<string, GeneratedHint>;\n\treadonly conventions: GeneratedConventions;\n}\n\n// ============================================================================\n// Type Utilities for Schema Inference\n// ============================================================================\n\n/**\n * Map a GeneratedColumnType to its TypeScript runtime type.\n */\nexport type ColumnTypeToTS<T extends GeneratedColumnType> = T extends\n\t| 'string'\n\t| 'text'\n\t| 'uuid'\n\t? string\n\t: T extends 'number' | 'integer' | 'decimal'\n\t\t? number\n\t\t: T extends 'bigint'\n\t\t\t? bigint\n\t\t\t: T extends 'boolean'\n\t\t\t\t? boolean\n\t\t\t\t: T extends 'date' | 'timestamp' | 'datetime'\n\t\t\t\t\t? Date\n\t\t\t\t\t: T extends 'time'\n\t\t\t\t\t\t? string\n\t\t\t\t\t\t: T extends 'json' | 'jsonb'\n\t\t\t\t\t\t\t? unknown\n\t\t\t\t\t\t\t: // PostgreSQL range types — no native Range<T> in TS; represented as string (e.g., \"[2020-01-01,2020-12-31)\")\n\t\t\t\t\t\t\t\tT extends\n\t\t\t\t\t\t\t\t\t\t| 'daterange'\n\t\t\t\t\t\t\t\t\t\t| 'tstzrange'\n\t\t\t\t\t\t\t\t\t\t| 'int4range'\n\t\t\t\t\t\t\t\t\t\t| 'tsrange'\n\t\t\t\t\t\t\t\t\t\t| 'int8range'\n\t\t\t\t\t\t\t\t\t\t| 'numrange'\n\t\t\t\t\t\t\t\t? string\n\t\t\t\t\t\t\t\t: never;\n\n/**\n * Infer the TypeScript row type from a GeneratedTable definition.\n */\nexport type InferRowType<T extends GeneratedTable> = {\n\t[K in keyof T]: T[K]['nullable'] extends true\n\t\t? ColumnTypeToTS<T[K]['type']> | null\n\t\t: ColumnTypeToTS<T[K]['type']>;\n};\n\n/**\n * Infer the database type from a GeneratedSchema.\n * Maps each table name to its row type.\n *\n * @example\n * ```typescript\n * const schema = { tables: { users: { id: { type: 'uuid' } } } } as const satisfies GeneratedSchema;\n * type DB = InferDBFromSchema<typeof schema>;\n * // DB = { users: { id: string } }\n * ```\n */\nexport type InferDBFromSchema<S extends GeneratedSchema> = {\n\t[TableName in keyof S['tables'] & string]: InferRowType<\n\t\tS['tables'][TableName]\n\t>;\n};\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\n/**\n * Map generated column type to ModelIR column type.\n */\nfunction generatedTypeToColumnType(genType: GeneratedColumnType): ColumnType {\n\tswitch (genType) {\n\t\tcase 'string':\n\t\tcase 'text':\n\t\t\treturn 'string';\n\t\tcase 'number':\n\t\tcase 'decimal':\n\t\t\treturn 'number';\n\t\tcase 'integer':\n\t\t\treturn 'integer';\n\t\tcase 'bigint':\n\t\t\treturn 'bigint';\n\t\tcase 'boolean':\n\t\t\treturn 'boolean';\n\t\tcase 'date':\n\t\t\treturn 'date';\n\t\tcase 'timestamp':\n\t\tcase 'datetime':\n\t\t\treturn 'datetime';\n\t\tcase 'json':\n\t\t\treturn 'json';\n\t\tcase 'jsonb':\n\t\t\treturn 'jsonb';\n\t\tcase 'time':\n\t\t\treturn 'time';\n\t\tcase 'uuid':\n\t\t\treturn 'uuid';\n\t\tcase 'daterange':\n\t\t\treturn 'daterange';\n\t\tcase 'tstzrange':\n\t\t\treturn 'tstzrange';\n\t\tcase 'int4range':\n\t\t\treturn 'int4range';\n\t\tcase 'tsrange':\n\t\t\treturn 'tsrange';\n\t\tcase 'int8range':\n\t\t\treturn 'int8range';\n\t\tcase 'numrange':\n\t\t\treturn 'numrange';\n\t}\n}\n\n/**\n * Map generated relation kind to ModelIR relation type.\n */\nfunction mapRelationType(kind: GeneratedRelationKind): RelationType {\n\tswitch (kind) {\n\t\tcase 'belongsTo':\n\t\t\treturn 'belongsTo';\n\t\tcase 'hasMany':\n\t\t\treturn 'hasMany';\n\t\tcase 'manyToMany':\n\t\t\treturn 'belongsToMany';\n\t}\n}\n\n/**\n * Build a TableIR from generated table definition.\n */\nfunction buildTableIRFromDefinition(\n\ttableName: string,\n\tgenTable: GeneratedTable,\n\tfkAutoIndex: boolean,\n): TableIR {\n\tconst columns: ColumnIR[] = [];\n\tconst foreignKeys: ForeignKeyIR[] = [];\n\tconst indexes: IndexIR[] = [];\n\tconst primaryKeys: string[] = [];\n\t// Track columns that already have explicit indexes\n\tconst indexedColumns = new Set<string>();\n\n\tfor (const [colName, colDef] of Object.entries(genTable)) {\n\t\t// Column (with unique support)\n\t\tconst col: Mutable<ColumnIR> = {\n\t\t\tname: colName,\n\t\t\ttype: generatedTypeToColumnType(colDef.type),\n\t\t\tnullable: colDef.nullable ?? false,\n\t\t\tdefault: colDef.default,\n\t\t};\n\t\tif (colDef.unique !== undefined) {\n\t\t\tcol.unique = colDef.unique;\n\t\t}\n\t\tif (colDef.autoIncrement !== undefined) {\n\t\t\tcol.autoIncrement = colDef.autoIncrement;\n\t\t}\n\t\tcolumns.push(col);\n\n\t\t// Primary key\n\t\tif (colDef.primaryKey) {\n\t\t\tprimaryKeys.push(colName);\n\t\t}\n\n\t\t// Foreign key (with onDelete support)\n\t\tif (colDef.references) {\n\t\t\tconst fk: Mutable<ForeignKeyIR> = {\n\t\t\t\tcolumns: [colName],\n\t\t\t\treferences: {\n\t\t\t\t\ttable: colDef.references.table,\n\t\t\t\t\tcolumns: [colDef.references.column ?? 'id'],\n\t\t\t\t},\n\t\t\t};\n\t\t\tif (colDef.references.onDelete) {\n\t\t\t\tfk.onDelete = colDef.references.onDelete;\n\t\t\t}\n\t\t\tforeignKeys.push(fk);\n\t\t}\n\n\t\t// Column-level index (explicit)\n\t\tif (colDef.index) {\n\t\t\tconst indexName =\n\t\t\t\ttypeof colDef.index === 'string'\n\t\t\t\t\t? colDef.index\n\t\t\t\t\t: `idx_${tableName}_${colName}`;\n\t\t\tindexes.push({\n\t\t\t\tname: indexName,\n\t\t\t\tcolumns: [colName],\n\t\t\t\tunique: false,\n\t\t\t});\n\t\t\tindexedColumns.add(colName);\n\t\t}\n\n\t\t// Auto-index for FK columns if fkAutoIndex is enabled and no explicit index\n\t\tif (fkAutoIndex && colDef.references && !colDef.index) {\n\t\t\tindexes.push({\n\t\t\t\tname: `idx_${tableName}_${colName}`,\n\t\t\t\tcolumns: [colName],\n\t\t\t\tunique: false,\n\t\t\t});\n\t\t\tindexedColumns.add(colName);\n\t\t}\n\t}\n\n\t// Extract pseudo-columns from self-referential FKs\n\tconst pseudoColumns: PseudoColumnMetadata[] = [];\n\tfor (const fk of foreignKeys) {\n\t\t// Check if FK points to same table (self-referential)\n\t\tconst fkColumn = fk.columns[0];\n\t\tconst targetColumn = fk.references.columns[0];\n\t\tif (\n\t\t\tfk.references.table === tableName &&\n\t\t\tfkColumn !== undefined &&\n\t\t\ttargetColumn !== undefined\n\t\t) {\n\t\t\t// Get column definition for role extraction\n\t\t\tconst colDef = genTable[fkColumn];\n\t\t\t// Infer role names from column name or explicit references\n\t\t\tconst inferredName = fkColumn.endsWith('Id')\n\t\t\t\t? fkColumn.slice(0, -2)\n\t\t\t\t: 'parent';\n\t\t\tconst parentRole = colDef?.references?.parentRole ?? inferredName;\n\t\t\tconst childRole =\n\t\t\t\tcolDef?.references?.childRole ??\n\t\t\t\t(parentRole === 'parent' ? 'children' : `${parentRole}s`);\n\n\t\t\tpseudoColumns.push(\n\t\t\t\tcreatePseudoColumnMetadata(\n\t\t\t\t\ttableName,\n\t\t\t\t\tfkColumn,\n\t\t\t\t\ttargetColumn,\n\t\t\t\t\tparentRole,\n\t\t\t\t\tchildRole,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Determine PK: explicit > composite FK > 'id' column > omit\n\tlet primaryKey: string | readonly string[] | undefined;\n\tif (primaryKeys.length > 0) {\n\t\tprimaryKey =\n\t\t\tprimaryKeys.length === 1 ? (primaryKeys[0] as string) : primaryKeys;\n\t} else {\n\t\t// No explicit PK — infer from FK columns or 'id'\n\t\tconst fkColumns = foreignKeys.flatMap((fk) => fk.columns);\n\t\tif (fkColumns.length > 0) {\n\t\t\tprimaryKey = fkColumns.length === 1 ? fkColumns[0] : fkColumns;\n\t\t} else {\n\t\t\tconst hasId = columns.some((c) => c.name === 'id');\n\t\t\tprimaryKey = hasId ? 'id' : undefined;\n\t\t}\n\t}\n\n\t// Freeze columns array for runtime immutability\n\tconst frozenColumns = Object.freeze(columns);\n\n\t// Freeze and return the table object\n\treturn Object.freeze({\n\t\tname: tableName,\n\t\tcolumns: frozenColumns,\n\t\t...(primaryKey !== undefined ? { primaryKey } : {}),\n\t\tforeignKeys: Object.freeze(foreignKeys),\n\t\tindexes: Object.freeze(indexes),\n\t\t...(pseudoColumns.length > 0 && {\n\t\t\tpseudoColumns: Object.freeze(pseudoColumns),\n\t\t}),\n\t});\n}\n\n/**\n * Build a RelationIR from generated relation definition.\n */\nfunction buildRelationIR(\n\tqualifiedName: string,\n\tgenRelation: GeneratedRelation,\n\thints: Record<string, GeneratedHint>,\n): RelationIR {\n\t// Extract source table and relation name from qualified name (e.g., \"posts.author\")\n\tconst dotIndex = qualifiedName.indexOf('.');\n\tconst sourceTable =\n\t\tdotIndex > 0 ? qualifiedName.slice(0, dotIndex) : qualifiedName;\n\tconst relationName =\n\t\tdotIndex > 0 ? qualifiedName.slice(dotIndex + 1) : qualifiedName;\n\n\t// Get hints for this relation\n\tconst hint = hints[qualifiedName];\n\t// Check cardinality from: hint > relation definition > inferred from kind\n\tconst relCardinality =\n\t\tgenRelation.kind === 'hasMany'\n\t\t\t? (genRelation as GeneratedHasMany).cardinality\n\t\t\t: undefined;\n\tconst cardinality: Cardinality =\n\t\thint?.cardinality === 'one'\n\t\t\t? 'one'\n\t\t\t: relCardinality === 'one'\n\t\t\t\t? 'one'\n\t\t\t\t: genRelation.kind === 'belongsTo'\n\t\t\t\t\t? 'one'\n\t\t\t\t\t: 'many';\n\n\t// Determine optionality from nullable FK (for belongsTo) or default to 'optional' for hasMany\n\tconst optionality: Optionality =\n\t\tgenRelation.kind === 'belongsTo' ? 'optional' : 'optional';\n\n\t// Determine relation type - hasMany with cardinality 'one' becomes 'hasOne'\n\tlet relationType = mapRelationType(genRelation.kind);\n\tif (genRelation.kind === 'hasMany' && cardinality === 'one') {\n\t\trelationType = 'hasOne';\n\t}\n\n\t// Build base relation\n\tconst baseRelation = {\n\t\tname: relationName,\n\t\tsource: sourceTable,\n\t\ttarget: genRelation.target,\n\t\ttype: relationType,\n\t\tcardinality,\n\t\toptionality,\n\t\tincludeStrategy: (genRelation.includeStrategy ?? 'auto') as IncludeStrategy,\n\t\tfilterStrategy: (hint?.defaultStrategy ?? 'auto') as FilterStrategy,\n\t\tjoinDefault: 'auto' as JoinDefault,\n\t};\n\n\t// Add relation-specific fields (including optional key overrides from generated relation).\n\t// sourceKey (hasMany): column on source table that the FK on target references (overrides PK).\n\t// targetKey (belongsTo): column on target table that the FK points to (overrides PK).\n\tswitch (genRelation.kind) {\n\t\tcase 'belongsTo':\n\t\t\treturn {\n\t\t\t\t...baseRelation,\n\t\t\t\tforeignKey: genRelation.foreignKey,\n\t\t\t\t...(genRelation.targetKey ? { targetKey: genRelation.targetKey } : {}),\n\t\t\t};\n\t\tcase 'hasMany':\n\t\t\treturn {\n\t\t\t\t...baseRelation,\n\t\t\t\tforeignKey: genRelation.foreignKey,\n\t\t\t\t...(genRelation.sourceKey ? { sourceKey: genRelation.sourceKey } : {}),\n\t\t\t};\n\t\tcase 'manyToMany':\n\t\t\treturn {\n\t\t\t\t...baseRelation,\n\t\t\t\tthrough: genRelation.through,\n\t\t\t\tforeignKey: genRelation.sourceFk,\n\t\t\t\totherKey: genRelation.targetFk,\n\t\t\t};\n\t}\n}\n\n/**\n * Build a ModelIR from a generated schema.\n *\n * This is the main entry point for the schema bridge.\n * It converts the output of `dbsp generate manifest` into a ModelIR\n * that can be used with createOrm.\n *\n * @example\n * ```typescript\n * import { schema } from './generated/dbsp/schema';\n * import { buildModelFromSchema, createOrm } from '@dbsp/core';\n *\n * const model = buildModelFromSchema(schema);\n * const orm = createOrm({ model, adapter });\n * ```\n */\nexport function buildModelFromSchema(schema: GeneratedSchema): ModelIR {\n\tconst tables = new Map<string, TableIR>();\n\tconst relations = new Map<string, RelationIR>();\n\tconst fkAutoIndex = schema.conventions.fkAutoIndex;\n\n\t// Build tables\n\tfor (const [tableName, genTable] of Object.entries(schema.tables)) {\n\t\ttables.set(\n\t\t\ttableName,\n\t\t\tbuildTableIRFromDefinition(tableName, genTable, fkAutoIndex),\n\t\t);\n\t}\n\n\t// Build relations\n\tfor (const [qualifiedName, genRelation] of Object.entries(schema.relations)) {\n\t\trelations.set(\n\t\t\tqualifiedName,\n\t\t\tbuildRelationIR(qualifiedName, genRelation, schema.hints),\n\t\t);\n\t}\n\n\treturn new ModelIRImpl(tables, relations);\n}\n\n/**\n * Build ModelIR directly from ResolvedSchema.\n *\n * Combines the conversion steps: ResolvedSchema → GeneratedSchema → ModelIR.\n * This is the canonical path for creating ModelIR from user-defined schemas.\n *\n * @example\n * ```typescript\n * import { defineSchema, buildModelFromResolvedSchema } from '@dbsp/core';\n *\n * const schema = defineSchema({ users: { ... } }, { relations: { ... } });\n * const model = buildModelFromResolvedSchema(schema);\n * ```\n */\nexport function buildModelFromResolvedSchema(schema: ResolvedSchema): ModelIR {\n\tconst generatedSchema = assertResolvedSchemaToGeneratedSchema(schema);\n\treturn buildModelFromSchema(generatedSchema);\n}\n\n/**\n * Type guard for GeneratedSchema.\n *\n * Note: Both GeneratedSchema and ResolvedSchema have the same structure,\n * so this check will return true for both. Use `isResolvedSchema()` to\n * specifically detect ResolvedSchema (from @dbsp/schema).\n */\nexport function isGeneratedSchema(value: unknown): value is GeneratedSchema {\n\tif (typeof value !== 'object' || value === null) {\n\t\treturn false;\n\t}\n\tconst obj = value as Record<string, unknown>;\n\treturn (\n\t\ttypeof obj.tables === 'object' &&\n\t\tobj.tables !== null &&\n\t\ttypeof obj.relations === 'object' &&\n\t\tobj.relations !== null &&\n\t\ttypeof obj.hints === 'object' &&\n\t\tobj.hints !== null &&\n\t\ttypeof obj.conventions === 'object' &&\n\t\tobj.conventions !== null\n\t);\n}\n\n/**\n * Column types that exist only in ResolvedSchema (from @dbsp/schema).\n * These types are PostgreSQL-specific and not present in GeneratedSchema.\n */\nconst RESOLVED_SCHEMA_ONLY_TYPES = new Set(['time', 'jsonb']);\n\n/**\n * Column types that exist only in GeneratedSchema.\n * These are dialect-agnostic types not present in ResolvedSchema.\n */\nconst GENERATED_SCHEMA_ONLY_TYPES = new Set(['number', 'datetime']);\n\n/**\n * Check if any column in the schema has a type only found in ResolvedSchema.\n */\nfunction hasResolvedSchemaOnlyTypes(\n\ttables: Record<string, Record<string, { type?: string }>>,\n): boolean {\n\tfor (const table of Object.values(tables)) {\n\t\tfor (const column of Object.values(table)) {\n\t\t\tif (column?.type && RESOLVED_SCHEMA_ONLY_TYPES.has(column.type)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Check if any column in the schema has a type only found in GeneratedSchema.\n */\nfunction hasGeneratedSchemaOnlyTypes(\n\ttables: Record<string, Record<string, { type?: string }>>,\n): boolean {\n\tfor (const table of Object.values(tables)) {\n\t\tfor (const column of Object.values(table)) {\n\t\t\tif (column?.type && GENERATED_SCHEMA_ONLY_TYPES.has(column.type)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Type guard for ResolvedSchema (from @dbsp/schema).\n *\n * Detects ResolvedSchema by checking for PostgreSQL-specific column types\n * like 'time' and 'jsonb' that only exist in ResolvedSchema.\n *\n * Note: If the schema has no such types, this may return false even for\n * a valid ResolvedSchema. In that case, the schema can be used directly\n * as a GeneratedSchema since both have the same structure.\n */\nexport function isResolvedSchema(value: unknown): boolean {\n\tif (!isGeneratedSchema(value)) {\n\t\treturn false;\n\t}\n\t// If it has ResolvedSchema-only types, it's definitely a ResolvedSchema\n\tif (\n\t\thasResolvedSchemaOnlyTypes(\n\t\t\tvalue.tables as Record<string, Record<string, { type?: string }>>,\n\t\t)\n\t) {\n\t\treturn true;\n\t}\n\t// If it has GeneratedSchema-only types, it's definitely NOT a ResolvedSchema\n\tif (\n\t\thasGeneratedSchemaOnlyTypes(\n\t\t\tvalue.tables as Record<string, Record<string, { type?: string }>>,\n\t\t)\n\t) {\n\t\treturn false;\n\t}\n\t// Ambiguous case: no distinguishing types. Assume GeneratedSchema (more common at runtime).\n\treturn false;\n}\n\n/**\n * Normalize a schema input to GeneratedSchema.\n *\n * This function accepts either a GeneratedSchema or a ResolvedSchema\n * and returns a GeneratedSchema. If the input is already a GeneratedSchema,\n * it is returned as-is. If it's a ResolvedSchema, it is converted.\n *\n * This is the recommended way to accept schemas in APIs that need to\n * support both schema formats transparently.\n *\n * @param input - Either a GeneratedSchema or ResolvedSchema\n * @returns GeneratedSchema (possibly converted from ResolvedSchema)\n * @throws Error if the input is not a valid schema\n *\n * @example\n * ```typescript\n * import { normalizeSchema } from '@dbsp/core';\n *\n * // Works with GeneratedSchema (from codegen)\n * const schema1 = normalizeSchema(generatedSchema);\n *\n * // Works with ResolvedSchema (from defineSchema())\n * const schema2 = normalizeSchema(resolvedSchema);\n * ```\n */\nexport function normalizeSchema(input: unknown): GeneratedSchema {\n\t// First check if it has the basic structure\n\tif (!isGeneratedSchema(input)) {\n\t\tthrow new Error(\n\t\t\t'Invalid schema: must have tables, relations, hints, and conventions properties',\n\t\t);\n\t}\n\n\t// Check if it looks like a ResolvedSchema (has PostgreSQL-specific types)\n\tif (isResolvedSchema(input)) {\n\t\t// Convert using the existing converter\n\t\tconst result = resolvedSchemaToGeneratedSchema(input);\n\t\tif (!result.success) {\n\t\t\tconst messages = result.errors.map((e) => e.message).join(', ');\n\t\t\tthrow new Error(`Schema conversion failed: ${messages}`);\n\t\t}\n\t\treturn result.schema;\n\t}\n\n\t// Already a GeneratedSchema (or ambiguous but structurally valid)\n\treturn input;\n}\n\n// ============================================================================\n// Valibot Validation Schemas (CORE-005)\n// ============================================================================\n\n/**\n * Schema column type from @dbsp/schema\n */\nconst SchemaColumnTypeSchema = v.picklist([\n\t'uuid',\n\t'string',\n\t'text',\n\t'integer',\n\t'bigint',\n\t'decimal',\n\t'boolean',\n\t'timestamp',\n\t'date',\n\t'time',\n\t'json',\n\t'jsonb',\n\t'daterange',\n\t'tstzrange',\n\t'int4range',\n\t'tsrange',\n\t'int8range',\n\t'numrange',\n]);\n\n/**\n * Foreign key reference schema\n */\n\n/**\n * Prototype-pollution-safe string key validator.\n *\n * Rejects keys that would mutate the Object prototype chain when used as\n * record keys. Used in all top-level record validators (tables, relations,\n * hints) to prevent `{ \"__proto__\": {...} }` from poisoning downstream objects.\n *\n * The three dangerous keys are: `__proto__`, `constructor`, `prototype`.\n */\nconst PROTO_POLLUTION_KEYS = ['__proto__', 'constructor', 'prototype'] as const;\n\n/**\n * Wraps a `v.record(v.string(), valueSchema)` with a pre-check that rejects\n * prototype-pollution keys BEFORE Valibot iterates the record entries.\n *\n * Why not `v.record(safePipedStringKey, valueSchema)`?\n * In Valibot v1, the key schema in `v.record` is only used for TS type inference;\n * it does NOT run validation on keys at parse time. The outer `v.unknown()` +\n * `v.check()` pipe runs on the raw input object before Valibot strips built-in\n * prototype properties like `constructor`, ensuring `constructor` and `__proto__`\n * (the latter only visible via JSON.parse) are caught.\n */\nfunction safeRecord<TValue extends v.GenericSchema>(valueSchema: TValue) {\n\treturn v.pipe(\n\t\tv.unknown(),\n\t\tv.check((input) => {\n\t\t\tif (typeof input !== 'object' || input === null) return true;\n\t\t\treturn !Object.keys(input).some((k) =>\n\t\t\t\t(PROTO_POLLUTION_KEYS as readonly string[]).includes(k),\n\t\t\t);\n\t\t}, 'Schema keys must not include prototype-pollution names (__proto__, constructor, prototype)'),\n\t\tv.record(v.string(), valueSchema),\n\t);\n}\n\nconst ForeignKeyReferenceSchema = v.object({\n\ttable: v.string(),\n\tcolumn: v.optional(v.string()),\n\tonDelete: v.optional(\n\t\tv.picklist(['CASCADE', 'SET NULL', 'RESTRICT', 'NO ACTION']),\n\t),\n\tindex: v.optional(v.boolean()),\n\tparentRole: v.optional(v.string()),\n\tchildRole: v.optional(v.string()),\n});\n\n/**\n * Column definition schema (from @dbsp/schema)\n */\nconst ColumnDefinitionSchema = v.object({\n\ttype: SchemaColumnTypeSchema,\n\tprimaryKey: v.optional(v.boolean()),\n\tnullable: v.optional(v.boolean()),\n\tunique: v.optional(v.boolean()),\n\tautoIncrement: v.optional(v.boolean()),\n\tdefault: v.optional(v.union([v.string(), v.number(), v.boolean()])),\n\treferences: v.optional(ForeignKeyReferenceSchema),\n\tindex: v.optional(v.union([v.boolean(), v.string()])),\n});\n\n/**\n * Table definition schema - flat format (column name -> column def).\n */\nconst FlatTableDefinitionSchema = safeRecord(ColumnDefinitionSchema);\n\n/**\n * Table definition with config - supports composite primary keys.\n * Format: { columns: { col1: ColumnDef }, primaryKey: ['col1', 'col2'] }\n */\nconst TableDefWithConfigSchema = v.object({\n\tcolumns: FlatTableDefinitionSchema,\n\tprimaryKey: v.array(v.string()),\n\tindexes: v.optional(\n\t\tv.array(\n\t\t\tv.object({\n\t\t\t\tcolumns: v.array(v.string()),\n\t\t\t\tunique: v.optional(v.boolean()),\n\t\t\t\tname: v.optional(v.string()),\n\t\t\t}),\n\t\t),\n\t),\n});\n\n/**\n * Table definition schema - accepts both flat and with-config formats.\n */\nconst TableDefinitionSchema = v.union([\n\tTableDefWithConfigSchema,\n\tFlatTableDefinitionSchema,\n]);\n\n/**\n * Tables definition schema\n */\nconst TablesDefinitionSchema = safeRecord(TableDefinitionSchema);\n\n/**\n * BelongsTo relation schema\n */\n/**\n * Include strategy schema for relations\n */\nconst IncludeStrategySchema = v.optional(\n\tv.picklist(['join', 'subquery', 'cte', 'lateral', 'json_agg', 'auto']),\n);\n\nconst BelongsToRelationSchema = v.object({\n\tkind: v.literal('belongsTo'),\n\ttarget: v.string(),\n\tforeignKey: v.string(),\n\ttargetKey: v.optional(v.string()),\n\tincludeStrategy: IncludeStrategySchema,\n});\n\n/**\n * HasMany relation schema\n */\nconst HasManyRelationSchema = v.object({\n\tkind: v.literal('hasMany'),\n\ttarget: v.string(),\n\tforeignKey: v.string(),\n\tsourceKey: v.optional(v.string()),\n\tincludeStrategy: IncludeStrategySchema,\n});\n\n/**\n * ManyToMany relation schema\n */\nconst ManyToManyRelationSchema = v.object({\n\tkind: v.literal('manyToMany'),\n\ttarget: v.string(),\n\tthrough: v.string(),\n\tsourceFk: v.string(),\n\ttargetFk: v.string(),\n\tincludeStrategy: IncludeStrategySchema,\n});\n\n/**\n * Relation definition schema (discriminated union)\n */\nconst RelationDefinitionSchema = v.variant('kind', [\n\tBelongsToRelationSchema,\n\tHasManyRelationSchema,\n\tManyToManyRelationSchema,\n]);\n\n/**\n * Relations definition schema\n */\nconst RelationsDefinitionSchema = safeRecord(RelationDefinitionSchema);\n\n/**\n * Hint definition schema\n */\nconst HintDefinitionSchema = v.object({\n\tdefaultStrategy: v.optional(v.picklist(['exists', 'join'])),\n\tcardinality: v.optional(v.picklist(['one', 'many'])),\n});\n\n/**\n * Hints definition schema\n */\nconst HintsDefinitionSchema = safeRecord(HintDefinitionSchema);\n\n/**\n * Conventions definition schema (resolved = all required)\n */\nconst ConventionsDefinitionSchema = v.object({\n\tfkPattern: v.string(),\n\tpluralize: v.boolean(),\n\ttimestamps: v.array(v.string()),\n\tfkAutoIndex: v.boolean(),\n});\n\n/**\n * Index definition schema\n */\nconst IndexDefinitionSchema = v.object({\n\tcolumns: v.array(v.string()),\n\tunique: v.optional(v.boolean()),\n\tname: v.optional(v.string()),\n});\n\n/**\n * Indexes definition schema - mapping table name to array of indexes\n */\nconst IndexesDefinitionSchema = safeRecord(v.array(IndexDefinitionSchema));\n\n/**\n * Complete ResolvedSchema validation schema\n */\nexport const ResolvedSchemaValidation = v.object({\n\ttables: TablesDefinitionSchema,\n\trelations: RelationsDefinitionSchema,\n\thints: HintsDefinitionSchema,\n\tconventions: ConventionsDefinitionSchema,\n\tindexes: v.optional(IndexesDefinitionSchema),\n});\n\n/**\n * Type inferred from ResolvedSchemaValidation\n */\nexport type ValidatedResolvedSchema = v.InferOutput<\n\ttypeof ResolvedSchemaValidation\n>;\n\n// ============================================================================\n// ResolvedSchema → GeneratedSchema Converter (CORE-005)\n// ============================================================================\n\n/**\n * Map schema column type to generated column type.\n * Handles type differences between the two systems.\n */\nfunction mapSchemaColumnType(\n\tschemaType: v.InferOutput<typeof SchemaColumnTypeSchema>,\n): GeneratedColumnType {\n\tswitch (schemaType) {\n\t\tcase 'uuid':\n\t\t\treturn 'uuid';\n\t\tcase 'string':\n\t\t\treturn 'string';\n\t\tcase 'text':\n\t\t\treturn 'text';\n\t\tcase 'integer':\n\t\t\treturn 'integer';\n\t\tcase 'bigint':\n\t\t\treturn 'bigint';\n\t\tcase 'decimal':\n\t\t\treturn 'decimal';\n\t\tcase 'boolean':\n\t\t\treturn 'boolean';\n\t\tcase 'timestamp':\n\t\t\treturn 'timestamp';\n\t\tcase 'date':\n\t\t\treturn 'date';\n\t\tcase 'time':\n\t\t\treturn 'time';\n\t\tcase 'json':\n\t\t\treturn 'json';\n\t\tcase 'jsonb':\n\t\t\treturn 'jsonb';\n\t\tcase 'daterange':\n\t\t\treturn 'daterange';\n\t\tcase 'tstzrange':\n\t\t\treturn 'tstzrange';\n\t\tcase 'int4range':\n\t\t\treturn 'int4range';\n\t\tcase 'tsrange':\n\t\t\treturn 'tsrange';\n\t\tcase 'int8range':\n\t\t\treturn 'int8range';\n\t\tcase 'numrange':\n\t\t\treturn 'numrange';\n\t}\n}\n\n/**\n * Convert a validated column definition to GeneratedColumn.\n */\nfunction convertColumn(\n\tcol: v.InferOutput<typeof ColumnDefinitionSchema>,\n): GeneratedColumn {\n\tconst result: Mutable<GeneratedColumn> = {\n\t\ttype: mapSchemaColumnType(col.type),\n\t};\n\tif (col.primaryKey !== undefined) {\n\t\tresult.primaryKey = col.primaryKey;\n\t}\n\tif (col.nullable !== undefined) {\n\t\tresult.nullable = col.nullable;\n\t}\n\tif (col.unique !== undefined) {\n\t\tresult.unique = col.unique;\n\t}\n\tif (col.autoIncrement !== undefined) {\n\t\tresult.autoIncrement = col.autoIncrement;\n\t}\n\tif (col.default !== undefined) {\n\t\tresult.default = col.default as string;\n\t}\n\tif (col.references) {\n\t\tresult.references = {\n\t\t\ttable: col.references.table,\n\t\t\t...(col.references.column !== undefined\n\t\t\t\t? { column: col.references.column }\n\t\t\t\t: {}),\n\t\t\t...(col.references.onDelete ? { onDelete: col.references.onDelete } : {}),\n\t\t\t...(col.references.index !== undefined\n\t\t\t\t? { index: col.references.index }\n\t\t\t\t: {}),\n\t\t\t...(col.references.parentRole\n\t\t\t\t? { parentRole: col.references.parentRole }\n\t\t\t\t: {}),\n\t\t\t...(col.references.childRole\n\t\t\t\t? { childRole: col.references.childRole }\n\t\t\t\t: {}),\n\t\t};\n\t}\n\treturn result as GeneratedColumn;\n}\n\n/**\n * Convert a validated relation definition to GeneratedRelation.\n */\nfunction convertRelation(\n\trel: v.InferOutput<typeof RelationDefinitionSchema>,\n): GeneratedRelation {\n\tswitch (rel.kind) {\n\t\tcase 'belongsTo': {\n\t\t\tconst result: Mutable<GeneratedBelongsTo> = {\n\t\t\t\tkind: 'belongsTo',\n\t\t\t\ttarget: rel.target,\n\t\t\t\tforeignKey: rel.foreignKey,\n\t\t\t};\n\t\t\tif (rel.targetKey !== undefined) {\n\t\t\t\tresult.targetKey = rel.targetKey;\n\t\t\t}\n\t\t\tif (rel.includeStrategy !== undefined) {\n\t\t\t\tresult.includeStrategy = rel.includeStrategy;\n\t\t\t}\n\t\t\treturn result as GeneratedBelongsTo;\n\t\t}\n\t\tcase 'hasMany': {\n\t\t\tconst result: Mutable<GeneratedHasMany> = {\n\t\t\t\tkind: 'hasMany',\n\t\t\t\ttarget: rel.target,\n\t\t\t\tforeignKey: rel.foreignKey,\n\t\t\t};\n\t\t\tif (rel.sourceKey !== undefined) {\n\t\t\t\tresult.sourceKey = rel.sourceKey;\n\t\t\t}\n\t\t\tif (rel.includeStrategy !== undefined) {\n\t\t\t\tresult.includeStrategy = rel.includeStrategy;\n\t\t\t}\n\t\t\treturn result as GeneratedHasMany;\n\t\t}\n\t\tcase 'manyToMany': {\n\t\t\tconst result: Mutable<GeneratedManyToMany> = {\n\t\t\t\tkind: 'manyToMany',\n\t\t\t\ttarget: rel.target,\n\t\t\t\tthrough: rel.through,\n\t\t\t\tsourceFk: rel.sourceFk,\n\t\t\t\ttargetFk: rel.targetFk,\n\t\t\t};\n\t\t\tif (rel.includeStrategy !== undefined) {\n\t\t\t\tresult.includeStrategy = rel.includeStrategy;\n\t\t\t}\n\t\t\treturn result as GeneratedManyToMany;\n\t\t}\n\t}\n}\n\n/**\n * Convert a validated hint definition to GeneratedHint.\n */\nfunction convertHint(\n\thint: v.InferOutput<typeof HintDefinitionSchema>,\n): GeneratedHint {\n\tconst result: Mutable<GeneratedHint> = {};\n\tif (hint.defaultStrategy !== undefined) {\n\t\tresult.defaultStrategy = hint.defaultStrategy;\n\t}\n\tif (hint.cardinality !== undefined) {\n\t\tresult.cardinality = hint.cardinality;\n\t}\n\treturn result as GeneratedHint;\n}\n\n/**\n * Result of schema conversion.\n */\nexport type SchemaConversionResult =\n\t| { success: true; schema: GeneratedSchema }\n\t| { success: false; errors: v.BaseIssue<unknown>[] };\n\n/**\n * Convert a ResolvedSchema (from @dbsp/schema) to GeneratedSchema.\n *\n * This function validates the input using Valibot and then converts the\n * schema structure to the format expected by createOrm().\n *\n * @param input - The ResolvedSchema to convert (output of defineSchema())\n * @returns Conversion result with either the converted schema or validation errors\n *\n * @example\n * ```typescript\n * import { defineSchema } from '@dbsp/schema';\n * import { resolvedSchemaToGeneratedSchema, createOrm } from '@dbsp/core';\n *\n * const resolved = defineSchema({ tables: { users: { id: { type: 'uuid' } } } });\n * const result = resolvedSchemaToGeneratedSchema(resolved);\n *\n * if (result.success) {\n * const orm = createOrm({ schema: result.schema, adapter });\n * } else {\n * console.error('Schema validation failed:', result.errors);\n * }\n * ```\n */\nexport function resolvedSchemaToGeneratedSchema(\n\tinput: unknown,\n): SchemaConversionResult {\n\t// Validate input\n\tconst parseResult = v.safeParse(ResolvedSchemaValidation, input);\n\n\tif (!parseResult.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terrors: parseResult.issues,\n\t\t};\n\t}\n\n\tconst validated = parseResult.output;\n\n\t// Convert tables (handles both flat and with-config formats)\n\t// Use Object.create(null) for accumulators to prevent prototype-chain mutation\n\t// even if a key somehow bypasses the safeStringKey Valibot check.\n\tconst tables = Object.create(null) as Record<string, GeneratedTable>;\n\tfor (const [tableName, tableDef] of Object.entries(validated.tables)) {\n\t\tconst convertedTable = Object.create(null) as Record<\n\t\t\tstring,\n\t\t\tGeneratedColumn\n\t\t>;\n\n\t\t// Discriminate with-config vs flat format by checking for a primaryKey array.\n\t\t// Using 'columns' as the discriminant is unsafe: a flat table could legitimately\n\t\t// have a column named 'columns', causing it to be misread as with-config.\n\t\t// TableDefWithConfigSchema requires `primaryKey: array(string())` which flat\n\t\t// shorthand columns never have, so this is a reliable discriminant.\n\t\tconst tableObj = tableDef as Record<string, unknown>;\n\t\tconst isWithConfig = Array.isArray(tableObj.primaryKey);\n\n\t\tconst columns = isWithConfig\n\t\t\t? (tableObj.columns as Record<string, unknown>)\n\t\t\t: tableObj;\n\n\t\tfor (const [colName, colDef] of Object.entries(columns)) {\n\t\t\tconvertedTable[colName] = convertColumn(\n\t\t\t\tcolDef as v.InferOutput<typeof ColumnDefinitionSchema>,\n\t\t\t);\n\t\t}\n\t\ttables[tableName] = convertedTable;\n\t}\n\n\t// Convert relations\n\tconst relations = Object.create(null) as Record<string, GeneratedRelation>;\n\tfor (const [relName, relDef] of Object.entries(validated.relations)) {\n\t\trelations[relName] = convertRelation(relDef);\n\t}\n\n\t// Convert hints\n\tconst hints = Object.create(null) as Record<string, GeneratedHint>;\n\tfor (const [hintName, hintDef] of Object.entries(validated.hints)) {\n\t\thints[hintName] = convertHint(hintDef);\n\t}\n\n\t// Convert conventions\n\tconst conventions: GeneratedConventions = {\n\t\tfkPattern: validated.conventions.fkPattern,\n\t\tpluralize: validated.conventions.pluralize,\n\t\ttimestamps: validated.conventions.timestamps,\n\t\tfkAutoIndex: validated.conventions.fkAutoIndex,\n\t};\n\n\treturn {\n\t\tsuccess: true,\n\t\tschema: {\n\t\t\ttables,\n\t\t\trelations,\n\t\t\thints,\n\t\t\tconventions,\n\t\t},\n\t};\n}\n\n/**\n * Assert and convert a ResolvedSchema to GeneratedSchema.\n *\n * Throws an error if validation fails. Use this when you're confident\n * the input is valid and want cleaner code without result checking.\n *\n * @param input - The ResolvedSchema to convert\n * @returns The converted GeneratedSchema\n * @throws Error if validation fails\n */\nexport function assertResolvedSchemaToGeneratedSchema(\n\tinput: unknown,\n): GeneratedSchema {\n\tconst result = resolvedSchemaToGeneratedSchema(input);\n\tif (!result.success) {\n\t\tconst messages = result.errors\n\t\t\t.map((e) => {\n\t\t\t\tconst path = e.path?.map((p) => p.key).join('.') || 'root';\n\t\t\t\treturn `[${path}] ${e.message} (expected: ${e.expected}, received: ${e.received})`;\n\t\t\t})\n\t\t\t.join('\\n');\n\t\tthrow new Error(`Schema validation failed:\\n${messages}`);\n\t}\n\treturn result.schema;\n}\n","/**\n * Dialect Capabilities Registry\n *\n * CORE-004: Centralized module for SQL dialect capabilities.\n * Avoids duplication across adapters by providing a single source of truth.\n *\n * Type definitions live in @dbsp/types. This module re-exports them\n * and provides runtime constants and functions.\n */\n\nimport type {\n\tColumnType,\n\tDDLFeature,\n\tDDLFeatureVersionRange,\n} from '@dbsp/types';\n\n// Re-export all dialect types from @dbsp/types for backward compatibility\nexport type {\n\tCommonColumnType,\n\tDDLFeatureVersionRange,\n\tDialectCapabilities,\n\tDialectName,\n\tDuckDBColumnType,\n\tIsTypeSupported,\n\tMSSQLColumnType,\n\tMySQLColumnType,\n\tPostgresColumnType,\n\tPostgresOnlyColumnType,\n\tSQLiteColumnType,\n\tSupportedColumnTypes,\n} from '@dbsp/types';\n\nimport type { DialectCapabilities } from '@dbsp/types';\n\n/**\n * PostgreSQL dialect capabilities.\n * The most feature-rich dialect, serves as the reference implementation.\n */\nexport const POSTGRESQL_CAPABILITIES: DialectCapabilities = {\n\tname: 'postgresql',\n\n\t// Features\n\tsupportsReturning: true,\n\tsupportsRecursiveCTE: true,\n\tsupportsWindowFunctions: true,\n\tsupportsArrayType: true,\n\tsupportsRangeTypes: true, // PostgreSQL has native range types (daterange, int4range, etc.)\n\tsupportsJsonType: true,\n\tsupportsJsonOperators: true, // PG: ->, ->>, @>, <@, ?, #>, #>>\n\tsupportsSchemas: true,\n\n\t// Include Strategy Capabilities (CORE-006)\n\tsupportsLateralJoin: true,\n\tsupportsJsonAgg: true,\n\n\t// DDL Feature Support (CAPS-001)\n\tsupportsDDLEnumTypes: true,\n\tsupportsDDLSequences: true,\n\tsupportsDDLExtensions: true,\n\tsupportsDDLPartitioning: true,\n\tsupportsDDLCheckConstraints: true,\n\tsupportsDDLOnUpdateFK: true,\n\tsupportsDDLDeferredFK: true,\n\tsupportsDDLIdentityColumns: true,\n\tsupportsDDLCollation: true,\n\tsupportsDDLComments: true,\n\tsupportsDDLIndexMethods: true,\n\tsupportsDDLIndexOpclass: true,\n\tsupportsDDLIndexInclude: true,\n\tsupportsDDLPartialIndexes: true,\n\tsupportsDDLExpressionIndexes: true,\n\tsupportsDDLRowLevelSecurity: true,\n\n\t// Syntax\n\trecursivePathStyle: 'array',\n\tstringConcatStyle: 'operator',\n\tidentifierQuote: '\"',\n\tparameterStyle: 'dollar',\n\tlimitStyle: 'limit-offset',\n\tbooleanStyle: 'native',\n};\n\n/**\n * MySQL dialect capabilities.\n */\nexport const MYSQL_CAPABILITIES: DialectCapabilities = {\n\tname: 'mysql',\n\n\t// Features\n\tsupportsReturning: false, // MySQL 8.0.21+ has limited support\n\tsupportsRecursiveCTE: true, // MySQL 8.0+\n\tsupportsWindowFunctions: true, // MySQL 8.0+\n\tsupportsArrayType: false,\n\tsupportsRangeTypes: false, // MySQL has no native range types\n\tsupportsJsonType: true,\n\tsupportsJsonOperators: false, // MySQL uses JSON_EXTRACT() functions, not operators\n\tsupportsSchemas: true, // MySQL uses database as schema\n\n\t// Include Strategy Capabilities (CORE-006)\n\tsupportsLateralJoin: false, // MySQL 8.0.14+ has LATERAL but limited\n\tsupportsJsonAgg: true, // JSON_ARRAYAGG() in MySQL 8.0+\n\n\t// Syntax\n\trecursivePathStyle: 'string',\n\tstringConcatStyle: 'function',\n\tidentifierQuote: '`',\n\tparameterStyle: 'question',\n\tlimitStyle: 'limit-offset',\n\tbooleanStyle: 'numeric',\n};\n\n/**\n * SQLite dialect capabilities.\n */\nexport const SQLITE_CAPABILITIES: DialectCapabilities = {\n\tname: 'sqlite',\n\n\t// Features\n\tsupportsReturning: true, // SQLite 3.35+\n\tsupportsRecursiveCTE: true,\n\tsupportsWindowFunctions: true, // SQLite 3.25+\n\tsupportsArrayType: false,\n\tsupportsRangeTypes: false, // SQLite has no native range types\n\tsupportsJsonType: true, // SQLite 3.38+ (JSON1 extension)\n\tsupportsJsonOperators: false, // SQLite uses json_extract() functions\n\tsupportsSchemas: false, // SQLite uses ATTACH for multiple databases\n\n\t// Include Strategy Capabilities (CORE-006)\n\tsupportsLateralJoin: false, // Not supported\n\tsupportsJsonAgg: false, // json_group_array exists but is limited\n\n\t// Syntax\n\trecursivePathStyle: 'string',\n\tstringConcatStyle: 'operator',\n\tidentifierQuote: '\"',\n\tparameterStyle: 'question',\n\tlimitStyle: 'limit-offset',\n\tbooleanStyle: 'numeric',\n};\n\n/**\n * DuckDB dialect capabilities.\n * Analytical database with PostgreSQL-compatible syntax.\n */\nexport const DUCKDB_CAPABILITIES: DialectCapabilities = {\n\tname: 'duckdb',\n\n\t// Features\n\tsupportsReturning: true,\n\tsupportsRecursiveCTE: true,\n\tsupportsWindowFunctions: true,\n\tsupportsArrayType: true, // DuckDB has LIST type\n\tsupportsRangeTypes: false, // DuckDB has no native range types like PostgreSQL\n\tsupportsJsonType: true,\n\tsupportsJsonOperators: false, // DuckDB uses json_extract() style\n\tsupportsSchemas: true,\n\n\t// Include Strategy Capabilities (CORE-006)\n\tsupportsLateralJoin: true, // DuckDB supports LATERAL\n\tsupportsJsonAgg: true, // list_agg / json_group_array\n\n\t// Syntax\n\trecursivePathStyle: 'array', // DuckDB uses LIST which is similar\n\tstringConcatStyle: 'operator',\n\tidentifierQuote: '\"',\n\tparameterStyle: 'dollar',\n\tlimitStyle: 'limit-offset',\n\tbooleanStyle: 'native',\n};\n\n/**\n * MSSQL dialect capabilities.\n */\nexport const MSSQL_CAPABILITIES: DialectCapabilities = {\n\tname: 'mssql',\n\n\t// Features\n\tsupportsReturning: true, // OUTPUT clause\n\tsupportsRecursiveCTE: true,\n\tsupportsWindowFunctions: true,\n\tsupportsArrayType: false,\n\tsupportsRangeTypes: false, // MSSQL has no native range types\n\tsupportsJsonType: true, // SQL Server 2016+\n\tsupportsJsonOperators: false, // MSSQL uses JSON_VALUE/JSON_QUERY functions\n\tsupportsSchemas: true,\n\n\t// Include Strategy Capabilities (CORE-006)\n\tsupportsLateralJoin: true, // CROSS APPLY / OUTER APPLY\n\tsupportsJsonAgg: false, // FOR JSON exists but different semantics\n\n\t// Syntax\n\trecursivePathStyle: 'string',\n\tstringConcatStyle: 'function', // CONCAT() or +\n\tidentifierQuote: '[',\n\tparameterStyle: 'named', // @param\n\tlimitStyle: 'top', // TOP or OFFSET FETCH\n\tbooleanStyle: 'numeric',\n};\n\n/**\n * Compare two version strings numerically (e.g., '8.0.16' vs '8.0.15').\n * Returns: -1 if a < b, 0 if equal, 1 if a > b.\n * Supports any number of segments (3.8, 8.0.16, 15.0.1.2).\n */\nfunction compareVersions(a: string, b: string): number {\n\tconst partsA = a.split('.').map(Number);\n\tconst partsB = b.split('.').map(Number);\n\tconst len = Math.max(partsA.length, partsB.length);\n\tfor (let i = 0; i < len; i++) {\n\t\tconst segA = partsA[i] ?? 0;\n\t\tconst segB = partsB[i] ?? 0;\n\t\tif (segA < segB) return -1;\n\t\tif (segA > segB) return 1;\n\t}\n\treturn 0;\n}\n\n/** Maps DDLFeature name → DialectCapabilities flag name */\nconst FEATURE_TO_FLAG: Record<DDLFeature, string> = {\n\tenum: 'supportsDDLEnumTypes',\n\tsequence: 'supportsDDLSequences',\n\textension: 'supportsDDLExtensions',\n\tpartition: 'supportsDDLPartitioning',\n\tcheckConstraint: 'supportsDDLCheckConstraints',\n\tonUpdateFK: 'supportsDDLOnUpdateFK',\n\tdeferredFK: 'supportsDDLDeferredFK',\n\tidentity: 'supportsDDLIdentityColumns',\n\tcollation: 'supportsDDLCollation',\n\tcomment: 'supportsDDLComments',\n\tindexMethod: 'supportsDDLIndexMethods',\n\tindexOpclass: 'supportsDDLIndexOpclass',\n\tindexInclude: 'supportsDDLIndexInclude',\n\tpartialIndex: 'supportsDDLPartialIndexes',\n\texpressionIndex: 'supportsDDLExpressionIndexes',\n};\n\n/**\n * Factory helper for adapter authors to create DialectCapabilities.\n * All DDL flags default to false (unsupported) unless overridden.\n * Required fields (name, syntax variants) must be provided.\n *\n * @param overrides - Required syntax fields plus any capability overrides.\n * @param options - Optional version-aware resolution. When `version` and\n * `versionRequirements` are both provided, features outside their version\n * range are set to `undefined` (unsupported) in the returned capabilities.\n */\nexport function createDialectCapabilities(\n\toverrides: Partial<DialectCapabilities> &\n\t\tPick<\n\t\t\tDialectCapabilities,\n\t\t\t| 'name'\n\t\t\t| 'identifierQuote'\n\t\t\t| 'parameterStyle'\n\t\t\t| 'limitStyle'\n\t\t\t| 'booleanStyle'\n\t\t\t| 'recursivePathStyle'\n\t\t\t| 'stringConcatStyle'\n\t\t>,\n\toptions?: {\n\t\t/** Current database version (e.g., '8.0.16', '3.35.0') */\n\t\tversion?: string;\n\t\t/** Per-feature version requirements. Features outside the range are set to undefined. */\n\t\tversionRequirements?: Partial<Record<DDLFeature, DDLFeatureVersionRange>>;\n\t},\n): DialectCapabilities {\n\tconst result: Record<string, unknown> = {\n\t\t// Feature defaults (all false = unsupported)\n\t\tsupportsReturning: false,\n\t\tsupportsRecursiveCTE: false,\n\t\tsupportsWindowFunctions: false,\n\t\tsupportsArrayType: false,\n\t\tsupportsRangeTypes: false,\n\t\tsupportsJsonType: false,\n\t\tsupportsJsonOperators: false,\n\t\tsupportsSchemas: false,\n\t\tsupportsLateralJoin: false,\n\t\tsupportsJsonAgg: false,\n\t\t// DDL flags all default to undefined (unsupported per INV-02)\n\t\t...overrides,\n\t};\n\n\tif (options?.version && options?.versionRequirements) {\n\t\tconst ver = options.version;\n\t\tconst reqs = options.versionRequirements;\n\t\tfor (const [feature, range] of Object.entries(reqs) as [\n\t\t\tDDLFeature,\n\t\t\tDDLFeatureVersionRange,\n\t\t][]) {\n\t\t\tconst flagName = FEATURE_TO_FLAG[feature];\n\t\t\tif (!flagName) continue;\n\t\t\tconst meetsMin = !range.min || compareVersions(ver, range.min) >= 0;\n\t\t\tconst meetsMax = !range.max || compareVersions(ver, range.max) <= 0;\n\t\t\tif (!meetsMin || !meetsMax) {\n\t\t\t\tdelete result[flagName];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result as unknown as DialectCapabilities;\n}\n\n/**\n * Registry of all known dialect capabilities.\n * Use `registerDialect()` to add custom dialects.\n */\nconst dialectRegistry: Map<string, DialectCapabilities> = new Map([\n\t['postgresql', POSTGRESQL_CAPABILITIES],\n\t['postgres', POSTGRESQL_CAPABILITIES], // Alias\n\t['pg', POSTGRESQL_CAPABILITIES], // Alias\n\t['mysql', MYSQL_CAPABILITIES],\n\t['sqlite', SQLITE_CAPABILITIES],\n\t['duckdb', DUCKDB_CAPABILITIES],\n\t['mssql', MSSQL_CAPABILITIES],\n\t['sqlserver', MSSQL_CAPABILITIES], // Alias\n]);\n\n/**\n * Error thrown when a dialect is not found in the registry.\n */\nexport class UnknownDialectError extends Error {\n\tconstructor(\n\t\tpublic readonly dialectName: string,\n\t\tpublic readonly availableDialects: string[],\n\t) {\n\t\tconst available = availableDialects.join(', ');\n\t\tsuper(`Unknown dialect '${dialectName}'. Available dialects: ${available}`);\n\t\tthis.name = 'UnknownDialectError';\n\t}\n}\n\n/**\n * Get capabilities for a known dialect.\n *\n * @param dialectName - The dialect identifier (e.g., 'postgresql', 'mysql')\n * @returns The dialect capabilities\n * @throws UnknownDialectError if the dialect is not registered\n *\n * @example\n * ```typescript\n * const caps = getDialectCapabilities('postgresql');\n * if (caps.supportsReturning) {\n * // Add RETURNING clause\n * }\n * ```\n */\nexport function getDialectCapabilities(\n\tdialectName: string,\n): DialectCapabilities {\n\tconst normalized = dialectName.toLowerCase();\n\tconst capabilities = dialectRegistry.get(normalized);\n\n\tif (!capabilities) {\n\t\tconst available = Array.from(dialectRegistry.keys()).filter(\n\t\t\t(key) => dialectRegistry.get(key)?.name === key, // Only show primary names, not aliases\n\t\t);\n\t\tthrow new UnknownDialectError(dialectName, available);\n\t}\n\n\treturn capabilities;\n}\n\n/**\n * Check if a dialect is registered.\n *\n * @param dialectName - The dialect identifier\n * @returns true if the dialect is known\n */\nexport function isKnownDialect(dialectName: string): boolean {\n\treturn dialectRegistry.has(dialectName.toLowerCase());\n}\n\n/**\n * Get all registered dialect names (primary names only, not aliases).\n *\n * @returns Array of dialect names\n */\nexport function getAvailableDialects(): string[] {\n\tconst seen = new Set<string>();\n\tconst result: string[] = [];\n\n\tfor (const [_key, caps] of dialectRegistry) {\n\t\tif (!seen.has(caps.name)) {\n\t\t\tseen.add(caps.name);\n\t\t\tresult.push(caps.name);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Register a custom dialect or override an existing one.\n *\n * @param dialectName - The dialect identifier\n * @param capabilities - The dialect capabilities\n *\n * @example\n * ```typescript\n * // Register a custom dialect\n * registerDialect('cockroachdb', {\n * ...POSTGRESQL_CAPABILITIES,\n * name: 'cockroachdb',\n * // Override specific capabilities\n * });\n *\n * // Add an alias\n * registerDialect('crdb', getDialectCapabilities('cockroachdb'));\n * ```\n */\nexport function registerDialect(\n\tdialectName: string,\n\tcapabilities: DialectCapabilities,\n): void {\n\tdialectRegistry.set(dialectName.toLowerCase(), capabilities);\n}\n\n/**\n * Create custom capabilities by extending a base dialect.\n *\n * @param base - The base dialect to extend\n * @param overrides - Partial capabilities to override\n * @returns New capabilities object\n *\n * @example\n * ```typescript\n * const cockroachCaps = extendDialect(POSTGRESQL_CAPABILITIES, {\n * name: 'cockroachdb',\n * supportsArrayType: false, // CockroachDB has limited array support\n * });\n * registerDialect('cockroachdb', cockroachCaps);\n * ```\n */\nexport function extendDialect(\n\tbase: DialectCapabilities,\n\toverrides: Partial<DialectCapabilities> & { name: string },\n): DialectCapabilities {\n\treturn { ...base, ...overrides };\n}\n\n// ============================================================================\n// Dialect Type Errors\n// ============================================================================\n\n/**\n * Error thrown when a column type is not supported by the target dialect.\n *\n * @example\n * ```typescript\n * // PostgreSQL range types are not supported in MySQL\n * throw new UnhandledTypeInDialect('daterange', 'mysql', 'Range types are PostgreSQL-specific');\n * ```\n */\nexport class UnhandledTypeInDialect extends Error {\n\tconstructor(\n\t\t/** The column type that is not supported */\n\t\tpublic readonly columnType: ColumnType | string,\n\t\t/** The dialect that doesn't support the type */\n\t\tpublic readonly dialectName: string,\n\t\t/** Optional hint for the user */\n\t\tpublic readonly hint?: string,\n\t) {\n\t\tconst hintSuffix = hint ? ` Hint: ${hint}` : '';\n\t\tsuper(\n\t\t\t`Type '${columnType}' is not supported by dialect '${dialectName}'.${hintSuffix}`,\n\t\t);\n\t\tthis.name = 'UnhandledTypeInDialect';\n\t}\n}\n\n/**\n * Check if a column type is supported by a dialect at runtime.\n * Returns true if supported, throws UnhandledTypeInDialect if not.\n *\n * @param type - The column type to check\n * @param dialectName - The target dialect\n * @param capabilities - The dialect capabilities\n * @throws UnhandledTypeInDialect if the type is not supported\n *\n * @example\n * ```typescript\n * assertTypeSupported('daterange', 'postgresql', pgCaps); // OK\n * assertTypeSupported('daterange', 'mysql', mysqlCaps); // throws!\n * ```\n */\nexport function assertTypeSupported(\n\ttype: ColumnType,\n\tdialectName: string,\n\tcapabilities: DialectCapabilities,\n): void {\n\t// Range types require supportsRangeTypes\n\tconst rangeTypes: ColumnType[] = [\n\t\t'daterange',\n\t\t'tsrange',\n\t\t'tstzrange',\n\t\t'int4range',\n\t\t'int8range',\n\t\t'numrange',\n\t];\n\n\tif (rangeTypes.includes(type) && !capabilities.supportsRangeTypes) {\n\t\tthrow new UnhandledTypeInDialect(\n\t\t\ttype,\n\t\t\tdialectName,\n\t\t\t'Range types are PostgreSQL-specific. Consider using separate start/end columns instead.',\n\t\t);\n\t}\n\n\t// JSONB specifically requires PostgreSQL\n\tif (type === 'jsonb' && dialectName !== 'postgresql') {\n\t\tthrow new UnhandledTypeInDialect(\n\t\t\ttype,\n\t\t\tdialectName,\n\t\t\t\"Use 'json' type instead, which is supported by most dialects.\",\n\t\t);\n\t}\n}\n","/**\n * Adapter-agnostic SQL utilities.\n *\n * Pure string helpers that work with any SQL dialect.\n * Placed in core so every package can use them without\n * pulling in a specific adapter dependency.\n */\n\n/**\n * Normalize SQL for comparison: collapse whitespace, lowercase, trim.\n * Useful for golden-file tests and assertion systems.\n */\nexport function normalizeSQL(sql: string): string {\n\treturn sql\n\t\t.toLowerCase()\n\t\t.replace(/\\s+/g, ' ')\n\t\t.replace(/\\s*,\\s*/g, ', ')\n\t\t.replace(/\\(\\s+/g, '(')\n\t\t.replace(/\\s+\\)/g, ')')\n\t\t.replace(/;\\s*$/, '')\n\t\t.trim();\n}\n","/**\n * Individual assertion evaluators for the assertion system.\n *\n * Each function takes inputs and returns an AssertionOutcome.\n * Grouped by domain: general, SQL, params, DB, intent.\n */\n\nimport { normalizeSQL } from '../sql-utils.js';\nimport type { AssertionType, TableAssertionData } from './assertion-parser.js';\nimport type {\n\tAssertionOutcome,\n\tAssertionQueryResult,\n\tIntentSummary,\n} from './types.js';\n\n// Re-export normalizeSQL from core (canonical location)\nexport { normalizeSQL };\n\n// ============================================================\n// Helpers\n// ============================================================\n\n/**\n * Convert camelCase to snake_case\n */\nfunction toSnakeCase(str: string): string {\n\treturn str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n// ============================================================\n// GENERAL ASSERTIONS\n// ============================================================\n\n/**\n * Assert that a string contains a substring\n */\nexport function assertContains(\n\tfield: string,\n\tactual: string,\n\texpected: string,\n\toriginalType?: AssertionType,\n): AssertionOutcome {\n\tconst passed = actual.includes(expected);\n\treturn {\n\t\ttype: originalType ?? (`${field}.contains` as AssertionType),\n\t\texpected,\n\t\tactual: passed ? undefined : actual, // Full value, no truncation\n\t\tpassed,\n\t\tmessage: passed ? undefined : `Expected ${field} to contain \"${expected}\"`,\n\t};\n}\n\n/**\n * Assert exact string equality\n */\nexport function assertEquals(\n\tfield: string,\n\tactual: string,\n\texpected: string,\n): AssertionOutcome {\n\tconst passed = actual.trim() === expected.trim();\n\treturn {\n\t\ttype: `${field}.equals` as AssertionType,\n\t\texpected,\n\t\tactual: passed ? undefined : actual, // Full value, no truncation\n\t\tpassed,\n\t\tmessage: passed ? undefined : `Expected ${field} to equal \"${expected}\"`,\n\t};\n}\n\n/**\n * Assert string matches regex\n */\nexport function assertMatches(\n\tfield: string,\n\tactual: string,\n\tpattern: string,\n): AssertionOutcome {\n\tconst regex = new RegExp(pattern);\n\tconst passed = regex.test(actual);\n\treturn {\n\t\ttype: `${field}.matches` as AssertionType,\n\t\texpected: pattern,\n\t\tactual: passed ? undefined : actual, // Full value, no truncation\n\t\tpassed,\n\t\tmessage: passed ? undefined : `Expected ${field} to match /${pattern}/`,\n\t};\n}\n\n/**\n * Assert query success/failure\n */\nexport function assertSuccess(\n\tactual: boolean,\n\texpected: boolean,\n): AssertionOutcome {\n\tconst passed = actual === expected;\n\treturn {\n\t\ttype: 'success',\n\t\texpected,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Expected query to ${expected ? 'succeed' : 'fail'}, but it ${actual ? 'succeeded' : 'failed'}`,\n\t};\n}\n\n// ============================================================\n// SQL ASSERTIONS\n// ============================================================\n\n/**\n * Assert SQL equality with normalization\n */\nexport function assertSQLEquals(\n\tactual: string,\n\texpected: string,\n): AssertionOutcome {\n\tconst normalizedActual = normalizeSQL(actual);\n\tconst normalizedExpected = normalizeSQL(expected);\n\tconst passed = normalizedActual === normalizedExpected;\n\n\treturn {\n\t\ttype: 'sql.equals',\n\t\texpected,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `SQL mismatch:\\n Expected: ${expected}\\n Actual: ${actual}`,\n\t};\n}\n\n/**\n * Factory for SQL identifier assertions (table/column).\n * Matches: logical name, physical snake_case, or quoted variants.\n */\nfunction createSQLIdentifierAssertion(\n\tassertionType: AssertionType,\n\tlabel: string,\n) {\n\treturn (sql: string, name: string): AssertionOutcome => {\n\t\tconst normalizedSql = sql.toLowerCase();\n\t\tconst logicalLower = name.toLowerCase();\n\t\tconst physicalSnake = toSnakeCase(name).toLowerCase();\n\n\t\tconst found =\n\t\t\tnormalizedSql.includes(logicalLower) ||\n\t\t\tnormalizedSql.includes(physicalSnake) ||\n\t\t\tnormalizedSql.includes(`\"${logicalLower}\"`) ||\n\t\t\tnormalizedSql.includes(`\"${physicalSnake}\"`);\n\n\t\treturn {\n\t\t\ttype: assertionType,\n\t\t\texpected: name,\n\t\t\tactual: found ? undefined : sql,\n\t\t\tpassed: found,\n\t\t\tmessage: found\n\t\t\t\t? undefined\n\t\t\t\t: `Expected SQL to reference ${label} \"${name}\"${physicalSnake !== logicalLower ? ` (or \"${physicalSnake}\")` : ''}`,\n\t\t};\n\t};\n}\n\nexport const assertSQLTable = createSQLIdentifierAssertion(\n\t'sql.table',\n\t'table',\n);\nexport const assertSQLColumn = createSQLIdentifierAssertion(\n\t'sql.column',\n\t'column',\n);\n\n/**\n * Assert SQL references a table via JOIN or CTE\n * Detects: LEFT/RIGHT/INNER/FULL/CROSS JOIN, WITH clause (CTE)\n * Handles schema-qualified names: \"schema\".\"table\" and plain \"table\"\n */\nexport function assertSQLJoin(\n\tsql: string,\n\ttableName: string,\n): AssertionOutcome {\n\tconst normalizedSql = sql.toLowerCase();\n\tconst tableNameLower = tableName.toLowerCase();\n\tconst tableSnake = toSnakeCase(tableName).toLowerCase();\n\n\t// Check for any type of JOIN (left, right, inner, full, cross)\n\tconst joinPattern = /\\b(left|right|inner|full|cross)?\\s*join\\b/;\n\tconst hasJoin = joinPattern.test(normalizedSql);\n\n\t// Check for CTE (WITH clause)\n\tconst ctePattern = new RegExp(\n\t\t`\\\\bwith\\\\b[^)]*\\\\b(${tableNameLower}|${tableSnake})\\\\b`,\n\t);\n\tconst hasCte = ctePattern.test(normalizedSql);\n\n\t// Check for table name (handles schema-qualified: \"schema\".\"table\")\n\t// Match: \"table\", \"schema\".\"table\", table (unquoted)\n\tconst tablePatterns = [\n\t\t`\"${tableNameLower}\"`, // quoted logical\n\t\t`\"${tableSnake}\"`, // quoted physical\n\t\t`.${tableNameLower}`, // after schema dot\n\t\t`.${tableSnake}`, // after schema dot (snake)\n\t\t` ${tableNameLower} `, // unquoted with spaces\n\t\t` ${tableSnake} `, // unquoted snake\n\t];\n\tconst hasTable = tablePatterns.some((p) => normalizedSql.includes(p));\n\n\t// Pass if: (has JOIN AND has table) OR (has CTE with table)\n\tconst found = (hasJoin && hasTable) || hasCte;\n\n\treturn {\n\t\ttype: 'sql.join',\n\t\texpected: tableName,\n\t\tactual: found ? undefined : sql,\n\t\tpassed: found,\n\t\tmessage: found\n\t\t\t? undefined\n\t\t\t: `Expected SQL to reference \"${tableName}\" via JOIN or CTE`,\n\t};\n}\n\n// ============================================================\n// PARAMS ASSERTIONS\n// ============================================================\n\n/**\n * Assert params array equality\n */\nexport function assertParamsEquals(\n\tactual: readonly unknown[],\n\texpected: unknown[],\n): AssertionOutcome {\n\tconst actualStr = JSON.stringify(actual);\n\tconst expectedStr = JSON.stringify(expected);\n\tconst passed = actualStr === expectedStr;\n\n\treturn {\n\t\ttype: 'params.equals',\n\t\texpected,\n\t\tactual: passed ? undefined : [...actual],\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Params mismatch:\\n Expected: ${expectedStr}\\n Actual: ${actualStr}`,\n\t};\n}\n\n/**\n * Assert params array length\n */\nexport function assertParamsLength(\n\tactual: readonly unknown[],\n\texpected: number,\n): AssertionOutcome {\n\tconst passed = actual.length === expected;\n\treturn {\n\t\ttype: 'params.length',\n\t\texpected,\n\t\tactual: passed ? undefined : actual.length,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Expected ${expected} params, got ${actual.length}`,\n\t};\n}\n\n/**\n * Assert parameter types (string, number, boolean, null, object)\n */\nexport function assertParamsType(\n\tparams: readonly unknown[],\n\texpectedTypes: string[],\n): AssertionOutcome {\n\tif (params.length !== expectedTypes.length) {\n\t\treturn {\n\t\t\ttype: 'params.type',\n\t\t\texpected: expectedTypes,\n\t\t\tactual: params.map((p) => typeof p),\n\t\t\tpassed: false,\n\t\t\tmessage: `Expected ${expectedTypes.length} params, got ${params.length}`,\n\t\t};\n\t}\n\n\tconst actualTypes: string[] = [];\n\tconst mismatches: string[] = [];\n\n\tfor (let i = 0; i < params.length; i++) {\n\t\tconst param = params[i];\n\t\tconst expectedType = expectedTypes[i];\n\t\tlet actualType: string;\n\n\t\tif (param === null) {\n\t\t\tactualType = 'null';\n\t\t} else if (Array.isArray(param)) {\n\t\t\tactualType = 'array';\n\t\t} else if (typeof param === 'object') {\n\t\t\tactualType = 'object';\n\t\t} else {\n\t\t\tactualType = typeof param;\n\t\t}\n\n\t\tactualTypes.push(actualType);\n\n\t\tif (actualType !== expectedType) {\n\t\t\tmismatches.push(\n\t\t\t\t`Index ${i}: expected ${expectedType}, got ${actualType}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst passed = mismatches.length === 0;\n\n\treturn {\n\t\ttype: 'params.type',\n\t\texpected: expectedTypes,\n\t\tactual: passed ? undefined : actualTypes,\n\t\tpassed,\n\t\tmessage: passed ? undefined : `Type mismatch: ${mismatches.join('; ')}`,\n\t};\n}\n\n/**\n * Spec format for asserting parameter value by index\n */\ninterface ParamsValueSpec {\n\tindex: number;\n\tvalue: unknown;\n}\n\n/**\n * Assert specific parameter value by index\n * Value format: { index: number, value: unknown }\n */\nexport function assertParamsValue(\n\tparams: readonly unknown[],\n\tspec: unknown,\n): AssertionOutcome {\n\tconst { index, value } =\n\t\ttypeof spec === 'object' && spec !== null\n\t\t\t? (spec as ParamsValueSpec)\n\t\t\t: { index: 0, value: spec };\n\n\tif (index >= params.length) {\n\t\treturn {\n\t\t\ttype: 'params.value',\n\t\t\texpected: value,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: `No param at index ${index} (only ${params.length} params)`,\n\t\t};\n\t}\n\n\tconst actual = params[index];\n\tconst passed = JSON.stringify(actual) === JSON.stringify(value);\n\n\treturn {\n\t\ttype: 'params.value',\n\t\texpected: value,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Param at index ${index}: expected ${JSON.stringify(value)}, got ${JSON.stringify(actual)}`,\n\t};\n}\n\n// ============================================================\n// DB ASSERTIONS (require database connection)\n// ============================================================\n\ntype RowCountComparator = (actual: number, expected: number) => boolean;\n\nfunction createRowCountAssertion(\n\tassertionType: AssertionType,\n\tcompare: RowCountComparator,\n\tmessageTemplate: (expected: number, actual: number) => string,\n) {\n\treturn (result: AssertionQueryResult, expected: number): AssertionOutcome => {\n\t\tconst rowCount = result.rowCount ?? 0;\n\t\tconst passed = compare(rowCount, expected);\n\t\treturn {\n\t\t\ttype: assertionType,\n\t\t\texpected,\n\t\t\tactual: passed ? undefined : rowCount,\n\t\t\tpassed,\n\t\t\tmessage: passed ? undefined : messageTemplate(expected, rowCount),\n\t\t};\n\t};\n}\n\nexport const assertDbRowsEquals = createRowCountAssertion(\n\t'db.rows.equals',\n\t(a, e) => a === e,\n\t(e, a) => `Expected ${e} rows, got ${a}`,\n);\n\nexport const assertDbRowsMin = createRowCountAssertion(\n\t'db.rows.min',\n\t(a, e) => a >= e,\n\t(e, a) => `Expected at least ${e} rows, got ${a}`,\n);\n\nexport const assertDbRowsMax = createRowCountAssertion(\n\t'db.rows.max',\n\t(a, e) => a <= e,\n\t(e, a) => `Expected at most ${e} rows, got ${a}`,\n);\n\n/**\n * Assert column exists in result\n */\nexport function assertDbColumnExists(\n\tresult: AssertionQueryResult,\n\tcolumnName: string,\n): AssertionOutcome {\n\tconst columns = result.columns ?? [];\n\tconst columnLower = columnName.toLowerCase();\n\tconst columnSnake = toSnakeCase(columnName).toLowerCase();\n\n\tconst found = columns.some((col) => {\n\t\tconst colLower = col.toLowerCase();\n\t\treturn colLower === columnLower || colLower === columnSnake;\n\t});\n\n\treturn {\n\t\ttype: 'db.column.exists',\n\t\texpected: columnName,\n\t\tactual: found ? undefined : columns,\n\t\tpassed: found,\n\t\tmessage: found\n\t\t\t? undefined\n\t\t\t: `Column \"${columnName}\" not found in result. Available: ${columns.join(', ')}`,\n\t};\n}\n\n/**\n * Spec format for asserting cell value in result\n */\ninterface CellValueSpec {\n\trow: number;\n\tcolumn: string;\n\tvalue: unknown;\n}\n\n/**\n * Assert specific cell value in result\n * Value format: { row: number, column: string, value: unknown }\n */\nexport function assertDbValueEquals(\n\tresult: AssertionQueryResult,\n\tspec: unknown,\n): AssertionOutcome {\n\tconst { row, column, value } =\n\t\ttypeof spec === 'object' && spec !== null\n\t\t\t? (spec as CellValueSpec)\n\t\t\t: { row: 0, column: '', value: spec };\n\n\tconst rows = result.rows ?? [];\n\tif (row >= rows.length) {\n\t\treturn {\n\t\t\ttype: 'db.value.equals',\n\t\t\texpected: value,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: `No row at index ${row} (only ${rows.length} rows)`,\n\t\t};\n\t}\n\n\tconst rowData = rows[row] as Record<string, unknown> | undefined;\n\tif (!rowData) {\n\t\treturn {\n\t\t\ttype: 'db.value.equals',\n\t\t\texpected: value,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: `Row ${row} is empty`,\n\t\t};\n\t}\n\n\t// Try both exact column name and snake_case\n\tconst actual = rowData[column] ?? rowData[toSnakeCase(column)];\n\tconst passed = JSON.stringify(actual) === JSON.stringify(value);\n\n\treturn {\n\t\ttype: 'db.value.equals',\n\t\texpected: value,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Value at [${row}][\"${column}\"]: expected ${JSON.stringify(value)}, got ${JSON.stringify(actual)}`,\n\t};\n}\n\n/**\n * Assert db.output table: compare parsed markdown table against actual DB rows.\n * - Row count must match exactly\n * - Only listed columns are checked (extra actual columns ignored)\n * - Values compared as trimmed strings\n * - \"NULL\" (case-sensitive) matches null/undefined actual values\n */\nexport function assertDbOutput(\n\tresult: AssertionQueryResult,\n\ttableData: TableAssertionData,\n): AssertionOutcome {\n\tconst { columns, rows: expectedRows } = tableData;\n\tconst actualRows = (result.rows ?? []) as Record<string, unknown>[];\n\n\t// Normalize a value for string comparison (Date → ISO, etc.)\n\tconst normalize = (val: unknown): string => {\n\t\tif (val === null || val === undefined) return 'NULL';\n\t\tif (val instanceof Date) return val.toISOString();\n\t\tif (typeof val === 'object') return JSON.stringify(val);\n\t\treturn String(val);\n\t};\n\n\t// Helper: format actual rows as markdown table for error messages\n\tconst formatActualTable = (): string => {\n\t\tif (actualRows.length === 0) return '(no rows)';\n\t\tconst actualCols =\n\t\t\tcolumns.length > 0\n\t\t\t\t? columns\n\t\t\t\t: Object.keys(actualRows[0] as Record<string, unknown>);\n\t\tconst header = `| ${actualCols.join(' | ')} |`;\n\t\tconst separator = `| ${actualCols.map(() => '---').join(' | ')} |`;\n\t\tconst rows = actualRows.map((row) => {\n\t\t\tconst cells = actualCols.map((col) => normalize(row[col]));\n\t\t\treturn `| ${cells.join(' | ')} |`;\n\t\t});\n\t\treturn [header, separator, ...rows].join('\\n');\n\t};\n\n\t// Row count check\n\tif (actualRows.length !== expectedRows.length) {\n\t\treturn {\n\t\t\ttype: 'db.output',\n\t\t\texpected: `${expectedRows.length} rows`,\n\t\t\tactual: `${actualRows.length} rows`,\n\t\t\tpassed: false,\n\t\t\tmessage: `Expected ${expectedRows.length} rows, got ${actualRows.length}\\nActual data:\\n${formatActualTable()}`,\n\t\t};\n\t}\n\n\t// Check expected columns exist in actual result (if any rows)\n\tif (actualRows.length > 0) {\n\t\tconst firstRow = actualRows[0] as Record<string, unknown>;\n\t\tfor (const col of columns) {\n\t\t\tif (!(col in firstRow)) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'db.output',\n\t\t\t\t\texpected: `column \"${col}\" in results`,\n\t\t\t\t\tactual: `columns: ${Object.keys(firstRow).join(', ')}`,\n\t\t\t\t\tpassed: false,\n\t\t\t\t\tmessage: `Expected column \"${col}\" not found in results. Available: ${Object.keys(firstRow).join(', ')}\\nActual data:\\n${formatActualTable()}`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t// Row-by-row, column-by-column comparison\n\tfor (let r = 0; r < expectedRows.length; r++) {\n\t\tconst expectedRow = expectedRows[r];\n\t\tconst actualRow = actualRows[r];\n\t\tif (!expectedRow || !actualRow) continue;\n\n\t\tfor (let c = 0; c < columns.length; c++) {\n\t\t\tconst col = columns[c];\n\t\t\tif (!col) continue;\n\t\t\tconst expectedVal = expectedRow[c] ?? '';\n\t\t\tconst actualVal = actualRow[col];\n\t\t\tconst normalizedActual = normalize(actualVal);\n\n\t\t\t// NULL handling: \"NULL\" (case-sensitive) matches null/undefined\n\t\t\tconst expectedIsNull = expectedVal === 'NULL';\n\t\t\tconst actualIsNull = actualVal === null || actualVal === undefined;\n\n\t\t\tif (expectedIsNull && actualIsNull) continue;\n\t\t\tif (expectedIsNull !== actualIsNull) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'db.output',\n\t\t\t\t\texpected: expectedVal,\n\t\t\t\t\tactual: normalizedActual,\n\t\t\t\t\tpassed: false,\n\t\t\t\t\tmessage: `Row ${r + 1}, column \"${col}\": expected ${expectedVal}, got ${normalizedActual}\\nActual data:\\n${formatActualTable()}`,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// String comparison (trimmed, with Date→ISO normalization)\n\t\t\tif (normalizedActual.trim() !== expectedVal.trim()) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'db.output',\n\t\t\t\t\texpected: expectedVal,\n\t\t\t\t\tactual: normalizedActual,\n\t\t\t\t\tpassed: false,\n\t\t\t\t\tmessage: `Row ${r + 1}, column \"${col}\": expected \"${expectedVal}\", got \"${normalizedActual}\"\\nActual data:\\n${formatActualTable()}`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\ttype: 'db.output',\n\t\texpected: `${expectedRows.length} rows matching`,\n\t\tactual: `${expectedRows.length} rows matching`,\n\t\tpassed: true,\n\t\tmessage: undefined,\n\t};\n}\n\n// ============================================================\n// INTENT AST ASSERTIONS (semantic verification)\n// ============================================================\n\n/**\n * Assert intent type (query, insert, update, delete, upsert)\n */\nexport function assertIntentType(\n\tresult: AssertionQueryResult,\n\texpected: string,\n): AssertionOutcome {\n\tconst actual = result.intent?.type;\n\n\tif (!result.intent) {\n\t\treturn {\n\t\t\ttype: 'intent.type',\n\t\t\texpected,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: 'No intent available (command or parse error)',\n\t\t};\n\t}\n\n\tconst passed = actual === expected;\n\n\treturn {\n\t\ttype: 'intent.type',\n\t\texpected,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Expected intent type \"${expected}\", got \"${actual}\"`,\n\t};\n}\n\n/**\n * Assert main table name (logical name)\n */\nexport function assertIntentTable(\n\tresult: AssertionQueryResult,\n\texpected: string,\n): AssertionOutcome {\n\tconst actual = result.intent?.table;\n\n\tif (!result.intent) {\n\t\treturn {\n\t\t\ttype: 'intent.table',\n\t\t\texpected,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: 'No intent available (command or parse error)',\n\t\t};\n\t}\n\n\t// Compare case-insensitively for flexibility\n\tconst passed = actual?.toLowerCase() === expected.toLowerCase();\n\n\treturn {\n\t\ttype: 'intent.table',\n\t\texpected,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Expected table \"${expected}\", got \"${actual}\"`,\n\t};\n}\n\n/**\n * Assert relations joined via `with` keyword\n * Value can be a single string or array of strings\n */\nexport function assertIntentWith(\n\tresult: AssertionQueryResult,\n\texpected: string | string[],\n): AssertionOutcome {\n\tconst actual = result.intent?.with ?? [];\n\tconst expectedArray = Array.isArray(expected) ? expected : [expected];\n\n\tif (!result.intent) {\n\t\treturn {\n\t\t\ttype: 'intent.with',\n\t\t\texpected: expectedArray,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: 'No intent available (command or parse error)',\n\t\t};\n\t}\n\n\t// Check if all expected relations are present (case-insensitive)\n\tconst actualLower = actual.map((r: string) => r.toLowerCase());\n\tconst missing = expectedArray.filter(\n\t\t(e) => !actualLower.includes(e.toLowerCase()),\n\t);\n\n\tconst passed = missing.length === 0;\n\n\treturn {\n\t\ttype: 'intent.with',\n\t\texpected: expectedArray,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Missing relations: ${missing.join(', ')}. Found: ${actual.join(', ')}`,\n\t};\n}\n\n/**\n * Factory for intent boolean flag assertions (hasWhere, hasGroupBy, hasOrderBy).\n */\nfunction createIntentBooleanAssertion(\n\tassertionType: AssertionType,\n\tfield: keyof IntentSummary,\n) {\n\treturn (\n\t\tresult: AssertionQueryResult,\n\t\texpected: boolean,\n\t): AssertionOutcome => {\n\t\tif (!result.intent) {\n\t\t\treturn {\n\t\t\t\ttype: assertionType,\n\t\t\t\texpected,\n\t\t\t\tactual: undefined,\n\t\t\t\tpassed: false,\n\t\t\t\tmessage: 'No intent available (command or parse error)',\n\t\t\t};\n\t\t}\n\n\t\tconst actual = (result.intent[field] as boolean) ?? false;\n\t\tconst passed = actual === expected;\n\n\t\treturn {\n\t\t\ttype: assertionType,\n\t\t\texpected,\n\t\t\tactual: passed ? undefined : actual,\n\t\t\tpassed,\n\t\t\tmessage: passed\n\t\t\t\t? undefined\n\t\t\t\t: `Expected ${String(field)}=${expected}, got ${actual}`,\n\t\t};\n\t};\n}\n\nexport const assertIntentHasWhere = createIntentBooleanAssertion(\n\t'intent.hasWhere',\n\t'hasWhere',\n);\nexport const assertIntentHasGroupBy = createIntentBooleanAssertion(\n\t'intent.hasGroupBy',\n\t'hasGroupBy',\n);\nexport const assertIntentHasOrderBy = createIntentBooleanAssertion(\n\t'intent.hasOrderBy',\n\t'hasOrderBy',\n);\n","/**\n * Assertion Parser for .assert.dbsp files.\n *\n * Parses YAML-like assertion files that validate query output.\n * Each assertion block starts with \"---\" followed by query reference.\n *\n * Pure string parser — zero external dependencies.\n */\n\n// Valid assertion types\nexport const ASSERTION_TYPES = [\n\t// Existing (keep for backward compat)\n\t'output.contains',\n\t'output.equals',\n\t'output.matches',\n\t'sql.equals',\n\t'sql.matches',\n\t'params.equals',\n\t'params.length',\n\t'plan.contains',\n\t'success',\n\t'error.contains',\n\n\t// NEW: Typed SQL assertions\n\t'sql.table', // Table name (logical or physical)\n\t'sql.column', // Column name in SQL\n\t'sql.join', // JOIN clause present\n\n\t// NEW: Typed params assertions\n\t'params.type', // Type validation per param\n\t'params.value', // Specific param value by index\n\n\t// NEW: DB-only assertions (skipped in dry-run)\n\t'db.success', // Success check (skipped in dry-run)\n\t'db.output.contains', // Output contains (skipped in dry-run)\n\t'db.rows.equals', // Exact row count\n\t'db.rows.min', // At least N rows\n\t'db.rows.max', // At most N rows\n\t'db.output', // Table block assertion (multiline row comparison)\n\t'db.column.exists', // Column in result\n\t'db.value.equals', // Specific cell value\n\n\t// NEW: Intent AST assertions (semantic verification)\n\t'intent.type', // Intent type (query/insert/update/delete/upsert)\n\t'intent.table', // Main table name (logical)\n\t'intent.with', // Relations joined via `with` keyword (was 'include')\n\t'intent.hasWhere', // Has WHERE clause (true/false)\n\t'intent.hasGroupBy', // Has GROUP BY (true/false)\n\t'intent.hasOrderBy', // Has ORDER BY (true/false)\n] as const;\n\nexport type AssertionType = (typeof ASSERTION_TYPES)[number];\n\n/**\n * Check if an assertion type requires database connection\n * All db.* assertions need actual query execution\n */\nexport function requiresDatabase(type: AssertionType): boolean {\n\treturn type.startsWith('db.');\n}\n\n/**\n * Parsed table data for db.output table assertions.\n * columns: header names; rows: cell values as trimmed strings.\n */\nexport interface TableAssertionData {\n\tcolumns: string[];\n\trows: string[][];\n}\n\n/**\n * A single assertion within a block\n */\nexport interface Assertion {\n\ttype: AssertionType;\n\tvalue: string | number | boolean | unknown[] | TableAssertionData;\n\tline: number;\n}\n\n/**\n * A block of assertions for a single query\n */\nexport interface AssertionBlock {\n\t/** Query index (0-based) if using \"query: N\" */\n\tqueryIndex?: number;\n\t/** Query text pattern if using \"match: text\" */\n\tqueryMatch?: string;\n\t/** Line number where the block starts */\n\tstartLine: number;\n\t/** All assertions in this block */\n\tassertions: Assertion[];\n}\n\n/**\n * Result of parsing an assertion file\n */\nexport interface ParseResult {\n\tblocks: AssertionBlock[];\n\terrors: ParseError[];\n}\n\n/**\n * A parsing error with location information\n */\nexport interface ParseError {\n\tline: number;\n\tmessage: string;\n}\n\n/**\n * Parse an assertion file content into structured blocks\n *\n * @param content - The raw content of the .assert.dbsp file\n * @returns ParseResult with blocks and any parsing errors\n */\nexport function parseAssertionFile(content: string): ParseResult {\n\tconst lines = content.split('\\n');\n\tconst blocks: AssertionBlock[] = [];\n\tconst errors: ParseError[] = [];\n\n\tlet currentBlock: AssertionBlock | null = null;\n\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst lineNum = i + 1; // 1-based line numbers for user display\n\t\tconst line = lines[i];\n\t\tif (line === undefined) continue;\n\t\tconst trimmed = line.trim();\n\n\t\t// Skip empty lines and comments\n\t\tif (!trimmed || trimmed.startsWith('#')) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check for block start: --- query: N or --- match: text\n\t\tif (trimmed.startsWith('---')) {\n\t\t\t// Save previous block if exists\n\t\t\tif (currentBlock) {\n\t\t\t\tblocks.push(currentBlock);\n\t\t\t}\n\n\t\t\tconst blockHeader = trimmed.slice(3).trim();\n\t\t\tconst parsed = parseBlockHeader(blockHeader, lineNum);\n\n\t\t\tif (parsed.error || !parsed.block) {\n\t\t\t\terrors.push({\n\t\t\t\t\tline: lineNum,\n\t\t\t\t\tmessage: parsed.error ?? 'Invalid block header',\n\t\t\t\t});\n\t\t\t\tcurrentBlock = null;\n\t\t\t} else {\n\t\t\t\tcurrentBlock = {\n\t\t\t\t\t...parsed.block,\n\t\t\t\t\tstartLine: lineNum,\n\t\t\t\t\tassertions: [],\n\t\t\t\t};\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Parse assertion line within a block\n\t\tif (currentBlock) {\n\t\t\tconst assertion = parseAssertionLine(trimmed, lineNum);\n\t\t\tif (assertion.error) {\n\t\t\t\terrors.push({ line: lineNum, message: assertion.error });\n\t\t\t} else if (assertion.assertion) {\n\t\t\t\t// db.output table block: collect pipe-delimited rows from subsequent lines\n\t\t\t\tif (\n\t\t\t\t\tassertion.assertion.type === 'db.output' &&\n\t\t\t\t\tassertion.assertion.value === ''\n\t\t\t\t) {\n\t\t\t\t\tconst tableResult = parseTableBlock(lines, i + 1);\n\t\t\t\t\tif (tableResult.error) {\n\t\t\t\t\t\terrors.push({ line: lineNum, message: tableResult.error });\n\t\t\t\t\t} else if (tableResult.data) {\n\t\t\t\t\t\tassertion.assertion.value = tableResult.data;\n\t\t\t\t\t\tcurrentBlock.assertions.push(assertion.assertion);\n\t\t\t\t\t}\n\t\t\t\t\ti += tableResult.linesConsumed; // skip past consumed table lines\n\t\t\t\t} else {\n\t\t\t\t\tcurrentBlock.assertions.push(assertion.assertion);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Assertion outside of any block\n\t\t\terrors.push({\n\t\t\t\tline: lineNum,\n\t\t\t\tmessage:\n\t\t\t\t\t'Assertion found outside of any block. Start a block with \"--- query: N\" or \"--- match: text\"',\n\t\t\t});\n\t\t}\n\t}\n\n\t// Don't forget the last block\n\tif (currentBlock) {\n\t\tblocks.push(currentBlock);\n\t}\n\n\treturn { blocks, errors };\n}\n\n/**\n * Parse a block header (after the \"---\")\n */\nfunction parseBlockHeader(\n\theader: string,\n\t_line: number,\n): { block?: Partial<AssertionBlock>; error?: string } {\n\t// Handle \"query: N\"\n\tconst queryMatch = header.match(/^query:\\s*(\\d+)$/);\n\tconst queryIndexStr = queryMatch?.[1];\n\tif (queryIndexStr !== undefined) {\n\t\tconst index = parseInt(queryIndexStr, 10);\n\t\treturn { block: { queryIndex: index } };\n\t}\n\n\t// Handle \"match: text\"\n\tconst matchMatch = header.match(/^match:\\s*(.+)$/);\n\tconst matchText = matchMatch?.[1];\n\tif (matchText !== undefined) {\n\t\tconst text = matchText.trim();\n\t\tif (!text) {\n\t\t\treturn { error: 'Empty match pattern' };\n\t\t}\n\t\treturn { block: { queryMatch: text } };\n\t}\n\n\t// Invalid header format\n\treturn {\n\t\terror: `Invalid block header: \"${header}\". Expected \"query: N\" or \"match: text\"`,\n\t};\n}\n\n/**\n * Parse a single assertion line\n */\nfunction parseAssertionLine(\n\tline: string,\n\tlineNum: number,\n): { assertion?: Assertion; error?: string } {\n\t// Find the colon separator\n\tconst colonIndex = line.indexOf(':');\n\tif (colonIndex === -1) {\n\t\treturn {\n\t\t\terror: `Invalid assertion syntax: \"${line}\". Expected \"type: value\"`,\n\t\t};\n\t}\n\n\tconst typeStr = line.slice(0, colonIndex).trim();\n\tconst valueStr = line.slice(colonIndex + 1).trim();\n\n\t// Validate assertion type\n\tif (!isValidAssertionType(typeStr)) {\n\t\treturn {\n\t\t\terror: `Unknown assertion type: \"${typeStr}\". Valid types: ${ASSERTION_TYPES.join(', ')}`,\n\t\t};\n\t}\n\n\tconst type = typeStr as AssertionType;\n\n\t// Parse value based on type\n\tconst parsedValue = parseAssertionValue(type, valueStr);\n\tif (parsedValue.error || parsedValue.value === undefined) {\n\t\treturn { error: parsedValue.error ?? 'Failed to parse assertion value' };\n\t}\n\n\treturn {\n\t\tassertion: {\n\t\t\ttype,\n\t\t\tvalue: parsedValue.value,\n\t\t\tline: lineNum,\n\t\t},\n\t};\n}\n\n/**\n * Check if a string is a valid assertion type\n */\nfunction isValidAssertionType(type: string): type is AssertionType {\n\treturn ASSERTION_TYPES.includes(type as AssertionType);\n}\n\n/**\n * Parse the value part of an assertion based on its type\n */\nfunction parseAssertionValue(\n\ttype: AssertionType,\n\tvalueStr: string,\n): { value?: string | number | boolean | unknown[]; error?: string } {\n\tswitch (type) {\n\t\t// Boolean value\n\t\tcase 'success':\n\t\tcase 'db.success':\n\t\tcase 'intent.hasWhere':\n\t\tcase 'intent.hasGroupBy':\n\t\tcase 'intent.hasOrderBy':\n\t\t\tif (valueStr === 'true') return { value: true };\n\t\t\tif (valueStr === 'false') return { value: false };\n\t\t\treturn {\n\t\t\t\terror: `Invalid boolean value for \"${type}\": \"${valueStr}\". Expected \"true\" or \"false\"`,\n\t\t\t};\n\n\t\t// Numeric value\n\t\tcase 'params.length':\n\t\tcase 'db.rows.equals':\n\t\tcase 'db.rows.min':\n\t\tcase 'db.rows.max': {\n\t\t\tconst num = parseInt(valueStr, 10);\n\t\t\tif (Number.isNaN(num) || num < 0) {\n\t\t\t\treturn {\n\t\t\t\t\terror: `Invalid number for \"${type}\": \"${valueStr}\". Expected non-negative integer`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { value: num };\n\t\t}\n\n\t\t// JSON array value\n\t\tcase 'params.equals':\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(valueStr);\n\t\t\t\tif (!Array.isArray(parsed)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\terror: `Invalid params.equals value: expected JSON array, got ${typeof parsed}`,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn { value: parsed };\n\t\t\t} catch (_e) {\n\t\t\t\treturn { error: `Invalid JSON for \"params.equals\": ${valueStr}` };\n\t\t\t}\n\n\t\t// JSON array value for params.type\n\t\tcase 'params.type':\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(valueStr);\n\t\t\t\tif (!Array.isArray(parsed)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\terror: `Invalid params.type value: expected JSON array, got ${typeof parsed}`,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn { value: parsed };\n\t\t\t} catch (_e) {\n\t\t\t\treturn { error: `Invalid JSON for \"params.type\": ${valueStr}` };\n\t\t\t}\n\n\t\t// JSON value for params.value (format: \"index:value\")\n\t\tcase 'params.value':\n\t\t\t// Format: index:value or just value (for simple cases)\n\t\t\treturn { value: valueStr };\n\n\t\t// JSON/any value for db.value.equals\n\t\tcase 'db.value.equals':\n\t\t\t// Try to parse as JSON, otherwise treat as string\n\t\t\ttry {\n\t\t\t\treturn { value: JSON.parse(valueStr) };\n\t\t\t} catch {\n\t\t\t\treturn { value: valueStr };\n\t\t\t}\n\n\t\t// Table block assertion: db.output has no inline value (table follows on next lines)\n\t\tcase 'db.output':\n\t\t\treturn { value: '' }; // Marker — table data parsed separately by parseAssertionFile\n\n\t\t// String values (all others)\n\t\tcase 'output.contains':\n\t\tcase 'output.equals':\n\t\tcase 'output.matches':\n\t\tcase 'sql.equals':\n\t\tcase 'sql.matches':\n\t\tcase 'sql.table':\n\t\tcase 'sql.column':\n\t\tcase 'sql.join':\n\t\tcase 'plan.contains':\n\t\tcase 'error.contains':\n\t\tcase 'db.column.exists':\n\t\tcase 'db.output.contains':\n\t\tcase 'intent.type':\n\t\tcase 'intent.table':\n\t\tcase 'intent.with':\n\t\t\t// For regex types, validate the pattern\n\t\t\tif (type.endsWith('.matches')) {\n\t\t\t\ttry {\n\t\t\t\t\tnew RegExp(valueStr);\n\t\t\t\t} catch (_e) {\n\t\t\t\t\treturn { error: `Invalid regex pattern: \"${valueStr}\"` };\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { value: valueStr };\n\n\t\tdefault:\n\t\t\treturn { error: `Unhandled assertion type: ${type}` };\n\t}\n}\n\n// ============================================================================\n// Table block parsing helpers (for db.output)\n// ============================================================================\n\n/**\n * Check if a pipe-delimited line is a separator row (e.g. |---|---|)\n */\nfunction isSeparatorRow(line: string): boolean {\n\treturn /^\\|[\\s\\-:|]+\\|$/.test(line.trim());\n}\n\n/**\n * Parse a pipe-delimited row into an array of trimmed cell values.\n * Handles escaped pipes (\\|) within cell values.\n */\nfunction parseTableCells(line: string): string[] {\n\tlet inner = line.trim();\n\t// Strip leading/trailing pipes\n\tif (inner.startsWith('|')) inner = inner.slice(1);\n\tif (inner.endsWith('|')) inner = inner.slice(0, -1);\n\n\tconst cells: string[] = [];\n\tlet current = '';\n\tfor (let i = 0; i < inner.length; i++) {\n\t\tif (inner[i] === '\\\\' && i + 1 < inner.length && inner[i + 1] === '|') {\n\t\t\tcurrent += '|';\n\t\t\ti++; // skip escaped pipe\n\t\t} else if (inner[i] === '|') {\n\t\t\tcells.push(current.trim());\n\t\t\tcurrent = '';\n\t\t} else {\n\t\t\tcurrent += inner[i];\n\t\t}\n\t}\n\tcells.push(current.trim());\n\treturn cells;\n}\n\n/**\n * Parse a table block starting at `startIndex` in the lines array.\n * Collects pipe-delimited rows, skips blanks and separator rows.\n * Returns parsed TableAssertionData and number of lines consumed.\n */\nfunction parseTableBlock(\n\tlines: string[],\n\tstartIndex: number,\n): { data?: TableAssertionData; linesConsumed: number; error?: string } {\n\tconst tableLines: string[] = [];\n\tlet consumed = 0;\n\n\tfor (let j = startIndex; j < lines.length; j++) {\n\t\tconst raw = lines[j];\n\t\tif (raw === undefined) break;\n\t\tconst trimmed = raw.trim();\n\n\t\t// Blank lines within table are ignored (not terminators)\n\t\tif (!trimmed) {\n\t\t\tconsumed++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Pipe-delimited line → part of the table\n\t\tif (trimmed.startsWith('|')) {\n\t\t\ttableLines.push(trimmed);\n\t\t\tconsumed++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Any other line (including --- block headers) → end of table\n\t\tbreak;\n\t}\n\n\tif (tableLines.length === 0) {\n\t\treturn {\n\t\t\tlinesConsumed: consumed,\n\t\t\terror: 'db.output: expected table rows starting with |',\n\t\t};\n\t}\n\n\t// Filter out separator rows\n\tconst dataLines = tableLines.filter((l) => !isSeparatorRow(l));\n\tif (dataLines.length === 0) {\n\t\treturn {\n\t\t\tlinesConsumed: consumed,\n\t\t\terror: 'db.output: table has only separator rows, no header or data',\n\t\t};\n\t}\n\n\tconst headerLine = dataLines[0] as string;\n\tconst columns = parseTableCells(headerLine);\n\tconst rows = dataLines.slice(1).map((l) => parseTableCells(l));\n\n\treturn { data: { columns, rows }, linesConsumed: consumed };\n}\n\n/**\n * Validate that all query references in assertion blocks are valid\n *\n * @param blocks - Parsed assertion blocks\n * @param queryCount - Number of queries in the query file\n * @param queries - The actual query strings (for match validation)\n * @returns Array of validation errors\n */\nexport function validateAssertionBlocks(\n\tblocks: AssertionBlock[],\n\tqueryCount: number,\n\tqueries: string[],\n): ParseError[] {\n\tconst errors: ParseError[] = [];\n\n\tfor (const block of blocks) {\n\t\t// Validate query index\n\t\tif (block.queryIndex !== undefined) {\n\t\t\tif (block.queryIndex < 0 || block.queryIndex >= queryCount) {\n\t\t\t\terrors.push({\n\t\t\t\t\tline: block.startLine,\n\t\t\t\t\tmessage: `Query index ${block.queryIndex} out of bounds (0-${queryCount - 1})`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Validate query match and check for ambiguity\n\t\tif (block.queryMatch !== undefined) {\n\t\t\tconst matchingIndices = queries\n\t\t\t\t.map((q, i) => (q.trim() === block.queryMatch?.trim() ? i : -1))\n\t\t\t\t.filter((i) => i !== -1);\n\n\t\t\tif (matchingIndices.length === 0) {\n\t\t\t\terrors.push({\n\t\t\t\t\tline: block.startLine,\n\t\t\t\t\tmessage: `No query matches \"${block.queryMatch}\"`,\n\t\t\t\t});\n\t\t\t} else if (matchingIndices.length > 1) {\n\t\t\t\t// ERR-06: Ambiguous match\n\t\t\t\terrors.push({\n\t\t\t\t\tline: block.startLine,\n\t\t\t\t\tmessage: `Ambiguous match: '${block.queryMatch}' matches queries ${matchingIndices.join(', ')}. Use query index instead.`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Warn if block has no assertions\n\t\tif (block.assertions.length === 0) {\n\t\t\terrors.push({\n\t\t\t\tline: block.startLine,\n\t\t\t\tmessage: 'Block has no assertions',\n\t\t\t});\n\t\t}\n\t}\n\n\treturn errors;\n}\n\n/**\n * Resolve which query index a block refers to\n *\n * @param block - The assertion block\n * @param queries - The query strings\n * @returns The resolved query index, or -1 if not found\n */\nexport function resolveQueryIndex(\n\tblock: AssertionBlock,\n\tqueries: string[],\n): number {\n\tif (block.queryIndex !== undefined) {\n\t\treturn block.queryIndex;\n\t}\n\n\tif (block.queryMatch !== undefined) {\n\t\tconst index = queries.findIndex(\n\t\t\t(q) => q.trim() === block.queryMatch?.trim(),\n\t\t);\n\t\treturn index;\n\t}\n\n\treturn -1;\n}\n","/**\n * Assertion Runner for .assert.dbsp files.\n *\n * Runs assertions against query results and collects pass/fail outcomes.\n * Shared by CLI and GUI sidecar.\n */\n\nimport {\n\tassertContains,\n\tassertDbColumnExists,\n\tassertDbOutput,\n\tassertDbRowsEquals,\n\tassertDbRowsMax,\n\tassertDbRowsMin,\n\tassertDbValueEquals,\n\tassertEquals,\n\tassertIntentHasGroupBy,\n\tassertIntentHasOrderBy,\n\tassertIntentHasWhere,\n\tassertIntentTable,\n\tassertIntentType,\n\tassertIntentWith,\n\tassertMatches,\n\tassertParamsEquals,\n\tassertParamsLength,\n\tassertParamsType,\n\tassertParamsValue,\n\tassertSQLColumn,\n\tassertSQLEquals,\n\tassertSQLJoin,\n\tassertSQLTable,\n\tassertSuccess,\n} from './assertion-functions.js';\nimport type {\n\tAssertion,\n\tAssertionBlock,\n\tTableAssertionData,\n} from './assertion-parser.js';\nimport { resolveQueryIndex } from './assertion-parser.js';\nimport type {\n\tAssertionOutcome,\n\tAssertionQueryResult,\n\tAssertionSummary,\n\tQueryAssertionResult,\n} from './types.js';\n\n/**\n * Run all assertion blocks against query results\n *\n * @param blocks - Parsed assertion blocks\n * @param results - Query execution results\n * @param queries - Original query strings (for matching)\n * @param hasDb - Whether a database connection is available (for db.* assertions)\n * @returns Summary with detailed results\n */\nexport function runAssertions(\n\tblocks: AssertionBlock[],\n\tresults: AssertionQueryResult[],\n\tqueries: string[],\n\thasDb = false,\n): AssertionSummary {\n\tconst queryResults: QueryAssertionResult[] = [];\n\tlet totalPassed = 0;\n\tlet totalFailed = 0;\n\tlet totalSkipped = 0;\n\n\tfor (const block of blocks) {\n\t\tconst queryIndex = resolveQueryIndex(block, queries);\n\n\t\t// Skip if query index couldn't be resolved (validation should catch this earlier)\n\t\tif (queryIndex === -1 || queryIndex >= results.length) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst result = results[queryIndex];\n\t\tif (!result) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst outcomes: AssertionOutcome[] = [];\n\t\tlet allPassed = true;\n\n\t\tfor (const assertion of block.assertions) {\n\t\t\tconst outcome = runSingleAssertion(assertion, result, hasDb);\n\t\t\toutcomes.push(outcome);\n\n\t\t\tif (outcome.skipped) {\n\t\t\t\ttotalSkipped++;\n\t\t\t} else if (outcome.passed) {\n\t\t\t\ttotalPassed++;\n\t\t\t} else {\n\t\t\t\ttotalFailed++;\n\t\t\t\tallPassed = false;\n\t\t\t}\n\t\t}\n\n\t\tqueryResults.push({\n\t\t\tqueryIndex,\n\t\t\tquery: result.query,\n\t\t\tquerySuccess: result.success,\n\t\t\tassertions: outcomes,\n\t\t\tpassed: allPassed,\n\t\t});\n\t}\n\n\treturn {\n\t\ttotal: totalPassed + totalFailed + totalSkipped,\n\t\tpassed: totalPassed,\n\t\tfailed: totalFailed,\n\t\tskipped: totalSkipped,\n\t\tresults: queryResults,\n\t};\n}\n\n/**\n * Run a single assertion against a query result\n */\nfunction runSingleAssertion(\n\tassertion: Assertion,\n\tresult: AssertionQueryResult,\n\thasDb: boolean,\n): AssertionOutcome {\n\tconst { type, value } = assertion;\n\n\t// Skip db.* assertions when no database connection\n\tif (type.startsWith('db.') && !hasDb) {\n\t\treturn {\n\t\t\ttype,\n\t\t\texpected: value,\n\t\t\tactual: undefined,\n\t\t\tpassed: true, // Consider skipped as not-failed\n\t\t\tmessage: undefined,\n\t\t\tskipped: true,\n\t\t\tskipReason: 'No database connection (dry-run mode)',\n\t\t};\n\t}\n\n\tswitch (type) {\n\t\t// Output assertions\n\t\tcase 'output.contains':\n\t\t\treturn assertContains('output', result.output ?? '', value as string);\n\n\t\tcase 'output.equals':\n\t\t\treturn assertEquals('output', result.output ?? '', value as string);\n\n\t\tcase 'output.matches':\n\t\t\treturn assertMatches('output', result.output ?? '', value as string);\n\n\t\t// SQL assertions\n\t\tcase 'sql.equals':\n\t\t\treturn assertSQLEquals(result.sql ?? '', value as string);\n\n\t\tcase 'sql.matches':\n\t\t\treturn assertMatches('sql', result.sql ?? '', value as string);\n\n\t\tcase 'sql.table':\n\t\t\treturn assertSQLTable(result.sql ?? '', value as string);\n\n\t\tcase 'sql.column':\n\t\t\treturn assertSQLColumn(result.sql ?? '', value as string);\n\n\t\tcase 'sql.join':\n\t\t\treturn assertSQLJoin(result.sql ?? '', value as string);\n\n\t\t// Params assertions\n\t\tcase 'params.equals':\n\t\t\treturn assertParamsEquals(result.params ?? [], value as unknown[]);\n\n\t\tcase 'params.length':\n\t\t\treturn assertParamsLength(result.params ?? [], value as number);\n\n\t\tcase 'params.type':\n\t\t\treturn assertParamsType(result.params ?? [], value as string[]);\n\n\t\tcase 'params.value':\n\t\t\treturn assertParamsValue(result.params ?? [], value as unknown);\n\n\t\t// Plan assertion (plan info is in output)\n\t\tcase 'plan.contains':\n\t\t\treturn assertContains('plan', result.output ?? '', value as string);\n\n\t\t// Success assertion\n\t\tcase 'success':\n\t\t\treturn assertSuccess(result.success, value as boolean);\n\n\t\t// Error assertion\n\t\tcase 'error.contains':\n\t\t\treturn assertContains('error', result.error ?? '', value as string);\n\n\t\t// DB assertions (require database connection)\n\t\tcase 'db.success':\n\t\t\t// Use dbSuccess if available, fall back to success for backwards compatibility\n\t\t\treturn assertSuccess(\n\t\t\t\tresult.dbSuccess ?? result.success,\n\t\t\t\tvalue as boolean,\n\t\t\t);\n\n\t\tcase 'db.output':\n\t\t\treturn assertDbOutput(result, value as TableAssertionData);\n\n\t\tcase 'db.output.contains':\n\t\t\treturn assertContains(\n\t\t\t\t'output',\n\t\t\t\tresult.output ?? '',\n\t\t\t\tvalue as string,\n\t\t\t\t'db.output.contains',\n\t\t\t);\n\n\t\tcase 'db.rows.equals':\n\t\t\treturn assertDbRowsEquals(result, value as number);\n\n\t\tcase 'db.rows.min':\n\t\t\treturn assertDbRowsMin(result, value as number);\n\n\t\tcase 'db.rows.max':\n\t\t\treturn assertDbRowsMax(result, value as number);\n\n\t\tcase 'db.column.exists':\n\t\t\treturn assertDbColumnExists(result, value as string);\n\n\t\tcase 'db.value.equals':\n\t\t\treturn assertDbValueEquals(result, value as unknown);\n\n\t\t// Intent AST assertions\n\t\tcase 'intent.type':\n\t\t\treturn assertIntentType(result, value as string);\n\n\t\tcase 'intent.table':\n\t\t\treturn assertIntentTable(result, value as string);\n\n\t\tcase 'intent.with':\n\t\t\treturn assertIntentWith(result, value as string | string[]);\n\n\t\tcase 'intent.hasWhere':\n\t\t\treturn assertIntentHasWhere(result, value as boolean);\n\n\t\tcase 'intent.hasGroupBy':\n\t\t\treturn assertIntentHasGroupBy(result, value as boolean);\n\n\t\tcase 'intent.hasOrderBy':\n\t\t\treturn assertIntentHasOrderBy(result, value as boolean);\n\n\t\tdefault:\n\t\t\treturn {\n\t\t\t\ttype,\n\t\t\t\texpected: value,\n\t\t\t\tactual: undefined,\n\t\t\t\tpassed: false,\n\t\t\t\tmessage: `Unknown assertion type: ${type}`,\n\t\t\t};\n\t}\n}\n","/**\n * Shared assertion types for .assert.dbsp evaluation.\n *\n * Used by both CLI (assertion-runner) and GUI sidecar (assertion-handler).\n */\n\nimport type { AssertionType } from './assertion-parser.js';\n\n// ── Intent summary (inline — no dependency on CLI's nql-executor) ──\n\n/**\n * Lightweight summary of a compiled query intent.\n * Populated by the NQL executor after compilation.\n */\nexport interface IntentSummary {\n\ttype: 'query' | 'insert' | 'update' | 'delete' | 'upsert' | 'setOperation';\n\ttable: string;\n\twith: string[];\n\thasWhere: boolean;\n\thasGroupBy: boolean;\n\thasOrderBy: boolean;\n\tctes: string[];\n}\n\n// ── Query result (sidecar-friendly version of CLI's BatchResult) ──\n\n/**\n * Portable query result for assertion evaluation.\n * Both CLI (via BatchResult adapter) and sidecar produce this shape.\n */\nexport interface AssertionQueryResult {\n\tquery: string;\n\tsuccess: boolean;\n\tdbSuccess?: boolean;\n\toutput?: string;\n\tsql?: string;\n\tparams?: readonly unknown[];\n\terror?: string;\n\trowCount?: number;\n\tcolumns?: string[];\n\trows?: unknown[];\n\tintent?: IntentSummary;\n}\n\n// ── Assertion outcome ──\n\n/**\n * Result of running a single assertion.\n */\nexport interface AssertionOutcome {\n\ttype: AssertionType;\n\texpected: unknown;\n\tactual: unknown;\n\tpassed: boolean;\n\tmessage: string | undefined;\n\t/** True if assertion was skipped (e.g., db.* without DB connection) */\n\tskipped?: boolean;\n\t/** Reason for skipping */\n\tskipReason?: string;\n}\n\n// ── Aggregated results ──\n\n/**\n * Result of running all assertions for a single query.\n */\nexport interface QueryAssertionResult {\n\tqueryIndex: number;\n\tquery: string;\n\tquerySuccess: boolean;\n\tassertions: AssertionOutcome[];\n\tpassed: boolean;\n}\n\n/**\n * Summary of all assertion results.\n */\nexport interface AssertionSummary {\n\ttotal: number;\n\tpassed: number;\n\tfailed: number;\n\tskipped: number;\n\tresults: QueryAssertionResult[];\n}\n\n/**\n * Determine whether a query result represents end-to-end success\n * (compile + DB execution combined).\n *\n * Truth table:\n * | success | dbSuccess | result |\n * |---------|------------|--------|\n * | false | (any) | false |\n * | true | undefined | true | (compile-only mode — no DB)\n * | true | true | true |\n * | true | false | false |\n *\n * Contract: conforming producers either omit `dbSuccess` (compile-only\n * mode — no DB execution) or set it to a real boolean reflecting DB\n * outcome.\n *\n * Stable predicate — the truth table above IS the contract; callers may\n * rely on its exact behavior. As a `@public` helper, the implementation\n * is also defensive: malformed input (`null`, `undefined`, missing\n * `success`, non-boolean `success`) returns `false` rather than throwing\n * or returning a non-boolean.\n *\n * @public\n */\nexport function isOverallSuccess(r: {\n\tsuccess: boolean;\n\tdbSuccess?: boolean;\n}): boolean {\n\treturn Boolean(r) && r.success === true && r.dbSuccess !== false;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAiDO,SAAS,2BACf,OACA,kBACA,cACA,YACA,WACuB;AAGvB,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,EACpB;AACD;AAMO,SAAS,gBAAgB,UAAoC;AAEnE,MAAI,SAAS,WAAW;AACvB,WAAO,SAAS,UAAU,cAAc,OACrC,iBACA;AAAA,EACJ;AAGA,UAAQ,SAAS,MAAM;AAAA,IACtB,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,EACT;AACD;AAKO,SAAS,oBACf,UAC4D;AAC5D,SAAO,SAAS,cAAc;AAC/B;AAMO,SAAS,kBAAkB,UAA+B;AAChE,SAAO,SAAS,WAAW,SAAS;AACrC;AAMO,SAAS,wBACf,WACA,iBACA,WAAW,IACS;AACpB,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA,SAAS;AAAA,EACV;AACD;;;AC5HA;AAWA;AAAA,4BAAc;;;ACMP,IAAM,cAAN,MAAqC;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGQ;AAAA,EAIA;AAAA,EAKjB,YACC,QACA,WACA,OACA,YACA,WACC;AAED,SAAK,SAAS,OAAO,OAAO,IAAI,IAAI,MAAM,CAAC;AAI3C,SAAK,YAAY,OAAO,OAAO,IAAI,IAAI,SAAS,CAAC;AAIjD,QAAI,OAAO;AACV,WAAK,QAAQ,OAAO,OAAO,IAAI,IAAI,KAAK,CAAC;AAAA,IAC1C;AACA,QAAI,cAAc,WAAW,SAAS,GAAG;AACxC,WAAK,aAAa,OAAO,OAAO,CAAC,GAAG,UAAU,CAAC;AAAA,IAChD;AACA,QAAI,WAAW;AACd,WAAK,YAAY,OAAO,OAAO,IAAI,IAAI,SAAS,CAAC;AAAA,IAIlD;AAGA,SAAK,oBAAoB,KAAK,4BAA4B,SAAS;AACnE,SAAK,oBAAoB,KAAK,4BAA4B,SAAS;AAGnE,SAAK,SAAS;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,MAAmC;AAC3C,WAAO,KAAK,OAAO,IAAI,IAAI;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,eAA+C;AAC1D,WAAO,KAAK,UAAU,IAAI,aAAa;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,aAA4C;AAC5D,WAAO,KAAK,kBAAkB,IAAI,WAAW,KAAK,CAAC;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,aAA4C;AAC1D,WAAO,KAAK,kBAAkB,IAAI,WAAW,KAAK,CAAC;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,aAAqB,aAA2C;AAC3E,UAAM,sBAAsB,KAAK,iBAAiB,WAAW;AAC7D,UAAM,oBAAoB,oBAAoB;AAAA,MAC7C,CAAC,MAAM,EAAE,WAAW;AAAA,IACrB;AAEA,QAAI,kBAAkB,UAAU,GAAG;AAClC,aAAO;AAAA,QACN,WAAW;AAAA,QACX,SAAS,kBAAkB,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,MAC7C;AAAA,IACD;AAEA,WAAO;AAAA,MACN,WAAW;AAAA,MACX,SAAS,kBAAkB,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,IAC7C;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAMQ,4BACP,WAC6C;AAC7C,UAAM,QAAQ,oBAAI,IAA0B;AAE5C,eAAW,YAAY,UAAU,OAAO,GAAG;AAC1C,YAAM,WAAW,MAAM,IAAI,SAAS,MAAM,KAAK,CAAC;AAChD,YAAM,IAAI,SAAS,QAAQ,CAAC,GAAG,UAAU,QAAQ,CAAC;AAAA,IACnD;AAGA,UAAM,cAAc,oBAAI,IAAmC;AAC3D,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO;AACjC,kBAAY,IAAI,KAAK,OAAO,OAAO,KAAK,CAAC;AAAA,IAC1C;AAEA,WAAO,OAAO,OAAO,WAAW;AAAA,EAIjC;AAAA,EAEQ,4BACP,WAC6C;AAC7C,UAAM,QAAQ,oBAAI,IAA0B;AAE5C,eAAW,YAAY,UAAU,OAAO,GAAG;AAC1C,YAAM,WAAW,MAAM,IAAI,SAAS,MAAM,KAAK,CAAC;AAChD,YAAM,IAAI,SAAS,QAAQ,CAAC,GAAG,UAAU,QAAQ,CAAC;AAAA,IACnD;AAGA,UAAM,cAAc,oBAAI,IAAmC;AAC3D,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO;AACjC,kBAAY,IAAI,KAAK,OAAO,OAAO,KAAK,CAAC;AAAA,IAC1C;AAEA,WAAO,OAAO,OAAO,WAAW;AAAA,EAIjC;AAAA,EAEQ,WAAiB;AACxB,UAAM,SAAmB,CAAC;AAG1B,eAAW,SAAS,KAAK,OAAO,OAAO,GAAG;AACzC,UAAI,MAAM,YAAY;AACrB,cAAM,SAAS,MAAM,QAAQ,MAAM,UAAU,IAC1C,MAAM,aACN,CAAC,MAAM,UAAU;AACpB,mBAAW,MAAM,QAAQ;AACxB,cAAI,CAAC,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG;AAC9C,mBAAO;AAAA,cACN,UAAU,MAAM,IAAI,yBAAyB,EAAE;AAAA,YAChD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAGA,eAAW,SAAS,KAAK,OAAO,OAAO,GAAG;AACzC,iBAAW,MAAM,MAAM,aAAa;AACnC,YAAI,CAAC,KAAK,OAAO,IAAI,GAAG,WAAW,KAAK,GAAG;AAC1C,iBAAO;AAAA,YACN,UAAU,MAAM,IAAI,4CAA4C,GAAG,WAAW,KAAK;AAAA,UACpF;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAGA,eAAW,YAAY,KAAK,UAAU,OAAO,GAAG;AAC/C,UAAI,CAAC,KAAK,OAAO,IAAI,SAAS,MAAM,GAAG;AACtC,eAAO;AAAA,UACN,aAAa,SAAS,IAAI,oCAAoC,SAAS,MAAM;AAAA,QAC9E;AAAA,MACD;AACA,UAAI,CAAC,KAAK,OAAO,IAAI,SAAS,MAAM,GAAG;AACtC,eAAO;AAAA,UACN,aAAa,SAAS,IAAI,oCAAoC,SAAS,MAAM;AAAA,QAC9E;AAAA,MACD;AACA,UAAI,SAAS,WAAW,CAAC,KAAK,OAAO,IAAI,SAAS,OAAO,GAAG;AAC3D,eAAO;AAAA,UACN,aAAa,SAAS,IAAI,qCAAqC,SAAS,OAAO;AAAA,QAChF;AAAA,MACD;AAAA,IACD;AAIA,SAAK,wBAAwB;AAE7B,QAAI,OAAO,SAAS,GAAG;AACtB,YAAM,IAAI;AAAA,QACT;AAAA,EAA+B,OAAO,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,MACxE;AAAA,IACD;AAAA,EACD;AAAA,EAEQ,0BAAoC;AAC3C,UAAM,WAAqB,CAAC;AAC5B,UAAM,UAAU,oBAAI,IAAY;AAChC,UAAM,iBAAiB,oBAAI,IAAY;AAEvC,UAAM,MAAM,CAAC,OAAe,SAAyB;AACpD,UAAI,eAAe,IAAI,KAAK,GAAG;AAC9B,cAAM,aAAa,KAAK,QAAQ,KAAK;AACrC,cAAM,QAAQ,CAAC,GAAG,KAAK,MAAM,UAAU,GAAG,KAAK,EAAE,KAAK,MAAM;AAC5D,iBAAS,KAAK,KAAK;AACnB;AAAA,MACD;AAEA,UAAI,QAAQ,IAAI,KAAK,GAAG;AACvB;AAAA,MACD;AAEA,cAAQ,IAAI,KAAK;AACjB,qBAAe,IAAI,KAAK;AAExB,YAAM,YAAY,KAAK,iBAAiB,KAAK;AAC7C,iBAAW,YAAY,WAAW;AACjC,YAAI,SAAS,QAAQ,CAAC,GAAG,MAAM,KAAK,CAAC;AAAA,MACtC;AAEA,qBAAe,OAAO,KAAK;AAAA,IAC5B;AAEA,eAAW,aAAa,KAAK,OAAO,KAAK,GAAG;AAC3C,UAAI,WAAW,CAAC,CAAC;AAAA,IAClB;AAEA,WAAO;AAAA,EACR;AACD;;;AC3OO,IAAM,gBAAwB;AAAA,EACpC,MAAM,CAAC,YAAoB,QAAQ,KAAK,OAAO;AAChD;AAMO,IAAM,eAAuB;AAAA,EACnC,MAAM,MAAM;AAAA,EAAC;AACd;AAMA,IAAI,eAAuB;AAoBpB,SAAS,UAAU,QAAsB;AAC/C,iBAAe;AAChB;AAMO,SAAS,YAAoB;AACnC,SAAO;AACR;AAKO,SAAS,cAAoB;AACnC,iBAAe;AAChB;;;AC9CO,IAAM,aAA4B,uBAAO,IAAI,YAAY;AAezD,IAAM,cAA6B,uBAAO,IAAI,aAAa;AAgB3D,IAAM,gBAA+B,uBAAO,IAAI,eAAe;AAkB/D,IAAM,QAAuB,uBAAO,IAAI,YAAY;AAoBpD,IAAM,gBAA+B,uBAAO,IAAI,mBAAmB;;;ACgSnE,SAAS,WACf,OAIC;AACD,SACC,OAAO,UAAU,YACjB,UAAU,QACV,SAAS,SACR,MAAkC,KAAK,MAAM;AAEhD;AAeO,SAAS,YACf,OAC8C;AAC9C,SACC,OAAO,UAAU,YACjB,UAAU,QACV,SAAS,SACR,MAAkC,KAAK,MAAM;AAEhD;AAeO,SAAS,cACf,OACsD;AACtD,SACC,OAAO,UAAU,YACjB,UAAU,QACV,SAAS,SACR,MAAkC,KAAK,MAAM;AAEhD;AAeO,SAAS,aACf,OACuD;AACvD,SACC,OAAO,UAAU,YACjB,UAAU,QACV,SAAS,SACR,MAAkC,KAAK,MAAM;AAEhD;AAQO,SAAS,gBACf,OAC0D;AAC1D,SAAO,YAAY,KAAK,KAAK,YAAY;AAC1C;;;AC1cA,IAAM,oBAAoB,oBAAI,IAAI;AAAA;AAAA,EAEjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAC;AAMD,SAAS,iBAAiB,WAAmB,YAA0B;AACtE,YAAU,EAAE;AAAA,IACX,2BAA2B,UAAU,eAAe,SAAS,2EAClB,UAAU;AAAA,EACtD;AACD;AAcO,SAAS,gBACf,WACA,YACA,cACS;AACT,QAAM,YAA8C;AAAA,IACnD,CAAC,UAAU,GAAG;AAAA,IACd,CAAC,WAAW,GAAG;AAAA,IACf,CAAC,KAAK,GAAG;AAAA,IACT,OAAO;AAAA;AAAA,IACP,GAAG,OAAe;AAEjB,UAAI,CAAC,2BAA2B,KAAK,KAAK,GAAG;AAC5C,cAAM,IAAI;AAAA,UACT,kBAAkB,KAAK;AAAA,QACxB;AAAA,MACD;AACA,aAAO;AAAA,QACN,GAAG;AAAA,QACH,QAAQ;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAGA,MAAI,gBAAgB,aAAa,SAAS,GAAG;AAC5C,cAAU,aAAa,IAAI;AAAA,EAC5B;AAEA,SAAO;AACR;AAQO,SAAS,iBAAiB,WAA2B;AAC3D,SAAO;AAAA,IACN,CAAC,UAAU,GAAG;AAAA,IACd,CAAC,KAAK,GAAG;AAAA,IACT,UAAU,CAAC;AAAA;AAAA,EACZ;AACD;AAKA,SAAS,gBAAgB,mBAAyC;AACjE,UAAQ,mBAAmB;AAAA,IAC1B,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR;AACC,aAAO;AAAA,EACT;AACD;AAKA,SAAS,UACR,SACA,YACU;AACV,SAAO,QAAQ,KAAK,CAACA,SAAQA,KAAI,SAAS,UAAU;AACrD;AAKA,SAAS,eAAe,SAAgD;AACvE,SAAO,QAAQ,IAAI,CAACA,SAAQA,KAAI,IAAI;AACrC;AAYO,SAAS,kBACf,aACA,cACA,OACA,cACA,YACS;AAET,QAAM,cACL,iBAAiB,SACd,CAAC,GAAI,cAAc,CAAC,GAAI,YAAY,IACnC,cAAc,CAAC;AAEpB,QAAM,OAAO;AAAA,IACZ,CAAC,aAAa,GAAG,EAAE,QAAQ,aAAa,MAAM,aAAa;AAAA,IAC3D,CAAC,KAAK,GAAG;AAAA,IACT,CAAC,aAAa,GAAG;AAAA;AAAA,IACjB,OAAO;AAAA;AAAA,EACR;AAGA,SAAO,IAAI,MAAM,MAAM;AAAA,IACtB,IAAI,QAAQ,MAAM,UAAU;AAE3B,UAAI,OAAO,SAAS,UAAU;AAC7B,eAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAAA,MAC1C;AAGA,UAAI,SAAS,KAAK;AACjB,eAAO,iBAAiB,WAAW;AAAA,MACpC;AAGA,UAAI,QAAQ,QAAQ;AACnB,eAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAAA,MAC1C;AAGA,YAAM,gBAAgB,MAAM,SAAS,WAAW;AAChD,UAAI,iBAAiB,UAAU,cAAc,SAAS,IAAc,GAAG;AAEtE,eAAO,gBAAgB,aAAa,MAAgB,WAAW;AAAA,MAChE;AAGA,iBAAW,OAAO,MAAM,iBAAiB,WAAW,GAAG;AACtD,YAAI,IAAI,SAAS,MAAM;AACtB,iBAAO;AAAA,YACN,IAAI;AAAA,YACJ,gBAAgB,IAAI,IAAI;AAAA,YACxB;AAAA,YACA;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAGA,iBAAW,OAAO,MAAM,eAAe,WAAW,GAAG;AACpD,YAAI,IAAI,WAAW,MAAM;AACxB,iBAAO;AAAA,YACN,IAAI;AAAA,YACJ;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAGA,aAAO;AAAA,IACR;AAAA,IACA,IAAI,QAAQ,MAAM;AACjB,UAAI,OAAO,SAAS,UAAU;AAC7B,eAAO,QAAQ;AAAA,MAChB;AACA,UAAI,SAAS,KAAK;AACjB,eAAO;AAAA,MACR;AACA,YAAM,gBAAgB,MAAM,SAAS,WAAW;AAChD,aACC,QAAQ,UACP,kBAAkB,UAClB,UAAU,cAAc,SAAS,IAAc;AAAA,IAElD;AAAA,IACA,QAAQ,QAAQ;AACf,YAAM,gBAAgB,MAAM,SAAS,WAAW;AAChD,YAAM,cAAc,gBACjB,eAAe,cAAc,OAAO,IACpC,CAAC;AACJ,aAAO,CAAC,GAAG,QAAQ,QAAQ,MAAM,GAAG,KAAK,GAAG,WAAW;AAAA,IACxD;AAAA,IACA,yBAAyB,QAAQ,MAAM;AACtC,YAAM,OAAO;AACb,UACC,SAAS,OACR,OAAO,SAAS,YAAY,KAAK,MAAM,QAAQ,IAAI,GACnD;AACD,eAAO;AAAA,UACN,cAAc;AAAA,UACd,YAAY;AAAA,UACZ,OAAO,KAAK,MAAM,QAAQ,MAAM,MAAM;AAAA,QACvC;AAAA,MACD;AACA,aAAO,QAAQ,yBAAyB,QAAQ,IAAI;AAAA,IACrD;AAAA,EACD,CAAC;AACF;AASO,SAAS,eAAe,WAAmB,OAAwB;AACzE,QAAM,UAAU,MAAM,SAAS,SAAS;AACxC,MAAI,CAAC,SAAS;AACb,UAAM,IAAI,MAAM,UAAU,SAAS,sBAAsB;AAAA,EAC1D;AAEA,QAAM,OAAO;AAAA,IACZ,CAAC,UAAU,GAAG;AAAA,IACd,CAAC,KAAK,GAAG;AAAA,EACV;AAIA,QAAM,YAAY,oBAAI,IAAoD;AAG1E,aAAW,YAAY,MAAM,iBAAiB,SAAS,GAAG;AACzD,UAAM,eAAe,gBAAgB,SAAS,IAAI;AAClD,cAAU,IAAI,SAAS,MAAM;AAAA,MAC5B,QAAQ,SAAS;AAAA,MACjB,MAAM;AAAA,IACP,CAAC;AAAA,EACF;AAGA,aAAW,YAAY,MAAM,eAAe,SAAS,GAAG;AAEvD,QAAI,SAAS,WAAW,UAAW;AAInC,UAAM,cAAc,SAAS;AAG7B,QAAI,CAAC,UAAU,IAAI,WAAW,GAAG;AAEhC,gBAAU,IAAI,aAAa,EAAE,QAAQ,SAAS,QAAQ,MAAM,UAAU,CAAC;AAAA,IACxE;AAAA,EACD;AAGA,QAAM,sBAAsB,oBAAI,IAAY;AAE5C,SAAO,IAAI,MAAM,MAAM;AAAA,IACtB,IAAI,QAAQ,MAAM,UAAU;AAE3B,UAAI,OAAO,SAAS,UAAU;AAC7B,eAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAAA,MAC1C;AAGA,UAAI,SAAS,KAAK;AACjB,eAAO,iBAAiB,SAAS;AAAA,MAClC;AAGA,UAAI,QAAQ,QAAQ;AACnB,eAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAAA,MAC1C;AAEA,YAAM,UAAU;AAGhB,UAAI,kBAAkB,IAAI,OAAO,GAAG;AAEnC,YAAI,UAAU,QAAQ,SAAS,OAAO,GAAG;AACxC,cAAI,CAAC,oBAAoB,IAAI,OAAO,GAAG;AACtC,6BAAiB,WAAW,OAAO;AACnC,gCAAoB,IAAI,OAAO;AAAA,UAChC;AACA,iBAAO,gBAAgB,WAAW,OAAO;AAAA,QAC1C;AAAA,MACD;AAGA,UAAI,UAAU,QAAQ,SAAS,OAAO,GAAG;AACxC,eAAO,gBAAgB,WAAW,OAAO;AAAA,MAC1C;AAGA,YAAM,WAAW,UAAU,IAAI,OAAO;AACtC,UAAI,UAAU;AAEb,eAAO;AAAA,UACN,SAAS;AAAA,UACT,SAAS;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAGA,aAAO;AAAA,IACR;AAAA,IACA,IAAI,QAAQ,MAAM;AACjB,UAAI,OAAO,SAAS,UAAU;AAC7B,eAAO,QAAQ;AAAA,MAChB;AACA,UAAI,SAAS,KAAK;AACjB,eAAO;AAAA,MACR;AACA,YAAM,UAAU;AAChB,aACC,QAAQ,UACR,UAAU,QAAQ,SAAS,OAAO,KAClC,UAAU,IAAI,OAAO;AAAA,IAEvB;AAAA,IACA,QAAQ,QAAQ;AACf,YAAM,cAAc,eAAe,QAAQ,OAAO;AAClD,YAAM,gBAAgB,MAAM,KAAK,UAAU,KAAK,CAAC;AACjD,aAAO;AAAA,QACN,GAAG,QAAQ,QAAQ,MAAM;AAAA,QACzB;AAAA,QACA,GAAG;AAAA,QACH,GAAG;AAAA,MACJ;AAAA,IACD;AAAA,IACA,yBAAyB,QAAQ,MAAM;AACtC,YAAM,OAAO;AACb,UACC,SAAS,OACR,OAAO,SAAS,YAAY,KAAK,MAAM,QAAQ,IAAI,GACnD;AACD,eAAO;AAAA,UACN,cAAc;AAAA,UACd,YAAY;AAAA,UACZ,OAAO,KAAK,MAAM,QAAQ,MAAM,MAAM;AAAA,QACvC;AAAA,MACD;AACA,aAAO,QAAQ,yBAAyB,QAAQ,IAAI;AAAA,IACrD;AAAA,EACD,CAAC;AACF;AAYO,SAAS,kBACf,OACA,YACS;AACT,QAAM,WAAW,IAAI,IAAI,UAAU;AACnC,QAAM,QAAQ,oBAAI,IAAoB;AAEtC,SAAO,IAAI;AAAA,IACV,CAAC;AAAA,IACD;AAAA,MACC,IAAI,SAAS,MAAM;AAElB,YAAI,OAAO,SAAS,UAAU;AAC7B,iBAAO;AAAA,QACR;AAEA,cAAM,UAAU;AAGhB,YAAI,MAAM,IAAI,OAAO,GAAG;AACvB,iBAAO,MAAM,IAAI,OAAO;AAAA,QACzB;AAGA,YAAI,SAAS,IAAI,OAAO,GAAG;AAC1B,gBAAM,WAAW,eAAe,SAAS,KAAK;AAC9C,gBAAM,IAAI,SAAS,QAAQ;AAC3B,iBAAO;AAAA,QACR;AAEA,eAAO;AAAA,MACR;AAAA,MACA,IAAI,SAAS,MAAM;AAClB,YAAI,OAAO,SAAS,UAAU;AAC7B,iBAAO;AAAA,QACR;AACA,eAAO,SAAS,IAAI,IAAc;AAAA,MACnC;AAAA,MACA,UAAU;AACT,eAAO;AAAA,MACR;AAAA,MACA,yBAAyB,SAAS,MAAM;AACvC,YAAI,OAAO,SAAS,YAAY,SAAS,IAAI,IAAI,GAAG;AAEnD,cAAI,WAAW,MAAM,IAAI,IAAI;AAC7B,cAAI,CAAC,UAAU;AACd,uBAAW,eAAe,MAAM,KAAK;AACrC,kBAAM,IAAI,MAAM,QAAQ;AAAA,UACzB;AACA,iBAAO;AAAA,YACN,cAAc;AAAA,YACd,YAAY;AAAA,YACZ,OAAO;AAAA,UACR;AAAA,QACD;AACA,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AACD;;;ACuBO,SAAS,IAGd,QAAiB,SAAsD;AACxE,SAAO;AAAA,IACN,SAAS;AAAA,IACT;AAAA,IACA,SAAU,WAAW,CAAC;AAAA,EACvB;AACD;AAKO,SAAS,MACf,OACyB;AACzB,SACC,OAAO,UAAU,YACjB,UAAU,QACV,aAAa,SACb,MAAM,YAAY;AAEpB;AA0BO,SAAS,OACf,YACA,aACA,SACA,QACY;AAEZ,QAAM,QAAQ,gBAAgB,YAAY,aAAa,QAAQ,OAAO;AACtE,QAAM,aAAa,OAAO,KAAK,UAAU;AAGzC,QAAM,iBAAiB,SAAS;AAChC,MAAI,gBAAgB;AACnB,UAAM,eAAe,IAAI,IAAI,UAAsB;AACnD,eAAW,aAAa,OAAO,KAAK,cAAc,GAAG;AACpD,UAAI,CAAC,aAAa,IAAI,SAAS,GAAG;AACjC,cAAM,IAAI;AAAA,UACT,0CAA0C,SAAS,iBACpC,CAAC,GAAG,YAAY,EAAE,KAAK,IAAI,CAAC;AAAA,QAC5C;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAGA,QAAM,SAAS;AAAA,IACd;AAAA,IACA;AAAA,EACD;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;AAAA,EAC5C;AACD;AASO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAChD,YACC,SACgB,OACA,QACf;AACD,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACb;AAAA,EALiB;AAAA,EACA;AAKlB;AAOO,SAAS,gBACf,YACA,aACA,QACA,SACU;AAKV,MACC,OAAO,SAAS,wBAAwB,YACxC,QAAQ,oBAAoB,KAAK,EAAE,WAAW,GAC7C;AACD,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAEA,QAAM,aAAa,OAAO,KAAK,UAAU;AAGzC,eAAa,YAAY,UAAU;AAGnC,QAAM,cAAc,YAAY,UAAU;AAG1C,QAAM,SAAS;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAGA,oBAAkB,MAAM;AAGxB,QAAM,YAAY,eAAe,YAAY,aAAa,UAAU;AAGpE,QAAM,WAAW,oBAAI,IAAqB;AAC1C,aAAW,SAAS,QAAQ;AAC3B,aAAS,IAAI,MAAM,MAAM,KAAK;AAAA,EAC/B;AAEA,QAAM,cAAc,oBAAI,IAAwB;AAChD,aAAW,YAAY,WAAW;AACjC,UAAM,gBAAgB,GAAG,SAAS,MAAM,IAAI,SAAS,IAAI;AACzD,gBAAY,IAAI,eAAe,QAAQ;AAAA,EACxC;AAGA,QAAM,aAAa,QAAQ;AAC3B,QAAM,cAAc,QAAQ,YACzB,IAAI;AAAA,IACJ,OAAO,QAAQ,OAAO,SAAS,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AAAA,MACrD;AAAA,MACA,EAAE,MAAM,GAAG,IAAI;AAAA,IAChB,CAAC;AAAA,EACF,IACC;AAEH,SAAO,IAAI;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AAMA,SAAS,aACR,YACA,YACO;AACP,QAAM,WAAW,IAAI,IAAI,UAAU;AAEnC,aAAW,CAAC,WAAW,QAAQ,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC/D,eAAW,CAAC,YAAY,SAAS,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAC/D,UAAI,MAAM,SAAS,GAAG;AAErB,YAAI,CAAC,SAAS,IAAI,UAAU,MAAM,GAAG;AACpC,gBAAM,IAAI;AAAA,YACT,gBAAgB,UAAU,oCAAoC,UAAU,MAAM;AAAA,YAC9E;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAGA,YAAI,UAAU,WAAW,aAAa,CAAC,UAAU,QAAQ,OAAO;AAC/D,gBAAM,IAAI;AAAA,YACT,wBAAwB,UAAU;AAAA,YAClC;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAGA,YAAI,UAAU,WAAW,aAAa,UAAU,QAAQ,OAAO;AAC9D,gBAAM,IAAI;AAAA,YACT,+DAA+D,UAAU,iBAAiB,UAAU,MAAM;AAAA,YAC1G;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAQA,IAAM,+BAA+B,oBAAI,IAAI,CAAC,SAAS,MAAM,CAAC;AAwB9D,SAAS,kBAAkB,QAAkC;AAC5D,QAAM,WAAW,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvD,aAAW,SAAS,QAAQ;AAC3B,eAAW,MAAM,MAAM,aAAa;AACnC,YAAM,SAAS,SAAS,IAAI,GAAG,WAAW,KAAK;AAK/C,UAAI,CAAC,QAAQ;AACZ,cAAM,IAAI;AAAA,UACT,mBAAmB,MAAM,IAAI,oCAAoC,GAAG,WAAW,KAAK;AAAA,UACpF,MAAM;AAAA,UACN,GAAG,QAAQ,CAAC;AAAA,QACb;AAAA,MACD;AAOA,iBAAW,UAAU,GAAG,SAAS;AAChC,YAAI,CAAC,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG;AAClD,gBAAM,IAAI;AAAA,YACT,mBAAmB,MAAM,IAAI,sCAAsC,MAAM;AAAA,YACzE,MAAM;AAAA,YACN;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAIA,UAAI,GAAG,QAAQ,WAAW,KAAK,GAAG,WAAW,QAAQ,WAAW,GAAG;AAClE,cAAM,IAAI;AAAA,UACT,mBAAmB,MAAM,IAAI;AAAA,UAC7B,MAAM;AAAA,UACN,GAAG,QAAQ,CAAC;AAAA,QACb;AAAA,MACD;AAIA,UAAI,GAAG,QAAQ,WAAW,GAAG,WAAW,QAAQ,QAAQ;AACvD,cAAM,IAAI;AAAA,UACT,mBAAmB,MAAM,IAAI,mCACzB,GAAG,QAAQ,MAAM,yBAAyB,GAAG,WAAW,QAAQ,MAAM;AAAA,UAC1E,MAAM;AAAA,UACN,GAAG,QAAQ,CAAC;AAAA,QACb;AAAA,MACD;AAGA,iBAAW,UAAU,GAAG,WAAW,SAAS;AAC3C,YAAI,CAAC,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,GAAG;AACnD,gBAAM,IAAI;AAAA,YACT,mBAAmB,MAAM,IAAI,qCAAqC,OAAO,IAAI,IAAI,MAAM;AAAA,YACvF,MAAM;AAAA,YACN,GAAG,QAAQ,CAAC;AAAA,UACb;AAAA,QACD;AAAA,MACD;AAGA,UAAI,GAAG,QAAQ,WAAW,KAAK,GAAG,WAAW,QAAQ,WAAW;AAC/D;AAED,iBAAW,UAAU,GAAG,WAAW,SAAS;AAE3C,cAAM,YAAY,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAC9D,YAAI,CAAC,UAAW;AAShB,cAAM,gBACL,OAAO,OAAO,eAAe,YAAY,OAAO,eAAe;AAChE,cAAM,WAAW,UAAU,WAAW;AAItC,cAAM,gBACL,OAAO,SAAS,KAAK,CAAC,QAAQ;AAC7B,gBAAM,SAAS,IAAI,UAAU;AAC7B,iBACC,IAAI,WAAW,QACf,IAAI,QAAQ,WAAW,KACvB,IAAI,QAAQ,CAAC,MAAM,UACnB,IAAI,UAAU,WACb,IAAI,gBAAgB,UAAa,IAAI,YAAY,WAAW,MAC7D,6BAA6B,IAAI,MAAM;AAAA,QAEzC,CAAC,KAAK;AACP,YAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC,eAAe;AAMlD,gBAAM,gBAAgB,MAAM,QAAQ,OAAO,UAAU;AACrD,gBAAM,sBAAsB,OAAO,OAAO,eAAe;AACzD,gBAAM,aAAa,gBAChB,gBAAgB,OAAO,IAAI,IAAI,MAAM,6FAAwF,OAAO,IAAI,0KACxI,sBACC,4KAA4K,OAAO,UAAoB,OACvM,8HAAyH,MAAM,iFAA4E,MAAM,gFAAgF,MAAM;AAC3S,gBAAM,IAAI;AAAA,YACT,mBAAmB,MAAM,IAAI,cAAc,OAAO,IAAI,IAAI,MAAM,8CAA8C,UAAU;AAAA,YACxH,MAAM;AAAA,YACN,GAAG,QAAQ,CAAC;AAAA,UACb;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAgBA,SAAS,YACR,YAC8B;AAC9B,QAAM,cAAc,oBAAI,IAA4B;AAEpD,aAAW,CAAC,WAAW,QAAQ,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC/D,UAAM,OAAuB,CAAC;AAC9B,UAAM,eAAe,oBAAI,IAAsB;AAE/C,eAAW,CAAC,YAAY,SAAS,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAC/D,UAAI,MAAM,SAAS,GAAG;AAErB,cAAM,WAAW,aAAa,IAAI,UAAU,MAAM,KAAK,CAAC;AACxD,iBAAS,KAAK,UAAU;AACxB,qBAAa,IAAI,UAAU,QAAQ,QAAQ;AAG3C,cAAM,gBAAgB;AAAA,UACrB;AAAA,UACA,UAAU;AAAA,QACX;AACA,cAAM,kBAAkB;AAAA,UACvB;AAAA,UACA;AAAA,UACA,UAAU;AAAA,UACV,UAAU,WAAW;AAAA,QACtB;AAEA,aAAK,KAAK;AAAA,UACT;AAAA,UACA,QAAQ,UAAU;AAAA,UAClB,SAAS,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD;AAGA,eAAW,CAAC,QAAQ,OAAO,KAAK,cAAc;AAC7C,UAAI,QAAQ,SAAS,KAAK,WAAW,WAAW;AAE/C,mBAAW,cAAc,SAAS;AACjC,gBAAMC,OAAM,KAAK,KAAK,CAAC,MAAM,EAAE,eAAe,UAAU;AACxD,cAAIA,QAAO,CAACA,KAAI,QAAQ,IAAI;AAC3B,kBAAM,IAAI;AAAA,cACT,oBAAoB,MAAM,2CAA2C,UAAU;AAAA,cAC/E;AAAA,cACA;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAGA,UAAM,gBAAgB,oBAAI,IAAY;AACtC,eAAWA,QAAO,MAAM;AACvB,UAAIA,KAAI,QAAQ,OAAO;AAEtB,cAAM,QAAQA,KAAI,QAAQ;AAC1B,cAAM,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM,aAAa;AAAA,UACnB,MAAM,eAAe;AAAA,QACtB;AACA,mBAAW,QAAQ,UAAU;AAC5B,cAAI,cAAc,IAAI,IAAI,GAAG;AAC5B,kBAAM,IAAI;AAAA,cACT,4BAA4B,IAAI;AAAA,cAChC;AAAA,cACAA,KAAI;AAAA,YACL;AAAA,UACD;AACA,wBAAc,IAAI,IAAI;AAAA,QACvB;AAAA,MACD,OAAO;AACN,YAAI,cAAc,IAAIA,KAAI,aAAa,GAAG;AACzC,gBAAM,IAAI;AAAA,YACT,4BAA4BA,KAAI,aAAa;AAAA,YAC7C;AAAA,YACAA,KAAI;AAAA,UACL;AAAA,QACD;AACA,sBAAc,IAAIA,KAAI,aAAa;AAAA,MACpC;AAAA,IACD;AAEA,gBAAY,IAAI,WAAW,IAAI;AAAA,EAChC;AAEA,SAAO;AACR;AAUA,SAAS,oBAAoB,YAAoB,SAA6B;AAC7E,MAAI,QAAQ,IAAI;AACf,WAAO,QAAQ;AAAA,EAChB;AAGA,MAAI,WAAW,SAAS,IAAI,GAAG;AAC9B,WAAO,WAAW,MAAM,GAAG,EAAE;AAAA,EAC9B;AAGA,MAAI,WAAW,SAAS,KAAK,GAAG;AAC/B,WAAO,WAAW,MAAM,GAAG,EAAE;AAAA,EAC9B;AAGA,SAAO;AACR;AAMA,SAAS,sBACR,eACA,aACA,SACA,WACS;AAET,MAAI,WAAW;AACd,WAAO;AAAA,EACR;AAEA,MAAI,QAAQ,SAAS;AACpB,WAAO,QAAQ;AAAA,EAChB;AAGA,SAAO,GAAG,aAAa,IAAI,WAAW;AACvC;AAUA,SAAS,gBACR,YACA,QACa;AACb,QAAM,YAAY,WAAW,MAAM;AACnC,MAAI,CAAC,UAAW,QAAO;AAEvB,aAAW,CAAC,EAAE,MAAM,KAAK,OAAO,QAAQ,SAAS,GAAG;AACnD,QAAI,MAAM,MAAM,EAAG;AACnB,UAAM,MAAM,mBAAmB,MAAM;AACrC,QAAI,IAAI,WAAY,QAAO,IAAI;AAAA,EAChC;AAEA,MAAI,QAAQ,WAAW;AACtB,UAAM,QAAQ,UAAU;AACxB,QAAI,SAAS,CAAC,MAAM,KAAK,EAAG,QAAO,mBAAmB,KAAK,EAAE;AAAA,EAC9D;AACA,SAAO;AACR;AAQA,SAAS,wBACR,WACA,eACA,YACA,SACyB;AACzB,QAAM,SAAS,UAAU,aAAa;AACtC,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI,MAAM,MAAM,GAAG;AAGlB,QAAI,CAAC,WAAY,QAAO;AACxB,UAAM,mBAAmB,OAAO;AAChC,UAAM,mBAAmB,WAAW,gBAAgB;AACpD,QAAI,CAAC,iBAAkB,QAAO;AAE9B,UAAM,iBAAiB,OAAO,QAAQ;AACtC,UAAM,qBACL,kBAAkB,eAAe,WAAW,IACzC,eAAe,CAAC,IAChB;AACJ,UAAM,gBAAwB,sBAAsB;AAEpD,UAAM,aAAa,GAAG,gBAAgB,IAAI,aAAa;AACvD,UAAM,OAAO,WAAW,oBAAI,IAAY;AACxC,QAAI,KAAK,IAAI,UAAU,EAAG,QAAO;AACjC,SAAK,IAAI,UAAU;AACnB,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACA,SAAO,mBAAmB,MAAM,EAAE;AACnC;AAKA,SAAS,eACR,YACA,WACA,YACsC;AAKtC,QAAM,YAAY,WAAW,UAAU,MAAM;AAC7C,QAAM,YACL,UAAU,QAAQ,YAAY,WAAW,IACtC,UAAU,QAAQ,WAAW,CAAC,IAC9B;AACJ,QAAM,eACL,aAAa,YACT,wBAAwB,WAAW,WAAW,UAAU,KAC1D,gBAAgB,YAAY,UAAU,MAAM,IAC3C,gBAAgB,YAAY,UAAU,MAAM;AAChD,QAAMC,OAAyB;AAAA,IAC9B,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU,UAAU,QAAQ,YAAY;AAAA,EACzC;AACA,MAAI,UAAU,QAAQ,OAAQ,CAAAA,KAAI,SAAS;AAE3C,MACC,UAAU,QAAQ,cAClB,UAAU,QAAQ,WAAW,WAAW,GACvC;AACD,UAAM,IAAI;AAAA,MACT,cAAc,UAAU,2BAA2B,UAAU,QAAQ,WAAW,MAAM;AAAA,IACvF;AAAA,EACD;AACA,QAAM,KAA4B;AAAA,IACjC,SAAS,CAAC,UAAU;AAAA,IACpB,YAAY;AAAA,MACX,OAAO,UAAU;AAAA,MACjB,SAAS,UAAU,QAAQ,cAAc,CAAC,IAAI;AAAA,IAC/C;AAAA,EACD;AACA,MAAI,UAAU,QAAQ,SAAU,IAAG,WAAW,UAAU,QAAQ;AAChE,MAAI,UAAU,QAAQ,SAAU,IAAG,WAAW,UAAU,QAAQ;AAEhE,SAAO,EAAE,KAAKA,MAAiB,GAAuB;AACvD;AAKA,SAAS,mBACR,YACA,WACmC;AACnC,QAAM,MAAM,mBAAmB,SAAS;AACxC,QAAMA,OAAyB;AAAA,IAC9B,MAAM;AAAA,IACN,MAAM,IAAI;AAAA,IACV,UAAU,IAAI,YAAY;AAAA,EAC3B;AACA,MAAI,IAAI,QAAQ,KAAK,EAAG,CAAAA,KAAI,iBAAiB,IAAI,OAAO,KAAK;AAC7D,MAAI,IAAI,OAAQ,CAAAA,KAAI,SAAS,IAAI;AACjC,MAAI,IAAI,cAAe,CAAAA,KAAI,gBAAgB,IAAI;AAC/C,MAAI,IAAI,YAAY,OAAW,CAAAA,KAAI,UAAU,IAAI;AACjD,SAAO,EAAE,KAAKA,MAAiB,MAAM,IAAI,cAAc,MAAM;AAC9D;AAKA,SAAS,qBACR,YACA,UACA,YAC6E;AAC7E,QAAM,UAAsB,CAAC;AAC7B,QAAM,cAA8B,CAAC;AACrC,QAAM,aAAuB,CAAC;AAE9B,aAAW,CAAC,YAAY,SAAS,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAC/D,QAAI,MAAM,SAAS,GAAG;AACrB,YAAM,EAAE,KAAAA,MAAK,GAAG,IAAI,eAAe,YAAY,WAAW,UAAU;AACpE,cAAQ,KAAKA,IAAG;AAChB,kBAAY,KAAK,EAAE;AAAA,IACpB,OAAO;AACN,YAAM,EAAE,KAAAA,MAAK,KAAK,IAAI,mBAAmB,YAAY,SAAS;AAC9D,cAAQ,KAAKA,IAAG;AAChB,UAAI,KAAM,YAAW,KAAK,UAAU;AAAA,IACrC;AAAA,EACD;AACA,SAAO,EAAE,SAAS,aAAa,WAAW;AAC3C;AAaA,SAAS,gBACR,YACA,aACA,SACA,SACyC;AACzC,MAAI,WAAW,SAAS,GAAG;AAC1B,WAAO,WAAW,WAAW,IAAK,WAAW,CAAC,IAAe;AAAA,EAC9D;AAIA,QAAM,YACL,SAAS,wBAAwB,SAC9B,OACA,QAAQ;AACZ,MAAI,cAAc,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS,GAAG;AACpE,WAAO;AAAA,EACR;AAEA,QAAM,YAAY,YAAY,QAAQ,CAAC,OAAO,GAAG,OAAO;AACxD,MAAI,UAAU,SAAS,GAAG;AACzB,WAAO,UAAU,WAAW,IAAI,UAAU,CAAC,IAAI;AAAA,EAChD;AACA,SAAO;AACR;AAKA,SAAS,mBACR,WACA,aACA,SACyB;AACzB,QAAM,gBAAwC,CAAC;AAC/C,QAAM,OAAO,YAAY,IAAI,SAAS,KAAK,CAAC;AAC5C,QAAM,WACL,OAAO,YAAY,WAAW,UAAW,UAAU,CAAC,KAAK;AAE1D,aAAWD,QAAO,MAAM;AACvB,QAAIA,KAAI,QAAQ,SAASA,KAAI,WAAW,WAAW;AAClD,oBAAc;AAAA,QACb;AAAA,UACC;AAAA,UACAA,KAAI;AAAA,UACJ;AAAA,UACAA,KAAI,QAAQ,MAAM;AAAA,UAClBA,KAAI,QAAQ,MAAM;AAAA,QACnB;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;AAKA,SAAS,mBAAmB,WAAmB,UAA+B;AAC7E,QAAM,UAAqB,CAAC;AAC5B,aAAW,CAAC,YAAY,SAAS,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAC/D,QAAI,MAAM,SAAS,EAAG;AACtB,UAAM,MAAM,mBAAmB,SAAS;AACxC,QAAI,IAAI,OAAO;AACd,cAAQ,KAAK;AAAA,QACZ,MAAM,OAAO,SAAS,IAAI,UAAU;AAAA,QACpC,SAAS,CAAC,UAAU;AAAA,QACpB,QAAQ;AAAA,MACT,CAAC;AAAA,IACF;AAAA,EACD;AACA,SAAO;AACR;AAKA,SAAS,sBACR,WACA,aAKC;AACD,QAAM,eAA0B,CAAC;AACjC,QAAM,mBAAwC,CAAC;AAC/C,QAAM,mBAAmC,CAAC;AAE1C,QAAM,mBAAmB,cAAc,SAAS;AAChD,MAAI,CAAC,kBAAkB;AACtB,WAAO,EAAE,cAAc,kBAAkB,iBAAiB;AAAA,EAC3D;AAEA,MAAI,iBAAiB,SAAS;AAC7B,eAAW,OAAO,iBAAiB,SAAS;AAC3C,YAAM,UAA4B;AAAA,QACjC,MAAM,IAAI,QAAQ,OAAO,SAAS,IAAI,IAAI,QAAQ,KAAK,GAAG,CAAC;AAAA,QAC3D,SAAS,IAAI;AAAA,QACb,QAAQ,IAAI,UAAU;AAAA,MACvB;AACA,UAAI,IAAI,OAAQ,SAAQ,SAAS,IAAI;AACrC,UAAI,IAAI,MAAO,SAAQ,QAAQ,IAAI;AACnC,UAAI,IAAI,QAAS,SAAQ,UAAU,IAAI;AACvC,UAAI,IAAI,KAAM,SAAQ,OAAO,IAAI;AACjC,mBAAa,KAAK,OAAkB;AAAA,IACrC;AAAA,EACD;AAEA,MAAI,iBAAiB,kBAAkB;AACtC,eAAW,OAAO,iBAAiB,kBAAkB;AACpD,uBAAiB,KAAK;AAAA,QACrB,MAAM,IAAI;AAAA,QACV,YAAY,UAAU,IAAI,UAAU;AAAA,MACrC,CAAC;AAAA,IACF;AAAA,EACD;AAEA,MAAI,iBAAiB,aAAa;AACjC,eAAW,SAAS,iBAAiB,aAAa;AACjD,UAAI,CAAC,MAAM,QAAQ,SAAS,QAAQ;AACnC,cAAM,IAAI;AAAA,UACT,oBAAoB,SAAS,aAAQ,MAAM,MAAM;AAAA,UACjD;AAAA,QACD;AAAA,MACD;AACA,YAAM,KAA4B;AAAA,QACjC,SAAS,CAAC,GAAG,MAAM,QAAQ,OAAO;AAAA,QAClC,YAAY;AAAA,UACX,OAAO,MAAM;AAAA,UACb,SAAS,MAAM,QAAQ,aACpB,CAAC,GAAG,MAAM,QAAQ,UAAU,IAC5B,CAAC,IAAI;AAAA,QACT;AAAA,MACD;AACA,UAAI,MAAM,QAAQ,SAAU,IAAG,WAAW,MAAM,QAAQ;AACxD,uBAAiB,KAAK,EAAkB;AAAA,IACzC;AAAA,EACD;AAEA,SAAO,EAAE,cAAc,kBAAkB,iBAAiB;AAC3D;AAKA,SAAS,YACR,YACA,aACA,YACA,aACA,SACY;AACZ,QAAM,SAAoB,CAAC;AAE3B,aAAW,aAAa,YAAY;AACnC,UAAM,WAAW,WAAW,SAAS;AACrC,QAAI,CAAC,SAAU;AAEf,UAAM,EAAE,SAAS,aAAa,WAAW,IAAI;AAAA,MAC5C;AAAA,MACA;AAAA,MACA;AAAA,IACD;AACA,UAAM,UAAU,gBAAgB,YAAY,aAAa,SAAS,OAAO;AACzE,UAAM,gBAAgB,mBAAmB,WAAW,aAAa,OAAO;AACxE,UAAM,gBAAgB,mBAAmB,WAAW,QAAQ;AAC5D,UAAM,EAAE,cAAc,kBAAkB,iBAAiB,IACxD,sBAAsB,WAAW,WAAW;AAE7C,UAAM,QAAiB;AAAA,MACtB,MAAM;AAAA,MACN;AAAA,MACA,GAAI,YAAY,SAAY,EAAE,YAAY,QAAQ,IAAI,CAAC;AAAA,MACvD,aAAa,CAAC,GAAG,aAAa,GAAG,gBAAgB;AAAA,MACjD,SAAS,CAAC,GAAG,eAAe,GAAG,YAAY;AAAA,MAC3C,GAAI,iBAAiB,SAAS,IAAI,EAAE,iBAAiB,IAAI,CAAC;AAAA,MAC1D,GAAI,cAAc,SAAS,IAAI,EAAE,cAAc,IAAI,CAAC;AAAA,IACrD;AACA,WAAO,KAAK,KAAK;AAAA,EAClB;AAEA,SAAO;AACR;AAKA,SAAS,mBAAmB,KAS1B;AACD,MAAI,OAAO,QAAQ,UAAU;AAC5B,WAAO,EAAE,MAAM,IAAI;AAAA,EACpB;AACA,SAAO;AACR;AASA,SAAS,eACR,aACA,aACA,YACe;AACf,QAAM,YAA0B,CAAC;AAEjC,aAAW,aAAa,YAAY;AACnC,UAAM,OAAO,YAAY,IAAI,SAAS,KAAK,CAAC;AAE5C,eAAWA,QAAO,MAAM;AACvB,UAAIA,KAAI,QAAQ,OAAO;AAEtB,cAAM,QAAQA,KAAI,QAAQ;AAG1B,kBAAU,KAAK;AAAA,UACd,MAAM,MAAM;AAAA,UACZ,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,YAAYA,KAAI;AAAA,UAChB,aAAa;AAAA,UACb,aAAaA,KAAI,QAAQ,WAAW,aAAa;AAAA,UACjD,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,QACd,CAAC;AAGD,kBAAU,KAAK;AAAA,UACd,MAAM,MAAM;AAAA,UACZ,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,YAAYA,KAAI;AAAA,UAChB,aAAa;AAAA,UACb,aAAa;AAAA;AAAA,UACb,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,QACd,CAAC;AAGD,cAAM,gBAAgB,MAAM,aAAa;AACzC,kBAAU,KAAK;AAAA,UACd,MAAM;AAAA,UACN,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,YAAYA,KAAI;AAAA,UAChB,aAAa;AAAA,UACb,aAAa;AAAA,UACb,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,UACb,WAAW;AAAA,YACV,WAAW;AAAA,YACX,UAAU;AAAA,YACV,SAAS,MAAM;AAAA,UAChB;AAAA,QACD,CAAC;AAGD,cAAM,kBAAkB,MAAM,eAAe;AAC7C,kBAAU,KAAK;AAAA,UACd,MAAM;AAAA,UACN,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,YAAYA,KAAI;AAAA,UAChB,aAAa;AAAA,UACb,aAAa;AAAA,UACb,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,UACb,WAAW;AAAA,YACV,WAAW;AAAA,YACX,UAAU;AAAA,YACV,SAAS,MAAM;AAAA,UAChB;AAAA,QACD,CAAC;AAAA,MACF,OAAO;AAEN,cAAM,WAAWA,KAAI,QAAQ,UAAU;AAGvC,kBAAU,KAAK;AAAA,UACd,MAAMA,KAAI;AAAA,UACV,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,QAAQA,KAAI;AAAA,UACZ,YAAYA,KAAI;AAAA,UAChB,aAAa;AAAA,UACb,aAAaA,KAAI,QAAQ,WAAW,aAAa;AAAA,UACjD,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,QACd,CAAC;AAGD,cAAM,cAA4B,WAAW,WAAW;AACxD,cAAM,qBAAqB,WAAW,QAAQ;AAE9C,kBAAU,KAAK;AAAA,UACd,MAAMA,KAAI;AAAA,UACV,MAAM;AAAA,UACN,QAAQA,KAAI;AAAA,UACZ,QAAQ;AAAA,UACR,YAAYA,KAAI;AAAA,UAChB,aAAa;AAAA,UACb,aAAa;AAAA;AAAA,UACb,iBAAiB;AAAA,UACjB,gBAAgB;AAAA,UAChB,aAAa;AAAA,QACd,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAwBA,SAAS,mBAAmB,MAAoC;AAC/D,UAAQ,MAAM;AAAA;AAAA,IAEb,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA;AAAA,IAER,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA;AAAA,IAER;AACC,aAAO;AAAA,EACT;AACD;AAgCA,eAAsB,gBAGrB,SACA,SACqB;AAErB,QAAM,oBAIF,CAAC;AACL,MAAI,SAAS,WAAW,OAAW,mBAAkB,SAAS,QAAQ;AACtE,MAAI,SAAS,WAAW,OAAW,mBAAkB,UAAU,QAAQ;AACvE,MAAI,SAAS,YAAY;AACxB,sBAAkB,UAAU,QAAQ;AAGrC,QAAM,sBAAsB,MAAM,QAAQ,WAAW,iBAAiB;AAEtE,QAAM,QAAQ;AACd,QAAM,iBAAiB,oBAAoB;AAI3C,QAAM,WAAW,oBAAI,IAGnB;AACF,aAAW,SAAS,MAAM,OAAO,OAAO,GAAG;AAC1C,UAAM,WAAW,oBAAI,IAGnB;AACF,eAAW,MAAM,MAAM,aAAa;AAEnC,YAAM,WAAW,GAAG,QAAQ,CAAC;AAC7B,UAAI,CAAC,SAAU;AAGf,YAAM,SAAS,MAAM,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AAC5D,eAAS,IAAI,UAAU;AAAA,QACtB,QAAQ,GAAG,WAAW;AAAA,QACtB,UAAU,QAAQ,YAAY;AAAA,QAC9B,QAAQ,QAAQ,UAAU;AAAA,MAC3B,CAAC;AAAA,IACF;AACA,aAAS,IAAI,MAAM,MAAM,QAAQ;AAAA,EAClC;AAGA,QAAM,aAAuC,CAAC;AAE9C,aAAW,SAAS,MAAM,OAAO,OAAO,GAAG;AAC1C,UAAM,WAAqB,CAAC;AAC5B,UAAM,WAAW,SAAS,IAAI,MAAM,IAAI,KAAK,oBAAI,IAAI;AAErD,eAAW,UAAU,MAAM,SAAS;AACnC,YAAM,KAAK,SAAS,IAAI,OAAO,IAAI;AAEnC,UAAI,IAAI;AAEP,iBAAS,OAAO,IAAI,IAAI,IAAI,GAAG,QAAQ;AAAA,UACtC,UAAU,GAAG;AAAA,UACb,QAAQ,GAAG;AAAA,QACZ,CAAC;AAAA,MACF,OAAO;AAEN,iBAAS,OAAO,IAAI,IAAI,mBAAmB,OAAO,IAAI;AAAA,MACvD;AAAA,IACD;AAEA,eAAW,MAAM,IAAI,IAAI;AAAA,EAC1B;AAEA,QAAM,aAAa,OAAO,KAAK,UAAU;AAGzC,QAAM,SAAS;AAAA,IACd;AAAA,IACA;AAAA,EACD;AAGA,QAAM,SAA6B;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAGA,MAAI,QAAQ,aAAa,QAAW;AACnC,WAAO,WAAW,QAAQ;AAAA,EAC3B;AACA,MAAI,mBAAmB,QAAW;AACjC,WAAO,iBAAiB;AAAA,EACzB;AAEA,SAAO;AACR;;;ACtrDO,IAAM,sBAA6D;AAAA,EACzE,WAAW;AAAA,EACX,WAAW;AAAA,EACX,YAAY,CAAC,aAAa,WAAW;AAAA,EACrC,aAAa;AACd;AAoBO,IAAM,oBAA4C;AAAA,EACxD,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,KAAK;AAAA,EACL,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,UAAU;AAAA,EACV,WAAW;AACZ;AAEO,SAAS,YACf,MACA,WACS;AACT,QAAM,QAAQ,KAAK,YAAY;AAG/B,MAAI,WAAW;AACd,UAAM,WAAW,UAAU,KAAK;AAChC,QAAI,aAAa,QAAW;AAC3B,UAAI,KAAK,CAAC,GAAG,YAAY,MAAM,KAAK,CAAC,GAAG;AACvC,eAAO,SAAS,OAAO,CAAC,EAAE,YAAY,IAAI,SAAS,MAAM,CAAC;AAAA,MAC3D;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAGA,QAAM,YAAY,kBAAkB,KAAK;AACzC,MAAI,cAAc,QAAW;AAE5B,QAAI,KAAK,CAAC,GAAG,YAAY,MAAM,KAAK,CAAC,GAAG;AACvC,aAAO,UAAU,OAAO,CAAC,EAAE,YAAY,IAAI,UAAU,MAAM,CAAC;AAAA,IAC7D;AACA,WAAO;AAAA,EACR;AAGA,MAAI,MAAM,SAAS,KAAK,KAAK,KAAK,SAAS,GAAG;AAC7C,WAAO,GAAG,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,EAC5B;AAIA,MACC,MAAM,SAAS,IAAI,KACnB,KAAK,SAAS,MACb,MAAM,SAAS,MAAM,KACrB,MAAM,SAAS,MAAM,KACrB,MAAM,SAAS,KAAK,KACpB,MAAM,SAAS,KAAK,KACnB,MAAM,SAAS,KAAK,KACpB,CAAC,MAAM,SAAS,MAAM,KACtB,CAAC,MAAM,SAAS,MAAM,IACvB;AACD,WAAO,KAAK,MAAM,GAAG,EAAE;AAAA,EACxB;AAGA,MAAI,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,SAAS,IAAI,KAAK,KAAK,SAAS,GAAG;AACpE,WAAO,KAAK,MAAM,GAAG,EAAE;AAAA,EACxB;AAGA,SAAO;AACR;AAMO,SAAS,UAAU,MAAsB;AAC/C,MACC,KAAK,SAAS,GAAG,KACjB,CAAC,CAAC,MAAM,MAAM,MAAM,IAAI,EAAE,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,GACrD;AACD,WAAO,GAAG,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,EAC5B;AACA,MACC,KAAK,SAAS,GAAG,KACjB,KAAK,SAAS,GAAG,KACjB,KAAK,SAAS,IAAI,KAClB,KAAK,SAAS,IAAI,GACjB;AACD,WAAO,GAAG,IAAI;AAAA,EACf;AACA,SAAO,GAAG,IAAI;AACf;AAKO,SAAS,WAAW,MAAsB;AAChD,SAAO,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;AACnD;AAKO,SAAS,aAAa,MAAsB;AAClD,SAAO,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;AACnD;AAOO,SAAS,sBAAsB,eAA+B;AAEpE,MAAI,kBAAkB,SAAU,QAAO;AAGvC,SAAO,UAAU,aAAa;AAC/B;AAsHO,SAAS,kBACf,WACA,OACA,aACA,YACe;AACf,QAAM,MAAoB,CAAC;AAC3B,QAAM,UAAU,YAAY;AAE5B,aAAW,CAAC,SAAS,MAAM,KAAK,OAAO,QAAQ,KAAK,GAAG;AAEtD,QAAI,OAAO,YAAY;AACtB,YAAM,cAAc,OAAO,WAAW;AACtC,UAAI,WAAW,IAAI,WAAW,GAAG;AAEhC,cAAM,eAAe,QAAQ,SAAS,IAAI,IACvC,QAAQ,MAAM,GAAG,EAAE,IACnB,YAAY,WAAW;AAE1B,cAAM,YAAY,gBAAgB;AAClC,cAAM,aAAyB;AAAA,UAC9B,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA,UAAU;AAAA,UACV,cAAc,OAAO,WAAW,UAAU;AAAA,QAC3C;AAGA,YAAI,WAAW;AACd,qBAAW,aAAa,OAAO,WAAW,cAAc;AACxD,qBAAW,YACV,OAAO,WAAW,aAAa,sBAAsB,YAAY;AAAA,QACnE;AAEA,YAAI,KAAK,UAAU;AAAA,MACpB;AACA;AAAA,IACD;AAIA,eAAW,kBAAkB,YAAY;AACxC,UAAI,mBAAmB,UAAW;AAElC,YAAM,WAAW,YAAY,cAAc;AAC3C,YAAM,iBAAiB,QAAQ,QAAQ,cAAc,QAAQ;AAE7D,UAAI,YAAY,gBAAgB;AAC/B,YAAI,KAAK;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,cAAc;AAAA,UACd,UAAU;AAAA,UACV,cAAc;AAAA,QACf,CAAC;AACD;AAAA,MACD;AAAA,IACD;AAGA,QAAI,QAAQ,SAAS,IAAI,GAAG;AAC3B,YAAM,SAAS,QAAQ,MAAM,GAAG,EAAE;AAClC,YAAM,WAAW,YAAY,SAAS;AAEtC,UACC,CAAC,UAAU,WAAW,cAAc,SAAS,QAAQ,EAAE,SAAS,MAAM,GACrE;AACD,YAAI,CAAC,IAAI,KAAK,CAAC,OAAO,GAAG,WAAW,OAAO,GAAG;AAC7C,cAAI,KAAK;AAAA,YACR,QAAQ;AAAA,YACR,aAAa;AAAA,YACb,cAAc;AAAA,YACd,UAAU;AAAA,YACV,cAAc;AAAA;AAAA,YAEd,YAAY;AAAA,YACZ,WAAW,sBAAsB,MAAM;AAAA,UACxC,CAAC;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAsBA,SAAS,iBACR,SACA,QACA,YACU;AAEV,MAAI,OAAO,WAAY,QAAO;AAE9B,MAAI,WAAW,SAAS,OAAO,EAAG,QAAO;AAEzC,MAAI,OAAO,WAAY,QAAO;AAE9B,MAAI,QAAQ,SAAS,IAAI,EAAG,QAAO;AAEnC,MAAI,CAAC,MAAM,aAAa,aAAa,WAAW,EAAE,SAAS,OAAO;AACjE,WAAO;AAGR,SAAO;AACR;AAMO,SAAS,iBACf,QACA,aACA,YACuB;AACvB,QAAM,UAAgC,CAAC;AAEvC,aAAW,CAAC,WAAW,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACxD,UAAM,MAAM,kBAAkB,WAAW,OAAO,aAAa,UAAU;AAGvE,QAAI,IAAI,WAAW,EAAG;AAGtB,UAAM,qBAAqB,OAAO,QAAQ,KAAK,EAAE;AAAA,MAAK,CAAC,CAAC,SAAS,MAAM,MACtE,iBAAiB,SAAS,QAAQ,YAAY,UAAU;AAAA,IACzD;AAEA,QAAI,mBAAoB;AAGxB,UAAM,MAAM,IAAI,CAAC;AACjB,UAAM,MAAM,IAAI,CAAC;AACjB,QAAI,OAAO,KAAK;AACf,cAAQ,KAAK;AAAA,QACZ,UAAU;AAAA,QACV,QAAQ,IAAI;AAAA,QACZ,QAAQ,IAAI;AAAA,QACZ,KAAK,IAAI;AAAA,QACT,KAAK,IAAI;AAAA,MACV,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO;AACR;AAUO,SAAS,yBACf,QACA,aACA,oBAA+C,CAAC,GACpB;AAC5B,QAAM,SAAoC,EAAE,GAAG,kBAAkB;AACjE,QAAM,aAAa,IAAI,IAAI,OAAO,KAAK,MAAM,CAAC;AAG9C,QAAM,cAAc,iBAAiB,QAAQ,aAAa,UAAU;AACpE,QAAM,iBAAiB,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;AAGjE,aAAW,OAAO,aAAa;AAC9B,UAAM,EAAE,UAAU,QAAQ,QAAQ,KAAK,IAAI,IAAI;AAG/C,UAAM,cAAc,YAAY,YAC7B,UAAU,YAAY,MAAM,CAAC,IAC7B;AACH,UAAM,cAAc,YAAY,YAC7B,UAAU,YAAY,MAAM,CAAC,IAC7B;AAEH,UAAM,UAAU,GAAG,MAAM,IAAI,WAAW;AACxC,UAAM,UAAU,GAAG,MAAM,IAAI,WAAW;AAGxC,QAAI,EAAE,WAAW,SAAS;AACzB,YAAM,MAAgC;AAAA,QACrC,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,UAAU;AAAA,QACV,UAAU;AAAA,MACX;AACA,aAAO,OAAO,IAAI;AAAA,IACnB;AAEA,QAAI,EAAE,WAAW,SAAS;AACzB,YAAM,MAAgC;AAAA,QACrC,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,UAAU;AAAA,QACV,UAAU;AAAA,MACX;AACA,aAAO,OAAO,IAAI;AAAA,IACnB;AAAA,EACD;AAGA,aAAW,CAAC,WAAW,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACxD,QAAI,eAAe,IAAI,SAAS,EAAG;AAEnC,UAAM,MAAM,kBAAkB,WAAW,OAAO,aAAa,UAAU;AAEvE,eAAW,MAAM,KAAK;AAErB,UAAI,eAAe,IAAI,GAAG,WAAW,EAAG;AAGxC,YAAM,eAAe,GAAG,SAAS,IAAI,GAAG,YAAY;AACpD,UAAI,EAAE,gBAAgB,SAAS;AAC9B,cAAM,MAA+B;AAAA,UACpC,MAAM;AAAA,UACN,QAAQ,GAAG;AAAA,UACX,YAAY,GAAG;AAAA,UACf,WAAW,GAAG;AAAA,QACf;AACA,eAAO,YAAY,IAAI;AAAA,MACxB;AAIA,YAAM,YAAY,GAAG,gBAAgB;AACrC,YAAM,cAAc,YACjB,sBAAsB,GAAG,YAAY,KACpC,MAAM;AAMP,cAAM,iBACL,GAAG,iBAAiB,YAAY,GAAG,WAAW;AAC/C,YAAI,gBAAgB;AACnB,iBAAO,YAAY,YAChB,UAAU,GAAG,YAAY,IACzB,GAAG;AAAA,QACP;AACA,eAAO,YAAY,YAChB,UAAU,YAAY,SAAS,CAAC,IAChC;AAAA,MACJ,GAAG;AACL,YAAM,aAAa,GAAG,GAAG,WAAW,IAAI,WAAW;AACnD,UAAI,EAAE,cAAc,SAAS;AAC5B,cAAM,MAA6B;AAAA,UAClC,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,YAAY,GAAG;AAAA,UACf,WAAW;AAAA,QACZ;AACA,eAAO,UAAU,IAAI;AAAA,MACtB;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;;;ACzgBO,SAAS,aACf,QACA,QACoB;AACpB,QAAM,YAAuC,QAAQ,aAAa,CAAC;AACnE,QAAM,QAA+B,QAAQ,SAAS,CAAC;AACvD,QAAM,cAA2C,QAAQ,eAAe,CAAC;AACzE,QAAM,UAAmC,QAAQ,WAAW,CAAC;AAC7D,QAAM,iBAAuC,QAAQ,kBAAkB,CAAC;AAGxE,QAAM,sBAA6D;AAAA,IAClE,GAAG;AAAA,IACH,GAAG;AAAA,EACJ;AAGA,QAAM,eAAe;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAGA,oBAAkB,QAAQ,SAAS;AAGnC,gBAAc,cAAc,KAAK;AAGjC,yBAAuB,QAAQ,cAAc;AAE7C,SAAO;AAAA,IACN;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,EACD;AACD;AAKA,SAAS,kBACR,QACA,WACO;AACP,QAAM,aAAa,IAAI,IAAI,OAAO,KAAK,MAAM,CAAC;AAE9C,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,SAAS,GAAG;AACnD,UAAM,cAAc,IAAI,MAAM,GAAG,EAAE,CAAC,KAAK;AAEzC,QAAI,CAAC,WAAW,IAAI,WAAW,GAAG;AACjC,YAAM,IAAIE;AAAA,QACT,aAAa,GAAG,2CAA2C,WAAW;AAAA,MACvE;AAAA,IACD;AAEA,QAAI,CAAC,WAAW,IAAI,IAAI,MAAM,GAAG;AAChC,YAAM,IAAIA;AAAA,QACT,aAAa,GAAG,2CAA2C,IAAI,MAAM;AAAA,MACtE;AAAA,IACD;AAEA,QAAI,IAAI,SAAS,gBAAgB,CAAC,WAAW,IAAI,IAAI,OAAO,GAAG;AAC9D,YAAM,IAAIA;AAAA,QACT,aAAa,GAAG,6CAA6C,IAAI,OAAO;AAAA,MACzE;AAAA,IACD;AAAA,EACD;AACD;AAKA,SAAS,cACR,WACA,OACO;AACP,aAAW,QAAQ,OAAO,KAAK,KAAK,GAAG;AACtC,QAAI,EAAE,QAAQ,YAAY;AACzB,YAAM,IAAIA;AAAA,QACT,cAAc,IAAI,6CACH,OAAO,KAAK,SAAS,EAAE,KAAK,IAAI,CAAC;AAAA,MACjD;AAAA,IACD;AAAA,EACD;AACD;AAKA,SAAS,uBACR,QACA,gBACO;AACP,QAAM,aAAa,IAAI,IAAI,OAAO,KAAK,MAAM,CAAC;AAE9C,aAAW,aAAa,OAAO,KAAK,cAAc,GAAG;AACpD,QAAI,CAAC,WAAW,IAAI,SAAS,GAAG;AAC/B,YAAM,IAAIA;AAAA,QACT,0CAA0C,SAAS,iBACpC,CAAC,GAAG,UAAU,EAAE,KAAK,IAAI,CAAC;AAAA,MAC1C;AAAA,IACD;AAAA,EACD;AACD;AAKO,IAAMA,yBAAN,cAAoC,MAAM;AAAA,EAChD,YAAY,SAAiB;AAC5B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACb;AACD;;;ACuLO,SAAS,YACf,KACiC;AACjC,SAAO,IAAI,SAAS;AACrB;AAKO,SAAS,UACf,KAC+B;AAC/B,SAAO,IAAI,SAAS;AACrB;AAKO,SAAS,aACf,KACkC;AAClC,SAAO,IAAI,SAAS;AACrB;;;AChXO,IAAM,iBAAN,MAAM,wBAAuB,MAAM;AAAA,EACvB,OAAO;AAAA;AAAA;AAAA;AAAA,EAKhB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAET,YAAY,MAA0D;AACrE,UAAM,UACL,kBAAkB,KAAK,SAAS,KAAK,KAAK,MAAM;AAAA;AAAA,UACrC,KAAK,GAAG;AAEpB,UAAM,OAAO;AAEb,SAAK,YAAY,KAAK;AACtB,SAAK,SAAS,KAAK;AACnB,SAAK,MAAM,KAAK;AAEhB,WAAO,eAAe,MAAM,gBAAe,SAAS;AAAA,EACrD;AACD;AAWO,IAAM,gBAAN,MAAM,uBAAsB,MAAM;AAAA,EACtB,OAAO;AAAA;AAAA;AAAA;AAAA,EAKhB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAET,YAAY,OAAe,MAAe;AACzC,UAAM,UAAU,OACb,wBAAwB,KAAK,MAAM,IAAI,KACvC,wBAAwB,KAAK;AAEhC,UAAM,OAAO;AACb,SAAK,QAAQ;AACb,QAAI,SAAS,QAAW;AACvB,WAAK,OAAO;AAAA,IACb;AACA,WAAO,eAAe,MAAM,eAAc,SAAS;AAAA,EACpD;AACD;AAmBO,IAAM,yBAAN,MAAM,gCAA+B,MAAM;AAAA,EAC/B,OAAO;AAAA;AAAA;AAAA;AAAA,EAKhB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA,EAET,YACC,aACA,aACA,SACC;AAGD,UAAM,iBAAiB;AAEvB,UAAM,cAAc;AAEpB,SAAK,cAAc;AACnB,SAAK,cAAc;AACnB,SAAK,UAAU;AACf,SAAK,gBAAgB;AAIrB,WAAO,eAAe,MAAM,wBAAuB,SAAS;AAAA,EAC7D;AACD;AAYO,SAAS,iBACf,QACA,YACqB;AACrB,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,QAAM,cAAc,OAAO,YAAY;AACvC,MAAI;AACJ,MAAI,YAAY,OAAO;AAEvB,aAAW,aAAa,YAAY;AACnC,UAAM,iBAAiB,UAAU,YAAY;AAG7C,QAAI,eAAe,WAAW,WAAW,GAAG;AAC3C,aAAO;AAAA,IACR;AAGA,UAAM,WAAW,oBAAoB,aAAa,cAAc;AAChE,QAAI,WAAW,aAAa,YAAY,KAAK,IAAI,OAAO,QAAQ,CAAC,GAAG;AACnE,kBAAY;AACZ,kBAAY;AAAA,IACb;AAAA,EACD;AAEA,SAAO;AACR;AAKA,SAAS,oBAAoB,GAAW,GAAmB;AAE1D,QAAM,OAAO,EAAE,SAAS;AACxB,QAAM,OAAO,EAAE,SAAS;AACxB,QAAM,SAAqB,CAAC;AAE5B,WAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC9B,WAAO,CAAC,IAAI,IAAI,MAAc,IAAI,EAAE,KAAK,CAAC;AAAA,EAC3C;AAGA,WAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC9B,UAAM,MAAM,OAAO,CAAC;AACpB,QAAI,IAAK,KAAI,CAAC,IAAI;AAAA,EACnB;AAEA,QAAM,WAAW,OAAO,CAAC;AACzB,MAAI,UAAU;AACb,aAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC9B,eAAS,CAAC,IAAI;AAAA,IACf;AAAA,EACD;AAEA,WAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC9B,UAAM,aAAa,OAAO,CAAC;AAC3B,UAAM,UAAU,OAAO,IAAI,CAAC;AAC5B,QAAI,CAAC,cAAc,CAAC,QAAS;AAE7B,aAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC9B,YAAM,WAAW,QAAQ,IAAI,CAAC,KAAK;AACnC,YAAM,SAAS,QAAQ,CAAC,KAAK;AAC7B,YAAM,WAAW,WAAW,IAAI,CAAC,KAAK;AAEtC,UAAI,EAAE,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC,GAAG;AACxC,mBAAW,CAAC,IAAI;AAAA,MACjB,OAAO;AACN,mBAAW,CAAC,IAAI,KAAK;AAAA,UACpB,WAAW;AAAA;AAAA,UACX,WAAW;AAAA;AAAA,UACX,SAAS;AAAA;AAAA,QACV;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,QAAM,UAAU,OAAO,EAAE,MAAM;AAC/B,SAAO,UAAW,QAAQ,EAAE,MAAM,KAAK,IAAK;AAC7C;AAoBO,IAAM,wBAAN,MAAM,+BAA8B,MAAM;AAAA,EAC9B,OAAO;AAAA;AAAA;AAAA;AAAA,EAKhB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAET,YAAY,MAIT;AACF,UAAM,aAAa,iBAAiB,KAAK,WAAW,KAAK,SAAS;AAGlE,UAAM,iBAAiB;AAEvB,UAAM,cAAc;AAEpB,SAAK,QAAQ,KAAK;AAClB,SAAK,YAAY,KAAK;AACtB,SAAK,YAAY,KAAK;AACtB,SAAK,gBAAgB;AACrB,QAAI,eAAe,QAAW;AAC7B,WAAK,aAAa;AAAA,IACnB;AAEA,WAAO,eAAe,MAAM,uBAAsB,SAAS;AAAA,EAC5D;AACD;AAWO,IAAM,wBAAN,MAAM,+BAA8B,MAAM;AAAA,EAC9B,OAAO;AAAA;AAAA;AAAA;AAAA,EAKhB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAET,YAAY,WAAmB,QAAgB;AAC9C,UAAM,UAAU,WAAW,SAAS,KAAK,MAAM;AAC/C,UAAM,OAAO;AACb,SAAK,YAAY;AACjB,SAAK,SAAS;AACd,WAAO,eAAe,MAAM,uBAAsB,SAAS;AAAA,EAC5D;AACD;AAyBO,SAAS,mBAAmB,OAAe,MAAoB;AACrE,MAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AACjC,UAAM,IAAI,sBAAsB,MAAM,GAAG,IAAI,yBAAyB;AAAA,EACvE;AACA,MAAI,MAAM,SAAS,IAAI;AACtB,UAAM,IAAI;AAAA,MACT;AAAA,MACA,GAAG,IAAI;AAAA,IACR;AAAA,EACD;AACA,MAAI,CAAC,iCAAiC,KAAK,KAAK,GAAG;AAClD,UAAM,IAAI;AAAA,MACT;AAAA,MACA,GAAG,IAAI;AAAA,IACR;AAAA,EACD;AACD;AAEO,IAAM,uBAAN,MAAM,8BAA6B,MAAM;AAAA,EAC7B,OAAO;AAAA;AAAA;AAAA;AAAA,EAKhB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAET,YAAY,WAAmB,KAAa;AAC3C,UAAM,UAAU,UAAU,SAAS,KAAK,GAAG;AAC3C,UAAM,OAAO;AACb,SAAK,YAAY;AACjB,SAAK,MAAM;AACX,WAAO,eAAe,MAAM,sBAAqB,SAAS;AAAA,EAC3D;AACD;AAmBO,IAAM,qBAAN,MAAM,4BAA2B,MAAM;AAAA,EAC3B,OAAO;AAAA;AAAA;AAAA;AAAA,EAKhB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAET,YAAY,MAA2D;AACtE,UAAM,aAAa,iBAAiB,KAAK,WAAW,KAAK,SAAS;AAGlE,UAAM,iBAAiB;AAEvB,UAAM,cAAc;AAEpB,SAAK,YAAY,KAAK;AACtB,SAAK,YAAY,KAAK;AACtB,SAAK,gBAAgB;AACrB,QAAI,eAAe,QAAW;AAC7B,WAAK,aAAa;AAAA,IACnB;AAEA,WAAO,eAAe,MAAM,oBAAmB,SAAS;AAAA,EACzD;AACD;AAoBO,IAAM,sBAAN,MAAM,6BAA4B,MAAM;AAAA,EAC5B,OAAO;AAAA;AAAA;AAAA;AAAA,EAKhB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAET,YAAY,MAIT;AACF,UAAM,aAAa,iBAAiB,KAAK,WAAW,KAAK,SAAS;AAGlE,UAAM,iBAAiB;AAEvB,UAAM,cAAc;AAEpB,SAAK,QAAQ,KAAK;AAClB,SAAK,YAAY,KAAK;AACtB,SAAK,YAAY,KAAK;AACtB,SAAK,gBAAgB;AACrB,QAAI,eAAe,QAAW;AAC7B,WAAK,aAAa;AAAA,IACnB;AAEA,WAAO,eAAe,MAAM,qBAAoB,SAAS;AAAA,EAC1D;AACD;AAoBO,IAAM,gCAAN,MAAM,uCAAsC,MAAM;AAAA,EACtC,OAAO;AAAA;AAAA;AAAA;AAAA,EAKhB;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAET,YAAY,MAAuD;AAClE,UAAM,UACL,oCAAoC,KAAK,YAAY,uBAAuB,KAAK,aAAa;AAAA;AAG/F,UAAM,OAAO;AAEb,SAAK,eAAe,KAAK;AACzB,SAAK,gBAAgB,KAAK;AAE1B,WAAO,eAAe,MAAM,+BAA8B,SAAS;AAAA,EACpE;AACD;AAuBO,IAAM,YAAY;AAAA;AAAA,EAExB,iBAAiB;AAAA;AAAA,EAEjB,WAAW;AAAA;AAAA,EAEX,oBAAoB;AAAA;AAAA,EAEpB,oBAAoB;AAAA;AAAA,EAEpB,mBAAmB;AAAA;AAAA,EAEnB,kBAAkB;AAAA;AAAA,EAElB,iBAAiB;AAAA;AAAA,EAEjB,kBAAkB;AAAA;AAAA,EAElB,4BAA4B;AAC7B;AAiCO,IAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrB,UAAU,MAIsD;AAC/D,UAAM,QAAQ,IAAI,eAAe,IAAI;AACrC,WAAO,OAAO,OAAO,OAAO,EAAE,MAAM,UAAU,gBAAgB,CAAC;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA,EAKA,SACC,OACA,MACuD;AACvD,UAAM,QAAQ,IAAI,cAAc,OAAO,IAAI;AAC3C,WAAO,OAAO,OAAO,OAAO,EAAE,MAAM,UAAU,UAAU,CAAC;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,kBACC,aACA,aACA,SACyE;AACzE,UAAM,QAAQ,IAAI,uBAAuB,aAAa,aAAa,OAAO;AAC1E,WAAO,OAAO,OAAO,OAAO,EAAE,MAAM,UAAU,mBAAmB,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,MAIyD;AACzE,UAAM,QAAQ,IAAI,sBAAsB,IAAI;AAC5C,WAAO,OAAO,OAAO,OAAO,EAAE,MAAM,UAAU,mBAAmB,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKA,iBACC,WACA,QACuE;AACvE,UAAM,QAAQ,IAAI,sBAAsB,WAAW,MAAM;AACzD,WAAO,OAAO,OAAO,OAAO,EAAE,MAAM,UAAU,kBAAkB,CAAC;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA,EAKA,gBACC,WACA,KACqE;AACrE,UAAM,QAAQ,IAAI,qBAAqB,WAAW,GAAG;AACrD,WAAO,OAAO,OAAO,OAAO,EAAE,MAAM,UAAU,iBAAiB,CAAC;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,MAGsD;AACnE,UAAM,QAAQ,IAAI,mBAAmB,IAAI;AACzC,WAAO,OAAO,OAAO,OAAO,EAAE,MAAM,UAAU,gBAAgB,CAAC;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,MAIuD;AACrE,UAAM,QAAQ,IAAI,oBAAoB,IAAI;AAC1C,WAAO,OAAO,OAAO,OAAO,EAAE,MAAM,UAAU,iBAAiB,CAAC;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,OAAyC;AACpD,WAAO,iBAAiB;AAAA,EACzB;AAAA;AAAA,EAGA,WAAW,OAAwC;AAClD,WAAO,iBAAiB;AAAA,EACzB;AAAA;AAAA,EAGA,oBAAoB,OAAiD;AACpE,WAAO,iBAAiB;AAAA,EACzB;AAAA;AAAA,EAGA,mBAAmB,OAAgD;AAClE,WAAO,iBAAiB;AAAA,EACzB;AAAA;AAAA,EAGA,mBAAmB,OAAgD;AAClE,WAAO,iBAAiB;AAAA,EACzB;AAAA;AAAA,EAGA,kBAAkB,OAA+C;AAChE,WAAO,iBAAiB;AAAA,EACzB;AAAA;AAAA,EAGA,gBAAgB,OAA6C;AAC5D,WAAO,iBAAiB;AAAA,EACzB;AAAA;AAAA,EAGA,iBAAiB,OAA8C;AAC9D,WAAO,iBAAiB;AAAA,EACzB;AAAA;AAAA,EAGA,2BACC,OACyC;AACzC,WAAO,iBAAiB;AAAA,EACzB;AAAA;AAAA,EAGA,YACC,OAUgC;AAChC,WACC,iBAAiB,kBACjB,iBAAiB,iBACjB,iBAAiB,0BACjB,iBAAiB,yBACjB,iBAAiB,yBACjB,iBAAiB,wBACjB,iBAAiB,sBACjB,iBAAiB,uBACjB,iBAAiB;AAAA,EAEnB;AAAA;AAAA,EAGA,QAAQ,OAAsD;AAC7D,WACC,iBAAiB,SACjB,UAAU,SACV,OAAQ,MAAoC,SAAS,YACpD,MAAmC,KAAK,WAAW,QAAQ;AAAA,EAE9D;AACD;;;AC5tBO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACC,aACA,aACA,SACC;AACD;AAAA,MACC,4BAA4B,WAAW,SAAS,WAAW,mCAC1B,QAAQ,KAAK,IAAI,CAAC;AAAA,IACpD;AACA,SAAK,OAAO;AACZ,SAAK,cAAc;AACnB,SAAK,cAAc;AACnB,SAAK,UAAU;AAAA,EAChB;AACD;AAMO,IAAM,8BAAN,cAA0C,MAAM;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACC,SACA,aACA,kBACA,iBACC;AACD;AAAA,MACC,kBAAkB,OAAO,qBAAqB,eAAe,oBAC1C,YAAY,KAAK,IAAI,CAAC,0BACjB,iBAAiB,KAAK,IAAI,CAAC;AAAA,IACpD;AACA,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,cAAc;AACnB,SAAK,mBAAmB;AACxB,SAAK,kBAAkB;AAAA,EACxB;AACD;AAUA,SAAS,mBAAmB,QAA4C;AACvE,QAAM,UAAoB,CAAC;AAG3B,UAAQ,SAAK,mCAAe,OAAO,MAAM,UAAU,CAAC;AAGpD,MAAI,OAAO,MAAM,QAAQ;AACxB,YAAQ,KAAK,GAAG,OAAO,MAAM,MAAM;AAAA,EACpC;AAGA,MAAI,OAAO,OAAO,OAAO;AACxB,YAAQ,KAAK,OAAO;AAAA,EACrB;AACA,MAAI,OAAO,OAAO,MAAM;AACvB,YAAQ,KAAK,MAAM;AAAA,EACpB;AAEA,SAAO,OAAO,OAAO,OAAO;AAC7B;AAMA,SAAS,wBAAwB,QAA4C;AAC5E,QAAM,UAAoB,CAAC;AAG3B,UAAQ,SAAK,mCAAe,OAAO,MAAM,UAAU,CAAC;AAGpD,MAAI,OAAO,MAAM,QAAQ;AACxB,YAAQ,KAAK,GAAG,OAAO,MAAM,MAAM;AAAA,EACpC;AAGA,MAAI,OAAO,OAAO,OAAO;AACxB,YAAQ,KAAK,OAAO;AAAA,EACrB;AACA,MAAI,OAAO,OAAO,MAAM;AACvB,YAAQ,KAAK,MAAM;AAAA,EACpB;AAEA,SAAO,OAAO,OAAO,OAAO;AAC7B;AAMO,SAAS,uBAAuB,QAA+B;AACrE,QAAM,cAAc,mBAAmB,MAAM;AAC7C,QAAM,mBAAmB,wBAAwB,MAAM;AAGvD,MAAI,YAAY,WAAW,iBAAiB,QAAQ;AACnD,UAAM,IAAI;AAAA,MACT,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,mCAAmC,YAAY,MAAM,mBAAmB,iBAAiB,MAAM;AAAA,IAChG;AAAA,EACD;AAGA,WAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC5C,QAAI,YAAY,CAAC,MAAM,iBAAiB,CAAC,GAAG;AAC3C,YAAM,IAAI;AAAA,QACT,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA,UAAU,CAAC,6BAA6B,YAAY,CAAC,CAAC,qBAAqB,iBAAiB,CAAC,CAAC;AAAA,MAC/F;AAAA,IACD;AAAA,EACD;AACD;AAuBO,SAAS,KACf,QACA,OACA,UAAuB,CAAC,GACX;AACb,QAAM,YAAY,YAAY,IAAI;AAElC,QAAM,QAAsB;AAAA,IAC3B,WAAW,CAAC;AAAA,IACZ,UAAU,CAAC;AAAA,IACX,MAAM,CAAC;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,MACjB,mBAAmB;AAAA,MACnB,aAAa;AAAA,MACb,oBAAoB;AAAA,MACpB,kBAAkB;AAAA,MAClB,WAAW;AAAA,MACX,iBAAiB;AAAA,MACjB,uBAAuB;AAAA,IACxB;AAAA,IACA,sBAAsB,oBAAI,IAAI;AAAA,IAC9B,iBAAiB,oBAAI,IAAI;AAAA,EAC1B;AAEA,QAAM,OAA8B;AAAA,IACnC,qBAAqB,QAAQ;AAAA,IAC7B,eAAe,QAAQ;AAAA,IACvB,YAAY,QAAQ,cAAc;AAAA,IAClC,cAAc,QAAQ,gBAAgB;AAAA,IACtC,iBAAiB,QAAQ,mBAAmB;AAAA,IAC5C,cAAc,QAAQ,gBAAgB,CAAC;AAAA,IACvC,wBAAwB,QAAQ,0BAA0B;AAAA,IAC1D,qBAAqB,QAAQ;AAAA,EAC9B;AAIA,QAAM,YAAY,OAAO,oBACtB,OACA,MAAM,SAAS,OAAO,IAAI;AAC7B,MAAI,CAAC,OAAO,qBAAqB,CAAC,WAAW;AAC5C,UAAM,IAAI,MAAM,kBAAkB,OAAO,IAAI,EAAE;AAAA,EAChD;AAGA,QAAM,iBAAiB,OAAO,QAC3B,mBAAmB,OAAO,OAAO,OAAO,MAAM,KAAK,IACnD;AAGH,MAAI,gBAAgB;AACnB,iBAAa,gBAAgB,OAAO,MAAM,OAAO,OAAO,MAAM,OAAO;AAAA,EACtE;AAGA,MAAI,OAAO,SAAS;AACnB,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,KAAK;AAC/C,YAAM,MAAM,OAAO,QAAQ,CAAC;AAC5B,UAAI,KAAK;AACR;AAAA,UACC;AAAA,UACA,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW,CAAC;AAAA,UACZ;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAGA,MAAI,KAAK,YAAY;AACpB,gBAAY,OAAO,KAAK,YAAY;AAAA,EACrC;AAGA,oBAAkB,QAAQ,KAAK;AAE/B,QAAM,iBAAiB,YAAY,IAAI,IAAI;AAI3C,QAAM,oBAAoB,MAAM,UAAU;AAAA,IACzC,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,WAAW;AAAA,EAC/C;AAEA,QAAM,WAAmC,oBACtC,OAAO,OAAO;AAAA,IACd;AAAA,IACA,mBAAmB,MAAM;AAAA,IACzB,aAAa;AAAA,IACb,kBAAkB,kBAAkB;AAAA,EACrC,CAAC,IACA,OAAO,OAAO;AAAA,IACd;AAAA,IACA,mBAAmB,MAAM;AAAA,IACzB,aAAa;AAAA,EACd,CAAC;AAEH,QAAM,SAAqB;AAAA,IAC1B,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO,OAAO,MAAM,UAAU,MAAM,CAAC;AAAA,IAChD,UAAU,OAAO,OAAO,MAAM,SAAS,MAAM,CAAC;AAAA,IAC9C,MAAM,OAAO,OAAO,MAAM,KAAK,MAAM,CAAC;AAAA,IACtC;AAAA,IACA;AAAA,EACD;AAEA,SAAO,OAAO,OAAO,MAAM;AAC5B;AAkBO,SAAS,cACf,QACA,OACA,UAAgC,CAAC,GACX;AACtB,QAAM,YAAY,YAAY,IAAI;AAGlC,yBAAuB,MAAM;AAE7B,QAAM,QAAsB;AAAA,IAC3B,WAAW,CAAC;AAAA,IACZ,UAAU,CAAC;AAAA,IACX,MAAM,CAAC;AAAA,IACP,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,MACjB,mBAAmB;AAAA,MACnB,aAAa;AAAA,MACb,oBAAoB;AAAA,MACpB,kBAAkB;AAAA,MAClB,WAAW;AAAA,MACX,iBAAiB;AAAA,MACjB,uBAAuB;AAAA,IACxB;AAAA,IACA,sBAAsB,oBAAI,IAAI;AAAA,IAC9B,iBAAiB,oBAAI,IAAI;AAAA,EAC1B;AAGA,QAAM,aAAa,MAAM,SAAS,OAAO,MAAM,IAAI;AACnD,MAAI,CAAC,YAAY;AAChB,UAAM,IAAI,MAAM,kBAAkB,OAAO,MAAM,IAAI,EAAE;AAAA,EACtD;AAGA,QAAM,gBAAgB,OAAO,UAAU;AAEvC,QAAM,uBAAqC;AAAA,IAC1C,IAAI,mBAAmB,OAAO,eAAe;AAAA,IAC7C,MAAM;AAAA,IACN,SAAS;AAAA,MACR,aAAa,OAAO,MAAM;AAAA,MAC1B,YAAY,aAAa,OAAO,OAAO;AAAA,IACxC;AAAA,IACA,QAAQ;AAAA,IACR,WAAW,2BAA2B,MAAM;AAAA,IAC5C,cAAc,CAAC,kBAAkB,WAAW;AAAA,EAC7C;AACA,QAAM,UAAU,KAAK,oBAAoB;AAGzC,MAAI,oBAAoB;AACxB,MACC,kBAAkB,gBAClB,OAAO,UAAU,SAAS,cACzB;AACD,UAAM,gBAAgB,OAAO;AAC7B,QAAI,cAAc,cAAc,QAAQ;AACvC,0BAAoB;AAEpB,YAAM,cAAc,cAAc,mBAAmB;AACrD,YAAM,WACL,QAAQ,+BACP,gBAAgB,kBAAkB,cAAc;AAElD,YAAM,wBAAsC;AAAA,QAC3C,IAAI,mBAAmB,OAAO,qBAAqB;AAAA,QACnD,MAAM;AAAA,QACN,SAAS;AAAA,UACR,aAAa,OAAO,MAAM;AAAA,UAC1B,QAAQ,cAAc;AAAA,UACtB,YAAY,aAAa,OAAO,OAAO;AAAA,QACxC;AAAA,QACA,QAAQ;AAAA,QACR,WAAW,+BAA+B,aAAa,QAAQ;AAAA,QAC/D,cAAc,CAAC,SAAS,WAAW;AAAA,MACpC;AACA,YAAM,UAAU,KAAK,qBAAqB;AAG1C,UAAI,aAAa,eAAe,gBAAgB,WAAW;AAC1D,cAAM,SAAS,KAAK;AAAA,UACnB,MAAM;AAAA,UACN,SAAS;AAAA,UACT,YAAY;AAAA,QACb,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAGA,MAAI,OAAO,WAAW,GAAG;AACxB,UAAM,IAAI,MAAM,8BAA8B,OAAO,QAAQ,EAAE;AAAA,EAChE;AAEA,MAAI,OAAO,WAAW,KAAK;AAC1B,UAAM,SAAS,KAAK;AAAA,MACnB,MAAM;AAAA,MACN,SAAS,eAAe,OAAO,QAAQ;AAAA,MACvC,YAAY;AAAA,IACb,CAAC;AAAA,EACF;AAEA,QAAM,iBAAiB,YAAY,IAAI,IAAI;AAE3C,QAAM,iBAAiB,OAAO,UAAU;AAGxC,QAAM,SAA8B;AAAA,IACnC,WAAW,OAAO,MAAM;AAAA,IACxB,WAAW,OAAO,OAAO,MAAM,UAAU,MAAM,CAAC;AAAA,IAChD,UAAU,OAAO,OAAO,MAAM,SAAS,MAAM,CAAC;AAAA,IAC9C,MAAM,OAAO,OAAO,MAAM,KAAK,MAAM,CAAC;AAAA,IACtC;AAAA,IACA,UAAU,OAAO,OAAO;AAAA,MACvB;AAAA,MACA,mBAAmB,MAAM;AAAA,MACzB,aAAa;AAAA,MACb,aAAa;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,IACD,CAAC;AAAA,EACF;AAEA,SAAO,OAAO,OAAO,MAAM;AAC5B;AAKA,SAAS,2BAA2B,QAAiC;AACpE,QAAM,QAAkB,CAAC;AAEzB,QAAM;AAAA,IACL,kBAAkB,OAAO,OAAO,WAAW,OAAO,UAAU,IAAI;AAAA,EACjE;AAEA,MAAI,OAAO,UAAU,SAAS,aAAa;AAC1C,UAAM;AAAA,MACL,aAAa,OAAO,UAAU,SAAS,cAAc,OAAO,UAAU,QAAQ;AAAA,IAC/E;AAAA,EACD,WAAW,OAAO,UAAU,SAAS,cAAc;AAClD,UAAM;AAAA,MACL,aAAa,OAAO,UAAU,SAAS,eAAe,OAAO,UAAU,SAAS;AAAA,IACjF;AAAA,EACD;AAEA,QAAM,KAAK,YAAY,OAAO,QAAQ,EAAE;AAExC,MAAI,OAAO,UAAU,OAAO,WAAW,QAAQ;AAC9C,UAAM,KAAK,UAAU,OAAO,MAAM,EAAE;AAAA,EACrC;AAEA,SAAO,MAAM,KAAK,IAAI;AACvB;AAKA,SAAS,+BACR,aACA,UACS;AACT,MAAI,gBAAgB,iBAAiB;AACpC,WAAO,aAAa,cACjB,sFACA;AAAA,EACJ;AACA,SAAO,aAAa,UACjB,2EACA;AACJ;AA+BA,SAAS,oCACR,cACA,aACA,OACU;AACV,QAAM,MAAM,MAAM,YAAY,GAAG,WAAW,IAAI,aAAa,QAAQ,EAAE;AACvE,MAAI,CAAC,IAAK,QAAO;AAEjB,QAAM,KACL,OAAO,IAAI,eAAe,WAAW,IAAI,aAAa,IAAI,aAAa,CAAC;AACzE,MAAI,CAAC,GAAI,QAAO;AAEhB,QAAM,gBAAgB,MAAM,SAAS,IAAI,MAAM;AAC/C,MAAI,CAAC,cAAe,QAAO;AAE3B,QAAM,SAAS,cAAc,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE;AAC9D,MAAI,CAAC,OAAQ,QAAO;AAEpB,SAAO,CAAC,OAAO;AAChB;AAEA,SAAS,mBACR,OACA,aACA,OACc;AACd,UAAQ,MAAM,MAAM;AAAA,IACnB,KAAK,MAAM;AACV,YAAM,UAAU;AAChB,UAAI,CAAC,QAAQ,SAAU,QAAO;AAG9B,YAAM,YAAY,QAAQ,SAAS;AACnC,UAAI,CAAC,aAAa,UAAU,SAAS,SAAU,QAAO;AACtD,YAAM,SAAS,YAAY,YAAY,UAAU,SAAS;AAC1D,UAAI,CAAC,UAAU,OAAO,WAAW,EAAG,QAAO;AAC3C,YAAM,YAAY,OAAO,CAAC;AAC1B,UAAI,CAAC,UAAW,QAAO;AAIvB,YAAM,gBAAgB,MAAM,iBAAiB,WAAW;AACxD,YAAM,gBAAgB,MAAM,SAAS,WAAW;AAGhD,YAAM,WACL,OAAO,eAAe,eAAe,WAClC,cAAc,aACb,eAAe,aAAa,CAAC,KAAK;AAEvC,UAAI;AAEJ,iBAAW,OAAO,eAAe;AAChC,YAAI,IAAI,WAAW,QAAQ,SAAS,KAAM;AAC1C,cAAM,KACL,OAAO,IAAI,eAAe,WACvB,IAAI,aACJ,IAAI,aAAa,CAAC;AAItB,YACC,IAAI,SAAS,aACb,OAAO,aACP,QAAQ,UAAU,UACjB;AACD,4BAAkB,IAAI;AACtB;AAAA,QACD;AAAA,MACD;AAEA,UAAI,CAAC,gBAAiB,QAAO;AAG7B,YAAM,cAAiC;AAAA,QACtC,MAAM;AAAA,QACN,UAAU;AAAA;AAAA,QAEV,GAAI,QAAQ,SAAS,SAAS,EAAE,OAAO,QAAQ,SAAS,MAAM;AAAA,MAC/D;AAEA,aAAO;AAAA,IACR;AAAA,IAEA,KAAK,OAAO;AACX,YAAM,WAAW;AACjB,YAAM,YAAY,SAAS,WAAW;AAAA,QAAI,CAAC,MAC1C,mBAAmB,GAAG,aAAa,KAAK;AAAA,MACzC;AACA,UAAI,UAAU,MAAM,CAAC,GAAG,MAAM,MAAM,SAAS,WAAW,CAAC,CAAC,EAAG,QAAO;AACpE,aAAO,EAAE,MAAM,OAAO,YAAY,UAAU;AAAA,IAC7C;AAAA,IAEA,KAAK,MAAM;AACV,YAAM,UAAU;AAChB,YAAM,YAAY,QAAQ,WAAW;AAAA,QAAI,CAAC,MACzC,mBAAmB,GAAG,aAAa,KAAK;AAAA,MACzC;AACA,UAAI,UAAU,MAAM,CAAC,GAAG,MAAM,MAAM,QAAQ,WAAW,CAAC,CAAC,EAAG,QAAO;AACnE,aAAO,EAAE,MAAM,MAAM,YAAY,UAAU;AAAA,IAC5C;AAAA,IAEA,KAAK,OAAO;AACX,YAAM,WAAW;AACjB,YAAM,YAAY;AAAA,QACjB,SAAS;AAAA,QACT;AAAA,QACA;AAAA,MACD;AACA,UAAI,cAAc,SAAS,UAAW,QAAO;AAO7C,UAAI,UAAU,SAAS,UAAU;AAChC,YACC,CAAC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD,GACC;AAED,iBAAO;AAAA,QACR;AACA,eAAO;AAAA,UACN,GAAG;AAAA,UACH,MAAM;AAAA,QACP;AAAA,MACD;AACA,aAAO,EAAE,MAAM,OAAO,WAAW,UAAU;AAAA,IAC5C;AAAA,IAEA;AACC,aAAO;AAAA,EACT;AACD;AAMA,SAAS,aACR,OACA,aACA,OACA,OACA,MACA,YACO;AACP,UAAQ,MAAM,MAAM;AAAA,IACnB,KAAK;AAAA,IACL,KAAK;AACJ;AAAA,QACC,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAG,UAAU,IAAI,MAAM,IAAI;AAAA,QAC3B,MAAM;AAAA,MACP;AACA;AAAA,IAED,KAAK;AACJ;AAAA,QACC,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAG,UAAU;AAAA,QACb,MAAM;AAAA,QACN,MAAM;AAAA,MACP;AACA;AAAA,IAED,KAAK;AACJ,eAAS,IAAI,GAAG,IAAI,MAAM,WAAW,QAAQ,KAAK;AACjD,cAAM,OAAO,MAAM,WAAW,CAAC;AAC/B,YAAI,MAAM;AACT;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,GAAG,UAAU,QAAQ,CAAC;AAAA,UACvB;AAAA,QACD;AAAA,MACD;AACA;AAAA,IAED,KAAK;AACJ,eAAS,IAAI,GAAG,IAAI,MAAM,WAAW,QAAQ,KAAK;AACjD,cAAM,OAAO,MAAM,WAAW,CAAC;AAC/B,YAAI,MAAM;AACT;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,GAAG,UAAU,OAAO,CAAC;AAAA,UACtB;AAAA,QACD;AAAA,MACD;AACA;AAAA,IAED,KAAK;AACJ;AAAA,QACC,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAG,UAAU;AAAA,MACd;AACA;AAAA;AAAA,IAGD,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAEJ;AAAA,IAED,KAAK;AACJ;AAAA,EACF;AACD;AAEA,SAAS,sBACR,cACA,aACA,OACA,OACA,MACA,YACA,aACA,MACO;AACP,QAAM;AAGN,QAAM,YAAY,MAAM,QAAQ,YAAY,IAAI,eAAe,CAAC,YAAY;AAG5E,MAAI,gBAAgB;AACpB,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AAC1C,UAAM,eAAe,UAAU,CAAC;AAChC,QAAI,CAAC,aAAc;AAEnB,UAAM,gBAAgB,MAAM,UAAU,SAAS;AAC/C,UAAM,YAAY,GAAG,UAAU,IAAI,CAAC;AAGpC,UAAM,WAAW;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAEA,QAAI,CAAC,UAAU;AACd;AAAA,IACD;AAGA,UAAM,UAAU,GAAG,aAAa,IAAI,SAAS,IAAI;AACjD,UAAM,QAAQ,MAAM,qBAAqB,IAAI,OAAO,KAAK,CAAC;AAC1D,UAAM,KAAK,SAAS;AACpB,UAAM,qBAAqB,IAAI,SAAS,KAAK;AAG7C,QAAI,eAAe;AAClB,YAAM,iBAAiB;AAAA,QACtB;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MACT;AAEA,YAAM,aAAa,mBAAmB,OAAO,iBAAiB;AAE9D,YAAM,YAAY,SAAS,WAAW,SAAS;AAE/C,YAAM,UAAmC;AAAA,QACxC,aAAa;AAAA,QACb,QAAQ,SAAS;AAAA,QACjB,UAAU,SAAS;AAAA,QACnB,YAAY;AAAA,QACZ,GAAI,UAAU,SAAS,KAAK,EAAE,cAAc,UAAU,KAAK,GAAG,EAAE;AAAA,QAChE,GAAI,aAAa,EAAE,UAAU;AAAA,MAC9B;AACA,YAAM,UAAU,KAAK;AAAA,QACpB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN;AAAA,QACA,QAAQ;AAAA,QACR,WAAW;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,QACA,cAAc,mBAAmB,WAAW,CAAC,MAAM,IAAI,CAAC,QAAQ;AAAA,MACjE,CAAC;AAGD,UAAI,mBAAmB,UAAU,SAAS,gBAAgB,QAAQ;AACjE,cAAM,SAAS,KAAK;AAAA,UACnB,MAAM;AAAA,UACN,SAAS,mCAAmC,SAAS,IAAI;AAAA,UACzD,YAAY,gDAAgD,SAAS,IAAI;AAAA,UACzE,iBAAiB;AAAA,QAClB,CAAC;AAAA,MACF;AAGA,UAAI,aAAa;AAChB;AAAA,UACC;AAAA,UACA,SAAS;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA,GAAG,UAAU;AAAA,QACd;AAAA,MACD;AAAA,IACD;AAGA,oBAAgB,SAAS;AAAA,EAC1B;AACD;AAMA,SAAS,eACR,SACA,aACA,OACA,OACA,MACA,YACA,OACA,qBAAqB,OACd;AACP,QAAM;AAGN,MAAI,QAAQ,KAAK,iBAAiB;AACjC,UAAM,SAAS,KAAK;AAAA,MACnB,MAAM;AAAA,MACN,SAAS,iBAAiB,KAAK,oBAAoB,KAAK,eAAe;AAAA,MACvE,YAAY;AAAA,IACb,CAAC;AAAA,EACF;AAGA,QAAM,eAAe,QAAQ,OAAO,QAAQ;AAG5C,QAAM,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EACT;AAEA,MAAI,CAAC,UAAU;AACd;AAAA,EACD;AAGA,QAAM,cAAc,GAAG,WAAW,IAAI,SAAS,IAAI;AACnD,MAAI,MAAM,gBAAgB,IAAI,WAAW,GAAG;AAC3C,UAAM,SAAS,KAAK;AAAA,MACnB,MAAM;AAAA,MACN,SAAS,8BAA8B,WAAW;AAAA,MAClD,YAAY;AAAA,IACb,CAAC;AACD;AAAA,EACD;AACA,QAAM,gBAAgB,IAAI,WAAW;AAGrC,QAAM,eAAe,GAAG,WAAW,IAAI,SAAS,IAAI;AACpD,QAAM,QAAQ,MAAM,qBAAqB,IAAI,YAAY,KAAK,CAAC;AAC/D,QAAM,KAAK,UAAU;AACrB,QAAM,qBAAqB,IAAI,cAAc,KAAK;AAGlD,QAAM,sBACJ,CAAC,CAAC,QAAQ,aAAa,CAAC,CAAC,SAAS,cACnC,SAAS,WAAW,SAAS;AAI9B,MAAI;AACJ,MAAI,oBAAoB;AAMvB,QAAI,KAAK,qBAAqB,yBAAyB,OAAO;AAC7D,YAAM,IAAI;AAAA,QACT,oFACqB,KAAK,oBAAoB,IAAI;AAAA,MACnD;AAAA,IACD;AACA,sBAAkB;AAAA,EACnB,WAAW,QAAQ,SAAS,QAAW;AAEtC,QAAI,QAAQ,SAAS,MAAM;AAC1B,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MAGD;AAAA,IACD;AACA,sBAAkB;AAAA,EACnB,WAAW,QAAQ,aAAa,QAAQ;AAIvC,UAAM,eAAe,QAAQ,SAAS,QAAQ,eAAe,OAAO;AACpE,sBAAkB;AAAA,MACjB;AAAA,MACA,KAAK;AAAA,MACL;AAAA;AAAA,MACoB;AAAA;AAAA,MACL;AAAA,IAChB;AAAA,EACD,OAAO;AACN,sBAAkB,yBAAyB,UAAU,IAAI;AAMzD,QAAI,QAAQ,SAAS,QAAQ,oBAAoB,QAAQ;AACxD,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MAGD;AAAA,IACD;AAAA,EACD;AAOA,QAAM,eAAe,kBAAkB,UAAU,MAAM,CAAC,CAAC,QAAQ,KAAK;AACtE,QAAM,mBACL,sBAAsB,QAAQ,SAAS,SAAY,SAAS;AAC7D,QAAM,mBACL,oBAAoB,SAAU,QAAQ,QAAQ,mBAAoB;AAEnE,QAAM,oBAAoB,mBAAmB,OAAO,kBAAkB;AAEtE,QAAM,UAAU,KAAK;AAAA,IACpB,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,MACR;AAAA,MACA,QAAQ,SAAS;AAAA,MACjB,UAAU,SAAS;AAAA,MACnB,cAAc,SAAS;AAAA,MACvB,cAAc,QAAQ;AAAA,MACtB;AAAA;AAAA,MAEA,GAAI,SAAS,eAAe,UAAa;AAAA,QACxC,YAAY,SAAS;AAAA,MACtB;AAAA,IACD;AAAA,IACA,QAAQ;AAAA;AAAA,IAER,GAAI,qBAAqB,UAAa,EAAE,UAAU,iBAAiB;AAAA,IACnE,WAAW,qBACR,mDAAmD,SAAS,IAAI,iCAChE,yBAAyB,UAAU,eAAe;AAAA,IACrD,cAAc;AAAA,MACb;AAAA,MACA,KAAK;AAAA,IACN;AAAA,EACD,CAAC;AAGD,MAAI,QAAQ,aAAa,CAAC,oBAAoB;AAC7C,UAAM,SAAS,KAAK;AAAA,MACnB,MAAM;AAAA,MACN,SAAS,wBAAwB,SAAS,IAAI,uDAAuD,SAAS,MAAM,YAAY,SAAS,MAAM;AAAA,MAC/I,YAAY;AAAA,IACb,CAAC;AAAA,EACF;AAGA,MAAI,oBAAoB,OAAO;AAC9B,UAAM,UAAU,OAAO,WAAW,IAAI,SAAS,IAAI;AAEnD,UAAM,cAAc,MAAM,KAAK,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO;AAC7D,QAAI,CAAC,aAAa;AACjB,YAAM,KAAK,KAAK;AAAA,QACf,MAAM;AAAA,QACN,SAAS,qBACN,2CAA2C,SAAS,IAAI,MACxD,YAAY,SAAS,IAAI;AAAA,QAC5B,cAAc,CAAC,UAAU;AAAA,QACzB,cAAc,GAAG,WAAW,IAAI,SAAS,IAAI;AAAA,QAC7C,WAAW;AAAA,MACZ,CAAC;AAAA,IACF,OAAO;AAEN,MAAC,YAAY,aAA0B,KAAK,UAAU;AAAA,IACvD;AAAA,EACD;AAGA,MAAI,oBAAoB,UAAU,qBAAqB,QAAW;AACjE,UAAM,iBAAiB,mBAAmB,OAAO,WAAW;AAE5D,UAAM,UAAU,KAAK;AAAA,MACpB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,QACR;AAAA,QACA,QAAQ,SAAS;AAAA,QACjB,UAAU,SAAS;AAAA,QACnB;AAAA,MACD;AAAA,MACA,QAAQ;AAAA,MACR,WAAW;AAAA,QACV;AAAA,QACA;AAAA,QACA,CAAC,CAAC,QAAQ;AAAA,MACX;AAAA,MACA,cAAc,qBAAqB,SAAS,CAAC,OAAO,IAAI,CAAC,MAAM;AAAA,IAChE,CAAC;AAAA,EACF;AAGA,MAAI,QAAQ,OAAO;AAClB;AAAA,MACC,QAAQ;AAAA,MACR,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG,UAAU;AAAA,IACd;AAAA,EACD;AAGA,MAAI,QAAQ,SAAS;AAMpB,UAAM,yBAAyB,qBAAqB;AACpD,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,QAAQ,KAAK;AAChD,YAAM,YAAY,QAAQ,QAAQ,CAAC;AACnC,UAAI,WAAW;AACd;AAAA,UACC;AAAA,UACA,SAAS;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA,GAAG,UAAU,YAAY,CAAC;AAAA,UAC1B,QAAQ;AAAA,UACR;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAGA,QAAM,gBAAgB,OAAO,WAAW;AACzC;AAMA,SAAS,qBACR,cACA,aACA,OACA,OACA,MACA,aACA,SACyB;AAEzB,QAAM,iBAAiB,MAAM,YAAY,GAAG,WAAW,IAAI,YAAY,EAAE;AACzE,MAAI,gBAAgB;AACnB,WAAO;AAAA,EACR;AAGA,QAAM,oBAAoB,MACxB,iBAAiB,WAAW,EAC5B,OAAO,CAAC,MAAM,EAAE,WAAW,YAAY;AAEzC,MAAI,kBAAkB,WAAW,GAAG;AAGnC,QAAI,iBAAiB,eAAe,iBAAiB,eAAe;AACnE,YAAM,2BAA2B,MAC/B,iBAAiB,WAAW,EAC5B,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM;AACrC,UAAI,yBAAyB,SAAS,GAAG;AAGxC,eAAO,yBAAyB,CAAC;AAAA,MAClC;AAAA,IACD;AAGA,UAAM,SAAS,KAAK;AAAA,MACnB,MAAM;AAAA,MACN,SAAS,qBAAqB,YAAY,iBAAiB,WAAW;AAAA,MACtE,YAAY;AAAA,IACb,CAAC;AACD,WAAO;AAAA,EACR;AAEA,MAAI,kBAAkB,WAAW,GAAG;AAEnC,WAAO,kBAAkB,CAAC;AAAA,EAC3B;AAGA,QAAM,UAAU,kBAAkB,IAAI,CAAC,MAAM,EAAE,IAAI;AAGnD,MAAI,SAAS;AACZ,UAAM,WAAW,kBAAkB,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO;AACjE,QAAI,UAAU;AACb,aAAO;AAAA,IACR;AAAA,EACD;AAGA,QAAM,kBAAkB,GAAG,WAAW,IAAI,YAAY;AACtD,QAAM,gBAAgB,KAAK,aAAa,eAAe;AACvD,MAAI,eAAe;AAClB,UAAM,WAAW,kBAAkB,KAAK,CAAC,MAAM,EAAE,SAAS,aAAa;AACvE,QAAI,UAAU;AACb,aAAO;AAAA,IACR;AAAA,EACD;AAGA,QAAM,IAAI,mBAAmB,aAAa,cAAc,OAAO;AAChE;AAMA,SAAS,wBACR,UACA,MACA,OACoB;AAEpB,MAAI,KAAK,qBAAqB;AAC7B,WAAO,KAAK;AAAA,EACb;AAGA,MAAI,SAAS,mBAAmB,QAAQ;AACvC,WAAO,SAAS;AAAA,EACjB;AAGA,MAAI,SAAS,gBAAgB,OAAO;AACnC,WAAO;AAAA,EACR;AAIA,SAAO;AACR;AAoBA,SAAS,yBACR,UACA,MACA,cAAc,OACY;AAC1B,QAAM,eAAe,KAAK;AAG1B,QAAM,mBAAmB,CACxB,aAC6B;AAC7B,QAAI,aAAa,QAAQ;AAExB,aAAO;AAAA,IACR;AAGA,QAAI,cAAc;AACjB,UAAI,aAAa,aAAa,CAAC,aAAa,qBAAqB;AAChE,cAAM,IAAI;AAAA,UACT,0CAA0C,aAAa,IAAI;AAAA,QAE5D;AAAA,MACD;AACA,UAAI,aAAa,cAAc,CAAC,aAAa,iBAAiB;AAC7D,cAAM,IAAI;AAAA,UACT,2CAA2C,aAAa,IAAI;AAAA,QAE7D;AAAA,MACD;AACA,UAAI,aAAa,SAAS,CAAC,aAAa,sBAAsB;AAC7D,cAAM,IAAI;AAAA,UACT,sCAAsC,aAAa,IAAI;AAAA,QAExD;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAGA,MAAI,SAAS,oBAAoB,QAAQ;AACxC,WAAO,iBAAiB,SAAS,eAAe;AAAA,EACjD;AAGA,MAAI,KAAK,0BAA0B,KAAK,2BAA2B,QAAQ;AAC1E,WAAO,iBAAiB,KAAK,sBAAsB;AAAA,EACpD;AAGA,SAAO,oBAAoB,UAAU,cAAc,WAAW;AAC/D;AAMA,SAAS,eAAe,SAAiC;AACxD,MAAI,CAAC,QAAQ,WAAW,QAAQ,QAAQ,WAAW,EAAG,QAAO;AAC7D,aAAW,SAAS,QAAQ,SAAS;AACpC,QAAI,MAAM,SAAS,KAAM,QAAO;AAChC,QAAI,eAAe,KAAK,EAAG,QAAO;AAAA,EACnC;AACA,SAAO;AACR;AAaA,SAAS,oBACR,WACA,cACA,aACA,gBAAgB,OAChB,WAAW,OACe;AAE1B,MAAI,aAAa;AAChB,QAAI,cAAc,yBAAyB,OAAO;AACjD,aAAO;AAAA,IACR;AAEA,WAAO;AAAA,EACR;AAUA,MAAI,cAAc,mBAAmB,CAAC,eAAe;AACpD,WAAO;AAAA,EACR;AAGA,MAAI,YAAY,cAAc,qBAAqB;AAClD,WAAO;AAAA,EACR;AAIA,SAAO;AACR;AAKO,IAAM,2BAAN,cAAuC,MAAM;AAAA,EACnD,YAAY,SAAiB;AAC5B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACb;AACD;AAKA,SAAS,yBACR,UACA,cACW;AACX,QAAM,gBAA2C;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAGA,SAAO,cAAc,OAAO,CAAC,MAAM;AAClC,QAAI,MAAM,SAAU,QAAO;AAC3B,QAAI,CAAC,aAAc,QAAO,MAAM,UAAU,MAAM;AAChD,QAAI,MAAM,aAAa,CAAC,aAAa,oBAAqB,QAAO;AACjE,QAAI,MAAM,cAAc,CAAC,aAAa,gBAAiB,QAAO;AAC9D,QAAI,MAAM,SAAS,CAAC,aAAa,qBAAsB,QAAO;AAC9D,WAAO;AAAA,EACR,CAAC;AACF;AAEA,SAAS,kBACR,UACA,MACA,WACmB;AAEnB,MAAI,KAAK,eAAe;AACvB,WAAO,KAAK;AAAA,EACb;AAGA,MAAI,SAAS,gBAAgB,QAAQ;AACpC,WAAO,SAAS;AAAA,EACjB;AAGA,MAAI,SAAS,gBAAgB,YAAY;AACxC,WAAO;AAAA,EACR;AAGA,MAAI,WAAW;AACd,WAAO;AAAA,EACR;AAGA,SAAO;AACR;AAUA,SAAS,kBAAkB,QAAqB,OAA2B;AAE1E,MACC,OAAO,UACP,UAAU,OAAO,UACjB,OAAO,OAAO,SAAS,eACtB;AACD,eAAWC,QAAO,OAAO,OAAO,SAAS;AAExC,cAAI,oCAAgBA,IAAG,GAAG;AACzB,cAAM,SAAS,KAAK;AAAA,UACnB,MAAM;AAAA,UACN,SAAS,iCAAiCA,KAAI,GAAG,aAAaA,KAAI,EAAE;AAAA,UACpE,YACC;AAAA,QAEF,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AACD;AAMA,SAAS,YAAY,OAAqB,WAAyB;AAGlE,QAAM,0BAA0B,oBAAI,IAA0B;AAC9D,aAAW,KAAK,MAAM,WAAW;AAChC,QAAI,EAAE,SAAS,oBAAoB;AAClC,YAAM,IAAI,GAAG,EAAE,SAAS,eAAe,EAAE,IAAI,EAAE,SAAS,YAAY,EAAE;AAEtE,UAAI,CAAC,wBAAwB,IAAI,CAAC,GAAG;AACpC,gCAAwB,IAAI,GAAG,CAAC;AAAA,MACjC;AAAA,IACD;AAAA,EACD;AACA,QAAM,aAAa,IAAI,IAAI,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAExD,aAAW,CAAC,cAAc,WAAW,KAAK,MAAM,sBAAsB;AACrE,QAAI,YAAY,UAAU,WAAW;AACpC,YAAM,QAAQ,aAAa,MAAM,GAAG;AACpC,YAAM,QAAQ,MAAM,CAAC,KAAK;AAC1B,YAAM,WAAW,MAAM,CAAC,KAAK;AAC7B,YAAM,UAAU,OAAO,KAAK,IAAI,QAAQ;AAKxC,YAAM,0BAA0B,wBAAwB;AAAA,QACvD,GAAG,KAAK,IAAI,QAAQ;AAAA,MACrB;AACA,UAAI,yBAAyB,WAAW,YAAY;AAEnD;AAAA,MACD;AAGA,UAAI,WAAW,IAAI,OAAO,GAAG;AAC5B;AAAA,MACD;AAEA,YAAM,KAAK,KAAK;AAAA,QACf,MAAM;AAAA,QACN,SAAS,GAAG,QAAQ,sBAAsB,YAAY,MAAM;AAAA,QAC5D,cAAc,OAAO,OAAO,YAAY,MAAM,CAAC;AAAA,QAC/C,cAAc;AAAA,MACf,CAAC;AAED,YAAM,aAAa,mBAAmB,OAAO,gBAAgB;AAC7D,YAAM,UAAU,KAAK;AAAA,QACpB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,UACR,aAAa;AAAA,UACb;AAAA,QACD;AAAA,QACA,QAAQ;AAAA,QACR,WAAW,cAAc,YAAY,YAAY,OAAO,4BAA4B,YAAY,MAAM,sBAAsB,SAAS;AAAA,QACrI,cAAc,CAAC,QAAQ;AAAA,MACxB,CAAC;AAAA,IACF;AAAA,EACD;AACD;AAMA,SAAS,mBAAmB,OAAqB,MAA4B;AAC5E,QAAM,iBAAiB,IAAI;AAC3B,QAAM,UAAU,MAAM,iBAAiB,IAAI,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AACvE,SAAO,GAAG,KAAK,QAAQ,KAAK,EAAE,CAAC,IAAI,OAAO;AAC3C;AAEA,SAAS,wBACR,UACA,UACA,MACA,WACS;AACT,QAAM,WAAW,OAAO,WAAW,IAAI,MAAM;AAC7C,QAAM,cAAc,YAAY,wBAAwB;AAExD,MAAI,aAAa,UAAU;AAC1B,WACC,YAAY,SAAS,MAAM,IAAI,SAAS,IAAI,qBAAqB,SAAS,WAAW,IAAI,QAAQ,GAAG,WAAW;AAAA,EAGjH;AAEA,SACC,YAAY,SAAS,MAAM,IAAI,SAAS,IAAI,qBAAqB,SAAS,WAAW,IAAI,QAAQ,GAAG,WAAW;AAGjH;AAEA,SAAS,yBACR,UACA,UACS;AACT,QAAM,SAAS,YAAY,SAAS,MAAM,IAAI,SAAS,IAAI,KAAK,SAAS,IAAI,kBAAkB,SAAS,WAAW;AAEnH,UAAQ,UAAU;AAAA,IACjB,KAAK;AACJ,aAAO,GAAG,MAAM;AAAA,IACjB,KAAK;AACJ,aAAO,GAAG,MAAM;AAAA,IACjB,KAAK;AACJ,aAAO,GAAG,MAAM;AAAA,IACjB,KAAK;AACJ,aAAO,GAAG,MAAM;AAAA,IACjB,KAAK;AACJ,aAAO,GAAG,MAAM;AAAA,EAClB;AACD;AAEA,SAAS,sBACR,UACA,UACA,YACS;AACT,MAAI,aAAa,SAAS;AACzB,QAAI,SAAS,gBAAgB,YAAY;AACxC,aACC,YAAY,SAAS,MAAM,IAAI,SAAS,IAAI;AAAA,IAG9C;AACA,WACC,YAAY,SAAS,MAAM,IAAI,SAAS,IAAI;AAAA,EAG9C;AAEA,SACC,YAAY,SAAS,MAAM,IAAI,SAAS,IAAI;AAG9C;;;AC3jDO,SAAS,kBACf,SAC8B;AAC9B,SACC,aAAa,WACb,gBAAgB,WAChB,OAAQ,QAA6B,YAAY;AAEnD;AAKO,SAAS,kBACf,SAC8B;AAC9B,SACC,YAAY,WACZ,OAAQ,QAA6B,WAAW;AAElD;AAKO,SAAS,sBACf,SACkC;AAClC,SACC,gBAAgB,WAChB,OAAQ,QAAiC,eAAe;AAE1D;AAKO,SAAS,qBACf,SACsC;AACtC,SACC,iBAAiB,WACjB,gBAAgB,WAChB,OAAQ,QAAqC,gBAAgB;AAE/D;AAKO,SAAS,eAAe,SAAgD;AAC9E,SACC,gBAAgB,WAChB,OAAQ,QAA0B,eAAe;AAEnD;AAKO,SAAS,sBACf,SACkC;AAClC,SACC,iBAAiB,WACjB,OAAQ,QAAiC,gBAAgB;AAE3D;AASO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC/C,YAAY,WAAmB;AAC9B;AAAA,MACC,cAAc,SAAS;AAAA,IAExB;AACA,SAAK,OAAO;AAAA,EACb;AACD;AAKO,IAAM,6BAAN,cAAyC,MAAM;AAAA,EACrD,YAAY,WAAmB,YAAuC;AACrE;AAAA,MACC,cAAc,SAAS,0BAA0B,UAAU;AAAA,IAE5D;AACA,SAAK,OAAO;AAAA,EACb;AACD;AAKO,SAAS,iBACf,SACA,YACA,WACO;AACP,MAAI,CAAC,QAAQ,aAAa,UAAU,GAAG;AACtC,UAAM,IAAI,2BAA2B,WAAW,UAAU;AAAA,EAC3D;AACD;;;AC9GO,SAAS,iBAAiB,OAAyC;AACzE,SACC,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,SACX,MAAyB,WAAW;AAEvC;AAUO,SAAS,YACf,MACA,SACA,OACA,MACiB;AACjB,MAAI,KAAK,WAAW,QAAQ,UAAU,KAAK,WAAW,MAAM,QAAQ;AACnE,UAAM,IAAI;AAAA,MACT,wEACS,KAAK,MAAM,KAAK,QAAQ,MAAM,KAAK,MAAM,MAAM;AAAA,IACzD;AAAA,EACD;AACA,MAAI,QAAQ,WAAW,GAAG;AACzB,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAC/D;AAGA,QAAM,cAAc,MAAM,KAAK,CAAC,MAAM,CAAC,kBAAkB,KAAK,CAAC,CAAC;AAChE,MAAI,gBAAgB,QAAW;AAC9B,UAAM,IAAI;AAAA,MACT,mCAAmC,WAAW;AAAA,IAE/C;AAAA,EACD;AACA,SAAO;AAAA,IACN,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,MAAM,SAAS;AAAA,IACtB,YAAY,MAAM,cAAc;AAAA,EACjC;AACD;;;ACjEA,IAAM,mBAAmB;AACzB,IAAM,wBACL;AACD,IAAM,oBAAoB;AAsC1B,SAAS,mBAAmB,OAAoC;AAE/D,MAAI,iBAAiB,cAAe,QAAO,MAAM;AAIjD,MACC,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,SACX,MAA8B,WAAW,QAC1C,YAAY,OACX;AACD,WAAQ,MAAuC;AAAA,EAChD;AACA,MAAI,OAAO,UAAU,UAAU;AAC9B,WAAO,EAAE,MAAM,OAAO,QAAQ,MAAM;AAAA,EACrC;AACA,SAAO,EAAE,MAAM,SAAS,OAAO,MAAM;AACtC;AAiBO,IAAM,gBAAN,MAAM,eAAc;AAAA,EACjB,SAAe;AAAA,EACf;AAAA,EAET,YAAY,QAA0B;AACrC,SAAK,SAAS;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,GAAG,OAA8B;AAChC,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,IAAI;AAAA,IACL,CAAqB;AAAA,EACtB;AAAA;AAAA,EAGA,GAAG,OAAuC;AACzC,WAAO,EAAE,MAAM,cAAc,MAAM,KAAK,QAAQ,UAAU,MAAM,MAAM;AAAA,EACvE;AAAA;AAAA,EAGA,IAAI,OAAuC;AAC1C,WAAO,EAAE,MAAM,cAAc,MAAM,KAAK,QAAQ,UAAU,OAAO,MAAM;AAAA,EACxE;AAAA;AAAA,EAGA,GAAG,OAAuC;AACzC,WAAO,EAAE,MAAM,cAAc,MAAM,KAAK,QAAQ,UAAU,MAAM,MAAM;AAAA,EACvE;AAAA;AAAA,EAGA,IAAI,OAAuC;AAC1C,WAAO,EAAE,MAAM,cAAc,MAAM,KAAK,QAAQ,UAAU,OAAO,MAAM;AAAA,EACxE;AAAA;AAAA,EAGA,GAAG,OAAuC;AACzC,WAAO,EAAE,MAAM,cAAc,MAAM,KAAK,QAAQ,UAAU,MAAM,MAAM;AAAA,EACvE;AAAA;AAAA,EAGA,IAAI,OAAuC;AAC1C,WAAO,EAAE,MAAM,cAAc,MAAM,KAAK,QAAQ,UAAU,OAAO,MAAM;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,WAAuC;AAC7C,QAAI,KAAK,OAAO,SAAS,YAAY;AACpC,YAAM,IAAI;AAAA,QACT,mFAAmF,KAAK,OAAO,IAAI;AAAA,MACpG;AAAA,IACD;AACA,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,QAAQ;AAAA,IACT,CAA6B;AAAA,EAC9B;AACD;AAYO,SAASC,KAAI,QAA+B;AAClD,SAAO,IAAI,cAAc;AAAA,IACxB,MAAM;AAAA,IACN;AAAA,EACD,CAA+B;AAChC;AAQO,SAAS,MAAM,OAA+B;AACpD,SAAO,IAAI,cAAc;AAAA,IACxB,MAAM;AAAA,IACN;AAAA,EACD,CAAiC;AAClC;AAQO,SAAS,KAAK,MAAqB,UAAiC;AAC1E,MAAI,CAAC,kBAAkB,KAAK,QAAQ,GAAG;AACtC,UAAM,IAAI,MAAM,sBAAsB,QAAQ,EAAE;AAAA,EACjD;AACA,SAAO,IAAI,cAAc;AAAA,IACxB,MAAM;AAAA,IACN,MAAM,KAAK;AAAA,IACX;AAAA,EACD,CAAgC;AACjC;AAUO,SAAS,GACf,UACA,MACA,OACgB;AAChB,MAAI,CAAC,YAAY,CAAC,iBAAiB,KAAK,QAAQ,GAAG;AAClD,UAAM,IAAI,MAAM,qBAAqB,QAAQ,EAAE;AAAA,EAChD;AACA,SAAO,IAAI,cAAc;AAAA,IACxB,MAAM;AAAA,IACN;AAAA,IACA,MAAM,mBAAmB,IAAI;AAAA,IAC7B,OAAO,mBAAmB,KAAK;AAAA,EAChC,CAAoC;AACrC;AAwBO,SAAS,GAAG,SAAiB,MAAkC;AACrE,MAAI,CAAC,QAAQ,CAAC,sBAAsB,KAAK,IAAI,GAAG;AAC/C,UAAM,IAAI,MAAM,0BAA0B,IAAI,EAAE;AAAA,EACjD;AACA,QAAM,cAAkC,CAAC;AACzC,QAAM,cAA+B,CAAC;AACtC,aAAW,OAAO,MAAM;AACvB,QAAI,gBAAgB,GAAG,GAAG;AACzB,kBAAY,KAAK,GAAG;AAAA,IACrB,OAAO;AACN,kBAAY,KAAK,mBAAmB,GAAG,CAAC;AAAA,IACzC;AAAA,EACD;AACA,QAAM,SAAmC;AAAA,IACxC,MAAM;AAAA,IACN;AAAA,IACA,MAAM;AAAA,IACN,GAAI,YAAY,SAAS,IAAI,EAAE,YAAY,YAAY,IAAI,CAAC;AAAA,EAC7D;AACA,SAAO,IAAI,cAAc,MAAM;AAChC;AAcO,SAAS,QACf,OACgB;AAChB,SAAO,IAAI,cAAc;AAAA,IACxB,MAAM;AAAA,IACN;AAAA,EACD,CAAmC;AACpC;AASO,SAAS,MAAM,UAAkB,MAAgC;AACvE,MAAI,CAAC,YAAY,CAAC,iBAAiB,KAAK,QAAQ,GAAG;AAClD,UAAM,IAAI,MAAM,qBAAqB,QAAQ,EAAE;AAAA,EAChD;AACA,SAAO,IAAI,cAAc;AAAA,IACxB,MAAM;AAAA,IACN;AAAA,IACA,SAAS,mBAAmB,IAAI;AAAA,EACjC,CAAiC;AAClC;AAWO,SAAS,SAAS,MAAc,OAAiC;AACvE,MAAI,CAAC,QAAQ,CAAC,sBAAsB,KAAK,IAAI,GAAG;AAC/C,UAAM,IAAI,MAAM,oCAAoC,IAAI,EAAE;AAAA,EAC3D;AACA,SAAO,IAAI,cAAc;AAAA,IACxB,MAAM;AAAA,IACN;AAAA,IACA,OAAO,mBAAmB,KAAK;AAAA,EAChC,CAAoC;AACrC;AAGO,SAAS,OAAsB;AACrC,SAAO,IAAI,cAAc,EAAE,MAAM,OAAO,CAAgC;AACzE;AAQO,SAAS,SAAS,OAAmC;AAC3D,SAAO,IAAI,cAAc;AAAA,IACxB,MAAM;AAAA,IACN,UAAU,MAAM,IAAI,kBAAkB;AAAA,EACvC,CAAiC;AAClC;AAUA,SAAS,gBAAgB,OAA0C;AAClE,SACC,OAAO,UAAU,YACjB,UAAU,QACV,CAAC,MAAM,QAAQ,KAAK,KACpB,EAAE,iBAAiB,kBACnB,kBAAkB,SACjB,MAAwB,iBAAiB;AAE5C;AAUO,SAAS,WACf,OACA,YAA4B,OACZ;AAChB,SAAO,EAAE,cAAc,MAAM,OAAO,UAAU;AAC/C;AASO,SAAS,SACfC,SACG,MACa;AAChB,QAAM,UAAU,OAAOA,SAAQ,WAAWD,KAAIC,IAAG,IAAIA;AACrD,SAAO,GAAG,aAAa,SAAS,GAAG,IAAI;AACxC;AAQO,SAAS,UACfA,MACA,cACG,MACa;AAChB,QAAM,UAAU,OAAOA,SAAQ,WAAWD,KAAIC,IAAG,IAAIA;AACrD,SAAO,GAAG,cAAc,SAAS,WAAW,GAAG,IAAI;AACpD;;;AC3bA,SAAS,eACR,OACmB;AACnB,MAAI,iBAAiB,eAAe;AACnC,WAAO,MAAM;AAAA,EACd;AACA,MAAI,UAAU,QAAQ,UAAU,QAAW;AAC1C,WAAO,EAAE,MAAM,WAAW,OAAO,KAAK;AAAA,EACvC;AACA,MAAI,OAAO,UAAU,UAAU;AAC9B,WAAO,EAAE,MAAM,OAAO,QAAQ,MAAM;AAAA,EACrC;AACA,SAAO,EAAE,MAAM,WAAW,MAAM;AACjC;AAIO,IAAM,cAAN,MAAM,aAAY;AAAA,EACP;AAAA,EAKjB,YACC,UAIC;AACD,SAAK,WAAW;AAAA,EACjB;AAAA,EAEA,KAAK,WAAwB,WAAmC;AAC/D,WAAO,IAAI,aAAY;AAAA,MACtB,GAAG,KAAK;AAAA,MACR,EAAE,WAAW,QAAQ,eAAe,SAAS,EAAE;AAAA,IAChD,CAAC;AAAA,EACF;AAAA,EAEA,KAAK,WAAqC;AACzC,UAAM,SAA+B;AAAA,MACpC,MAAM;AAAA,MACN,MAAM,KAAK;AAAA,MACX,MAAM,eAAe,SAAS;AAAA,IAC/B;AACA,WAAO,IAAI,cAAc,MAA0B;AAAA,EACpD;AAAA,EAEA,GAAG,OAA8B;AAChC,WAAO,KAAK,OAAO,EAAE,GAAG,KAAK;AAAA,EAC9B;AAAA,EAEA,SAAwB;AACvB,UAAM,SAA+B;AAAA,MACpC,MAAM;AAAA,MACN,MAAM,KAAK;AAAA,IACZ;AACA,WAAO,IAAI,cAAc,MAA0B;AAAA,EACpD;AACD;AAEO,SAAS,SACf,WACA,WACc;AACd,SAAO,IAAI,YAAY,CAAC,EAAE,WAAW,QAAQ,eAAe,SAAS,EAAE,CAAC,CAAC;AAC1E;;;AC3DO,SAAS,eACf,SACA,eACU;AACV,MAAI,CAAC,SAAS;AACb,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;;;ACWO,IAAM,aAAN,MAAiB;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACA;AAAA,EAER,YAAY,MAAc,SAAmB,YAAqB;AACjE,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,aAAa;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,SAAmD;AAC7D,UAAM,UAAU,OAAO,OAAO,OAAO,EAAE,IAAI,CAAC,QAAQ,IAAI,MAAM;AAC9D,QAAI,QAAQ,SAAS,KAAK,CAAC,QAAQ,MAAM,CAAC,MAAM,MAAM,QAAQ,CAAC,CAAC,GAAG;AAClE,YAAM,IAAI;AAAA,QACT;AAAA,QACA,6DAA6D,QAAQ,KAAK,IAAI,CAAC;AAAA,MAChF;AAAA,IACD;AACA,SAAK,gBAAgB;AACrB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,YAA0B;AACnC,SAAK,kBAAkB;AACvB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MACC,eAC2B;AAC3B,QAAI,CAAC,KAAK,eAAe;AACxB,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,UAAM,YAA6B;AAAA,MAClC,MAAM;AAAA,MACN,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,GAAI,KAAK,oBAAoB,UAAa;AAAA,QACzC,aAAa,KAAK;AAAA,MACnB;AAAA,IACD;AAEA,WAAO,IAAI;AAAA,MACV;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IACN;AAAA,EACD;AACD;AAoBO,IAAM,kBAAN,MAAyC;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YACC,WACA,cACA,SACA,YACC;AACD,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,UAAU;AACf,SAAK,aAAa;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,cAA8B;AAC7B,UAAM,cAAc,KAAK,aAAa,YAAY;AAClD,WAAO;AAAA,MACN,MAAM;AAAA,MACN,MAAM,CAAC,KAAK,SAAS;AAAA,MACrB,OAAO;AAAA,IACR;AAAA,EACD;AAAA,EAEQ,iBAA0B;AACjC,WAAO,eAAmB,KAAK,SAAS,SAAS;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAgB;AACf,UAAM,UAAU,KAAK,eAAe;AACpC,UAAM,SAAS,KAAK,YAAY;AAChC,UAAM,iBAAiB,KAAK,aACzB,EAAE,YAAY,KAAK,WAAW,IAC9B;AAEH,UAAM,WAA0B,QAAQ;AAAA,MACvC;AAAA,MACA;AAAA,IACD;AAEA,WAAO;AAAA,MACN,KAAK,SAAS;AAAA,MACd,QAAQ,SAAS;AAAA,MACjB;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAA0B;AAC/B,UAAM,UAAU,KAAK,eAAe;AACpC,UAAM,SAAS,KAAK,YAAY;AAChC,UAAM,iBAAiB,KAAK,aACzB,EAAE,YAAY,KAAK,WAAW,IAC9B;AAEH,UAAM,WAAW,QAAQ;AAAA,MACxB;AAAA,MACA;AAAA,IACD;AAEA,WAAO,QAAQ,QAAQ,QAAQ;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,UAA8B;AAC7B,WAAO,KAAK,IAAI;AAAA,EACjB;AACD;;;ACjJO,IAAM,2BACZ,OAAO,OAAkC;AAAA;AAAA;AAAA;AAAA,EAIxC;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAO,KAAM,QAAO,CAAC;AAChC,aAAO,CAAC,GAAG,MAAM,MAAM,KAAK,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,KAAK,EAAE;AAAA,IAChE;AAAA,EACD;AAAA,EACA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,WAAW,KAAM,QAAO,CAAC;AACpC,aAAO,CAAC,GAAG,MAAM,UAAU,KAAK,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,KAAK,EAAE;AAAA,IACpE;AAAA,EACD;AAAA,EACA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,YAAY,OAAQ,QAAO,CAAC;AACvC,aAAO,MAAM,WAAW,IAAI,CAAC,SAAS,EAAE,QAAQ,IAAI,EAAE;AAAA,IACvD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,YAAI,MAAM,WAAW;AACpB,iBAAO,KAAK,EAAE,OAAO,WAAW,QAAQ,UAAU,CAAC;AAAA,QACpD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EACA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,YAAI,MAAM,SAAS;AAClB,iBAAO,KAAK,EAAE,OAAO,WAAW,QAAQ,GAAG,SAAS,WAAW,CAAC;AAAA,QACjE;AACA,mBAAWC,QAAO,MAAM,SAAS;AAChC,cAAIA,KAAI,SAAS;AAChB,mBAAO,KAAK;AAAA,cACX,OAAO;AAAA,cACP,QAAQA,KAAI;AAAA,cACZ,QAAQ,GAAG,SAAS,IAAIA,KAAI,IAAI;AAAA,YACjC,CAAC;AAAA,UACF;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EACA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,YAAI,MAAM,kBAAkB,QAAQ;AACnC,qBAAW,OAAO,MAAM,kBAAkB;AACzC,mBAAO,KAAK;AAAA,cACX,OAAO;AAAA,cACP,QAAQ,GAAG,SAAS,IAAI,IAAI,IAAI;AAAA,YACjC,CAAC;AAAA,UACF;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EACA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,mBAAW,MAAM,MAAM,aAAa;AACnC,cAAI,GAAG,YAAY,GAAG,aAAa,aAAa;AAC/C,mBAAO,KAAK;AAAA,cACX,OAAO;AAAA,cACP,QAAQ,GAAG,SAAS,cAAS,GAAG,WAAW,KAAK;AAAA,YACjD,CAAC;AAAA,UACF;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EACA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,mBAAW,MAAM,MAAM,aAAa;AACnC,cAAI,GAAG,UAAU;AAChB,mBAAO,KAAK;AAAA,cACX,OAAO;AAAA,cACP,QAAQ,GAAG,SAAS,cAAS,GAAG,WAAW,KAAK;AAAA,YACjD,CAAC;AAAA,UACF;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,mBAAWA,QAAO,MAAM,SAAS;AAChC,cAAIA,KAAI,UAAU;AACjB,mBAAO,KAAK;AAAA,cACX,OAAO;AAAA,cACP,QAAQA,KAAI;AAAA,cACZ,QAAQ,GAAG,SAAS,IAAIA,KAAI,IAAI;AAAA,YACjC,CAAC;AAAA,UACF;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EACA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,mBAAWA,QAAO,MAAM,SAAS;AAChC,cAAIA,KAAI,WAAW;AAClB,mBAAO,KAAK;AAAA,cACX,OAAO;AAAA,cACP,QAAQA,KAAI;AAAA,cACZ,QAAQ,GAAG,SAAS,IAAIA,KAAI,IAAI;AAAA,YACjC,CAAC;AAAA,UACF;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,mBAAW,OAAO,MAAM,SAAS;AAChC,cAAI,IAAI,UAAU,IAAI,WAAW,SAAS;AACzC,kBAAM,UAAU,IAAI,QAAQ,UAAU,SAAS;AAC/C,mBAAO,KAAK,EAAE,OAAO,WAAW,QAAQ,QAAQ,CAAC;AAAA,UAClD;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EACA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,mBAAW,OAAO,MAAM,SAAS;AAChC,cAAI,IAAI,WAAW,OAAO,KAAK,IAAI,OAAO,EAAE,SAAS,GAAG;AACvD,kBAAM,UAAU,IAAI,QAAQ,UAAU,SAAS;AAC/C,mBAAO,KAAK,EAAE,OAAO,WAAW,QAAQ,QAAQ,CAAC;AAAA,UAClD;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EACA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,mBAAW,OAAO,MAAM,SAAS;AAChC,cAAI,IAAI,SAAS,QAAQ;AACxB,kBAAM,UAAU,IAAI,QAAQ,UAAU,SAAS;AAC/C,mBAAO,KAAK,EAAE,OAAO,WAAW,QAAQ,QAAQ,CAAC;AAAA,UAClD;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EACA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,mBAAW,OAAO,MAAM,SAAS;AAChC,cAAI,IAAI,OAAO;AACd,kBAAM,UAAU,IAAI,QAAQ,UAAU,SAAS;AAC/C,mBAAO,KAAK,EAAE,OAAO,WAAW,QAAQ,QAAQ,CAAC;AAAA,UAClD;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AAAA,EACA;AAAA,IACC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY,OAAO;AAClB,UAAI,CAAC,MAAM,OAAQ,QAAO,CAAC;AAC3B,YAAM,SAAyB,CAAC;AAChC,iBAAW,CAAC,WAAW,KAAK,KAAK,MAAM,QAAQ;AAC9C,mBAAW,OAAO,MAAM,SAAS;AAChC,cAAI,IAAI,aAAa,QAAQ;AAC5B,kBAAM,UAAU,IAAI,QAAQ,UAAU,SAAS;AAC/C,mBAAO,KAAK,EAAE,OAAO,WAAW,QAAQ,QAAQ,CAAC;AAAA,UAClD;AAAA,QACD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,EACD;AACD,CAAC;;;AC5TK,SAAS,cACf,OACS;AACT,MAAI,OAAO,UAAU,UAAU;AAC9B,WAAO;AAAA,EACR;AACA,QAAM,UAAU,MAAM,WAAW;AACjC,MAAI,YAAY,QAAW;AAC1B,UAAM,IAAI,MAAM,wCAAwC;AAAA,EACzD;AACA,SAAO;AACR;;;AC6CO,IAAM,gBAAN,MAAM,eAAc;AAAA,EAClB,YACU,QACA,aAAgC,CAAC,GACjC,SAGX,CAAC,GACN;AANgB;AACA;AACA;AAAA,EAIf;AAAA,EANe;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUlB,OAAO,QAAQC,KAAyD;AACvE,WAAO,IAAI,eAAc,EAAE,MAAM,WAAW,IAAAA,IAAG,CAAC;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,UACNA,KACA,OACgB;AAChB,WAAO,IAAI,eAAc;AAAA,MACxB,MAAM;AAAA,MACN,IAAAA;AAAA,MACA,GAAI,UAAU,SAAY,EAAE,MAAM,IAAI,CAAC;AAAA,IACxC,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,OAAOA,KAAoB,OAA8B;AAC/D,WAAO,IAAI,eAAc,EAAE,MAAM,UAAU,IAAAA,KAAI,MAAM,CAAC;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,eACI,QACa;AAChB,UAAM,aAAa,OAAO;AAAA,MAAI,CAAC,MAC9B,OAAO,MAAM,WAAW,IAAI,cAAc,CAAC;AAAA,IAC5C;AACA,WAAO,IAAI;AAAA,MACV,KAAK;AAAA,MACL,CAAC,GAAG,KAAK,YAAY,GAAG,UAAU;AAAA,MAClC,KAAK;AAAA,IACN;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,QACC,OACA,YAA4B,OACZ;AAChB,UAAM,YAAY,OAAO,UAAU,WAAW,QAAQ,cAAc,KAAK;AACzE,WAAO,IAAI,eAAc,KAAK,QAAQ,KAAK,YAAY;AAAA,MACtD,GAAG,KAAK;AAAA,MACR,EAAE,OAAO,WAAW,UAAU;AAAA,IAC/B,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,GAAG,OAA+B;AACjC,WAAO;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ,KAAK,eAAe,KAAK;AAAA,IAClC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,OAA6B;AACnD,UAAMA,MAAK,KAAK,OAAO;AACvB,UAAM,QACL,KAAK,OAAO,SAAS,eAAe,KAAK,OAAO,SAAS,WACtD,KAAK,OAAO,QACZ;AAEJ,UAAM,OAAsC,CAAC;AAC7C,QAAI,KAAK,WAAW,SAAS,GAAG;AAC/B,WAAK,cAAc,KAAK;AAAA,IACzB;AACA,QAAI,KAAK,OAAO,SAAS,GAAG;AAC3B,WAAK,UAAU,KAAK;AAAA,IACrB;AAEA,UAAM,SAAuB;AAAA,MAC5B,MAAM;AAAA,MACN,UAAUA;AAAA,MACV;AAAA,MACA;AAAA,IACD;AAEA,QAAI,UAAU,QAAW;AACxB,aAAO,EAAE,GAAG,QAAQ,MAAM;AAAA,IAC3B;AACA,WAAO;AAAA,EACR;AACD;AAaO,SAAS,YAA2B;AAC1C,SAAO,cAAc,QAAQ,YAAY;AAC1C;AASO,SAAS,OAAsB;AACrC,SAAO,cAAc,QAAQ,MAAM;AACpC;AASO,SAAS,YAA2B;AAC1C,SAAO,cAAc,QAAQ,YAAY;AAC1C;AAWO,SAAS,KAAK,OAA8B;AAClD,SAAO,cAAc,UAAU,OAAO,KAAK;AAC5C;AAWO,SAAS,KAAK,OAA8B;AAClD,SAAO,cAAc,UAAU,OAAO,KAAK;AAC5C;AAgBO,SAAS,OAAO,OAA+B;AACrD,SAAO,cAAc,UAAU,SAAS,KAAK;AAC9C;AAWO,SAAS,KAAK,OAA8B;AAClD,SAAO,cAAc,UAAU,OAAO,KAAK;AAC5C;AAWO,SAAS,KAAK,OAA8B;AAClD,SAAO,cAAc,UAAU,OAAO,KAAK;AAC5C;AAWO,SAAS,IAAI,OAA8B;AACjD,SAAO,cAAc,OAAO,OAAO,KAAK;AACzC;AAWO,SAAS,KAAK,OAA8B;AAClD,SAAO,cAAc,OAAO,QAAQ,KAAK;AAC1C;;;ACzOO,SAAS,SAAS,OAA8B;AACtD,SAAO,EAAE,OAAO,UAAU,KAAK;AAChC;AAKO,SAAS,gBAAgB,OAAwC;AACvE,SACC,OAAO,UAAU,YACjB,UAAU,QACV,WAAW,SACX,cAAc,SACb,MAAwB,aAAa;AAExC;AAcA,SAAS,uBACR,UACmB;AACnB,SAAO,CACN,OACA,WAC4B;AAAA,IAC5B,MAAM;AAAA,IACN,OAAO,cAAc,KAAK;AAAA,IAC1B;AAAA,IACA;AAAA,EACD;AACD;AAQO,IAAM,KAAuB,uBAAuB,IAAI;AAQxD,IAAM,MAAwB,uBAAuB,KAAK;AAQ1D,IAAM,KAAuB,uBAAuB,IAAI;AAQxD,IAAM,MAAwB,uBAAuB,KAAK;AAQ1D,IAAM,KAAuB,uBAAuB,IAAI;AAQxD,IAAM,MAAwB,uBAAuB,KAAK;AAW1D,IAAM,iBACZ,uBAAuB,gBAAgB;AA2BjC,SAAS,KACf,OACA,SACA,SACkB;AAClB,QAAM,kBACL,OAAO,YAAY,YAAY,UAAU,SAAS;AACnD,QAAM,aAAa,OAAO,YAAY,WAAW,QAAQ,SAAS;AAElE,QAAM,SAA0B;AAAA,IAC/B,MAAM;AAAA,IACN,OAAO,cAAc,KAAK;AAAA,IAC1B;AAAA,EACD;AACA,QAAM,SACL,oBAAoB,SAAY,EAAE,GAAG,QAAQ,gBAAgB,IAAI;AAClE,MAAI,eAAe,QAAW;AAC7B,WAAO,EAAE,GAAG,QAAQ,QAAQ,WAAW;AAAA,EACxC;AACA,SAAO;AACR;AAoBO,SAAS,QACf,OACA,QACgB;AAChB,SAAO,EAAE,MAAM,MAAM,OAAO,cAAc,KAAK,GAAG,OAAO;AAC1D;AAeO,SAAS,WACf,OACA,OACgB;AAChB,QAAM,OACL,WAAW,QACP,MAA0B,MAAM,IAChC;AACL,SAAO;AAAA,IACN,MAAM;AAAA,IACN,OAAO,cAAc,KAAK;AAAA,IAC1B,QAAQ,CAAC;AAAA,IACT,UAAU,KAAK,SAAS;AAAA,EACzB;AACD;AAaO,SAAS,IACf,OACA,QACiB;AACjB,SAAO,EAAE,MAAM,OAAO,OAAO,cAAc,KAAK,GAAG,OAAO;AAC3D;AAgBO,SAAS,OACf,OACkB;AAClB,SAAO,EAAE,MAAM,QAAQ,OAAO,cAAc,KAAK,GAAG,UAAU,SAAS;AACxE;AA6EO,SAAS,UACf,OACkB;AAClB,SAAO,EAAE,MAAM,QAAQ,OAAO,cAAc,KAAK,GAAG,UAAU,YAAY;AAC3E;AAcO,SAAS,OACZ,YACc;AAEjB,QAAM,iBACL,WAAW,WAAW,KAAK,MAAM,QAAQ,WAAW,CAAC,CAAC,IAClD,WAAW,CAAC,IACZ;AAEL,SAAO,EAAE,MAAM,OAAO,YAAY,eAAe;AAClD;AAUO,SAAS,MACZ,YACa;AAEhB,QAAM,iBACL,WAAW,WAAW,KAAK,MAAM,QAAQ,WAAW,CAAC,CAAC,IAClD,WAAW,CAAC,IACZ;AAEL,SAAO,EAAE,MAAM,MAAM,YAAY,eAAe;AACjD;AAOO,SAAS,IAAI,WAAwC;AAC3D,SAAO,EAAE,MAAM,OAAO,UAAU;AACjC;AAgBO,SAAS,OACf,UACA,SAKoB;AACpB,QAAM,SAAqC,EAAE,MAAM,UAAU,SAAS;AACtE,MAAI,SAAS,UAAU,QAAW;AACjC,WAAO,QAAQ,QAAQ;AAAA,EACxB;AACA,MAAI,SAAS,cAAc,QAAW;AACrC,WAAO,YAAY,QAAQ;AAAA,EAC5B;AACA,MAAI,SAAS,YAAY,QAAW;AACnC,WAAO,UAAU,QAAQ;AAAA,EAC1B;AACA,SAAO;AACR;AAWO,SAAS,UACf,UACA,SAKuB;AACvB,QAAM,SAAwC;AAAA,IAC7C,MAAM;AAAA,IACN;AAAA,EACD;AACA,MAAI,SAAS,UAAU,QAAW;AACjC,WAAO,QAAQ,QAAQ;AAAA,EACxB;AACA,MAAI,SAAS,cAAc,QAAW;AACrC,WAAO,YAAY,QAAQ;AAAA,EAC5B;AACA,MAAI,SAAS,YAAY,QAAW;AACnC,WAAO,UAAU,QAAQ;AAAA,EAC1B;AACA,SAAO;AACR;AAmBO,SAAS,UACf,IACuB;AACvB,QAAM,SACL,iBAAiB,KACb,GAAsC,YAAY,IAClD,GAAuB,MAAM,EAAE,SAAS;AAC7C,SAAO,EAAE,MAAM,aAAa,UAAU,OAAO;AAC9C;AAeO,SAAS,aACf,IAC0B;AAC1B,QAAM,SACL,iBAAiB,KACb,GAAsC,YAAY,IAClD,GAAuB,MAAM,EAAE,SAAS;AAC7C,SAAO,EAAE,MAAM,gBAAgB,UAAU,OAAO;AACjD;AAUA,SAAS,gBACR,KACS;AACT,QAAM,OAAO,IAAI,aAAa;AAC9B,MAAI,CAAC,MAAM;AACV,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC7D;AACA,SAAO,KAAK;AACb;AAqBO,SAAS,MACf,UACA,QAC4B;AAC5B,QAAM,eAAe,gBAAgB,QAAQ;AAC7C,QAAM,QAAQ,OAAO,QAAQ;AAC7B,SAAO;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV;AAAA,IACA,MAAM;AAAA,EACP;AACD;AAqBO,SAAS,KACf,UACA,QAC4B;AAC5B,QAAM,eAAe,gBAAgB,QAAQ;AAC7C,QAAM,QAAQ,OAAO,QAAQ;AAC7B,SAAO;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV;AAAA,IACA,MAAM;AAAA,EACP;AACD;AAqBO,SAAS,KACf,UACA,QAC4B;AAC5B,QAAM,eAAe,gBAAgB,QAAQ;AAC7C,QAAM,QAAQ,OAAO,QAAQ;AAC7B,SAAO;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV;AAAA,IACA,MAAM;AAAA,EACP;AACD;AA2BO,SAAS,SACf,QACA,IACiB;AACjB,MAAI,OAAO,WAAW,GAAG;AACxB,UAAM,IAAI,MAAM,wCAAwC;AAAA,EACzD;AACA,MAAI,CAAC,MAAM,GAAG,KAAK,MAAM,IAAI;AAC5B,UAAM,IAAI,MAAM,uCAAuC;AAAA,EACxD;AAEA,aAAW,KAAK,QAAQ;AACvB,uBAAmB,GAAG,QAAQ;AAAA,EAC/B;AACA,qBAAmB,IAAI,QAAQ;AAC/B,SAAO;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ,EAAE,MAAM,YAAY,QAAQ,GAAG;AAAA,EACxC;AACD;AA2CO,SAAS,IAAI,aAAqB,IAA4B;AACpE,MAAI,CAAC,MAAM,GAAG,KAAK,MAAM,IAAI;AAC5B,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACnD;AACA,SAAO;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ,EAAE,MAAM,OAAO,KAAK,aAAa,GAAG;AAAA,EAC7C;AACD;AA0BO,SAAS,IAAI,QAAgB,OAA+B;AAClE,MAAI,CAAC,UAAU,OAAO,KAAK,MAAM,IAAI;AACpC,UAAM,IAAI,MAAM,wCAAwC;AAAA,EACzD;AACA,MAAI,CAAC,SAAS,MAAM,KAAK,MAAM,IAAI;AAClC,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACnD;AACA,SAAO;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ,EAAE,MAAM,eAAe,QAAQ,MAAM;AAAA,EAC9C;AACD;AA+BO,SAAS,eACf,UACA,QACA,IACuB;AACvB,MAAI,CAAC,YAAY,SAAS,KAAK,MAAM,IAAI;AACxC,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACtE;AACA,MAAI,CAAC,UAAU,OAAO,KAAK,MAAM,IAAI;AACpC,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACpE;AACA,MAAI,CAAC,MAAO,GAAc,KAAK,MAAM,IAAI;AACxC,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC9D;AACA,SAAO;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ,EAAE,MAAM,kBAAkB,UAAU,QAAQ,GAAG;AAAA,EACxD;AACD;AAUO,IAAM,iBAAiB,uBAAO,IAAI,cAAc;AA8ChD,SAAS,IAAI,aAAuC;AAC1D,MAAI,CAAC,eAAe,YAAY,KAAK,MAAM,IAAI;AAC9C,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC1D;AACA,SAAO,EAAE,CAAC,cAAc,GAAG,MAAM,KAAK,YAAY;AACnD;AAKO,SAAS,SAAS,OAA2C;AACnE,SACC,OAAO,UAAU,YACjB,UAAU,QACV,kBAAkB,SACjB,MAAkC,cAAc,MAAM;AAEzD;;;AC92BO,SAAS,eAAe;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACD,GAAyC;AACxC,QAAM,aAAa,MAAM,KAAK;AAC9B,QAAM,aAAa,OAAO;AAAA,IAAI,CAAC,EAAE,MAAM,WAAW,OAAO,OAAO,MAC/D;AAAA,MACC;AAAA,MACA,QAAQ,MAAM;AAAA,MACd;AAAA,QACC;AAAA,QACA,SAAS,SAAS,QAAQ,SAAS,CAAC;AAAA,QACpC,SAAS,gBAAgB,UAAU;AAAA,MACpC;AAAA,IACD;AAAA,EACD;AACA,QAAM,cAAc;AAAA,IACnB;AAAA,IACA,SAAS,UAAU,MAAM,GAAG,UAAU,CAAC;AAAA,EACxC;AACA,SAAO,GAAG,OAAOC,KAAI,UAAU,GAAG,WAAW;AAC9C;AA0BO,SAAS,UAAU,WAAW,MAAqB;AACzD,SAAO,GAAG,kBAAkBA,KAAI,QAAQ,CAAC;AAC1C;;;AC/GA,IAAM,iBAA+C;AAAA,EACpD,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,KAAK;AACN;AAuBO,SAAS,aACf,MACA,UACuB;AACvB,SAAO,EAAE,MAAM,SAAS;AACzB;AAQO,SAAS,eACf,OACQ;AACR,SAAO,CAAC,GAAG,KAAK,EACd,KAAK,CAAC,GAAG,MAAM,eAAe,EAAE,QAAQ,IAAI,eAAe,EAAE,QAAQ,CAAC,EACtE,IAAI,CAAC,MAAM,EAAE,IAAI;AACpB;AAiBO,SAAS,2BACZ,OACe;AAElB,QAAM,UAAU,CAAC,GAAG,KAAK,EAAE,QAAQ;AACnC,SAAO,OAAO,QAAqD;AAClE,QAAI,UAA4B;AAChC,eAAW,QAAQ,SAAS;AAC3B,YAAM,SAAS,MAAM,KAAK,OAAO;AACjC,UAAI,WAAW,QAAW;AACzB,kBAAU;AAAA,MACX;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;AAaO,SAAS,wBACZ,OACe;AAClB,SAAO,OAAO,QAAqD;AAClE,QAAI,UAA4B;AAChC,eAAW,QAAQ,OAAO;AACzB,YAAM,SAAS,MAAM,KAAK,OAAO;AACjC,UAAI,WAAW,QAAW;AACzB,kBAAU;AAAA,MACX;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;AAWO,SAAS,0BACZ,OACc;AACjB,QAAM,UAAU,CAAC,GAAG,KAAK,EAAE,QAAQ;AACnC,SAAO,OAAU,KAAuB,WAA0B;AACjE,QAAI,UAAa;AACjB,eAAW,QAAQ,SAAS;AAC3B,YAAM,OAAO,MAAM,KAAK,KAAK,OAAO;AACpC,UAAI,SAAS,QAAW;AACvB,kBAAU;AAAA,MACX;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;AAOO,SAAS,uBACZ,OACc;AACjB,SAAO,OAAU,KAAuB,WAA0B;AACjE,QAAI,UAAa;AACjB,eAAW,QAAQ,OAAO;AACzB,YAAM,OAAO,MAAM,KAAK,KAAK,OAAO;AACpC,UAAI,SAAS,QAAW;AACvB,kBAAU;AAAA,MACX;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;AAUO,SAAS,8BACZ,OACkB;AACrB,QAAM,UAAU,CAAC,GAAG,KAAK,EAAE,QAAQ;AACnC,SAAO,OACN,QACqC;AACrC,QAAI,UAAkC;AACtC,eAAW,QAAQ,SAAS;AAC3B,YAAM,SAAS,MAAM,KAAK,OAAO;AACjC,UAAI,WAAW,QAAW;AACzB,kBAAU;AAAA,MACX;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;AAMO,SAAS,2BACZ,OACkB;AACrB,SAAO,OACN,QACqC;AACrC,QAAI,UAAkC;AACtC,eAAW,QAAQ,OAAO;AACzB,YAAM,SAAS,MAAM,KAAK,OAAO;AACjC,UAAI,WAAW,QAAW;AACzB,kBAAU;AAAA,MACX;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;AAUO,SAAS,6BACZ,OACiB;AACpB,QAAM,UAAU,CAAC,GAAG,KAAK,EAAE,QAAQ;AACnC,SAAO,OAAU,KAA6B,WAA8B;AAC3E,QAAI,UAAe;AACnB,eAAW,QAAQ,SAAS;AAC3B,YAAM,OAAO,MAAM,KAAK,KAAK,OAAO;AACpC,UAAI,SAAS,QAAW;AACvB,kBAAU;AAAA,MACX;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;AAMO,SAAS,0BACZ,OACiB;AACpB,SAAO,OAAU,KAA6B,WAA8B;AAC3E,QAAI,UAAe;AACnB,eAAW,QAAQ,OAAO;AACzB,YAAM,OAAO,MAAM,KAAK,KAAK,OAAO;AACpC,UAAI,SAAS,QAAW;AACvB,kBAAU;AAAA,MACX;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACD;AAWO,SAAS,uBAAuB,OAAmC;AACzE,QAAM,UAAU,CAAC,GAAG,KAAK,EAAE,QAAQ;AACnC,SAAO,OAAO,QAAsD;AACnE,QAAI,aAA+B;AACnC,eAAW,QAAQ,SAAS;AAC3B,YAAM,SAAS,MAAM,KAAK,UAAU;AACpC,UAAI,WAAW,QAAW;AAEzB,qBAAa,EAAE,GAAG,YAAY,OAAO,OAAO;AAAA,MAC7C;AAAA,IACD;AACA,WAAO,WAAW;AAAA,EACnB;AACD;AAOO,SAAS,oBAAoB,OAAmC;AACtE,SAAO,OAAO,QAAsD;AACnE,QAAI,aAA+B;AACnC,eAAW,QAAQ,OAAO;AACzB,YAAM,SAAS,MAAM,KAAK,UAAU;AACpC,UAAI,WAAW,QAAW;AACzB,qBAAa,EAAE,GAAG,YAAY,OAAO,OAAO;AAAA,MAC7C;AAAA,IACD;AACA,WAAO,WAAW;AAAA,EACnB;AACD;;;AChHA,IAAM,kBAAN,MAAM,iBAAuC;AAAA,EAC3B;AAAA,EAEjB,YAAY,OAAmB;AAC9B,SAAK,QAAQ,SAAS;AAAA,MACrB,aAAa,CAAC;AAAA,MACd,YAAY,CAAC;AAAA,MACb,gBAAgB,CAAC;AAAA,MACjB,eAAe,CAAC;AAAA,MAChB,SAAS,CAAC;AAAA,MACV,QAAQ;AAAA,IACT;AAAA,EACD;AAAA,EAEA,YAAY,MAAoC;AAC/C,SAAK,gBAAgB;AACrB,WAAO,IAAI,iBAAgB;AAAA,MAC1B,GAAG,KAAK;AAAA,MACR,aAAa,CAAC,GAAG,KAAK,MAAM,aAAa,IAAI;AAAA,IAC9C,CAAC;AAAA,EACF;AAAA,EAEA,WAAW,MAAmC;AAC7C,SAAK,gBAAgB;AACrB,WAAO,IAAI,iBAAgB;AAAA,MAC1B,GAAG,KAAK;AAAA,MACR,YAAY,CAAC,GAAG,KAAK,MAAM,YAAY,IAAI;AAAA,IAC5C,CAAC;AAAA,EACF;AAAA,EAEA,eAAe,MAAuC;AACrD,SAAK,gBAAgB;AACrB,WAAO,IAAI,iBAAgB;AAAA,MAC1B,GAAG,KAAK;AAAA,MACR,gBAAgB,CAAC,GAAG,KAAK,MAAM,gBAAgB,IAAI;AAAA,IACpD,CAAC;AAAA,EACF;AAAA,EAEA,cAAc,MAAsC;AACnD,SAAK,gBAAgB;AACrB,WAAO,IAAI,iBAAgB;AAAA,MAC1B,GAAG,KAAK;AAAA,MACR,eAAe,CAAC,GAAG,KAAK,MAAM,eAAe,IAAI;AAAA,IAClD,CAAC;AAAA,EACF;AAAA,EAEA,QAAQ,MAAgC;AACvC,SAAK,gBAAgB;AACrB,WAAO,IAAI,iBAAgB;AAAA,MAC1B,GAAG,KAAK;AAAA,MACR,SAAS,CAAC,GAAG,KAAK,MAAM,SAAS,IAAI;AAAA,IACtC,CAAC;AAAA,EACF;AAAA,EAEA,SAAsB;AACrB,QAAI,KAAK,MAAM,OAAQ,QAAO;AAC9B,WAAO,IAAI,iBAAgB,EAAE,GAAG,KAAK,OAAO,QAAQ,KAAK,CAAC;AAAA,EAC3D;AAAA;AAAA,EAGA,WAAsB;AACrB,WAAO,KAAK;AAAA,EACb;AAAA,EAEQ,kBAAwB;AAC/B,QAAI,KAAK,MAAM,QAAQ;AACtB,YAAM,IAAI;AAAA,QACT;AAAA,MAED;AAAA,IACD;AAAA,EACD;AACD;AAWO,SAAS,aAAa,SAAiC;AAC7D,SAAQ,QAA4B,SAAS;AAC9C;AAWA,IAAM,mBAAmB,oBAAI,QAAmB;AAOzC,SAAS,mBAAmB,OAA8B;AAChE,mBAAiB,IAAI,KAAK;AAC1B,SAAO,MAAM,iBAAiB,OAAO,KAAK;AAC3C;AAQA,eAAsB,oBACrB,OACAC,KACa;AACb,QAAM,OAAO,mBAAmB,KAAK;AACrC,MAAI;AACH,WAAO,MAAMA,IAAG,KAAK;AAAA,EACtB,UAAE;AACD,SAAK;AAAA,EACN;AACD;AASO,SAAS,SAAS,OAA2B;AAEnD,MAAI,iBAAiB,IAAI,KAAK,EAAG,QAAO;AAExC,SACC,MAAM,YAAY,SAAS,KAC3B,MAAM,WAAW,SAAS,KAC1B,MAAM,eAAe,SAAS,KAC9B,MAAM,cAAc,SAAS,KAC7B,MAAM,QAAQ,SAAS;AAEzB;AAQA,eAAsB,oBACrB,OACA,KACA,aAC4B;AAC5B,MAAI,UAAU;AACd,aAAW,QAAQ,OAAO;AACzB,UAAM,SAAS,OAAO,OAAO,EAAE,GAAG,QAAQ,CAAC;AAC3C,QAAI;AACH,YAAM,SAAS,MAAM,KAAK,MAAM;AAChC,UAAI,WAAW,UAAa,WAAW,MAAM;AAC5C,kBAAU;AAAA,MACX;AAAA,IACD,SAAS,OAAO;AACf,UAAI,aAAa;AAChB,cAAM,SAAS;AAAA,UACd;AAAA,UACA,KAAK,QAAQ;AAAA,UACb;AAAA,UACA;AAAA,QACD;AACA,YAAI,WAAW,WAAY;AAAA,MAC5B;AACA,YAAM;AAAA,IACP;AAAA,EACD;AACA,SAAO;AACR;AAOA,eAAsB,mBACrB,OACA,KACA,QACA,aACa;AACb,MAAI,UAAU;AAEd,WAAS,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,CAAC,KAAM;AACX,UAAM,SAAS,OAAO,OAAO,EAAE,GAAG,IAAI,CAAC;AACvC,QAAI;AACH,YAAM,cAAc,MAAM,KAAK,QAAQ,OAAO;AAC9C,UAAI,gBAAgB,UAAa,gBAAgB,MAAM;AACtD,kBAAU;AAAA,MACX;AAAA,IACD,SAAS,OAAO;AACf,UAAI,aAAa;AAChB,cAAM,SAAS;AAAA,UACd;AAAA,UACA,KAAK,QAAQ;AAAA,UACb;AAAA,UACA;AAAA,QACD;AACA,YAAI,WAAW,WAAY;AAAA,MAC5B;AACA,YAAM;AAAA,IACP;AAAA,EACD;AACA,SAAO;AACR;AAMA,eAAsB,uBACrB,OACA,KACA,aACkC;AAClC,MAAI,UAAU;AACd,aAAW,QAAQ,OAAO;AACzB,UAAM,SAAS,OAAO,OAAO,EAAE,GAAG,QAAQ,CAAC;AAC3C,QAAI;AACH,YAAM,SAAS,MAAM,KAAK,MAAM;AAChC,UAAI,WAAW,UAAa,WAAW,MAAM;AAC5C,kBAAU;AAAA,MACX;AAAA,IACD,SAAS,OAAO;AACf,UAAI,aAAa;AAChB,cAAM,SAAS;AAAA,UACd;AAAA,UACA,KAAK,QAAQ;AAAA,UACb;AAAA,UACA;AAAA,QACD;AACA,YAAI,WAAW,WAAY;AAAA,MAC5B;AACA,YAAM;AAAA,IACP;AAAA,EACD;AACA,SAAO;AACR;AAMA,eAAsB,sBACrB,OACA,KACA,QACA,aACe;AACf,MAAI,UAAU;AACd,WAAS,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,CAAC,KAAM;AACX,UAAM,SAAS,OAAO,OAAO,EAAE,GAAG,IAAI,CAAC;AACvC,QAAI;AACH,YAAM,cAAc,MAAM,KAAK,QAAQ,OAAO;AAC9C,UAAI,gBAAgB,UAAa,gBAAgB,MAAM;AACtD,kBAAU;AAAA,MACX;AAAA,IACD,SAAS,OAAO;AACf,UAAI,aAAa;AAChB,cAAM,SAAS;AAAA,UACd;AAAA,UACA,KAAK,QAAQ;AAAA,UACb;AAAA,UACA;AAAA,QACD;AACA,YAAI,WAAW,WAAY;AAAA,MAC5B;AACA,YAAM;AAAA,IACP;AAAA,EACD;AACA,SAAO;AACR;AAMA,eAAsB,gBACrB,OACA,KACiB;AACjB,MAAI,eAAe,IAAI;AACvB,aAAW,QAAQ,OAAO;AACzB,UAAM,SAAS,OAAO,OAAO,EAAE,GAAG,KAAK,OAAO,aAAa,CAAC;AAC5D,QAAI;AACH,YAAM,SAAS,MAAM,KAAK,MAAM;AAChC,UAAI,kBAAkB,OAAO;AAC5B,uBAAe;AAAA,MAChB;AAAA,IACD,QAAQ;AAAA,IAER;AAAA,EACD;AACA,SAAO;AACR;AAgBO,SAAS,oBAAiC;AAChD,SAAO,IAAI,gBAAgB;AAC5B;;;AC5eO,IAAM,kBAAN,MAAM,iBAAgB;AAAA,EACX;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EAKR,YAAY,OAAe;AAC1B,SAAK,QAAQ;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,OAAgC;AACtC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,UAAU;AAChB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAyC;AAC9C,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,SAAS;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,KAAyB;AACtC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,aAAa,EAAE,IAAI,SAAS,MAAM;AACxC,WAAO,MAAM,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAmC;AACtC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,aAAa,EAAE,IAAI,OAAO,MAAM;AACtC,WAAO,MAAM,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAmC;AACtC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,aAAa,EAAE,IAAI,OAAO,MAAM;AACtC,WAAO,MAAM,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAmC;AACtC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,aAAa,EAAE,IAAI,OAAO,MAAM;AACtC,WAAO,MAAM,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAAmC;AACtC,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,aAAa,EAAE,IAAI,OAAO,MAAM;AACtC,WAAO,MAAM,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QAA4B;AAC3B,QAAI,CAAC,KAAK,WAAW,CAAC,KAAK,YAAY;AACtC,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AAGA,UAAM,cAAc,KAAK,WAAW,KAAK,YAAY,SAAS;AAE9D,UAAM,SAAsB;AAAA,MAC3B,MAAM;AAAA,MACN,MAAM,KAAK;AAAA;AAAA,MAEX,QAAQ,KAAK,aACV;AAAA,QACA,MAAM;AAAA,QACN,YAAY;AAAA,UACX;AAAA,YACC,UAAU,KAAK,WAAW;AAAA,YAC1B,OAAO,KAAK,WAAW;AAAA,UACxB;AAAA,QACD;AAAA,MACD,IACC,EAAE,MAAM,UAAU,QAAQ,CAAC,WAAW,EAAE;AAAA,MAC3C,GAAI,KAAK,UAAU,EAAE,OAAO,KAAK,OAAO;AAAA,IACzC;AAEA,WAAO,IAAI,mBAAmB,MAAM;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAoB;AACnB,WAAO,KAAK,MAAM,EAAE,SAAS;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,OAAO,OAA+B;AACrC,WAAO,KAAK,MAAM,EAAE,OAAO,KAAK;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKQ,QAAyB;AAChC,UAAM,QAAQ,IAAI,iBAAgB,KAAK,KAAK;AAC5C,QAAI,KAAK,YAAY,OAAW,OAAM,UAAU,KAAK;AACrD,QAAI,KAAK,WAAW,OAAW,OAAM,SAAS,KAAK;AACnD,QAAI,KAAK,eAAe,OAAW,OAAM,aAAa,KAAK;AAC3D,WAAO;AAAA,EACR;AACD;AAUO,IAAM,qBAAN,MAAyB;AAAA,EACtB,QAAQ;AAAA,EACR;AAAA,EAET,YAAY,QAAqB;AAChC,SAAK,SAAS;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,WAAwB;AACvB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cACC,OACA,UACsB;AACtB,WAAO;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAU,KAAK;AAAA,IAChB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,OAAO,OAA+B;AACrC,WAAO;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ,EAAE,MAAM,YAAY,OAAO,KAAK,QAAQ,IAAI,MAAM;AAAA,IAC3D;AAAA,EACD;AACD;AAuBO,SAAS,SAAS,OAAgC;AACxD,SAAO,IAAI,gBAAgB,KAAK;AACjC;AAaO,SAAS,SAAS,QAAmC;AAC3D,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,EACD;AACD;AAUO,SAAS,qBACf,OAC8B;AAC9B,SACC,OAAO,UAAU,YACjB,UAAU,QACV,WAAW,SACV,MAAkC,UAAU;AAE/C;;;AC3MO,SAAS,cAAc,OAAsC;AACnE,SACC,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,OAAQ,MAAkC,SAAS;AAErD;AAKA,SAAS,iBAAiB,OAA0C;AACnE,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAChD,WAAO;AAAA,EACR;AACA,QAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,SAAO,KAAK,SAAS,KAAK,KAAK,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,CAAC;AAC9D;AASA,SAAS,kBAAkB,OAAe,OAAiC;AAE1E,MAAI,UAAU,MAAM;AACnB,WAAO;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,UAAU;AAAA,IACX;AAAA,EACD;AAGA,MAAI,iBAAiB,KAAK,GAAG;AAC5B,WAAO,sBAAsB,OAAO,KAAK;AAAA,EAC1C;AAGA,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EACD;AACD;AAKA,SAAS,uBACR,OACA,UACA,OACc;AACd,MAAI,qBAAqB,KAAK,GAAG;AAChC,WAAO,MAAM,cAAc,OAAO,QAAQ;AAAA,EAC3C;AACA,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AAKA,SAAS,sBACR,OACA,KACc;AACd,QAAM,aAA4B,CAAC;AAGnC,MAAI,OAAO,OAAO,KAAK,KAAK,KAAK,IAAI,QAAQ,QAAW;AACvD,eAAW,KAAK,uBAAuB,OAAO,MAAM,IAAI,GAAG,CAAC;AAAA,EAC7D;AAGA,MAAI,OAAO,OAAO,KAAK,MAAM,KAAK,IAAI,SAAS,QAAW;AACzD,eAAW,KAAK,uBAAuB,OAAO,OAAO,IAAI,IAAI,CAAC;AAAA,EAC/D;AAGA,MAAI,OAAO,OAAO,KAAK,KAAK,KAAK,IAAI,QAAQ,QAAW;AACvD,eAAW,KAAK,uBAAuB,OAAO,MAAM,IAAI,GAAG,CAAC;AAAA,EAC7D;AAGA,MAAI,OAAO,OAAO,KAAK,MAAM,KAAK,IAAI,SAAS,QAAW;AACzD,eAAW,KAAK,uBAAuB,OAAO,OAAO,IAAI,IAAI,CAAC;AAAA,EAC/D;AAGA,MAAI,OAAO,OAAO,KAAK,KAAK,KAAK,IAAI,QAAQ,QAAW;AACvD,eAAW,KAAK,uBAAuB,OAAO,MAAM,IAAI,GAAG,CAAC;AAAA,EAC7D;AAGA,MAAI,OAAO,OAAO,KAAK,MAAM,KAAK,IAAI,SAAS,QAAW;AACzD,eAAW,KAAK,uBAAuB,OAAO,OAAO,IAAI,IAAI,CAAC;AAAA,EAC/D;AAGA,MAAI,OAAO,OAAO,KAAK,KAAK,KAAK,IAAI,QAAQ,QAAW;AACvD,eAAW,KAAK;AAAA,MACf,MAAM;AAAA,MACN;AAAA,MACA,QAAQ,IAAI;AAAA,IACb,CAAyB;AAAA,EAC1B;AAGA,MAAI,OAAO,OAAO,KAAK,OAAO,KAAK,IAAI,UAAU,QAAW;AAC3D,eAAW,KAAK;AAAA,MACf,MAAM;AAAA,MACN;AAAA,MACA,SAAS,IAAI;AAAA,IACd,CAA2B;AAAA,EAC5B;AAGA,MAAI,OAAO,OAAO,KAAK,QAAQ,KAAK,IAAI,WAAW,QAAW;AAC7D,eAAW,KAAK;AAAA,MACf,MAAM;AAAA,MACN;AAAA,MACA,SAAS,IAAI;AAAA,MACb,iBAAiB;AAAA,IAClB,CAA2B;AAAA,EAC5B;AAGA,MAAI,OAAO,OAAO,KAAK,UAAU,KAAK,IAAI,aAAa,MAAM;AAC5D,eAAW,KAAK;AAAA,MACf,MAAM;AAAA,MACN;AAAA,MACA,UAAU;AAAA,IACX,CAA2B;AAAA,EAC5B;AAGA,MAAI,WAAW,WAAW,GAAG;AAC5B,UAAM,IAAI;AAAA,MACT,8CAA8C,KAAK;AAAA,IACpD;AAAA,EACD;AAEA,MAAI,WAAW,WAAW,GAAG;AAE5B,WAAO,WAAW,CAAC;AAAA,EACpB;AAEA,SAAO,EAAE,MAAM,OAAO,WAAW;AAClC;AAKA,IAAM,iBAAiB,oBAAI,IAAI,CAAC,aAAa,eAAe,WAAW,CAAC;AAuBjE,SAAS,oBACf,QACc;AAId,aAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACtC,QAAI,eAAe,IAAI,GAAG,GAAG;AAC5B,YAAM,IAAI;AAAA,QACT;AAAA,QACA,2BAA2B,GAAG;AAAA,MAC/B;AAAA,IACD;AAAA,EACD;AAEA,QAAM,UAAU,OAAO,QAAQ,MAAM;AAErC,MAAI,QAAQ,WAAW,GAAG;AACzB,UAAM,IAAI,MAAM,8BAA8B;AAAA,EAC/C;AAEA,QAAM,aAA4B,QAAQ;AAAA,IAAI,CAAC,CAAC,OAAO,KAAK,MAC3D,kBAAkB,OAAO,KAAoB;AAAA,EAC9C;AAGA,MAAI,WAAW,WAAW,GAAG;AAE5B,WAAO,WAAW,CAAC;AAAA,EACpB;AAGA,SAAO,EAAE,MAAM,OAAO,WAAW;AAClC;;;AC1OO,SAAS,iBAAiB,MAA0C;AAC1E,SACC,OAAO,SAAS,YAChB,SAAS,QACT,YAAY,QACZ,KAAK,WAAW;AAElB;;;ACjDO,SAAS,0BACf,SACqC;AACrC,SACC,YAAY,UACZ,eAAe,WACf,QAAQ,cAAc;AAExB;AAMO,SAAS,uBACf,UACA,SACgB;AAChB,MAAI,CAAC,SAAS;AACb,WAAO,EAAE,SAAS;AAAA,EACnB;AAEA,QAAM,SAAiC,EAAE,SAAS;AAElD,MAAI,QAAQ,QAAQ,QAAW;AAC9B,WAAO,MAAM,QAAQ;AAAA,EACtB;AACA,MAAI,QAAQ,UAAU,QAAW;AAChC,WAAO,QAAQ,QAAQ;AAAA,EACxB;AACA,MAAI,QAAQ,WAAW,QAAW;AACjC,WAAO,SAAS,QAAQ;AAAA,EACzB;AACA,MAAI,QAAQ,YAAY,UAAa,QAAQ,QAAQ,SAAS,GAAG;AAChE,WAAO,UAAU,QAAQ,QAAQ;AAAA,MAAI,CAAC,WACrC,sBAAsB,MAAM;AAAA,IAC7B;AAAA,EACD;AAEA,MAAI,QAAQ,SAAS,QAAW;AAC/B,WAAO,OAAO,QAAQ;AAAA,EACvB;AAGA,MAAI,0BAA0B,OAAO,GAAG;AACvC,UAAM,gBAAkD,CAAC;AAEzD,QAAI,QAAQ,aAAa,QAAW;AACnC,oBAAc,WAAW,QAAQ;AAAA,IAClC;AAEA,QAAI,QAAQ,cAAc;AACzB,oBAAc,QAAQ,EAAE,OAAO,KAAK;AAAA,IACrC;AACA,WAAO,YAAY;AAAA,EACpB;AAEA,SAAO;AACR;AAKO,SAAS,sBAAsB,QAAsC;AAC3E,QAAM,SAAiC,EAAE,UAAU,OAAO,SAAS;AAEnE,MAAI,OAAO,QAAQ,QAAW;AAC7B,WAAO,MAAM,OAAO;AAAA,EACrB;AACA,MAAI,OAAO,UAAU,QAAW;AAC/B,WAAO,QAAQ,OAAO;AAAA,EACvB;AACA,MAAI,OAAO,WAAW,QAAW;AAChC,WAAO,SAAS,OAAO;AAAA,EACxB;AACA,MAAI,OAAO,YAAY,UAAa,OAAO,QAAQ,SAAS,GAAG;AAC9D,WAAO,UAAU,OAAO,QAAQ,IAAI,CAAC,MAAM,sBAAsB,CAAC,CAAC;AAAA,EACpE;AAEA,SAAO;AACR;AASO,SAAS,wBACf,MACA,SACgB;AAChB,QAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,MAAI,MAAM,WAAW,GAAG;AACvB,UAAM,IAAI,MAAM,sBAAsB;AAAA,EACvC;AAIA,QAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AACvC,MAAI,CAAC,UAAU;AACd,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACtD;AACA,MAAI,UAAyB,uBAAuB,UAAU,OAAO;AAQrE,WAAS,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,CAAC,KAAM;AACX,cACC,SAAS,SAAS,SACf,EAAE,UAAU,MAAM,MAAM,QAAQ,MAAM,SAAS,CAAC,OAAO,EAAE,IACzD,EAAE,UAAU,MAAM,SAAS,CAAC,OAAO,EAAE;AAAA,EAC1C;AAEA,SAAO;AACR;AASO,SAAS,yBACf,OACA,aACA,cACA,SACO;AAEP,QAAM,gBAAgB,GAAG,WAAW,IAAI,YAAY;AACpD,QAAM,WAAW,MAAM,YAAY,aAAa;AAEhD,MAAI,CAAC,UAAU;AAEd;AAAA,EACD;AAGA,MAAI,CAAC,QAAQ,WAAW;AACvB,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,IAED;AAAA,EACD;AAGA,MAAI,SAAS,WAAW,SAAS,QAAQ;AACxC,UAAM,IAAI;AAAA,MACT;AAAA,MACA,qEACc,YAAY,eAAe,SAAS,MAAM,SAAS,SAAS,MAAM;AAAA,IAEjF;AAAA,EACD;AAIA,QAAM,EAAE,UAAU,IAAI;AACtB,QAAM,UAAU,SAAS;AAEzB,MAAI,cAAc,aAAa;AAG9B,QAAI,YAAY,aAAa,YAAY,iBAAiB;AACzD,YAAM,IAAI;AAAA,QACT;AAAA,QACA,qFACc,YAAY,eAAe,OAAO;AAAA,MAEjD;AAAA,IACD;AAAA,EACD,WAAW,cAAc,eAAe;AAGvC,QAAI,YAAY,eAAe,YAAY,UAAU;AACpD,YAAM,IAAI;AAAA,QACT;AAAA,QACA,4EACc,YAAY,eAAe,OAAO;AAAA,MAEjD;AAAA,IACD;AAAA,EACD;AACD;AAqDO,IAAM,gBAAN,MAAM,eAAiC;AAAA,EAC5B;AAAA,EACA;AAAA,EACR;AAAA,EAET,YACC,OACA,MACA,gBAA+B,CAAC,GAChC,cACC;AACD,SAAK,QAAQ;AACb,SAAK,gBAAgB;AACrB,SAAK,QAAQ;AAAA,MACZ;AAAA,MACA,cAAc,cAAc,eACzB,CAAC,GAAG,aAAa,YAAY,IAC7B,CAAC;AAAA,MACJ,eAAe,cAAc,gBAC1B,CAAC,GAAG,aAAa,aAAa,IAC9B,CAAC;AAAA,MACJ,UAAU,cAAc,WAAW,CAAC,GAAG,aAAa,QAAQ,IAAI,CAAC;AAAA,MACjE,mBAAmB,cAAc,oBAC9B,CAAC,GAAG,aAAa,iBAAiB,IAClC,CAAC;AAAA,MACJ,YAAY,cAAc,aAAa,CAAC,GAAG,aAAa,UAAU,IAAI,CAAC;AAAA,MACvE,eAAe,cAAc,gBAC1B,CAAC,GAAG,aAAa,aAAa,IAC9B,CAAC;AAAA,MACJ,gBAAgB,cAAc,iBAC3B,CAAC,GAAG,aAAa,cAAc,IAC/B,CAAC;AAAA,MACJ,cAAc,cAAc;AAAA,MAC5B,YAAY,cAAc;AAAA,MAC1B,aAAa,cAAc;AAAA,MAC3B,YAAY,cAAc;AAAA,IAC3B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,UAAkB,SAA6C;AAEzE,QAAI,0BAA0B,OAAO,GAAG;AACvC,+BAAyB,KAAK,OAAO,KAAK,MAAM,MAAM,UAAU,OAAO;AAAA,IAGxE;AAGA,QAAI,SAAS,SAAS,GAAG,GAAG;AAC3B,WAAK,MAAM,SAAS,KAAK,wBAAwB,UAAU,OAAO,CAAC;AAAA,IACpE,OAAO;AACN,WAAK,MAAM,SAAS,KAAK,uBAAuB,UAAU,OAAO,CAAC;AAAA,IACnE;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,SAAsC;AAEhD,UAAM,oBAAwC,CAAC;AAC/C,QAAI,iBAAiB;AAErB,eAAWC,QAAO,SAAS;AAC1B,UAAI,iBAAiBA,IAAG,GAAG;AAC1B,yBAAiB;AACjB,0BAAkB,KAAMA,KAAuB,MAAM;AAAA,MACtD,OAAO;AAEN,0BAAkB,KAAK,EAAE,MAAM,UAAU,QAAQA,KAAc,CAAC;AAAA,MACjE;AAAA,IACD;AAGA,QAAI,gBAAgB;AACnB,WAAK,MAAM,eAAe;AAAA,QACzB,MAAM;AAAA,QACN,SAAS;AAAA,MACV;AAAA,IACD,OAAO;AAEN,YAAM,SAAS,kBAAkB;AAAA,QAChC,CAAC,MAAO,EAA6B;AAAA,MACtC;AACA,WAAK,MAAM,eAAe,EAAE,MAAM,UAAU,OAAO;AAAA,IACpD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,WAAqD;AAE7D,UAAM,SAAS,cAAc,SAAS,IACnC,YACA,oBAAoB,SAAiD;AACxE,SAAK,MAAM,aAAa,KAAK,MAAM;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aACC,MACA,OACA,SACO;AACP,UAAM,MAAgC,EAAE,UAAU,KAAK;AACvD,QAAI,UAAU,QAAW;AACxB,UAAI,QAAQ;AAAA,IACb,WAAW,SAAS,UAAU,QAAW;AACxC,UAAI,QAAQ,QAAQ;AAAA,IACrB;AACA,QAAI,SAAS,OAAO,QAAW;AAC9B,UAAI,KAAK,QAAQ;AAAA,IAClB;AAEA,QAAI,SAAS,UAAU;AACtB,UAAI,WAAW;AAAA,IAChB;AACA,SAAK,MAAM,WAAW,KAAK,GAAsB;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,QAAiC;AAC3C,SAAK,MAAM,cAAc,KAAK,GAAG,MAAM;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,WAA8B;AACvC,SAAK,MAAM,cAAc,KAAK,SAAS;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,QAAiB,MAAY;AACxC,SAAK,MAAM,aAAa;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,WACC,sBACA,WACO;AAEP,QAAI,OAAO,yBAAyB,UAAU;AAC7C,WAAK,MAAM,eAAe,KAAK;AAAA,QAC9B,OAAO;AAAA,QACP,WAAW,aAAa;AAAA,MACzB,CAAC;AACD;AAAA,IACD;AAGA,QAAI,MAAM,QAAQ,oBAAoB,GAAG;AACxC,iBAAW,QAAQ,sBAAsB;AACxC,aAAK,MAAM,eAAe,KAAK;AAAA,UAC9B,OAAO,KAAK;AAAA,UACZ,WAAW,KAAK,aAAa;AAAA,UAC7B,OAAO,KAAK;AAAA,QACb,CAAC;AAAA,MACF;AACA;AAAA,IACD;AAGA,eAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,oBAAoB,GAAG;AAChE,WAAK,MAAM,eAAe,KAAK;AAAA,QAC9B;AAAA,QACA,WAAW;AAAA,MACZ,CAAC;AAAA,IACF;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,OAAqB;AAC7B,SAAK,MAAM,aAAa;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,OAAqB;AAC9B,SAAK,MAAM,cAAc;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAA2B;AAC1B,UAAM,SAA+B;AAAA,MACpC,MAAM;AAAA,MACN,MAAM,KAAK,MAAM;AAAA,IAClB;AAGA,QAAI,KAAK,MAAM,WAAW,SAAS,GAAG;AACrC,YAAM,kBAAkD;AAAA,QACvD,MAAM;AAAA,QACN,YAAY,CAAC,GAAG,KAAK,MAAM,UAAU;AAAA,MACtC;AAEA,UAAI,KAAK,MAAM,cAAc,SAAS,GAAG;AACxC,wBAAgB,SAAS,CAAC,GAAG,KAAK,MAAM,aAAa;AAAA,MACtD;AACA,aAAO,SAAS;AAAA,IACjB,WAAW,KAAK,MAAM,iBAAiB,QAAW;AACjD,aAAO,SAAS,KAAK,MAAM;AAAA,IAC5B;AAGA,QAAI,KAAK,MAAM,aAAa,WAAW,GAAG;AACzC,YAAM,cAAc,KAAK,MAAM,aAAa,CAAC;AAC7C,UAAI,gBAAgB,QAAW;AAC9B,eAAO,QAAQ;AAAA,MAChB;AAAA,IACD,WAAW,KAAK,MAAM,aAAa,SAAS,GAAG;AAC9C,aAAO,QAAQ,IAAI,GAAG,KAAK,MAAM,YAAY;AAAA,IAC9C;AAEA,QAAI,KAAK,MAAM,SAAS,SAAS,GAAG;AACnC,aAAO,UAAU,KAAK,MAAM;AAAA,IAC7B;AAEA,QAAI,KAAK,MAAM,cAAc,SAAS,GAAG;AACxC,aAAO,UAAU,CAAC,GAAG,KAAK,MAAM,aAAa;AAAA,IAC9C;AAGA,QAAI,KAAK,MAAM,cAAc,WAAW,GAAG;AAC1C,YAAM,eAAe,KAAK,MAAM,cAAc,CAAC;AAC/C,UAAI,iBAAiB,QAAW;AAC/B,eAAO,SAAS;AAAA,MACjB;AAAA,IACD,WAAW,KAAK,MAAM,cAAc,SAAS,GAAG;AAC/C,aAAO,SAAS,IAAI,GAAG,KAAK,MAAM,aAAa;AAAA,IAChD;AAGA,QAAI,KAAK,MAAM,YAAY;AAC1B,aAAO,WAAW;AAAA,IACnB;AAEA,QAAI,KAAK,MAAM,eAAe,SAAS,GAAG;AACzC,aAAO,UAAU,CAAC,GAAG,KAAK,MAAM,cAAc;AAAA,IAC/C;AAEA,QAAI,KAAK,MAAM,eAAe,QAAW;AACxC,aAAO,QAAQ,KAAK,MAAM;AAAA,IAC3B;AAEA,QAAI,KAAK,MAAM,gBAAgB,QAAW;AACzC,aAAO,SAAS,KAAK,MAAM;AAAA,IAC5B;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,QAAkC;AACpD,QAAI,CAAC,OAAO,WAAW,OAAO,KAAK,KAAK,aAAa,EAAE,WAAW,GAAG;AACpE,aAAO;AAAA,IACR;AAEA,UAAM,kBAAkB,OAAO,QAAQ;AAAA,MAAI,CAAC,QAC3C,KAAK,mBAAmB,GAAG;AAAA,IAC5B;AAEA,WAAO;AAAA,MACN,GAAG;AAAA,MACH,SAAS;AAAA,IACV;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,KAAmC;AAE7D,QAAI,IAAI,QAAQ,QAAW;AAE1B,UAAI,IAAI,WAAW,IAAI,QAAQ,SAAS,GAAG;AAC1C,eAAO;AAAA,UACN,GAAG;AAAA,UACH,SAAS,IAAI,QAAQ,IAAI,CAAC,WAAW,KAAK,mBAAmB,MAAM,CAAC;AAAA,QACrE;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAGA,UAAM,OAAO,KAAK,cAAc,IAAI,QAAQ;AAC5C,UAAM,SAAwB,OAAO,EAAE,GAAG,KAAK,KAAK,KAAK,IAAI;AAG7D,QAAI,OAAO,WAAW,OAAO,QAAQ,SAAS,GAAG;AAChD,aAAO;AAAA,QACN,GAAG;AAAA,QACH,SAAS,OAAO,QAAQ;AAAA,UAAI,CAAC,WAC5B,KAAK,mBAAmB,MAAM;AAAA,QAC/B;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,QAAgC;AAC/B,WAAO,IAAI;AAAA,MACV,KAAK;AAAA,MACL,KAAK,MAAM;AAAA,MACX,EAAE,GAAG,KAAK,cAAc;AAAA,MACxB;AAAA,QACC,cAAc,KAAK,MAAM;AAAA,QACzB,cAAc,CAAC,GAAG,KAAK,MAAM,YAAY;AAAA,QACzC,eAAe,CAAC,GAAG,KAAK,MAAM,aAAa;AAAA,QAC3C,UAAU,CAAC,GAAG,KAAK,MAAM,QAAQ;AAAA,QACjC,mBAAmB,CAAC,GAAG,KAAK,MAAM,iBAAiB;AAAA,QACnD,YAAY,CAAC,GAAG,KAAK,MAAM,UAAU;AAAA,QACrC,eAAe,CAAC,GAAG,KAAK,MAAM,aAAa;AAAA,QAC3C,gBAAgB,CAAC,GAAG,KAAK,MAAM,cAAc;AAAA,QAC7C,YAAY,KAAK,MAAM;AAAA,QACvB,aAAa,KAAK,MAAM;AAAA,QACxB,YAAY,KAAK,MAAM;AAAA,MACxB;AAAA,IACD;AAAA,EACD;AACD;;;AC7gBO,IAAM,iCAAN,MAAM,wCAAuC,MAAM;AAAA,EACvC,OAAO;AAAA;AAAA,EAGhB;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA,EAET,YAAY,MAIT;AACF,QAAI,UAAU,oCAAoC,KAAK,WAAW,MAAM,KAAK,MAAM;AACnF,QAAI,KAAK,YAAY;AACpB,iBAAW;AAAA;AAAA,cAAmB,KAAK,UAAU;AAAA,IAC9C;AAEA,UAAM,OAAO;AACb,SAAK,cAAc,KAAK;AACxB,SAAK,SAAS,KAAK;AACnB,QAAI,KAAK,YAAY;AACpB,WAAK,aAAa,KAAK;AAAA,IACxB;AAEA,WAAO,eAAe,MAAM,gCAA+B,SAAS;AAAA,EACrE;AACD;AASA,IAAM,sBAAsB,oBAAI,IAAY,CAAC,OAAO,OAAO,OAAO,KAAK,CAAC;AAKxE,IAAM,sBAAkE;AAAA,EACvE,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;AAMA,IAAM,uBAAuE;AAAA,EAC5E,OAAO;AAAA;AAAA,EACP,OAAO;AAAA;AAAA,EACP,OAAO;AAAA;AAAA,EACP,OAAO;AAAA;AACR;AAKO,SAAS,uBACf,OACgC;AAChC,SAAO,OAAO,UAAU,YAAY,oBAAoB,IAAI,KAAK;AAClE;AAKO,SAAS,mBAAmB,OAA2C;AAC7E,SACC,MAAM,QAAQ,KAAK,KACnB,MAAM,WAAW,KACjB,uBAAuB,MAAM,CAAC,CAAC,KAC/B,OAAO,MAAM,CAAC,MAAM;AAEtB;AAKO,SAAS,oBACf,OAC6B;AAC7B,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACxE,WAAO;AAAA,EACR;AACA,QAAM,MAAM;AACZ,SAAO,uBAAuB,IAAI,WAAW;AAC9C;AAiBO,SAAS,iBAAiB,KAAgC;AAChE,QAAM,WAAW,IAAI,QAAQ,GAAG;AAChC,MAAI,aAAa,MAAM,aAAa,KAAK,aAAa,IAAI,SAAS,GAAG;AACrE,UAAM,IAAI,+BAA+B;AAAA,MACxC,aAAa;AAAA,MACb,QAAQ;AAAA,MACR,YAAY;AAAA,IACb,CAAC;AAAA,EACF;AAEA,SAAO;AAAA,IACN,aAAa,IAAI,MAAM,GAAG,QAAQ;AAAA,IAClC,cAAc,IAAI,MAAM,WAAW,CAAC;AAAA,EACrC;AACD;AAsBO,SAAS,iBACf,KACA,OACoB;AAEpB,MAAI,uBAAuB,KAAK,GAAG;AAClC,WAAO;AAAA,MACN,aAAa;AAAA,MACb,cAAc,oBAAoB,KAAK;AAAA,MACvC,kBAAkB,qBAAqB,KAAK;AAAA,MAC5C,QAAQ;AAAA,MACR,IAAI;AAAA,MACJ,SAAS;AAAA,IACV;AAAA,EACD;AAGA,MAAI,mBAAmB,KAAK,GAAG;AAC9B,UAAM,CAAC,aAAa,MAAM,IAAI;AAC9B,WAAO;AAAA,MACN;AAAA,MACA,cAAc,oBAAoB,WAAW;AAAA,MAC7C,kBAAkB,qBAAqB,WAAW;AAAA,MAClD;AAAA,MACA,IAAI;AAAA,MACJ,SAAS;AAAA,IACV;AAAA,EACD;AAGA,MAAI,oBAAoB,KAAK,GAAG;AAC/B,UAAM,EAAE,aAAa,IAAI,QAAQ,QAAQ,IAAI;AAC7C,WAAO;AAAA,MACN;AAAA,MACA,cAAc,oBAAoB,WAAW;AAAA,MAC7C,kBAAkB,qBAAqB,WAAW;AAAA,MAClD;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAGA,QAAM,WACL,OAAO,UAAU,WAAW,KAAK,UAAU,KAAK,IAAI,OAAO,KAAK;AACjE,QAAM,IAAI,+BAA+B;AAAA,IACxC,aAAa;AAAA,IACb,QAAQ,uCAAuC,QAAQ;AAAA,IACvD,YACC;AAAA,EACF,CAAC;AACF;AAkBO,SAAS,gBAAgB,WAA2B;AAC1D,QAAM,WAAW,YAAY,SAAS;AAEtC,QAAM,YAAY,SAAS,QAAQ,YAAY,KAAK,EAAE,YAAY;AAElE,QAAM,iBAAiB,UAAU,WAAW,GAAG,IAC5C,UAAU,MAAM,CAAC,IACjB;AACH,SAAO,GAAG,cAAc;AACzB;AAYO,SAAS,YACf,SACU;AACV,QAAM,EAAE,UAAU,IAAI;AAGtB,QAAM,aAAa,oBAAI,IAAY;AACnC,QAAM,kBAID,CAAC;AAGN,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG;AACrD,QAAI,UAAU,OAAW;AAEzB,UAAM,SAAS,iBAAiB,GAAG;AACnC,UAAM,MAAM,iBAAiB,KAAK,KAA0B;AAE5D,eAAW,IAAI,OAAO,WAAW;AAGjC,QAAI,SAAS,IAAI;AACjB,QAAI,WAAW,QAAW;AAEzB,eAAS,OAAO;AAAA,IACjB;AACA,eAAW,IAAI,MAAM;AAGrB,QAAI,IAAI,gBAAgB,SAAS,IAAI,YAAY,QAAW;AAC3D,YAAM,IAAI,+BAA+B;AAAA,QACxC,aAAa;AAAA,QACb,QACC;AAAA,QACD,YAAY;AAAA,MACb,CAAC;AAAA,IACF;AAGA,QAAI,IAAI,YAAY,QAAW;AAC9B,iBAAW,IAAI,IAAI,OAAO;AAAA,IAC3B;AAEA,oBAAgB,KAAK,EAAE,KAAK,QAAQ,IAAI,CAAC;AAAA,EAC1C;AAIA,QAAM,SAAS,oBAAI,IAAqB;AACxC,aAAW,QAAQ,YAAY;AAC9B,WAAO,IAAI,MAAM;AAAA,MAChB;AAAA,MACA,SAAS,CAAC;AAAA,MACV,YAAY;AAAA,MACZ,aAAa,CAAC;AAAA,MACd,SAAS,CAAC;AAAA,IACX,CAAC;AAAA,EACF;AAGA,QAAM,eAAe,oBAAI,IAAwB;AAEjD,aAAW,EAAE,KAAK,QAAQ,IAAI,KAAK,iBAAiB;AAEnD,UAAM,SAAS,IAAI,UAAU,OAAO;AAGpC,QAAI,aAAa,IAAI;AACrB,QAAI,eAAe,QAAW;AAE7B,UAAI,IAAI,iBAAiB,aAAa;AAErC,qBAAa,gBAAgB,MAAM;AAAA,MACpC,WACC,IAAI,iBAAiB,aACrB,IAAI,iBAAiB,UACpB;AAED,qBAAa,gBAAgB,OAAO,WAAW;AAAA,MAChD;AAAA,IAGD;AAGA,UAAM,cACL,IAAI,iBAAiB,cAAc,aAAa;AAEjD,UAAM,gBAAgB;AACtB,UAAM,WAAuB;AAAA,MAC5B,MAAM,OAAO;AAAA,MACb,MAAM,IAAI;AAAA,MACV,QAAQ,OAAO;AAAA,MACf;AAAA,MACA,SAAS,IAAI;AAAA,MACb;AAAA,MACA,aAAa,IAAI;AAAA,MACjB;AAAA,MACA,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,aAAa;AAAA,IACd;AAEA,iBAAa,IAAI,eAAe,QAAQ;AAAA,EACzC;AAGA,SAAO,IAAI,mBAAmB,QAAQ,YAAY;AACnD;AAKA,IAAM,qBAAN,MAA4C;AAAA,EAClC;AAAA,EACA;AAAA,EAET,YACC,QACA,WACC;AACD,SAAK,SAAS;AACd,SAAK,YAAY;AAAA,EAClB;AAAA,EAEA,SAAS,MAAmC;AAC3C,WAAO,KAAK,OAAO,IAAI,IAAI;AAAA,EAC5B;AAAA,EAEA,YAAY,eAA+C;AAC1D,WAAO,KAAK,UAAU,IAAI,aAAa;AAAA,EACxC;AAAA,EAEA,iBAAiB,aAA4C;AAC5D,UAAM,SAAuB,CAAC;AAC9B,eAAW,CAAC,KAAK,QAAQ,KAAK,KAAK,WAAW;AAC7C,UAAI,IAAI,WAAW,GAAG,WAAW,GAAG,GAAG;AACtC,eAAO,KAAK,QAAQ;AAAA,MACrB;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA,EAEA,eAAe,aAA4C;AAC1D,UAAM,SAAuB,CAAC;AAC9B,eAAW,YAAY,KAAK,UAAU,OAAO,GAAG;AAC/C,UAAI,SAAS,WAAW,aAAa;AACpC,eAAO,KAAK,QAAQ;AAAA,MACrB;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA,EAEA,YACC,aACA,aACqD;AACrD,UAAM,oBAA8B,CAAC;AACrC,eAAW,CAAC,KAAK,QAAQ,KAAK,KAAK,WAAW;AAC7C,UACC,IAAI,WAAW,GAAG,WAAW,GAAG,KAChC,SAAS,WAAW,aACnB;AACD,0BAAkB,KAAK,SAAS,IAAI;AAAA,MACrC;AAAA,IACD;AACA,WAAO;AAAA,MACN,WAAW,kBAAkB,SAAS;AAAA,MACtC,SAAS;AAAA,IACV;AAAA,EACD;AACD;;;AC5bA,IAAe,sBAAf,MAQE;AAAA,EACkB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACT,MAGC;AACD,SAAK,QAAQ,KAAK;AAClB,SAAK,QAAQ,KAAK;AAClB,SAAK,UAAU,KAAK;AACpB,SAAK,aAAa,KAAK;AACvB,SAAK,mBAAmB,KAAK;AAC7B,SAAK,YAAY,KAAK;AACtB,SAAK,cAAc,KAAK;AACxB,SAAK,gBAAgB,KAAK;AAAA,EAC3B;AAAA,EAeA,IAAc,WAA6B;AAC1C,WAAO;AAAA,MACN,OAAO,KAAK;AAAA,MACZ,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,WAAW,KAAK;AAAA,MAChB,aAAa,KAAK;AAAA,MAClB,eAAe,KAAK;AAAA,IACrB;AAAA,EACD;AAAA;AAAA,EAGU,eAAe,WAA4B;AACpD,QAAI,CAAC,KAAK,SAAS;AAClB,YAAM,IAAI,eAAe;AAAA,QACxB;AAAA,QACA,QAAQ;AAAA,QACR,KAAK;AAAA,MACN,CAAC;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,KAAK,cAA6C;AACjD,UAAM,UAAU,KAAK,eAAe,MAAM;AAC1C,UAAM,SAAS,KAAK,YAAY;AAChC,UAAM,iBAAiC;AAAA,MACtC,GAAI,KAAK,eAAe,UAAa,EAAE,YAAY,KAAK,WAAW;AAAA,MACnE,GAAG;AAAA,IACJ;AACA,UAAM,WAAW,KAAK;AAAA,MACrB;AAAA,MACA;AAAA,MACA,OAAO,KAAK,cAAc,EAAE,SAAS,IAAI,iBAAiB;AAAA,IAC3D;AAEA,UAAM,OAA8C;AAAA,MACnD,YAAY,oBAAI,KAAK;AAAA,IACtB;AACA,QAAI,KAAK,eAAe,QAAW;AAClC,WAAK,SAAS,KAAK;AAAA,IACpB;AAEA,WAAO;AAAA,MACN,KAAK,SAAS;AAAA,MACd,YAAY,SAAS;AAAA,MACrB;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,UAAsB;AAC3B,UAAM,UAAU,KAAK,eAAe,KAAK,aAAa;AAGtD,QAAI,CAAC,KAAK,aAAa,CAAC,SAAS,KAAK,SAAS,GAAG;AACjD,aAAO,KAAK,oBAAoB,OAAO;AAAA,IACxC;AAEA,WAAO,KAAK,iBAAiB,OAAO;AAAA,EACrC;AAAA,EAEA,MAAc,oBAAoB,SAA8B;AAC/D,UAAM,SAAS,KAAK,YAAY;AAChC,UAAM,iBAAiB,KAAK,aACzB,EAAE,YAAY,KAAK,WAAW,IAC9B;AACH,UAAM,WAAW,KAAK,cAAc,SAAS,QAAQ,cAAc;AAEnE,QAAI,KAAK,oBAAoB,KAAK,iBAAiB,SAAS,GAAG;AAC9D,YAAM,SAAS,MAAM,QAAQ,QAAQ,QAAQ;AAC7C,aAAO;AAAA,IACR;AACA,UAAM,QAAQ,QAAQ,QAAQ;AAC9B,WAAO;AAAA,EACR;AAAA,EAEA,MAAc,iBAAiB,SAA8B;AAC5D,UAAM,QAAQ,KAAK;AACnB,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,2CAA2C;AAEvE,WAAO;AAAA,MAAoB;AAAA,MAAO,CAAC,MAClC,KAAK,sBAAsB,SAAS,CAAC;AAAA,IACtC;AAAA,EACD;AAAA,EAEA,MAAc,sBACb,SACA,OACa;AACb,UAAM,SAAS,KAAK,YAAY;AAChC,UAAM,YAAY,OAAO;AACzB,UAAM,YAAY,KAAK,IAAI;AAG3B,UAAM,EAAE,aAAa,KAAK,IAAI,KAAK,kBAAkB,MAAM;AAG3D,QAAI,MAA2B,OAAO,OAAO;AAAA,MAC5C,OAAO,KAAK;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,KAAK,eAAe,SAAY,EAAE,YAAY,KAAK,WAAW,IAAI,CAAC;AAAA,MACvE,GAAI,KAAK,gBAAgB,EAAE,eAAe,KAAK,IAAI,CAAC;AAAA,IACrD,CAAC;AAED,QAAI;AAEH,UAAI,MAAM,eAAe,SAAS,GAAG;AACpC,cAAM,MAAM;AAAA,UACX,MAAM;AAAA,UACN;AAAA,UACA,KAAK;AAAA,QACN;AAAA,MACD;AAGA,YAAM,iBAAiB,KAAK,aACzB,EAAE,YAAY,KAAK,WAAW,IAC9B;AACH,YAAM,WAAW,KAAK,cAAc,SAAS,QAAQ,cAAc;AACnE,YAAM,WAAW,KAAK,IAAI,IAAI;AAE9B,UAAI,KAAK,oBAAoB,KAAK,iBAAiB,SAAS,GAAG;AAC9D,cAAM,SAAS,MAAM,QAAQ,QAAQ,QAAQ;AAG7C,cAAM,WAAgC,OAAO,OAAO;AAAA,UACnD,GAAG;AAAA,UACH,KAAK,SAAS;AAAA,UACd,YAAY,SAAS;AAAA,UACrB;AAAA,QACD,CAAC;AAGD,YAAI,MAAM,cAAc,SAAS,GAAG;AACnC,gBAAM,cAAc,MAAM;AAAA,YACzB,MAAM;AAAA,YACN;AAAA,YACA;AAAA,YACA,KAAK;AAAA,UACN;AACA,iBAAO;AAAA,QACR;AACA,eAAO;AAAA,MACR;AAEA,YAAM,QAAQ,QAAQ,QAAQ;AAG9B,UAAI,MAAM,cAAc,SAAS,GAAG;AACnC,cAAM,WAAgC,OAAO,OAAO;AAAA,UACnD,GAAG;AAAA,UACH,KAAK,SAAS;AAAA,UACd,YAAY,SAAS;AAAA,UACrB;AAAA,QACD,CAAC;AACD,cAAM;AAAA,UACL,MAAM;AAAA,UACN;AAAA,UACA,CAAC;AAAA,UACD,KAAK;AAAA,QACN;AAAA,MACD;AAEA,aAAO;AAAA,IACR,SAAS,OAAO;AAEf,UAAI,MAAM,QAAQ,SAAS,GAAG;AAC7B,cAAM,WAAW;AAAA,UAChB,OAAO,KAAK;AAAA,UACZ;AAAA,UACA;AAAA,UACA;AAAA,UACA,OAAO;AAAA,UACP,GAAI,KAAK,eAAe,SACrB,EAAE,YAAY,KAAK,WAAW,IAC9B,CAAC;AAAA,QACL;AACA,cAAM,cAAc,MAAM,gBAAgB,MAAM,SAAS,QAAQ;AACjE,cAAM;AAAA,MACP;AACA,YAAM;AAAA,IACP;AAAA,EACD;AAAA;AAAA,EAGQ,kBAAkB,QAGxB;AACD,QAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAAU;AACzD,YAAM,SAAU,OAAuC;AACvD,aAAO;AAAA,QACN,aAAa,OAAO,SAAS,IAAI,SAAS;AAAA,QAC1C,MAAM,OAAO,SAAS,IAAI,SAAS,OAAO,CAAC;AAAA,MAC5C;AAAA,IACD;AACA,QAAI,OAAO,SAAS,UAAU;AAC7B,aAAO;AAAA,QACN,aAAa;AAAA,QACb,MAAO,OAAwB;AAAA,MAChC;AAAA,IACD;AACA,QAAI,OAAO,SAAS,eAAe;AAClC,YAAM,UAAW,OAA6B;AAC9C,aAAO;AAAA,QACN,aAAa;AAAA,QACb,MAAM;AAAA,MACP;AAAA,IACD;AAEA,WAAO,EAAE,aAAa,UAAU,MAAM,OAAU;AAAA,EACjD;AACD;AAUO,IAAM,gBAAN,MAAM,uBAAgC,oBAG3C;AAAA,EACgB;AAAA,EAEE,gBAAgB;AAAA,EAEnC,YACC,MAIC;AACD,UAAM,IAAI;AACV,SAAK,aAAa,KAAK,UAAU,CAAC;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OACC,MACmB;AACnB,UAAM,aAAa,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AACrD,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,QAAQ;AAAA,MACR,WAAW,KAAK;AAAA,IACjB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,UACC,SACqB;AACrB,WAAO,IAAI,eAAmB;AAAA,MAC7B,GAAG,KAAK;AAAA,MACR,QAAQ,KAAK;AAAA,MACb,WAAW;AAAA,IACZ,CAAC;AAAA,EACF;AAAA,EAEU,cAA4B;AACrC,QAAI,KAAK,WAAW,WAAW,GAAG;AACjC,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,UAAM,SAAuB;AAAA,MAC5B,MAAM;AAAA,MACN,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,IACd;AAEA,QAAI,KAAK,oBAAoB,KAAK,iBAAiB,SAAS,GAAG;AAC9D,aAAO,EAAE,GAAG,QAAQ,WAAW,KAAK,iBAAiB;AAAA,IACtD;AAEA,WAAO;AAAA,EACR;AAAA,EAEU,cACT,SACA,QACA,SACgB;AAChB,WAAO,QAAQ,cAAc,QAAQ,OAAO;AAAA,EAC7C;AACD;AAUO,IAAM,gBAAN,MAAM,uBAAgC,oBAG3C;AAAA,EACgB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEE,gBAAgB;AAAA,EAEnC,YACC,MAQC;AACD,UAAM,IAAI;AACV,SAAK,UAAU,KAAK,OAAO,CAAC;AAC5B,SAAK,cAAc,KAAK;AACxB,SAAK,eAAe,KAAK,YAAY;AACrC,SAAK,oBAAoB,KAAK;AAC9B,SAAK,YAAY,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,MAAiD;AACpD,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,KAAK,EAAE,GAAG,KAAK,SAAS,GAAG,KAAK;AAAA,MAChC,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,WAAW,KAAK;AAAA,MAChB,mBAAmB,KAAK;AAAA,MACxB,WAAW,KAAK;AAAA,IACjB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAA0C;AAC/C,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,KAAK,KAAK;AAAA,MACV,OAAO;AAAA,MACP,UAAU,KAAK;AAAA,MACf,WAAW,KAAK;AAAA,MAChB,mBAAmB,KAAK;AAAA,MACxB,WAAW,KAAK;AAAA,IACjB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,UACC,SACqB;AACrB,WAAO,IAAI,eAAmB;AAAA,MAC7B,GAAG,KAAK;AAAA,MACR,KAAK,KAAK;AAAA,MACV,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,WAAW;AAAA,MACX,mBAAmB,KAAK;AAAA,MACxB,WAAW,KAAK;AAAA,IACjB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,SACC,aACA,MACmB;AACnB,UAAM,eAAe,MAAM,QAAQ,WAAW,IAC3C,cACA,CAAC,WAAW;AACf,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,KAAK,KAAK;AAAA,MACV,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,WAAW,KAAK;AAAA,MAChB,mBAAmB;AAAA,MACnB,WAAW;AAAA,IACZ,CAAC;AAAA,EACF;AAAA,EAEU,cAAgD;AAEzD,QAAI,KAAK,qBAAqB,KAAK,WAAW;AAC7C,UAAI,KAAK,UAAU,WAAW,GAAG;AAChC,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAEA,YAAMC,UAA4B;AAAA,QACjC,MAAM;AAAA,QACN,OAAO,KAAK;AAAA,QACZ,cAAc,KAAK;AAAA,QACnB,SAAS,KAAK;AAAA,MACf;AAEA,UAAI,OAAO,KAAK,KAAK,OAAO,EAAE,SAAS,GAAG;AACzC,eAAO,OAAOA,SAAQ,EAAE,WAAW,KAAK,QAAQ,CAAC;AAAA,MAClD;AACA,UAAI,KAAK,aAAa;AACrB,eAAO,OAAOA,SAAQ,EAAE,OAAO,KAAK,YAAY,CAAC;AAAA,MAClD;AACA,UAAI,KAAK,oBAAoB,KAAK,iBAAiB,SAAS,GAAG;AAC9D,eAAO,OAAOA,SAAQ,EAAE,WAAW,KAAK,iBAAiB,CAAC;AAAA,MAC3D;AAEA,aAAOA;AAAA,IACR;AAGA,QAAI,OAAO,KAAK,KAAK,OAAO,EAAE,WAAW,GAAG;AAC3C,YAAM,IAAI,sBAAsB,UAAU,qBAAqB;AAAA,IAChE;AAEA,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,cAAc;AAC5C,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,UAAM,SAAuB;AAAA,MAC5B,MAAM;AAAA,MACN,OAAO,KAAK;AAAA,MACZ,KAAK,KAAK;AAAA,IACX;AAEA,QAAI,KAAK,aAAa;AACrB,aAAO,OAAO,QAAQ,EAAE,OAAO,KAAK,YAAY,CAAC;AAAA,IAClD;AACA,QAAI,KAAK,cAAc;AACtB,aAAO,OAAO,QAAQ,EAAE,UAAU,KAAK,CAAC;AAAA,IACzC;AACA,QAAI,KAAK,oBAAoB,KAAK,iBAAiB,SAAS,GAAG;AAC9D,aAAO,OAAO,QAAQ,EAAE,WAAW,KAAK,iBAAiB,CAAC;AAAA,IAC3D;AAEA,WAAO;AAAA,EACR;AAAA,EAEU,cACT,SACA,QACA,SACgB;AAChB,QAAI,OAAO,SAAS,eAAe;AAClC,aAAO,QAAQ,mBAAmB,QAAQ,OAAO;AAAA,IAClD;AACA,WAAO,QAAQ,cAAc,QAAQ,OAAO;AAAA,EAC7C;AACD;AAUO,IAAM,gBAAN,MAAM,uBAAgC,oBAG3C;AAAA,EACgB;AAAA,EACA;AAAA,EACA;AAAA,EAEE,gBAAgB;AAAA,EAEnC,YACC,MAMC;AACD,UAAM,IAAI;AACV,SAAK,cAAc,KAAK;AACxB,SAAK,eAAe,KAAK,YAAY;AACrC,SAAK,mBAAmB,KAAK;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAA0C;AAC/C,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,OAAO;AAAA,MACP,UAAU,KAAK;AAAA,MACf,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,IACjB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,WAAiD;AACxD,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,SAAS,aAAa;AAAA,MACtB,WAAW,KAAK;AAAA,IACjB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,UACC,SACqB;AACrB,WAAO,IAAI,eAAmB;AAAA,MAC7B,GAAG,KAAK;AAAA,MACR,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,SAAS,KAAK;AAAA,MACd,WAAW;AAAA,IACZ,CAAC;AAAA,EACF;AAAA,EAEU,cAA4B;AACrC,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,cAAc;AAC5C,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,UAAM,SAAuB;AAAA,MAC5B,MAAM;AAAA,MACN,OAAO,KAAK;AAAA,IACb;AAEA,QAAI,KAAK,aAAa;AACrB,aAAO,OAAO,QAAQ,EAAE,OAAO,KAAK,YAAY,CAAC;AAAA,IAClD;AACA,QAAI,KAAK,cAAc;AACtB,aAAO,OAAO,QAAQ,EAAE,UAAU,KAAK,CAAC;AAAA,IACzC;AACA,QAAI,KAAK,qBAAqB,QAAW;AACxC,aAAO,OAAO,QAAQ,EAAE,SAAS,KAAK,iBAAiB,CAAC;AAAA,IACzD;AACA,QAAI,KAAK,oBAAoB,KAAK,iBAAiB,SAAS,GAAG;AAC9D,aAAO,OAAO,QAAQ,EAAE,WAAW,KAAK,iBAAiB,CAAC;AAAA,IAC3D;AAEA,WAAO;AAAA,EACR;AAAA,EAEU,cACT,SACA,QACA,SACgB;AAChB,WAAO,QAAQ,cAAc,QAAQ,OAAO;AAAA,EAC7C;AACD;AAmCO,IAAM,gBAAN,MAAM,uBAAgC,oBAG3C;AAAA,EACgB;AAAA,EACA;AAAA,EACA;AAAA,EAEE,gBAAgB;AAAA,EAEnC,YACC,MAMC;AACD,UAAM,IAAI;AACV,SAAK,aAAa,KAAK,UAAU,CAAC;AAClC,SAAK,iBAAiB,KAAK;AAC3B,SAAK,iBAAiB,KAAK;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OACC,MACmB;AACnB,UAAM,aAAa,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AACrD,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,QAAQ;AAAA,MACR,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK;AAAA,IACjB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,SAA8C;AACxD,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,QAAQ,KAAK;AAAA,MACb,YAAY,EAAE,QAAQ;AAAA,MACtB,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK;AAAA,IACjB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqB,gBAA0C;AAC9D,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,QAAQ,KAAK;AAAA,MACb,YAAY,EAAE,YAAY,eAAe;AAAA,MACzC,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK;AAAA,IACjB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,SACC,KACA,OACmB;AACnB,UAAM,SAA+B;AAAA,MACpC,MAAM;AAAA,MACN,GAAI,OAAO,EAAE,IAAI;AAAA,MACjB,GAAI,SAAS,EAAE,MAAM;AAAA,IACtB;AACA,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK;AAAA,MACjB;AAAA,MACA,WAAW,KAAK;AAAA,IACjB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAA8B;AAC7B,WAAO,IAAI,eAAc;AAAA,MACxB,GAAG,KAAK;AAAA,MACR,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK;AAAA,MACjB,QAAQ,EAAE,MAAM,YAAY;AAAA,MAC5B,WAAW,KAAK;AAAA,IACjB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UACC,SACqB;AACrB,WAAO,IAAI,eAAmB;AAAA,MAC7B,GAAG,KAAK;AAAA,MACR,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,MACb,WAAW;AAAA,IACZ,CAAC;AAAA,EACF;AAAA,EAEU,cAA4B;AACrC,QAAI,KAAK,WAAW,WAAW,GAAG;AACjC,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,QAAI,CAAC,KAAK,gBAAgB;AACzB,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,QAAI,CAAC,KAAK,gBAAgB;AACzB,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,UAAM,SAAuB;AAAA,MAC5B,MAAM;AAAA,MACN,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,YAAY,KAAK;AAAA,MACjB,QAAQ,KAAK;AAAA,IACd;AAEA,QAAI,KAAK,oBAAoB,KAAK,iBAAiB,SAAS,GAAG;AAC9D,aAAO,EAAE,GAAG,QAAQ,WAAW,KAAK,iBAAiB;AAAA,IACtD;AAEA,WAAO;AAAA,EACR;AAAA,EAEU,cACT,SACA,QACA,SACgB;AAChB,WAAO,QAAQ,cAAc,QAAQ,OAAO;AAAA,EAC7C;AACD;;;ACz8BA,SAAS,+BAA+B;AAcxC,SAAS,gBACR,SACA,QAC6B;AAC7B,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,SAAO,OAAO,YAAY,OAAO,KAAK,OAAO;AAC9C;AAaO,SAAS,kBACf,OACA,cACA,WAA+D,WAC/D,WAAsC,0BAClB;AACpB,QAAM,WAA6B,CAAC;AACpC,QAAM,cAAc,aAAa;AAEjC,aAAW,WAAW,UAAU;AAC/B,QAAI,aAAa,QAAQ,UAAU,EAAG;AACtC,UAAM,SAAS,QAAQ,YAAY,KAAK;AACxC,QAAI,OAAO,WAAW,EAAG;AACzB,UAAM,oBAAoB,gBAAgB,QAAQ,SAAS,QAAQ;AACnE,QAAI,sBAAsB,SAAU;AACpC,eAAW,SAAS,QAAQ;AAC3B,UAAI,sBAAsB,SAAS;AAClC,cAAM,IAAI;AAAA,UACT,QAAQ;AAAA,UACR;AAAA,UACA,MAAM;AAAA,QACP;AAAA,MACD;AAEA,YAAM,UAAU,wBAAwB,QAAQ,OAAO,iBAAiB,WAAW,UAAU,MAAM,MAAM;AACzG,eAAS,KAAK;AAAA,QACb,SAAS,QAAQ;AAAA,QACjB,SAAS;AAAA,QACT,SAAS,MAAM;AAAA,QACf;AAAA,MACD,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO,EAAE,SAAS;AACnB;;;AC1DA,SAAkC,WAAW,kBAAkB;AAwExD,SAAS,aAAa,OAAgB,OAAuB;AACnE,MAAI,UAAU,MAAM;AACnB,WAAO;AAAA,EACR;AACA,UAAQ,OAAO,OAAO;AAAA,IACrB,KAAK;AACJ,aAAO,QAAQ,SAAS;AAAA,IACzB,KAAK,UAAU;AACd,UAAI,CAAC,OAAO,SAAS,KAAK,GAAG;AAC5B,cAAM,IAAI;AAAA,UACT,qDAAqD,KAAK,iBAAiB,KAAK;AAAA,QAGjF;AAAA,MACD;AAGA,YAAM,IAAI,QAAQ,IAAI,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,OAAO,KAAK;AAI1D,UAAI,OAAO,KAAK,CAAC,GAAG;AACnB,cAAM,IAAI;AAAA,UACT,sBAAsB,KAAK,gBAAgB,KAAK;AAAA,QAEjD;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAAA,IACA,KAAK,UAAU;AACd,UAAI,MAAM,SAAS,IAAI,KAAK,MAAM,SAAS,IAAI,GAAG;AACjD,cAAM,IAAI;AAAA,UACT,4EAA4E,KAAK;AAAA,QAGlF;AAAA,MACD;AAGA,YAAM,UAAU,MAAM,WAAW,KAAK,IAAI;AAC1C,aAAO,IAAI,OAAO;AAAA,IACnB;AAAA,IACA,SAAS;AACR,YAAM,WAAW,UAAU,SAAY,cAAc,OAAO;AAC5D,YAAM,IAAI;AAAA,QACT,iDAAiD,QAAQ,iBAAiB,KAAK;AAAA,MAGhF;AAAA,IACD;AAAA,EACD;AACD;AAkBO,SAAS,aACf,kBACA,OACA,SACA,YACS;AACT,SAAO,SAAS,IACf,YACG,QACa;AAIhB,QAAI,QAAgB,QAAQ,CAAC,KAAK;AAClC,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,eAAS,aAAa,OAAO,CAAC,GAAG,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK;AAAA,IAC1D;AAEA,WAAO,IAAI;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACD;AAMA,IAAM,iBAAN,MAAiD;AAAA,EACxC;AAAA,EACS;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EAEjB,YACC,OACA,kBACA,OACA,SACA,YACC;AACD,SAAK,QAAQ;AACb,SAAK,mBAAmB;AACxB,SAAK,QAAQ;AACb,SAAK,UAAU;AACf,SAAK,cAAc;AAAA,EACpB;AAAA,EAEQ,UAAuB;AAC9B,QAAI,KAAK,SAAS;AACjB,aAAO,KAAK;AAAA,IACb;AAGA,UAAM,kBAAkB,4BAA4B,KAAK,KAAK;AAG9D,UAAM,SAAS;AAAA,MACd,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACD;AACA,QAAI,CAAC,OAAO,SAAS;AACpB,YAAM,SACL,OAAO,QAAQ,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK;AACpD,YAAM,IAAI,MAAM,2BAA2B,MAAM,EAAE;AAAA,IACpD;AACA,QAAI,OAAO,KAAK,YAAY,CAAC,OAAO,KAAK,OAAO;AAC/C,YAAM,IAAI;AAAA,QACT;AAAA,MAGD;AAAA,IACD;AACA,QAAI,CAAC,OAAO,KAAK,OAAO;AACvB,YAAM,IAAI,MAAM,+CAA+C;AAAA,IAChE;AAIA,SAAK,UAAU,OAAO,IAAI;AAC1B,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,aAA0B;AACzB,WAAO,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,OAAmB;AAClB,UAAM,SAAS,KAAK,QAAQ;AAC5B,WAAO,KAAY,QAAQ,KAAK,KAAK;AAAA,EACtC;AAAA,EAEA,KAAK,MAA4B;AAChC,UAAM,aAAa,KAAK,KAAK;AAE7B,QAAI,CAAC,KAAK,SAAS;AAClB,aAAO;AAAA,QACN,MAAM;AAAA,QACN,KAAK;AAAA,QACL,QAAQ,CAAC;AAAA,QACT,GAAI,SAAS,UAAa,EAAE,KAAK;AAAA,MAClC;AAAA,IACD;AAEA,UAAM,WAAW,KAAK,QAAQ,QAAW,UAAU;AAEnD,QAAI;AACH,aAAO,KAAK,QAAQ,WAAW,YAAY,UAAU,IAAI;AAAA,IAC1D,SAAS,KAAK;AACb,UACC,eAAe,SACf,IAAI,QAAQ,YAAY,EAAE,SAAS,iBAAiB,GACnD;AAED,cAAM,OAAa;AAAA,UAClB,MAAM;AAAA,UACN,KAAK,SAAS;AAAA,UACd,QAAQ,SAAS;AAAA,QAClB;AACA,YAAI,SAAS,QAAW;AACvB,iBAAO;AAAA,YACN,GAAG;AAAA,YACH,MAAM;AAAA,cACL,GAAI,KAAK,cAAc,UAAa;AAAA,gBACnC,WAAW,KAAK;AAAA,cACjB;AAAA,cACA,GAAI,KAAK,kBAAkB,UAAa;AAAA,gBACvC,eAAe,KAAK;AAAA,cACrB;AAAA,YACD;AAAA,UACD;AAAA,QACD;AACA,eAAO;AAAA,MACR;AACA,YAAM;AAAA,IACP;AAAA,EACD;AAAA,EAEA,MAAM,MAAoB;AACzB,QAAI,CAAC,KAAK,SAAS;AAClB,YAAM,IAAI;AAAA,QACT;AAAA,MAED;AAAA,IACD;AAEA,UAAM,aAAa,KAAK,KAAK;AAC7B,UAAM,WAAW,KAAK,QAAQ,QAAW,UAAU;AACnD,WAAO,KAAK,QAAQ,QAAQ,QAAQ;AAAA,EACrC;AAAA,EAEA,MAAM,QAA2B;AAChC,UAAM,OAAO,MAAM,KAAK,IAAI;AAC5B,WAAO,KAAK,CAAC,KAAK;AAAA,EACnB;AACD;AAWO,SAAS,4BACf,OACiC;AACjC,QAAM,cAAc,oBAAI,IAAY;AACpC,QAAM,oBAAoB,oBAAI,IAAY;AAE1C,aAAW,SAAS,MAAM,OAAO,OAAO,GAAG;AAC1C,QAAI,CAAC,MAAM,cAAe;AAC1B,eAAW,MAAM,MAAM,eAAe;AACrC,kBAAY,IAAI,GAAG,WAAW,YAAY,CAAC;AAC3C,kBAAY,IAAI,GAAG,UAAU,YAAY,CAAC;AAC1C,kBAAY,IAAI,GAAG,iBAAiB,YAAY,CAAC;AACjD,kBAAY,IAAI,GAAG,kBAAkB,YAAY,CAAC;AAClD,wBAAkB,IAAI,GAAG,iBAAiB,YAAY,CAAC;AACvD,wBAAkB,IAAI,GAAG,kBAAkB,YAAY,CAAC;AAAA,IACzD;AAAA,EACD;AAGA,MAAI,YAAY,SAAS,EAAG,QAAO;AAEnC,SAAO;AAAA,IACN,sBAAsB,CAAC,GAAG,WAAW;AAAA,IACrC,mBAAmB,CAAC,GAAG,iBAAiB;AAAA,EACzC;AACD;;;ACxVO,SAAS,sBACf,QACA,OACM;AACN,MAAI,UAAU,KAAM,QAAO,CAAC;AAC5B,QAAM,MAAM;AACZ,SAAQ,IAAI,KAAK,KAAa,CAAC;AAChC;AAUO,SAAS,oBACf,OACA,OACA,WACwC;AAExC,QAAM,iBAAiB,MAAM,iBAAiB,KAAK;AACnD,MAAI,CAAC,kBAAkB,eAAe,WAAW,GAAG;AACnD,WAAO;AAAA,EACR;AAGA,aAAW,YAAY,gBAAgB;AAEtC,QAAI,SAAS,WAAW,SAAS,QAAQ;AACxC;AAAA,IACD;AAGA,QAAI,cAAc,aAAa;AAE9B,UAAI,SAAS,SAAS,eAAe,SAAS,SAAS,UAAU;AAChE,eAAO,EAAE,MAAM,SAAS,MAAM,MAAM,SAAS,KAAK;AAAA,MACnD;AAAA,IACD,OAAO;AAEN,UAAI,SAAS,SAAS,WAAW;AAChC,eAAO,EAAE,MAAM,SAAS,MAAM,MAAM,SAAS,KAAK;AAAA,MACnD;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;;;ACnCA,SAAS,iBAAiB,SAAuC;AAChE,MAAI,OAAO,YAAY,SAAU,QAAO;AACxC,MAAI,OAAO,QAAQ,UAAU,SAAU,QAAO,QAAQ;AACtD,QAAM,QAAS,QAA+B;AAC9C,SAAO,SAAS;AACjB;AAaO,SAAS,sBACf,SACA,cACA,WACqB;AACrB,MAAI,QAAQ,eAAe,WAAW,GAAG;AACxC,UAAM,UAAU,QAAQ,eAAe,CAAC;AACxC,QAAI,CAAC,QAAS,QAAO;AAErB,UAAM,QAAQ,iBAAiB,OAAO;AACtC,QAAI,UAAU,KAAM,QAAO;AAE3B,UAAM,UACL,OAAO,YAAY,WAChB,QACE,QAAQ,aAAwB;AACtC,UAAM,cAAc,aAAa,KAAK;AAEtC,QAAI,gBAAgB,QAAW;AAC9B,aAAO;AAAA,IACR;AAEA,UAAM,QACL,YAAY,QAAQ,cAAc,YAAY,cAAc;AAC7D,WAAO;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,UAAU,QAAQ,OAAO;AAAA,MACzB,OAAO;AAAA,IACR;AAAA,EACD;AAEA,QAAM,aAA4B,CAAC;AAEnC,WAAS,IAAI,GAAG,IAAI,QAAQ,eAAe,QAAQ,KAAK;AACvD,UAAM,QAAuB,CAAC;AAE9B,aAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC5B,YAAM,UAAU,QAAQ,eAAe,CAAC;AACxC,UAAI,CAAC,QAAS;AAEd,YAAM,QAAQ,iBAAiB,OAAO;AACtC,UAAI,UAAU,KAAM;AAEpB,YAAM,UACL,OAAO,YAAY,WAChB,QACE,QAAQ,aAAwB;AACtC,YAAM,cAAc,aAAa,KAAK;AAEtC,UAAI,gBAAgB,QAAW;AAC9B,eAAO;AAAA,MACR;AAEA,UAAI,IAAI,GAAG;AACV,cAAM,KAAK;AAAA,UACV,MAAM;AAAA,UACN;AAAA,UACA,UAAU;AAAA,UACV,OAAO;AAAA,QACR,CAAC;AAAA,MACF,OAAO;AACN,cAAM,QACL,YAAY,QACT,cAAc,YACd,cAAc;AAClB,cAAM,KAAK;AAAA,UACV,MAAM;AAAA,UACN;AAAA,UACA,UAAU,QAAQ,OAAO;AAAA,UACzB,OAAO;AAAA,QACR,CAAC;AAAA,MACF;AAAA,IACD;AAEA,QAAI,MAAM,SAAS,GAAG;AACrB,iBAAW;AAAA,QACV,MAAM,WAAW,IACb,MAAM,CAAC,IACR,EAAE,MAAM,OAAO,YAAY,MAAM;AAAA,MACrC;AAAA,IACD;AAAA,EACD;AAEA,MAAI,WAAW,WAAW,GAAG;AAC5B,WAAO;AAAA,EACR;AAEA,QAAM,iBAAiB,WAAW,CAAC;AACnC,SAAO,WAAW,WAAW,KAAK,mBAAmB,SAClD,iBACA,EAAE,MAAM,MAAM,WAAW;AAC7B;AAaO,SAAS,YACf,SACA,KACS;AACT,QAAM,aAAsC,uBAAO,OAAO,IAAI;AAE9D,aAAW,WAAW,QAAQ,gBAAgB;AAC7C,QAAI,CAAC,QAAS;AACd,QAAI,OAAO,YAAY,UAAU;AAChC,iBAAW,OAAO,IAAI,IAAI,OAAO;AAAA,IAClC,OAAO;AACN,YAAM,QAAQ,QAAQ;AACtB,UAAI,OAAO,UAAU,UAAU;AAC9B,mBAAW,KAAK,IAAI,IAAI,KAAK;AAAA,MAC9B,OAAO;AACN,cAAM,QAAS,QAA+B;AAC9C,YAAI,CAAC,OAAO;AACX,gBAAM,IAAI;AAAA,YACT;AAAA,YACA;AAAA,UAED;AAAA,QACD;AACA,mBAAW,KAAK,IAAI,IAAI,KAAK;AAAA,MAC9B;AAAA,IACD;AAAA,EACD;AAEA,SAAO,OAAO,KAAK,KAAK,UAAU,UAAU,GAAG,OAAO,EAAE,SAAS,QAAQ;AAC1E;AAWA,eAAsB,SACrB,SACA,SACoC;AACpC,QAAM,OAAO,SAAS,QAAQ;AAC9B,QAAM,UAAU,SAAS,WAAW;AACpC,QAAM,YAAY,SAAS,aAAa;AAExC,MAAI,CAAC,OAAO,cAAc,IAAI,KAAK,OAAO,GAAG;AAC5C,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACA,MAAI,CAAC,OAAO,cAAc,OAAO,KAAK,UAAU,GAAG;AAClD,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAEA,QAAM,UAAU,OAAO,KAAK;AAE5B,QAAM,mBAAmB,QAAQ,MAAM;AACvC,mBAAiB,aAAa;AAC9B,mBAAiB,cAAc;AAE/B,QAAM,OAAO,MAAM,iBAAiB,IAAI;AAExC,MAAI;AACJ,MAAI;AAEJ,MAAI,WAAW;AAMd,UAAM,UAAU,QAAQ,qBAAqB;AAC7C,UAAM,iBAA0D;AAAA,MAC/D,OAAO,QAAQ,IAAI;AAAA,IACpB;AACA,QAAI,QAAQ,IAAI,eAAe,QAAW;AACzC,qBAAe,aAAa,QAAQ,IAAI;AAAA,IACzC;AAEA,UAAM,aAAa,QAAQ,cAAc,SAAS;AAClD,UAAM,WAAW,QAAQ,YAAY,SAAS;AAE9C,QAAI,cAAc,UAAU;AAC3B,YAAM,cAAc,QAAQ,MAAM;AAClC,kBAAY,aAAa;AACzB,kBAAY,cAAc;AAC1B,kBAAY,eAAe,OAAO,CAAC;AACnC,kBAAY,SAAS,OAAO,CAAC;AAC7B,kBAAY,kBAAkB,OAAO,CAAC;AACtC,kBAAY,WAAW,OAAO,CAAC;AAC/B,kBAAY,eAAe;AAE3B,YAAM,WAAW,YAAY,KAAK;AAClC,YAAM,eAAe,QAAQ,QAAQ,UAAU,cAAc;AAE7D,YAAM,UAAU,qCAAqC,aAAa,GAAG;AACrE,YAAM,aAAc,MAAM,QAAQ,QAAQ;AAAA,QACzC,KAAK;AAAA,QACL,YAAY,aAAa;AAAA,MAC1B,CAAC;AACD,cAAQ,OAAO,WAAW,CAAC,GAAG,UAAU,CAAC;AAAA,IAC1C,OAAO;AACN,YAAM,eAAe,QAAQ,MAAM;AAGnC,mBAAa,aAAa;AAC1B,mBAAa,cAAc;AAC3B,mBAAa,eAAe,OAAO,CAAC;AACpC,mBAAa,WAAW,OAAO,GAAG,aAAa,WAAW,QAAQ;AAAA,QACjE,UAAU;AAAA,QACV,IAAI;AAAA,MACL,CAAC;AACD,mBAAa,SAAS,OAAO,CAAC;AAC9B,mBAAa,kBAAkB,OAAO,CAAC;AACvC,mBAAa,eAAe;AAE5B,YAAM,cAAc,MAAM,aAAa,IAAI;AAC3C,cAAQ,OAAO,YAAY,CAAC,GAAG,UAAU,CAAC;AAAA,IAC3C;AACA,iBAAa,KAAK,KAAK,QAAQ,OAAO;AAAA,EACvC;AAEA,QAAM,cAAc,YACjB,QAAQ,cAAc,KACtB,KAAK,WAAW;AACnB,QAAM,cAAc,OAAO;AAE3B,SAAO;AAAA,IACN;AAAA,IACA,YAAY;AAAA,MACX;AAAA,MACA;AAAA,MACA,GAAI,UAAU,UAAa,EAAE,MAAM;AAAA,MACnC,GAAI,eAAe,UAAa,EAAE,WAAW;AAAA,MAC7C;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACD;AAWA,eAAsB,eACrB,SACA,SAC0C;AAC1C,QAAM,QAAQ,SAAS,SAAS;AAChC,QAAM,SAAS,SAAS,UAAU;AAClC,QAAM,YAAY,SAAS,aAAa;AAGxC,MAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,GAAG;AAC9C,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAGA,MAAI,QAAQ,eAAe,WAAW,GAAG;AACxC,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAGA,MAAI,eAA+C;AACnD,MAAI,QAAQ;AACX,QAAI;AACJ,QAAI;AACH,eAAS,KAAK,MAAM,OAAO,KAAK,QAAQ,QAAQ,EAAE,SAAS,OAAO,CAAC;AAAA,IACpE,QAAQ;AACP,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,QACC,OAAO,WAAW,YAClB,WAAW,QACX,MAAM,QAAQ,MAAM,GACnB;AACD,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAEA,UAAM,aAAsC,uBAAO,OAAO,IAAI;AAC9D,eAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACtC,UAAI,OAAO,OAAO,QAAmC,GAAG,GAAG;AAC1D,QAAC,WAAuC,GAAG,IAC1C,OACC,GAAG;AAAA,MACN;AAAA,IACD;AACA,mBAAe;AAAA,EAChB;AAGA,QAAM,mBAAmB,QAAQ,MAAM;AACvC,MAAI,cAAc;AACjB,UAAM,mBAAmB;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,IACD;AACA,QAAI,kBAAkB;AACrB,uBAAiB,aAAa,KAAK,gBAAgB;AAAA,IACpD;AAAA,EACD;AAKA,MAAI,cAAc,YAAY;AAC7B,qBAAiB,eAAe;AAAA,MAC/B;AAAA,MACA,iBAAiB,eAAe;AAAA,MAChC,GAAG,iBAAiB,eAAe,IAAI,CAAC,QAAQ;AAAA,QAC/C,GAAG;AAAA,QACH,WAAY,GAAG,cAAc,QAAQ,SAAS;AAAA,MAC/C,EAAE;AAAA,IACH;AAAA,EACD;AAGA,mBAAiB,aAAa,QAAQ;AAGtC,QAAM,aAAa,MAAM,iBAAiB,IAAI;AAE9C,QAAM,UAAU,WAAW,SAAS;AACpC,QAAM,SAAS,UAAU,WAAW,MAAM,GAAG,KAAK,IAAI;AAGtD,QAAM,OAAO,cAAc,aAAa,OAAO,MAAM,EAAE,QAAQ,IAAI;AAEnE,QAAM,aACL,WAAW,KAAK,SAAS,IACtB,YAAY,SAAS,KAAK,KAAK,SAAS,CAAC,CAA4B,IACrE;AACJ,QAAM,aACL,KAAK,SAAS,IACX,YAAY,SAAS,KAAK,CAAC,CAA4B,IACvD;AAEJ,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA,YACC,cAAc,YAAa,SAAS,aAAa,OAAQ;AAAA,IAC1D,aAAa,cAAc,YAAY,UAAU,WAAW;AAAA,IAC5D,aAAa,cAAc,YAAY,WAAW,OAAO;AAAA,EAC1D;AACD;;;AC1ZO,SAAS,uBACf,SACA,YACO;AAEP,QAAM,mBAAmB,WAAW,UAAU;AAAA,IAC7C,CAAC,MAAM,EAAE,SAAS,sBAAsB,EAAE,WAAW;AAAA,EACtD;AAEA,MAAI,iBAAiB,WAAW,GAAG;AAClC;AAAA,EACD;AAOA,QAAM,eAAe,oBAAI,IAGvB;AACF,aAAW,YAAY,kBAAkB;AACxC,UAAM,gBAAgB,SAAS,SAAS;AACxC,UAAM,eAAe,SAAS,SAAS;AACvC,UAAM,eAAe,SAAS,SAAS;AACvC,UAAM,UAAU,iBAAiB,eAAe,iBAAiB;AAGjE,QAAI,OAAO,kBAAkB,UAAU;AACtC,mBAAa,IAAI,eAAe;AAAA,QAC/B;AAAA,QACA,cACC,OAAO,iBAAiB,WAAW,eAAe;AAAA,QACnD;AAAA,MACD,CAAC;AAAA,IACF,WAAW,OAAO,iBAAiB,UAAU;AAE5C,mBAAa,IAAI,cAAc,EAAE,SAAS,aAAa,CAAC;AAAA,IACzD;AAAA,EACD;AAEA,MAAI,aAAa,SAAS,GAAG;AAC5B;AAAA,EACD;AAGA,aAAW,OAAO,SAAS;AAC1B,QAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC5C;AAAA,IACD;AAEA,UAAMC,UAAS;AAEf,eAAW,CAAC,cAAc,IAAI,KAAK,cAAc;AAKhD,YAAM,aAAa,CAAC,YAAY;AAChC,UAAI,KAAK,gBAAgB,KAAK,iBAAiB,cAAc;AAC5D,mBAAW,KAAK,KAAK,YAAY;AAAA,MAClC;AAEA,UAAI,mBAAkC;AACtC,iBAAW,YAAY,YAAY;AAClC,cAAM,YAAY,GAAG,QAAQ;AAC7B,cAAM,YAAY,UAAU;AAAA,UAAQ;AAAA,UAAa,CAAC,GAAG,MACpD,EAAE,YAAY;AAAA,QACf;AACA,YAAI,aAAaA,SAAQ;AACxB,6BAAmB;AACnB;AAAA,QACD;AACA,YAAI,aAAaA,SAAQ;AACxB,6BAAmB;AACnB;AAAA,QACD;AAAA,MACD;AAEA,UAAI,kBAAkB;AACrB,cAAM,YAAYA,QAAO,gBAAgB;AAGzC,YAAI;AACJ,YAAI,OAAO,cAAc,UAAU;AAClC,cAAI;AACH,qBAAS,KAAK,MAAM,SAAS;AAAA,UAC9B,QAAQ;AACP,qBAAS,KAAK,UAAU,OAAO,CAAC;AAAA,UACjC;AAAA,QACD,WAAW,MAAM,QAAQ,SAAS,GAAG;AACpC,mBAAS;AAAA,QACV,WAAW,cAAc,QAAQ,cAAc,QAAW;AACzD,mBAAS,KAAK,UAAU,OAAO,CAAC;AAAA,QACjC,OAAO;AACN,mBAAS;AAAA,QACV;AAGA,YAAI,KAAK,WAAW,MAAM,QAAQ,MAAM,GAAG;AAC1C,mBAAS,OAAO,SAAS,IAAI,OAAO,CAAC,IAAI;AAAA,QAC1C;AAIA,cAAM,YAAY,KAAK,gBAAgB;AACvC,QAAAA,QAAO,SAAS,IAAI;AACpB,eAAOA,QAAO,gBAAgB;AAAA,MAC/B;AAAA,IACD;AAAA,EACD;AACD;;;ACxEA,IAAM,oBAAoB;AAEnB,IAAM,iBAAN,MAAwC;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,OAAgB,MAAc,YAAqB;AAC9D,SAAK,QAAQ;AACb,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBACL,SACA,kBACA,SACA,gBACgB;AAChB,QAAI,QAAQ,WAAW,EAAG;AAE1B,eAAW,eAAe,kBAAkB;AAI3C,YAAM,YAAuB,CAAC;AAC9B,iBAAW,KAAK,SAAS;AACxB,cAAM,KAAK,KAAK;AAAA,UACf;AAAA,UACA,YAAY;AAAA,QACb;AACA,YAAI,OAAO,UAAa,OAAO,KAAM,WAAU,KAAK,EAAE;AAAA,MACvD;AAEA,UAAI,UAAU,WAAW,EAAG;AAG5B,YAAM,eAAe,QAAQ;AAAA,QAC5B;AAAA,QACA;AAAA,QACA;AAAA,MACD;AACA,YAAM,eAAe,MAAM,QAAQ,QAAQ,YAAY;AAGvD,YAAM,qBAAqB,oBAAI,IAAwB;AACvD,iBAAW,SAAS,cAAc;AACjC,cAAM,WAAW,KAAK;AAAA,UACrB;AAAA,UACA,YAAY;AAAA,QACb;AACA,YAAI,aAAa,QAAW;AAC3B,gBAAM,WAAW,mBAAmB,IAAI,QAAQ;AAChD,cAAI,UAAU;AACb,qBAAS,KAAK,KAAK;AAAA,UACpB,OAAO;AACN,+BAAmB,IAAI,UAAU,CAAC,KAAK,CAAC;AAAA,UACzC;AAAA,QACD;AAAA,MACD;AAIA,YAAM,UACL,YAAY,iBAAiB,eAC7B,YAAY,iBAAiB;AAC9B,iBAAW,UAAU,SAAS;AAC7B,cAAM,WAAW,KAAK;AAAA,UACrB;AAAA,UACA,YAAY;AAAA,QACb;AACA,cAAM,WAAW,mBAAmB,IAAI,QAAQ,KAAK,CAAC;AACtD,QAAC,OAAmC,YAAY,YAAY,IAAI,UAC5D,SAAS,CAAC,KAAK,OAChB;AAAA,MACJ;AAGA,UAAI,YAAY,kBAAkB,YAAY,eAAe,SAAS,GAAG;AAIxE,cAAM,cAAyC,CAAC;AAChD,mBAAW,OAAO,mBAAmB,OAAO,GAAG;AAC9C,qBAAW,QAAQ;AAClB,wBAAY,KAAK,IAA+B;AAAA,QAClD;AACA,YAAI,YAAY,SAAS,GAAG;AAC3B,gBAAM,KAAK;AAAA,YACV;AAAA,YACA,YAAY;AAAA,YACZ;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,SAAoB,YAA8B;AAErE,UAAM,gBAAgB,WAAW,UAAU;AAAA,MAC1C,CAAC,MAAM,EAAE,SAAS,sBAAsB,EAAE,WAAW;AAAA,IACtD;AAEA,QAAI,cAAc,WAAW,GAAG;AAC/B;AAAA,IACD;AAGA,UAAM,YAAY,cAChB,IAAI,CAAC,MAAM,EAAE,SAAS,QAAQ,EAC9B,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ,EAChD,IAAI,CAAC,cAAc,EAAE,UAAU,QAAQ,GAAG,QAAQ,IAAI,EAAE;AAE1D,QAAI,UAAU,WAAW,GAAG;AAC3B;AAAA,IACD;AAYA,UAAM,qBAAiC,UAAU,IAAI,CAAC,UAAU;AAAA,MAC/D,GAAG;AAAA,MACH,YAAY;AAAA,IACb,EAAE;AAEF,QAAI,QAAQ,SAAS,GAAG;AAEvB,YAAM,WAAW,QAAQ;AAAA,QACxB,CAAC,MAA6B,OAAO,MAAM,YAAY,MAAM;AAAA,MAC9D;AACA,UAAI,UAAU;AACb,cAAM,cAAc;AACpB,cAAM,UAAU,OAAO,KAAK,WAAW;AACvC,mBAAW,QAAQ,oBAAoB;AACtC,eAAK,aAAa,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,KAAK,MAAM,CAAC;AAAA,QAClE;AAAA,MACD;AAAA,IACD;AAGA,eAAW,OAAO,SAAS;AAC1B,UAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC5C;AAAA,MACD;AAEA,YAAMC,UAAS;AAEf,iBAAW,QAAQ,oBAAoB;AAEtC,cAAM,OACL,KAAK,cAAc,KAAK,WAAW,SAAS,IACzC,KAAK,aACL,OAAO,KAAKA,OAAM,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,KAAK,MAAM,CAAC;AAE/D,YAAI,KAAK,WAAW,EAAG;AAEvB,cAAM,YAAqC,CAAC;AAC5C,YAAI,UAAU;AAId,mBAAW,OAAO,MAAM;AACvB,gBAAM,MAAMA,QAAO,GAAG;AACtB,cAAI,QAAQ,QAAW;AAEtB,sBAAU,IAAI,MAAM,KAAK,OAAO,MAAM,CAAC,IAAI;AAC3C,mBAAOA,QAAO,GAAG;AACjB,gBAAI,QAAQ,KAAM,WAAU;AAAA,UAC7B;AAAA,QACD;AAGA,QAAAA,QAAO,KAAK,QAAQ,IAAI,UAAU,OAAO;AAAA,MAC1C;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,uBAAuB,SAAoB,YAA8B;AACxE,2BAA6B,SAAS,UAAU;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,yBACL,SACA,mBACA,SACgB;AAChB,QAAI,QAAQ,WAAW,EAAG;AAE1B,eAAW,UAAU,mBAAmB;AACvC,YAAM,KAAK;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,2BACb,SACA,QACA,SACgB;AAChB,UAAM,EAAE,UAAU,QAAQ,IAAI;AAC9B,UAAM;AAAA,MACL;AAAA,MACA,OAAO;AAAA,MACP,WAAW;AAAA,MACX,WAAW;AAAA,MACX,eAAe;AAAA,IAChB,IAAI;AAGJ,UAAM,gBAAgB,GAAG,KAAK,IAAI,IAAI,QAAQ;AAC9C,UAAM,eAAe,KAAK,MAAM,YAAY,aAAa;AACzD,QAAI,CAAC,cAAc;AAElB,YAAM,iBAAiB,KAAK,MAAM,iBAAiB,KAAK,IAAI;AAC5D,YAAM,YAAY,gBAAgB,IAAI,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC;AACzD,YAAM,IAAI,sBAAsB;AAAA,QAC/B,OAAO,KAAK;AAAA,QACZ,WAAW;AAAA,QACX;AAAA,MACD,CAAC;AAAA,IACF;AAGA,UAAM,WAAW,KAAK,oBAAoB,aAAa,UAAU;AAKjE,UAAM,WAAW,QACf,IAAI,CAAC,MAAM,EAAE,EAAa,EAC1B,OAAO,CAAC,OAAO,OAAO,UAAa,OAAO,IAAI;AAEhD,QAAI,SAAS,WAAW,EAAG;AAG3B,UAAM,UAAU,cAAc,QAAQ,IAAI,SAAS;AACnD,UAAM,kBAAkB,KAAK;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAGA,UAAM,SAAS,cAAc,iBAAiB,KAAK,KAAK;AAGxD,UAAM,iBAA0C,CAAC;AACjD,QAAI,KAAK,eAAe,QAAW;AAClC,qBAAe,aAAa,KAAK;AAAA,IAClC;AAEA,UAAM,oBAAoB,QAAQ;AAAA,MACjC;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACD;AAGA,UAAM,gBAAiB,MAAM,QAAQ,QAAQ,iBAAiB;AAM9D,SAAK;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,qBACP,SACA,cACA,UACA,WACA,UACA,cACkB;AAClB,UAAM,EAAE,QAAQ,WAAW,IAAI;AAG/B,UAAM,WAAW,KAAK,oBAAoB,UAAU;AAOpD,UAAM,aACL,SAAS,WAAW,IACjB;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO,SAAS,CAAC;AAAA,IAClB,IACC;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,IACT;AAGH,UAAM,YAAY,KAAK,qBAAqB,QAAQ,UAAU,SAAS;AAGvE,UAAM,SAAmC;AAAA,MACxC,MAAM;AAAA,MACN;AAAA,MACA,OAAO;AAAA,QACN,MAAM;AAAA,QACN,YAAY,EAAE,MAAM,UAAU,MAAM,KAAK;AAAA,QACzC,OAAO;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAGA,QAAI,cAAc;AACjB,aAAO,QAAQ,EAAE,OAAO,CAAC,EAAE;AAAA,IAC5B;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKQ,oBACP,YACS;AACT,QAAI,CAAC,YAAY;AAChB,aAAO;AAAA,IACR;AACA,QAAI,OAAO,eAAe,UAAU;AACnC,aAAO;AAAA,IACR;AAEA,UAAM,QAAQ,WAAW,CAAC;AAC1B,WAAO,SAAS;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKQ,qBACP,WACA,gBACA,WAC+B;AAI/B,WAAO;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,MACR,UAAU;AAAA,MACV;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,sBACP,SACA,eACA,UACA,WACA,YACA,MACA,UACO;AAEP,UAAM,mBAAmB,oBAAI,IAA0B;AAEvD,eAAW,OAAO,eAAe;AAGhC,YAAM,UAAU,IAAI,YAAY,IAAI;AACpC,YAAM,WAAW,iBAAiB,IAAI,OAAO,KAAK,CAAC;AAGnD,UAAI,YAAY,IAAI,UAAU,GAAG;AAChC;AAAA,MACD;AAEA,eAAS,KAAK,GAAG;AACjB,uBAAiB,IAAI,SAAS,QAAQ;AAAA,IACvC;AAGA,UAAM,iBACL,cAAc,cACX,aAAa,WACZ,cACA,GAAG,QAAQ,eACZ,aAAa,aACZ,gBACA,GAAG,QAAQ;AAGhB,eAAW,UAAU,SAAS;AAC7B,YAAM,KAAK,OAAO;AAClB,YAAM,gBAAgB,iBAAiB,IAAI,EAAE,KAAK,CAAC;AAEnD,UAAI,MAAM;AAET,eAAO,cAAc,IAAI;AAAA,MAC1B,OAAO;AAEN,eAAO,cAAc,IAAI,KAAK;AAAA,UAC7B;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,qBACP,MACA,WACA,YACiC;AACjC,QAAI,KAAK,WAAW,EAAG,QAAO,cAAc,cAAc,OAAO,CAAC;AAGlE,UAAM,SAAS,CAAC,GAAG,IAAI,EAAE;AAAA,MACxB,CAAC,GAAG,OAAQ,EAAE,SAAoB,MAAO,EAAE,SAAoB;AAAA,IAChE;AAEA,QAAI,cAAc,aAAa;AAG9B,UAAI,UAAU;AACd,eAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC5C,cAAM,MAAM,OAAO,CAAC;AACpB,cAAM,OAAO,EAAE,GAAG,IAAI;AACtB,YAAI,YAAY,MAAM;AACrB,eAAK,cAAc,cAAc,WAAW,UAAU,IAAI;AAAA,QAC3D;AACA,kBAAU;AAAA,MACX;AACA,aAAO;AAAA,IACR;AAGA,UAAM,UAAU,oBAAI,IAAwB;AAC5C,UAAM,QAAqB,CAAC;AAE5B,eAAW,OAAO,QAAQ;AACzB,YAAM,OAAO,EAAE,GAAG,KAAK,UAAU,CAAC,EAAE;AACpC,cAAQ,IAAI,IAAI,IAAI,IAAI;AAExB,YAAM,WAAW,IAAI,UAAU;AAC/B,UAAI,aAAa,QAAQ,aAAa,QAAW;AAChD,cAAM,SAAS,QAAQ,IAAI,QAAQ;AACnC,YAAI,QAAQ;AACX,UAAC,OAAO,SAAyB,KAAK,IAAI;AAAA,QAC3C,OAAO;AACN,gBAAM,KAAK,IAAI;AAAA,QAChB;AAAA,MACD,OAAO;AACN,cAAM,KAAK,IAAI;AAAA,MAChB;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,gBACP,KACA,KACU;AACV,QAAI,OAAO,QAAQ,UAAU;AAC5B,aAAO,IAAI,GAAG;AAAA,IACf;AAEA,UAAM,SAAS,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;AAEpC,QAAI,OAAO,KAAK,CAACC,OAAMA,OAAM,UAAaA,OAAM,IAAI,GAAG;AACtD,aAAO;AAAA,IACR;AACA,UAAM,QAAQ,OAAO,IAAI,CAACA,OAAM,OAAOA,EAAC,CAAC;AACzC,QAAI,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,iBAAiB,CAAC,GAAG;AAKrD,aAAO,KAAK,UAAU,KAAK;AAAA,IAC5B;AACA,WAAO,MAAM,KAAK,iBAAiB;AAAA,EACpC;AACD;;;ACjgBO,IAAM,0BAAN,MAAM,yBAEb;AAAA,EACU;AAAA,EACQ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YACC,QACA,OACA,SACA,YACC;AACD,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,SAAK,UAAU;AACf,SAAK,aAAa;AAAA,EACnB;AAAA,EAEA,MAAM,OAA4D;AACjE,WAAO,KAAK,QAAQ,SAAS,OAAO,KAAK;AAAA,EAC1C;AAAA,EAEA,SAAS,OAA4D;AACpE,WAAO,KAAK,QAAQ,SAAS,MAAM,KAAK;AAAA,EACzC;AAAA,EAEA,UAAU,OAA4D;AACrE,WAAO,KAAK,QAAQ,aAAa,OAAO,KAAK;AAAA,EAC9C;AAAA,EAEA,aAAa,OAA4D;AACxE,WAAO,KAAK,QAAQ,aAAa,MAAM,KAAK;AAAA,EAC7C;AAAA,EAEA,OAAO,OAA4D;AAClE,WAAO,KAAK,QAAQ,UAAU,OAAO,KAAK;AAAA,EAC3C;AAAA,EAEA,UAAU,OAA4D;AACrE,WAAO,KAAK,QAAQ,UAAU,MAAM,KAAK;AAAA,EAC1C;AAAA,EAEQ,QACPC,KACA,KACA,OAC+B;AAC/B,UAAM,cAAe,MAAuC,YAAY;AACxE,UAAM,YAAgC;AAAA,MACrC,MAAM;AAAA,MACN,IAAAA;AAAA,MACA;AAAA,MACA,MAAM,KAAK;AAAA,MACX,OAAO;AAAA,IACR;AACA,WAAO,IAAI;AAAA,MACV;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACN;AAAA,EACD;AAAA,EAEA,OAAa;AACZ,UAAM,UAAU,KAAK,eAAe;AACpC,UAAM,WAAW,QAAQ,oBAAoB,KAAK,QAAQ,KAAK,KAAK;AAIpE,UAAM,OAAiB;AAAA,MACtB,YAAY,oBAAI,KAAK;AAAA,MACrB,GAAI,KAAK,eAAe,SAAY,EAAE,QAAQ,KAAK,WAAW,IAAI,CAAC;AAAA,IACpE;AACA,WAAO;AAAA,MACN,KAAK,SAAS;AAAA,MACd,QAAQ,SAAS;AAAA,MACjB;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,MAA0B;AAC/B,UAAM,UAAU,KAAK,eAAe;AACpC,UAAM,WAAW,QAAQ,oBAAoB,KAAK,QAAQ,KAAK,KAAK;AACpE,WAAO,QAAQ,QAAQ,QAAQ;AAAA,EAChC;AAAA,EAEA,MAAM,QAAsC;AAC3C,UAAM,OAAO,MAAM,KAAK,IAAI;AAC5B,WAAO,KAAK,CAAC;AAAA,EACd;AAAA,EAEQ,iBAA0B;AACjC,QAAI,CAAC,KAAK,SAAS;AAClB,YAAM,IAAI,eAAe;AAAA,QACxB,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,KAAK;AAAA,MACN,CAAC;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACb;AACD;AAUO,SAAS,wBACfA,KACA,KACA,MACA,OACqB;AACrB,SAAO;AAAA,IACN,MAAM;AAAA,IACN,IAAAA;AAAA,IACA;AAAA,IACA,MAAM,KAAK,YAAY;AAAA,IACvB,OAAO,MAAM,YAAY;AAAA,EAC1B;AACD;;;AC9LO,SAAS,OACf,SACA,SACiC;AACjC,QAAM,UAAU,QAAQ,qBAAqB;AAG7C,QAAM,iBACL,SAAS,cAAc,SACpB,EAAE,WAAW,QAAQ,UAAU,IAC/B;AAGJ,QAAM,YAAY,QAAQ,IAAI;AAC9B,QAAM,cAAc,QAAQ,IAAI;AAChC,QAAM,QAAQ,QAAQ;AACtB,QAAM,aAAa,QAAQ,IAAI;AAC/B,QAAM,SAAS,QAAQ,IAAI;AAM3B,QAAM,kBAAkB,SAAS;AAMjC,MAAI,gBACH;AACD,MAAI,eAA4B;AAChC,MAAI,kBAAyD;AAC7D,MAAI,gBAAgB;AACpB,MAAI,aAAa;AAEjB,QAAM,eAA+C;AAAA,IACpD,CAAC,OAAO,aAAa,IAAI;AACxB,aAAO;AAAA,IACR;AAAA,IACA,MAAM,OAAO;AAGZ,UAAI,CAAC,YAAY;AAChB,qBAAa;AAEb,YAAI,aAAa,SAAS,SAAS,GAAG;AAErC,gBAAM,YAAY,QAAQ,YAAY,KAAK;AAC3C,gBAAM,MAAwB;AAAA,YAC7B;AAAA,YACA,WAAW;AAAA,YACX,QAAQ;AAAA,YACR,YAAY;AAAA,YACZ,aAAa;AAAA,YACb,GAAI,eAAe,UAAa,EAAE,WAAW;AAAA,YAC7C,GAAI,UAAU,EAAE,eAAe,KAAK;AAAA,UACrC;AAEA,cAAI,aAAa;AACjB,cAAI;AACH,kBAAM,eAAe,MAAM;AAAA,cAC1B,UAAU;AAAA,cACV;AAAA,cACA;AAAA,YACD;AACA,yBAAa,aAAa;AAAA,UAC3B,SAAS,OAAO;AACf,gBAAI,UAAU,QAAQ,SAAS,GAAG;AACjC,oBAAM,MAAM,gBAAgB,UAAU,SAAS;AAAA,gBAC9C;AAAA,gBACA,WAAW;AAAA,gBACX;AAAA,gBACA,QAAQ;AAAA,gBACR,OAAO;AAAA,cACR,CAAC;AAAA,YACF;AACA,kBAAM;AAAA,UACP;AAGA,gBAAM,sBACL,QAAQ,4BAA4B,UAAU;AAC/C,gBAAM,kBACL,QAAQ,mBAAmB,mBAAmB;AAC/C,gBAAM,cAA2B;AAAA,YAChC,GAAI,QAAQ,IAAI,uBAAuB;AAAA,cACtC,qBAAqB,QAAQ,IAAI;AAAA,YAClC;AAAA,YACA,GAAG,QAAQ,IAAI;AAAA,UAChB;AACA,gBAAM,aAAa,QAAQ;AAAA,YAC1B;AAAA,YACA;AAAA,UACD;AACA,gBAAM,iBAA0D;AAAA,YAC/D,OAAO,QAAQ,IAAI;AAAA,UACpB;AACA,cAAI,eAAe,QAAW;AAC7B,2BAAe,aAAa;AAAA,UAC7B;AACA,gBAAM,WAAW,QAAQ,QAAQ,YAAY,cAAc;AAC3D,0BAAgB;AAChB,yBAAe,QAAQ,WAAW,YAAY,QAAQ;AACtD,cACC,aAAa,MAAM,WAAW,UAC9B,eAAe,QACd;AACD,2BAAe;AAAA,cACd,GAAG;AAAA,cACH,MAAM,EAAE,GAAG,aAAa,MAAM,QAAQ,WAAW;AAAA,YAClD;AAAA,UACD;AAAA,QACD,OAAO;AAEN,gBAAM,aAAa,QAAQ,KAAK;AAChC,0BAAgB;AAAA,YACf,KAAK,WAAW;AAAA,YAChB,YAAY,WAAW;AAAA,UACxB;AACA,yBAAe;AAAA,QAChB;AAAA,MACD;AAGA,UAAI,CAAC,iBAAiB;AAGrB,0BAAkB,QAAQ;AAAA;AAAA,UAEzB;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAGA,UAAI,CAAC,iBAAiB,mBAAmB,cAAc;AACtD,wBAAgB;AAChB,wBAAgB,YAAY;AAAA,MAC7B;AAEA,aAAO,gBAAgB,KAAK;AAAA,IAC7B;AAAA,IACA,MAAM,OAAO,OAAiB;AAC7B,UAAI,iBAAiB,QAAQ;AAC5B,eAAO,gBAAgB,OAAO,KAAK;AAAA,MACpC;AACA,aAAO,EAAE,MAAM,MAAe,OAAO,OAAU;AAAA,IAChD;AAAA,IACA,MAAM,MAAM,OAAiB;AAE5B,UAAI,aAAa,UAAU,QAAQ,SAAS,KAAK,iBAAiB,OAAO;AACxE,cAAM,YAAY,QAAQ,YAAY,KAAK;AAC3C,cAAM,aAAa,MAAM,gBAAgB,UAAU,SAAS;AAAA,UAC3D;AAAA,UACA,WAAW;AAAA,UACX;AAAA,UACA,QAAQ;AAAA,UACR,OAAO;AAAA,QACR,CAAC;AACD,cAAM;AAAA,MACP;AACA,UAAI,iBAAiB,OAAO;AAC3B,eAAO,gBAAgB,MAAM,KAAK;AAAA,MACnC;AACA,YAAM;AAAA,IACP;AAAA,EACD;AAEA,SAAO;AACR;;;AC3GO,IAAM,mBAAN,MAAM,kBAEb;AAAA;AAAA,EAEU;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA,WAA4B,CAAC;AAAA;AAAA,EAE7B,oBAA8C,CAAC;AAAA,EACvC;AAAA;AAAA,EAEjB,eAAyC;AAAA;AAAA,EAEzC,eAA8B,CAAC;AAAA,EACvB,qBAA0C;AAAA;AAAA,EAElD,aAAgC,CAAC;AAAA;AAAA,EAEjC,gBAA0B,CAAC;AAAA;AAAA,EAE3B,iBAAkC,CAAC;AAAA;AAAA,EAEnC,aAAiC;AAAA;AAAA,EAEjC,cAAkC;AAAA,EAC1B,gBAA+B,CAAC;AAAA,EAChC,kBAAkB;AAAA,EAClB,oBAA8B,CAAC;AAAA,EAC/B,qBAAqB;AAAA,EACrB,aAA2D;AAAA;AAAA,EAEnE,cAA4B,CAAC;AAAA;AAAA,EAE7B;AAAA,EAEA,YACC,KACA,MACA,gBAA+B,CAAC,GAC/B;AACD,SAAK,MAAM;AACX,SAAK,OAAO;AACZ,SAAK,gBAAgB;AAAA,EACtB;AAAA,EAEA,QACC,UACA,SACwB;AACxB,UAAM,UAAU,KAAK,MAAM;AAG3B,QAAI,0BAA0B,OAAO,GAAG;AACvC,+BAAyB,KAAK,IAAI,OAAO,KAAK,MAAM,UAAU,OAAO;AAAA,IAEtE;AAGA,QAAI,SAAS,SAAS,GAAG,GAAG;AAC3B,cAAQ,SAAS,KAAK,wBAAwB,UAAU,OAAO,CAAC;AAAA,IACjE,OAAO;AACN,cAAQ,SAAS,KAAK,uBAAuB,UAAU,OAAO,CAAC;AAAA,IAChE;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BA,QAAQ,SAAmD;AAC1D,UAAM,UAAU,KAAK,MAAM;AAG3B,UAAM,oBAAwC,CAAC;AAC/C,QAAI,iBAAiB;AAErB,eAAWC,QAAO,SAAS;AAC1B,UAAI,iBAAiBA,IAAG,GAAG;AAC1B,yBAAiB;AACjB,0BAAkB,KAAKA,KAAI,MAAM;AAAA,MAClC,OAAO;AAEN,0BAAkB,KAAK,EAAE,MAAM,UAAU,QAAQA,KAAI,CAAC;AAAA,MACvD;AAAA,IACD;AAGA,QAAI,gBAAgB;AACnB,cAAQ,eAAe;AAAA,QACtB,MAAM;AAAA,QACN,SAAS;AAAA,MACV;AAAA,IACD,OAAO;AAEN,YAAM,SAAS,kBAAkB;AAAA,QAChC,CAAC,MAAO,EAA6B;AAAA,MACtC;AACA,cAAQ,eAAe,EAAE,MAAM,UAAU,OAAO;AAAA,IACjD;AAIA,WAAO;AAAA,EACR;AAAA,EAEA,SACC,QACA,IACoE;AACpE,UAAM,UAAU,KAAK,MAAM;AAG3B,UAAM,iBAAmC;AAAA,MACxC,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACD;AAGA,QAAI,QAAQ,cAAc,SAAS,eAAe;AACjD,cAAQ,eAAe;AAAA,QACtB,MAAM;AAAA,QACN,SAAS,CAAC,GAAG,QAAQ,aAAa,SAAS,cAAc;AAAA,MAC1D;AAAA,IACD,WAAW,QAAQ,cAAc,SAAS,UAAU;AAEnD,YAAM,mBACL,QAAQ,aAAa,OAAO;AAAA,QAC3B,CAAC,WAAW,EAAE,MAAM,UAAU,QAAQ,MAAM;AAAA,MAC7C;AACD,cAAQ,eAAe;AAAA,QACtB,MAAM;AAAA,QACN,SAAS,CAAC,GAAG,kBAAkB,cAAc;AAAA,MAC9C;AAAA,IACD,OAAO;AAGN,cAAQ,eAAe;AAAA,QACtB,MAAM;AAAA,QACN,SAAS,CAAC,cAAc;AAAA,MACzB;AAAA,IACD;AAMA,WAAO;AAAA,EAGR;AAAA,EAEA,MACC,gBACA,IACwB;AACxB,UAAM,UAAU,KAAK,MAAM;AAC3B,UAAM,MAAgC,EAAE,UAAU,QAAQ;AAE1D,QAAI,mBAAmB,QAAW;AAAA,IAElC,WAAW,OAAO,mBAAmB,UAAU;AAE9C,UAAI,QAAQ;AACZ,UAAI,OAAO,QAAW;AACrB,YAAI,KAAK;AAAA,MACV;AAAA,IACD,WAAW,gBAAgB,cAAc,GAAG;AAE3C,UAAI,QAAQ,eAAe;AAC3B,UAAI,WAAW;AACf,UAAI,OAAO,QAAW;AACrB,YAAI,KAAK;AAAA,MACV;AAAA,IACD,OAAO;AAEN,UAAI,eAAe,UAAU,QAAW;AACvC,YAAI,QAAQ,eAAe;AAAA,MAC5B;AACA,UAAI,eAAe,OAAO,QAAW;AACpC,YAAI,KAAK,eAAe;AAAA,MACzB;AAAA,IACD;AAEA,YAAQ,WAAW,KAAK,GAAsB;AAC9C,WAAO;AAAA,EACR;AAAA,EAEA,IAAI,OAA+B,IAAoC;AACtE,UAAM,UAAU,KAAK,MAAM;AAC3B,UAAM,aAAa,gBAAgB,KAAK;AACxC,UAAM,YAAY,aAAa,MAAM,QAAQ;AAC7C,UAAM,MAAgC,EAAE,UAAU,OAAO,OAAO,UAAU;AAC1E,QAAI,YAAY;AACf,UAAI,WAAW;AAAA,IAChB;AACA,QAAI,OAAO,QAAW;AACrB,UAAI,KAAK;AAAA,IACV;AACA,YAAQ,WAAW,KAAK,GAAsB;AAC9C,WAAO;AAAA,EACR;AAAA,EAEA,IAAI,OAA+B,IAAoC;AACtE,UAAM,UAAU,KAAK,MAAM;AAC3B,UAAM,aAAa,gBAAgB,KAAK;AACxC,UAAM,YAAY,aAAa,MAAM,QAAQ;AAC7C,UAAM,MAAgC,EAAE,UAAU,OAAO,OAAO,UAAU;AAC1E,QAAI,YAAY;AACf,UAAI,WAAW;AAAA,IAChB;AACA,QAAI,OAAO,QAAW;AACrB,UAAI,KAAK;AAAA,IACV;AACA,YAAQ,WAAW,KAAK,GAAsB;AAC9C,WAAO;AAAA,EACR;AAAA,EAEA,IAAI,OAAe,IAAoC;AACtD,UAAM,UAAU,KAAK,MAAM;AAC3B,UAAM,MAAgC,EAAE,UAAU,OAAO,MAAM;AAC/D,QAAI,OAAO,QAAW;AACrB,UAAI,KAAK;AAAA,IACV;AACA,YAAQ,WAAW,KAAK,GAAsB;AAC9C,WAAO;AAAA,EACR;AAAA,EAEA,IAAI,OAAe,IAAoC;AACtD,UAAM,UAAU,KAAK,MAAM;AAC3B,UAAM,MAAgC,EAAE,UAAU,OAAO,MAAM;AAC/D,QAAI,OAAO,QAAW;AACrB,UAAI,KAAK;AAAA,IACV;AACA,YAAQ,WAAW,KAAK,GAAsB;AAC9C,WAAO;AAAA,EACR;AAAA,EAEA,QAAQ,QAAkD;AACzD,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,cAAc,KAAK,GAAG,MAAM;AACpC,WAAO;AAAA,EACR;AAAA,EAEA,OAAO,WAA+C;AACrD,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,cAAc,KAAK,SAAS;AACpC,WAAO;AAAA,EACR;AAAA,EAEA,WAAkC;AACjC,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,kBAAkB;AAC1B,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,cAAc,SAA0C;AACvD,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,oBAAoB;AAC5B,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAMA,YAAmC;AAClC,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,aAAa;AAAA,MACpB,UAAU;AAAA,MACV,YAAY,QAAQ,YAAY,cAAc;AAAA,IAC/C;AACA,WAAO;AAAA,EACR;AAAA,EAEA,WAAkC;AACjC,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,aAAa;AAAA,MACpB,UAAU;AAAA,MACV,YAAY,QAAQ,YAAY,cAAc;AAAA,IAC/C;AACA,WAAO;AAAA,EACR;AAAA,EAEA,iBAAwC;AACvC,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,aAAa;AAAA,MACpB,UAAU;AAAA,MACV,YAAY,QAAQ,YAAY,cAAc;AAAA,IAC/C;AACA,WAAO;AAAA,EACR;AAAA,EAEA,cAAqC;AACpC,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,aAAa;AAAA,MACpB,UAAU;AAAA,MACV,YAAY,QAAQ,YAAY,cAAc;AAAA,IAC/C;AACA,WAAO;AAAA,EACR;AAAA,EAEA,KACC,UACA,YACwB;AACxB,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,aAAa,EAAE,UAAU,YAAY,cAAc,QAAQ;AACnE,WAAO;AAAA,EACR;AAAA,EAEA,aAAoC;AACnC,QAAI,CAAC,KAAK,YAAY;AACrB,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AACA,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,aAAa,EAAE,GAAG,KAAK,YAAY,YAAY,aAAa;AACpE,WAAO;AAAA,EACR;AAAA,EAEA,SAAgC;AAC/B,QAAI,CAAC,KAAK,YAAY;AACrB,YAAM,IAAI;AAAA,QACT;AAAA,MACD;AAAA,IACD;AACA,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,aAAa,EAAE,GAAG,KAAK,YAAY,YAAY,SAAS;AAChE,WAAO;AAAA,EACR;AAAA,EAEA,QACC,sBAMA,WACA,SACwB;AACxB,UAAM,UAAU,KAAK,MAAM;AAG3B,QAAI,gCAAgC,eAAe;AAClD,cAAQ,eAAe,KAAK;AAAA,QAC3B,YAAY,qBAAqB;AAAA,QACjC,WAAW,aAAa;AAAA,QACxB,GAAI,SAAS,UAAU,SAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,MAChE,CAAC;AACD,aAAO;AAAA,IACR;AAGA,QAAI,iBAAiB,oBAAkC,GAAG;AACzD,cAAQ,eAAe,KAAK;AAAA,QAC3B,YAAa,qBACX;AAAA,QACF,WAAW,aAAa;AAAA,QACxB,GAAI,SAAS,UAAU,SAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,MAChE,CAAC;AACD,aAAO;AAAA,IACR;AAGA,QAAI,OAAO,yBAAyB,UAAU;AAC7C,cAAQ,eAAe,KAAK;AAAA,QAC3B,OAAO;AAAA,QACP,WAAW,aAAa;AAAA,QACxB,GAAI,SAAS,UAAU,SAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,MAChE,CAAC;AACD,aAAO;AAAA,IACR;AAGA,QAAI,MAAM,QAAQ,oBAAoB,GAAG;AACxC,iBAAW,QAAQ,sBAAsB;AACxC,gBAAQ,eAAe,KAAK;AAAA,UAC3B,OAAO,KAAK;AAAA,UACZ,WAAW,KAAK,aAAa;AAAA,UAC7B,OAAO,KAAK;AAAA,QACb,CAAC;AAAA,MACF;AACA,aAAO;AAAA,IACR;AAGA,eAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,oBAAoB,GAAG;AAChE,cAAQ,eAAe,KAAK;AAAA,QAC3B;AAAA,QACA,WAAW;AAAA,MACZ,CAAC;AAAA,IACF;AACA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,OAAsC;AAC3C,QAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,GAAG;AAC9C,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AACA,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,aAAa;AACrB,WAAO;AAAA,EACR;AAAA,EAEA,OAAO,OAAsC;AAC5C,QAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,GAAG;AAC9C,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AACA,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,cAAc;AACtB,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,WAAsE;AAC3E,UAAM,UAAU,KAAK,MAAM;AAK3B,QAAI,qBAAqB,eAAe;AAGvC,YAAM,YAAY;AAAA,QACjB,MAAM;AAAA,QACN,MAAM,UAAU;AAAA,MACjB;AACA,cAAQ,aAAa,KAAK,SAAS;AACnC,aAAO;AAAA,IACR;AAEA,UAAM,SAAS,cAAc,SAAS,IACnC,YACA,oBAAoB,SAAiD;AACxE,YAAQ,aAAa,KAAK,MAAM;AAChC,WAAO;AAAA,EACR;AAAA,EAEA,KACC,wBACA,MACwB;AACxB,UAAM,UAAU,KAAK,MAAM;AAC3B,UAAM,OAAO,MAAM,QAAQ;AAE3B,QAAI,iBAAiB,sBAAsB,GAAG;AAC7C,YAAM,KAAK;AACX,UAAI,CAAC,MAAM,IAAI;AACd,cAAM,IAAI;AAAA,UACT;AAAA,QACD;AAAA,MACD;AACA,YAAM,aAAyB;AAAA,QAC9B,aAAa;AAAA,UACZ,MAAM,GAAG;AAAA,UACT,SAAS,GAAG;AAAA,UACZ,OAAO,GAAG;AAAA,UACV,OAAO,GAAG;AAAA,UACV,YAAY,GAAG;AAAA,QAChB;AAAA,QACA,IAAI,KAAK;AAAA,QACT;AAAA,QACA,GAAI,KAAK,OAAO,SAAY,EAAE,OAAO,KAAK,GAAG,IAAI,EAAE,OAAO,GAAG,MAAM;AAAA,MACpE;AACA,cAAQ,YAAY,KAAK,UAAU;AAAA,IACpC,OAAO;AAEN,yBAAmB,wBAAwB,OAAO;AAClD,YAAM,aAAyB,MAAM,KAClC;AAAA,QACA,OAAO;AAAA,QACP,IAAI,KAAK;AAAA,QACT;AAAA,QACA,GAAI,KAAK,OAAO,UAAa,EAAE,OAAO,KAAK,GAAG;AAAA,MAC/C,IACC;AAAA,QACA,UAAU;AAAA,QACV;AAAA,QACA,GAAI,MAAM,OAAO,UAAa,EAAE,OAAO,KAAK,GAAG;AAAA,MAChD;AACF,cAAQ,YAAY,KAAK,UAAU;AAAA,IACpC;AACA,WAAO;AAAA,EACR;AAAA,EAEA,eAAe,QAAwC;AACtD,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,qBAAqB;AAC7B,WAAO;AAAA,EACR;AAAA,EAEA,iBAAiB,QAAgB,UAAyC;AACzE,UAAM,UAAU,KAAK,MAAM;AAC3B,IAAC,QAAQ,cAAyC,MAAM,IAAI;AAC5D,WAAO;AAAA,EACR;AAAA,EAEA,gBAAgB,SAA6C;AAC5D,WAAO,KAAK,qBAAqB;AAAA,MAChC,qBAAqB;AAAA,QACpB,GAAG,KAAK,IAAI;AAAA,QACZ,GAAG;AAAA,MACJ;AAAA,IACD,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,yBAAkC;AACzC,WAAO,KAAK,uBAAuB,SAChC,KAAK,qBACL,KAAK,IAAI;AAAA,EACb;AAAA,EAEA,OAAmB;AAClB,UAAM,SAAS,KAAK,YAAY;AAGhC,QAAI,OAAO,QAAQ,CAAC,KAAK,IAAI,eAAe;AAC3C,cAAQ;AAAA,QACP;AAAA,MAED;AAAA,IACD;AAGA,UAAM,kBAAkB,KAAK,mBAAmB,MAAM;AAGtD,UAAM,cAA2B;AAAA,MAChC,GAAI,KAAK,IAAI,uBAAuB;AAAA,QACnC,qBAAqB,KAAK,IAAI;AAAA,MAC/B;AAAA;AAAA,MAEA,GAAG,KAAK,IAAI;AAAA,IACb;AAEA,QAAI;AACH,aAAO,KAAK,iBAAiB,KAAK,IAAI,OAAO,WAAW;AAAA,IACzD,SAAS,OAAO;AACf,UAAI,iBAAiB,oBAAoB;AACxC,eAAO,KAAK,gBAAgB,OAAO,iBAAiB,WAAW;AAAA,MAChE;AACA,YAAM;AAAA,IACP;AAAA,EACD;AAAA,EAEA,MAAM,MAA0B;AAC/B,UAAM,UAAU,KAAK,qBAAqB;AAG1C,QAAI,KAAK,IAAI,aAAa,SAAS,KAAK,IAAI,SAAS,GAAG;AACvD,aAAO,KAAK,iBAAiB,SAAS,KAAK;AAAA,IAC5C;AAGA,UAAM,aAAa,KAAK,KAAK;AAG7B,UAAM,iBAGF,EAAE,OAAO,KAAK,IAAI,MAAM;AAC5B,QAAI,KAAK,IAAI,eAAe,QAAW;AACtC,qBAAe,aAAa,KAAK,IAAI;AAAA,IACtC;AAGA,UAAM,uBAAuB,QAAQ;AAAA,MACpC;AAAA,MACA;AAAA,IACD;AACA,UAAM,cAAe,MAAM,QAAQ;AAAA,MAClC,qBAAqB;AAAA,IACtB;AAGA,UAAM,WAAW,IAAI;AAAA,MACpB,KAAK,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK,IAAI;AAAA,IACV;AAGA,aAAS,uBAAuB,aAAa,UAAU;AAGvD,aAAS,oBAAoB,aAAa,UAAU;AAGpD,QAAI,qBAAqB,iBAAiB,SAAS,GAAG;AACrD,YAAM,SAAS;AAAA,QACd;AAAA,QACA,qBAAqB;AAAA,QACrB;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAGA,QAAI,KAAK,kBAAkB,SAAS,GAAG;AACtC,YAAM,SAAS;AAAA,QACd;AAAA,QACA,KAAK;AAAA,QACL;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,QAAsC;AAE3C,QAAI,KAAK,IAAI,aAAa,SAAS,KAAK,IAAI,SAAS,GAAG;AACvD,YAAM,UAAU,KAAK,qBAAqB;AAC1C,YAAMC,QAAO,MAAM,KAAK,iBAA4B,SAAS,OAAO;AACpE,aAAOA,MAAK,CAAC;AAAA,IACd;AACA,UAAM,OAAO,MAAM,KAAK,IAAI;AAC5B,WAAO,KAAK,CAAC;AAAA,EACd;AAAA,EAEA,MAAM,eAAiC;AACtC,UAAM,SAAS,MAAM,KAAK,MAAM;AAChC,QAAI,WAAW,QAAW;AACzB,YAAM,IAAI,cAAc,KAAK,IAAI;AAAA,IAClC;AACA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,KACL,OAC+B;AAC/B,UAAM,YAAY,KAAK,iBAAiB,KAAK;AAC7C,WAAO,KAAK,MAAM,SAAS,EAAE,MAAM;AAAA,EACpC;AAAA,EAEA,MAAM,YACL,OACmB;AACnB,UAAM,SAAS,MAAM,KAAK,KAAK,KAAK;AACpC,QAAI,WAAW,QAAW;AACzB,YAAM,IAAI;AAAA,QACT,KAAK;AAAA,QACL;AAAA,MACD;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,MAAM,QAA0D;AACrE,QAAI,OAAO,WAAW,GAAG;AACxB,aAAO,CAAC;AAAA,IACT;AACA,WAAO,KAAK,MAAM,QAAQ,KAAK,kBAAkB,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAA4B;AACnC,UAAM,QAAQ,KAAK,IAAI,MAAM,SAAS,KAAK,IAAI;AAC/C,UAAM,KAAK,OAAO;AAClB,QAAI,OAAO,OAAO,UAAU;AAC3B,aAAO;AAAA,IACR;AACA,QAAI,MAAM,QAAQ,EAAE,KAAK,GAAG,SAAS,GAAG;AACvC,aAAO,GAAG,CAAC;AAAA,IACZ;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBACP,OACc;AACd,QAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;AAE3D,aAAO,GAAG,KAAK,kBAAkB,GAAG,KAAK;AAAA,IAC1C;AAEA,UAAM,QAAQ,KAAK,IAAI,MAAM,SAAS,KAAK,IAAI;AAC/C,QAAI,CAAC,OAAO;AACX,YAAM,IAAI,sBAAsB,QAAQ,eAAe;AAAA,IACxD;AACA,UAAM,QAAQ,MAAM,cAAc,CAAC;AACnC,UAAM,cAAc,IAAI,IAAI,OAAO,UAAU,WAAW,CAAC,KAAK,IAAI,KAAK;AAEvE,UAAM,UAAU,OAAO,QAAQ,KAAK;AACpC,QAAI,QAAQ,WAAW,GAAG;AACzB,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACxD;AACA,QAAI,YAAY,OAAO,GAAG;AACzB,iBAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACrC,YAAI,CAAC,YAAY,IAAI,GAAG,GAAG;AAC1B,gBAAM,IAAI;AAAA,YACT;AAAA,YACA,+BAA+B,GAAG;AAAA,UACnC;AAAA,QACD;AAAA,MACD;AAAA,IACD;AACA,QAAI,QAAQ,WAAW,GAAG;AACzB,YAAM,QAAQ,QAAQ,CAAC;AACvB,UAAI,CAAC,OAAO;AACX,cAAM,IAAI,MAAM,qCAAqC;AAAA,MACtD;AACA,YAAM,CAAC,OAAO,UAAU,IAAI;AAC5B,aAAO,GAAG,OAAO,UAAU;AAAA,IAC5B;AACA,UAAM,aAAa,QAAQ;AAAA,MAAI,CAAC,CAAC,OAAO,UAAU,MACjD,GAAG,OAAO,UAAU;AAAA,IACrB;AACA,WAAO,IAAI,GAAG,UAAU;AAAA,EACzB;AAAA,EAEA,KAAK,MAA4B;AAChC,UAAM,UAAU,KAAK,qBAAqB;AAC1C,UAAM,aAAa,KAAK,KAAK;AAG7B,UAAM,iBAGF,EAAE,OAAO,KAAK,IAAI,MAAM;AAC5B,QAAI,KAAK,IAAI,eAAe,QAAW;AACtC,qBAAe,aAAa,KAAK,IAAI;AAAA,IACtC;AAEA,UAAM,WAAW,QAAQ,QAAQ,YAAY,cAAc;AAG3D,UAAM,WAA0B;AAAA,MAC/B,GAAI,MAAM,cAAc,UAAa,EAAE,WAAW,KAAK,UAAU;AAAA,MACjE,GAAI,MAAM,kBAAkB,UAAa;AAAA,QACxC,eAAe,KAAK;AAAA,MACrB;AAAA,IACD;AAIA,UAAM,OAAO,QAAQ,WAAW,YAAY,UAAU,QAAQ;AAG9D,QAAI,KAAK,MAAM,WAAW,UAAa,KAAK,IAAI,eAAe,QAAW;AACzE,aAAO;AAAA,QACN,GAAG;AAAA,QACH,MAAM;AAAA,UACL,GAAG,KAAK;AAAA,UACR,QAAQ,KAAK,IAAI;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,SAA2B;AAChC,UAAM,UAAU,KAAK,qBAAqB;AAG1C,QAAI,KAAK,IAAI,aAAa,SAAS,KAAK,IAAI,SAAS,GAAG;AAEvD,aAAO;AAAA,QAAoB,KAAK,IAAI;AAAA,QAAW,CAAC,MAC/C,KAAK,gBAAgB,SAAS,CAAC;AAAA,MAChC;AAAA,IACD;AAGA,UAAM,eAAe,KAAK,kBAAkB;AAC5C,UAAM,kBAAkB,KAAK,mBAAmB,YAAY;AAE5D,UAAM,cAA2B;AAAA,MAChC,GAAI,KAAK,IAAI,uBAAuB;AAAA,QACnC,qBAAqB,KAAK,IAAI;AAAA,MAC/B;AAAA,MACA,GAAG,KAAK,IAAI;AAAA,IACb;AAEA,UAAM,aAAa,KAAK;AAAA,MACvB;AAAA,MACA;AAAA,IACD;AAEA,UAAM,iBAGF,EAAE,OAAO,KAAK,IAAI,MAAM;AAC5B,QAAI,KAAK,IAAI,eAAe,QAAW;AACtC,qBAAe,aAAa,KAAK,IAAI;AAAA,IACtC;AAEA,UAAM,WAAW,QAAQ,QAAQ,YAAY,cAAc;AAC3D,UAAM,OAAO,MAAM,QAAQ,QAAQ,QAAQ;AAC3C,WACC,KAAK,SAAS,KAAM,KAAK,CAAC,EAA8B,WAAW;AAAA,EAErE;AAAA,EAEA,MAAc,gBACb,SACA,OACmB;AACnB,UAAM,YAAY,KAAK,IAAI;AAG3B,UAAM,YAAY,KAAK,YAAY,KAAK;AACxC,UAAM,YAA8B;AAAA,MACnC,OAAO,KAAK;AAAA,MACZ,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,GAAI,KAAK,IAAI,eAAe,UAAa;AAAA,QACxC,YAAY,KAAK,IAAI;AAAA,MACtB;AAAA,MACA,GAAI,KAAK,IAAI,iBAAiB,EAAE,eAAe,KAAK;AAAA,IACrD;AAGA,QAAI;AACJ,QAAI;AACH,YAAM,eAAe,MAAM;AAAA,QAC1B,MAAM;AAAA,QACN;AAAA,QACA,KAAK,IAAI;AAAA,MACV;AACA,eAAS,aAAa;AAAA,IACvB,SAAS,OAAO;AACf,UAAI,MAAM,QAAQ,SAAS,GAAG;AAC7B,cAAM,MAAM,gBAAgB,MAAM,SAAS;AAAA,UAC1C,OAAO,KAAK;AAAA,UACZ,WAAW;AAAA,UACX;AAAA,UACA,QAAQ;AAAA,UACR,OAAO;AAAA,QACR,CAAC;AAAA,MACF;AACA,YAAM;AAAA,IACP;AAGA,aAAS,KAAK,4BAA4B,MAAM;AAGhD,UAAM,eAAe,KAAK,4BAA4B,MAAM;AAC5D,UAAM,kBAAkB,KAAK,mBAAmB,YAAY;AAC5D,UAAM,cAA2B;AAAA,MAChC,GAAI,KAAK,IAAI,uBAAuB;AAAA,QACnC,qBAAqB,KAAK,IAAI;AAAA,MAC/B;AAAA,MACA,GAAG,KAAK,IAAI;AAAA,IACb;AACA,UAAM,aAAa,KAAK;AAAA,MACvB;AAAA,MACA;AAAA,IACD;AACA,UAAM,iBAA0D;AAAA,MAC/D,OAAO,KAAK,IAAI;AAAA,IACjB;AACA,QAAI,KAAK,IAAI,eAAe,QAAW;AACtC,qBAAe,aAAa,KAAK,IAAI;AAAA,IACtC;AACA,UAAM,WAAW,QAAQ,QAAQ,YAAY,cAAc;AAC3D,UAAM,OAAO,MAAM,QAAQ,QAAQ,QAAQ;AAC3C,UAAM,SACL,KAAK,SAAS,KAAM,KAAK,CAAC,EAA8B,WAAW;AAGpE,UAAM,WAA6B;AAAA,MAClC,OAAO,KAAK;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,MACA,YAAY;AAAA,MACZ,KAAK,SAAS;AAAA,MACd,YAAY,SAAS;AAAA,MACrB,UAAU,KAAK,IAAI,IAAI;AAAA,MACvB,GAAI,KAAK,IAAI,eAAe,UAAa;AAAA,QACxC,YAAY,KAAK,IAAI;AAAA,MACtB;AAAA,IACD;AACA,QAAI;AACH,aAAO,MAAM;AAAA,QACZ,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,KAAK,IAAI;AAAA,MACV;AAAA,IACD,SAAS,OAAO;AACf,UAAI,MAAM,QAAQ,SAAS,GAAG;AAC7B,cAAM,MAAM,gBAAgB,MAAM,SAAS;AAAA,UAC1C,OAAO,KAAK;AAAA,UACZ,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA,OAAO;AAAA,UACP,KAAK,SAAS;AAAA,QACf,CAAC;AAAA,MACF;AACA,YAAM;AAAA,IACP;AAAA,EACD;AAAA,EAEA,aAAmB;AAClB,UAAM,UAAU,KAAK,qBAAqB;AAC1C,UAAM,eAAe,KAAK,kBAAkB;AAC5C,UAAM,kBAAkB,KAAK,mBAAmB,YAAY;AAE5D,UAAM,cAA2B;AAAA,MAChC,GAAI,KAAK,IAAI,uBAAuB;AAAA,QACnC,qBAAqB,KAAK,IAAI;AAAA,MAC/B;AAAA,MACA,GAAG,KAAK,IAAI;AAAA,IACb;AAEA,UAAM,aAAa,KAAK;AAAA,MACvB;AAAA,MACA;AAAA,IACD;AAEA,UAAM,iBAGF,EAAE,OAAO,KAAK,IAAI,MAAM;AAC5B,QAAI,KAAK,IAAI,eAAe,QAAW;AACtC,qBAAe,aAAa,KAAK,IAAI;AAAA,IACtC;AAEA,UAAM,WAAW,QAAQ,QAAQ,YAAY,cAAc;AAC3D,UAAM,OAAO,QAAQ,WAAW,YAAY,QAAQ;AAEpD,QAAI,KAAK,MAAM,WAAW,UAAa,KAAK,IAAI,eAAe,QAAW;AACzE,aAAO;AAAA,QACN,GAAG;AAAA,QACH,MAAM;AAAA,UACL,GAAG,KAAK;AAAA,UACR,QAAQ,KAAK,IAAI;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,UAA8B;AAC7B,WAAO,KAAK,IAAI;AAAA,EACjB;AAAA,EAEA,OAAO,SAAyD;AAC/D,WAAkB,OAAO,MAAM,OAAO;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,SAA8D;AAC5E,WAAsB,SAAS,MAAM,OAAO;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eACL,SAC0C;AAC1C,WAAsB,eAAe,MAAM,OAAO;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,uBAAgC;AAC/B,QAAI,CAAC,KAAK,IAAI,SAAS;AACtB,YAAM,IAAI,eAAe;AAAA,QACxB,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,KAAK;AAAA,MACN,CAAC;AAAA,IACF;AACA,WAAO,KAAK,IAAI;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB,QAAkC;AACpD,QAAI,CAAC,OAAO,WAAW,OAAO,KAAK,KAAK,aAAa,EAAE,WAAW,GAAG;AACpE,aAAO;AAAA,IACR;AAEA,UAAM,kBAAkB,OAAO,QAAQ;AAAA,MAAI,CAAC,QAC3C,KAAK,mBAAmB,GAAG;AAAA,IAC5B;AAEA,WAAO;AAAA,MACN,GAAG;AAAA,MACH,SAAS;AAAA,IACV;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,KAAmC;AAE7D,QAAI,IAAI,QAAQ,QAAW;AAE1B,UAAI,IAAI,WAAW,IAAI,QAAQ,SAAS,GAAG;AAC1C,eAAO;AAAA,UACN,GAAG;AAAA,UACH,SAAS,IAAI,QAAQ,IAAI,CAAC,WAAW,KAAK,mBAAmB,MAAM,CAAC;AAAA,QACrE;AAAA,MACD;AACA,aAAO;AAAA,IACR;AAGA,UAAM,OAAO,KAAK,cAAc,IAAI,QAAQ;AAC5C,UAAM,SAAwB,OAAO,EAAE,GAAG,KAAK,KAAK,KAAK,IAAI;AAG7D,QAAI,OAAO,WAAW,OAAO,QAAQ,SAAS,GAAG;AAChD,aAAO;AAAA,QACN,GAAG;AAAA,QACH,SAAS,OAAO,QAAQ;AAAA,UAAI,CAAC,WAC5B,KAAK,mBAAmB,MAAM;AAAA,QAC/B;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,sBAAsB,MAAmB;AACpD,UAAM,SAA+B;AAAA,MACpC,MAAM;AAAA,MACN,MAAM,KAAK;AAAA,IACZ;AAGA,QAAI,KAAK,WAAW,SAAS,GAAG;AAC/B,YAAM,kBAAkD;AAAA,QACvD,MAAM;AAAA,QACN,YAAY,CAAC,GAAG,KAAK,UAAU;AAAA,MAChC;AAEA,UAAI,KAAK,cAAc,SAAS,GAAG;AAClC,wBAAgB,SAAS,CAAC,GAAG,KAAK,aAAa;AAAA,MAChD;AACA,aAAO,SAAS;AAAA,IACjB,WAAW,KAAK,iBAAiB,QAAW;AAC3C,aAAO,SAAS,KAAK;AAAA,IACtB;AAGA,UAAM,kBAAiC,CAAC;AAGxC,QAAI,qBAAqB;AACxB,YAAM,qBACL,CAAC,KAAK,sBAAsB,KAAK,IAAI,iBAClC,KAAK,IAAI,eAAe,KAAK,IAAI,IACjC;AACJ,UAAI,oBAAoB;AACvB,wBAAgB,KAAK,kBAAkB;AAAA,MACxC;AAAA,IACD;AAGA,oBAAgB,KAAK,GAAG,KAAK,YAAY;AAGzC,QAAI,gBAAgB,WAAW,GAAG;AACjC,YAAM,cAAc,gBAAgB,CAAC;AACrC,UAAI,gBAAgB,QAAW;AAC9B,eAAO,QAAQ;AAAA,MAChB;AAAA,IACD,WAAW,gBAAgB,SAAS,GAAG;AACtC,aAAO,QAAQ,IAAI,GAAG,eAAe;AAAA,IACtC;AAGA,QAAI,KAAK,cAAc,WAAW,GAAG;AACpC,YAAM,eAAe,KAAK,cAAc,CAAC;AACzC,UAAI,iBAAiB,QAAW;AAC/B,eAAO,SAAS;AAAA,MACjB;AAAA,IACD,WAAW,KAAK,cAAc,SAAS,GAAG;AACzC,aAAO,SAAS,IAAI,GAAG,KAAK,aAAa;AAAA,IAC1C;AAGA,QAAI,KAAK,iBAAiB;AACzB,aAAO,WAAW;AAAA,IACnB;AAGA,QAAI,KAAK,kBAAkB,SAAS,GAAG;AACtC,aAAO,aAAa,CAAC,GAAG,KAAK,iBAAiB;AAAA,IAC/C;AAEA,QAAI,KAAK,SAAS,SAAS,GAAG;AAC7B,aAAO,UAAU,KAAK;AAAA,IACvB;AACA,QAAI,KAAK,cAAc,SAAS,GAAG;AAClC,aAAO,UAAU,CAAC,GAAG,KAAK,aAAa;AAAA,IACxC;AACA,QAAI,KAAK,eAAe,SAAS,GAAG;AACnC,aAAO,UAAU,CAAC,GAAG,KAAK,cAAc;AAAA,IACzC;AACA,QAAI,KAAK,eAAe,QAAW;AAClC,aAAO,QAAQ,KAAK;AAAA,IACrB;AACA,QAAI,KAAK,gBAAgB,QAAW;AACnC,aAAO,SAAS,KAAK;AAAA,IACtB;AAGA,QAAI,KAAK,YAAY;AACpB,UAAI,KAAK,cAAc,SAAS,GAAG;AAClC,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,aAAO,OAAO,KAAK;AAAA,IACpB;AAGA,QAAI,KAAK,YAAY,SAAS,GAAG;AAChC,aAAO,QAAQ,CAAC,GAAG,KAAK,WAAW;AAAA,IACpC;AAGA,QAAI,KAAK,mBAAmB;AAC3B,aAAO,oBAAoB,KAAK;AAAA,IACjC;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,4BAA4B,QAAkC;AAC7D,QAAI,KAAK,sBAAsB,CAAC,KAAK,IAAI,eAAgB,QAAO;AAChE,UAAM,qBAAqB,KAAK,IAAI,eAAe,KAAK,IAAI;AAC5D,QAAI,CAAC,mBAAoB,QAAO;AAEhC,UAAM,gBAAgB,OAAO;AAC7B,UAAM,WAAW,gBACd,IAAI,oBAAoB,aAAa,IACrC;AAEH,WAAO,EAAE,GAAG,QAAQ,OAAO,SAAS;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,iBACb,SACA,YACa;AACb,UAAM,QAAQ,KAAK,IAAI;AACvB,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,2CAA2C;AAEvE,WAAO;AAAA,MAAoB;AAAA,MAAO,CAAC,MAClC,KAAK,sBAAyB,SAAS,YAAY,CAAC;AAAA,IACrD;AAAA,EACD;AAAA,EAEA,MAAc,sBACb,SACA,YACA,OACa;AACb,UAAM,YAAY,KAAK,IAAI;AAG3B,UAAM,YAAY,KAAK,YAAY,KAAK;AAGxC,UAAM,YAA8B;AAAA,MACnC,OAAO,KAAK;AAAA,MACZ,WAAW;AAAA,MACX,QAAQ;AAAA,MACR;AAAA,MACA,GAAI,KAAK,IAAI,eAAe,UAAa;AAAA,QACxC,YAAY,KAAK,IAAI;AAAA,MACtB;AAAA,MACA,GAAI,KAAK,IAAI,iBAAiB,EAAE,eAAe,KAAK;AAAA,IACrD;AAGA,QAAI;AACJ,QAAI;AACH,YAAM,eAAe,MAAM;AAAA,QAC1B,MAAM;AAAA,QACN;AAAA,QACA,KAAK,IAAI;AAAA,MACV;AACA,eAAS,aAAa;AAAA,IACvB,SAAS,OAAO;AAEf,UAAI,MAAM,QAAQ,SAAS,GAAG;AAC7B,cAAM,aAAa,MAAM,gBAAgB,MAAM,SAAS;AAAA,UACvD,OAAO,KAAK;AAAA,UACZ,WAAW;AAAA,UACX;AAAA,UACA,QAAQ;AAAA,UACR,OAAO;AAAA,QACR,CAAC;AACD,cAAM;AAAA,MACP;AACA,YAAM;AAAA,IACP;AAGA,aAAS,KAAK,4BAA4B,MAAM;AAGhD,UAAM,kBAAkB,KAAK,mBAAmB,MAAM;AACtD,UAAM,cAA2B;AAAA,MAChC,GAAI,KAAK,IAAI,uBAAuB;AAAA,QACnC,qBAAqB,KAAK,IAAI;AAAA,MAC/B;AAAA,MACA,GAAG,KAAK,IAAI;AAAA,IACb;AAEA,UAAM,aAAa,KAAK;AAAA,MACvB;AAAA,MACA;AAAA,IACD;AAGA,UAAM,iBAA0D;AAAA,MAC/D,OAAO,KAAK,IAAI;AAAA,IACjB;AACA,QAAI,KAAK,IAAI,eAAe,QAAW;AACtC,qBAAe,aAAa,KAAK,IAAI;AAAA,IACtC;AAEA,UAAM,uBAAuB,QAAQ;AAAA,MACpC;AAAA,MACA;AAAA,IACD;AAEA,QAAI;AACJ,QAAI;AACH,oBAAe,MAAM,QAAQ;AAAA,QAC5B,qBAAqB;AAAA,MACtB;AAAA,IACD,SAAS,OAAO;AACf,UAAI,MAAM,QAAQ,SAAS,GAAG;AAC7B,cAAM,aAAa,MAAM,gBAAgB,MAAM,SAAS;AAAA,UACvD,OAAO,KAAK;AAAA,UACZ,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA,OAAO;AAAA,UACP,KAAK,qBAAqB,KAAK;AAAA,QAChC,CAAC;AACD,cAAM;AAAA,MACP;AACA,YAAM;AAAA,IACP;AAGA,UAAM,WAAW,IAAI;AAAA,MACpB,KAAK,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK,IAAI;AAAA,IACV;AACA,aAAS,uBAAuB,aAAa,UAAU;AACvD,aAAS,oBAAoB,aAAa,UAAU;AACpD,QAAI,qBAAqB,iBAAiB,SAAS,GAAG;AACrD,YAAM,SAAS;AAAA,QACd;AAAA,QACA,qBAAqB;AAAA,QACrB;AAAA,QACA;AAAA,MACD;AAAA,IACD;AACA,QAAI,KAAK,kBAAkB,SAAS,GAAG;AACtC,YAAM,SAAS;AAAA,QACd;AAAA,QACA,KAAK;AAAA,QACL;AAAA,MACD;AAAA,IACD;AAGA,UAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,UAAM,WAA6B;AAAA,MAClC,OAAO,KAAK;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,KAAK,qBAAqB,KAAK;AAAA,MAC/B,YAAY,qBAAqB,KAAK;AAAA,MACtC;AAAA,MACA,GAAI,KAAK,IAAI,eAAe,UAAa;AAAA,QACxC,YAAY,KAAK,IAAI;AAAA,MACtB;AAAA,IACD;AAGA,QAAI;AAIH,YAAM,eAAe,MAAM;AAAA,QAC1B,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,KAAK,IAAI;AAAA,MACV;AACA,aAAO;AAAA,IACR,SAAS,OAAO;AACf,UAAI,MAAM,QAAQ,SAAS,GAAG;AAC7B,cAAM,aAAa,MAAM,gBAAgB,MAAM,SAAS;AAAA,UACvD,OAAO,KAAK;AAAA,UACZ,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA,OAAO;AAAA,UACP,KAAK,qBAAqB,KAAK;AAAA,QAChC,CAAC;AACD,cAAM;AAAA,MACP;AACA,YAAM;AAAA,IACP;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAAiC;AACxC,UAAM,aAAa,KAAK,YAAY;AACpC,UAAM;AAAA,MACL,SAAS;AAAA,MACT,SAAS;AAAA,MACT,GAAG;AAAA,IACJ,IAAI;AAIJ,WAAO;AAAA,MACN,GAAG;AAAA,MACH,YAAY;AAAA,MACZ,OAAO;AAAA,IACR;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,4BAA4B,YAAsC;AACzE,UAAM;AAAA,MACL,SAAS;AAAA,MACT,SAAS;AAAA,MACT,GAAG;AAAA,IACJ,IAAI;AAIJ,WAAO;AAAA,MACN,GAAG;AAAA,MACH,YAAY;AAAA,MACZ,OAAO;AAAA,IACR;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,0BACC,QACA,aACa;AACb,QAAI;AACH,aAAO,KAAK,QAAQ,KAAK,IAAI,OAAO,WAAW;AAAA,IAChD,SAAS,OAAO;AACf,UAAI,iBAAiB,oBAAoB;AACxC,eAAO,KAAK,gBAAgB,OAAO,QAAQ,WAAW;AAAA,MACvD;AACA,YAAM;AAAA,IACP;AAAA,EACD;AAAA,EAEQ,gBACP,OACA,QACA,kBAA+B,CAAC,GACnB;AACb,QAAI,KAAK,uBAAuB,GAAG;AAElC,YAAM,IAAI;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACP;AAAA,IACD;AAMA,UAAM,gBAAgB,MAAM,QAAQ,MAAM,EAAE,KAAK;AACjD,UAAM,gBAAgB,cAAc,CAAC;AACrC,QAAI,CAAC,eAAe;AACnB,YAAM;AAAA,IACP;AAEA,UAAM,kBAAkB,GAAG,MAAM,WAAW,IAAI,MAAM,WAAW;AACjE,UAAM,cAA2B;AAAA,MAChC,GAAG;AAAA,MACH,cAAc;AAAA,QACb,GAAG,gBAAgB;AAAA,QACnB,CAAC,eAAe,GAAG;AAAA;AAAA,MACpB;AAAA,IACD;AAGA,UAAM,SAAS,KAAK,QAAQ,KAAK,IAAI,OAAO,WAAW;AAMvD,UAAM,UAAU;AAAA,MACf,MAAM;AAAA,MACN,SACC,0BAA0B,MAAM,WAAW,WAAW,MAAM,WAAW,oCACrC,aAAa,kDACzB,cAAc,KAAK,IAAI,CAAC;AAAA,MAC/C,YAAY,eAAe,aAAa;AAAA,IACzC;AAEA,WAAO;AAAA,MACN,GAAG;AAAA,MACH,UAAU,CAAC,GAAG,OAAO,UAAU,OAAO;AAAA,IACvC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,QAAmC;AAGlC,WAAO,KAAK;AAAA,MACX,KAAK,IAAI,wBAAwB,SAC9B,EAAE,qBAAqB,EAAE,GAAG,KAAK,IAAI,oBAAoB,EAAE,IAC3D,CAAC;AAAA,IACL;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBACP,aAC4B;AAC5B,UAAM,UAAU,IAAI;AAAA,MACnB,EAAE,GAAG,KAAK,KAAK,GAAG,YAAY;AAAA,MAC9B,KAAK;AAAA,MACL,EAAE,GAAG,KAAK,cAAc;AAAA,IACzB;AAEA,YAAQ,SAAS,KAAK,GAAG,KAAK,QAAQ;AACtC,YAAQ,kBAAkB,KAAK,GAAG,KAAK,iBAAiB;AACxD,YAAQ,aAAa,KAAK,GAAG,KAAK,YAAY;AAC9C,YAAQ,cAAc,KAAK,GAAG,KAAK,aAAa;AAChD,YAAQ,WAAW,KAAK,GAAG,KAAK,UAAU;AAC1C,YAAQ,cAAc,KAAK,GAAG,KAAK,aAAa;AAChD,YAAQ,eAAe,KAAK,GAAG,KAAK,cAAc;AAElD,YAAQ,eAAe,KAAK;AAC5B,YAAQ,kBAAkB,KAAK;AAC/B,YAAQ,oBAAoB,CAAC,GAAG,KAAK,iBAAiB;AACtD,YAAQ,qBAAqB,KAAK;AAClC,YAAQ,qBAAqB,KAAK;AAClC,YAAQ,aAAa,KAAK;AAC1B,YAAQ,cAAc,KAAK;AAC3B,YAAQ,aAAa,KAAK;AAC1B,YAAQ,YAAY,KAAK,GAAG,KAAK,WAAW;AAC5C,QAAI,KAAK,mBAAmB;AAC3B,cAAQ,oBAAoB,KAAK;AAAA,IAClC;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,OAA4D;AACjE,WAAO,IAAI;AAAA,MACV;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,MACA,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,IACV;AAAA,EACD;AAAA,EAEA,SAAS,OAA4D;AACpE,WAAO,IAAI;AAAA,MACV;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,MACA,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,IACV;AAAA,EACD;AAAA,EAEA,UAAU,OAA4D;AACrE,WAAO,IAAI;AAAA,MACV;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,MACA,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,IACV;AAAA,EACD;AAAA,EAEA,aAAa,OAA4D;AACxE,WAAO,IAAI;AAAA,MACV;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,MACA,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,IACV;AAAA,EACD;AAAA,EAEA,OAAO,OAA4D;AAClE,WAAO,IAAI;AAAA,MACV;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,MACA,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,IACV;AAAA,EACD;AAAA,EAEA,UAAU,OAA4D;AACrE,WAAO,IAAI;AAAA,MACV;AAAA,QACC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,MACA,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,IACV;AAAA,EACD;AAAA,EAEA,wBAA+C;AAC9C,UAAM,UAAU,KAAK,MAAM;AAC3B,YAAQ,qBAAqB;AAC7B,WAAO;AAAA,EACR;AACD;;;ACjrDO,IAAM,qBAAN,MAA4C;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YACC,SACA,cACA,SACA,YACC;AACD,SAAK,UAAU;AACf,SAAK,eAAe;AACpB,SAAK,UAAU;AACf,SAAK,aAAa;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,MAA+B;AACtC,SAAK,cAAc;AAAA,MAClB,MAAM;AAAA,MACN,SAAS,KAAK,IAAI,CAAC,YAAY,EAAE,MAAM,UAAU,OAAO,EAAE;AAAA,IAC3D;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAA8B;AACnC,SAAK,aAAa;AAClB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,QAAgB,YAA4B,OAAa;AAChE,UAAM,SAAwB,EAAE,OAAO,QAAQ,UAAU;AACzD,SAAK,eAAe,CAAC,GAAI,KAAK,gBAAgB,CAAC,GAAI,MAAM;AACzD,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,GAAiB;AACtB,SAAK,aAAa;AAClB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,GAAiB;AACvB,SAAK,cAAc;AACnB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,cAA8B;AAC7B,UAAM,cAA2B;AAAA,MAChC,MAAM;AAAA,MACN,MAAM,KAAK;AAAA,MACX,GAAI,KAAK,gBAAgB,UAAa,EAAE,QAAQ,KAAK,YAAY;AAAA,MACjE,GAAI,KAAK,eAAe,UAAa,EAAE,OAAO,KAAK,WAAW;AAAA,MAC9D,GAAI,KAAK,iBAAiB,UAAa,EAAE,SAAS,KAAK,aAAa;AAAA,MACpE,GAAI,KAAK,eAAe,UAAa,EAAE,OAAO,KAAK,WAAW;AAAA,MAC9D,GAAI,KAAK,gBAAgB,UAAa,EAAE,QAAQ,KAAK,YAAY;AAAA,IAClE;AAEA,WAAO;AAAA,MACN,MAAM;AAAA,MACN,MAAM,CAAC,KAAK,YAAY;AAAA,MACxB,OAAO;AAAA,IACR;AAAA,EACD;AAAA,EAEQ,iBAA0B;AACjC,WAAO,eAAmB,KAAK,SAAS,WAAW;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAsB;AACrB,UAAM,UAAU,KAAK,eAAe;AACpC,UAAM,SAAS,KAAK,YAAY;AAChC,UAAM,iBAAiB,KAAK,aACzB,EAAE,YAAY,KAAK,WAAW,IAC9B;AACH,UAAM,WAA0B,QAAQ;AAAA,MACvC;AAAA,MACA;AAAA,IACD;AACA,WAAO;AAAA,MACN,KAAK,SAAS;AAAA,MACd,QAAQ,SAAS;AAAA,MACjB;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAA0B;AAC/B,UAAM,UAAU,KAAK,eAAe;AACpC,UAAM,SAAS,KAAK,YAAY;AAChC,UAAM,iBAAiB,KAAK,aACzB,EAAE,YAAY,KAAK,WAAW,IAC9B;AACH,UAAM,WAAW,QAAQ;AAAA,MACxB;AAAA,MACA;AAAA,IACD;AACA,WAAO,QAAQ,QAAQ,QAAQ;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,UAA8B;AAC7B,WAAO,KAAK,IAAI;AAAA,EACjB;AACD;AAKO,SAAS,oBACf,SACA,SACA,SACA,YAC8B;AAC9B,QAAM,aACL,QAAQ,KACP,YAAY;AACd,QAAM,aACL,QAAQ,KACP,YAAY;AAEd,QAAM,eAA6B;AAAA,IAClC,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,UAAU,QAAQ,YAAY;AAAA,IAC9B,GAAI,QAAQ,aAAa,UAAa,EAAE,UAAU,QAAQ,SAAS;AAAA,IACnE,GAAI,QAAQ,gBAAgB,UAAa;AAAA,MACxC,aAAa,QAAQ;AAAA,IACtB;AAAA,EACD;AAEA,SAAO,IAAI;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;;;AC5KA,SAAS,WAAW,MAAsB;AACzC,SAAO,IAAI,KAAK,QAAQ,MAAM,IAAI,CAAC;AACpC;AAGA,SAAS,oBACR,WACA,YACS;AACT,SAAO,aACJ,GAAG,WAAW,UAAU,CAAC,IAAI,WAAW,SAAS,CAAC,KAClD,WAAW,SAAS;AACxB;AAEA,SAAS,oBACR,WACA,YACA,SACS;AACT,QAAM,QAAQ,CAAC,YAAY,oBAAoB,WAAW,UAAU,CAAC,EAAE;AACvE,MAAI,SAAS,gBAAiB,OAAM,KAAK,kBAAkB;AAC3D,MAAI,SAAS,QAAS,OAAM,KAAK,SAAS;AAC1C,SAAO,MAAM,KAAK,GAAG;AACtB;AAEA,SAAS,kBACR,WACA,YACA,SACS;AACT,QAAM,YAAsB,CAAC;AAC7B,MAAI,SAAS,KAAM,WAAU,KAAK,MAAM;AACxC,MAAI,SAAS,QAAS,WAAU,KAAK,SAAS;AAC9C,QAAM,MAAM,UAAU,SAAS,IAAI,IAAI,UAAU,KAAK,IAAI,CAAC,OAAO;AAClE,SAAO,UAAU,GAAG,GAAG,oBAAoB,WAAW,UAAU,CAAC;AAClE;AAEA,SAAS,uBACR,WACA,QACA,YACA,SACS;AACT,QAAM,MAAM,oBAAoB,WAAW,UAAU;AACrD,QAAMC,OAAM,WAAW,MAAM;AAC7B,QAAM,UAAoB,CAAC;AAE3B,MAAI,QAAQ,SAAS,QAAW;AAC/B,QAAI,SAAS,gBAAgBA,IAAG,SAAS,QAAQ,IAAI;AACrD,QAAI,QAAQ,UAAU,QAAW;AAChC,gBAAU,UAAU,QAAQ,KAAK;AAAA,IAClC;AACA,YAAQ,KAAK,MAAM;AAAA,EACpB;AACA,MAAI,QAAQ,eAAe,MAAM;AAChC,YAAQ,KAAK,gBAAgBA,IAAG,eAAe;AAAA,EAChD,WAAW,QAAQ,eAAe,OAAO;AACxC,YAAQ,KAAK,gBAAgBA,IAAG,gBAAgB;AAAA,EACjD;AACA,MAAI,QAAQ,gBAAgB,MAAM;AACjC,YAAQ,KAAK,gBAAgBA,IAAG,eAAe;AAAA,EAChD,WAAW,QAAQ,eAAe,QAAW;AAC5C,YAAQ,KAAK,gBAAgBA,IAAG,gBAAgB,QAAQ,UAAU,EAAE;AAAA,EACrE;AACA,MAAI,QAAQ,WAAW,GAAG;AACzB,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACA,SAAO,eAAe,GAAG,IAAI,QAAQ,KAAK,IAAI,CAAC;AAChD;AAEA,SAAS,uBACR,WACA,YACA,MACS;AACT,QAAM,MAAM,oBAAoB,WAAW,UAAU;AACrD,QAAM,QAAkB,CAAC,QAAQ;AACjC,MAAI,KAAK,OAAQ,OAAM,KAAK,QAAQ;AACpC,QAAM,KAAK,OAAO;AAClB,MAAI,KAAK,aAAc,OAAM,KAAK,cAAc;AAChD,MAAI,KAAK,YAAa,OAAM,KAAK,eAAe;AAChD,QAAM,KAAK,WAAW,KAAK,IAAI,CAAC;AAChC,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,GAAG;AACd,MAAI,KAAK,OAAQ,OAAM,KAAK,SAAS,KAAK,MAAM,EAAE;AAElD,QAAM,UAAU,KAAK,QAAQ,IAAI,CAACA,SAAQ;AACzC,QAAI,OAAOA,SAAQ,UAAU;AAC5B,YAAM,YAAY,WAAWA,IAAG;AAChC,YAAMC,MAAK,KAAK,UAAUD,IAAG,KAAK,OAAO,IAAI,KAAK,QAAQA,IAAG,CAAC,KAAK;AACnE,aAAO,GAAG,SAAS,GAAGC,GAAE;AAAA,IACzB;AACA,UAAMA,MAAKD,KAAI,WAAW,OAAO,IAAIA,KAAI,OAAO,KAAK;AACrD,WAAO,IAAIA,KAAI,UAAU,IAAIC,GAAE;AAAA,EAChC,CAAC;AACD,QAAM,KAAK,IAAI,QAAQ,KAAK,IAAI,CAAC,GAAG;AAEpC,MAAI,KAAK,WAAW,KAAK,QAAQ,SAAS,GAAG;AAC5C,UAAM;AAAA,MACL,YAAY,KAAK,QAAQ,IAAI,CAAC,MAAM,WAAW,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,IAC9D;AAAA,EACD;AACA,MAAI,KAAK,QAAQ,OAAO,KAAK,KAAK,IAAI,EAAE,SAAS,GAAG;AACnD,UAAM,cAAc,OAAO,QAAQ,KAAK,IAAI,EAC1C,IAAI,CAAC,CAAC,GAAGC,EAAC,MAAM,GAAG,CAAC,MAAMA,EAAC,EAAE,EAC7B,KAAK,IAAI;AACX,UAAM,KAAK,SAAS,WAAW,GAAG;AAAA,EACnC;AACA,MAAI,KAAK,MAAO,OAAM,KAAK,SAAS,KAAK,KAAK,EAAE;AAChD,SAAO,MAAM,KAAK,GAAG;AACtB;AAEA,SAAS,qBACR,MACA,YACA,SACS;AACT,QAAM,QAAkB,CAAC,YAAY;AACrC,MAAI,SAAS,aAAc,OAAM,KAAK,cAAc;AACpD,MAAI,SAAS,SAAU,OAAM,KAAK,WAAW;AAC7C,QAAM,KAAK,SAAS,UAAU;AAC9B,QAAM,KAAK,KAAK,GAAG,WAAW,EAAE,CAAC,IAAI,WAAW,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC;AAC1E,MAAI,SAAS,QAAS,OAAM,KAAK,SAAS;AAC1C,SAAO,MAAM,KAAK,GAAG;AACtB;AAIA,SAAS,cACR,WACA,YACA,SACAC,iBACsB;AACtB,SAAO;AAAA,IACN,MAAM,OAAO,MAAyC;AACrD,YAAM,IAAIA,gBAAe;AACzB,UAAI,KAAK,gBAAgB,EAAE,eAAe;AACzC,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,YAAMC,OAAM,EAAE,sBACX,EAAE,oBAAoB,WAAW,MAAM,UAAU,IACjD,uBAAuB,WAAW,YAAY,IAAI;AACrD,YAAM,EAAE,aAAaA,IAAG;AAAA,IACzB;AAAA,IAEA,MAAM,KAAK,MAAc,SAA2C;AACnE,YAAM,IAAID,gBAAe;AACzB,UAAI,SAAS,gBAAgB,EAAE,eAAe;AAC7C,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,YAAMC,OAAM,EAAE,oBACX,EAAE,kBAAkB,MAAM,OAAO,IACjC,qBAAqB,MAAM,YAAY,OAAO;AACjD,YAAM,EAAE,aAAaA,IAAG;AAAA,IACzB;AAAA,IAEA,MAAM,KAAK,SAA0D;AACpE,UAAI,CAAC,SAAS;AACb,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,UAAI,QAAQ,aAAa;AACxB,eAAO,QAAQ,YAAY,WAAW,YAAY,OAAO;AAAA,MAC1D;AAEA,YAAMA,OACL,mTAGsC,UAAU,QAAQ,MAAM,IAAI,CAAC,QAClE,aACE,qBAAqB,WAAW,QAAQ,MAAM,IAAI,CAAC,OACnD,MACH;AACD,UAAI,gBAAgB,WAAW,OAAO,QAAQ,eAAe,YAAY;AACxE,cAAM,OAAO,MACZ,QAAQ,WAIPA,MAAK,CAAC,CAAC;AACT,eAAO;AAAA,MACR;AAEA,UAAI,QAAQ,WAAY,OAAM,QAAQ,WAAWA,IAAG;AACpD,aAAO,CAAC;AAAA,IACT;AAAA,IAEA,MAAM,OAAO,MAAgC;AAC5C,UAAI,CAAC,SAAS;AACb,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,UAAI,CAAC,QAAQ,aAAa;AACzB,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,aAAO,QAAQ,YAAY,MAAM,WAAW,UAAU;AAAA,IACvD;AAAA,EACD;AACD;AAOA,SAAS,cACR,WACA,YACA,SACW;AACX,WAASD,kBAAmC;AAC3C,QAAI,CAAC,SAAS,YAAY;AACzB,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MAED;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAEA,SAAO;AAAA,IACN,MAAM,SAAS,SAA0C;AACxD,YAAM,IAAIA,gBAAe;AACzB,YAAMC,OAAM,EAAE,mBACX,EAAE,iBAAiB,WAAW,YAAY,OAAO,IACjD,oBAAoB,WAAW,YAAY,OAAO;AACrD,YAAM,EAAE,aAAaA,IAAG;AAAA,IACzB;AAAA,IAEA,MAAM,OAAO,SAAwC;AACpD,YAAM,IAAID,gBAAe;AACzB,UAAI,EAAE,eAAe;AACpB,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,YAAMC,OAAM,EAAE,iBACX,EAAE,eAAe,WAAW,YAAY,OAAO,IAC/C,kBAAkB,WAAW,YAAY,OAAO;AACnD,YAAM,EAAE,aAAaA,IAAG;AAAA,IACzB;AAAA,IAEA,MAAM,YACL,QACA,SACgB;AAChB,yBAAmB,WAAW,OAAO;AACrC,yBAAmB,QAAQ,QAAQ;AACnC,YAAM,IAAID,gBAAe;AACzB,YAAMC,OAAM,EAAE,sBACX,EAAE,oBAAoB,WAAW,QAAQ,SAAS,UAAU,IAC5D,uBAAuB,WAAW,QAAQ,YAAY,OAAO;AAChE,YAAM,EAAE,aAAaA,IAAG;AAAA,IACzB;AAAA,IAEA,SAAS,cAAc,WAAW,YAAY,SAASD,eAAc;AAAA,IAErE,MAAM,cAA+B;AACpC,UAAI,CAAC,SAAS;AACb,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,UAAI,CAAC,QAAQ,aAAa;AACzB,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,aAAO,QAAQ,YAAY,WAAW,UAAU;AAAA,IACjD;AAAA,EACD;AACD;AAOO,SAAS,uBACf,aACA,SACA,YACS;AAET,QAAM,QAAQ,oBAAI,IAAoB;AAEtC,SAAO,IAAI,MAAM,aAAa;AAAA,IAC7B,IAAI,QAAQ,MAAM,UAAU;AAE3B,UAAI,OAAO,SAAS,UAAU;AAC7B,eAAO,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAAA,MAC1C;AAEA,UAAI,MAAM,IAAI,IAAI,GAAG;AACpB,eAAO,MAAM,IAAI,IAAI;AAAA,MACtB;AAEA,YAAM,WAAW,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AACnD,UAAI,aAAa,UAAa,aAAa,MAAM;AAChD,eAAO;AAAA,MACR;AAGA,YAAM,MAAM,cAAc,MAAM,YAAY,OAAO;AACnD,YAAM,YAAY,OAAO,OAAO,uBAAO,OAAO,IAAI,GAAG,UAAU,GAAG;AAClE,YAAM,IAAI,MAAM,SAAS;AACzB,aAAO;AAAA,IACR;AAAA,EACD,CAAC;AACF;AAQO,SAAS,kBACf,OACA,YACA,eACA,SACA,YACA,qBACA,kBACA,mBACA,gBACA,WACA,aACA,eACA,aAC0B;AAG1B,QAAM,MAAc;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAGA,QAAM,eAAe;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAGA,QAAM,WAAgC;AAAA,IACrC;AAAA,IACA;AAAA,IACA,GAAI,YAAY,SAAY,EAAE,QAAqC,IAAI,CAAC;AAAA,IACxE,GAAI,eAAe,SAAY,EAAE,WAAW,IAAI,CAAC;AAAA,IACjD,GAAI,wBAAwB,SAAY,EAAE,oBAAoB,IAAI,CAAC;AAAA,IACnE,GAAI,sBAAsB,SACvB,EAAE,qBAAqB,kBAAkB,IACzC,CAAC;AAAA,IACJ,GAAI,mBAAmB,SAAY,EAAE,eAAe,IAAI,CAAC;AAAA,IACzD,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IAC/C,GAAI,gBAAgB,SAAY,EAAE,YAAY,IAAI,CAAC;AAAA,IACnD,GAAI,kBAAkB,SAAY,EAAE,cAAc,IAAI,CAAC;AAAA,EACxD;AAGA,QAAM,iBAAiB;AAAA,IACtB,eAAe,CAAC;AAAA,IAChB;AAAA,IACA;AAAA,EACD;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA,QAAQ;AAAA;AAAA,IAER,KACC,OAGwC;AAExC,UACC,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,SACX,MAAoC,WAAW,eAC/C;AACD,cAAM,KAAK;AACX,cAAM,UAAU,IAAI;AAAA,UACnB;AAAA,UACA,GAAG;AAAA,UACH;AAAA,QACD;AACA,gBAAQ,oBAAoB;AAAA,UAC3B,MAAM,GAAG;AAAA,UACT,SAAS,GAAG;AAAA,UACZ,OAAO,GAAG;AAAA,UACV,OAAO,GAAG;AAAA,UACV,YAAY,GAAG;AAAA,QAChB;AACA,eAAO;AAAA,MACR;AACA,YAAM,WAAW;AACjB,YAAM,YAAY,SAAS,UAAU;AACrC,UAAI,cAAc,QAAW;AAC5B,cAAM,IAAI,MAAM,6CAA6C;AAAA,MAC9D;AACA,aAAO,IAAI;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA,IACA,OACC,MACwB;AACxB,aAAO,IAAI;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA,IACA,WAAWE,aAA6C;AAEvD,yBAAmBA,aAAY,QAAQ;AACvC,UAAI,SAAS;AACZ,gBAAQ,mBAAmBA,aAAY,QAAQ;AAAA,MAChD;AAEA,YAAM,gBAAgB,SAAS,WAAWA,WAAU;AACpD,aAAO;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACAA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAgBA,MAAM,cACL,OACA,aACA,SACqB;AACrB,UAAI,CAAC,SAAS;AACb,cAAM,IAAI;AAAA,UACT;AAAA,QAED;AAAA,MACD;AAGA,UAAI,CAAC,MAAM,SAAS,KAAK,GAAG;AAC3B,cAAM,IAAI,sBAAsB,iBAAiB,iBAAiB;AAAA,MACnE;AAKA,YAAM,sBAAsB;AAC5B,YAAM,cAAc,QAAQ,YAAY;AACxC,UAAI,CAAC,OAAO,cAAc,WAAW,KAAK,cAAc,GAAG;AAC1D,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,YAAM,eAAe,KAAK,IAAI,aAAa,mBAAmB;AAG9D,YAAM,kBAAkB,oBAAoB,OAAO,OAAO,WAAW;AACrE,UAAI,CAAC,iBAAiB;AACrB,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAEA,YAAM,YAAY,QAAQ,UAAU;AAGpC,YAAM,EAAE,eAAe,UAAU,GAAG,iBAAiB,IAAI;AACzD,YAAM,eAAoC;AAE1C,YAAM,UAAU,IAAI;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAEA,YAAM,SAAS,MAAM,QACnB,MAAM,GAAG,WAAW,WAAW,CAAC,EAChC,QAAQ,gBAAgB,MAAM;AAAA,QAC9B,WAAW;AAAA,QACX,WAAW;AAAA,QACX,MAAM;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA,MACX,CAAC,EACA,MAAM;AAIR,aAAO,sBAA+B,QAAQ,WAAW;AAAA,IAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWA,MAAM,gBACL,OACA,aACA,SACqB;AACrB,UAAI,CAAC,SAAS;AACb,cAAM,IAAI;AAAA,UACT;AAAA,QAED;AAAA,MACD;AAGA,UAAI,CAAC,MAAM,SAAS,KAAK,GAAG;AAC3B,cAAM,IAAI,sBAAsB,mBAAmB,iBAAiB;AAAA,MACrE;AAKA,YAAM,sBAAsB;AAC5B,YAAM,cAAc,QAAQ,YAAY;AACxC,UAAI,CAAC,OAAO,cAAc,WAAW,KAAK,cAAc,GAAG;AAC1D,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AACA,YAAM,eAAe,KAAK,IAAI,aAAa,mBAAmB;AAG9D,YAAM,kBAAkB,oBAAoB,OAAO,OAAO,aAAa;AACvE,UAAI,CAAC,iBAAiB;AACrB,cAAM,IAAI;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAEA,YAAM,YAAY,QAAQ,UAAU;AAGpC,YAAM,EAAE,eAAe,UAAU,GAAG,iBAAiB,IAAI;AACzD,YAAM,eAAoC;AAE1C,YAAM,UAAU,IAAI;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAEA,YAAM,SAAS,MAAM,QACnB,MAAM,GAAG,WAAW,WAAW,CAAC,EAChC,QAAQ,gBAAgB,MAAM;AAAA,QAC9B,WAAW;AAAA,QACX,WAAW;AAAA,QACX,MAAM;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA,MACX,CAAC,EACA,MAAM;AAIR,aAAO,sBAA+B,QAAQ,aAAa;AAAA,IAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQA,KACC,UACuC;AACvC,YAAM,YAAY,SAAS,UAAU;AACrC,UAAI,cAAc,QAAW;AAC5B,cAAM,IAAI,MAAM,6CAA6C;AAAA,MAC9D;AACA,aAAO,IAAI,cAAc;AAAA,QACxB,OAAO;AAAA,QACP,GAAG;AAAA,MACJ,CAAC;AAAA,IACF;AAAA;AAAA,IAGA,OACC,UACuC;AACvC,YAAM,YAAY,SAAS,UAAU;AACrC,UAAI,cAAc,QAAW;AAC5B,cAAM,IAAI,MAAM,6CAA6C;AAAA,MAC9D;AACA,aAAO,IAAI,cAAc;AAAA,QACxB,OAAO;AAAA,QACP,GAAG;AAAA,MACJ,CAAC;AAAA,IACF;AAAA;AAAA,IAGA,WACC,UACuC;AACvC,YAAM,YAAY,SAAS,UAAU;AACrC,UAAI,cAAc,QAAW;AAC5B,cAAM,IAAI,MAAM,6CAA6C;AAAA,MAC9D;AACA,aAAO,IAAI,cAAc;AAAA,QACxB,OAAO;AAAA,QACP,GAAG;AAAA,MACJ,CAAC;AAAA,IACF;AAAA;AAAA,IAGA,WACC,UACuC;AACvC,YAAM,YAAY,SAAS,UAAU;AACrC,UAAI,cAAc,QAAW;AAC5B,cAAM,IAAI,MAAM,6CAA6C;AAAA,MAC9D;AACA,aAAO,IAAI,cAAc;AAAA,QACxB,OAAO;AAAA,QACP,GAAG;AAAA,MACJ,CAAC;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAMA,OAAO,OAA8B;AACpC,yBAAmB,OAAO,OAAO;AACjC,aAAO,IAAI,cAAc,EAAE,OAAO,GAAG,aAAa,CAAC;AAAA,IACpD;AAAA,IAEA,OAAO,OAA8B;AACpC,yBAAmB,OAAO,OAAO;AACjC,aAAO,IAAI,cAAc,EAAE,OAAO,GAAG,aAAa,CAAC;AAAA,IACpD;AAAA,IAEA,OAAO,OAA8B;AACpC,yBAAmB,OAAO,OAAO;AACjC,aAAO,IAAI,cAAc,EAAE,OAAO,GAAG,aAAa,CAAC;AAAA,IACpD;AAAA,IAEA,UAAU,OAA8B;AACvC,yBAAmB,OAAO,OAAO;AACjC,aAAO,IAAI,cAAc,EAAE,OAAO,UAAU,MAAM,GAAG,aAAa,CAAC;AAAA,IACpE;AAAA,IAEA,UAAU,OAA8B;AACvC,yBAAmB,OAAO,OAAO;AACjC,aAAO,IAAI,cAAc,EAAE,OAAO,UAAU,MAAM,GAAG,aAAa,CAAC;AAAA,IACpE;AAAA;AAAA,IAGA,OAAO,OAA8B;AACpC,yBAAmB,OAAO,OAAO;AACjC,aAAO,IAAI,cAAc,EAAE,OAAO,GAAG,aAAa,CAAC;AAAA,IACpD;AAAA;AAAA;AAAA;AAAA,IAMA,MAAM,YAAeC,KAAqD;AACzE,UAAI,CAAC,SAAS;AACb,cAAM,IAAI;AAAA,UACT;AAAA,QAED;AAAA,MACD;AAGA,aAAO,QAAQ,YAAY,OAAO,cAAc;AAE/C,cAAM,QAAQ;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,UACA;AAAA,QACD;AACA,eAAOA,IAAG,KAAK;AAAA,MAChB,CAAC;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA+BA,MAAM,IACL,WACA,aAAiC,CAAC,GACnB;AACf,UAAI,CAAC,SAAS;AACb,cAAM,IAAI;AAAA,UACT;AAAA,QAED;AAAA,MACD;AAGA,aAAO,QAAQ,WAAc,WAAW,UAAU;AAAA,IACnD;AAAA,IAEA,YACC,MACA,SACA,OACA,MACiB;AACjB,aAAO,YAAY,MAAM,SAAS,OAAO,IAAI;AAAA,IAC9C;AAAA,IAEA,iBAAiB,MAA8C;AAC9D,UAAI,CAAC,SAAS;AACb,cAAM,IAAI;AAAA,UACT;AAAA,QAED;AAAA,MACD;AACA,YAAM,WAAW,QAAQ,wBAAwB,KAAK,MAAM;AAC5D,aAAO;AAAA,QACN,KAAK,SAAS;AAAA,QACd,YAAY,SAAS;AAAA,QACrB,UAAqC;AACpC,iBAAO,SAAS,WAAc,SAAS,KAAK,SAAS,UAAU;AAAA,QAChE;AAAA,MACD;AAAA,IACD;AAAA,IAEA,QAAQ,MAA0B;AACjC,aAAO,IAAI,WAAW,MAAM,SAAS,UAAU;AAAA,IAChD;AAAA,IAEA,UACC,MACA,SAC8B;AAC9B,aAAO,oBAA6B,MAAM,SAAS,SAAS,UAAU;AAAA,IACvE;AAAA;AAAA;AAAA;AAAA,IAMA,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOJ,MAAM,UAAU,MAAc,SAA2C;AACxE,YAAI,CAAC,SAAS,YAAY;AACzB,gBAAM,IAAI;AAAA,YACT;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAEA,2BAAmB,MAAM,OAAO;AAChC,cAAM,KAAK,SAAS,UAAU;AAC9B,YAAI,IAAI;AACP,6BAAmB,IAAI,QAAQ;AAAA,QAChC;AACA,cAAMF,OAAM,QAAQ,oBACjB,QAAQ,kBAAkB,MAAM,OAAO,KACtC,MAAM;AACP,gBAAM,QAAkB,CAAC,YAAY;AACrC,cAAI,SAAS,aAAc,OAAM,KAAK,cAAc;AACpD,cAAI,SAAS,SAAU,OAAM,KAAK,WAAW;AAC7C,gBAAM;AAAA,YACL,KACG,IAAI,GAAG,QAAQ,MAAM,IAAI,CAAC,MAAM,KAAK,QAAQ,MAAM,IAAI,CAAC,MACxD,IAAI,KAAK,QAAQ,MAAM,IAAI,CAAC;AAAA,UAChC;AACA,cAAI,SAAS,QAAS,OAAM,KAAK,SAAS;AAC1C,iBAAO,MAAM,KAAK,GAAG;AAAA,QACtB,GAAG;AACL,cAAM,QAAQ,WAAWA,IAAG;AAAA,MAC7B;AAAA,IACD;AAAA,EACD;AACD;;;AC3uBO,SAAS,UACf,SAC0B;AAC1B,QAAM;AAAA,IACL,QAAQ;AAAA,IACR,OAAO;AAAA,IACP;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,IACb,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EACD,IAAI;AAIJ,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,aAAa,WAAW,WAAW;AAEtC,YAAQ,UAAU;AAClB,uBAAmB,UAAU;AAC7B,qBAAiB,UAAU;AAG3B,QACC,WACA,UAAU,YACV,QAAQ,YACR,UAAU,aAAa,QAAQ,UAC9B;AACD,YAAM,IAAI,8BAA8B;AAAA,QACvC,cAAc,UAAU;AAAA,QACxB,eAAe,QAAQ;AAAA,MACxB,CAAC;AAAA,IACF;AAAA,EACD,WAAW,aAAa;AAEvB,YAAQ;AACR,uBAAmB;AACnB,qBAAiB;AAAA,EAClB,OAAO;AACN,UAAM,IAAI;AAAA,MACT;AAAA,IAGD;AAAA,EACD;AAGA,MAAI,SAAS,qBAAqB;AACjC,UAAM,SAAS;AAAA,MACd;AAAA,MACA,QAAQ;AAAA,MACR,uBAAuB;AAAA,IACxB;AACA,eAAW,KAAK,OAAO,UAAU;AAChC,cAAQ,KAAK,UAAU,EAAE,OAAO,EAAE;AAAA,IACnC;AAAA,EACD;AAGA,QAAM,kBAAkB,cACrB,aAAa,YAAY,OAAO,CAAC,IACjC;AAIH,QAAM,cACL,aAAa,YAAY,YACrB,UAAU,SACX,kBAAkB,OAAO,MAAM,SAAS,CAAC,GAAG,MAAM,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC;AAIzE,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA,CAAC;AAAA;AAAA,IACD;AAAA,IACA;AAAA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IACA;AAAA,EACD;AACD;;;AC3OA,SAAS,YACR,OACA,WACgB;AAChB,SAAO,GAAG,WAAW,MAAM,MAAM,CAAC,CAAC,GAAG,MAAM,MAAM,CAAC,CAAC,CAAC;AACtD;AAOA,SAAS,kBAAkB,KAAsB;AAChD,MAAI,IAAI,WAAW,GAAG;AACrB,UAAM,IAAI;AAAA,MACT,iDAAiD,IAAI,MAAM;AAAA,IAC5D;AAAA,EACD;AACD;AA8BO,SAAS,cACf,eACA,cACA,YAAuB,aACY;AACnC,MAAI,MAAM,QAAQ,YAAY,GAAG;AAChC,sBAAkB,YAAY;AAC9B,UAAM,QAAQ;AACd,WAAO,GAAG,MAAMG,KAAI,aAAa,GAAG,YAAY,OAAO,SAAS,CAAC;AAAA,EAClE;AACA,SAAO;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO;AAAA,EACR;AACD;AA4BO,SAAS,cACf,eACA,cACA,YAAuB,aACY;AACnC,MAAI,MAAM,QAAQ,YAAY,GAAG;AAChC,sBAAkB,YAAY;AAC9B,UAAM,QAAQ;AACd,WAAO,GAAG,MAAMA,KAAI,aAAa,GAAG,YAAY,OAAO,SAAS,CAAC;AAAA,EAClE;AACA,SAAO;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO;AAAA,EACR;AACD;AA4BO,SAAS,iBACf,eACA,cACA,YAAuB,aACY;AACnC,MAAI,MAAM,QAAQ,YAAY,GAAG;AAChC,sBAAkB,YAAY;AAC9B,UAAM,QAAQ;AACd,WAAO,GAAG,MAAMA,KAAI,aAAa,GAAG,YAAY,OAAO,SAAS,CAAC;AAAA,EAClE;AACA,SAAO;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO;AAAA,EACR;AACD;;;AC1MA,YAAY,OAAO;AAkQnB,SAAS,0BAA0B,SAA0C;AAC5E,UAAQ,SAAS;AAAA,IAChB,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AAAA,IACL,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,EACT;AACD;AAKA,SAASC,iBAAgB,MAA2C;AACnE,UAAQ,MAAM;AAAA,IACb,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,EACT;AACD;AAKA,SAAS,2BACR,WACA,UACA,aACU;AACV,QAAM,UAAsB,CAAC;AAC7B,QAAM,cAA8B,CAAC;AACrC,QAAM,UAAqB,CAAC;AAC5B,QAAM,cAAwB,CAAC;AAE/B,QAAM,iBAAiB,oBAAI,IAAY;AAEvC,aAAW,CAAC,SAAS,MAAM,KAAK,OAAO,QAAQ,QAAQ,GAAG;AAEzD,UAAMC,OAAyB;AAAA,MAC9B,MAAM;AAAA,MACN,MAAM,0BAA0B,OAAO,IAAI;AAAA,MAC3C,UAAU,OAAO,YAAY;AAAA,MAC7B,SAAS,OAAO;AAAA,IACjB;AACA,QAAI,OAAO,WAAW,QAAW;AAChC,MAAAA,KAAI,SAAS,OAAO;AAAA,IACrB;AACA,QAAI,OAAO,kBAAkB,QAAW;AACvC,MAAAA,KAAI,gBAAgB,OAAO;AAAA,IAC5B;AACA,YAAQ,KAAKA,IAAG;AAGhB,QAAI,OAAO,YAAY;AACtB,kBAAY,KAAK,OAAO;AAAA,IACzB;AAGA,QAAI,OAAO,YAAY;AACtB,YAAM,KAA4B;AAAA,QACjC,SAAS,CAAC,OAAO;AAAA,QACjB,YAAY;AAAA,UACX,OAAO,OAAO,WAAW;AAAA,UACzB,SAAS,CAAC,OAAO,WAAW,UAAU,IAAI;AAAA,QAC3C;AAAA,MACD;AACA,UAAI,OAAO,WAAW,UAAU;AAC/B,WAAG,WAAW,OAAO,WAAW;AAAA,MACjC;AACA,kBAAY,KAAK,EAAE;AAAA,IACpB;AAGA,QAAI,OAAO,OAAO;AACjB,YAAM,YACL,OAAO,OAAO,UAAU,WACrB,OAAO,QACP,OAAO,SAAS,IAAI,OAAO;AAC/B,cAAQ,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,CAAC,OAAO;AAAA,QACjB,QAAQ;AAAA,MACT,CAAC;AACD,qBAAe,IAAI,OAAO;AAAA,IAC3B;AAGA,QAAI,eAAe,OAAO,cAAc,CAAC,OAAO,OAAO;AACtD,cAAQ,KAAK;AAAA,QACZ,MAAM,OAAO,SAAS,IAAI,OAAO;AAAA,QACjC,SAAS,CAAC,OAAO;AAAA,QACjB,QAAQ;AAAA,MACT,CAAC;AACD,qBAAe,IAAI,OAAO;AAAA,IAC3B;AAAA,EACD;AAGA,QAAM,gBAAwC,CAAC;AAC/C,aAAW,MAAM,aAAa;AAE7B,UAAM,WAAW,GAAG,QAAQ,CAAC;AAC7B,UAAM,eAAe,GAAG,WAAW,QAAQ,CAAC;AAC5C,QACC,GAAG,WAAW,UAAU,aACxB,aAAa,UACb,iBAAiB,QAChB;AAED,YAAM,SAAS,SAAS,QAAQ;AAEhC,YAAM,eAAe,SAAS,SAAS,IAAI,IACxC,SAAS,MAAM,GAAG,EAAE,IACpB;AACH,YAAM,aAAa,QAAQ,YAAY,cAAc;AACrD,YAAM,YACL,QAAQ,YAAY,cACnB,eAAe,WAAW,aAAa,GAAG,UAAU;AAEtD,oBAAc;AAAA,QACb;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAGA,MAAI;AACJ,MAAI,YAAY,SAAS,GAAG;AAC3B,iBACC,YAAY,WAAW,IAAK,YAAY,CAAC,IAAe;AAAA,EAC1D,OAAO;AAEN,UAAM,YAAY,YAAY,QAAQ,CAAC,OAAO,GAAG,OAAO;AACxD,QAAI,UAAU,SAAS,GAAG;AACzB,mBAAa,UAAU,WAAW,IAAI,UAAU,CAAC,IAAI;AAAA,IACtD,OAAO;AACN,YAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AACjD,mBAAa,QAAQ,OAAO;AAAA,IAC7B;AAAA,EACD;AAGA,QAAM,gBAAgB,OAAO,OAAO,OAAO;AAG3C,SAAO,OAAO,OAAO;AAAA,IACpB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,GAAI,eAAe,SAAY,EAAE,WAAW,IAAI,CAAC;AAAA,IACjD,aAAa,OAAO,OAAO,WAAW;AAAA,IACtC,SAAS,OAAO,OAAO,OAAO;AAAA,IAC9B,GAAI,cAAc,SAAS,KAAK;AAAA,MAC/B,eAAe,OAAO,OAAO,aAAa;AAAA,IAC3C;AAAA,EACD,CAAC;AACF;AAKA,SAAS,gBACR,eACA,aACA,OACa;AAEb,QAAM,WAAW,cAAc,QAAQ,GAAG;AAC1C,QAAM,cACL,WAAW,IAAI,cAAc,MAAM,GAAG,QAAQ,IAAI;AACnD,QAAM,eACL,WAAW,IAAI,cAAc,MAAM,WAAW,CAAC,IAAI;AAGpD,QAAM,OAAO,MAAM,aAAa;AAEhC,QAAM,iBACL,YAAY,SAAS,YACjB,YAAiC,cAClC;AACJ,QAAM,cACL,MAAM,gBAAgB,QACnB,QACA,mBAAmB,QAClB,QACA,YAAY,SAAS,cACpB,QACA;AAGN,QAAM,cACL,YAAY,SAAS,cAAc,aAAa;AAGjD,MAAI,eAAeD,iBAAgB,YAAY,IAAI;AACnD,MAAI,YAAY,SAAS,aAAa,gBAAgB,OAAO;AAC5D,mBAAe;AAAA,EAChB;AAGA,QAAM,eAAe;AAAA,IACpB,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ,YAAY;AAAA,IACpB,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,iBAAkB,YAAY,mBAAmB;AAAA,IACjD,gBAAiB,MAAM,mBAAmB;AAAA,IAC1C,aAAa;AAAA,EACd;AAKA,UAAQ,YAAY,MAAM;AAAA,IACzB,KAAK;AACJ,aAAO;AAAA,QACN,GAAG;AAAA,QACH,YAAY,YAAY;AAAA,QACxB,GAAI,YAAY,YAAY,EAAE,WAAW,YAAY,UAAU,IAAI,CAAC;AAAA,MACrE;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN,GAAG;AAAA,QACH,YAAY,YAAY;AAAA,QACxB,GAAI,YAAY,YAAY,EAAE,WAAW,YAAY,UAAU,IAAI,CAAC;AAAA,MACrE;AAAA,IACD,KAAK;AACJ,aAAO;AAAA,QACN,GAAG;AAAA,QACH,SAAS,YAAY;AAAA,QACrB,YAAY,YAAY;AAAA,QACxB,UAAU,YAAY;AAAA,MACvB;AAAA,EACF;AACD;AAkBO,SAAS,qBAAqBE,SAAkC;AACtE,QAAM,SAAS,oBAAI,IAAqB;AACxC,QAAM,YAAY,oBAAI,IAAwB;AAC9C,QAAM,cAAcA,QAAO,YAAY;AAGvC,aAAW,CAAC,WAAW,QAAQ,KAAK,OAAO,QAAQA,QAAO,MAAM,GAAG;AAClE,WAAO;AAAA,MACN;AAAA,MACA,2BAA2B,WAAW,UAAU,WAAW;AAAA,IAC5D;AAAA,EACD;AAGA,aAAW,CAAC,eAAe,WAAW,KAAK,OAAO,QAAQA,QAAO,SAAS,GAAG;AAC5E,cAAU;AAAA,MACT;AAAA,MACA,gBAAgB,eAAe,aAAaA,QAAO,KAAK;AAAA,IACzD;AAAA,EACD;AAEA,SAAO,IAAI,YAAY,QAAQ,SAAS;AACzC;AAgBO,SAAS,6BAA6BA,SAAiC;AAC7E,QAAM,kBAAkB,sCAAsCA,OAAM;AACpE,SAAO,qBAAqB,eAAe;AAC5C;AASO,SAAS,kBAAkB,OAA0C;AAC3E,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAChD,WAAO;AAAA,EACR;AACA,QAAM,MAAM;AACZ,SACC,OAAO,IAAI,WAAW,YACtB,IAAI,WAAW,QACf,OAAO,IAAI,cAAc,YACzB,IAAI,cAAc,QAClB,OAAO,IAAI,UAAU,YACrB,IAAI,UAAU,QACd,OAAO,IAAI,gBAAgB,YAC3B,IAAI,gBAAgB;AAEtB;AAMA,IAAM,6BAA6B,oBAAI,IAAI,CAAC,QAAQ,OAAO,CAAC;AAM5D,IAAM,8BAA8B,oBAAI,IAAI,CAAC,UAAU,UAAU,CAAC;AAKlE,SAAS,2BACR,QACU;AACV,aAAW,SAAS,OAAO,OAAO,MAAM,GAAG;AAC1C,eAAW,UAAU,OAAO,OAAO,KAAK,GAAG;AAC1C,UAAI,QAAQ,QAAQ,2BAA2B,IAAI,OAAO,IAAI,GAAG;AAChE,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;AAKA,SAAS,4BACR,QACU;AACV,aAAW,SAAS,OAAO,OAAO,MAAM,GAAG;AAC1C,eAAW,UAAU,OAAO,OAAO,KAAK,GAAG;AAC1C,UAAI,QAAQ,QAAQ,4BAA4B,IAAI,OAAO,IAAI,GAAG;AACjE,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AACA,SAAO;AACR;AAYO,SAAS,iBAAiB,OAAyB;AACzD,MAAI,CAAC,kBAAkB,KAAK,GAAG;AAC9B,WAAO;AAAA,EACR;AAEA,MACC;AAAA,IACC,MAAM;AAAA,EACP,GACC;AACD,WAAO;AAAA,EACR;AAEA,MACC;AAAA,IACC,MAAM;AAAA,EACP,GACC;AACD,WAAO;AAAA,EACR;AAEA,SAAO;AACR;AA2BO,SAAS,gBAAgB,OAAiC;AAEhE,MAAI,CAAC,kBAAkB,KAAK,GAAG;AAC9B,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAGA,MAAI,iBAAiB,KAAK,GAAG;AAE5B,UAAM,SAAS,gCAAgC,KAAK;AACpD,QAAI,CAAC,OAAO,SAAS;AACpB,YAAM,WAAW,OAAO,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI;AAC9D,YAAM,IAAI,MAAM,6BAA6B,QAAQ,EAAE;AAAA,IACxD;AACA,WAAO,OAAO;AAAA,EACf;AAGA,SAAO;AACR;AASA,IAAM,yBAA2B,WAAS;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAC;AAeD,IAAM,uBAAuB,CAAC,aAAa,eAAe,WAAW;AAarE,SAAS,WAA2C,aAAqB;AACxE,SAAS;AAAA,IACN,UAAQ;AAAA,IACR,QAAM,CAAC,UAAU;AAClB,UAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,aAAO,CAAC,OAAO,KAAK,KAAK,EAAE;AAAA,QAAK,CAAC,MAC/B,qBAA2C,SAAS,CAAC;AAAA,MACvD;AAAA,IACD,GAAG,4FAA4F;AAAA,IAC7F,SAAS,SAAO,GAAG,WAAW;AAAA,EACjC;AACD;AAEA,IAAM,4BAA8B,SAAO;AAAA,EAC1C,OAAS,SAAO;AAAA,EAChB,QAAU,WAAW,SAAO,CAAC;AAAA,EAC7B,UAAY;AAAA,IACT,WAAS,CAAC,WAAW,YAAY,YAAY,WAAW,CAAC;AAAA,EAC5D;AAAA,EACA,OAAS,WAAW,UAAQ,CAAC;AAAA,EAC7B,YAAc,WAAW,SAAO,CAAC;AAAA,EACjC,WAAa,WAAW,SAAO,CAAC;AACjC,CAAC;AAKD,IAAM,yBAA2B,SAAO;AAAA,EACvC,MAAM;AAAA,EACN,YAAc,WAAW,UAAQ,CAAC;AAAA,EAClC,UAAY,WAAW,UAAQ,CAAC;AAAA,EAChC,QAAU,WAAW,UAAQ,CAAC;AAAA,EAC9B,eAAiB,WAAW,UAAQ,CAAC;AAAA,EACrC,SAAW,WAAW,QAAM,CAAG,SAAO,GAAK,SAAO,GAAK,UAAQ,CAAC,CAAC,CAAC;AAAA,EAClE,YAAc,WAAS,yBAAyB;AAAA,EAChD,OAAS,WAAW,QAAM,CAAG,UAAQ,GAAK,SAAO,CAAC,CAAC,CAAC;AACrD,CAAC;AAKD,IAAM,4BAA4B,WAAW,sBAAsB;AAMnE,IAAM,2BAA6B,SAAO;AAAA,EACzC,SAAS;AAAA,EACT,YAAc,QAAQ,SAAO,CAAC;AAAA,EAC9B,SAAW;AAAA,IACR;AAAA,MACC,SAAO;AAAA,QACR,SAAW,QAAQ,SAAO,CAAC;AAAA,QAC3B,QAAU,WAAW,UAAQ,CAAC;AAAA,QAC9B,MAAQ,WAAW,SAAO,CAAC;AAAA,MAC5B,CAAC;AAAA,IACF;AAAA,EACD;AACD,CAAC;AAKD,IAAM,wBAA0B,QAAM;AAAA,EACrC;AAAA,EACA;AACD,CAAC;AAKD,IAAM,yBAAyB,WAAW,qBAAqB;AAQ/D,IAAM,wBAA0B;AAAA,EAC7B,WAAS,CAAC,QAAQ,YAAY,OAAO,WAAW,YAAY,MAAM,CAAC;AACtE;AAEA,IAAM,0BAA4B,SAAO;AAAA,EACxC,MAAQ,UAAQ,WAAW;AAAA,EAC3B,QAAU,SAAO;AAAA,EACjB,YAAc,SAAO;AAAA,EACrB,WAAa,WAAW,SAAO,CAAC;AAAA,EAChC,iBAAiB;AAClB,CAAC;AAKD,IAAM,wBAA0B,SAAO;AAAA,EACtC,MAAQ,UAAQ,SAAS;AAAA,EACzB,QAAU,SAAO;AAAA,EACjB,YAAc,SAAO;AAAA,EACrB,WAAa,WAAW,SAAO,CAAC;AAAA,EAChC,iBAAiB;AAClB,CAAC;AAKD,IAAM,2BAA6B,SAAO;AAAA,EACzC,MAAQ,UAAQ,YAAY;AAAA,EAC5B,QAAU,SAAO;AAAA,EACjB,SAAW,SAAO;AAAA,EAClB,UAAY,SAAO;AAAA,EACnB,UAAY,SAAO;AAAA,EACnB,iBAAiB;AAClB,CAAC;AAKD,IAAM,2BAA6B,UAAQ,QAAQ;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AACD,CAAC;AAKD,IAAM,4BAA4B,WAAW,wBAAwB;AAKrE,IAAM,uBAAyB,SAAO;AAAA,EACrC,iBAAmB,WAAW,WAAS,CAAC,UAAU,MAAM,CAAC,CAAC;AAAA,EAC1D,aAAe,WAAW,WAAS,CAAC,OAAO,MAAM,CAAC,CAAC;AACpD,CAAC;AAKD,IAAM,wBAAwB,WAAW,oBAAoB;AAK7D,IAAM,8BAAgC,SAAO;AAAA,EAC5C,WAAa,SAAO;AAAA,EACpB,WAAa,UAAQ;AAAA,EACrB,YAAc,QAAQ,SAAO,CAAC;AAAA,EAC9B,aAAe,UAAQ;AACxB,CAAC;AAKD,IAAM,wBAA0B,SAAO;AAAA,EACtC,SAAW,QAAQ,SAAO,CAAC;AAAA,EAC3B,QAAU,WAAW,UAAQ,CAAC;AAAA,EAC9B,MAAQ,WAAW,SAAO,CAAC;AAC5B,CAAC;AAKD,IAAM,0BAA0B,WAAa,QAAM,qBAAqB,CAAC;AAKlE,IAAM,2BAA6B,SAAO;AAAA,EAChD,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,EACP,aAAa;AAAA,EACb,SAAW,WAAS,uBAAuB;AAC5C,CAAC;AAiBD,SAAS,oBACR,YACsB;AACtB,UAAQ,YAAY;AAAA,IACnB,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,EACT;AACD;AAKA,SAAS,cACRD,MACkB;AAClB,QAAM,SAAmC;AAAA,IACxC,MAAM,oBAAoBA,KAAI,IAAI;AAAA,EACnC;AACA,MAAIA,KAAI,eAAe,QAAW;AACjC,WAAO,aAAaA,KAAI;AAAA,EACzB;AACA,MAAIA,KAAI,aAAa,QAAW;AAC/B,WAAO,WAAWA,KAAI;AAAA,EACvB;AACA,MAAIA,KAAI,WAAW,QAAW;AAC7B,WAAO,SAASA,KAAI;AAAA,EACrB;AACA,MAAIA,KAAI,kBAAkB,QAAW;AACpC,WAAO,gBAAgBA,KAAI;AAAA,EAC5B;AACA,MAAIA,KAAI,YAAY,QAAW;AAC9B,WAAO,UAAUA,KAAI;AAAA,EACtB;AACA,MAAIA,KAAI,YAAY;AACnB,WAAO,aAAa;AAAA,MACnB,OAAOA,KAAI,WAAW;AAAA,MACtB,GAAIA,KAAI,WAAW,WAAW,SAC3B,EAAE,QAAQA,KAAI,WAAW,OAAO,IAChC,CAAC;AAAA,MACJ,GAAIA,KAAI,WAAW,WAAW,EAAE,UAAUA,KAAI,WAAW,SAAS,IAAI,CAAC;AAAA,MACvE,GAAIA,KAAI,WAAW,UAAU,SAC1B,EAAE,OAAOA,KAAI,WAAW,MAAM,IAC9B,CAAC;AAAA,MACJ,GAAIA,KAAI,WAAW,aAChB,EAAE,YAAYA,KAAI,WAAW,WAAW,IACxC,CAAC;AAAA,MACJ,GAAIA,KAAI,WAAW,YAChB,EAAE,WAAWA,KAAI,WAAW,UAAU,IACtC,CAAC;AAAA,IACL;AAAA,EACD;AACA,SAAO;AACR;AAKA,SAAS,gBACR,KACoB;AACpB,UAAQ,IAAI,MAAM;AAAA,IACjB,KAAK,aAAa;AACjB,YAAM,SAAsC;AAAA,QAC3C,MAAM;AAAA,QACN,QAAQ,IAAI;AAAA,QACZ,YAAY,IAAI;AAAA,MACjB;AACA,UAAI,IAAI,cAAc,QAAW;AAChC,eAAO,YAAY,IAAI;AAAA,MACxB;AACA,UAAI,IAAI,oBAAoB,QAAW;AACtC,eAAO,kBAAkB,IAAI;AAAA,MAC9B;AACA,aAAO;AAAA,IACR;AAAA,IACA,KAAK,WAAW;AACf,YAAM,SAAoC;AAAA,QACzC,MAAM;AAAA,QACN,QAAQ,IAAI;AAAA,QACZ,YAAY,IAAI;AAAA,MACjB;AACA,UAAI,IAAI,cAAc,QAAW;AAChC,eAAO,YAAY,IAAI;AAAA,MACxB;AACA,UAAI,IAAI,oBAAoB,QAAW;AACtC,eAAO,kBAAkB,IAAI;AAAA,MAC9B;AACA,aAAO;AAAA,IACR;AAAA,IACA,KAAK,cAAc;AAClB,YAAM,SAAuC;AAAA,QAC5C,MAAM;AAAA,QACN,QAAQ,IAAI;AAAA,QACZ,SAAS,IAAI;AAAA,QACb,UAAU,IAAI;AAAA,QACd,UAAU,IAAI;AAAA,MACf;AACA,UAAI,IAAI,oBAAoB,QAAW;AACtC,eAAO,kBAAkB,IAAI;AAAA,MAC9B;AACA,aAAO;AAAA,IACR;AAAA,EACD;AACD;AAKA,SAAS,YACR,MACgB;AAChB,QAAM,SAAiC,CAAC;AACxC,MAAI,KAAK,oBAAoB,QAAW;AACvC,WAAO,kBAAkB,KAAK;AAAA,EAC/B;AACA,MAAI,KAAK,gBAAgB,QAAW;AACnC,WAAO,cAAc,KAAK;AAAA,EAC3B;AACA,SAAO;AACR;AAiCO,SAAS,gCACf,OACyB;AAEzB,QAAM,cAAgB,YAAU,0BAA0B,KAAK;AAE/D,MAAI,CAAC,YAAY,SAAS;AACzB,WAAO;AAAA,MACN,SAAS;AAAA,MACT,QAAQ,YAAY;AAAA,IACrB;AAAA,EACD;AAEA,QAAM,YAAY,YAAY;AAK9B,QAAM,SAAS,uBAAO,OAAO,IAAI;AACjC,aAAW,CAAC,WAAW,QAAQ,KAAK,OAAO,QAAQ,UAAU,MAAM,GAAG;AACrE,UAAM,iBAAiB,uBAAO,OAAO,IAAI;AAUzC,UAAM,WAAW;AACjB,UAAM,eAAe,MAAM,QAAQ,SAAS,UAAU;AAEtD,UAAM,UAAU,eACZ,SAAS,UACV;AAEH,eAAW,CAAC,SAAS,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACxD,qBAAe,OAAO,IAAI;AAAA,QACzB;AAAA,MACD;AAAA,IACD;AACA,WAAO,SAAS,IAAI;AAAA,EACrB;AAGA,QAAM,YAAY,uBAAO,OAAO,IAAI;AACpC,aAAW,CAAC,SAAS,MAAM,KAAK,OAAO,QAAQ,UAAU,SAAS,GAAG;AACpE,cAAU,OAAO,IAAI,gBAAgB,MAAM;AAAA,EAC5C;AAGA,QAAM,QAAQ,uBAAO,OAAO,IAAI;AAChC,aAAW,CAAC,UAAU,OAAO,KAAK,OAAO,QAAQ,UAAU,KAAK,GAAG;AAClE,UAAM,QAAQ,IAAI,YAAY,OAAO;AAAA,EACtC;AAGA,QAAM,cAAoC;AAAA,IACzC,WAAW,UAAU,YAAY;AAAA,IACjC,WAAW,UAAU,YAAY;AAAA,IACjC,YAAY,UAAU,YAAY;AAAA,IAClC,aAAa,UAAU,YAAY;AAAA,EACpC;AAEA,SAAO;AAAA,IACN,SAAS;AAAA,IACT,QAAQ;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACD;AAYO,SAAS,sCACf,OACkB;AAClB,QAAM,SAAS,gCAAgC,KAAK;AACpD,MAAI,CAAC,OAAO,SAAS;AACpB,UAAM,WAAW,OAAO,OACtB,IAAI,CAAC,MAAM;AACX,YAAM,OAAO,EAAE,MAAM,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,GAAG,KAAK;AACpD,aAAO,IAAI,IAAI,KAAK,EAAE,OAAO,eAAe,EAAE,QAAQ,eAAe,EAAE,QAAQ;AAAA,IAChF,CAAC,EACA,KAAK,IAAI;AACX,UAAM,IAAI,MAAM;AAAA,EAA8B,QAAQ,EAAE;AAAA,EACzD;AACA,SAAO,OAAO;AACf;;;AC/tCO,IAAM,0BAA+C;AAAA,EAC3D,MAAM;AAAA;AAAA,EAGN,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,mBAAmB;AAAA,EACnB,oBAAoB;AAAA;AAAA,EACpB,kBAAkB;AAAA,EAClB,uBAAuB;AAAA;AAAA,EACvB,iBAAiB;AAAA;AAAA,EAGjB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA;AAAA,EAGjB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,uBAAuB;AAAA,EACvB,yBAAyB;AAAA,EACzB,6BAA6B;AAAA,EAC7B,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,4BAA4B;AAAA,EAC5B,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,yBAAyB;AAAA,EACzB,yBAAyB;AAAA,EACzB,yBAAyB;AAAA,EACzB,2BAA2B;AAAA,EAC3B,8BAA8B;AAAA,EAC9B,6BAA6B;AAAA;AAAA,EAG7B,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,cAAc;AACf;AAKO,IAAM,qBAA0C;AAAA,EACtD,MAAM;AAAA;AAAA,EAGN,mBAAmB;AAAA;AAAA,EACnB,sBAAsB;AAAA;AAAA,EACtB,yBAAyB;AAAA;AAAA,EACzB,mBAAmB;AAAA,EACnB,oBAAoB;AAAA;AAAA,EACpB,kBAAkB;AAAA,EAClB,uBAAuB;AAAA;AAAA,EACvB,iBAAiB;AAAA;AAAA;AAAA,EAGjB,qBAAqB;AAAA;AAAA,EACrB,iBAAiB;AAAA;AAAA;AAAA,EAGjB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,cAAc;AACf;AAKO,IAAM,sBAA2C;AAAA,EACvD,MAAM;AAAA;AAAA,EAGN,mBAAmB;AAAA;AAAA,EACnB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA;AAAA,EACzB,mBAAmB;AAAA,EACnB,oBAAoB;AAAA;AAAA,EACpB,kBAAkB;AAAA;AAAA,EAClB,uBAAuB;AAAA;AAAA,EACvB,iBAAiB;AAAA;AAAA;AAAA,EAGjB,qBAAqB;AAAA;AAAA,EACrB,iBAAiB;AAAA;AAAA;AAAA,EAGjB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,cAAc;AACf;AAMO,IAAM,sBAA2C;AAAA,EACvD,MAAM;AAAA;AAAA,EAGN,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,mBAAmB;AAAA;AAAA,EACnB,oBAAoB;AAAA;AAAA,EACpB,kBAAkB;AAAA,EAClB,uBAAuB;AAAA;AAAA,EACvB,iBAAiB;AAAA;AAAA,EAGjB,qBAAqB;AAAA;AAAA,EACrB,iBAAiB;AAAA;AAAA;AAAA,EAGjB,oBAAoB;AAAA;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,cAAc;AACf;AAKO,IAAM,qBAA0C;AAAA,EACtD,MAAM;AAAA;AAAA,EAGN,mBAAmB;AAAA;AAAA,EACnB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,mBAAmB;AAAA,EACnB,oBAAoB;AAAA;AAAA,EACpB,kBAAkB;AAAA;AAAA,EAClB,uBAAuB;AAAA;AAAA,EACvB,iBAAiB;AAAA;AAAA,EAGjB,qBAAqB;AAAA;AAAA,EACrB,iBAAiB;AAAA;AAAA;AAAA,EAGjB,oBAAoB;AAAA,EACpB,mBAAmB;AAAA;AAAA,EACnB,iBAAiB;AAAA,EACjB,gBAAgB;AAAA;AAAA,EAChB,YAAY;AAAA;AAAA,EACZ,cAAc;AACf;AAOA,SAAS,gBAAgB,GAAW,GAAmB;AACtD,QAAM,SAAS,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AACtC,QAAM,SAAS,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AACtC,QAAM,MAAM,KAAK,IAAI,OAAO,QAAQ,OAAO,MAAM;AACjD,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC7B,UAAM,OAAO,OAAO,CAAC,KAAK;AAC1B,UAAM,OAAO,OAAO,CAAC,KAAK;AAC1B,QAAI,OAAO,KAAM,QAAO;AACxB,QAAI,OAAO,KAAM,QAAO;AAAA,EACzB;AACA,SAAO;AACR;AAGA,IAAM,kBAA8C;AAAA,EACnD,MAAM;AAAA,EACN,UAAU;AAAA,EACV,WAAW;AAAA,EACX,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS;AAAA,EACT,aAAa;AAAA,EACb,cAAc;AAAA,EACd,cAAc;AAAA,EACd,cAAc;AAAA,EACd,iBAAiB;AAClB;AAYO,SAAS,0BACf,WAWA,SAMsB;AACtB,QAAM,SAAkC;AAAA;AAAA,IAEvC,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,IACtB,yBAAyB;AAAA,IACzB,mBAAmB;AAAA,IACnB,oBAAoB;AAAA,IACpB,kBAAkB;AAAA,IAClB,uBAAuB;AAAA,IACvB,iBAAiB;AAAA,IACjB,qBAAqB;AAAA,IACrB,iBAAiB;AAAA;AAAA,IAEjB,GAAG;AAAA,EACJ;AAEA,MAAI,SAAS,WAAW,SAAS,qBAAqB;AACrD,UAAM,MAAM,QAAQ;AACpB,UAAM,OAAO,QAAQ;AACrB,eAAW,CAAC,SAAS,KAAK,KAAK,OAAO,QAAQ,IAAI,GAG7C;AACJ,YAAM,WAAW,gBAAgB,OAAO;AACxC,UAAI,CAAC,SAAU;AACf,YAAM,WAAW,CAAC,MAAM,OAAO,gBAAgB,KAAK,MAAM,GAAG,KAAK;AAClE,YAAM,WAAW,CAAC,MAAM,OAAO,gBAAgB,KAAK,MAAM,GAAG,KAAK;AAClE,UAAI,CAAC,YAAY,CAAC,UAAU;AAC3B,eAAO,OAAO,QAAQ;AAAA,MACvB;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAMA,IAAM,kBAAoD,oBAAI,IAAI;AAAA,EACjE,CAAC,cAAc,uBAAuB;AAAA,EACtC,CAAC,YAAY,uBAAuB;AAAA;AAAA,EACpC,CAAC,MAAM,uBAAuB;AAAA;AAAA,EAC9B,CAAC,SAAS,kBAAkB;AAAA,EAC5B,CAAC,UAAU,mBAAmB;AAAA,EAC9B,CAAC,UAAU,mBAAmB;AAAA,EAC9B,CAAC,SAAS,kBAAkB;AAAA,EAC5B,CAAC,aAAa,kBAAkB;AAAA;AACjC,CAAC;AAKM,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC9C,YACiB,aACA,mBACf;AACD,UAAM,YAAY,kBAAkB,KAAK,IAAI;AAC7C,UAAM,oBAAoB,WAAW,0BAA0B,SAAS,EAAE;AAJ1D;AACA;AAIhB,SAAK,OAAO;AAAA,EACb;AAAA,EANiB;AAAA,EACA;AAMlB;AAiBO,SAAS,uBACf,aACsB;AACtB,QAAM,aAAa,YAAY,YAAY;AAC3C,QAAM,eAAe,gBAAgB,IAAI,UAAU;AAEnD,MAAI,CAAC,cAAc;AAClB,UAAM,YAAY,MAAM,KAAK,gBAAgB,KAAK,CAAC,EAAE;AAAA,MACpD,CAAC,QAAQ,gBAAgB,IAAI,GAAG,GAAG,SAAS;AAAA;AAAA,IAC7C;AACA,UAAM,IAAI,oBAAoB,aAAa,SAAS;AAAA,EACrD;AAEA,SAAO;AACR;AAQO,SAAS,eAAe,aAA8B;AAC5D,SAAO,gBAAgB,IAAI,YAAY,YAAY,CAAC;AACrD;AAOO,SAAS,uBAAiC;AAChD,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,SAAmB,CAAC;AAE1B,aAAW,CAAC,MAAM,IAAI,KAAK,iBAAiB;AAC3C,QAAI,CAAC,KAAK,IAAI,KAAK,IAAI,GAAG;AACzB,WAAK,IAAI,KAAK,IAAI;AAClB,aAAO,KAAK,KAAK,IAAI;AAAA,IACtB;AAAA,EACD;AAEA,SAAO;AACR;AAqBO,SAAS,gBACf,aACA,cACO;AACP,kBAAgB,IAAI,YAAY,YAAY,GAAG,YAAY;AAC5D;AAkBO,SAAS,cACf,MACA,WACsB;AACtB,SAAO,EAAE,GAAG,MAAM,GAAG,UAAU;AAChC;AAeO,IAAM,yBAAN,cAAqC,MAAM;AAAA,EACjD,YAEiB,YAEA,aAEA,MACf;AACD,UAAM,aAAa,OAAO,UAAU,IAAI,KAAK;AAC7C;AAAA,MACC,SAAS,UAAU,kCAAkC,WAAW,KAAK,UAAU;AAAA,IAChF;AATgB;AAEA;AAEA;AAMhB,SAAK,OAAO;AAAA,EACb;AAAA,EAXiB;AAAA,EAEA;AAAA,EAEA;AAQlB;AAiBO,SAAS,oBACf,MACA,aACA,cACO;AAEP,QAAM,aAA2B;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAEA,MAAI,WAAW,SAAS,IAAI,KAAK,CAAC,aAAa,oBAAoB;AAClE,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AAGA,MAAI,SAAS,WAAW,gBAAgB,cAAc;AACrD,UAAM,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACD;;;ACvfO,SAAS,aAAaE,MAAqB;AACjD,SAAOA,KACL,YAAY,EACZ,QAAQ,QAAQ,GAAG,EACnB,QAAQ,YAAY,IAAI,EACxB,QAAQ,UAAU,GAAG,EACrB,QAAQ,UAAU,GAAG,EACrB,QAAQ,SAAS,EAAE,EACnB,KAAK;AACR;;;ACIA,SAAS,YAAY,KAAqB;AACzC,SAAO,IAAI,QAAQ,UAAU,CAAC,WAAW,IAAI,OAAO,YAAY,CAAC,EAAE;AACpE;AASO,SAAS,eACf,OACA,QACA,UACA,cACmB;AACnB,QAAM,SAAS,OAAO,SAAS,QAAQ;AACvC,SAAO;AAAA,IACN,MAAM,gBAAiB,GAAG,KAAK;AAAA,IAC/B;AAAA,IACA,QAAQ,SAAS,SAAY;AAAA;AAAA,IAC7B;AAAA,IACA,SAAS,SAAS,SAAY,YAAY,KAAK,gBAAgB,QAAQ;AAAA,EACxE;AACD;AAKO,SAAS,aACf,OACA,QACA,UACmB;AACnB,QAAM,SAAS,OAAO,KAAK,MAAM,SAAS,KAAK;AAC/C,SAAO;AAAA,IACN,MAAM,GAAG,KAAK;AAAA,IACd;AAAA,IACA,QAAQ,SAAS,SAAY;AAAA;AAAA,IAC7B;AAAA,IACA,SAAS,SAAS,SAAY,YAAY,KAAK,cAAc,QAAQ;AAAA,EACtE;AACD;AAKO,SAAS,cACf,OACA,QACA,SACmB;AACnB,QAAM,QAAQ,IAAI,OAAO,OAAO;AAChC,QAAM,SAAS,MAAM,KAAK,MAAM;AAChC,SAAO;AAAA,IACN,MAAM,GAAG,KAAK;AAAA,IACd,UAAU;AAAA,IACV,QAAQ,SAAS,SAAY;AAAA;AAAA,IAC7B;AAAA,IACA,SAAS,SAAS,SAAY,YAAY,KAAK,cAAc,OAAO;AAAA,EACrE;AACD;AAKO,SAAS,cACf,QACA,UACmB;AACnB,QAAM,SAAS,WAAW;AAC1B,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,SAAS,SAAY;AAAA,IAC7B;AAAA,IACA,SAAS,SACN,SACA,qBAAqB,WAAW,YAAY,MAAM,YAAY,SAAS,cAAc,QAAQ;AAAA,EACjG;AACD;AASO,SAAS,gBACf,QACA,UACmB;AACnB,QAAM,mBAAmB,aAAa,MAAM;AAC5C,QAAM,qBAAqB,aAAa,QAAQ;AAChD,QAAM,SAAS,qBAAqB;AAEpC,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,SAAS,SAAY;AAAA,IAC7B;AAAA,IACA,SAAS,SACN,SACA;AAAA,cAA8B,QAAQ;AAAA,cAAiB,MAAM;AAAA,EACjE;AACD;AAMA,SAAS,6BACR,eACA,OACC;AACD,SAAO,CAACC,MAAa,SAAmC;AACvD,UAAM,gBAAgBA,KAAI,YAAY;AACtC,UAAM,eAAe,KAAK,YAAY;AACtC,UAAM,gBAAgB,YAAY,IAAI,EAAE,YAAY;AAEpD,UAAM,QACL,cAAc,SAAS,YAAY,KACnC,cAAc,SAAS,aAAa,KACpC,cAAc,SAAS,IAAI,YAAY,GAAG,KAC1C,cAAc,SAAS,IAAI,aAAa,GAAG;AAE5C,WAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ,QAAQ,SAAYA;AAAA,MAC5B,QAAQ;AAAA,MACR,SAAS,QACN,SACA,6BAA6B,KAAK,KAAK,IAAI,IAAI,kBAAkB,eAAe,SAAS,aAAa,OAAO,EAAE;AAAA,IACnH;AAAA,EACD;AACD;AAEO,IAAM,iBAAiB;AAAA,EAC7B;AAAA,EACA;AACD;AACO,IAAM,kBAAkB;AAAA,EAC9B;AAAA,EACA;AACD;AAOO,SAAS,cACfA,MACA,WACmB;AACnB,QAAM,gBAAgBA,KAAI,YAAY;AACtC,QAAM,iBAAiB,UAAU,YAAY;AAC7C,QAAM,aAAa,YAAY,SAAS,EAAE,YAAY;AAGtD,QAAM,cAAc;AACpB,QAAM,UAAU,YAAY,KAAK,aAAa;AAG9C,QAAM,aAAa,IAAI;AAAA,IACtB,sBAAsB,cAAc,IAAI,UAAU;AAAA,EACnD;AACA,QAAM,SAAS,WAAW,KAAK,aAAa;AAI5C,QAAM,gBAAgB;AAAA,IACrB,IAAI,cAAc;AAAA;AAAA,IAClB,IAAI,UAAU;AAAA;AAAA,IACd,IAAI,cAAc;AAAA;AAAA,IAClB,IAAI,UAAU;AAAA;AAAA,IACd,IAAI,cAAc;AAAA;AAAA,IAClB,IAAI,UAAU;AAAA;AAAA,EACf;AACA,QAAM,WAAW,cAAc,KAAK,CAAC,MAAM,cAAc,SAAS,CAAC,CAAC;AAGpE,QAAM,QAAS,WAAW,YAAa;AAEvC,SAAO;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ,QAAQ,SAAYA;AAAA,IAC5B,QAAQ;AAAA,IACR,SAAS,QACN,SACA,8BAA8B,SAAS;AAAA,EAC3C;AACD;AASO,SAAS,mBACf,QACA,UACmB;AACnB,QAAM,YAAY,KAAK,UAAU,MAAM;AACvC,QAAM,cAAc,KAAK,UAAU,QAAQ;AAC3C,QAAM,SAAS,cAAc;AAE7B,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,SAAS,SAAY,CAAC,GAAG,MAAM;AAAA,IACvC;AAAA,IACA,SAAS,SACN,SACA;AAAA,cAAiC,WAAW;AAAA,cAAiB,SAAS;AAAA,EAC1E;AACD;AAKO,SAAS,mBACf,QACA,UACmB;AACnB,QAAM,SAAS,OAAO,WAAW;AACjC,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,SAAS,SAAY,OAAO;AAAA,IACpC;AAAA,IACA,SAAS,SACN,SACA,YAAY,QAAQ,gBAAgB,OAAO,MAAM;AAAA,EACrD;AACD;AAKO,SAAS,iBACf,QACA,eACmB;AACnB,MAAI,OAAO,WAAW,cAAc,QAAQ;AAC3C,WAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ,OAAO,IAAI,CAAC,MAAM,OAAO,CAAC;AAAA,MAClC,QAAQ;AAAA,MACR,SAAS,YAAY,cAAc,MAAM,gBAAgB,OAAO,MAAM;AAAA,IACvE;AAAA,EACD;AAEA,QAAM,cAAwB,CAAC;AAC/B,QAAM,aAAuB,CAAC;AAE9B,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,UAAMC,SAAQ,OAAO,CAAC;AACtB,UAAM,eAAe,cAAc,CAAC;AACpC,QAAI;AAEJ,QAAIA,WAAU,MAAM;AACnB,mBAAa;AAAA,IACd,WAAW,MAAM,QAAQA,MAAK,GAAG;AAChC,mBAAa;AAAA,IACd,WAAW,OAAOA,WAAU,UAAU;AACrC,mBAAa;AAAA,IACd,OAAO;AACN,mBAAa,OAAOA;AAAA,IACrB;AAEA,gBAAY,KAAK,UAAU;AAE3B,QAAI,eAAe,cAAc;AAChC,iBAAW;AAAA,QACV,SAAS,CAAC,cAAc,YAAY,SAAS,UAAU;AAAA,MACxD;AAAA,IACD;AAAA,EACD;AAEA,QAAM,SAAS,WAAW,WAAW;AAErC,SAAO;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ,SAAS,SAAY;AAAA,IAC7B;AAAA,IACA,SAAS,SAAS,SAAY,kBAAkB,WAAW,KAAK,IAAI,CAAC;AAAA,EACtE;AACD;AAcO,SAAS,kBACf,QACA,MACmB;AACnB,QAAM,EAAE,OAAO,MAAM,IACpB,OAAO,SAAS,YAAY,SAAS,OACjC,OACD,EAAE,OAAO,GAAG,OAAO,KAAK;AAE5B,MAAI,SAAS,OAAO,QAAQ;AAC3B,WAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS,qBAAqB,KAAK,UAAU,OAAO,MAAM;AAAA,IAC3D;AAAA,EACD;AAEA,QAAM,SAAS,OAAO,KAAK;AAC3B,QAAM,SAAS,KAAK,UAAU,MAAM,MAAM,KAAK,UAAU,KAAK;AAE9D,SAAO;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ,SAAS,SAAY;AAAA,IAC7B;AAAA,IACA,SAAS,SACN,SACA,kBAAkB,KAAK,cAAc,KAAK,UAAU,KAAK,CAAC,SAAS,KAAK,UAAU,MAAM,CAAC;AAAA,EAC7F;AACD;AAQA,SAAS,wBACR,eACA,SACA,iBACC;AACD,SAAO,CAAC,QAA8B,aAAuC;AAC5E,UAAM,WAAW,OAAO,YAAY;AACpC,UAAM,SAAS,QAAQ,UAAU,QAAQ;AACzC,WAAO;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,QAAQ,SAAS,SAAY;AAAA,MAC7B;AAAA,MACA,SAAS,SAAS,SAAY,gBAAgB,UAAU,QAAQ;AAAA,IACjE;AAAA,EACD;AACD;AAEO,IAAM,qBAAqB;AAAA,EACjC;AAAA,EACA,CAAC,GAAG,MAAM,MAAM;AAAA,EAChB,CAAC,GAAG,MAAM,YAAY,CAAC,cAAc,CAAC;AACvC;AAEO,IAAM,kBAAkB;AAAA,EAC9B;AAAA,EACA,CAAC,GAAG,MAAM,KAAK;AAAA,EACf,CAAC,GAAG,MAAM,qBAAqB,CAAC,cAAc,CAAC;AAChD;AAEO,IAAM,kBAAkB;AAAA,EAC9B;AAAA,EACA,CAAC,GAAG,MAAM,KAAK;AAAA,EACf,CAAC,GAAG,MAAM,oBAAoB,CAAC,cAAc,CAAC;AAC/C;AAKO,SAAS,qBACf,QACA,YACmB;AACnB,QAAM,UAAU,OAAO,WAAW,CAAC;AACnC,QAAM,cAAc,WAAW,YAAY;AAC3C,QAAM,cAAc,YAAY,UAAU,EAAE,YAAY;AAExD,QAAM,QAAQ,QAAQ,KAAK,CAACC,SAAQ;AACnC,UAAM,WAAWA,KAAI,YAAY;AACjC,WAAO,aAAa,eAAe,aAAa;AAAA,EACjD,CAAC;AAED,SAAO;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ,QAAQ,SAAY;AAAA,IAC5B,QAAQ;AAAA,IACR,SAAS,QACN,SACA,WAAW,UAAU,qCAAqC,QAAQ,KAAK,IAAI,CAAC;AAAA,EAChF;AACD;AAeO,SAAS,oBACf,QACA,MACmB;AACnB,QAAM,EAAE,KAAK,QAAQ,MAAM,IAC1B,OAAO,SAAS,YAAY,SAAS,OACjC,OACD,EAAE,KAAK,GAAG,QAAQ,IAAI,OAAO,KAAK;AAEtC,QAAM,OAAO,OAAO,QAAQ,CAAC;AAC7B,MAAI,OAAO,KAAK,QAAQ;AACvB,WAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS,mBAAmB,GAAG,UAAU,KAAK,MAAM;AAAA,IACrD;AAAA,EACD;AAEA,QAAM,UAAU,KAAK,GAAG;AACxB,MAAI,CAAC,SAAS;AACb,WAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS,OAAO,GAAG;AAAA,IACpB;AAAA,EACD;AAGA,QAAM,SAAS,QAAQ,MAAM,KAAK,QAAQ,YAAY,MAAM,CAAC;AAC7D,QAAM,SAAS,KAAK,UAAU,MAAM,MAAM,KAAK,UAAU,KAAK;AAE9D,SAAO;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ,SAAS,SAAY;AAAA,IAC7B;AAAA,IACA,SAAS,SACN,SACA,aAAa,GAAG,MAAM,MAAM,gBAAgB,KAAK,UAAU,KAAK,CAAC,SAAS,KAAK,UAAU,MAAM,CAAC;AAAA,EACpG;AACD;AASO,SAAS,eACf,QACA,WACmB;AACnB,QAAM,EAAE,SAAS,MAAM,aAAa,IAAI;AACxC,QAAM,aAAc,OAAO,QAAQ,CAAC;AAGpC,QAAM,YAAY,CAAC,QAAyB;AAC3C,QAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO;AAC9C,QAAI,eAAe,KAAM,QAAO,IAAI,YAAY;AAChD,QAAI,OAAO,QAAQ,SAAU,QAAO,KAAK,UAAU,GAAG;AACtD,WAAO,OAAO,GAAG;AAAA,EAClB;AAGA,QAAM,oBAAoB,MAAc;AACvC,QAAI,WAAW,WAAW,EAAG,QAAO;AACpC,UAAM,aACL,QAAQ,SAAS,IACd,UACA,OAAO,KAAK,WAAW,CAAC,CAA4B;AACxD,UAAM,SAAS,KAAK,WAAW,KAAK,KAAK,CAAC;AAC1C,UAAM,YAAY,KAAK,WAAW,IAAI,MAAM,KAAK,EAAE,KAAK,KAAK,CAAC;AAC9D,UAAM,OAAO,WAAW,IAAI,CAAC,QAAQ;AACpC,YAAM,QAAQ,WAAW,IAAI,CAACA,SAAQ,UAAU,IAAIA,IAAG,CAAC,CAAC;AACzD,aAAO,KAAK,MAAM,KAAK,KAAK,CAAC;AAAA,IAC9B,CAAC;AACD,WAAO,CAAC,QAAQ,WAAW,GAAG,IAAI,EAAE,KAAK,IAAI;AAAA,EAC9C;AAGA,MAAI,WAAW,WAAW,aAAa,QAAQ;AAC9C,WAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU,GAAG,aAAa,MAAM;AAAA,MAChC,QAAQ,GAAG,WAAW,MAAM;AAAA,MAC5B,QAAQ;AAAA,MACR,SAAS,YAAY,aAAa,MAAM,cAAc,WAAW,MAAM;AAAA;AAAA,EAAmB,kBAAkB,CAAC;AAAA,IAC9G;AAAA,EACD;AAGA,MAAI,WAAW,SAAS,GAAG;AAC1B,UAAM,WAAW,WAAW,CAAC;AAC7B,eAAWA,QAAO,SAAS;AAC1B,UAAI,EAAEA,QAAO,WAAW;AACvB,eAAO;AAAA,UACN,MAAM;AAAA,UACN,UAAU,WAAWA,IAAG;AAAA,UACxB,QAAQ,YAAY,OAAO,KAAK,QAAQ,EAAE,KAAK,IAAI,CAAC;AAAA,UACpD,QAAQ;AAAA,UACR,SAAS,oBAAoBA,IAAG,sCAAsC,OAAO,KAAK,QAAQ,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA,EAAmB,kBAAkB,CAAC;AAAA,QAC7I;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAGA,WAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC7C,UAAM,cAAc,aAAa,CAAC;AAClC,UAAM,YAAY,WAAW,CAAC;AAC9B,QAAI,CAAC,eAAe,CAAC,UAAW;AAEhC,aAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACxC,YAAMA,OAAM,QAAQ,CAAC;AACrB,UAAI,CAACA,KAAK;AACV,YAAM,cAAc,YAAY,CAAC,KAAK;AACtC,YAAM,YAAY,UAAUA,IAAG;AAC/B,YAAM,mBAAmB,UAAU,SAAS;AAG5C,YAAM,iBAAiB,gBAAgB;AACvC,YAAM,eAAe,cAAc,QAAQ,cAAc;AAEzD,UAAI,kBAAkB,aAAc;AACpC,UAAI,mBAAmB,cAAc;AACpC,eAAO;AAAA,UACN,MAAM;AAAA,UACN,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,SAAS,OAAO,IAAI,CAAC,aAAaA,IAAG,eAAe,WAAW,SAAS,gBAAgB;AAAA;AAAA,EAAmB,kBAAkB,CAAC;AAAA,QAC/H;AAAA,MACD;AAGA,UAAI,iBAAiB,KAAK,MAAM,YAAY,KAAK,GAAG;AACnD,eAAO;AAAA,UACN,MAAM;AAAA,UACN,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,SAAS,OAAO,IAAI,CAAC,aAAaA,IAAG,gBAAgB,WAAW,WAAW,gBAAgB;AAAA;AAAA,EAAoB,kBAAkB,CAAC;AAAA,QACnI;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN,MAAM;AAAA,IACN,UAAU,GAAG,aAAa,MAAM;AAAA,IAChC,QAAQ,GAAG,aAAa,MAAM;AAAA,IAC9B,QAAQ;AAAA,IACR,SAAS;AAAA,EACV;AACD;AASO,SAAS,iBACf,QACA,UACmB;AACnB,QAAM,SAAS,OAAO,QAAQ;AAE9B,MAAI,CAAC,OAAO,QAAQ;AACnB,WAAO;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,IACV;AAAA,EACD;AAEA,QAAM,SAAS,WAAW;AAE1B,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,SAAS,SAAY;AAAA,IAC7B;AAAA,IACA,SAAS,SACN,SACA,yBAAyB,QAAQ,WAAW,MAAM;AAAA,EACtD;AACD;AAKO,SAAS,kBACf,QACA,UACmB;AACnB,QAAM,SAAS,OAAO,QAAQ;AAE9B,MAAI,CAAC,OAAO,QAAQ;AACnB,WAAO;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,IACV;AAAA,EACD;AAGA,QAAM,SAAS,QAAQ,YAAY,MAAM,SAAS,YAAY;AAE9D,SAAO;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,SAAS,SAAY;AAAA,IAC7B;AAAA,IACA,SAAS,SACN,SACA,mBAAmB,QAAQ,WAAW,MAAM;AAAA,EAChD;AACD;AAMO,SAAS,iBACf,QACA,UACmB;AACnB,QAAM,SAAS,OAAO,QAAQ,QAAQ,CAAC;AACvC,QAAM,gBAAgB,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC,QAAQ;AAEpE,MAAI,CAAC,OAAO,QAAQ;AACnB,WAAO;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,IACV;AAAA,EACD;AAGA,QAAM,cAAc,OAAO,IAAI,CAAC,MAAc,EAAE,YAAY,CAAC;AAC7D,QAAM,UAAU,cAAc;AAAA,IAC7B,CAAC,MAAM,CAAC,YAAY,SAAS,EAAE,YAAY,CAAC;AAAA,EAC7C;AAEA,QAAM,SAAS,QAAQ,WAAW;AAElC,SAAO;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ,SAAS,SAAY;AAAA,IAC7B;AAAA,IACA,SAAS,SACN,SACA,sBAAsB,QAAQ,KAAK,IAAI,CAAC,YAAY,OAAO,KAAK,IAAI,CAAC;AAAA,EACzE;AACD;AAKA,SAAS,6BACR,eACA,OACC;AACD,SAAO,CACN,QACA,aACsB;AACtB,QAAI,CAAC,OAAO,QAAQ;AACnB,aAAO;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,SAAS;AAAA,MACV;AAAA,IACD;AAEA,UAAM,SAAU,OAAO,OAAO,KAAK,KAAiB;AACpD,UAAM,SAAS,WAAW;AAE1B,WAAO;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,QAAQ,SAAS,SAAY;AAAA,MAC7B;AAAA,MACA,SAAS,SACN,SACA,YAAY,OAAO,KAAK,CAAC,IAAI,QAAQ,SAAS,MAAM;AAAA,IACxD;AAAA,EACD;AACD;AAEO,IAAM,uBAAuB;AAAA,EACnC;AAAA,EACA;AACD;AACO,IAAM,yBAAyB;AAAA,EACrC;AAAA,EACA;AACD;AACO,IAAM,yBAAyB;AAAA,EACrC;AAAA,EACA;AACD;;;ACrvBO,IAAM,kBAAkB;AAAA;AAAA,EAE9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA;AAAA,EAGA;AAAA;AAAA,EACA;AAAA;AAAA;AAAA,EAGA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA;AAAA,EAGA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACD;AAQO,SAAS,iBAAiB,MAA8B;AAC9D,SAAO,KAAK,WAAW,KAAK;AAC7B;AAwDO,SAAS,mBAAmB,SAA8B;AAChE,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,SAA2B,CAAC;AAClC,QAAM,SAAuB,CAAC;AAE9B,MAAI,eAAsC;AAE1C,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACtC,UAAM,UAAU,IAAI;AACpB,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,SAAS,OAAW;AACxB,UAAM,UAAU,KAAK,KAAK;AAG1B,QAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,GAAG;AACxC;AAAA,IACD;AAGA,QAAI,QAAQ,WAAW,KAAK,GAAG;AAE9B,UAAI,cAAc;AACjB,eAAO,KAAK,YAAY;AAAA,MACzB;AAEA,YAAM,cAAc,QAAQ,MAAM,CAAC,EAAE,KAAK;AAC1C,YAAM,SAAS,iBAAiB,aAAa,OAAO;AAEpD,UAAI,OAAO,SAAS,CAAC,OAAO,OAAO;AAClC,eAAO,KAAK;AAAA,UACX,MAAM;AAAA,UACN,SAAS,OAAO,SAAS;AAAA,QAC1B,CAAC;AACD,uBAAe;AAAA,MAChB,OAAO;AACN,uBAAe;AAAA,UACd,GAAG,OAAO;AAAA,UACV,WAAW;AAAA,UACX,YAAY,CAAC;AAAA,QACd;AAAA,MACD;AACA;AAAA,IACD;AAGA,QAAI,cAAc;AACjB,YAAM,YAAY,mBAAmB,SAAS,OAAO;AACrD,UAAI,UAAU,OAAO;AACpB,eAAO,KAAK,EAAE,MAAM,SAAS,SAAS,UAAU,MAAM,CAAC;AAAA,MACxD,WAAW,UAAU,WAAW;AAE/B,YACC,UAAU,UAAU,SAAS,eAC7B,UAAU,UAAU,UAAU,IAC7B;AACD,gBAAM,cAAc,gBAAgB,OAAO,IAAI,CAAC;AAChD,cAAI,YAAY,OAAO;AACtB,mBAAO,KAAK,EAAE,MAAM,SAAS,SAAS,YAAY,MAAM,CAAC;AAAA,UAC1D,WAAW,YAAY,MAAM;AAC5B,sBAAU,UAAU,QAAQ,YAAY;AACxC,yBAAa,WAAW,KAAK,UAAU,SAAS;AAAA,UACjD;AACA,eAAK,YAAY;AAAA,QAClB,OAAO;AACN,uBAAa,WAAW,KAAK,UAAU,SAAS;AAAA,QACjD;AAAA,MACD;AAAA,IACD,OAAO;AAEN,aAAO,KAAK;AAAA,QACX,MAAM;AAAA,QACN,SACC;AAAA,MACF,CAAC;AAAA,IACF;AAAA,EACD;AAGA,MAAI,cAAc;AACjB,WAAO,KAAK,YAAY;AAAA,EACzB;AAEA,SAAO,EAAE,QAAQ,OAAO;AACzB;AAKA,SAAS,iBACR,QACA,OACsD;AAEtD,QAAM,aAAa,OAAO,MAAM,kBAAkB;AAClD,QAAM,gBAAgB,aAAa,CAAC;AACpC,MAAI,kBAAkB,QAAW;AAChC,UAAM,QAAQ,SAAS,eAAe,EAAE;AACxC,WAAO,EAAE,OAAO,EAAE,YAAY,MAAM,EAAE;AAAA,EACvC;AAGA,QAAM,aAAa,OAAO,MAAM,iBAAiB;AACjD,QAAM,YAAY,aAAa,CAAC;AAChC,MAAI,cAAc,QAAW;AAC5B,UAAM,OAAO,UAAU,KAAK;AAC5B,QAAI,CAAC,MAAM;AACV,aAAO,EAAE,OAAO,sBAAsB;AAAA,IACvC;AACA,WAAO,EAAE,OAAO,EAAE,YAAY,KAAK,EAAE;AAAA,EACtC;AAGA,SAAO;AAAA,IACN,OAAO,0BAA0B,MAAM;AAAA,EACxC;AACD;AAKA,SAAS,mBACR,MACA,SAC4C;AAE5C,QAAM,aAAa,KAAK,QAAQ,GAAG;AACnC,MAAI,eAAe,IAAI;AACtB,WAAO;AAAA,MACN,OAAO,8BAA8B,IAAI;AAAA,IAC1C;AAAA,EACD;AAEA,QAAM,UAAU,KAAK,MAAM,GAAG,UAAU,EAAE,KAAK;AAC/C,QAAM,WAAW,KAAK,MAAM,aAAa,CAAC,EAAE,KAAK;AAGjD,MAAI,CAAC,qBAAqB,OAAO,GAAG;AACnC,WAAO;AAAA,MACN,OAAO,4BAA4B,OAAO,mBAAmB,gBAAgB,KAAK,IAAI,CAAC;AAAA,IACxF;AAAA,EACD;AAEA,QAAM,OAAO;AAGb,QAAM,cAAc,oBAAoB,MAAM,QAAQ;AACtD,MAAI,YAAY,SAAS,YAAY,UAAU,QAAW;AACzD,WAAO,EAAE,OAAO,YAAY,SAAS,kCAAkC;AAAA,EACxE;AAEA,SAAO;AAAA,IACN,WAAW;AAAA,MACV;AAAA,MACA,OAAO,YAAY;AAAA,MACnB,MAAM;AAAA,IACP;AAAA,EACD;AACD;AAKA,SAAS,qBAAqB,MAAqC;AAClE,SAAO,gBAAgB,SAAS,IAAqB;AACtD;AAKA,SAAS,oBACR,MACA,UACoE;AACpE,UAAQ,MAAM;AAAA;AAAA,IAEb,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACJ,UAAI,aAAa,OAAQ,QAAO,EAAE,OAAO,KAAK;AAC9C,UAAI,aAAa,QAAS,QAAO,EAAE,OAAO,MAAM;AAChD,aAAO;AAAA,QACN,OAAO,8BAA8B,IAAI,OAAO,QAAQ;AAAA,MACzD;AAAA;AAAA,IAGD,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,eAAe;AACnB,YAAM,MAAM,SAAS,UAAU,EAAE;AACjC,UAAI,OAAO,MAAM,GAAG,KAAK,MAAM,GAAG;AACjC,eAAO;AAAA,UACN,OAAO,uBAAuB,IAAI,OAAO,QAAQ;AAAA,QAClD;AAAA,MACD;AACA,aAAO,EAAE,OAAO,IAAI;AAAA,IACrB;AAAA;AAAA,IAGA,KAAK;AACJ,UAAI;AACH,cAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,YAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC3B,iBAAO;AAAA,YACN,OAAO,yDAAyD,OAAO,MAAM;AAAA,UAC9E;AAAA,QACD;AACA,eAAO,EAAE,OAAO,OAAO;AAAA,MACxB,SAAS,IAAI;AACZ,eAAO,EAAE,OAAO,qCAAqC,QAAQ,GAAG;AAAA,MACjE;AAAA;AAAA,IAGD,KAAK;AACJ,UAAI;AACH,cAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,YAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC3B,iBAAO;AAAA,YACN,OAAO,uDAAuD,OAAO,MAAM;AAAA,UAC5E;AAAA,QACD;AACA,eAAO,EAAE,OAAO,OAAO;AAAA,MACxB,SAAS,IAAI;AACZ,eAAO,EAAE,OAAO,mCAAmC,QAAQ,GAAG;AAAA,MAC/D;AAAA;AAAA,IAGD,KAAK;AAEJ,aAAO,EAAE,OAAO,SAAS;AAAA;AAAA,IAG1B,KAAK;AAEJ,UAAI;AACH,eAAO,EAAE,OAAO,KAAK,MAAM,QAAQ,EAAE;AAAA,MACtC,QAAQ;AACP,eAAO,EAAE,OAAO,SAAS;AAAA,MAC1B;AAAA;AAAA,IAGD,KAAK;AACJ,aAAO,EAAE,OAAO,GAAG;AAAA;AAAA;AAAA,IAGpB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAEJ,UAAI,KAAK,SAAS,UAAU,GAAG;AAC9B,YAAI;AACH,cAAI,OAAO,QAAQ;AAAA,QACpB,SAAS,IAAI;AACZ,iBAAO,EAAE,OAAO,2BAA2B,QAAQ,IAAI;AAAA,QACxD;AAAA,MACD;AACA,aAAO,EAAE,OAAO,SAAS;AAAA,IAE1B;AACC,aAAO,EAAE,OAAO,6BAA6B,IAAI,GAAG;AAAA,EACtD;AACD;AASA,SAAS,eAAe,MAAuB;AAC9C,SAAO,kBAAkB,KAAK,KAAK,KAAK,CAAC;AAC1C;AAMA,SAAS,gBAAgB,MAAwB;AAChD,MAAI,QAAQ,KAAK,KAAK;AAEtB,MAAI,MAAM,WAAW,GAAG,EAAG,SAAQ,MAAM,MAAM,CAAC;AAChD,MAAI,MAAM,SAAS,GAAG,EAAG,SAAQ,MAAM,MAAM,GAAG,EAAE;AAElD,QAAM,QAAkB,CAAC;AACzB,MAAI,UAAU;AACd,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACtC,QAAI,MAAM,CAAC,MAAM,QAAQ,IAAI,IAAI,MAAM,UAAU,MAAM,IAAI,CAAC,MAAM,KAAK;AACtE,iBAAW;AACX;AAAA,IACD,WAAW,MAAM,CAAC,MAAM,KAAK;AAC5B,YAAM,KAAK,QAAQ,KAAK,CAAC;AACzB,gBAAU;AAAA,IACX,OAAO;AACN,iBAAW,MAAM,CAAC;AAAA,IACnB;AAAA,EACD;AACA,QAAM,KAAK,QAAQ,KAAK,CAAC;AACzB,SAAO;AACR;AAOA,SAAS,gBACR,OACA,YACuE;AACvE,QAAM,aAAuB,CAAC;AAC9B,MAAI,WAAW;AAEf,WAAS,IAAI,YAAY,IAAI,MAAM,QAAQ,KAAK;AAC/C,UAAMC,OAAM,MAAM,CAAC;AACnB,QAAIA,SAAQ,OAAW;AACvB,UAAM,UAAUA,KAAI,KAAK;AAGzB,QAAI,CAAC,SAAS;AACb;AACA;AAAA,IACD;AAGA,QAAI,QAAQ,WAAW,GAAG,GAAG;AAC5B,iBAAW,KAAK,OAAO;AACvB;AACA;AAAA,IACD;AAGA;AAAA,EACD;AAEA,MAAI,WAAW,WAAW,GAAG;AAC5B,WAAO;AAAA,MACN,eAAe;AAAA,MACf,OAAO;AAAA,IACR;AAAA,EACD;AAGA,QAAM,YAAY,WAAW,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;AAC7D,MAAI,UAAU,WAAW,GAAG;AAC3B,WAAO;AAAA,MACN,eAAe;AAAA,MACf,OAAO;AAAA,IACR;AAAA,EACD;AAEA,QAAM,aAAa,UAAU,CAAC;AAC9B,QAAM,UAAU,gBAAgB,UAAU;AAC1C,QAAM,OAAO,UAAU,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,gBAAgB,CAAC,CAAC;AAE7D,SAAO,EAAE,MAAM,EAAE,SAAS,KAAK,GAAG,eAAe,SAAS;AAC3D;AAUO,SAAS,wBACf,QACA,YACA,SACe;AACf,QAAM,SAAuB,CAAC;AAE9B,aAAW,SAAS,QAAQ;AAE3B,QAAI,MAAM,eAAe,QAAW;AACnC,UAAI,MAAM,aAAa,KAAK,MAAM,cAAc,YAAY;AAC3D,eAAO,KAAK;AAAA,UACX,MAAM,MAAM;AAAA,UACZ,SAAS,eAAe,MAAM,UAAU,qBAAqB,aAAa,CAAC;AAAA,QAC5E,CAAC;AAAA,MACF;AAAA,IACD;AAGA,QAAI,MAAM,eAAe,QAAW;AACnC,YAAM,kBAAkB,QACtB,IAAI,CAAC,GAAG,MAAO,EAAE,KAAK,MAAM,MAAM,YAAY,KAAK,IAAI,IAAI,EAAG,EAC9D,OAAO,CAAC,MAAM,MAAM,EAAE;AAExB,UAAI,gBAAgB,WAAW,GAAG;AACjC,eAAO,KAAK;AAAA,UACX,MAAM,MAAM;AAAA,UACZ,SAAS,qBAAqB,MAAM,UAAU;AAAA,QAC/C,CAAC;AAAA,MACF,WAAW,gBAAgB,SAAS,GAAG;AAEtC,eAAO,KAAK;AAAA,UACX,MAAM,MAAM;AAAA,UACZ,SAAS,qBAAqB,MAAM,UAAU,qBAAqB,gBAAgB,KAAK,IAAI,CAAC;AAAA,QAC9F,CAAC;AAAA,MACF;AAAA,IACD;AAGA,QAAI,MAAM,WAAW,WAAW,GAAG;AAClC,aAAO,KAAK;AAAA,QACX,MAAM,MAAM;AAAA,QACZ,SAAS;AAAA,MACV,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO;AACR;AASO,SAAS,kBACf,OACA,SACS;AACT,MAAI,MAAM,eAAe,QAAW;AACnC,WAAO,MAAM;AAAA,EACd;AAEA,MAAI,MAAM,eAAe,QAAW;AACnC,UAAM,QAAQ,QAAQ;AAAA,MACrB,CAAC,MAAM,EAAE,KAAK,MAAM,MAAM,YAAY,KAAK;AAAA,IAC5C;AACA,WAAO;AAAA,EACR;AAEA,SAAO;AACR;;;ACjgBO,SAAS,cACf,QACA,SACA,SACA,QAAQ,OACW;AACnB,QAAM,eAAuC,CAAC;AAC9C,MAAI,cAAc;AAClB,MAAI,cAAc;AAClB,MAAI,eAAe;AAEnB,aAAW,SAAS,QAAQ;AAC3B,UAAM,aAAa,kBAAkB,OAAO,OAAO;AAGnD,QAAI,eAAe,MAAM,cAAc,QAAQ,QAAQ;AACtD;AAAA,IACD;AAEA,UAAM,SAAS,QAAQ,UAAU;AACjC,QAAI,CAAC,QAAQ;AACZ;AAAA,IACD;AAEA,UAAM,WAA+B,CAAC;AACtC,QAAI,YAAY;AAEhB,eAAW,aAAa,MAAM,YAAY;AACzC,YAAM,UAAU,mBAAmB,WAAW,QAAQ,KAAK;AAC3D,eAAS,KAAK,OAAO;AAErB,UAAI,QAAQ,SAAS;AACpB;AAAA,MACD,WAAW,QAAQ,QAAQ;AAC1B;AAAA,MACD,OAAO;AACN;AACA,oBAAY;AAAA,MACb;AAAA,IACD;AAEA,iBAAa,KAAK;AAAA,MACjB;AAAA,MACA,OAAO,OAAO;AAAA,MACd,cAAc,OAAO;AAAA,MACrB,YAAY;AAAA,MACZ,QAAQ;AAAA,IACT,CAAC;AAAA,EACF;AAEA,SAAO;AAAA,IACN,OAAO,cAAc,cAAc;AAAA,IACnC,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,EACV;AACD;AAKA,SAAS,mBACR,WACA,QACA,OACmB;AACnB,QAAM,EAAE,MAAM,MAAM,IAAI;AAGxB,MAAI,KAAK,WAAW,KAAK,KAAK,CAAC,OAAO;AACrC,WAAO;AAAA,MACN;AAAA,MACA,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA;AAAA,MACR,SAAS;AAAA,MACT,SAAS;AAAA,MACT,YAAY;AAAA,IACb;AAAA,EACD;AAEA,UAAQ,MAAM;AAAA;AAAA,IAEb,KAAK;AACJ,aAAO,eAAe,UAAU,OAAO,UAAU,IAAI,KAAe;AAAA,IAErE,KAAK;AACJ,aAAO,aAAa,UAAU,OAAO,UAAU,IAAI,KAAe;AAAA,IAEnE,KAAK;AACJ,aAAO,cAAc,UAAU,OAAO,UAAU,IAAI,KAAe;AAAA;AAAA,IAGpE,KAAK;AACJ,aAAO,gBAAgB,OAAO,OAAO,IAAI,KAAe;AAAA,IAEzD,KAAK;AACJ,aAAO,cAAc,OAAO,OAAO,OAAO,IAAI,KAAe;AAAA,IAE9D,KAAK;AACJ,aAAO,eAAe,OAAO,OAAO,IAAI,KAAe;AAAA,IAExD,KAAK;AACJ,aAAO,gBAAgB,OAAO,OAAO,IAAI,KAAe;AAAA,IAEzD,KAAK;AACJ,aAAO,cAAc,OAAO,OAAO,IAAI,KAAe;AAAA;AAAA,IAGvD,KAAK;AACJ,aAAO,mBAAmB,OAAO,UAAU,CAAC,GAAG,KAAkB;AAAA,IAElE,KAAK;AACJ,aAAO,mBAAmB,OAAO,UAAU,CAAC,GAAG,KAAe;AAAA,IAE/D,KAAK;AACJ,aAAO,iBAAiB,OAAO,UAAU,CAAC,GAAG,KAAiB;AAAA,IAE/D,KAAK;AACJ,aAAO,kBAAkB,OAAO,UAAU,CAAC,GAAG,KAAgB;AAAA;AAAA,IAG/D,KAAK;AACJ,aAAO,eAAe,QAAQ,OAAO,UAAU,IAAI,KAAe;AAAA;AAAA,IAGnE,KAAK;AACJ,aAAO,cAAc,OAAO,SAAS,KAAgB;AAAA;AAAA,IAGtD,KAAK;AACJ,aAAO,eAAe,SAAS,OAAO,SAAS,IAAI,KAAe;AAAA;AAAA,IAGnE,KAAK;AAEJ,aAAO;AAAA,QACN,OAAO,aAAa,OAAO;AAAA,QAC3B;AAAA,MACD;AAAA,IAED,KAAK;AACJ,aAAO,eAAe,QAAQ,KAA2B;AAAA,IAE1D,KAAK;AACJ,aAAO;AAAA,QACN;AAAA,QACA,OAAO,UAAU;AAAA,QACjB;AAAA,QACA;AAAA,MACD;AAAA,IAED,KAAK;AACJ,aAAO,mBAAmB,QAAQ,KAAe;AAAA,IAElD,KAAK;AACJ,aAAO,gBAAgB,QAAQ,KAAe;AAAA,IAE/C,KAAK;AACJ,aAAO,gBAAgB,QAAQ,KAAe;AAAA,IAE/C,KAAK;AACJ,aAAO,qBAAqB,QAAQ,KAAe;AAAA,IAEpD,KAAK;AACJ,aAAO,oBAAoB,QAAQ,KAAgB;AAAA;AAAA,IAGpD,KAAK;AACJ,aAAO,iBAAiB,QAAQ,KAAe;AAAA,IAEhD,KAAK;AACJ,aAAO,kBAAkB,QAAQ,KAAe;AAAA,IAEjD,KAAK;AACJ,aAAO,iBAAiB,QAAQ,KAA0B;AAAA,IAE3D,KAAK;AACJ,aAAO,qBAAqB,QAAQ,KAAgB;AAAA,IAErD,KAAK;AACJ,aAAO,uBAAuB,QAAQ,KAAgB;AAAA,IAEvD,KAAK;AACJ,aAAO,uBAAuB,QAAQ,KAAgB;AAAA,IAEvD;AACC,aAAO;AAAA,QACN;AAAA,QACA,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,SAAS,2BAA2B,IAAI;AAAA,MACzC;AAAA,EACF;AACD;;;AC9IO,SAAS,iBAAiB,GAGrB;AACX,SAAO,QAAQ,CAAC,KAAK,EAAE,YAAY,QAAQ,EAAE,cAAc;AAC5D;","names":["col","ref","col","SchemaValidationError","col","ref","col","col","fn","ref","fn","col","intent","record","record","v","op","col","rows","col","op","v","requireAdapter","sql","schemaName","fn","ref","mapRelationType","col","schema","sql","sql","param","col","raw"]}
|
|
1
|
+
{"version":3,"sources":["../src/model-ir.ts","../src/intent-ast.ts","../src/model-impl.ts","../src/dx/logger.ts","../src/dx/symbols.ts","../src/dx/table-ref.ts","../src/dx/table-ref-factory.ts","../src/dx/schema.ts","../src/conventions.ts","../src/schema-dsl.ts","../src/schema-dsl-types.ts","../src/dx/errors.ts","../src/planner.ts","../src/adapter.ts","../src/dx/batch-values.ts","../src/dx/expressions.ts","../src/dx/case-when-builder.ts","../src/dx/builder-utils.ts","../src/dx/cte-builder.ts","../src/dx/feature-checkers.ts","../src/dx/column-utils.ts","../src/dx/window-functions.ts","../src/dx/filters.ts","../src/dx/full-text-search.ts","../src/dx/hook-utils.ts","../src/dx/hooks.ts","../src/dx/subquery-builder.ts","../src/dx/object-filter.ts","../src/dx/types.ts","../src/dx/intent-builder.ts","../src/dx/lightweight-model.ts","../src/dx/mutation-builders.ts","../src/dx/negotiate-features.ts","../src/dx/nql.ts","../src/dx/hierarchy-helpers.ts","../src/dx/pagination-impl.ts","../src/dx/hydration-utils.ts","../src/dx/result-hydrator.ts","../src/dx/set-operation-builder.ts","../src/dx/stream-impl.ts","../src/dx/query-builder.ts","../src/dx/raw-cte-builder.ts","../src/dx/orm-instance.ts","../src/dx/orm.ts","../src/dx/range.ts","../src/dx/schema-bridge.ts","../src/dialects/index.ts","../src/sql-utils.ts","../src/assert/assertion-functions.ts","../src/assert/assertion-parser.ts","../src/assert/assertion-runner.ts","../src/assert/types.ts"],"sourcesContent":["/**\n * @module model-ir\n * ModelIR (Model Intermediate Representation) - Schema definition format for db-semantic-planner.\n * Represents database tables, columns, and relations with planning metadata.\n *\n * Type definitions live in @dbsp/types. This module re-exports them\n * and provides runtime functions.\n */\n\n// Re-export all types from @dbsp/types for backward compatibility\nexport type {\n\tAmbiguityCheckResult,\n\tCardinality,\n\tCheckConstraintIR,\n\tColumnIR,\n\tColumnType,\n\tEnumIR,\n\tFilterStrategy,\n\tForeignKeyIR,\n\tIncludeStrategy,\n\tIndexIR,\n\tJoinDefault,\n\tModelIR,\n\tOnDeleteAction,\n\tOptionality,\n\tPartitionIR,\n\tPseudoColumnMetadata,\n\tRecursiveMetadata,\n\tRelationIR,\n\tRelationKind,\n\tRelationType,\n\tSequenceIR,\n\tTableIR,\n} from '@dbsp/types';\n\nimport type {\n\tPseudoColumnMetadata,\n\tRecursiveMetadata,\n\tRelationIR,\n\tRelationKind,\n} from '@dbsp/types';\n\n// ============================================================================\n// Runtime Functions (stay in @dbsp/core)\n// ============================================================================\n\n/**\n * Creates pseudo-column metadata from a self-referential FK.\n */\nexport function createPseudoColumnMetadata(\n\ttable: string,\n\tforeignKeyColumn: string,\n\ttargetColumn: string,\n\tparentRole: string,\n\tchildRole: string,\n): PseudoColumnMetadata {\n\t// For single self-ref FK: ascendant/descendant are direct keywords\n\t// For multi-FK: they become scoped (e.g., manager.ascendant)\n\treturn {\n\t\ttable,\n\t\tforeignKeyColumn,\n\t\ttargetColumn,\n\t\tparentRole,\n\t\tchildRole,\n\t\tascendantKeyword: 'ascendant',\n\t\tdescendantKeyword: 'descendant',\n\t};\n}\n\n/**\n * CLI-NQL: Convert ORM-style RelationType to database-style RelationKind.\n * Handles recursive relations when recursive metadata is present.\n */\nexport function getRelationKind(relation: RelationIR): RelationKind {\n\t// Check for recursive relation first\n\tif (relation.recursive) {\n\t\treturn relation.recursive.direction === 'up'\n\t\t\t? 'recursive-up'\n\t\t\t: 'recursive-down';\n\t}\n\n\t// Map ORM types to database perspective\n\tswitch (relation.type) {\n\t\tcase 'belongsTo':\n\t\tcase 'hasOne':\n\t\t\treturn 'many-to-one';\n\t\tcase 'hasMany':\n\t\t\treturn 'one-to-many';\n\t\tcase 'belongsToMany':\n\t\t\treturn 'many-to-many';\n\t}\n}\n\n/**\n * CLI-NQL: Type guard to check if a relation has recursive metadata.\n */\nexport function isRecursiveRelation(\n\trelation: RelationIR,\n): relation is RelationIR & { recursive: RecursiveMetadata } {\n\treturn relation.recursive !== undefined;\n}\n\n/**\n * CLI-NQL: Check if a relation is self-referential (source === target).\n * Self-referential relations are candidates for recursive traversal.\n */\nexport function isSelfReferential(relation: RelationIR): boolean {\n\treturn relation.source === relation.target;\n}\n\n/**\n * CLI-NQL: Create default recursive metadata for a self-referential relation.\n * Used when schema doesn't explicitly define recursive metadata.\n */\nexport function createRecursiveMetadata(\n\tdirection: 'up' | 'down',\n\tthroughRelation: string,\n\tmaxDepth = 10,\n): RecursiveMetadata {\n\treturn {\n\t\tdirection,\n\t\tmaxDepth,\n\t\tthrough: throughRelation,\n\t};\n}\n","/**\n * @module intent-ast\n * IntentAST (Intent Abstract Syntax Tree) - Query intent representation for db-semantic-planner.\n *\n * This module re-exports all IntentAST types and type guards from @dbsp/types.\n * The canonical source is @dbsp/types/intent-ast.\n *\n * @since ARCH-007: Types centralized in @dbsp/types to avoid circular dependencies.\n */\n\n// Re-export everything from @dbsp/types (types + type guards + helpers)\nexport * from '@dbsp/types';\n","/**\n * @module model-impl\n * ModelIR implementation with Map-based storage and helper methods.\n */\n\nimport type {\n\tAmbiguityCheckResult,\n\tEnumIR,\n\tModelIR,\n\tRelationIR,\n\tSequenceIR,\n\tTableIR,\n} from './model-ir.js';\n\n/**\n * Immutable ModelIR implementation\n */\nexport class ModelIRImpl implements ModelIR {\n\treadonly tables: ReadonlyMap<string, TableIR>;\n\treadonly relations: ReadonlyMap<string, RelationIR>;\n\treadonly enums?: ReadonlyMap<string, EnumIR>;\n\treadonly extensions?: readonly string[];\n\treadonly sequences?: ReadonlyMap<string, SequenceIR>;\n\n\t// Pre-computed indexes for efficient lookups\n\tprivate readonly relationsBySource: ReadonlyMap<\n\t\tstring,\n\t\treadonly RelationIR[]\n\t>;\n\tprivate readonly relationsByTarget: ReadonlyMap<\n\t\tstring,\n\t\treadonly RelationIR[]\n\t>;\n\n\tconstructor(\n\t\ttables: Map<string, TableIR>,\n\t\trelations: Map<string, RelationIR>,\n\t\tenums?: Map<string, EnumIR>,\n\t\textensions?: readonly string[],\n\t\tsequences?: Map<string, SequenceIR>,\n\t) {\n\t\t// Freeze the maps to ensure immutability\n\t\tthis.tables = Object.freeze(new Map(tables)) as ReadonlyMap<\n\t\t\tstring,\n\t\t\tTableIR\n\t\t>;\n\t\tthis.relations = Object.freeze(new Map(relations)) as ReadonlyMap<\n\t\t\tstring,\n\t\t\tRelationIR\n\t\t>;\n\t\tif (enums) {\n\t\t\tthis.enums = Object.freeze(new Map(enums)) as ReadonlyMap<string, EnumIR>;\n\t\t}\n\t\tif (extensions && extensions.length > 0) {\n\t\t\tthis.extensions = Object.freeze([...extensions]) as readonly string[];\n\t\t}\n\t\tif (sequences) {\n\t\t\tthis.sequences = Object.freeze(new Map(sequences)) as ReadonlyMap<\n\t\t\t\tstring,\n\t\t\t\tSequenceIR\n\t\t\t>;\n\t\t}\n\n\t\t// Build indexes\n\t\tthis.relationsBySource = this.buildRelationsBySourceIndex(relations);\n\t\tthis.relationsByTarget = this.buildRelationsByTargetIndex(relations);\n\n\t\t// Validate the schema\n\t\tthis.validate();\n\t}\n\n\t/**\n\t * Get table by name\n\t */\n\tgetTable(name: string): TableIR | undefined {\n\t\treturn this.tables.get(name);\n\t}\n\n\t/**\n\t * Get relation by qualified name \"source.relationName\"\n\t */\n\tgetRelation(qualifiedName: string): RelationIR | undefined {\n\t\treturn this.relations.get(qualifiedName);\n\t}\n\n\t/**\n\t * Get all relations from a source table\n\t */\n\tgetRelationsFrom(sourceTable: string): readonly RelationIR[] {\n\t\treturn this.relationsBySource.get(sourceTable) ?? [];\n\t}\n\n\t/**\n\t * Get all relations to a target table\n\t */\n\tgetRelationsTo(targetTable: string): readonly RelationIR[] {\n\t\treturn this.relationsByTarget.get(targetTable) ?? [];\n\t}\n\n\t/**\n\t * Check if relation path is ambiguous (multiple relations to same target)\n\t */\n\tisAmbiguous(sourceTable: string, targetTable: string): AmbiguityCheckResult {\n\t\tconst relationsFromSource = this.getRelationsFrom(sourceTable);\n\t\tconst matchingRelations = relationsFromSource.filter(\n\t\t\t(r) => r.target === targetTable,\n\t\t);\n\n\t\tif (matchingRelations.length <= 1) {\n\t\t\treturn {\n\t\t\t\tambiguous: false,\n\t\t\t\toptions: matchingRelations.map((r) => r.name),\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tambiguous: true,\n\t\t\toptions: matchingRelations.map((r) => r.name),\n\t\t};\n\t}\n\n\t// =========================================================================\n\t// Private Methods\n\t// =========================================================================\n\n\tprivate buildRelationsBySourceIndex(\n\t\trelations: Map<string, RelationIR>,\n\t): ReadonlyMap<string, readonly RelationIR[]> {\n\t\tconst index = new Map<string, RelationIR[]>();\n\n\t\tfor (const relation of relations.values()) {\n\t\t\tconst existing = index.get(relation.source) ?? [];\n\t\t\tindex.set(relation.source, [...existing, relation]);\n\t\t}\n\n\t\t// Create frozen index with readonly arrays\n\t\tconst frozenIndex = new Map<string, readonly RelationIR[]>();\n\t\tfor (const [key, value] of index) {\n\t\t\tfrozenIndex.set(key, Object.freeze(value));\n\t\t}\n\n\t\treturn Object.freeze(frozenIndex) as ReadonlyMap<\n\t\t\tstring,\n\t\t\treadonly RelationIR[]\n\t\t>;\n\t}\n\n\tprivate buildRelationsByTargetIndex(\n\t\trelations: Map<string, RelationIR>,\n\t): ReadonlyMap<string, readonly RelationIR[]> {\n\t\tconst index = new Map<string, RelationIR[]>();\n\n\t\tfor (const relation of relations.values()) {\n\t\t\tconst existing = index.get(relation.target) ?? [];\n\t\t\tindex.set(relation.target, [...existing, relation]);\n\t\t}\n\n\t\t// Create frozen index with readonly arrays\n\t\tconst frozenIndex = new Map<string, readonly RelationIR[]>();\n\t\tfor (const [key, value] of index) {\n\t\t\tfrozenIndex.set(key, Object.freeze(value));\n\t\t}\n\n\t\treturn Object.freeze(frozenIndex) as ReadonlyMap<\n\t\t\tstring,\n\t\t\treadonly RelationIR[]\n\t\t>;\n\t}\n\n\tprivate validate(): void {\n\t\tconst errors: string[] = [];\n\n\t\t// Validate PK columns exist when PK is defined\n\t\tfor (const table of this.tables.values()) {\n\t\t\tif (table.primaryKey) {\n\t\t\t\tconst pkCols = Array.isArray(table.primaryKey)\n\t\t\t\t\t? table.primaryKey\n\t\t\t\t\t: [table.primaryKey];\n\t\t\t\tfor (const pk of pkCols) {\n\t\t\t\t\tif (!table.columns.some((c) => c.name === pk)) {\n\t\t\t\t\t\terrors.push(\n\t\t\t\t\t\t\t`Table \"${table.name}\" primary key column \"${pk}\" not found in columns`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Validate all FK references point to existing tables\n\t\tfor (const table of this.tables.values()) {\n\t\t\tfor (const fk of table.foreignKeys) {\n\t\t\t\tif (!this.tables.has(fk.references.table)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Table \"${table.name}\" has FK referencing non-existent table \"${fk.references.table}\"`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Validate all relation targets exist\n\t\tfor (const relation of this.relations.values()) {\n\t\t\tif (!this.tables.has(relation.source)) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Relation \"${relation.name}\" has non-existent source table \"${relation.source}\"`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!this.tables.has(relation.target)) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Relation \"${relation.name}\" has non-existent target table \"${relation.target}\"`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (relation.through && !this.tables.has(relation.through)) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Relation \"${relation.name}\" has non-existent through table \"${relation.through}\"`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Detect circular relations (informational only, not an error)\n\t\t// Detection logic is retained but logging removed to avoid test pollution\n\t\tthis.detectCircularRelations();\n\n\t\tif (errors.length > 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`ModelIR validation failed:\\n${errors.map((e) => ` - ${e}`).join('\\n')}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate detectCircularRelations(): string[] {\n\t\tconst circular: string[] = [];\n\t\tconst visited = new Set<string>();\n\t\tconst recursionStack = new Set<string>();\n\n\t\tconst dfs = (table: string, path: string[]): void => {\n\t\t\tif (recursionStack.has(table)) {\n\t\t\t\tconst cycleStart = path.indexOf(table);\n\t\t\t\tconst cycle = [...path.slice(cycleStart), table].join(' -> ');\n\t\t\t\tcircular.push(cycle);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (visited.has(table)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvisited.add(table);\n\t\t\trecursionStack.add(table);\n\n\t\t\tconst relations = this.getRelationsFrom(table);\n\t\t\tfor (const relation of relations) {\n\t\t\t\tdfs(relation.target, [...path, table]);\n\t\t\t}\n\n\t\t\trecursionStack.delete(table);\n\t\t};\n\n\t\tfor (const tableName of this.tables.keys()) {\n\t\t\tdfs(tableName, []);\n\t\t}\n\n\t\treturn circular;\n\t}\n}\n","/**\n * E10: Injectable Logger\n *\n * Provides a pluggable logging interface for library code.\n * Default implementation uses console, but can be replaced for:\n * - Silent mode (testing, production)\n * - Custom logging frameworks (pino, winston, etc.)\n * - Structured logging\n */\n\n/**\n * Logger interface for dbsp library code.\n *\n * Only includes methods actually used by the library.\n * Extend as needed when new log levels are required.\n */\nexport interface Logger {\n\t/**\n\t * Log a warning message.\n\t * Used for: reserved word usage, raw SQL warnings, deprecation notices.\n\t */\n\twarn(message: string): void;\n}\n\n/**\n * Default logger that writes to console.\n * Used when no custom logger is provided.\n */\nexport const defaultLogger: Logger = {\n\twarn: (message: string) => console.warn(message),\n};\n\n/**\n * Silent logger that discards all messages.\n * Useful for testing or when warnings should be suppressed.\n */\nexport const silentLogger: Logger = {\n\twarn: () => {},\n};\n\n/**\n * Global logger instance.\n * Can be replaced via setLogger() for application-wide configuration.\n */\nlet globalLogger: Logger = defaultLogger;\n\n/**\n * Set the global logger instance.\n *\n * @param logger - Logger implementation to use globally\n *\n * @example\n * ```typescript\n * import { setLogger, silentLogger } from '@dbsp/core';\n *\n * // Silence all warnings in tests\n * setLogger(silentLogger);\n *\n * // Use custom logger\n * setLogger({\n * warn: (msg) => myLogger.warning('[dbsp]', msg),\n * });\n * ```\n */\nexport function setLogger(logger: Logger): void {\n\tglobalLogger = logger;\n}\n\n/**\n * Get the current global logger.\n * Internal use - prefer using getLogger() in library code.\n */\nexport function getLogger(): Logger {\n\treturn globalLogger;\n}\n\n/**\n * Reset logger to default (for testing).\n */\nexport function resetLogger(): void {\n\tglobalLogger = defaultLogger;\n}\n","/**\n * @fileoverview ES6 Symbols for type-safe query API metadata.\n *\n * These symbols are used as property keys in TableRef, ColumnRef, and RelationRef\n * to store metadata without colliding with user-defined column names.\n *\n * @example\n * ```typescript\n * import { TABLE_META, COLUMN_META } from './symbols';\n *\n * // Access table name from TableRef\n * const tableName = users[TABLE_META]; // 'users'\n *\n * // Access column name from ColumnRef\n * const columnName = users.id[COLUMN_META]; // 'id'\n * ```\n *\n * @module symbols\n * @since DX-040\n */\n\n/**\n * Symbol for accessing table name metadata from a TableRef.\n *\n * @description\n * Used internally to retrieve the table name from a TableRef object.\n * Uses `Symbol.for()` to create a global symbol that survives serialization\n * and can be accessed across module boundaries.\n *\n * @example\n * ```typescript\n * const { users } = schema.tables;\n * const tableName = users[TABLE_META]; // 'users'\n * ```\n */\nexport const TABLE_META: unique symbol = Symbol.for('dbsp:table');\n\n/**\n * Symbol for accessing column name metadata from a ColumnRef.\n *\n * @description\n * Used internally to retrieve the column name from a ColumnRef object.\n * Uses `Symbol.for()` for cross-module accessibility.\n *\n * @example\n * ```typescript\n * const { users } = schema.tables;\n * const columnName = users.id[COLUMN_META]; // 'id'\n * ```\n */\nexport const COLUMN_META: unique symbol = Symbol.for('dbsp:column');\n\n/**\n * Symbol for accessing relation metadata from a RelationRef.\n *\n * @description\n * Used internally to retrieve relation information (target table, relation type)\n * from a RelationRef object. Uses `Symbol.for()` for cross-module accessibility.\n *\n * @example\n * ```typescript\n * const { users } = schema.tables;\n * const relInfo = users.posts[RELATION_META];\n * // { target: 'posts', type: 'hasMany' }\n * ```\n */\nexport const RELATION_META: unique symbol = Symbol.for('dbsp:relation');\n\n/**\n * Symbol for type branding (internal use).\n *\n * @description\n * Used internally to distinguish between TableRef, ColumnRef, and RelationRef\n * at runtime. This enables type guards and runtime validation.\n * Uses `Symbol.for()` for cross-module accessibility.\n *\n * @example\n * ```typescript\n * function isTableRef(value: unknown): value is TableRef<any, any> {\n * return typeof value === 'object' && value !== null && BRAND in value\n * && (value as any)[BRAND] === 'TableRef';\n * }\n * ```\n */\nexport const BRAND: unique symbol = Symbol.for('dbsp:brand');\n\n/**\n * Symbol for tracking the relation path through which a column was accessed.\n *\n * @description\n * Used to enable cross-table queries. When a column is accessed through a relation\n * (e.g., `users.posts.published`), this symbol stores the relation path.\n * This allows the query builder to generate EXISTS subqueries automatically.\n * Uses `Symbol.for()` for cross-module accessibility.\n *\n * @example\n * ```typescript\n * const { users } = schema.tables;\n * const col = users.posts.published;\n * const path = col[RELATION_PATH]; // ['posts']\n * // Multiple hops: users.posts.comments.author\n * // path would be ['posts', 'comments']\n * ```\n */\nexport const RELATION_PATH: unique symbol = Symbol.for('dbsp:relationPath');\n\n/**\n * Type declarations for Symbol keys to enable TypeScript inference.\n *\n * These types allow TypeScript to understand the shape of objects\n * that use these symbols as keys.\n */\nexport type TableMetaKey = typeof TABLE_META;\nexport type ColumnMetaKey = typeof COLUMN_META;\nexport type RelationMetaKey = typeof RELATION_META;\nexport type BrandKey = typeof BRAND;\n\n// ============================================================================\n// Type Guards for Symbol-keyed Properties\n// ============================================================================\n\n/**\n * Type-safe check for the presence of a symbol-keyed property on an unknown value.\n *\n * Replaces `SYMBOL in (value as unknown as object)` casts throughout the DX layer.\n *\n * @param value - The value to check (any type)\n * @param sym - The symbol key to look for\n * @returns `true` if `value` is a non-null object containing `sym`\n *\n * @example\n * ```typescript\n * if (hasSymbolMeta(value, COLUMN_META)) {\n * // value is narrowed to Record<typeof COLUMN_META, unknown>\n * }\n * ```\n */\nexport function hasSymbolMeta<S extends symbol>(\n\tvalue: unknown,\n\tsym: S,\n): value is Record<S, unknown> {\n\treturn typeof value === 'object' && value !== null && sym in value;\n}\n","/**\n * @fileoverview Type-safe table and column reference types for the query API.\n *\n * This module defines the core reference types used in the type-safe query builder:\n * - `TableRef`: Reference to a table with typed columns and relations\n * - `ColumnRef`: Reference to a column with table, name, and TypeScript type\n * - `RelationRef`: Reference to a relation (FK-based join path)\n * - `AliasedColumn`: Column with an alias for result type inference\n * - `AllColumns`: Wildcard type for SELECT *\n *\n * These types use ES6 Symbols for internal metadata to avoid collision\n * with user-defined column names (see symbols.ts).\n *\n * @example\n * ```typescript\n * const { users } = schema.tables;\n *\n * // TableRef with columns\n * users.id // ColumnRef<'users', 'id', number>\n * users.name // ColumnRef<'users', 'name', string>\n * users['*'] // AllColumns<'users', {...}>\n *\n * // RelationRef for cross-table queries\n * users.posts // RelationRef<'posts', Post[], 'hasMany'>\n * users.posts.title // ColumnRef<'posts', 'title', string>\n * ```\n *\n * @module table-ref\n * @since DX-040\n */\n\nimport {\n\tBRAND,\n\tCOLUMN_META,\n\thasSymbolMeta,\n\tRELATION_META,\n\tRELATION_PATH,\n\tTABLE_META,\n} from './symbols.js';\n\n// Re-export symbols for convenience\nexport {\n\tBRAND,\n\tCOLUMN_META,\n\thasSymbolMeta,\n\tRELATION_META,\n\tRELATION_PATH,\n\tTABLE_META,\n};\n\n/**\n * Relation types supported by the ORM.\n */\nexport type RelationType = 'belongsTo' | 'hasMany' | 'hasOne';\n\n/**\n * Base interface for ColumnRef metadata (using Symbols).\n * @internal\n */\ninterface ColumnRefBase<TTable extends string, TColumn extends string, TType> {\n\t/** @internal Table name metadata (via Symbol) */\n\treadonly [TABLE_META]: TTable;\n\n\t/** @internal Column name metadata (via Symbol) */\n\treadonly [COLUMN_META]: TColumn;\n\n\t/** @internal Type brand for runtime identification */\n\treadonly [BRAND]: 'ColumnRef';\n\n\t/**\n\t * Phantom type for TypeScript inference.\n\t * @internal Not used at runtime - only for type inference.\n\t */\n\treadonly _type: TType;\n}\n\n/**\n * Reference to a column in a table.\n *\n * @typeParam TTable - The table name as a string literal type (e.g., 'users')\n * @typeParam TColumn - The column name as a string literal type (e.g., 'id')\n * @typeParam TType - The TypeScript type of the column value (e.g., number, string)\n *\n * @description\n * ColumnRef carries type information for compile-time inference while also\n * containing runtime metadata accessible via Symbols. The `_type` property\n * is a phantom type (never instantiated at runtime) used for inference.\n *\n * @example\n * ```typescript\n * // users.id is ColumnRef<'users', 'id', number>\n * const id: ColumnRef<'users', 'id', number>;\n *\n * // Access metadata (rarely needed by users)\n * id[TABLE_META] // 'users'\n * id[COLUMN_META] // 'id'\n *\n * // Create alias for result type\n * id.as('userId') // AliasedColumn<'users', 'id', number, 'userId'>\n * ```\n */\nexport type ColumnRef<\n\tTTable extends string,\n\tTColumn extends string,\n\tTType,\n> = ColumnRefBase<TTable, TColumn, TType> & {\n\t/**\n\t * Create an aliased version of this column for result type inference.\n\t *\n\t * @typeParam TAlias - The alias name as a string literal type\n\t * @param alias - Must match `/^[a-zA-Z_][a-zA-Z0-9_]*$/` (validated at runtime)\n\t * @returns AliasedColumn with the specified alias\n\t * @throws Error if alias doesn't match the valid identifier pattern\n\t *\n\t * @example\n\t * ```typescript\n\t * users.id.as('userId')\n\t * // Result type will use 'userId' instead of 'id'\n\t * ```\n\t */\n\tas<TAlias extends string>(\n\t\talias: TAlias,\n\t): AliasedColumn<TTable, TColumn, TType, TAlias>;\n};\n\n/**\n * Column with an alias for result type inference.\n *\n * @typeParam TTable - The source table name\n * @typeParam TColumn - The source column name\n * @typeParam TType - The TypeScript type of the column value\n * @typeParam TAlias - The alias name that will appear in query results\n *\n * @description\n * Extends ColumnRef with an `_alias` property. When used in a query,\n * the result type will use the alias instead of the original column name.\n *\n * @example\n * ```typescript\n * const query = orm.from(users)\n * .select(users.id.as('userId'))\n * .all();\n * // Result type: { userId: number }[]\n * ```\n */\nexport type AliasedColumn<\n\tTTable extends string,\n\tTColumn extends string,\n\tTType,\n\tTAlias extends string,\n> = ColumnRef<TTable, TColumn, TType> & {\n\t/**\n\t * The alias name for this column.\n\t * Used to determine the property name in query results.\n\t */\n\treadonly _alias: TAlias;\n};\n\n/**\n * Represents all columns from a table for SELECT * operations.\n *\n * @typeParam TTable - The table name\n * @typeParam TColumns - Record mapping column names to their TypeScript types\n *\n * @description\n * Used when accessing the wildcard property `table['*']`.\n * When used in a query, selects all columns from the table.\n *\n * @example\n * ```typescript\n * orm.from(users).select(users['*']).all()\n * // SQL: SELECT * FROM users\n * // Result type: User[]\n * ```\n */\nexport interface AllColumns<\n\tTTable extends string,\n\tTColumns extends Record<string, unknown>,\n> {\n\t/** @internal Type brand for runtime identification */\n\treadonly [BRAND]: 'AllColumns';\n\n\t/** @internal Table name metadata */\n\treadonly [TABLE_META]: TTable;\n\n\t/**\n\t * Phantom type containing all column types.\n\t * @internal Used for result type inference.\n\t */\n\treadonly _columns: TColumns;\n}\n\n/**\n * Base interface for RelationRef metadata (using Symbols).\n * @internal\n */\ninterface RelationRefBase<\n\tTTarget extends string,\n\tTTargetType,\n\tTRelationType extends RelationType,\n> {\n\t/** @internal Relation metadata containing target and type */\n\treadonly [RELATION_META]: { target: TTarget; type: TRelationType };\n\n\t/** @internal Type brand for runtime identification */\n\treadonly [BRAND]: 'RelationRef';\n\n\t/**\n\t * Phantom type for the related records.\n\t * @internal Used for result type inference with include().\n\t */\n\treadonly _type: TTargetType;\n}\n\n/**\n * Reference to a relation (FK-based join path).\n *\n * @typeParam TTarget - The target table name (e.g., 'posts')\n * @typeParam TTargetType - The TypeScript type of related records (e.g., Post[])\n * @typeParam TRelationType - The relation type: 'belongsTo' | 'hasMany' | 'hasOne'\n * @typeParam TTargetColumns - Record mapping target column names to their types\n *\n * @description\n * RelationRef enables cross-table queries by allowing access to columns\n * from related tables. It also supports the wildcard `'*'` for selecting\n * all columns from the related table.\n *\n * @example\n * ```typescript\n * // users.posts is RelationRef<'posts', Post[], 'hasMany'>\n *\n * // Access related table's columns\n * users.posts.title // ColumnRef<'posts', 'title', string>\n * users.posts['*'] // AllColumns<'posts', {...}>\n *\n * // Use in cross-table queries\n * orm.from(users).where(eq(users.posts.published, true))\n * // Generates EXISTS subquery\n * ```\n */\nexport type RelationRef<\n\tTTarget extends string,\n\tTTargetType,\n\tTRelationType extends RelationType,\n\tTTargetColumns extends Record<string, unknown> = Record<string, unknown>,\n> = RelationRefBase<TTarget, TTargetType, TRelationType> & {\n\t/**\n\t * Access columns through relation (for cross-table queries).\n\t */\n\treadonly [K in keyof TTargetColumns]: ColumnRef<\n\t\tTTarget,\n\t\tK & string,\n\t\tTTargetColumns[K]\n\t>;\n} & {\n\t/**\n\t * Wildcard for selecting all columns from the related table.\n\t *\n\t * @example\n\t * ```typescript\n\t * users.posts['*'] // AllColumns<'posts', {...}>\n\t * ```\n\t */\n\treadonly '*': AllColumns<TTarget, TTargetColumns>;\n};\n\n/**\n * Base interface for TableRef metadata (using Symbols).\n * @internal\n */\ninterface TableRefBase<TName extends string> {\n\t/** @internal Table name metadata (via Symbol) */\n\treadonly [TABLE_META]: TName;\n\n\t/** @internal Type brand for runtime identification */\n\treadonly [BRAND]: 'TableRef';\n}\n\n/**\n * Reference to a table in the schema.\n *\n * @typeParam TName - The table name as a string literal type (e.g., 'users')\n * @typeParam TColumns - Record mapping column names to ColumnRef types\n * @typeParam TRelations - Record mapping relation names to RelationRef types\n *\n * @description\n * TableRef is the primary type for type-safe queries. It provides:\n * - Access to all columns as ColumnRef properties\n * - Access to all relations as RelationRef properties\n * - A `'*'` wildcard for SELECT * operations\n * - Internal metadata via Symbols (no collision with user columns)\n *\n * TableRef objects are created by the schema builder and accessed via\n * `schema.tables.tableName`.\n *\n * @example\n * ```typescript\n * const { users, posts } = schema.tables;\n *\n * // Access columns\n * users.id // ColumnRef<'users', 'id', number>\n * users.name // ColumnRef<'users', 'name', string>\n *\n * // Access relations\n * users.posts // RelationRef<'posts', Post[], 'hasMany'>\n *\n * // Wildcard\n * users['*'] // AllColumns<'users', {...}>\n *\n * // Internal metadata (rarely needed)\n * users[TABLE_META] // 'users'\n * ```\n */\nexport type TableRef<\n\tTName extends string,\n\tTColumns extends Record<string, ColumnRef<TName, string, unknown>>,\n\tTRelations extends Record<\n\t\tstring,\n\t\tRelationRef<string, unknown, RelationType>\n\t> = Record<never, never>,\n> = TableRefBase<TName> & {\n\t/**\n\t * All columns as ColumnRef properties.\n\t */\n\treadonly [K in keyof TColumns]: TColumns[K];\n} & {\n\t/**\n\t * All relations as RelationRef properties (excluding column name conflicts).\n\t */\n\treadonly [K in keyof TRelations as K extends keyof TColumns\n\t\t? never\n\t\t: K]: TRelations[K];\n} & {\n\t/**\n\t * Wildcard for SELECT * operations.\n\t * The `'*'` character is never a valid SQL identifier, preventing collisions.\n\t *\n\t * @example\n\t * ```typescript\n\t * orm.from(users).select(users['*']).all()\n\t * // SQL: SELECT * FROM users\n\t * ```\n\t */\n\treadonly '*': AllColumns<TName, InferColumnTypes<TColumns>>;\n};\n\n/**\n * Helper type to extract column types from a TColumns record.\n *\n * @typeParam TColumns - Record of column names to ColumnRef types\n * @returns Record mapping column names to their TypeScript types\n *\n * @internal\n */\nexport type InferColumnTypes<\n\tTColumns extends Record<string, ColumnRef<string, string, unknown>>,\n> = {\n\t[K in keyof TColumns]: TColumns[K] extends ColumnRef<string, string, infer T>\n\t\t? T\n\t\t: never;\n};\n\n/**\n * Helper type to infer the row type from a TableRef.\n *\n * @typeParam T - A TableRef type\n * @returns The TypeScript type representing a single row from the table\n *\n * @example\n * ```typescript\n * type UserRow = InferTableRow<typeof users>;\n * // { id: number; name: string; email: string }\n * ```\n */\nexport type InferTableRow<T> =\n\tT extends TableRef<string, infer TColumns, infer _TRelations>\n\t\t? InferColumnTypes<TColumns>\n\t\t: never;\n\n/**\n * Type guard to check if a value is a TableRef.\n *\n * @param value - The value to check\n * @returns True if the value is a TableRef\n *\n * @example\n * ```typescript\n * if (isTableRef(value)) {\n * const tableName = value[TABLE_META];\n * }\n * ```\n */\nexport function isTableRef(\n\tvalue: unknown,\n): value is TableRef<\n\tstring,\n\tRecord<string, ColumnRef<string, string, unknown>>\n> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tBRAND in value &&\n\t\t(value as Record<symbol, unknown>)[BRAND] === 'TableRef'\n\t);\n}\n\n/**\n * Type guard to check if a value is a ColumnRef.\n *\n * @param value - The value to check\n * @returns True if the value is a ColumnRef\n *\n * @example\n * ```typescript\n * if (isColumnRef(value)) {\n * const columnName = value[COLUMN_META];\n * }\n * ```\n */\nexport function isColumnRef(\n\tvalue: unknown,\n): value is ColumnRef<string, string, unknown> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tBRAND in value &&\n\t\t(value as Record<symbol, unknown>)[BRAND] === 'ColumnRef'\n\t);\n}\n\n/**\n * Type guard to check if a value is a RelationRef.\n *\n * @param value - The value to check\n * @returns True if the value is a RelationRef\n *\n * @example\n * ```typescript\n * if (isRelationRef(value)) {\n * const relInfo = value[RELATION_META];\n * }\n * ```\n */\nexport function isRelationRef(\n\tvalue: unknown,\n): value is RelationRef<string, unknown, RelationType> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tBRAND in value &&\n\t\t(value as Record<symbol, unknown>)[BRAND] === 'RelationRef'\n\t);\n}\n\n/**\n * Type guard to check if a value is an AllColumns.\n *\n * @param value - The value to check\n * @returns True if the value is an AllColumns\n *\n * @example\n * ```typescript\n * if (isAllColumns(value)) {\n * const tableName = value[TABLE_META];\n * }\n * ```\n */\nexport function isAllColumns(\n\tvalue: unknown,\n): value is AllColumns<string, Record<string, unknown>> {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tBRAND in value &&\n\t\t(value as Record<symbol, unknown>)[BRAND] === 'AllColumns'\n\t);\n}\n\n/**\n * Type guard to check if a value is an AliasedColumn.\n *\n * @param value - The value to check\n * @returns True if the value is an AliasedColumn\n */\nexport function isAliasedColumn(\n\tvalue: unknown,\n): value is AliasedColumn<string, string, unknown, string> {\n\treturn isColumnRef(value) && '_alias' in value;\n}\n","/**\n * @fileoverview Runtime factory for creating TableRef, ColumnRef, and RelationRef objects.\n *\n * This module creates the runtime representations of the type-safe table references.\n * It uses ES6 Symbols for metadata and Proxies for lazy property access.\n *\n * @module table-ref-factory\n * @since DX-040\n */\n\nimport type { ModelIR } from '../model-ir.js';\nimport { getLogger } from './logger.js';\nimport {\n\tBRAND,\n\tCOLUMN_META,\n\tRELATION_META,\n\tRELATION_PATH,\n\ttype RelationType,\n\tTABLE_META,\n} from './table-ref.js';\n\n// ============================================================================\n// JS Reserved Words (H-03)\n// ============================================================================\n\n/**\n * JavaScript reserved words and built-in properties that might conflict\n * with column names. When accessed, these are intercepted by the Proxy\n * and a warning is logged.\n */\nconst JS_RESERVED_WORDS = new Set([\n\t// Object built-ins\n\t'constructor',\n\t'prototype',\n\t'__proto__',\n\t'hasOwnProperty',\n\t'isPrototypeOf',\n\t'propertyIsEnumerable',\n\t'toLocaleString',\n\t'toString',\n\t'valueOf',\n\t// Function built-ins\n\t'arguments',\n\t'caller',\n\t'callee',\n\t'length',\n\t'name',\n\t// Common JS keywords used as identifiers\n\t'class',\n\t'default',\n\t'delete',\n\t'export',\n\t'extends',\n\t'import',\n\t'new',\n\t'return',\n\t'super',\n\t'switch',\n\t'this',\n\t'throw',\n\t'typeof',\n]);\n\n/**\n * Log a warning when a reserved word is used as a column name.\n * This is ERR-05 from the spec.\n */\nfunction warnReservedWord(tableName: string, columnName: string): void {\n\tgetLogger().warn(\n\t\t`[dbsp] Warning: Column \"${columnName}\" in table \"${tableName}\" is a JavaScript reserved word. ` +\n\t\t\t`Access it via bracket notation: table['${columnName}']`,\n\t);\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Create a ColumnRef object with Symbol metadata.\n *\n * @param tableName - The table name\n * @param columnName - The column name\n * @param relationPath - Optional relation path for cross-table queries (DX-040 Block 7)\n * @returns A ColumnRef-like object with Symbol properties\n */\nexport function createColumnRef(\n\ttableName: string,\n\tcolumnName: string,\n\trelationPath?: readonly string[],\n): object {\n\tconst columnRef: Record<symbol | string, unknown> = {\n\t\t[TABLE_META]: tableName,\n\t\t[COLUMN_META]: columnName,\n\t\t[BRAND]: 'ColumnRef' as const,\n\t\t_type: undefined as unknown, // Phantom type placeholder\n\t\tas(alias: string) {\n\t\t\t// Validate alias (ERR-04)\n\t\t\tif (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(alias)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid alias \"${alias}\": must match /^[a-zA-Z_][a-zA-Z0-9_]*$/`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\t...this,\n\t\t\t\t_alias: alias,\n\t\t\t};\n\t\t},\n\t};\n\n\t// Add relation path if provided (for cross-table queries)\n\tif (relationPath && relationPath.length > 0) {\n\t\tcolumnRef[RELATION_PATH] = relationPath;\n\t}\n\n\treturn columnRef;\n}\n\n/**\n * Create an AllColumns object for SELECT * operations.\n *\n * @param tableName - The table name\n * @returns An AllColumns-like object\n */\nexport function createAllColumns(tableName: string): object {\n\treturn {\n\t\t[TABLE_META]: tableName,\n\t\t[BRAND]: 'AllColumns' as const,\n\t\t_columns: {}, // Phantom type placeholder\n\t};\n}\n\n/**\n * Map ModelIR RelationType to table-ref RelationType.\n */\nfunction mapRelationType(modelRelationType: string): RelationType {\n\tswitch (modelRelationType) {\n\t\tcase 'belongsTo':\n\t\t\treturn 'belongsTo';\n\t\tcase 'hasMany':\n\t\tcase 'belongsToMany':\n\t\t\treturn 'hasMany';\n\t\tcase 'hasOne':\n\t\t\treturn 'hasOne';\n\t\tdefault:\n\t\t\treturn 'hasMany'; // Default fallback\n\t}\n}\n\n/**\n * Helper to check if a column exists in a table.\n */\nfunction hasColumn(\n\tcolumns: readonly { name: string }[],\n\tcolumnName: string,\n): boolean {\n\treturn columns.some((col) => col.name === columnName);\n}\n\n/**\n * Helper to get column names from a table.\n */\nfunction getColumnNames(columns: readonly { name: string }[]): string[] {\n\treturn columns.map((col) => col.name);\n}\n\n/**\n * Create a RelationRef object with column access via Proxy.\n *\n * @param targetTable - The target table name\n * @param relationType - The relation type (belongsTo, hasMany, hasOne)\n * @param model - The ModelIR for looking up target table columns\n * @param relationName - The name of the relation (for building relation path)\n * @param parentPath - The parent relation path (for chained relations like users.posts.comments)\n * @returns A RelationRef-like object with Proxy for column access\n */\nexport function createRelationRef(\n\ttargetTable: string,\n\trelationType: RelationType,\n\tmodel: ModelIR,\n\trelationName?: string,\n\tparentPath?: readonly string[],\n): object {\n\t// Build the current relation path\n\tconst currentPath: readonly string[] =\n\t\trelationName !== undefined\n\t\t\t? [...(parentPath ?? []), relationName]\n\t\t\t: (parentPath ?? []);\n\n\tconst base = {\n\t\t[RELATION_META]: { target: targetTable, type: relationType },\n\t\t[BRAND]: 'RelationRef' as const,\n\t\t[RELATION_PATH]: currentPath, // Store path on RelationRef too\n\t\t_type: undefined as unknown, // Phantom type placeholder\n\t};\n\n\t// Use Proxy for lazy column access on the relation\n\treturn new Proxy(base, {\n\t\tget(target, prop, receiver) {\n\t\t\t// Handle Symbol properties\n\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\t// Handle '*' wildcard\n\t\t\tif (prop === '*') {\n\t\t\t\treturn createAllColumns(targetTable);\n\t\t\t}\n\n\t\t\t// Handle built-in properties\n\t\t\tif (prop in target) {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\t// Check if this is a column in the target table\n\t\t\tconst targetTableIR = model.getTable(targetTable);\n\t\t\tif (targetTableIR && hasColumn(targetTableIR.columns, prop as string)) {\n\t\t\t\t// Pass the relation path for cross-table query support\n\t\t\t\treturn createColumnRef(targetTable, prop as string, currentPath);\n\t\t\t}\n\n\t\t\t// Check if this is a relation from the target table (chained relations)\n\t\t\tfor (const rel of model.getRelationsFrom(targetTable)) {\n\t\t\t\tif (rel.name === prop) {\n\t\t\t\t\treturn createRelationRef(\n\t\t\t\t\t\trel.target,\n\t\t\t\t\t\tmapRelationType(rel.type),\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tprop as string,\n\t\t\t\t\t\tcurrentPath,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check inverse relations\n\t\t\tfor (const rel of model.getRelationsTo(targetTable)) {\n\t\t\t\tif (rel.source === prop) {\n\t\t\t\t\treturn createRelationRef(\n\t\t\t\t\t\trel.source,\n\t\t\t\t\t\t'hasMany',\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tprop as string,\n\t\t\t\t\t\tcurrentPath,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Return undefined for non-existent properties\n\t\t\treturn undefined;\n\t\t},\n\t\thas(target, prop) {\n\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\treturn prop in target;\n\t\t\t}\n\t\t\tif (prop === '*') {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tconst targetTableIR = model.getTable(targetTable);\n\t\t\treturn (\n\t\t\t\tprop in target ||\n\t\t\t\t(targetTableIR !== undefined &&\n\t\t\t\t\thasColumn(targetTableIR.columns, prop as string))\n\t\t\t);\n\t\t},\n\t\townKeys(target) {\n\t\t\tconst targetTableIR = model.getTable(targetTable);\n\t\t\tconst columnNames = targetTableIR\n\t\t\t\t? getColumnNames(targetTableIR.columns)\n\t\t\t\t: [];\n\t\t\treturn [...Reflect.ownKeys(target), '*', ...columnNames];\n\t\t},\n\t\tgetOwnPropertyDescriptor(target, prop) {\n\t\t\tconst self = this as ProxyHandler<typeof base>;\n\t\t\tif (\n\t\t\t\tprop === '*' ||\n\t\t\t\t(typeof prop === 'string' && self.has?.(target, prop))\n\t\t\t) {\n\t\t\t\treturn {\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tvalue: self.get?.(target, prop, target),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn Reflect.getOwnPropertyDescriptor(target, prop);\n\t\t},\n\t});\n}\n\n/**\n * Create a TableRef object with columns and relations via Proxy.\n *\n * @param tableName - The table name\n * @param model - The ModelIR containing table and relation information\n * @returns A TableRef-like object with Proxy for lazy property access\n */\nexport function createTableRef(tableName: string, model: ModelIR): object {\n\tconst tableIR = model.getTable(tableName);\n\tif (!tableIR) {\n\t\tthrow new Error(`Table \"${tableName}\" not found in model`);\n\t}\n\n\tconst base = {\n\t\t[TABLE_META]: tableName,\n\t\t[BRAND]: 'TableRef' as const,\n\t};\n\n\t// Build relations map: relation name -> { targetTable, relationType }\n\t// Include both direct relations (from this table) and inverse relations (to this table)\n\tconst relations = new Map<string, { target: string; type: RelationType }>();\n\n\t// Direct relations (belongsTo) - where this table is the source\n\tfor (const relation of model.getRelationsFrom(tableName)) {\n\t\tconst relationType = mapRelationType(relation.type);\n\t\trelations.set(relation.name, {\n\t\t\ttarget: relation.target,\n\t\t\ttype: relationType,\n\t\t});\n\t}\n\n\t// Inverse relations (hasMany/hasOne) - where this table is the target\n\tfor (const relation of model.getRelationsTo(tableName)) {\n\t\t// Skip if the relation is from this table to itself (would be handled above)\n\t\tif (relation.source === tableName) continue;\n\n\t\t// Derive inverse relation name: use explicit inverse option or default to source table name\n\t\t// The inverse name should be on the relation itself if specified\n\t\tconst inverseName = relation.source; // Default: source table name (e.g., 'posts')\n\n\t\t// Only add if not already present (direct relations take precedence)\n\t\tif (!relations.has(inverseName)) {\n\t\t\t// Inverse of belongsTo is hasMany (or hasOne if the FK is unique, but we default to hasMany)\n\t\t\trelations.set(inverseName, { target: relation.source, type: 'hasMany' });\n\t\t}\n\t}\n\n\t// Track which reserved words have been warned about\n\tconst warnedReservedWords = new Set<string>();\n\n\treturn new Proxy(base, {\n\t\tget(target, prop, receiver) {\n\t\t\t// Handle Symbol properties\n\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\t// Handle '*' wildcard (H-02)\n\t\t\tif (prop === '*') {\n\t\t\t\treturn createAllColumns(tableName);\n\t\t\t}\n\n\t\t\t// Handle built-in properties\n\t\t\tif (prop in target) {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\tconst propStr = prop as string;\n\n\t\t\t// Check for JS reserved words (H-03, ERR-05)\n\t\t\tif (JS_RESERVED_WORDS.has(propStr)) {\n\t\t\t\t// Check if it's actually a column\n\t\t\t\tif (hasColumn(tableIR.columns, propStr)) {\n\t\t\t\t\tif (!warnedReservedWords.has(propStr)) {\n\t\t\t\t\t\twarnReservedWord(tableName, propStr);\n\t\t\t\t\t\twarnedReservedWords.add(propStr);\n\t\t\t\t\t}\n\t\t\t\t\treturn createColumnRef(tableName, propStr);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if this is a column\n\t\t\tif (hasColumn(tableIR.columns, propStr)) {\n\t\t\t\treturn createColumnRef(tableName, propStr);\n\t\t\t}\n\n\t\t\t// Check if this is a relation\n\t\t\tconst relation = relations.get(propStr);\n\t\t\tif (relation) {\n\t\t\t\t// Pass relation name for building relation path (DX-040 Block 7)\n\t\t\t\treturn createRelationRef(\n\t\t\t\t\trelation.target,\n\t\t\t\t\trelation.type,\n\t\t\t\t\tmodel,\n\t\t\t\t\tpropStr,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Return undefined for non-existent properties\n\t\t\treturn undefined;\n\t\t},\n\t\thas(target, prop) {\n\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\treturn prop in target;\n\t\t\t}\n\t\t\tif (prop === '*') {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tconst propStr = prop as string;\n\t\t\treturn (\n\t\t\t\tprop in target ||\n\t\t\t\thasColumn(tableIR.columns, propStr) ||\n\t\t\t\trelations.has(propStr)\n\t\t\t);\n\t\t},\n\t\townKeys(target) {\n\t\t\tconst columnNames = getColumnNames(tableIR.columns);\n\t\t\tconst relationNames = Array.from(relations.keys());\n\t\t\treturn [\n\t\t\t\t...Reflect.ownKeys(target),\n\t\t\t\t'*',\n\t\t\t\t...columnNames,\n\t\t\t\t...relationNames,\n\t\t\t];\n\t\t},\n\t\tgetOwnPropertyDescriptor(target, prop) {\n\t\t\tconst self = this as ProxyHandler<typeof base>;\n\t\t\tif (\n\t\t\t\tprop === '*' ||\n\t\t\t\t(typeof prop === 'string' && self.has?.(target, prop))\n\t\t\t) {\n\t\t\t\treturn {\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tvalue: self.get?.(target, prop, target),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn Reflect.getOwnPropertyDescriptor(target, prop);\n\t\t},\n\t});\n}\n\n/**\n * Create the tables Proxy for a schema.\n *\n * This is the main entry point that creates a Proxy which lazily\n * instantiates TableRef objects when tables are accessed.\n *\n * @param model - The ModelIR containing all table and relation information\n * @param tableNames - List of table names in the schema\n * @returns A Proxy that returns TableRef objects for each table\n */\nexport function createTablesProxy(\n\tmodel: ModelIR,\n\ttableNames: string[],\n): object {\n\tconst tableSet = new Set(tableNames);\n\tconst cache = new Map<string, object>();\n\n\treturn new Proxy(\n\t\t{},\n\t\t{\n\t\t\tget(_target, prop) {\n\t\t\t\t// Handle Symbol properties\n\t\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\n\t\t\t\tconst propStr = prop as string;\n\n\t\t\t\t// Return cached TableRef if exists\n\t\t\t\tif (cache.has(propStr)) {\n\t\t\t\t\treturn cache.get(propStr);\n\t\t\t\t}\n\n\t\t\t\t// Create TableRef if this is a valid table\n\t\t\t\tif (tableSet.has(propStr)) {\n\t\t\t\t\tconst tableRef = createTableRef(propStr, model);\n\t\t\t\t\tcache.set(propStr, tableRef);\n\t\t\t\t\treturn tableRef;\n\t\t\t\t}\n\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t\thas(_target, prop) {\n\t\t\t\tif (typeof prop === 'symbol') {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\treturn tableSet.has(prop as string);\n\t\t\t},\n\t\t\townKeys() {\n\t\t\t\treturn tableNames;\n\t\t\t},\n\t\t\tgetOwnPropertyDescriptor(_target, prop) {\n\t\t\t\tif (typeof prop === 'string' && tableSet.has(prop)) {\n\t\t\t\t\t// Get or create the TableRef\n\t\t\t\t\tlet tableRef = cache.get(prop);\n\t\t\t\t\tif (!tableRef) {\n\t\t\t\t\t\ttableRef = createTableRef(prop, model);\n\t\t\t\t\t\tcache.set(prop, tableRef);\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tconfigurable: true,\n\t\t\t\t\t\tenumerable: true,\n\t\t\t\t\t\tvalue: tableRef,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t},\n\t\t},\n\t);\n}\n","/**\n * ARCH-005: Unified Schema API\n *\n * Replaces defineSchema(), TypedSchema, and GeneratedSchema with a single\n * schema() + ref() API. Relations are auto-inferred from FK declarations.\n *\n * @example\n * ```typescript\n * import { schema, ref } from '@dbsp/core';\n *\n * const db = schema({\n * users: { id: 'uuid', email: { type: 'text', unique: true } },\n * posts: { id: 'uuid', authorId: ref('users') },\n * });\n * ```\n */\n\nimport type { WhereIntent } from '@dbsp/types';\nimport type { Mutable } from '@dbsp/types/internal';\nimport type { DbCasing } from '../adapter.js';\nimport { ModelIRImpl } from '../model-impl.js';\nimport type {\n\tCheckConstraintIR,\n\tColumnIR,\n\tColumnType,\n\tForeignKeyIR,\n\tIndexIR,\n\tModelIR,\n\tOnDeleteAction,\n\tPseudoColumnMetadata,\n\tRelationIR,\n\tRelationType,\n\tTableIR,\n} from '../model-ir.js';\nimport { createPseudoColumnMetadata } from '../model-ir.js';\nimport type { InferTables } from './schema-tables-types.js';\nimport { createTablesProxy } from './table-ref-factory.js';\n\n// ============================================================================\n// Public Types\n// ============================================================================\n\n/**\n * Supported column types in schema definitions.\n * Maps to ColumnType from ModelIR.\n */\nexport type SchemaColumnType = ColumnType;\n\n/**\n * Column definition - short form (just type) or long form (with options).\n */\nexport type ColumnDef =\n\t| SchemaColumnType\n\t| {\n\t\t\ttype: SchemaColumnType;\n\t\t\tdbType?: string;\n\t\t\tnullable?: boolean;\n\t\t\tunique?: boolean;\n\t\t\tprimaryKey?: boolean;\n\t\t\tautoIncrement?: boolean;\n\t\t\tdefault?: unknown;\n\t\t\tindex?: boolean;\n\t };\n\n/**\n * Self-referential relation role names.\n * Required when declaring a ref() to the same table.\n */\nexport interface SelfRefRoles {\n\t/** Name for the direct parent relation (e.g., 'parent', 'manager') */\n\tparent: string;\n\t/** Name for the direct children relation (e.g., 'children', 'directReports') */\n\tchildren: string;\n\t/** Name for recursive ancestors (default: 'ancestors') */\n\tancestors?: string;\n\t/** Name for recursive descendants (default: 'descendants') */\n\tdescendants?: string;\n}\n\n/**\n * Options for ref() foreign key declarations.\n */\nexport interface RefOptions {\n\t// FK column constraints\n\t/** Is this FK nullable? → optional relation */\n\tnullable?: boolean;\n\t/** Is this FK unique? → 1:1 instead of 1:N */\n\tunique?: boolean;\n\n\t// FK behavior\n\t/** ON DELETE action */\n\tonDelete?: OnDeleteAction;\n\t/** ON UPDATE action */\n\tonUpdate?: 'CASCADE' | 'SET NULL' | 'RESTRICT' | 'NO ACTION';\n\n\t// Relation naming\n\t/** Local relation name (e.g., 'createdBy' for createdById column) */\n\tas?: string;\n\t/** Inverse relation name on target table (e.g., 'writings' instead of 'author_posts') */\n\tinverse?: string;\n\n\t// Self-ref only (MANDATORY when source === target)\n\t/** Role names for self-referential relations */\n\troles?: SelfRefRoles;\n\n\t/**\n\t * Source columns forming a composite FK (table-level `foreignKeys` only).\n\t */\n\tcolumns?: readonly string[];\n\n\t/**\n\t * Target columns the FK references.\n\t * - For column-level `ref()`: the target column on the referenced\n\t * table. Defaults to `['id']` by convention; the actual target\n\t * PK column is not auto-resolved. Length must be exactly 1.\n\t * - For table-level composite FKs: the list of target columns.\n\t */\n\treferences?: readonly string[];\n}\n\n/**\n * Marker type for ref() declarations in schema.\n * Generic over target and options to preserve literal types for inference.\n * @internal\n */\nexport interface RefDefinition<\n\tTTarget extends string = string,\n\tTOptions extends RefOptions = RefOptions,\n> {\n\treadonly __brand: 'ref';\n\treadonly target: TTarget;\n\treadonly options: TOptions;\n}\n\n/**\n * Table definition - a record of column names to column or ref definitions.\n */\nexport type TableDef = Record<string, ColumnDef | RefDefinition>;\n\n/**\n * Schema definition - a record of table names to table definitions.\n */\nexport type SchemaDefinition = Record<string, TableDef>;\n\n/**\n * Table-level constraints for composite indexes and foreign keys.\n * Used as the 2nd argument to schema() for constraints that span multiple columns.\n *\n * @example\n * ```typescript\n * schema({\n * orderItems: {\n * orderId: 'uuid',\n * productId: 'uuid',\n * quantity: 'integer',\n * },\n * }, {\n * orderItems: {\n * indexes: [\n * { columns: ['orderId', 'productId'], unique: true },\n * ],\n * foreignKeys: [\n * ref('orders', { columns: ['orderId', 'productId'], references: ['orderId', 'productId'] }),\n * ],\n * },\n * });\n * ```\n */\nexport interface SchemaIndexOptions {\n\t/** Columns included in the index */\n\tcolumns: string[];\n\t/** Whether this is a unique index */\n\tunique?: boolean;\n\t/** Custom index name (auto-generated if not provided) */\n\tname?: string;\n\t/** Index access method (default: btree). E.g. 'gin', 'gist', 'hnsw', 'bm25' */\n\tmethod?: string;\n\t/** Partial index predicate (WHERE clause) */\n\twhere?: string;\n\t/** Per-column operator class overrides. Key = column name, value = opclass name */\n\topclass?: Record<string, string>;\n\t/** Index storage parameters (WITH clause). Key = param name, value = param value */\n\twith?: Record<string, string>;\n}\n\nexport interface SchemaTableOptions {\n\t/** Indexes for this table (simple, composite, partial, GIN, HNSW, BM25, etc.) */\n\tindexes?: SchemaIndexOptions[];\n\t/** CHECK constraints for this table */\n\tcheckConstraints?: Array<{\n\t\tname: string;\n\t\texpression: string;\n\t}>;\n\t/** Composite foreign keys for this table (use ref() with columns/references) */\n\tforeignKeys?: RefDefinition[];\n}\n\n/**\n * Per-table constraint options, keyed by table name.\n */\nexport type SchemaConstraints = Record<string, SchemaTableOptions>;\n\n/**\n * Top-level schema-wide DDL objects: extensions, sequences.\n */\nexport interface SchemaExtras {\n\t/** PostgreSQL extensions to ensure (CREATE EXTENSION IF NOT EXISTS \"name\") */\n\textensions?: string[];\n\t/** Sequences to create (CREATE SEQUENCE). Key = sequence name */\n\tsequences?: Record<\n\t\tstring,\n\t\t{\n\t\t\tstartWith?: number;\n\t\t\tincrementBy?: number;\n\t\t\tminValue?: number;\n\t\t\tmaxValue?: number;\n\t\t\tcycle?: boolean;\n\t\t}\n\t>;\n}\n\n/**\n * Result of schema() function with strongly-typed table/column info.\n */\n/**\n * Per-table default filters applied to all queries.\n * Commonly used for soft delete filtering.\n *\n * @example\n * ```typescript\n * import { isNull } from '@dbsp/core';\n *\n * const db = schema(tables, undefined, {\n * defaultFilters: {\n * products: isNull('deletedAt'),\n * users: isNull('deletedAt'),\n * },\n * });\n * ```\n */\nexport type DefaultFilters = Record<string, WhereIntent>;\n\n/**\n * Options for schema() function.\n */\nexport interface SchemaOptions {\n\t/**\n\t * Default filters applied automatically to all queries per table.\n\t * Override with `.withoutDefaultFilters()` on the query builder.\n\t */\n\tdefaultFilters?: DefaultFilters;\n\t/**\n\t * Column name treated as the implicit primary key for short-form column\n\t * declarations. When set (default `'id'`), `inferPrimaryKey` resolves the\n\t * implicit PK BEFORE falling back to FK columns: a column matching this name\n\t * is treated as the PK whenever no explicit `primaryKey: true` flag is present\n\t * on any column — regardless of whether the table also has FK columns.\n\t *\n\t * Default: `'id'` (matches existing codebase convention).\n\t *\n\t * Set to `null` to disable the implicit-PK convention entirely. Primary\n\t * keys must then be declared explicitly with `primaryKey: true` (or are\n\t * inferred from FK columns for junction tables). Empty string (`''`) and\n\t * whitespace-only strings are rejected eagerly at `schema()` time\n\t * (before any per-table processing) with a `SchemaValidationError`.\n\t *\n\t * Match the adapter's `defaultPkColumnName` if your project uses a\n\t * different naming scheme (e.g. `'pk_uuid'`).\n\t *\n\t * @remarks\n\t * `inferPrimaryKey` resolves PKs in this order:\n\t * 1. Explicit `primaryKey: true` on column(s)\n\t * 2. Column matching `defaultPkColumnName` (this option) — skipped when set to `null`\n\t * 3. FK columns (composite, for junction tables — applies regardless of this option)\n\t * 4. No primary key\n\t *\n\t * @example\n\t * // Default — 'id' is implicit PK\n\t * schema({ users: { id: 'uuid' } });\n\t *\n\t * // Custom convention\n\t * schema({ users: { pk_uuid: 'uuid' } }, undefined, { defaultPkColumnName: 'pk_uuid' });\n\t *\n\t * // Strict — no implicit PK convention\n\t * schema({ users: { id: 'uuid' } }, undefined, { defaultPkColumnName: null });\n\t * // ↑ no PK declared — FKs targeting users.id will fail validation.\n\t */\n\tdefaultPkColumnName?: string | null;\n}\n\nexport interface Schema<T extends SchemaDefinition> {\n\t/** The raw schema definition */\n\treadonly definition: T;\n\t/** Converted ModelIR for use with ORM */\n\treadonly model: ModelIR;\n\t/** Table names */\n\treadonly tableNames: (keyof T)[];\n\t/**\n\t * Type-safe table references for query building.\n\t *\n\t * Provides typed access to tables, columns, and relations:\n\t * - `schema.tables.users` returns a TableRef with typed columns\n\t * - `schema.tables.users.id` returns a ColumnRef\n\t * - `schema.tables.users.posts` returns a RelationRef (if relation exists)\n\t * - `schema.tables.users['*']` returns AllColumns for SELECT *\n\t *\n\t * @example\n\t * ```typescript\n\t * const { users, posts } = schema.tables;\n\t *\n\t * // Type-safe column access\n\t * users.id // ColumnRef<'users', 'id', string>\n\t * users.name // ColumnRef<'users', 'name', string>\n\t *\n\t * // Type-safe relation access\n\t * users.posts // RelationRef<'posts', Post[], 'hasMany'>\n\t *\n\t * // Wildcard for SELECT *\n\t * users['*'] // AllColumns<'users', {...}>\n\t * ```\n\t *\n\t * @since DX-040\n\t */\n\treadonly tables: InferTables<T>;\n\t/**\n\t * DB column casing — describes what casing the database uses.\n\t * @see DbCasing\n\t */\n\treadonly dbCasing?: DbCasing;\n\t/**\n\t * Timestamp when this schema was introspected from the database.\n\t * Only present for schemas created via getSchemaFromDb().\n\t * Useful for detecting schema drift.\n\t */\n\treadonly introspectedAt?: Date;\n\t/**\n\t * Default filters per table (e.g., soft delete filtering).\n\t * Applied automatically to all queries unless `.withoutDefaultFilters()` is called.\n\t */\n\treadonly defaultFilters?: DefaultFilters;\n}\n\n// ============================================================================\n// Type Inference Helpers\n// ============================================================================\n\n/**\n * JSON-compatible value type for json/jsonb columns.\n */\nexport type JsonValue =\n\t| string\n\t| number\n\t| boolean\n\t| null\n\t| JsonValue[]\n\t| { [key: string]: JsonValue };\n\n/**\n * Range value type for PostgreSQL range types.\n */\nexport interface InferredRangeValue<T> {\n\treadonly start: T | null;\n\treadonly end: T | null;\n\treadonly startInclusive?: boolean;\n\treadonly endInclusive?: boolean;\n}\n\n/**\n * Maps a ColumnType string to its TypeScript type.\n */\nexport type InferColumnType<T extends SchemaColumnType> =\n\t// String types\n\tT extends 'string' | 'text' | 'uuid'\n\t\t? string\n\t\t: // Numeric types\n\t\t\tT extends 'number' | 'integer' | 'decimal'\n\t\t\t? number\n\t\t\t: // BigInt\n\t\t\t\tT extends 'bigint'\n\t\t\t\t? bigint\n\t\t\t\t: // Boolean\n\t\t\t\t\tT extends 'boolean'\n\t\t\t\t\t? boolean\n\t\t\t\t\t: // Date/time types\n\t\t\t\t\t\tT extends 'date' | 'time' | 'datetime' | 'timestamp'\n\t\t\t\t\t\t? Date\n\t\t\t\t\t\t: // JSON types\n\t\t\t\t\t\t\tT extends 'json' | 'jsonb'\n\t\t\t\t\t\t\t? JsonValue\n\t\t\t\t\t\t\t: // PostgreSQL range types\n\t\t\t\t\t\t\t\tT extends 'daterange'\n\t\t\t\t\t\t\t\t? InferredRangeValue<Date>\n\t\t\t\t\t\t\t\t: T extends 'tsrange' | 'tstzrange'\n\t\t\t\t\t\t\t\t\t? InferredRangeValue<Date>\n\t\t\t\t\t\t\t\t\t: T extends 'int4range' | 'int8range'\n\t\t\t\t\t\t\t\t\t\t? InferredRangeValue<number>\n\t\t\t\t\t\t\t\t\t\t: T extends 'numrange'\n\t\t\t\t\t\t\t\t\t\t\t? InferredRangeValue<number>\n\t\t\t\t\t\t\t\t\t\t\t: // Fallback\n\t\t\t\t\t\t\t\t\t\t\t\tunknown;\n\n/**\n * Extracts the type string from a ColumnDef (handles short and long forms).\n */\ntype ExtractColumnType<C extends ColumnDef> = C extends SchemaColumnType\n\t? C\n\t: C extends { type: infer T extends SchemaColumnType }\n\t\t? T\n\t\t: never;\n\n/**\n * Checks if a ColumnDef is nullable.\n */\ntype IsNullable<C extends ColumnDef> = C extends { nullable: true }\n\t? true\n\t: false;\n\n/**\n * Infers the TypeScript type for a single column definition.\n * Handles both short form ('string') and long form ({ type: 'string', nullable: true }).\n */\nexport type InferColumn<C extends ColumnDef> =\n\tIsNullable<C> extends true\n\t\t? InferColumnType<ExtractColumnType<C>> | null\n\t\t: InferColumnType<ExtractColumnType<C>>;\n\n/**\n * Infers the FK column type from a RefDefinition.\n *\n * ⚠️ **Limitation:** FK columns are typed as `number | string` because inferring\n * the target PK type at compile time would require resolving cross-table references,\n * which creates circular type dependencies in TypeScript.\n *\n * **Why not infer from target table?**\n * Given `ref('users')`, we'd need to:\n * 1. Find `users` table in the schema\n * 2. Find column with `primaryKey: true`\n * 3. Get its type\n *\n * This creates circular refs when tables reference each other (A→B→A).\n *\n * **Pragmatic trade-off:** `number | string` covers 99% of PKs (auto-increment int or UUID).\n *\n * @example\n * authorId: ref('users') // Type: number | string\n * editorId: ref('users', { nullable: true }) // Type: number | string | null\n */\nexport type InferRefColumn<R extends RefDefinition> = R extends {\n\toptions: { nullable: true };\n}\n\t? number | string | null\n\t: number | string;\n\n/**\n * Infers the row type for a single table definition.\n * Maps each column to its TypeScript type.\n */\nexport type InferRow<T extends TableDef> = {\n\t[K in keyof T]: T[K] extends RefDefinition\n\t\t? InferRefColumn<T[K]>\n\t\t: T[K] extends ColumnDef\n\t\t\t? InferColumn<T[K]>\n\t\t\t: unknown;\n};\n\n/**\n * Infers the complete database type from a schema definition.\n * Maps each table name to its row type.\n *\n * @example\n * ```typescript\n * const mySchema = schema({\n * users: { id: 'integer', email: 'string', bio: { type: 'text', nullable: true } },\n * posts: { id: 'integer', title: 'string', authorId: ref('users') },\n * });\n *\n * type DB = InferDB<typeof mySchema.definition>;\n * // DB = {\n * // users: { id: number; email: string; bio: string | null };\n * // posts: { id: number; title: string; authorId: number | string };\n * // }\n * ```\n */\nexport type InferDB<S extends SchemaDefinition> = {\n\t[TableName in keyof S]: InferRow<S[TableName]>;\n};\n\n/**\n * Helper type to extract the inferred DB type from a Schema instance.\n */\nexport type InferSchemaDB<S extends Schema<SchemaDefinition>> =\n\tS extends Schema<infer T> ? InferDB<T> : never;\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Declares a foreign key reference to another table.\n *\n * @param target - Target table name (must exist in schema)\n * @param options - Optional FK constraints and relation naming\n * @returns RefDefinition for use in table definitions\n *\n * @example\n * ```typescript\n * // Simple FK (1:N)\n * authorId: ref('users')\n *\n * // Optional FK\n * editorId: ref('users', { nullable: true })\n *\n * // 1:1 relation (unique FK)\n * userId: ref('users', { unique: true })\n *\n * // Custom naming\n * createdById: ref('users', { as: 'createdBy', inverse: 'createdDocuments' })\n *\n * // Self-ref (requires roles)\n * parentId: ref('categories', { roles: { parent: 'parent', children: 'children' } })\n * ```\n */\nexport function ref<\n\tTTarget extends string,\n\tTOptions extends RefOptions = Record<string, never>,\n>(target: TTarget, options?: TOptions): RefDefinition<TTarget, TOptions> {\n\treturn {\n\t\t__brand: 'ref',\n\t\ttarget,\n\t\toptions: (options ?? {}) as TOptions,\n\t};\n}\n\n/**\n * Type guard for RefDefinition.\n */\nexport function isRef(\n\tvalue: ColumnDef | RefDefinition,\n): value is RefDefinition {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'__brand' in value &&\n\t\tvalue.__brand === 'ref'\n\t);\n}\n\n/**\n * Creates a type-safe schema definition and converts it to ModelIR.\n *\n * @param definition - Schema definition with tables and columns\n * @returns Schema object with definition, model, and table names\n *\n * @example\n * ```typescript\n * const db = schema({\n * users: {\n * id: 'uuid',\n * email: { type: 'text', unique: true },\n * },\n * posts: {\n * id: 'uuid',\n * title: 'text',\n * authorId: ref('users'),\n * },\n * });\n *\n * // Use with ORM\n * const orm = createOrm({ model: db.model, adapter });\n * ```\n */\nexport function schema<T extends SchemaDefinition>(\n\tdefinition: T,\n\tconstraints?: SchemaConstraints,\n\toptions?: SchemaOptions,\n\textras?: SchemaExtras,\n): Schema<T> {\n\t// Validate and convert to ModelIR\n\tconst model = schemaToModelIR(definition, constraints, extras, options);\n\tconst tableNames = Object.keys(definition) as (keyof T)[];\n\n\t// Validate default filters reference existing tables\n\tconst defaultFilters = options?.defaultFilters;\n\tif (defaultFilters) {\n\t\tconst tableNameSet = new Set(tableNames as string[]);\n\t\tfor (const tableName of Object.keys(defaultFilters)) {\n\t\t\tif (!tableNameSet.has(tableName)) {\n\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t`Default filter for non-existent table '${tableName}'. ` +\n\t\t\t\t\t\t`Available: ${[...tableNameSet].join(', ')}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Create type-safe tables proxy (DX-040)\n\tconst tables = createTablesProxy(\n\t\tmodel,\n\t\ttableNames as string[],\n\t) as InferTables<T>;\n\n\treturn {\n\t\tdefinition,\n\t\tmodel,\n\t\ttableNames,\n\t\ttables,\n\t\t...(defaultFilters ? { defaultFilters } : {}),\n\t};\n}\n\n// ============================================================================\n// Conversion to ModelIR\n// ============================================================================\n\n/**\n * Validation error during schema conversion.\n */\nexport class SchemaValidationError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly table?: string,\n\t\tpublic readonly column?: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'SchemaValidationError';\n\t}\n}\n\n/**\n * Converts a schema definition to ModelIR.\n *\n * @internal\n */\nexport function schemaToModelIR(\n\tdefinition: SchemaDefinition,\n\tconstraints?: SchemaConstraints,\n\textras?: SchemaExtras,\n\toptions?: SchemaOptions,\n): ModelIR {\n\t// R6-L1: fail-fast before any per-table work. Empty / whitespace-only\n\t// defaultPkColumnName is rejected here (once) rather than per-table in\n\t// inferPrimaryKey, because the error is a schema-level misconfiguration\n\t// and should be reported at the earliest possible point.\n\tif (\n\t\ttypeof options?.defaultPkColumnName === 'string' &&\n\t\toptions.defaultPkColumnName.trim().length === 0\n\t) {\n\t\tthrow new SchemaValidationError(\n\t\t\t`defaultPkColumnName cannot be an empty or whitespace-only string. Pass null to disable the implicit-PK convention or omit the option for the default 'id'.`,\n\t\t);\n\t}\n\n\tconst tableNames = Object.keys(definition);\n\n\t// Phase 1: Validate refs point to existing tables (existence + roles only)\n\tvalidateRefs(definition, tableNames);\n\n\t// Phase 2: Collect all refs and validate constraints\n\tconst refsByTable = collectRefs(definition);\n\n\t// Phase 3: Build tables (columns, PKs, FKs, indexes) — inferPrimaryKey runs here\n\tconst tables = buildTables(\n\t\tdefinition,\n\t\trefsByTable,\n\t\ttableNames,\n\t\tconstraints,\n\t\toptions,\n\t);\n\n\t// Phase 3.5: Validate FK targets exist and are referenceable (post-build, uses resolved PKs)\n\tvalidateFkTargets(tables);\n\n\t// Phase 4: Build relations from refs\n\tconst relations = buildRelations(definition, refsByTable, tableNames);\n\n\t// Phase 5: Build ModelIR\n\tconst tableMap = new Map<string, TableIR>();\n\tfor (const table of tables) {\n\t\ttableMap.set(table.name, table);\n\t}\n\n\tconst relationMap = new Map<string, RelationIR>();\n\tfor (const relation of relations) {\n\t\tconst qualifiedName = `${relation.source}.${relation.name}`;\n\t\trelationMap.set(qualifiedName, relation);\n\t}\n\n\t// Phase 6: Build extras (extensions, sequences)\n\tconst extensions = extras?.extensions;\n\tconst sequenceMap = extras?.sequences\n\t\t? new Map(\n\t\t\t\tObject.entries(extras.sequences).map(([name, seq]) => [\n\t\t\t\t\tname,\n\t\t\t\t\t{ name, ...seq },\n\t\t\t\t]),\n\t\t\t)\n\t\t: undefined;\n\n\treturn new ModelIRImpl(\n\t\ttableMap,\n\t\trelationMap,\n\t\tundefined,\n\t\textensions,\n\t\tsequenceMap,\n\t);\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\nfunction validateRefs(\n\tdefinition: SchemaDefinition,\n\ttableNames: string[],\n): void {\n\tconst tableSet = new Set(tableNames);\n\n\tfor (const [tableName, tableDef] of Object.entries(definition)) {\n\t\tfor (const [columnName, columnDef] of Object.entries(tableDef)) {\n\t\t\tif (isRef(columnDef)) {\n\t\t\t\t// Check target exists\n\t\t\t\tif (!tableSet.has(columnDef.target)) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Foreign key '${columnName}' references non-existent table '${columnDef.target}'`,\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\tcolumnName,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Self-ref requires roles\n\t\t\t\tif (columnDef.target === tableName && !columnDef.options.roles) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Self-referential FK '${columnName}' must have 'roles' option with parent/children names`,\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\tcolumnName,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Roles only valid for self-ref\n\t\t\t\tif (columnDef.target !== tableName && columnDef.options.roles) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`'roles' option is only valid for self-referential FKs, but '${columnName}' references '${columnDef.target}'`,\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\tcolumnName,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * PostgreSQL UNIQUE constraints only support btree and hash index methods.\n * Other methods (gin, gist, brin, spgist, hnsw, bm25, etc.) cannot enforce\n * uniqueness and therefore cannot back a foreign key target column.\n * Treat undefined as 'btree' (the PostgreSQL default).\n */\nconst UNIQUE_CAPABLE_INDEX_METHODS = new Set(['btree', 'hash']);\n\n/**\n * Validates FK target columns exist and are referenceable.\n *\n * For ALL FKs (single-column and composite):\n * - Source and target column counts must match.\n * - Every referenced column must exist on the target table.\n *\n * For single-column FKs only (the case `buildRefColumn` produces where both\n * `fk.columns.length === 1` AND `fk.references.columns.length === 1`):\n * - Referenced column must be referenceable: singleton primary key,\n * column-level `unique: true`, or a single-column UNIQUE index declared\n * via SchemaConstraints covering exactly the referenced column with no\n * partial-index `WHERE` clause, no expression columns, and using a\n * uniqueness-capable index method (btree or hash).\n * - Mirrors PostgreSQL error 42830 (\"there is no unique constraint matching\n * given keys for referenced table\") at schema()-time instead of at DDL\n * apply time.\n *\n * Composite PK members alone do not qualify as referenceable (matches PG strict\n * semantics): a column that is part of a composite PK still needs an explicit\n * UNIQUE constraint to be the target of an FK.\n */\nfunction validateFkTargets(tables: readonly TableIR[]): void {\n\tconst tableMap = new Map(tables.map((t) => [t.name, t]));\n\n\tfor (const table of tables) {\n\t\tfor (const fk of table.foreignKeys) {\n\t\t\tconst target = tableMap.get(fk.references.table);\n\t\t\t// Defensive: column-level FKs are pre-validated by validateRefs (Phase 1),\n\t\t\t// but table-level constraints.foreignKeys bypass that — so this gate is\n\t\t\t// the only barrier against constraint-based FKs to non-existent tables.\n\t\t\t// Throw rather than skip silently.\n\t\t\tif (!target) {\n\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t`Foreign key in '${table.name}' references non-existent table '${fk.references.table}'`,\n\t\t\t\t\ttable.name,\n\t\t\t\t\tfk.columns[0],\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// R4-1: Source-column existence — guard against constraint-level FKs that\n\t\t\t// declare `columns: [...]` referencing local columns that don't exist on\n\t\t\t// the source table. Column-level FKs (via buildRefColumn) can't trigger\n\t\t\t// this because the source column IS the column being declared, but\n\t\t\t// SchemaConstraints.foreignKeys does not validate this elsewhere.\n\t\t\tfor (const srcCol of fk.columns) {\n\t\t\t\tif (!table.columns.some((c) => c.name === srcCol)) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Foreign key in '${table.name}' uses non-existent source column '${srcCol}'`,\n\t\t\t\t\t\ttable.name,\n\t\t\t\t\t\tsrcCol,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Validate column counts. Zero-length arrays on either side are malformed\n\t\t\t// and should be flagged here rather than silently passed to PG.\n\t\t\tif (fk.columns.length === 0 || fk.references.columns.length === 0) {\n\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t`Foreign key in '${table.name}' has zero-length \\`columns\\` or \\`references\\` array`,\n\t\t\t\t\ttable.name,\n\t\t\t\t\tfk.columns[0],\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// R6-3a: source and target column counts must match for ALL FKs (composite included).\n\t\t\t// PostgreSQL requires a 1-to-1 mapping between source and referenced columns.\n\t\t\tif (fk.columns.length !== fk.references.columns.length) {\n\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t`Foreign key in '${table.name}' has mismatched column counts: ` +\n\t\t\t\t\t\t`${fk.columns.length} source column(s) but ${fk.references.columns.length} referenced column(s)`,\n\t\t\t\t\ttable.name,\n\t\t\t\t\tfk.columns[0],\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// R6-3b: every referenced column must exist on the target table — applies to ALL FKs.\n\t\t\tfor (const refCol of fk.references.columns) {\n\t\t\t\tif (!target.columns.some((c) => c.name === refCol)) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Foreign key in '${table.name}' references non-existent column '${target.name}.${refCol}'`,\n\t\t\t\t\t\ttable.name,\n\t\t\t\t\t\tfk.columns[0],\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Uniqueness check is single-column-only — composites left to PostgreSQL.\n\t\t\tif (fk.columns.length !== 1 || fk.references.columns.length !== 1)\n\t\t\t\tcontinue;\n\n\t\t\tfor (const refCol of fk.references.columns) {\n\t\t\t\t// Existence already validated by R6-3b above for all FKs — targetCol is guaranteed defined here.\n\t\t\t\tconst targetCol = target.columns.find((c) => c.name === refCol);\n\t\t\t\tif (!targetCol) continue; // defensive\n\t\t\t\t// Uniqueness — a column is referenceable when any of the following holds:\n\t\t\t\t// 1. It is the table's singleton resolved primaryKey (covers explicit column-level PK,\n\t\t\t\t// table-level singleton PK, and the implicit-id convention resolved by inferPrimaryKey).\n\t\t\t\t// 2. It has explicit `unique: true`.\n\t\t\t\t// 3. It is the sole column of a non-partial, non-expression single-column UNIQUE index\n\t\t\t\t// declared via SchemaConstraints (partial indexes with a WHERE clause, or expression\n\t\t\t\t// indexes, do NOT make a column referenceable — PG error 42830).\n\t\t\t\t// Members of a composite PK alone do not qualify (matches PG strict semantics).\n\t\t\t\tconst isSingletonPk =\n\t\t\t\t\ttypeof target.primaryKey === 'string' && target.primaryKey === refCol;\n\t\t\t\tconst isUnique = targetCol.unique === true;\n\t\t\t\t// R2-F2: PG only allows UNIQUE constraints on btree/hash indexes —\n\t\t\t\t// gin/gist/brin/spgist/hnsw/bm25 cannot enforce uniqueness even when\n\t\t\t\t// `unique: true` is declared. Fail at schema() time instead of DDL apply.\n\t\t\t\tconst isUniqueIndex =\n\t\t\t\t\ttarget.indexes?.some((idx) => {\n\t\t\t\t\t\tconst method = idx.method ?? 'btree';\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\tidx.unique === true &&\n\t\t\t\t\t\t\tidx.columns.length === 1 &&\n\t\t\t\t\t\t\tidx.columns[0] === refCol &&\n\t\t\t\t\t\t\tidx.where === undefined &&\n\t\t\t\t\t\t\t(idx.expressions === undefined || idx.expressions.length === 0) &&\n\t\t\t\t\t\t\tUNIQUE_CAPABLE_INDEX_METHODS.has(method)\n\t\t\t\t\t\t);\n\t\t\t\t\t}) ?? false;\n\t\t\t\tif (!isSingletonPk && !isUnique && !isUniqueIndex) {\n\t\t\t\t\t// R2-F1: tailor the remediation hint based on the target's PK shape.\n\t\t\t\t\t// - composite PK (string[]): no single PK column to target; suggest\n\t\t\t\t\t// marking unique or using a table-level composite FK.\n\t\t\t\t\t// - resolved single PK (string): point at the existing PK column.\n\t\t\t\t\t// - no PK at all: suggest the defaultPkColumnName convention.\n\t\t\t\t\tconst isCompositePk = Array.isArray(target.primaryKey);\n\t\t\t\t\tconst hasSingleResolvedPk = typeof target.primaryKey === 'string';\n\t\t\t\t\tconst suggestion = isCompositePk\n\t\t\t\t\t\t? `Either mark '${target.name}.${refCol}' with \\`unique: true\\` or add a single-column unique index via SchemaConstraints — '${target.name}' has a composite primary key, so a single-column FK cannot target the PK directly (use a table-level composite FK referencing all PK columns if that is the intent).`\n\t\t\t\t\t\t: hasSingleResolvedPk\n\t\t\t\t\t\t\t? `Either mark the target column with \\`unique: true\\`, add a single-column unique index via SchemaConstraints, or change the FK to target the existing primary key column '${target.primaryKey as string}'.`\n\t\t\t\t\t\t\t: `Either mark the target column with \\`unique: true\\`, add a single-column unique index via SchemaConstraints, or — if '${refCol}' is your primary-key column convention — pass \\`{ defaultPkColumnName: '${refCol}' }\\` as the third argument to \\`schema()\\` (or omit the option entirely if '${refCol}' is 'id').`;\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Foreign key in '${table.name}' targets '${target.name}.${refCol}' which is neither primary key nor unique. ${suggestion}`,\n\t\t\t\t\t\ttable.name,\n\t\t\t\t\t\tfk.columns[0],\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Collected ref info for a table.\n */\ninterface CollectedRef {\n\tcolumnName: string;\n\ttarget: string;\n\toptions: RefOptions;\n\tlocalRelation: string; // Derived relation name\n\tinverseRelation: string; // Derived inverse relation name\n}\n\n/**\n * Collects refs per table and validates multi-FK constraints.\n */\nfunction collectRefs(\n\tdefinition: SchemaDefinition,\n): Map<string, CollectedRef[]> {\n\tconst refsByTable = new Map<string, CollectedRef[]>();\n\n\tfor (const [tableName, tableDef] of Object.entries(definition)) {\n\t\tconst refs: CollectedRef[] = [];\n\t\tconst refsByTarget = new Map<string, string[]>(); // target -> column names\n\n\t\tfor (const [columnName, columnDef] of Object.entries(tableDef)) {\n\t\t\tif (isRef(columnDef)) {\n\t\t\t\t// Track refs by target for multi-FK validation\n\t\t\t\tconst existing = refsByTarget.get(columnDef.target) || [];\n\t\t\t\texisting.push(columnName);\n\t\t\t\trefsByTarget.set(columnDef.target, existing);\n\n\t\t\t\t// Derive relation names\n\t\t\t\tconst localRelation = deriveLocalRelation(\n\t\t\t\t\tcolumnName,\n\t\t\t\t\tcolumnDef.options,\n\t\t\t\t);\n\t\t\t\tconst inverseRelation = deriveInverseRelation(\n\t\t\t\t\tlocalRelation,\n\t\t\t\t\ttableName,\n\t\t\t\t\tcolumnDef.options,\n\t\t\t\t\tcolumnDef.target === tableName,\n\t\t\t\t);\n\n\t\t\t\trefs.push({\n\t\t\t\t\tcolumnName,\n\t\t\t\t\ttarget: columnDef.target,\n\t\t\t\t\toptions: columnDef.options,\n\t\t\t\t\tlocalRelation,\n\t\t\t\t\tinverseRelation,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Validate multi-FK to same table requires explicit naming\n\t\tfor (const [target, columns] of refsByTarget) {\n\t\t\tif (columns.length > 1 && target !== tableName) {\n\t\t\t\t// Multiple FKs to same non-self table - all must have 'as'\n\t\t\t\tfor (const columnName of columns) {\n\t\t\t\t\tconst ref = refs.find((r) => r.columnName === columnName);\n\t\t\t\t\tif (ref && !ref.options.as) {\n\t\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t\t`Multiple FKs to '${target}' require explicit 'as' naming. Column '${columnName}' has no 'as' option.`,\n\t\t\t\t\t\t\ttableName,\n\t\t\t\t\t\t\tcolumnName,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check for duplicate relation names within this table\n\t\tconst seenRelations = new Set<string>();\n\t\tfor (const ref of refs) {\n\t\t\tif (ref.options.roles) {\n\t\t\t\t// Self-ref - check all role names\n\t\t\t\tconst roles = ref.options.roles;\n\t\t\t\tconst allNames = [\n\t\t\t\t\troles.parent,\n\t\t\t\t\troles.children,\n\t\t\t\t\troles.ancestors || 'ancestors',\n\t\t\t\t\troles.descendants || 'descendants',\n\t\t\t\t];\n\t\t\t\tfor (const name of allNames) {\n\t\t\t\t\tif (seenRelations.has(name)) {\n\t\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t\t`Duplicate relation name '${name}'`,\n\t\t\t\t\t\t\ttableName,\n\t\t\t\t\t\t\tref.columnName,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tseenRelations.add(name);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (seenRelations.has(ref.localRelation)) {\n\t\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t\t`Duplicate relation name '${ref.localRelation}'`,\n\t\t\t\t\t\ttableName,\n\t\t\t\t\t\tref.columnName,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tseenRelations.add(ref.localRelation);\n\t\t\t}\n\t\t}\n\n\t\trefsByTable.set(tableName, refs);\n\t}\n\n\treturn refsByTable;\n}\n\n// ============================================================================\n// Naming Derivation\n// ============================================================================\n\n/**\n * Derives local relation name from column name.\n * authorId -> author, user_id -> user\n */\nfunction deriveLocalRelation(columnName: string, options: RefOptions): string {\n\tif (options.as) {\n\t\treturn options.as;\n\t}\n\n\t// Remove 'Id' suffix (camelCase)\n\tif (columnName.endsWith('Id')) {\n\t\treturn columnName.slice(0, -2);\n\t}\n\n\t// Remove '_id' suffix (snake_case - shouldn't happen but handle it)\n\tif (columnName.endsWith('_id')) {\n\t\treturn columnName.slice(0, -3);\n\t}\n\n\t// Fallback: use column name as-is\n\treturn columnName;\n}\n\n/**\n * Derives inverse relation name.\n * Default pattern: {localRelation}_{tableName}\n */\nfunction deriveInverseRelation(\n\tlocalRelation: string,\n\tsourceTable: string,\n\toptions: RefOptions,\n\tisSelfRef: boolean,\n): string {\n\t// Self-ref doesn't use standard inverse naming\n\tif (isSelfRef) {\n\t\treturn ''; // Handled via roles\n\t}\n\n\tif (options.inverse) {\n\t\treturn options.inverse;\n\t}\n\n\t// Pattern: author -> author_posts (for source table 'posts')\n\treturn `${localRelation}_${sourceTable}`;\n}\n\n// ============================================================================\n// Table Building\n// ============================================================================\n\n/**\n * Returns the ColumnType of the primary key in the target table definition.\n * Falls back to 'uuid' if the target is not found or has no explicit PK.\n */\nfunction getTargetPkType(\n\tdefinition: SchemaDefinition,\n\ttarget: string,\n): ColumnType {\n\tconst targetDef = definition[target];\n\tif (!targetDef) return 'uuid';\n\n\tfor (const [, colDef] of Object.entries(targetDef)) {\n\t\tif (isRef(colDef)) continue;\n\t\tconst def = normalizeColumnDef(colDef);\n\t\tif (def.primaryKey) return def.type;\n\t}\n\n\tif ('id' in targetDef) {\n\t\tconst idDef = targetDef.id;\n\t\tif (idDef && !isRef(idDef)) return normalizeColumnDef(idDef).type;\n\t}\n\treturn 'uuid';\n}\n\n/**\n * Returns the ColumnType for a specific named column in a target table definition.\n * Used by buildRefColumn to derive the source column type when `references` points\n * to a non-PK unique column. Falls back to `undefined` when the column is not found\n * or is itself a ref (chain case handled by getTargetPkType).\n */\nfunction getReferencedColumnType(\n\ttargetDef: TableDef,\n\treferencedCol: string,\n\tdefinition?: SchemaDefinition,\n\tvisited?: Set<string>,\n): ColumnType | undefined {\n\tconst colDef = targetDef[referencedCol];\n\tif (!colDef) return undefined;\n\tif (isRef(colDef)) {\n\t\t// R6-5 (chained ref): follow the chain to resolve the final concrete type.\n\t\t// Guard against cycles and runaway chains with a visited-key accumulator.\n\t\tif (!definition) return undefined;\n\t\tconst chainedTableName = colDef.target;\n\t\tconst chainedTargetDef = definition[chainedTableName];\n\t\tif (!chainedTargetDef) return undefined;\n\t\t// The chained ref's referenced column: options.references[0] ?? 'id'\n\t\tconst chainedRefCols = colDef.options.references;\n\t\tconst firstChainedRefCol =\n\t\t\tchainedRefCols && chainedRefCols.length === 1\n\t\t\t\t? chainedRefCols[0]\n\t\t\t\t: undefined;\n\t\tconst chainedRefCol: string = firstChainedRefCol ?? 'id';\n\t\t// Visited key uniquely identifies the (tableDef, column) pair in the chain.\n\t\tconst visitedKey = `${chainedTableName}.${chainedRefCol}`;\n\t\tconst seen = visited ?? new Set<string>();\n\t\tif (seen.has(visitedKey)) return undefined; // cycle detected\n\t\tseen.add(visitedKey);\n\t\treturn getReferencedColumnType(\n\t\t\tchainedTargetDef,\n\t\t\tchainedRefCol,\n\t\t\tdefinition,\n\t\t\tseen,\n\t\t);\n\t}\n\treturn normalizeColumnDef(colDef).type;\n}\n\n/**\n * Builds a FK column + ForeignKeyIR pair from a ref definition.\n */\nfunction buildRefColumn(\n\tcolumnName: string,\n\tcolumnDef: RefDefinition,\n\tdefinition: SchemaDefinition,\n): { col: ColumnIR; fk: ForeignKeyIR } {\n\t// R5-1: When options.references specifies a single target column, derive the\n\t// source column type from THAT column's type rather than the target's PK type.\n\t// This prevents a type mismatch when the FK points at a unique non-PK column\n\t// that has a different type than the table's PK (e.g. email:string vs id:uuid).\n\tconst targetDef = definition[columnDef.target];\n\tconst targetCol =\n\t\tcolumnDef.options.references?.length === 1\n\t\t\t? columnDef.options.references[0]\n\t\t\t: undefined;\n\tconst inferredType =\n\t\ttargetCol && targetDef\n\t\t\t? (getReferencedColumnType(targetDef, targetCol, definition) ??\n\t\t\t\tgetTargetPkType(definition, columnDef.target))\n\t\t\t: getTargetPkType(definition, columnDef.target);\n\tconst col: Mutable<ColumnIR> = {\n\t\tname: columnName,\n\t\ttype: inferredType,\n\t\tnullable: columnDef.options.nullable ?? false,\n\t};\n\tif (columnDef.options.unique) col.unique = true;\n\n\tif (\n\t\tcolumnDef.options.references &&\n\t\tcolumnDef.options.references.length !== 1\n\t) {\n\t\tthrow new SchemaValidationError(\n\t\t\t`FK column '${columnName}' got 'references' with ${columnDef.options.references.length} columns; column-level FK requires exactly one target column (use table-level foreignKeys for composite FKs).`,\n\t\t);\n\t}\n\tconst fk: Mutable<ForeignKeyIR> = {\n\t\tcolumns: [columnName],\n\t\treferences: {\n\t\t\ttable: columnDef.target,\n\t\t\tcolumns: columnDef.options.references ?? ['id'],\n\t\t},\n\t};\n\tif (columnDef.options.onDelete) fk.onDelete = columnDef.options.onDelete;\n\tif (columnDef.options.onUpdate) fk.onUpdate = columnDef.options.onUpdate;\n\n\treturn { col: col as ColumnIR, fk: fk as ForeignKeyIR };\n}\n\n/**\n * Builds a regular ColumnIR from a normalized column definition.\n */\nfunction buildRegularColumn(\n\tcolumnName: string,\n\tcolumnDef: ColumnDef,\n): { col: ColumnIR; isPk: boolean } {\n\tconst def = normalizeColumnDef(columnDef);\n\tconst col: Mutable<ColumnIR> = {\n\t\tname: columnName,\n\t\ttype: def.type,\n\t\tnullable: def.nullable ?? false,\n\t};\n\tif (def.dbType?.trim()) col.originalDbType = def.dbType.trim();\n\tif (def.unique) col.unique = def.unique;\n\tif (def.autoIncrement) col.autoIncrement = def.autoIncrement;\n\tif (def.default !== undefined) col.default = def.default;\n\treturn { col: col as ColumnIR, isPk: def.primaryKey ?? false };\n}\n\n/**\n * Builds columns, foreign keys, and explicit primary key list for a table.\n */\nfunction buildColumnsForTable(\n\t_tableName: string,\n\ttableDef: TableDef,\n\tdefinition: SchemaDefinition,\n): { columns: ColumnIR[]; foreignKeys: ForeignKeyIR[]; primaryKey: string[] } {\n\tconst columns: ColumnIR[] = [];\n\tconst foreignKeys: ForeignKeyIR[] = [];\n\tconst primaryKey: string[] = [];\n\n\tfor (const [columnName, columnDef] of Object.entries(tableDef)) {\n\t\tif (isRef(columnDef)) {\n\t\t\tconst { col, fk } = buildRefColumn(columnName, columnDef, definition);\n\t\t\tcolumns.push(col);\n\t\t\tforeignKeys.push(fk);\n\t\t} else {\n\t\t\tconst { col, isPk } = buildRegularColumn(columnName, columnDef);\n\t\t\tcolumns.push(col);\n\t\t\tif (isPk) primaryKey.push(columnName);\n\t\t}\n\t}\n\treturn { columns, foreignKeys, primaryKey };\n}\n\n/**\n * Infers the final primary key from explicit declarations, the implicit-PK name\n * convention, or FK columns (for junction tables).\n *\n * Resolution order:\n * 1. Explicit `primaryKey: true` on column(s)\n * 2. Column matching `defaultPkColumnName` (options.defaultPkColumnName) — skipped\n * when set to `null` (strict mode)\n * 3. FK columns (composite PK for junction tables — applies regardless of option)\n * 4. No primary key\n */\nfunction inferPrimaryKey(\n\tprimaryKey: string[],\n\tforeignKeys: ForeignKeyIR[],\n\tcolumns: ColumnIR[],\n\toptions?: { defaultPkColumnName?: string | null },\n): string | readonly string[] | undefined {\n\tif (primaryKey.length > 0) {\n\t\treturn primaryKey.length === 1 ? (primaryKey[0] as string) : primaryKey;\n\t}\n\t// Implicit PK convention BEFORE FK fallback. Honoured unless explicitly\n\t// disabled with `defaultPkColumnName: null`. Empty/whitespace-only strings\n\t// are rejected at schemaToModelIR() time (R6-L1 guard fires before this runs).\n\tconst pkColName =\n\t\toptions?.defaultPkColumnName === undefined\n\t\t\t? 'id'\n\t\t\t: options.defaultPkColumnName;\n\tif (pkColName !== null && columns.some((c) => c.name === pkColName)) {\n\t\treturn pkColName;\n\t}\n\t// FK fallback for junction tables (applies regardless of the option above).\n\tconst fkColumns = foreignKeys.flatMap((fk) => fk.columns);\n\tif (fkColumns.length > 0) {\n\t\treturn fkColumns.length === 1 ? fkColumns[0] : fkColumns;\n\t}\n\treturn undefined;\n}\n\n/**\n * Builds pseudo-columns for self-referential FKs with roles.\n */\nfunction buildPseudoColumns(\n\ttableName: string,\n\trefsByTable: Map<string, CollectedRef[]>,\n\tfinalPk: string | readonly string[] | undefined,\n): PseudoColumnMetadata[] {\n\tconst pseudoColumns: PseudoColumnMetadata[] = [];\n\tconst refs = refsByTable.get(tableName) ?? [];\n\tconst pkColumn =\n\t\ttypeof finalPk === 'string' ? finalPk : (finalPk?.[0] ?? 'id');\n\n\tfor (const ref of refs) {\n\t\tif (ref.options.roles && ref.target === tableName) {\n\t\t\tpseudoColumns.push(\n\t\t\t\tcreatePseudoColumnMetadata(\n\t\t\t\t\ttableName,\n\t\t\t\t\tref.columnName,\n\t\t\t\t\tpkColumn,\n\t\t\t\t\tref.options.roles.parent,\n\t\t\t\t\tref.options.roles.children,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn pseudoColumns;\n}\n\n/**\n * Builds IndexIR entries from column-level `index: true` declarations.\n */\nfunction buildColumnIndexes(tableName: string, tableDef: TableDef): IndexIR[] {\n\tconst indexes: IndexIR[] = [];\n\tfor (const [columnName, columnDef] of Object.entries(tableDef)) {\n\t\tif (isRef(columnDef)) continue;\n\t\tconst def = normalizeColumnDef(columnDef);\n\t\tif (def.index) {\n\t\t\tindexes.push({\n\t\t\t\tname: `idx_${tableName}_${columnName}`,\n\t\t\t\tcolumns: [columnName],\n\t\t\t\tunique: false,\n\t\t\t});\n\t\t}\n\t}\n\treturn indexes;\n}\n\n/**\n * Processes table-level constraints (indexes, CHECK constraints, composite FKs).\n */\nfunction buildTableConstraints(\n\ttableName: string,\n\tconstraints: SchemaConstraints | undefined,\n): {\n\textraIndexes: IndexIR[];\n\tcheckConstraints: CheckConstraintIR[];\n\textraForeignKeys: ForeignKeyIR[];\n} {\n\tconst extraIndexes: IndexIR[] = [];\n\tconst checkConstraints: CheckConstraintIR[] = [];\n\tconst extraForeignKeys: ForeignKeyIR[] = [];\n\n\tconst tableConstraints = constraints?.[tableName];\n\tif (!tableConstraints) {\n\t\treturn { extraIndexes, checkConstraints, extraForeignKeys };\n\t}\n\n\tif (tableConstraints.indexes) {\n\t\tfor (const idx of tableConstraints.indexes) {\n\t\t\tconst indexIR: Mutable<IndexIR> = {\n\t\t\t\tname: idx.name ?? `idx_${tableName}_${idx.columns.join('_')}`,\n\t\t\t\tcolumns: idx.columns,\n\t\t\t\tunique: idx.unique ?? false,\n\t\t\t};\n\t\t\tif (idx.method) indexIR.method = idx.method;\n\t\t\tif (idx.where) indexIR.where = idx.where;\n\t\t\tif (idx.opclass) indexIR.opclass = idx.opclass;\n\t\t\tif (idx.with) indexIR.with = idx.with;\n\t\t\textraIndexes.push(indexIR as IndexIR);\n\t\t}\n\t}\n\n\tif (tableConstraints.checkConstraints) {\n\t\tfor (const chk of tableConstraints.checkConstraints) {\n\t\t\tcheckConstraints.push({\n\t\t\t\tname: chk.name,\n\t\t\t\texpression: `CHECK (${chk.expression})`,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (tableConstraints.foreignKeys) {\n\t\tfor (const fkRef of tableConstraints.foreignKeys) {\n\t\t\tif (!fkRef.options.columns?.length) {\n\t\t\t\tthrow new SchemaValidationError(\n\t\t\t\t\t`Composite FK on \"${tableName}\" → \"${fkRef.target}\" requires 'columns' option`,\n\t\t\t\t\ttableName,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst fk: Mutable<ForeignKeyIR> = {\n\t\t\t\tcolumns: [...fkRef.options.columns],\n\t\t\t\treferences: {\n\t\t\t\t\ttable: fkRef.target,\n\t\t\t\t\tcolumns: fkRef.options.references\n\t\t\t\t\t\t? [...fkRef.options.references]\n\t\t\t\t\t\t: ['id'],\n\t\t\t\t},\n\t\t\t};\n\t\t\tif (fkRef.options.onDelete) fk.onDelete = fkRef.options.onDelete;\n\t\t\textraForeignKeys.push(fk as ForeignKeyIR);\n\t\t}\n\t}\n\n\treturn { extraIndexes, checkConstraints, extraForeignKeys };\n}\n\n/**\n * Builds TableIR objects from schema definition.\n */\nfunction buildTables(\n\tdefinition: SchemaDefinition,\n\trefsByTable: Map<string, CollectedRef[]>,\n\ttableNames: string[],\n\tconstraints?: SchemaConstraints,\n\toptions?: SchemaOptions,\n): TableIR[] {\n\tconst tables: TableIR[] = [];\n\n\tfor (const tableName of tableNames) {\n\t\tconst tableDef = definition[tableName];\n\t\tif (!tableDef) continue;\n\n\t\tconst { columns, foreignKeys, primaryKey } = buildColumnsForTable(\n\t\t\ttableName,\n\t\t\ttableDef,\n\t\t\tdefinition,\n\t\t);\n\t\tconst finalPk = inferPrimaryKey(primaryKey, foreignKeys, columns, options);\n\t\tconst pseudoColumns = buildPseudoColumns(tableName, refsByTable, finalPk);\n\t\tconst columnIndexes = buildColumnIndexes(tableName, tableDef);\n\t\tconst { extraIndexes, checkConstraints, extraForeignKeys } =\n\t\t\tbuildTableConstraints(tableName, constraints);\n\n\t\tconst table: TableIR = {\n\t\t\tname: tableName,\n\t\t\tcolumns,\n\t\t\t...(finalPk !== undefined ? { primaryKey: finalPk } : {}),\n\t\t\tforeignKeys: [...foreignKeys, ...extraForeignKeys],\n\t\t\tindexes: [...columnIndexes, ...extraIndexes],\n\t\t\t...(checkConstraints.length > 0 ? { checkConstraints } : {}),\n\t\t\t...(pseudoColumns.length > 0 ? { pseudoColumns } : {}),\n\t\t};\n\t\ttables.push(table);\n\t}\n\n\treturn tables;\n}\n\n/**\n * Normalizes column definition to object form.\n */\nfunction normalizeColumnDef(def: ColumnDef): {\n\ttype: SchemaColumnType;\n\tdbType?: string;\n\tnullable?: boolean;\n\tunique?: boolean;\n\tprimaryKey?: boolean;\n\tautoIncrement?: boolean;\n\tdefault?: unknown;\n\tindex?: boolean;\n} {\n\tif (typeof def === 'string') {\n\t\treturn { type: def };\n\t}\n\treturn def;\n}\n\n// ============================================================================\n// Relation Building\n// ============================================================================\n\n/**\n * Builds RelationIR objects from collected refs.\n */\nfunction buildRelations(\n\t_definition: SchemaDefinition,\n\trefsByTable: Map<string, CollectedRef[]>,\n\ttableNames: string[],\n): RelationIR[] {\n\tconst relations: RelationIR[] = [];\n\n\tfor (const tableName of tableNames) {\n\t\tconst refs = refsByTable.get(tableName) || [];\n\n\t\tfor (const ref of refs) {\n\t\t\tif (ref.options.roles) {\n\t\t\t\t// Self-referential - generate 4 relations\n\t\t\t\tconst roles = ref.options.roles;\n\n\t\t\t\t// 1. Direct parent (belongsTo)\n\t\t\t\trelations.push({\n\t\t\t\t\tname: roles.parent,\n\t\t\t\t\ttype: 'belongsTo',\n\t\t\t\t\tsource: tableName,\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: 'one',\n\t\t\t\t\toptionality: ref.options.nullable ? 'optional' : 'required',\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t});\n\n\t\t\t\t// 2. Direct children (hasMany)\n\t\t\t\trelations.push({\n\t\t\t\t\tname: roles.children,\n\t\t\t\t\ttype: 'hasMany',\n\t\t\t\t\tsource: tableName,\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: 'many',\n\t\t\t\t\toptionality: 'optional', // Children are always optional\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t});\n\n\t\t\t\t// 3. Recursive ancestors (hasMany with recursive metadata)\n\t\t\t\tconst ancestorsName = roles.ancestors || 'ancestors';\n\t\t\t\trelations.push({\n\t\t\t\t\tname: ancestorsName,\n\t\t\t\t\ttype: 'hasMany',\n\t\t\t\t\tsource: tableName,\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: 'many',\n\t\t\t\t\toptionality: 'optional',\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t\trecursive: {\n\t\t\t\t\t\tdirection: 'up',\n\t\t\t\t\t\tmaxDepth: 10,\n\t\t\t\t\t\tthrough: roles.parent,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\t// 4. Recursive descendants (hasMany with recursive metadata)\n\t\t\t\tconst descendantsName = roles.descendants || 'descendants';\n\t\t\t\trelations.push({\n\t\t\t\t\tname: descendantsName,\n\t\t\t\t\ttype: 'hasMany',\n\t\t\t\t\tsource: tableName,\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: 'many',\n\t\t\t\t\toptionality: 'optional',\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t\trecursive: {\n\t\t\t\t\t\tdirection: 'down',\n\t\t\t\t\t\tmaxDepth: 10,\n\t\t\t\t\t\tthrough: roles.children,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Standard relation - generate belongsTo and inverse hasMany/hasOne\n\t\t\t\tconst isUnique = ref.options.unique ?? false;\n\n\t\t\t\t// 1. belongsTo from source to target\n\t\t\t\trelations.push({\n\t\t\t\t\tname: ref.localRelation,\n\t\t\t\t\ttype: 'belongsTo',\n\t\t\t\t\tsource: tableName,\n\t\t\t\t\ttarget: ref.target,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: 'one',\n\t\t\t\t\toptionality: ref.options.nullable ? 'optional' : 'required',\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t});\n\n\t\t\t\t// 2. Inverse relation from target to source\n\t\t\t\tconst inverseType: RelationType = isUnique ? 'hasOne' : 'hasMany';\n\t\t\t\tconst inverseCardinality = isUnique ? 'one' : 'many';\n\n\t\t\t\trelations.push({\n\t\t\t\t\tname: ref.inverseRelation,\n\t\t\t\t\ttype: inverseType,\n\t\t\t\t\tsource: ref.target,\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: ref.columnName,\n\t\t\t\t\tcardinality: inverseCardinality,\n\t\t\t\t\toptionality: 'optional', // Inverse is always optional\n\t\t\t\t\tincludeStrategy: 'auto',\n\t\t\t\t\tfilterStrategy: 'auto',\n\t\t\t\t\tjoinDefault: 'auto',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn relations;\n}\n\n// ============================================================================\n// Database Introspection → Schema\n// ============================================================================\n\n/**\n * Options for getSchemaFromDb.\n */\nexport interface GetSchemaFromDbOptions {\n\t/** Schema name to introspect (default: 'public' for PostgreSQL) */\n\treadonly schema?: string;\n\t/** Tables to include (default: all). */\n\treadonly tables?: readonly string[];\n\t/** Tables to exclude (glob patterns supported). */\n\treadonly exclude?: readonly string[];\n}\n\n/**\n * Map ColumnType from ModelIR to JS-friendly runtime type strings.\n * Used by getSchemaFromDb to create user-friendly schema definitions.\n *\n * Tests expect: 'serial/integer' → 'number', 'varchar/text' → 'string'\n */\nfunction columnTypeToJsType(type: ColumnType): SchemaColumnType {\n\tswitch (type) {\n\t\t// Numeric types → 'number' (includes integer, bigint, decimal)\n\t\tcase 'integer':\n\t\tcase 'bigint':\n\t\tcase 'decimal':\n\t\t\treturn 'number';\n\t\t// String types → 'string' (includes text, uuid)\n\t\tcase 'text':\n\t\tcase 'uuid':\n\t\t\treturn 'string';\n\t\t// All other types pass through as-is (they're valid SchemaColumnType)\n\t\tdefault:\n\t\t\treturn type;\n\t}\n}\n\n/**\n * Adapter interface for introspection.\n * Must have introspect() method and optionally dbCasing.\n */\ninterface IntrospectableAdapter {\n\treadonly dbCasing?: DbCasing;\n\tintrospect(options?: {\n\t\tschema?: string;\n\t\tinclude?: readonly string[];\n\t\texclude?: readonly string[];\n\t}): Promise<ModelIR & { introspectedAt?: Date }>;\n}\n\n/**\n * Create a Schema from database introspection.\n *\n * This function introspects the database schema and returns a Schema<T>\n * that can be used with createOrm().\n *\n * @example\n * ```typescript\n * const adapter = createPgsqlAdapter(pool);\n * const schema = await getSchemaFromDb(adapter, { schema: 'public' });\n * const orm = createOrm({ schema, adapter });\n * ```\n *\n * @param adapter - An adapter that implements introspect()\n * @param options - Introspection options (schema name, table filters)\n * @returns A Schema<T> with definition, model, and type-safe tables\n */\nexport async function getSchemaFromDb<\n\tT extends SchemaDefinition = SchemaDefinition,\n>(\n\tadapter: IntrospectableAdapter,\n\toptions?: GetSchemaFromDbOptions,\n): Promise<Schema<T>> {\n\t// Build introspection options, only including defined values\n\tconst introspectOptions: {\n\t\tschema?: string;\n\t\tinclude?: readonly string[];\n\t\texclude?: readonly string[];\n\t} = {};\n\tif (options?.schema !== undefined) introspectOptions.schema = options.schema;\n\tif (options?.tables !== undefined) introspectOptions.include = options.tables;\n\tif (options?.exclude !== undefined)\n\t\tintrospectOptions.exclude = options.exclude;\n\n\t// Call adapter introspection\n\tconst introspectionResult = await adapter.introspect(introspectOptions);\n\n\tconst model = introspectionResult;\n\tconst introspectedAt = introspectionResult.introspectedAt;\n\n\t// Build FK lookup: column name → target table\n\t// ForeignKeyIR uses columns[] array and references.table\n\tconst fkLookup = new Map<\n\t\tstring,\n\t\tMap<string, { target: string; nullable: boolean; unique: boolean }>\n\t>();\n\tfor (const table of model.tables.values()) {\n\t\tconst tableFks = new Map<\n\t\t\tstring,\n\t\t\t{ target: string; nullable: boolean; unique: boolean }\n\t\t>();\n\t\tfor (const fk of table.foreignKeys) {\n\t\t\t// Only handle single-column FKs for now (composite FKs are rare in schema defs)\n\t\t\tconst fkColumn = fk.columns[0];\n\t\t\tif (!fkColumn) continue;\n\n\t\t\t// Find the column to check nullable/unique\n\t\t\tconst column = table.columns.find((c) => c.name === fkColumn);\n\t\t\ttableFks.set(fkColumn, {\n\t\t\t\ttarget: fk.references.table,\n\t\t\t\tnullable: column?.nullable ?? true,\n\t\t\t\tunique: column?.unique ?? false,\n\t\t\t});\n\t\t}\n\t\tfkLookup.set(table.name, tableFks);\n\t}\n\n\t// Convert ModelIR to SchemaDefinition\n\tconst definition: Record<string, TableDef> = {};\n\n\tfor (const table of model.tables.values()) {\n\t\tconst tableDef: TableDef = {};\n\t\tconst tableFks = fkLookup.get(table.name) ?? new Map();\n\n\t\tfor (const column of table.columns) {\n\t\t\tconst fk = tableFks.get(column.name);\n\n\t\t\tif (fk) {\n\t\t\t\t// FK column → ref() definition\n\t\t\t\ttableDef[column.name] = ref(fk.target, {\n\t\t\t\t\tnullable: fk.nullable,\n\t\t\t\t\tunique: fk.unique,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// Regular column → JS type\n\t\t\t\ttableDef[column.name] = columnTypeToJsType(column.type);\n\t\t\t}\n\t\t}\n\n\t\tdefinition[table.name] = tableDef;\n\t}\n\n\tconst tableNames = Object.keys(definition) as (keyof T)[];\n\n\t// Create type-safe tables proxy\n\tconst tables = createTablesProxy(\n\t\tmodel,\n\t\ttableNames as string[],\n\t) as InferTables<T>;\n\n\t// Build result with optional properties only if defined\n\tconst result: Mutable<Schema<T>> = {\n\t\tdefinition: definition as T,\n\t\tmodel,\n\t\ttableNames,\n\t\ttables,\n\t};\n\n\t// Add optional properties only if they have values\n\tif (adapter.dbCasing !== undefined) {\n\t\tresult.dbCasing = adapter.dbCasing;\n\t}\n\tif (introspectedAt !== undefined) {\n\t\tresult.introspectedAt = introspectedAt;\n\t}\n\n\treturn result as Schema<T>;\n}\n","/**\n * Schema Convention Inference\n *\n * Detects foreign keys and M:N relations using:\n * 1. Explicit `references` (highest priority)\n * 2. Convention patterns (fallback)\n *\n * M:N auto-detection: tables with exactly 2 FKs and no business columns.\n *\n * Migrated from @dbsp/schema/conventions.ts as part of ARCH-003.\n */\n\nimport type {\n\tSchemaBelongsToRelation,\n\tSchemaColumnDefinition,\n\tSchemaConventionsDefinition,\n\tSchemaHasManyRelation,\n\tSchemaManyToManyRelation,\n\tSchemaRelationsDefinition,\n\tSchemaTableDefinition,\n\tSchemaTablesDefinition,\n} from './schema-dsl-types.js';\n\n// =============================================================================\n// Default Conventions\n// =============================================================================\n\nexport const DEFAULT_CONVENTIONS: Required<SchemaConventionsDefinition> = {\n\tfkPattern: '{singular}Id',\n\tpluralize: true,\n\ttimestamps: ['createdAt', 'updatedAt'],\n\tfkAutoIndex: true,\n};\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Convert table name to singular form.\n * Simple heuristic: remove trailing 's' if present.\n */\n/**\n * Built-in mapping of irregular plural forms to their singular equivalents.\n * Import and extend this to handle domain-specific irregular plurals:\n *\n * ```ts\n * import { IRREGULAR_PLURALS, singularize } from '@dbsp/core';\n * const custom = { ...IRREGULAR_PLURALS, matrices: 'matrix', indices: 'index' };\n * singularize('matrices', custom); // 'matrix'\n * ```\n */\nexport const IRREGULAR_PLURALS: Record<string, string> = {\n\tpeople: 'person',\n\tchildren: 'child',\n\tmen: 'man',\n\twomen: 'woman',\n\tteeth: 'tooth',\n\tfeet: 'foot',\n\tgeese: 'goose',\n\tmice: 'mouse',\n\tdata: 'datum',\n\tmedia: 'medium',\n\tcriteria: 'criterion',\n\tphenomena: 'phenomenon',\n};\n\nexport function singularize(\n\tname: string,\n\toverrides?: Record<string, string>,\n): string {\n\tconst lower = name.toLowerCase();\n\n\t// Check user-provided overrides first\n\tif (overrides) {\n\t\tconst override = overrides[lower];\n\t\tif (override !== undefined) {\n\t\t\tif (name[0]?.toUpperCase() === name[0]) {\n\t\t\t\treturn override.charAt(0).toUpperCase() + override.slice(1);\n\t\t\t}\n\t\t\treturn override;\n\t\t}\n\t}\n\n\t// Check built-in irregular plurals\n\tconst irregular = IRREGULAR_PLURALS[lower];\n\tif (irregular !== undefined) {\n\t\t// Preserve original case pattern\n\t\tif (name[0]?.toUpperCase() === name[0]) {\n\t\t\treturn irregular.charAt(0).toUpperCase() + irregular.slice(1);\n\t\t}\n\t\treturn irregular;\n\t}\n\n\t// Handle 'ies' → 'y' (categories → category)\n\tif (lower.endsWith('ies') && name.length > 3) {\n\t\treturn `${name.slice(0, -3)}y`;\n\t}\n\n\t// Handle 'es' for words ending in -shes, -ches, -xes, -zes, -ses (boxes → box)\n\t// But NOT for -les, -res, -tes, etc. (profiles → profile, not profil)\n\tif (\n\t\tlower.endsWith('es') &&\n\t\tname.length > 2 &&\n\t\t(lower.endsWith('shes') ||\n\t\t\tlower.endsWith('ches') ||\n\t\t\tlower.endsWith('xes') ||\n\t\t\tlower.endsWith('zes') ||\n\t\t\t(lower.endsWith('ses') &&\n\t\t\t\t!lower.endsWith('ases') &&\n\t\t\t\t!lower.endsWith('uses')))\n\t) {\n\t\treturn name.slice(0, -2);\n\t}\n\n\t// Handle regular plurals ending in 's' (but not 'ss')\n\tif (lower.endsWith('s') && !lower.endsWith('ss') && name.length > 1) {\n\t\treturn name.slice(0, -1);\n\t}\n\n\t// Already singular or unknown pattern\n\treturn name;\n}\n\n/**\n * Convert table name to plural form.\n * Simple heuristic: add 's' or 'es' or 'ies'.\n */\nexport function pluralize(name: string): string {\n\tif (\n\t\tname.endsWith('y') &&\n\t\t!['ay', 'ey', 'oy', 'uy'].some((s) => name.endsWith(s))\n\t) {\n\t\treturn `${name.slice(0, -1)}ies`;\n\t}\n\tif (\n\t\tname.endsWith('s') ||\n\t\tname.endsWith('x') ||\n\t\tname.endsWith('ch') ||\n\t\tname.endsWith('sh')\n\t) {\n\t\treturn `${name}es`;\n\t}\n\treturn `${name}s`;\n}\n\n/**\n * Capitalize first letter.\n */\nexport function capitalize(name: string): string {\n\treturn name.charAt(0).toUpperCase() + name.slice(1);\n}\n\n/**\n * Decapitalize first letter.\n */\nexport function decapitalize(name: string): string {\n\treturn name.charAt(0).toLowerCase() + name.slice(1);\n}\n\n/**\n * Get the inverse relation name for a self-referential FK.\n * Special case: parent → children (most common hierarchy pattern).\n * Otherwise: pluralize the belongsTo name (manager → managers).\n */\nexport function getSelfRefInverseName(belongsToName: string): string {\n\t// The most common self-ref pattern\n\tif (belongsToName === 'parent') return 'children';\n\n\t// For other cases, just pluralize (manager → managers)\n\treturn pluralize(belongsToName);\n}\n\n/**\n * Pseudo-column metadata for a self-referential FK.\n * Exported for use by schema builder.\n */\ninterface SelfRefPseudoColumn {\n\t/** FK column name (e.g., 'parentId', 'managerId') */\n\tforeignKeyColumn: string;\n\t/** Target column (usually 'id') */\n\ttargetColumn: string;\n\t/** Parent role name (e.g., 'parent', 'manager') */\n\tparentRole: string;\n\t/** Child role name (e.g., 'children', 'subordinates') */\n\tchildRole: string;\n}\n\n/**\n * Extract pseudo-column metadata from detected FKs.\n * Only self-referential FKs produce pseudo-columns.\n */\nexport function extractSelfRefPseudoColumns(\n\ttableName: string,\n\tfks: DetectedFK[],\n): SelfRefPseudoColumn[] {\n\tconst selfRefFKs = fks.filter((fk) => fk.targetTable === tableName);\n\tif (selfRefFKs.length === 0) return [];\n\n\t// Single self-ref FK: use default parent/child keywords\n\t// Multiple self-ref FKs: require explicit roles (validated elsewhere)\n\treturn selfRefFKs.map((fk) => ({\n\t\tforeignKeyColumn: fk.column,\n\t\ttargetColumn: fk.targetColumn,\n\t\tparentRole: fk.parentRole ?? fk.inferredName,\n\t\tchildRole: fk.childRole ?? getSelfRefInverseName(fk.inferredName),\n\t}));\n}\n\n/**\n * Validate self-referential FK roles for a table.\n * Returns error messages if validation fails.\n */\nexport function validateSelfRefRoles(\n\ttableName: string,\n\tpseudoColumns: SelfRefPseudoColumn[],\n\treservedNames: Set<string> = new Set([\n\t\t'parent',\n\t\t'child',\n\t\t'ascendant',\n\t\t'descendant',\n\t]),\n): string[] {\n\tconst errors: string[] = [];\n\n\tif (pseudoColumns.length === 0) return errors;\n\n\t// Collect all role names for collision detection\n\tconst allRoles = new Set<string>();\n\n\tfor (const pc of pseudoColumns) {\n\t\t// Check reserved name collision (only for multi-FK tables)\n\t\tif (pseudoColumns.length > 1) {\n\t\t\tif (reservedNames.has(pc.parentRole)) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Table '${tableName}': parentRole '${pc.parentRole}' conflicts with reserved keyword. Use a custom role name.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (reservedNames.has(pc.childRole)) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Table '${tableName}': childRole '${pc.childRole}' conflicts with reserved keyword. Use a custom role name.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Check cross-collision between different FKs\n\t\tif (allRoles.has(pc.parentRole)) {\n\t\t\terrors.push(\n\t\t\t\t`Table '${tableName}': duplicate parentRole '${pc.parentRole}'. Each self-ref FK needs unique roles.`,\n\t\t\t);\n\t\t}\n\t\tif (allRoles.has(pc.childRole)) {\n\t\t\terrors.push(\n\t\t\t\t`Table '${tableName}': duplicate childRole '${pc.childRole}'. Each self-ref FK needs unique roles.`,\n\t\t\t);\n\t\t}\n\n\t\tallRoles.add(pc.parentRole);\n\t\tallRoles.add(pc.childRole);\n\t}\n\n\treturn errors;\n}\n\n// =============================================================================\n// FK Detection\n// =============================================================================\n\ninterface DetectedFK {\n\t/** Column name in source table */\n\tcolumn: string;\n\t/** Target table name */\n\ttargetTable: string;\n\t/** Inferred relation name (e.g., 'author' from 'authorId') */\n\tinferredName: string;\n\t/** Whether this was explicitly defined via `references` */\n\texplicit: boolean;\n\t/** Target column (from references.column or default 'id') */\n\ttargetColumn: string;\n\t/** Custom parent role for self-ref FKs (from parentRole or inferred) */\n\tparentRole?: string;\n\t/** Custom child role for self-ref FKs (from childRole or inferred) */\n\tchildRole?: string;\n}\n\n/**\n * Detect foreign keys in a table.\n * Priority: explicit `references` > convention pattern.\n */\nexport function detectForeignKeys(\n\ttableName: string,\n\ttable: SchemaTableDefinition,\n\tconventions: Required<SchemaConventionsDefinition>,\n\ttableNames: Set<string>,\n): DetectedFK[] {\n\tconst fks: DetectedFK[] = [];\n\tconst pattern = conventions.fkPattern;\n\n\tfor (const [colName, colDef] of Object.entries(table)) {\n\t\t// PRIORITY 1: Explicit `references` takes precedence\n\t\tif (colDef.references) {\n\t\t\tconst targetTable = colDef.references.table;\n\t\t\tif (tableNames.has(targetTable)) {\n\t\t\t\t// Infer relation name from column (remove 'Id' suffix if present)\n\t\t\t\tconst inferredName = colName.endsWith('Id')\n\t\t\t\t\t? colName.slice(0, -2)\n\t\t\t\t\t: singularize(targetTable);\n\n\t\t\t\tconst isSelfRef = targetTable === tableName;\n\t\t\t\tconst detectedFK: DetectedFK = {\n\t\t\t\t\tcolumn: colName,\n\t\t\t\t\ttargetTable,\n\t\t\t\t\tinferredName,\n\t\t\t\t\texplicit: true,\n\t\t\t\t\ttargetColumn: colDef.references.column ?? 'id',\n\t\t\t\t};\n\n\t\t\t\t// Add self-ref roles if applicable\n\t\t\t\tif (isSelfRef) {\n\t\t\t\t\tdetectedFK.parentRole = colDef.references.parentRole ?? inferredName;\n\t\t\t\t\tdetectedFK.childRole =\n\t\t\t\t\t\tcolDef.references.childRole ?? getSelfRefInverseName(inferredName);\n\t\t\t\t}\n\n\t\t\t\tfks.push(detectedFK);\n\t\t\t}\n\t\t\tcontinue; // Skip convention check if explicit reference exists\n\t\t}\n\n\t\t// PRIORITY 2: Convention-based detection\n\t\t// Pattern like '{singular}Id' → check if column matches any table's singular form\n\t\tfor (const candidateTable of tableNames) {\n\t\t\tif (candidateTable === tableName) continue; // Skip self (handled separately)\n\n\t\t\tconst singular = singularize(candidateTable);\n\t\t\tconst expectedColumn = pattern.replace('{singular}', singular);\n\n\t\t\tif (colName === expectedColumn) {\n\t\t\t\tfks.push({\n\t\t\t\t\tcolumn: colName,\n\t\t\t\t\ttargetTable: candidateTable,\n\t\t\t\t\tinferredName: singular,\n\t\t\t\t\texplicit: false,\n\t\t\t\t\ttargetColumn: 'id',\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Check for self-referential FK (e.g., parentId → same table)\n\t\tif (colName.endsWith('Id')) {\n\t\t\tconst prefix = colName.slice(0, -2);\n\t\t\tconst singular = singularize(tableName);\n\t\t\t// Common self-ref patterns: parentId, managerId, etc.\n\t\t\tif (\n\t\t\t\t['parent', 'manager', 'supervisor', 'owner', singular].includes(prefix)\n\t\t\t) {\n\t\t\t\tif (!fks.some((fk) => fk.column === colName)) {\n\t\t\t\t\tfks.push({\n\t\t\t\t\t\tcolumn: colName,\n\t\t\t\t\t\ttargetTable: tableName,\n\t\t\t\t\t\tinferredName: prefix,\n\t\t\t\t\t\texplicit: false,\n\t\t\t\t\t\ttargetColumn: 'id',\n\t\t\t\t\t\t// Auto-infer roles for convention-based self-ref FKs\n\t\t\t\t\t\tparentRole: prefix,\n\t\t\t\t\t\tchildRole: getSelfRefInverseName(prefix),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fks;\n}\n\n// =============================================================================\n// M:N Detection\n// =============================================================================\n\ninterface DetectedManyToMany {\n\t/** Junction table name */\n\tjunction: string;\n\t/** First table in the M:N relation */\n\ttableA: string;\n\t/** Second table in the M:N relation */\n\ttableB: string;\n\t/** FK column pointing to tableA */\n\tfkA: string;\n\t/** FK column pointing to tableB */\n\tfkB: string;\n}\n\n/**\n * Check if a column is a \"business\" column (not FK, not metadata).\n */\nfunction isBusinessColumn(\n\tcolName: string,\n\tcolDef: SchemaColumnDefinition,\n\ttimestamps: string[],\n): boolean {\n\t// Primary key is not business data\n\tif (colDef.primaryKey) return false;\n\t// Timestamp columns are metadata\n\tif (timestamps.includes(colName)) return false;\n\t// FK columns are not business data (they reference other tables)\n\tif (colDef.references) return false;\n\t// Columns ending in 'Id' are likely FKs (convention)\n\tif (colName.endsWith('Id')) return false;\n\t// Common metadata columns\n\tif (['id', 'createdBy', 'updatedBy', 'deletedAt'].includes(colName))\n\t\treturn false;\n\n\t// Everything else is business data\n\treturn true;\n}\n\n/**\n * Detect pure M:N junction tables.\n * Criteria: exactly 2 FK columns, no business columns.\n */\nexport function detectManyToMany(\n\ttables: SchemaTablesDefinition,\n\tconventions: Required<SchemaConventionsDefinition>,\n\ttableNames: Set<string>,\n): DetectedManyToMany[] {\n\tconst results: DetectedManyToMany[] = [];\n\n\tfor (const [tableName, table] of Object.entries(tables)) {\n\t\tconst fks = detectForeignKeys(tableName, table, conventions, tableNames);\n\n\t\t// Must have exactly 2 FKs\n\t\tif (fks.length !== 2) continue;\n\n\t\t// Check for business columns\n\t\tconst hasBusinessColumns = Object.entries(table).some(([colName, colDef]) =>\n\t\t\tisBusinessColumn(colName, colDef, conventions.timestamps),\n\t\t);\n\n\t\tif (hasBusinessColumns) continue;\n\n\t\t// This is a pure junction table\n\t\tconst fkA = fks[0];\n\t\tconst fkB = fks[1];\n\t\tif (fkA && fkB) {\n\t\t\tresults.push({\n\t\t\t\tjunction: tableName,\n\t\t\t\ttableA: fkA.targetTable,\n\t\t\t\ttableB: fkB.targetTable,\n\t\t\t\tfkA: fkA.column,\n\t\t\t\tfkB: fkB.column,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn results;\n}\n\n// =============================================================================\n// Relation Inference\n// =============================================================================\n\n/**\n * Infer all relations from table definitions.\n * Returns a map of 'sourceTable.relationName' → RelationDefinition.\n */\nexport function inferRelationsFromSchema(\n\ttables: SchemaTablesDefinition,\n\tconventions: Required<SchemaConventionsDefinition>,\n\texplicitRelations: SchemaRelationsDefinition = {},\n): SchemaRelationsDefinition {\n\tconst result: SchemaRelationsDefinition = { ...explicitRelations };\n\tconst tableNames = new Set(Object.keys(tables));\n\n\t// First pass: detect M:N relations (junction tables)\n\tconst manyToManys = detectManyToMany(tables, conventions, tableNames);\n\tconst junctionTables = new Set(manyToManys.map((m) => m.junction));\n\n\t// Add M:N relations (bidirectional)\n\tfor (const m2m of manyToManys) {\n\t\tconst { junction, tableA, tableB, fkA, fkB } = m2m;\n\n\t\t// Use opposite table name for relation path (not junction name)\n\t\tconst relNameAtoB = conventions.pluralize\n\t\t\t? pluralize(singularize(tableB))\n\t\t\t: tableB;\n\t\tconst relNameBtoA = conventions.pluralize\n\t\t\t? pluralize(singularize(tableA))\n\t\t\t: tableA;\n\n\t\tconst keyAtoB = `${tableA}.${relNameAtoB}`;\n\t\tconst keyBtoA = `${tableB}.${relNameBtoA}`;\n\n\t\t// Only add if not explicitly defined\n\t\tif (!(keyAtoB in result)) {\n\t\t\tconst rel: SchemaManyToManyRelation = {\n\t\t\t\tkind: 'manyToMany',\n\t\t\t\ttarget: tableB,\n\t\t\t\tthrough: junction,\n\t\t\t\tsourceFk: fkA,\n\t\t\t\ttargetFk: fkB,\n\t\t\t};\n\t\t\tresult[keyAtoB] = rel;\n\t\t}\n\n\t\tif (!(keyBtoA in result)) {\n\t\t\tconst rel: SchemaManyToManyRelation = {\n\t\t\t\tkind: 'manyToMany',\n\t\t\t\ttarget: tableA,\n\t\t\t\tthrough: junction,\n\t\t\t\tsourceFk: fkB,\n\t\t\t\ttargetFk: fkA,\n\t\t\t};\n\t\t\tresult[keyBtoA] = rel;\n\t\t}\n\t}\n\n\t// Second pass: detect 1:N and N:1 relations (skip junction tables)\n\tfor (const [tableName, table] of Object.entries(tables)) {\n\t\tif (junctionTables.has(tableName)) continue;\n\n\t\tconst fks = detectForeignKeys(tableName, table, conventions, tableNames);\n\n\t\tfor (const fk of fks) {\n\t\t\t// Skip FKs that point to junction tables\n\t\t\tif (junctionTables.has(fk.targetTable)) continue;\n\n\t\t\t// BelongsTo: source has FK to target\n\t\t\tconst belongsToKey = `${tableName}.${fk.inferredName}`;\n\t\t\tif (!(belongsToKey in result)) {\n\t\t\t\tconst rel: SchemaBelongsToRelation = {\n\t\t\t\t\tkind: 'belongsTo',\n\t\t\t\t\ttarget: fk.targetTable,\n\t\t\t\t\tforeignKey: fk.column,\n\t\t\t\t\ttargetKey: fk.targetColumn,\n\t\t\t\t};\n\t\t\t\tresult[belongsToKey] = rel;\n\t\t\t}\n\n\t\t\t// HasMany: target has many of source (inverse)\n\t\t\t// For self-referential FKs, use semantic inverse name (parent → children)\n\t\t\tconst isSelfRef = fk.targetTable === tableName;\n\t\t\tconst hasManyName = isSelfRef\n\t\t\t\t? getSelfRefInverseName(fk.inferredName)\n\t\t\t\t: (() => {\n\t\t\t\t\t\t// When the FK has a custom alias (inferredName differs from the\n\t\t\t\t\t\t// singularized target table name), use pluralize(inferredName) so\n\t\t\t\t\t\t// that multiple FKs to the same table get distinct hasMany names.\n\t\t\t\t\t\t// e.g. caller_id (inferredName='caller') → 'callers'\n\t\t\t\t\t\t// callee_id (inferredName='callee') → 'callees'\n\t\t\t\t\t\tconst hasCustomAlias =\n\t\t\t\t\t\t\tfk.inferredName !== singularize(fk.targetTable);\n\t\t\t\t\t\tif (hasCustomAlias) {\n\t\t\t\t\t\t\treturn conventions.pluralize\n\t\t\t\t\t\t\t\t? pluralize(fk.inferredName)\n\t\t\t\t\t\t\t\t: fk.inferredName;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn conventions.pluralize\n\t\t\t\t\t\t\t? pluralize(singularize(tableName))\n\t\t\t\t\t\t\t: tableName;\n\t\t\t\t\t})();\n\t\t\tconst hasManyKey = `${fk.targetTable}.${hasManyName}`;\n\t\t\tif (!(hasManyKey in result)) {\n\t\t\t\tconst rel: SchemaHasManyRelation = {\n\t\t\t\t\tkind: 'hasMany',\n\t\t\t\t\ttarget: tableName,\n\t\t\t\t\tforeignKey: fk.column,\n\t\t\t\t\tsourceKey: 'id',\n\t\t\t\t};\n\t\t\t\tresult[hasManyKey] = rel;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n","/**\n * Schema DSL - defineSchema() function\n *\n * Main entry point for defining the schema Source of Truth.\n * Merges explicit definitions with convention-inferred relations.\n *\n * Migrated from @dbsp/schema/define.ts as part of ARCH-003.\n */\n\nimport {\n\tDEFAULT_CONVENTIONS,\n\tinferRelationsFromSchema,\n} from './conventions.js';\nimport type {\n\tResolvedSchema,\n\tSchemaConfigInput,\n\tSchemaConventionsDefinition,\n\tSchemaDefaultFilters,\n\tSchemaHintsDefinition,\n\tSchemaIndexesDefinition,\n\tSchemaRelationsDefinition,\n\tSchemaTablesDefinition,\n} from './schema-dsl-types.js';\n\n/**\n * Define a schema with tables, relations, hints, and conventions.\n *\n * @example Simple - just tables\n * ```typescript\n * const schema = defineSchema({\n * users: {\n * id: { type: 'uuid', primaryKey: true },\n * name: { type: 'string', nullable: false },\n * },\n * posts: {\n * id: { type: 'uuid', primaryKey: true },\n * authorId: { type: 'uuid', references: { table: 'users' } },\n * },\n * });\n * ```\n *\n * @example With config\n * ```typescript\n * const schema = defineSchema(\n * {\n * users: { id: { type: 'uuid', primaryKey: true } },\n * roles: { id: { type: 'uuid', primaryKey: true } },\n * },\n * {\n * relations: {...}\n * }\n * );\n * ```\n */\nexport function defineSchema<T extends SchemaTablesDefinition>(\n\ttables: T,\n\tconfig?: SchemaConfigInput,\n): ResolvedSchema<T> {\n\tconst relations: SchemaRelationsDefinition = config?.relations ?? {};\n\tconst hints: SchemaHintsDefinition = config?.hints ?? {};\n\tconst conventions: SchemaConventionsDefinition = config?.conventions ?? {};\n\tconst indexes: SchemaIndexesDefinition = config?.indexes ?? {};\n\tconst defaultFilters: SchemaDefaultFilters = config?.defaultFilters ?? {};\n\n\t// Merge user conventions with defaults\n\tconst resolvedConventions: Required<SchemaConventionsDefinition> = {\n\t\t...DEFAULT_CONVENTIONS,\n\t\t...conventions,\n\t};\n\n\t// Infer relations from table definitions + merge with explicit\n\tconst allRelations = inferRelationsFromSchema(\n\t\ttables,\n\t\tresolvedConventions,\n\t\trelations,\n\t);\n\n\t// Validate explicit relations reference existing tables\n\tvalidateRelations(tables, relations);\n\n\t// Validate hints reference existing relations\n\tvalidateHints(allRelations, hints);\n\n\t// Validate default filters reference existing tables\n\tvalidateDefaultFilters(tables, defaultFilters);\n\n\treturn {\n\t\ttables,\n\t\trelations: allRelations,\n\t\thints,\n\t\tconventions: resolvedConventions,\n\t\tindexes,\n\t\tdefaultFilters,\n\t};\n}\n\n/**\n * Validate that explicit relations reference existing tables.\n */\nfunction validateRelations(\n\ttables: SchemaTablesDefinition,\n\trelations: SchemaRelationsDefinition,\n): void {\n\tconst tableNames = new Set(Object.keys(tables));\n\n\tfor (const [key, rel] of Object.entries(relations)) {\n\t\tconst sourceTable = key.split('.')[0] ?? key;\n\n\t\tif (!tableNames.has(sourceTable)) {\n\t\t\tthrow new SchemaValidationError(\n\t\t\t\t`Relation '${key}' references non-existent source table '${sourceTable}'`,\n\t\t\t);\n\t\t}\n\n\t\tif (!tableNames.has(rel.target)) {\n\t\t\tthrow new SchemaValidationError(\n\t\t\t\t`Relation '${key}' references non-existent target table '${rel.target}'`,\n\t\t\t);\n\t\t}\n\n\t\tif (rel.kind === 'manyToMany' && !tableNames.has(rel.through)) {\n\t\t\tthrow new SchemaValidationError(\n\t\t\t\t`Relation '${key}' references non-existent junction table '${rel.through}'`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Validate that hints reference existing relation paths.\n */\nfunction validateHints(\n\trelations: SchemaRelationsDefinition,\n\thints: SchemaHintsDefinition,\n): void {\n\tfor (const path of Object.keys(hints)) {\n\t\tif (!(path in relations)) {\n\t\t\tthrow new SchemaValidationError(\n\t\t\t\t`Hint path '${path}' does not match any relation. ` +\n\t\t\t\t\t`Available: ${Object.keys(relations).join(', ')}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Validate that default filters reference existing tables.\n */\nfunction validateDefaultFilters(\n\ttables: SchemaTablesDefinition,\n\tdefaultFilters: SchemaDefaultFilters,\n): void {\n\tconst tableNames = new Set(Object.keys(tables));\n\n\tfor (const tableName of Object.keys(defaultFilters)) {\n\t\tif (!tableNames.has(tableName)) {\n\t\t\tthrow new SchemaValidationError(\n\t\t\t\t`Default filter for non-existent table '${tableName}'. ` +\n\t\t\t\t\t`Available: ${[...tableNames].join(', ')}`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Error thrown when schema validation fails.\n */\nexport class SchemaValidationError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'SchemaValidationError';\n\t}\n}\n","/**\n * Schema DSL Types\n *\n * Input types for defineSchema() - the user-facing schema definition DSL.\n * These types are simpler than the IR types and serve as the \"source of truth\"\n * for schema definitions before they're processed into ModelIR.\n *\n * Migrated from @dbsp/schema/types.ts as part of ARCH-003.\n */\n\nimport type { WhereIntent } from '@dbsp/types';\n\n// =============================================================================\n// Column Types (DSL - simpler than ColumnType in model-ir.ts)\n// =============================================================================\n\n/**\n * Supported column types in the schema DSL.\n * Maps to database types during DDL generation.\n */\nexport type SchemaColumnType =\n\t| 'uuid'\n\t| 'string'\n\t| 'text'\n\t| 'integer'\n\t| 'bigint'\n\t| 'decimal'\n\t| 'boolean'\n\t| 'timestamp'\n\t| 'date'\n\t| 'time'\n\t| 'json'\n\t| 'jsonb'\n\t// PostgreSQL-specific range types (will error on non-PG dialects)\n\t| 'daterange'\n\t| 'tsrange'\n\t| 'tstzrange'\n\t| 'int4range'\n\t| 'int8range'\n\t| 'numrange';\n\n/** Foreign key delete behavior */\nexport type SchemaOnDeleteAction =\n\t| 'CASCADE'\n\t| 'SET NULL'\n\t| 'RESTRICT'\n\t| 'NO ACTION';\n\n/**\n * Foreign key reference definition.\n * When present, takes priority over convention-based FK detection.\n */\nexport interface SchemaForeignKeyReference {\n\t/** Target table name */\n\ttable: string;\n\t/** Target column name (defaults to 'id') */\n\tcolumn?: string;\n\t/** Delete behavior (CASCADE, SET NULL, RESTRICT, NO ACTION) */\n\tonDelete?: SchemaOnDeleteAction;\n\t/**\n\t * Custom role name for parent direction in self-referential FKs.\n\t * Required when table has multiple self-referential FKs.\n\t * Example: parentRole: 'manager' for managerId FK\n\t * @default 'parent' (for single self-ref FK)\n\t */\n\tparentRole?: string;\n\t/**\n\t * Custom role name for child direction in self-referential FKs.\n\t * Required when table has multiple self-referential FKs.\n\t * Example: childRole: 'subordinates' for managerId FK\n\t * @default 'children' or pluralized parentRole (for single self-ref FK)\n\t */\n\tchildRole?: string;\n}\n\n/**\n * Column definition in the schema DSL.\n */\nexport interface SchemaColumnDefinition {\n\t/** Column data type */\n\ttype: SchemaColumnType;\n\t/** Whether the column is the primary key */\n\tprimaryKey?: boolean;\n\t/** Whether the column allows NULL values */\n\tnullable?: boolean;\n\t/** Whether the column has a unique constraint */\n\tunique?: boolean;\n\t/** Default value (e.g., 'now()', 'gen_random_uuid()', 0, true) */\n\tdefault?: string | number | boolean;\n\t/** Explicit foreign key reference (takes priority over conventions) */\n\treferences?: SchemaForeignKeyReference;\n\t/** Create an index on this column (true for auto-name, string for custom name) */\n\tindex?: boolean | string;\n}\n\n/**\n * Table definition: mapping of column names to their definitions.\n */\nexport type SchemaTableDefinition = Record<string, SchemaColumnDefinition>;\n\n/**\n * All tables in the schema.\n */\nexport type SchemaTablesDefinition = Record<string, SchemaTableDefinition>;\n\n/**\n * Index definition for composite indexes.\n */\nexport interface SchemaIndexDefinition {\n\t/** Columns included in the index */\n\tcolumns: string[];\n\t/** Whether this is a unique index */\n\tunique?: boolean;\n\t/** Custom index name (auto-generated if not provided) */\n\tname?: string;\n}\n\n/**\n * Index configuration by table.\n */\nexport type SchemaIndexesDefinition = Record<string, SchemaIndexDefinition[]>;\n\n// =============================================================================\n// Relation Types (Discriminated Union)\n// =============================================================================\n\n/**\n * Relation kinds for discriminated union.\n */\nexport type SchemaRelationKind = 'belongsTo' | 'hasMany' | 'manyToMany';\n\n/**\n * Strategy for including related data in queries.\n * - 'join': Use SQL JOIN (default for belongsTo)\n * - 'subquery': Execute subquery query\n * - 'cte': Use Common Table Expression\n * - 'lateral': Use LATERAL JOIN\n * - 'json_agg': Use JSON aggregation\n * - 'auto': Let planner decide based on relation type\n */\nexport type SchemaIncludeStrategy =\n\t| 'join'\n\t| 'subquery'\n\t| 'cte'\n\t| 'lateral'\n\t| 'json_agg'\n\t| 'auto';\n\n/**\n * Base properties shared by all relation types.\n */\ninterface SchemaRelationBase {\n\t/** Target table name */\n\ttarget: string;\n\t/** Include strategy hint for the planner */\n\tincludeStrategy?: SchemaIncludeStrategy;\n}\n\n/**\n * BelongsTo relation: source table has FK to target table.\n * Example: posts.author → users (posts.authorId references users.id)\n */\nexport interface SchemaBelongsToRelation extends SchemaRelationBase {\n\tkind: 'belongsTo';\n\t/** Foreign key column in the source table */\n\tforeignKey: string;\n\t/** Target column (defaults to 'id') */\n\ttargetKey?: string;\n}\n\n/**\n * HasMany relation: target table has FK to source table.\n * Example: users.posts → posts (posts.authorId references users.id)\n */\nexport interface SchemaHasManyRelation extends SchemaRelationBase {\n\tkind: 'hasMany';\n\t/** Foreign key column in the target table */\n\tforeignKey: string;\n\t/** Source column (defaults to 'id') */\n\tsourceKey?: string;\n}\n\n/**\n * ManyToMany relation: junction table connects source and target.\n * Example: posts ↔ categories via post_categories\n */\nexport interface SchemaManyToManyRelation extends SchemaRelationBase {\n\tkind: 'manyToMany';\n\t/** Junction table name */\n\tthrough: string;\n\t/** FK column in junction pointing to source */\n\tsourceFk: string;\n\t/** FK column in junction pointing to target */\n\ttargetFk: string;\n}\n\n/**\n * Union of all relation types.\n * Use `kind` field for type narrowing.\n */\nexport type SchemaRelationDefinition =\n\t| SchemaBelongsToRelation\n\t| SchemaHasManyRelation\n\t| SchemaManyToManyRelation;\n\n/**\n * Explicit relations mapping.\n * Keys are 'sourceTable.relationName' format.\n */\nexport type SchemaRelationsDefinition = Record<\n\tstring,\n\tSchemaRelationDefinition\n>;\n\n// =============================================================================\n// Planner Hints\n// =============================================================================\n\n/**\n * Strategy hint for filtering on to-many relations.\n */\nexport type SchemaFilterStrategy = 'exists' | 'join';\n\n/**\n * Cardinality hint for relation traversal.\n */\nexport type SchemaCardinality = 'one' | 'many';\n\n/**\n * Hint definition for a specific relation path.\n */\nexport interface SchemaHintDefinition {\n\t/** Preferred filter strategy */\n\tdefaultStrategy?: SchemaFilterStrategy;\n\t/** Expected cardinality */\n\tcardinality?: SchemaCardinality;\n}\n\n/**\n * All hints, keyed by 'table.relation' path.\n */\nexport type SchemaHintsDefinition = Record<string, SchemaHintDefinition>;\n\n// =============================================================================\n// Convention Configuration\n// =============================================================================\n\n/**\n * Convention settings for automatic FK detection and naming.\n */\nexport interface SchemaConventionsDefinition {\n\t/**\n\t * Pattern for foreign key column names.\n\t * {singular} is replaced with singular table name.\n\t * @default '{singular}Id'\n\t */\n\tfkPattern?: string;\n\n\t/**\n\t * Whether to auto-pluralize relation names.\n\t * @default true\n\t */\n\tpluralize?: boolean;\n\n\t/**\n\t * Column names recognized as timestamps.\n\t * @default ['createdAt', 'updatedAt']\n\t */\n\ttimestamps?: string[];\n\n\t/**\n\t * Automatically create indexes on foreign key columns.\n\t * FK columns are frequently used in JOINs, so indexing is a best practice.\n\t * @default true\n\t */\n\tfkAutoIndex?: boolean;\n}\n\n// =============================================================================\n// Schema Definition\n// =============================================================================\n\n/**\n * Complete schema definition input for defineSchema() wrapped form.\n * Prefer the new hybrid API: defineSchema(tables, config?)\n */\nexport interface SchemaDefinitionInput<\n\tT extends SchemaTablesDefinition = SchemaTablesDefinition,\n> {\n\t/** Table definitions */\n\ttables: T;\n\t/** Explicit relation definitions (override auto-detected) */\n\trelations?: SchemaRelationsDefinition;\n\t/** Planner hints */\n\thints?: SchemaHintsDefinition;\n\t/** Convention configuration */\n\tconventions?: SchemaConventionsDefinition;\n}\n\n/**\n * Per-table default filters applied to all queries.\n * Commonly used for soft delete filtering.\n */\nexport type SchemaDefaultFilters = {\n\t[tableName: string]: WhereIntent;\n};\n\n/**\n * Configuration options for defineSchema (new API).\n */\nexport interface SchemaConfigInput {\n\t/** Explicit relation definitions (override auto-detected) */\n\trelations?: SchemaRelationsDefinition;\n\t/** Planner hints */\n\thints?: SchemaHintsDefinition;\n\t/** Convention configuration */\n\tconventions?: SchemaConventionsDefinition;\n\t/** Table-level index definitions (composite indexes) */\n\tindexes?: SchemaIndexesDefinition;\n\t/**\n\t * Default filters applied automatically to all queries on each table.\n\t * Use for soft delete (`isNull('deletedAt')`), multi-tenant, or active filtering.\n\t * Override per-query with `.withoutDefaultFilters()`.\n\t */\n\tdefaultFilters?: SchemaDefaultFilters;\n}\n\n/**\n * Resolved schema with all relations (explicit + inferred).\n * This is the output of defineSchema().\n */\nexport interface ResolvedSchema<\n\tT extends SchemaTablesDefinition = SchemaTablesDefinition,\n> {\n\t/** Original table definitions */\n\ttables: T;\n\t/** All relations (explicit + auto-detected) */\n\trelations: SchemaRelationsDefinition;\n\t/** Planner hints */\n\thints: SchemaHintsDefinition;\n\t/** Resolved conventions with defaults applied */\n\tconventions: Required<SchemaConventionsDefinition>;\n\t/** Table-level index definitions */\n\tindexes: SchemaIndexesDefinition;\n\t/** Default filters per table (e.g., soft delete) */\n\tdefaultFilters: SchemaDefaultFilters;\n}\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Type guard for BelongsTo relation.\n */\nexport function isBelongsTo(\n\trel: SchemaRelationDefinition,\n): rel is SchemaBelongsToRelation {\n\treturn rel.kind === 'belongsTo';\n}\n\n/**\n * Type guard for HasMany relation.\n */\nexport function isHasMany(\n\trel: SchemaRelationDefinition,\n): rel is SchemaHasManyRelation {\n\treturn rel.kind === 'hasMany';\n}\n\n/**\n * Type guard for ManyToMany relation.\n */\nexport function isManyToMany(\n\trel: SchemaRelationDefinition,\n): rel is SchemaManyToManyRelation {\n\treturn rel.kind === 'manyToMany';\n}\n","/**\n * Error thrown when attempting to execute a query without a database configured.\n *\n * @example\n * ```typescript\n * const orm = createOrm({ model: schema, adapter: mockAdapter }); // Mock adapter\n * await orm.select('users').findMany(); // Throws ExecutionError (mock can't execute)\n * ```\n */\nexport class ExecutionError extends Error {\n\toverride readonly name = 'ExecutionError' as const;\n\n\t/**\n\t * The operation that was attempted.\n\t */\n\treadonly operation: string;\n\n\t/**\n\t * The reason the operation failed.\n\t */\n\treadonly reason: string;\n\n\t/**\n\t * How to fix the issue.\n\t */\n\treadonly fix: string;\n\n\tconstructor(opts: { operation: string; reason: string; fix: string }) {\n\t\tconst message =\n\t\t\t`Cannot execute ${opts.operation}: ${opts.reason}\\n\\n` +\n\t\t\t`To fix: ${opts.fix}`;\n\n\t\tsuper(message);\n\n\t\tthis.operation = opts.operation;\n\t\tthis.reason = opts.reason;\n\t\tthis.fix = opts.fix;\n\n\t\tObject.setPrototypeOf(this, ExecutionError.prototype);\n\t}\n}\n\n/**\n * Error thrown when firstOrThrow() finds no results.\n *\n * @example\n * ```typescript\n * await orm.select('users').where(eq('id', 999)).firstOrThrow();\n * // Throws NotFoundError: No record found for 'users'\n * ```\n */\nexport class NotFoundError extends Error {\n\toverride readonly name = 'NotFoundError' as const;\n\n\t/**\n\t * The table that was queried.\n\t */\n\treadonly table: string;\n\n\t/**\n\t * Optional: hint about the query that returned no results.\n\t */\n\treadonly hint?: string;\n\n\tconstructor(table: string, hint?: string) {\n\t\tconst message = hint\n\t\t\t? `No record found for '${table}'. ${hint}`\n\t\t\t: `No record found for '${table}'`;\n\n\t\tsuper(message);\n\t\tthis.table = table;\n\t\tif (hint !== undefined) {\n\t\t\tthis.hint = hint;\n\t\t}\n\t\tObject.setPrototypeOf(this, NotFoundError.prototype);\n\t}\n}\n\n/**\n * Error thrown when strict mode is enabled and an ambiguous relation is detected.\n *\n * This error provides detailed information about the ambiguity and available options\n * for disambiguation.\n *\n * @example\n * ```typescript\n * try {\n * orm.select('users').include('posts').plan();\n * } catch (error) {\n * if (error instanceof AmbiguousRelationError) {\n * console.log(error.options); // ['authoredPosts', 'reviewedPosts']\n * }\n * }\n * ```\n */\nexport class AmbiguousRelationError extends Error {\n\toverride readonly name = 'AmbiguousRelationError' as const;\n\n\t/**\n\t * The source table where the ambiguous relation originates.\n\t */\n\treadonly sourceTable: string;\n\n\t/**\n\t * The target table that has multiple possible relations.\n\t */\n\treadonly targetTable: string;\n\n\t/**\n\t * Available relation names that can be used to disambiguate.\n\t * Use one of these values with `{ via: 'relationName' }` to resolve the ambiguity.\n\t */\n\treadonly options: readonly string[];\n\n\t/**\n\t * Public-safe message (no schema enumeration).\n\t * Matches the pattern of RelationNotFoundError, TableNotFoundError, ColumnNotFoundError.\n\t */\n\treadonly publicMessage: string;\n\n\tconstructor(\n\t\tsourceTable: string,\n\t\ttargetTable: string,\n\t\toptions: readonly string[],\n\t) {\n\t\t// Generic message for .message — does NOT embed schema details to avoid info leakage.\n\t\t// Detailed developer guidance is available via .sourceTable, .targetTable, .options.\n\t\tconst genericMessage = 'Ambiguous relation';\n\n\t\tsuper(genericMessage);\n\n\t\tthis.sourceTable = sourceTable;\n\t\tthis.targetTable = targetTable;\n\t\tthis.options = options;\n\t\tthis.publicMessage = genericMessage;\n\n\t\t// Required for proper instanceof checks when extending built-in classes\n\t\t// See: https://github.com/microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work\n\t\tObject.setPrototypeOf(this, AmbiguousRelationError.prototype);\n\t}\n}\n\n/**\n * Finds the closest match to a target string from a list of candidates.\n * Uses Levenshtein distance for fuzzy matching.\n *\n * @example\n * ```typescript\n * findClosestMatch('usrs', ['users', 'posts', 'comments']); // 'users'\n * findClosestMatch('xyz', ['users', 'posts']); // undefined (no close match)\n * ```\n */\nexport function findClosestMatch(\n\ttarget: string,\n\tcandidates: readonly string[],\n): string | undefined {\n\tif (candidates.length === 0) return undefined;\n\n\tconst targetLower = target.toLowerCase();\n\tlet bestMatch: string | undefined;\n\tlet bestScore = Number.POSITIVE_INFINITY;\n\n\tfor (const candidate of candidates) {\n\t\tconst candidateLower = candidate.toLowerCase();\n\n\t\t// Exact prefix match is best\n\t\tif (candidateLower.startsWith(targetLower)) {\n\t\t\treturn candidate;\n\t\t}\n\n\t\t// Calculate simple distance (Levenshtein approximation for small strings)\n\t\tconst distance = levenshteinDistance(targetLower, candidateLower);\n\t\tif (distance < bestScore && distance <= Math.max(target.length, 3)) {\n\t\t\tbestScore = distance;\n\t\t\tbestMatch = candidate;\n\t\t}\n\t}\n\n\treturn bestMatch;\n}\n\n/**\n * Simple Levenshtein distance implementation.\n */\nfunction levenshteinDistance(a: string, b: string): number {\n\t// Pre-initialize matrix with zeros\n\tconst rows = b.length + 1;\n\tconst cols = a.length + 1;\n\tconst matrix: number[][] = [];\n\n\tfor (let i = 0; i < rows; i++) {\n\t\tmatrix[i] = new Array<number>(cols).fill(0);\n\t}\n\n\t// Initialize first column\n\tfor (let i = 0; i < rows; i++) {\n\t\tconst row = matrix[i];\n\t\tif (row) row[0] = i;\n\t}\n\t// Initialize first row\n\tconst firstRow = matrix[0];\n\tif (firstRow) {\n\t\tfor (let j = 0; j < cols; j++) {\n\t\t\tfirstRow[j] = j;\n\t\t}\n\t}\n\n\tfor (let i = 1; i < rows; i++) {\n\t\tconst currentRow = matrix[i];\n\t\tconst prevRow = matrix[i - 1];\n\t\tif (!currentRow || !prevRow) continue;\n\n\t\tfor (let j = 1; j < cols; j++) {\n\t\t\tconst prevDiag = prevRow[j - 1] ?? 0;\n\t\t\tconst prevUp = prevRow[j] ?? 0;\n\t\t\tconst prevLeft = currentRow[j - 1] ?? 0;\n\n\t\t\tif (b.charAt(i - 1) === a.charAt(j - 1)) {\n\t\t\t\tcurrentRow[j] = prevDiag;\n\t\t\t} else {\n\t\t\t\tcurrentRow[j] = Math.min(\n\t\t\t\t\tprevDiag + 1, // substitution\n\t\t\t\t\tprevLeft + 1, // insertion\n\t\t\t\t\tprevUp + 1, // deletion\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst lastRow = matrix[b.length];\n\treturn lastRow ? (lastRow[a.length] ?? 0) : 0;\n}\n\n/**\n * Error thrown when a requested relation does not exist.\n *\n * Provides helpful suggestions including available relations and fuzzy-matched\n * \"Did you mean?\" hints.\n *\n * @example\n * ```typescript\n * const err = new RelationNotFoundError({\n * table: 'users',\n * requested: 'comment',\n * available: ['posts', 'profile', 'comments'],\n * });\n * // err.message === 'Relation not found'\n * // err.available === ['posts', 'profile', 'comments']\n * // err.suggestion === 'comments'\n * ```\n */\nexport class RelationNotFoundError extends Error {\n\toverride readonly name = 'RelationNotFoundError' as const;\n\n\t/**\n\t * The table where the relation was requested.\n\t */\n\treadonly table: string;\n\n\t/**\n\t * The relation name that was requested but not found.\n\t */\n\treadonly requested: string;\n\n\t/**\n\t * Available relations on this table.\n\t */\n\treadonly available: readonly string[];\n\n\t/**\n\t * Suggested relation name (fuzzy match), if any.\n\t */\n\treadonly suggestion?: string;\n\n\t/**\n\t * Public-safe message (no schema enumeration).\n\t */\n\treadonly publicMessage: string;\n\n\tconstructor(opts: {\n\t\ttable: string;\n\t\trequested: string;\n\t\tavailable: readonly string[];\n\t}) {\n\t\tconst suggestion = findClosestMatch(opts.requested, opts.available);\n\n\t\t// Generic message — does NOT embed available list to avoid info leakage\n\t\tconst genericMessage = 'Relation not found';\n\n\t\tsuper(genericMessage);\n\n\t\tthis.table = opts.table;\n\t\tthis.requested = opts.requested;\n\t\tthis.available = opts.available;\n\t\tthis.publicMessage = genericMessage;\n\t\tif (suggestion !== undefined) {\n\t\t\tthis.suggestion = suggestion;\n\t\t}\n\n\t\tObject.setPrototypeOf(this, RelationNotFoundError.prototype);\n\t}\n}\n\n/**\n * Error thrown when an operation is invalid or malformed.\n *\n * @example\n * ```typescript\n * orm.insert('users').values([]).execute();\n * // Throws InvalidOperationError: No values provided for insert\n * ```\n */\nexport class InvalidOperationError extends Error {\n\toverride readonly name = 'InvalidOperationError' as const;\n\n\t/**\n\t * The operation that was attempted.\n\t */\n\treadonly operation: string;\n\n\t/**\n\t * The reason the operation is invalid.\n\t */\n\treadonly reason: string;\n\n\tconstructor(operation: string, reason: string) {\n\t\tconst message = `Invalid ${operation}: ${reason}`;\n\t\tsuper(message);\n\t\tthis.operation = operation;\n\t\tthis.reason = reason;\n\t\tObject.setPrototypeOf(this, InvalidOperationError.prototype);\n\t}\n}\n\n/**\n * Error thrown when an operation is potentially unsafe and requires explicit confirmation.\n *\n * @example\n * ```typescript\n * orm.update('users').set({ active: false }).execute();\n * // Throws UnsafeOperationError: WHERE clause required\n * ```\n */\n\n/**\n * Validate that a string is a safe SQL identifier (table, column, schema, alias).\n *\n * Rules:\n * 1. Must not be empty\n * 2. Must not exceed 63 characters (PostgreSQL limit)\n * 3. Must start with a letter or underscore\n * 4. Must contain only alphanumeric, underscore, or dollar sign\n *\n * @param value - The identifier to validate\n * @param type - Type label for error messages (e.g. 'schema', 'table', 'column')\n * @throws InvalidOperationError if validation fails\n */\nexport function validateIdentifier(value: string, type: string): void {\n\tif (!value || value.length === 0) {\n\t\tthrow new InvalidOperationError(type, `${type} name must not be empty`);\n\t}\n\tif (value.length > 63) {\n\t\tthrow new InvalidOperationError(\n\t\t\ttype,\n\t\t\t`${type} name must not exceed 63 characters`,\n\t\t);\n\t}\n\tif (!/^[a-zA-Z_][a-zA-Z0-9_$]{0,62}$/.test(value)) {\n\t\tthrow new InvalidOperationError(\n\t\t\ttype,\n\t\t\t`${type} name contains invalid characters`,\n\t\t);\n\t}\n}\n\nexport class UnsafeOperationError extends Error {\n\toverride readonly name = 'UnsafeOperationError' as const;\n\n\t/**\n\t * The operation that was attempted.\n\t */\n\treadonly operation: string;\n\n\t/**\n\t * How to make the operation safe or explicit.\n\t */\n\treadonly fix: string;\n\n\tconstructor(operation: string, fix: string) {\n\t\tconst message = `Unsafe ${operation}: ${fix}`;\n\t\tsuper(message);\n\t\tthis.operation = operation;\n\t\tthis.fix = fix;\n\t\tObject.setPrototypeOf(this, UnsafeOperationError.prototype);\n\t}\n}\n\n/**\n * Error thrown when a requested table does not exist in the schema.\n *\n * Provides helpful suggestions including available tables and fuzzy-matched\n * \"Did you mean?\" hints.\n *\n * @example\n * ```typescript\n * const err = new TableNotFoundError({\n * requested: 'usrs',\n * available: ['users', 'posts', 'comments'],\n * });\n * // err.message === 'Table not found'\n * // err.available === ['users', 'posts', 'comments']\n * // err.suggestion === 'users'\n * ```\n */\nexport class TableNotFoundError extends Error {\n\toverride readonly name = 'TableNotFoundError' as const;\n\n\t/**\n\t * The table name that was requested but not found.\n\t */\n\treadonly requested: string;\n\n\t/**\n\t * Available tables in the schema.\n\t */\n\treadonly available: readonly string[];\n\n\t/**\n\t * Suggested table name (fuzzy match), if any.\n\t */\n\treadonly suggestion?: string;\n\n\t/**\n\t * Public-safe message (no schema enumeration).\n\t */\n\treadonly publicMessage: string;\n\n\tconstructor(opts: { requested: string; available: readonly string[] }) {\n\t\tconst suggestion = findClosestMatch(opts.requested, opts.available);\n\n\t\t// Generic message — does NOT embed available list to avoid info leakage\n\t\tconst genericMessage = 'Table not found';\n\n\t\tsuper(genericMessage);\n\n\t\tthis.requested = opts.requested;\n\t\tthis.available = opts.available;\n\t\tthis.publicMessage = genericMessage;\n\t\tif (suggestion !== undefined) {\n\t\t\tthis.suggestion = suggestion;\n\t\t}\n\n\t\tObject.setPrototypeOf(this, TableNotFoundError.prototype);\n\t}\n}\n\n/**\n * Error thrown when a requested column does not exist on a table.\n *\n * Provides helpful suggestions including available columns and fuzzy-matched\n * \"Did you mean?\" hints.\n *\n * @example\n * ```typescript\n * const err = new ColumnNotFoundError({\n * table: 'users',\n * requested: 'emial',\n * available: ['id', 'email', 'name', 'createdAt'],\n * });\n * // err.message === 'Column not found'\n * // err.available === ['id', 'email', 'name', 'createdAt']\n * // err.suggestion === 'email'\n * ```\n */\nexport class ColumnNotFoundError extends Error {\n\toverride readonly name = 'ColumnNotFoundError' as const;\n\n\t/**\n\t * The table where the column was requested.\n\t */\n\treadonly table: string;\n\n\t/**\n\t * The column name that was requested but not found.\n\t */\n\treadonly requested: string;\n\n\t/**\n\t * Available columns on this table.\n\t */\n\treadonly available: readonly string[];\n\n\t/**\n\t * Suggested column name (fuzzy match), if any.\n\t */\n\treadonly suggestion?: string;\n\n\t/**\n\t * Public-safe message (no schema enumeration).\n\t */\n\treadonly publicMessage: string;\n\n\tconstructor(opts: {\n\t\ttable: string;\n\t\trequested: string;\n\t\tavailable: readonly string[];\n\t}) {\n\t\tconst suggestion = findClosestMatch(opts.requested, opts.available);\n\n\t\t// Generic message — does NOT embed available list to avoid info leakage\n\t\tconst genericMessage = 'Column not found';\n\n\t\tsuper(genericMessage);\n\n\t\tthis.table = opts.table;\n\t\tthis.requested = opts.requested;\n\t\tthis.available = opts.available;\n\t\tthis.publicMessage = genericMessage;\n\t\tif (suggestion !== undefined) {\n\t\t\tthis.suggestion = suggestion;\n\t\t}\n\n\t\tObject.setPrototypeOf(this, ColumnNotFoundError.prototype);\n\t}\n}\n\n/**\n * Error thrown when schema's naming convention doesn't match adapter's naming convention.\n *\n * This validation prevents subtle bugs where column names in queries don't match\n * the expected database column names due to naming convention mismatch.\n *\n * @example\n * ```typescript\n * const schema = await getSchemaFromDb(adapter); // dbCasing: 'snake_case'\n * const orm = createOrm({\n * schema,\n * adapter: createPgsqlAdapter(pool, { dbCasing: 'preserve' }),\n * });\n * // Throws NamingConventionMismatchError\n * ```\n *\n * @since ARCH-006\n */\nexport class NamingConventionMismatchError extends Error {\n\toverride readonly name = 'NamingConventionMismatchError' as const;\n\n\t/**\n\t * The DB casing used by the schema.\n\t */\n\treadonly schemaCasing: string;\n\n\t/**\n\t * The DB casing used by the adapter.\n\t */\n\treadonly adapterCasing: string;\n\n\tconstructor(opts: { schemaCasing: string; adapterCasing: string }) {\n\t\tconst message =\n\t\t\t`DB casing mismatch: Schema uses '${opts.schemaCasing}' but adapter uses '${opts.adapterCasing}'.\\n` +\n\t\t\t`Either align them or recreate the schema with the same dbCasing as the adapter.`;\n\n\t\tsuper(message);\n\n\t\tthis.schemaCasing = opts.schemaCasing;\n\t\tthis.adapterCasing = opts.adapterCasing;\n\n\t\tObject.setPrototypeOf(this, NamingConventionMismatchError.prototype);\n\t}\n}\n\n// ============================================================================\n// Error Codes\n// ============================================================================\n\n/**\n * Error codes for programmatic error handling.\n *\n * Use these codes to identify error types without relying on `instanceof` checks,\n * which is useful for serialization and cross-boundary error handling.\n *\n * @example\n * ```typescript\n * try {\n * await orm.select('users').all();\n * } catch (error) {\n * if (error.code === ErrorCode.EXECUTION_ERROR) {\n * // Handle execution error\n * }\n * }\n * ```\n */\nexport const ErrorCode = {\n\t/** Query execution failed (no adapter configured) */\n\tEXECUTION_ERROR: 'DBSP_E001',\n\t/** No record found (firstOrThrow) */\n\tNOT_FOUND: 'DBSP_E002',\n\t/** Ambiguous relation detected in strict mode */\n\tAMBIGUOUS_RELATION: 'DBSP_E003',\n\t/** Relation not found in schema */\n\tRELATION_NOT_FOUND: 'DBSP_E004',\n\t/** Invalid operation in current context */\n\tINVALID_OPERATION: 'DBSP_E005',\n\t/** Unsafe operation blocked */\n\tUNSAFE_OPERATION: 'DBSP_E006',\n\t/** Table not found in schema */\n\tTABLE_NOT_FOUND: 'DBSP_E007',\n\t/** Column not found on table */\n\tCOLUMN_NOT_FOUND: 'DBSP_E008',\n\t/** Schema naming convention doesn't match adapter naming convention */\n\tNAMING_CONVENTION_MISMATCH: 'DBSP_E009',\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\n// ============================================================================\n// Error Factory\n// ============================================================================\n\n/**\n * Factory functions for creating DBSP errors with consistent structure.\n *\n * Using the factory provides several benefits:\n * - Consistent error creation across the codebase\n * - Error codes are automatically attached\n * - Type-safe error construction\n * - Centralized error message formatting\n *\n * @example\n * ```typescript\n * import { Errors } from '@dbsp/core';\n *\n * // Create errors with factory\n * throw Errors.tableNotFound({\n * requested: 'userz',\n * available: ['users', 'posts', 'comments'],\n * });\n *\n * // Check error type\n * if (Errors.isTableNotFound(error)) {\n * console.log(error.suggestion); // 'users'\n * }\n * ```\n */\nexport const Errors = {\n\t// -------------------------------------------------------------------------\n\t// Factory functions\n\t// -------------------------------------------------------------------------\n\n\t/**\n\t * Create an execution error (no adapter configured).\n\t */\n\texecution(opts: {\n\t\toperation: string;\n\t\treason: string;\n\t\tfix: string;\n\t}): ExecutionError & { code: typeof ErrorCode.EXECUTION_ERROR } {\n\t\tconst error = new ExecutionError(opts);\n\t\treturn Object.assign(error, { code: ErrorCode.EXECUTION_ERROR });\n\t},\n\n\t/**\n\t * Create a not found error (firstOrThrow returned no results).\n\t */\n\tnotFound(\n\t\ttable: string,\n\t\thint?: string,\n\t): NotFoundError & { code: typeof ErrorCode.NOT_FOUND } {\n\t\tconst error = new NotFoundError(table, hint);\n\t\treturn Object.assign(error, { code: ErrorCode.NOT_FOUND });\n\t},\n\n\t/**\n\t * Create an ambiguous relation error.\n\t */\n\tambiguousRelation(\n\t\tsourceTable: string,\n\t\ttargetTable: string,\n\t\toptions: readonly string[],\n\t): AmbiguousRelationError & { code: typeof ErrorCode.AMBIGUOUS_RELATION } {\n\t\tconst error = new AmbiguousRelationError(sourceTable, targetTable, options);\n\t\treturn Object.assign(error, { code: ErrorCode.AMBIGUOUS_RELATION });\n\t},\n\n\t/**\n\t * Create a relation not found error.\n\t */\n\trelationNotFound(opts: {\n\t\ttable: string;\n\t\trequested: string;\n\t\tavailable: readonly string[];\n\t}): RelationNotFoundError & { code: typeof ErrorCode.RELATION_NOT_FOUND } {\n\t\tconst error = new RelationNotFoundError(opts);\n\t\treturn Object.assign(error, { code: ErrorCode.RELATION_NOT_FOUND });\n\t},\n\n\t/**\n\t * Create an invalid operation error.\n\t */\n\tinvalidOperation(\n\t\toperation: string,\n\t\treason: string,\n\t): InvalidOperationError & { code: typeof ErrorCode.INVALID_OPERATION } {\n\t\tconst error = new InvalidOperationError(operation, reason);\n\t\treturn Object.assign(error, { code: ErrorCode.INVALID_OPERATION });\n\t},\n\n\t/**\n\t * Create an unsafe operation error.\n\t */\n\tunsafeOperation(\n\t\toperation: string,\n\t\tfix: string,\n\t): UnsafeOperationError & { code: typeof ErrorCode.UNSAFE_OPERATION } {\n\t\tconst error = new UnsafeOperationError(operation, fix);\n\t\treturn Object.assign(error, { code: ErrorCode.UNSAFE_OPERATION });\n\t},\n\n\t/**\n\t * Create a table not found error.\n\t */\n\ttableNotFound(opts: {\n\t\trequested: string;\n\t\tavailable: readonly string[];\n\t}): TableNotFoundError & { code: typeof ErrorCode.TABLE_NOT_FOUND } {\n\t\tconst error = new TableNotFoundError(opts);\n\t\treturn Object.assign(error, { code: ErrorCode.TABLE_NOT_FOUND });\n\t},\n\n\t/**\n\t * Create a column not found error.\n\t */\n\tcolumnNotFound(opts: {\n\t\ttable: string;\n\t\trequested: string;\n\t\tavailable: readonly string[];\n\t}): ColumnNotFoundError & { code: typeof ErrorCode.COLUMN_NOT_FOUND } {\n\t\tconst error = new ColumnNotFoundError(opts);\n\t\treturn Object.assign(error, { code: ErrorCode.COLUMN_NOT_FOUND });\n\t},\n\n\t// -------------------------------------------------------------------------\n\t// Type guards\n\t// -------------------------------------------------------------------------\n\n\t/** Check if error is an ExecutionError */\n\tisExecution(error: unknown): error is ExecutionError {\n\t\treturn error instanceof ExecutionError;\n\t},\n\n\t/** Check if error is a NotFoundError */\n\tisNotFound(error: unknown): error is NotFoundError {\n\t\treturn error instanceof NotFoundError;\n\t},\n\n\t/** Check if error is an AmbiguousRelationError */\n\tisAmbiguousRelation(error: unknown): error is AmbiguousRelationError {\n\t\treturn error instanceof AmbiguousRelationError;\n\t},\n\n\t/** Check if error is a RelationNotFoundError */\n\tisRelationNotFound(error: unknown): error is RelationNotFoundError {\n\t\treturn error instanceof RelationNotFoundError;\n\t},\n\n\t/** Check if error is an InvalidOperationError */\n\tisInvalidOperation(error: unknown): error is InvalidOperationError {\n\t\treturn error instanceof InvalidOperationError;\n\t},\n\n\t/** Check if error is an UnsafeOperationError */\n\tisUnsafeOperation(error: unknown): error is UnsafeOperationError {\n\t\treturn error instanceof UnsafeOperationError;\n\t},\n\n\t/** Check if error is a TableNotFoundError */\n\tisTableNotFound(error: unknown): error is TableNotFoundError {\n\t\treturn error instanceof TableNotFoundError;\n\t},\n\n\t/** Check if error is a ColumnNotFoundError */\n\tisColumnNotFound(error: unknown): error is ColumnNotFoundError {\n\t\treturn error instanceof ColumnNotFoundError;\n\t},\n\n\t/** Check if error is a NamingConventionMismatchError */\n\tisNamingConventionMismatch(\n\t\terror: unknown,\n\t): error is NamingConventionMismatchError {\n\t\treturn error instanceof NamingConventionMismatchError;\n\t},\n\n\t/** Check if error is any DBSP error */\n\tisDbspError(\n\t\terror: unknown,\n\t): error is\n\t\t| ExecutionError\n\t\t| NotFoundError\n\t\t| AmbiguousRelationError\n\t\t| RelationNotFoundError\n\t\t| InvalidOperationError\n\t\t| UnsafeOperationError\n\t\t| TableNotFoundError\n\t\t| ColumnNotFoundError\n\t\t| NamingConventionMismatchError {\n\t\treturn (\n\t\t\terror instanceof ExecutionError ||\n\t\t\terror instanceof NotFoundError ||\n\t\t\terror instanceof AmbiguousRelationError ||\n\t\t\terror instanceof RelationNotFoundError ||\n\t\t\terror instanceof InvalidOperationError ||\n\t\t\terror instanceof UnsafeOperationError ||\n\t\t\terror instanceof TableNotFoundError ||\n\t\t\terror instanceof ColumnNotFoundError ||\n\t\t\terror instanceof NamingConventionMismatchError\n\t\t);\n\t},\n\n\t/** Check if error has a DBSP error code */\n\thasCode(error: unknown): error is Error & { code: ErrorCode } {\n\t\treturn (\n\t\t\terror instanceof Error &&\n\t\t\t'code' in error &&\n\t\t\ttypeof (error as Error & { code: unknown }).code === 'string' &&\n\t\t\t(error as Error & { code: string }).code.startsWith('DBSP_E')\n\t\t);\n\t},\n} as const;\n","/**\n * @module planner\n * Semantic Planner - Decision engine for query planning.\n * Transforms QueryIntent + ModelIR into PlanReport with strategic decisions.\n *\n * Type definitions live in @dbsp/types. This module re-exports them\n * and provides runtime functions.\n */\n\nimport type {\n\tCTEDefinition,\n\tDecisionType,\n\tDialectCapabilities,\n\tIncludeStrategy,\n\tPlanDecision,\n\tPlanOptions,\n\tPlanReport,\n\tPlanWarning,\n\tRecursivePlanOptions,\n\tRecursivePlanReport,\n\tResolvedIncludeStrategy,\n} from '@dbsp/types';\nimport { InvalidOperationError } from './dx/errors.js';\nimport {\n\tgetNodeIdAlias,\n\ttype IncludeIntent,\n\tisRawExpression,\n\ttype QueryIntent,\n\ttype RecursiveIntent,\n\ttype WhereAndIntent,\n\ttype WhereInIntent,\n\ttype WhereIntent,\n\ttype WhereNotIntent,\n\ttype WhereOrIntent,\n} from './intent-ast.js';\nimport type { ModelIR, RelationIR } from './model-ir.js';\n\n// Re-export all planner types from @dbsp/types for backward compatibility\nexport type {\n\tCTEDefinition,\n\tDecisionType,\n\tPlanDecision,\n\tPlanOptions,\n\tPlanReport,\n\tPlanWarning,\n\tPlanWarningCode,\n\tRecursivePlanOptions,\n\tRecursivePlanReport,\n\tResolvedIncludeStrategy,\n} from '@dbsp/types';\n\n// ============================================================================\n// Warning Types\n// ============================================================================\n\n/**\n * Warning codes for planning issues\n */\n\n/**\n * A warning about the query plan\n */\n\n// ============================================================================\n// CTE Types\n// ============================================================================\n\n/**\n * CTE definition for extracted subqueries\n */\n\n// ============================================================================\n// Plan Report\n// ============================================================================\n\n/**\n * Complete plan report\n */\n\n// ============================================================================\n// Plan Options\n// ============================================================================\n\n/**\n * Planning options for customization\n */\n\n// ============================================================================\n// Errors\n// ============================================================================\n\n/**\n * Error thrown when plan cannot be created due to ambiguity\n */\nexport class AmbiguousPlanError extends Error {\n\treadonly sourceTable: string;\n\treadonly targetTable: string;\n\treadonly options: readonly string[];\n\n\tconstructor(\n\t\tsourceTable: string,\n\t\ttargetTable: string,\n\t\toptions: readonly string[],\n\t) {\n\t\tsuper(\n\t\t\t`Ambiguous relation from \"${sourceTable}\" to \"${targetTable}\". ` +\n\t\t\t\t`Use \"via\" to specify one of: ${options.join(', ')}`,\n\t\t);\n\t\tthis.name = 'AmbiguousPlanError';\n\t\tthis.sourceTable = sourceTable;\n\t\tthis.targetTable = targetTable;\n\t\tthis.options = options;\n\t}\n}\n\n/**\n * Error thrown when recursive CTE base/recursive cases have incompatible shapes.\n * Per RFC-001: columns must match in count, order, and be type-compatible.\n */\nexport class RecursiveShapeMismatchError extends Error {\n\treadonly cteName: string;\n\treadonly baseColumns: readonly string[];\n\treadonly recursiveColumns: readonly string[];\n\treadonly mismatchDetails: string;\n\n\tconstructor(\n\t\tcteName: string,\n\t\tbaseColumns: readonly string[],\n\t\trecursiveColumns: readonly string[],\n\t\tmismatchDetails: string,\n\t) {\n\t\tsuper(\n\t\t\t`Recursive CTE \"${cteName}\" shape mismatch: ${mismatchDetails}. ` +\n\t\t\t\t`Base columns: [${baseColumns.join(', ')}], ` +\n\t\t\t\t`Recursive columns: [${recursiveColumns.join(', ')}]`,\n\t\t);\n\t\tthis.name = 'RecursiveShapeMismatchError';\n\t\tthis.cteName = cteName;\n\t\tthis.baseColumns = baseColumns;\n\t\tthis.recursiveColumns = recursiveColumns;\n\t\tthis.mismatchDetails = mismatchDetails;\n\t}\n}\n\n// ============================================================================\n// Recursive CTE Shape Validation Helpers\n// ============================================================================\n\n/**\n * Computes expected base case columns from RecursiveIntent.\n * Order: [node_id_alias, ...select_fields, depth (if track.depth), path (if track.path)]\n */\nfunction computeBaseColumns(intent: RecursiveIntent): readonly string[] {\n\tconst columns: string[] = [];\n\n\t// node_id is always first\n\tcolumns.push(getNodeIdAlias(intent.start.nodeIdExpr));\n\n\t// select fields (if specified)\n\tif (intent.start.select) {\n\t\tcolumns.push(...intent.start.select);\n\t}\n\n\t// tracked columns\n\tif (intent.track?.depth) {\n\t\tcolumns.push('depth');\n\t}\n\tif (intent.track?.path) {\n\t\tcolumns.push('path');\n\t}\n\n\treturn Object.freeze(columns);\n}\n\n/**\n * Computes expected recursive step columns from RecursiveIntent.\n * Must match base columns in count and order.\n */\nfunction computeRecursiveColumns(intent: RecursiveIntent): readonly string[] {\n\tconst columns: string[] = [];\n\n\t// node_id is always first (from traversal)\n\tcolumns.push(getNodeIdAlias(intent.start.nodeIdExpr));\n\n\t// select fields must match base\n\tif (intent.start.select) {\n\t\tcolumns.push(...intent.start.select);\n\t}\n\n\t// tracked columns with expressions\n\tif (intent.track?.depth) {\n\t\tcolumns.push('depth'); // Will be `prev.depth + 1`\n\t}\n\tif (intent.track?.path) {\n\t\tcolumns.push('path'); // Will be `prev.path || id`\n\t}\n\n\treturn Object.freeze(columns);\n}\n\n/**\n * Validates that base and recursive columns are shape-compatible.\n * Throws RecursiveShapeMismatchError if validation fails.\n */\nexport function validateRecursiveShape(intent: RecursiveIntent): void {\n\tconst baseColumns = computeBaseColumns(intent);\n\tconst recursiveColumns = computeRecursiveColumns(intent);\n\n\t// Check column count\n\tif (baseColumns.length !== recursiveColumns.length) {\n\t\tthrow new RecursiveShapeMismatchError(\n\t\t\tintent.cteName,\n\t\t\tbaseColumns,\n\t\t\trecursiveColumns,\n\t\t\t`column count mismatch: base has ${baseColumns.length}, recursive has ${recursiveColumns.length}`,\n\t\t);\n\t}\n\n\t// Check column order (names must match at each position)\n\tfor (let i = 0; i < baseColumns.length; i++) {\n\t\tif (baseColumns[i] !== recursiveColumns[i]) {\n\t\t\tthrow new RecursiveShapeMismatchError(\n\t\t\t\tintent.cteName,\n\t\t\t\tbaseColumns,\n\t\t\t\trecursiveColumns,\n\t\t\t\t`column ${i} name mismatch: base has \"${baseColumns[i]}\", recursive has \"${recursiveColumns[i]}\"`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Planner State (Internal)\n// ============================================================================\n\ninterface PlannerState {\n\tdecisions: PlanDecision[];\n\twarnings: PlanWarning[];\n\tctes: CTEDefinition[];\n\trelationsAnalyzed: number;\n\tdecisionCounters: Record<DecisionType, number>;\n\trelationAccessCounts: Map<string, string[]>; // relation path -> intent paths\n\tvisitedIncludes: Set<string>; // For circular detection\n}\n\n// ============================================================================\n// Planner Implementation\n// ============================================================================\n\n/**\n * Create a query plan from an intent and model\n */\nexport function plan(\n\tintent: QueryIntent,\n\tmodel: ModelIR,\n\toptions: PlanOptions = {},\n): PlanReport {\n\tconst startTime = performance.now();\n\n\tconst state: PlannerState = {\n\t\tdecisions: [],\n\t\twarnings: [],\n\t\tctes: [],\n\t\trelationsAnalyzed: 0,\n\t\tdecisionCounters: {\n\t\t\t'filter-strategy': 0,\n\t\t\t'join-type': 0,\n\t\t\t'include-strategy': 0,\n\t\t\t'cte-extraction': 0,\n\t\t\tambiguity: 0,\n\t\t\t'recursive-cte': 0,\n\t\t\t'bidirectional-edges': 0,\n\t\t},\n\t\trelationAccessCounts: new Map(),\n\t\tvisitedIncludes: new Set(),\n\t};\n\n\tconst opts: Required<PlanOptions> = {\n\t\tforceFilterStrategy: options.forceFilterStrategy as 'exists' | 'join',\n\t\tforceJoinType: options.forceJoinType as 'left' | 'inner',\n\t\tenableCTEs: options.enableCTEs ?? true,\n\t\tcteThreshold: options.cteThreshold ?? 2,\n\t\tmaxIncludeDepth: options.maxIncludeDepth ?? 5,\n\t\tdisambiguate: options.disambiguate ?? {},\n\t\tdefaultIncludeStrategy: options.defaultIncludeStrategy ?? 'auto',\n\t\tdialectCapabilities: options.dialectCapabilities as DialectCapabilities,\n\t};\n\n\t// Validate root table — skip when the FROM is a BatchValues unnest() source\n\t// (the alias is not a real table; schema validation would incorrectly fail)\n\tconst rootTable = intent.batchValuesSource\n\t\t? null\n\t\t: model.getTable(intent.from);\n\tif (!intent.batchValuesSource && !rootTable) {\n\t\tthrow new Error(`Unknown table: ${intent.from}`);\n\t}\n\n\t// Optimize IN-subquery → EXISTS when the relation is known in schema.\n\t// The optimized WHERE goes into `executableIntent` (adapter compiles from it),\n\t// while `intent` stays as the original submitted intent (observable via dump()).\n\t// `plannedIntent` is only used locally to decide whether to emit executableIntent.\n\tconst optimizedWhere = intent.where\n\t\t? optimizeInToExists(intent.where, intent.from, model)\n\t\t: undefined;\n\n\t// Build the post-optimization intent (used as executableIntent when optimization ran)\n\tconst plannedIntent: QueryIntent =\n\t\toptimizedWhere !== undefined && optimizedWhere !== intent.where\n\t\t\t? { ...intent, where: optimizedWhere }\n\t\t\t: intent;\n\n\t// Process where clause\n\tif (optimizedWhere) {\n\t\tprocessWhere(optimizedWhere, intent.from, model, state, opts, 'where');\n\t}\n\n\t// Process includes\n\tif (intent.include) {\n\t\tfor (let i = 0; i < intent.include.length; i++) {\n\t\t\tconst inc = intent.include[i];\n\t\t\tif (inc) {\n\t\t\t\tprocessInclude(\n\t\t\t\t\tinc,\n\t\t\t\t\tintent.from,\n\t\t\t\t\tmodel,\n\t\t\t\t\tstate,\n\t\t\t\t\topts,\n\t\t\t\t\t`include[${i}]`,\n\t\t\t\t\t0,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Extract CTEs if enabled\n\tif (opts.enableCTEs) {\n\t\textractCTEs(state, opts.cteThreshold);\n\t}\n\n\t// Detect raw SQL usage and add security warnings\n\tdetectRawSqlUsage(intent, state);\n\n\tconst planningTimeMs = performance.now() - startTime;\n\n\t// PERF (FIND-051): use .slice() instead of spread ([...arr]) — avoids the extra\n\t// iterable-protocol overhead; semantically identical for plain arrays.\n\tconst ambiguousDecision = state.decisions.find(\n\t\t(d) => d.type === 'ambiguity' && d.choice === 'unresolved',\n\t);\n\n\tconst metadata: PlanReport['metadata'] = ambiguousDecision\n\t\t? Object.freeze({\n\t\t\t\tplanningTimeMs,\n\t\t\t\trelationsAnalyzed: state.relationsAnalyzed,\n\t\t\t\tisAmbiguous: true,\n\t\t\t\tambiguousOptions: ambiguousDecision.alternatives as readonly string[],\n\t\t\t})\n\t\t: Object.freeze({\n\t\t\t\tplanningTimeMs,\n\t\t\t\trelationsAnalyzed: state.relationsAnalyzed,\n\t\t\t\tisAmbiguous: false,\n\t\t\t});\n\n\tconst report: PlanReport = {\n\t\trootTable: intent.from,\n\t\tdecisions: Object.freeze(state.decisions.slice()),\n\t\twarnings: Object.freeze(state.warnings.slice()),\n\t\tctes: Object.freeze(state.ctes.slice()),\n\t\t// intent is ALWAYS the original submitted intent (contract: observable via dump()).\n\t\t// executableIntent carries the optimized WHERE (e.g. IN→EXISTS) when the\n\t\t// optimizer rewrote it, so the adapter compiles the correct SQL from that field.\n\t\t// When no optimization applies, executableIntent is left undefined and the\n\t\t// adapter falls back to intent.\n\t\tintent,\n\t\t...(plannedIntent !== intent && { executableIntent: plannedIntent }),\n\t\tmetadata,\n\t};\n\n\treturn Object.freeze(report);\n}\n\n// ============================================================================\n// Recursive Intent Planning\n// ============================================================================\n\n/**\n * RecursivePlanReport extends PlanReport with recursive-specific metadata.\n */\n\n/**\n * Options specific to recursive CTE planning.\n */\n\n/**\n * Create a plan for a recursive CTE intent.\n * Per RFC-001: validates shape, generates decisions for traversal strategy.\n */\nexport function planRecursive(\n\tintent: RecursiveIntent,\n\tmodel: ModelIR,\n\toptions: RecursivePlanOptions = {},\n): RecursivePlanReport {\n\tconst startTime = performance.now();\n\n\t// Step 1: Validate shape compatibility\n\tvalidateRecursiveShape(intent);\n\n\tconst state: PlannerState = {\n\t\tdecisions: [],\n\t\twarnings: [],\n\t\tctes: [],\n\t\trelationsAnalyzed: 0,\n\t\tdecisionCounters: {\n\t\t\t'filter-strategy': 0,\n\t\t\t'join-type': 0,\n\t\t\t'include-strategy': 0,\n\t\t\t'cte-extraction': 0,\n\t\t\tambiguity: 0,\n\t\t\t'recursive-cte': 0,\n\t\t\t'bidirectional-edges': 0,\n\t\t},\n\t\trelationAccessCounts: new Map(),\n\t\tvisitedIncludes: new Set(),\n\t};\n\n\t// Validate that start table exists\n\tconst startTable = model.getTable(intent.start.from);\n\tif (!startTable) {\n\t\tthrow new Error(`Unknown table: ${intent.start.from}`);\n\t}\n\n\t// Step 2: Generate recursive-cte decision\n\tconst traversalKind = intent.traversal.kind;\n\n\tconst recursiveCteDecision: PlanDecision = {\n\t\tid: generateDecisionId(state, 'recursive-cte'),\n\t\ttype: 'recursive-cte',\n\t\tcontext: {\n\t\t\tsourceTable: intent.start.from,\n\t\t\tintentPath: `recursive:${intent.cteName}`,\n\t\t},\n\t\tchoice: 'with-recursive',\n\t\treasoning: generateRecursiveReasoning(intent),\n\t\talternatives: ['with-recursive', 'iterative'],\n\t};\n\tstate.decisions.push(recursiveCteDecision);\n\n\t// Step 3: Handle bidirectional edges (for edge-table traversal)\n\tlet usesBidirectional = false;\n\tif (\n\t\ttraversalKind === 'edge-table' &&\n\t\tintent.traversal.kind === 'edge-table'\n\t) {\n\t\tconst edgeTraversal = intent.traversal;\n\t\tif (edgeTraversal.direction === 'both') {\n\t\t\tusesBidirectional = true;\n\n\t\t\tconst storageHint = edgeTraversal.edgeStorageHint ?? 'unknown';\n\t\t\tconst strategy =\n\t\t\t\toptions.forceBidirectionalStrategy ??\n\t\t\t\t(storageHint === 'directed-only' ? 'union-all' : 'union');\n\n\t\t\tconst bidirectionalDecision: PlanDecision = {\n\t\t\t\tid: generateDecisionId(state, 'bidirectional-edges'),\n\t\t\t\ttype: 'bidirectional-edges',\n\t\t\t\tcontext: {\n\t\t\t\t\tsourceTable: intent.start.from,\n\t\t\t\t\ttarget: edgeTraversal.edgeTable,\n\t\t\t\t\tintentPath: `recursive:${intent.cteName}:edges`,\n\t\t\t\t},\n\t\t\t\tchoice: strategy,\n\t\t\t\treasoning: generateBidirectionalReasoning(storageHint, strategy),\n\t\t\t\talternatives: ['union', 'union-all'],\n\t\t\t};\n\t\t\tstate.decisions.push(bidirectionalDecision);\n\n\t\t\t// Add warning if using union-all with unknown storage\n\t\t\tif (strategy === 'union-all' && storageHint === 'unknown') {\n\t\t\t\tstate.warnings.push({\n\t\t\t\t\tcode: 'POTENTIAL_ROW_EXPLOSION',\n\t\t\t\t\tmessage: `Bidirectional edge traversal with UNION ALL on unknown storage hint may produce duplicates`,\n\t\t\t\t\tsuggestion: `Set edgeStorageHint: 'directed-only' if edges are guaranteed uni-directional, or use dedupe: 'final'`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// Step 4: Validate maxDepth\n\tif (intent.maxDepth < 1) {\n\t\tthrow new Error(`maxDepth must be >= 1, got ${intent.maxDepth}`);\n\t}\n\n\tif (intent.maxDepth > 100) {\n\t\tstate.warnings.push({\n\t\t\tcode: 'DEEP_NESTING',\n\t\t\tmessage: `maxDepth of ${intent.maxDepth} is unusually high`,\n\t\t\tsuggestion: `Consider if you really need traversal depth > 100. Large values may cause performance issues.`,\n\t\t});\n\t}\n\n\tconst planningTimeMs = performance.now() - startTime;\n\n\tconst dedupeStrategy = intent.dedupe ?? 'none';\n\n\t// PERF (FIND-051): use .slice() instead of spread — avoids iterable-protocol overhead.\n\tconst report: RecursivePlanReport = {\n\t\trootTable: intent.start.from,\n\t\tdecisions: Object.freeze(state.decisions.slice()),\n\t\twarnings: Object.freeze(state.warnings.slice()),\n\t\tctes: Object.freeze(state.ctes.slice()),\n\t\tintent,\n\t\tmetadata: Object.freeze({\n\t\t\tplanningTimeMs,\n\t\t\trelationsAnalyzed: state.relationsAnalyzed,\n\t\t\tisAmbiguous: false,\n\t\t\tisRecursive: true as const,\n\t\t\ttraversalKind,\n\t\t\tusesBidirectional,\n\t\t\tdedupeStrategy,\n\t\t}),\n\t};\n\n\treturn Object.freeze(report) as RecursivePlanReport;\n}\n\n/**\n * Generate reasoning for recursive CTE decision.\n */\nfunction generateRecursiveReasoning(intent: RecursiveIntent): string {\n\tconst parts: string[] = [];\n\n\tparts.push(\n\t\t`Recursive CTE \"${intent.cteName}\" using ${intent.traversal.kind} traversal`,\n\t);\n\n\tif (intent.traversal.kind === 'adjacency') {\n\t\tparts.push(\n\t\t\t`direction=${intent.traversal.direction}, parentId=${intent.traversal.parentId}`,\n\t\t);\n\t} else if (intent.traversal.kind === 'edge-table') {\n\t\tparts.push(\n\t\t\t`edgeTable=${intent.traversal.edgeTable}, direction=${intent.traversal.direction}`,\n\t\t);\n\t}\n\n\tparts.push(`maxDepth=${intent.maxDepth}`);\n\n\tif (intent.dedupe && intent.dedupe !== 'none') {\n\t\tparts.push(`dedupe=${intent.dedupe}`);\n\t}\n\n\treturn parts.join(', ');\n}\n\n/**\n * Generate reasoning for bidirectional edge decision.\n */\nfunction generateBidirectionalReasoning(\n\tstorageHint: 'unknown' | 'directed-only',\n\tstrategy: 'union' | 'union-all',\n): string {\n\tif (storageHint === 'directed-only') {\n\t\treturn strategy === 'union-all'\n\t\t\t? 'edgeStorageHint=directed-only guarantees no reverse duplicates, UNION ALL is safe'\n\t\t\t: 'UNION used despite directed-only hint (forced or conservative)';\n\t}\n\treturn strategy === 'union'\n\t\t? 'edgeStorageHint=unknown, using UNION to eliminate potential duplicates'\n\t\t: 'UNION ALL used despite unknown storage hint (may produce duplicates)';\n}\n\n// ============================================================================\n// IN → EXISTS Optimization\n// ============================================================================\n\n/**\n * Optimize IN (subquery) → EXISTS when the subquery targets a known relation.\n *\n * Pattern detected:\n * WHERE id IN (SELECT customer_id FROM orders WHERE ...)\n * Rewritten to:\n * WHERE EXISTS (SELECT 1 FROM orders WHERE orders.customer_id = outer.id AND ...)\n *\n * This is a standard SQL optimization: EXISTS short-circuits on first match,\n * while IN materializes the full set. The rewrite is valid when the subquery\n * selects a FK column that references the outer table's PK.\n */\n\n/**\n * Check whether the FK column resolved by a WHERE EXISTS rewrite is provably\n * non-nullable in the ModelIR.\n *\n * Used to guard NOT(IN-subquery) → NOT EXISTS rewrites: SQL's three-valued logic\n * means `x NOT IN (SELECT y ...)` returns UNKNOWN (not TRUE) when y can be NULL,\n * so it excludes the row. NOT EXISTS does not have this behavior — it returns\n * TRUE when the subquery is empty. The rewrite is only semantically equivalent\n * when the FK column is NOT NULL.\n *\n * Returns `false` (conservative) when the relation or column cannot be resolved.\n */\nfunction isSubquerySelectedColumnNonNullable(\n\texistsIntent: { relation: string },\n\tsourceTable: string,\n\tmodel: ModelIR,\n): boolean {\n\tconst rel = model.getRelation(`${sourceTable}.${existsIntent.relation}`);\n\tif (!rel) return false;\n\n\tconst fk =\n\t\ttypeof rel.foreignKey === 'string' ? rel.foreignKey : rel.foreignKey?.[0];\n\tif (!fk) return false;\n\n\tconst targetTableIR = model.getTable(rel.target);\n\tif (!targetTableIR) return false;\n\n\tconst column = targetTableIR.columns.find((c) => c.name === fk);\n\tif (!column) return false;\n\n\treturn !column.nullable;\n}\n\nfunction optimizeInToExists(\n\twhere: WhereIntent,\n\tsourceTable: string,\n\tmodel: ModelIR,\n\t// negated tracks whether this node is under an odd number of NOT wrappers.\n\t// It is used ONLY for the NULL-safety guard — it never determines the rewrite\n\t// form (exists vs notExists).\n\t//\n\t// The rewrite form is determined solely by the in-intent's OWN `not` flag:\n\t// • inWhere.not === false → rewrite to { kind: 'exists' }\n\t// • inWhere.not === true → rewrite to { kind: 'notExists' }\n\t//\n\t// The outer boolean structure (not/and/or wrappers) is PRESERVED by recursion,\n\t// so the form must mirror only the in-intent's own polarity. The `negated`\n\t// parity is XOR'd with `inWhere.not` to compute whether the rewrite would\n\t// occur in a negated context — used ONLY to block rewrites where the FK is\n\t// nullable (NULL-unsafe under effective negation).\n\t//\n\t// Examples at the 'in' leaf:\n\t// • inSubquery(...) at negated=false → effectiveNeg=false, form=exists → exists\n\t// • inSubquery(...) at negated=true → effectiveNeg=true, nullable?keep:form=exists → exists (outer not preserved)\n\t// • {not:true} at negated=false → effectiveNeg=true, nullable?keep:form=notExists\n\t// • {not:true} at negated=true → effectiveNeg=false, form=exists (double-neg, outer not preserved)\n\tnegated = false,\n): WhereIntent {\n\tswitch (where.kind) {\n\t\tcase 'in': {\n\t\t\tconst inWhere = where as WhereInIntent;\n\t\t\tif (!inWhere.subquery) return where;\n\n\t\t\t// Only rewrite when the subquery is SIMPLE: single source table, one\n\t\t\t// selected column (the FK), and NO modifiers that change the result set.\n\t\t\t// Any of the following make the subquery non-simple — keep IN unchanged:\n\t\t\t// limit / orderBy — LIMIT n restricts which rows satisfy IN, can't be\n\t\t\t// expressed in EXISTS form\n\t\t\t// offset — similar row-restriction semantics\n\t\t\t// groupBy / having — HAVING count(*)>1 restricts to duplicates etc.;\n\t\t\t// EXISTS (SELECT 1 ... GROUP BY x HAVING ...) drops\n\t\t\t// the HAVING restriction and matches MORE rows\n\t\t\t// distinct / distinctOn — deduplicate semantics lost in EXISTS\n\t\t\t// joins / include — extra tables in the subquery aren't propagated\n\t\t\t// batchValuesSource — unnest() source, not a real table\n\t\t\t// aggregate select — SELECT max(price) is not a simple FK projection\n\t\t\tconst sq = inWhere.subquery;\n\t\t\tif (\n\t\t\t\tsq.limit != null ||\n\t\t\t\tsq.orderBy?.length ||\n\t\t\t\tsq.offset != null ||\n\t\t\t\tsq.groupBy?.length ||\n\t\t\t\tsq.having != null ||\n\t\t\t\tsq.distinct ||\n\t\t\t\tsq.distinctOn?.length ||\n\t\t\t\tsq.joins?.length ||\n\t\t\t\tsq.include?.length ||\n\t\t\t\tsq.batchValuesSource != null ||\n\t\t\t\tsq.existsWrap ||\n\t\t\t\tsq.lock != null ||\n\t\t\t\t(sq.select != null && sq.select.type !== 'fields')\n\t\t\t) {\n\t\t\t\treturn where;\n\t\t\t}\n\n\t\t\t// Extract the single column from the subquery's select\n\t\t\tconst subSelect = inWhere.subquery.select;\n\t\t\tif (!subSelect || subSelect.type !== 'fields') return where;\n\t\t\tconst fields = 'fields' in subSelect ? subSelect.fields : undefined;\n\t\t\tif (!fields || fields.length !== 1) return where;\n\t\t\tconst subColumn = fields[0];\n\t\t\tif (!subColumn) return where;\n\n\t\t\t// Look for a relation from sourceTable to subquery's table\n\t\t\t// where the FK column matches the subquery's selected column\n\t\t\tconst relationsFrom = model.getRelationsFrom(sourceTable);\n\t\t\tconst sourceTableIR = model.getTable(sourceTable);\n\t\t\t// For composite PKs, only the first column is checked — multi-column\n\t\t\t// IN-subquery optimization is not supported (falls through as-is).\n\t\t\tconst sourcePk =\n\t\t\t\ttypeof sourceTableIR?.primaryKey === 'string'\n\t\t\t\t\t? sourceTableIR.primaryKey\n\t\t\t\t\t: (sourceTableIR?.primaryKey?.[0] ?? 'id');\n\n\t\t\tlet matchedRelation: string | undefined;\n\n\t\t\tfor (const rel of relationsFrom) {\n\t\t\t\tif (rel.target !== inWhere.subquery.from) continue;\n\t\t\t\tconst fk =\n\t\t\t\t\ttypeof rel.foreignKey === 'string'\n\t\t\t\t\t\t? rel.foreignKey\n\t\t\t\t\t\t: rel.foreignKey?.[0];\n\n\t\t\t\t// hasMany: outer.pk IN (SELECT fk FROM target WHERE ...)\n\t\t\t\t// The subquery selects the FK column, outer field is PK\n\t\t\t\tif (\n\t\t\t\t\trel.type === 'hasMany' &&\n\t\t\t\t\tfk === subColumn &&\n\t\t\t\t\tinWhere.field === sourcePk\n\t\t\t\t) {\n\t\t\t\t\tmatchedRelation = rel.name;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!matchedRelation) return where;\n\n\t\t\t// NULL-safety guard: compute effective negation (XOR of outer context parity\n\t\t\t// and the in-intent's own `not` flag) to determine whether this rewrite\n\t\t\t// occurs under effective negation. Under effective negation with a nullable\n\t\t\t// FK, `x NOT IN (SELECT y ...)` returns UNKNOWN (row excluded) when y is NULL,\n\t\t\t// whereas `NOT EXISTS` always returns TRUE — so the rewrite would BROADEN the\n\t\t\t// filter. Block the rewrite in that case.\n\t\t\tconst effectiveNegated = negated !== Boolean(inWhere.not);\n\t\t\tif (effectiveNegated) {\n\t\t\t\tconst existsIntent = { relation: matchedRelation };\n\t\t\t\tif (\n\t\t\t\t\t!isSubquerySelectedColumnNonNullable(existsIntent, sourceTable, model)\n\t\t\t\t) {\n\t\t\t\t\t// Nullable FK under effective negation — keep original IN (correct SQL semantics)\n\t\t\t\t\treturn where;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Rewrite form is determined SOLELY by the in-intent's own `not` flag,\n\t\t\t// NOT by `effectiveNegated`. The outer boolean structure (not/and/or\n\t\t\t// wrappers) is preserved by the recursion, so the form must mirror only\n\t\t\t// the in-intent's own polarity:\n\t\t\t// • inWhere.not === false → { kind: 'exists' } — outer NOT wraps it if present\n\t\t\t// • inWhere.not === true → { kind: 'notExists' } — outer NOT wraps it if present\n\t\t\tconst targetKind = inWhere.not ? 'notExists' : 'exists';\n\t\t\treturn {\n\t\t\t\tkind: targetKind,\n\t\t\t\trelation: matchedRelation,\n\t\t\t\t...(inWhere.subquery.where && { where: inWhere.subquery.where }),\n\t\t\t} as unknown as WhereIntent;\n\t\t}\n\n\t\tcase 'and': {\n\t\t\tconst andWhere = where as WhereAndIntent;\n\t\t\tconst optimized = andWhere.conditions.map((c) =>\n\t\t\t\toptimizeInToExists(c, sourceTable, model, negated),\n\t\t\t);\n\t\t\tif (optimized.every((c, i) => c === andWhere.conditions[i])) return where;\n\t\t\treturn { kind: 'and', conditions: optimized } as WhereAndIntent;\n\t\t}\n\n\t\tcase 'or': {\n\t\t\t// The adapter now compiles EXISTS inline at its boolean tree position\n\t\t\t// (enrichExistsDecisionsInPlace replaces stubs in-place rather than hoisting\n\t\t\t// to top-level AND). Recursing here is safe: an exists inside an OR\n\t\t\t// becomes a whereOr stub that is enriched in-place, preserving OR semantics.\n\t\t\tconst orWhere = where as WhereOrIntent;\n\t\t\tconst optimized = orWhere.conditions.map((c) =>\n\t\t\t\toptimizeInToExists(c, sourceTable, model, negated),\n\t\t\t);\n\t\t\tif (optimized.every((c, i) => c === orWhere.conditions[i])) return where;\n\t\t\treturn { kind: 'or', conditions: optimized } as WhereOrIntent;\n\t\t}\n\n\t\tcase 'not': {\n\t\t\tconst notWhere = where as WhereNotIntent;\n\t\t\t// Flip negation parity for the child (used only for the null-safety guard\n\t\t\t// inside 'case in'). The outer 'not' wrapper is ALWAYS preserved: after\n\t\t\t// the child rewrites its 'in' leaf to 'exists' or 'notExists', the outer\n\t\t\t// not() remains to produce the correct SQL structure:\n\t\t\t// not(in_not=false) → child becomes exists → not(exists) = NOT EXISTS ✓\n\t\t\t// not(in_not=true) → child becomes notExists → not(notExists) = NOT NOT EXISTS = EXISTS (adapter compiles correctly)\n\t\t\tconst optimized = optimizeInToExists(\n\t\t\t\tnotWhere.condition,\n\t\t\t\tsourceTable,\n\t\t\t\tmodel,\n\t\t\t\t!negated,\n\t\t\t);\n\t\t\tif (optimized === notWhere.condition) return where;\n\t\t\treturn { kind: 'not', condition: optimized } as WhereNotIntent;\n\t\t}\n\n\t\tdefault:\n\t\t\treturn where;\n\t}\n}\n\n// ============================================================================\n// Where Processing\n// ============================================================================\n\nfunction processWhere(\n\twhere: WhereIntent,\n\tsourceTable: string,\n\tmodel: ModelIR,\n\tstate: PlannerState,\n\topts: Required<PlanOptions>,\n\tintentPath: string,\n): void {\n\tswitch (where.kind) {\n\t\tcase 'exists':\n\t\tcase 'notExists':\n\t\t\tprocessRelationFilter(\n\t\t\t\twhere.relation,\n\t\t\t\tsourceTable,\n\t\t\t\tmodel,\n\t\t\t\tstate,\n\t\t\t\topts,\n\t\t\t\t`${intentPath}.${where.kind}`,\n\t\t\t\twhere.where,\n\t\t\t);\n\t\t\tbreak;\n\n\t\tcase 'relationFilter':\n\t\t\tprocessRelationFilter(\n\t\t\t\twhere.relation,\n\t\t\t\tsourceTable,\n\t\t\t\tmodel,\n\t\t\t\tstate,\n\t\t\t\topts,\n\t\t\t\t`${intentPath}.relationFilter`,\n\t\t\t\twhere.where,\n\t\t\t\twhere.mode,\n\t\t\t);\n\t\t\tbreak;\n\n\t\tcase 'and':\n\t\t\tfor (let i = 0; i < where.conditions.length; i++) {\n\t\t\t\tconst cond = where.conditions[i];\n\t\t\t\tif (cond) {\n\t\t\t\t\tprocessWhere(\n\t\t\t\t\t\tcond,\n\t\t\t\t\t\tsourceTable,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\topts,\n\t\t\t\t\t\t`${intentPath}.and[${i}]`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 'or':\n\t\t\tfor (let i = 0; i < where.conditions.length; i++) {\n\t\t\t\tconst cond = where.conditions[i];\n\t\t\t\tif (cond) {\n\t\t\t\t\tprocessWhere(\n\t\t\t\t\t\tcond,\n\t\t\t\t\t\tsourceTable,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tstate,\n\t\t\t\t\t\topts,\n\t\t\t\t\t\t`${intentPath}.or[${i}]`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase 'not':\n\t\t\tprocessWhere(\n\t\t\t\twhere.condition,\n\t\t\t\tsourceTable,\n\t\t\t\tmodel,\n\t\t\t\tstate,\n\t\t\t\topts,\n\t\t\t\t`${intentPath}.not`,\n\t\t\t);\n\t\t\tbreak;\n\n\t\t// Scalar conditions don't need relation analysis\n\t\tcase 'comparison':\n\t\tcase 'like':\n\t\tcase 'in':\n\t\tcase 'any':\n\t\tcase 'null':\n\t\t\t// No relation analysis needed\n\t\t\tbreak;\n\n\t\tcase 'expression':\n\t\t\tbreak; // Custom expression — no relation analysis, pass through\n\n\t\t// Adapter-only kinds: planner records no decisions; the adapter compiles\n\t\t// them directly from the intent. Explicit cases here prevent silent\n\t\t// fallthrough and keep the switch exhaustive.\n\n\t\tcase 'rawExists':\n\t\tcase 'rawNotExists':\n\t\t\t// The subquery is an arbitrary QueryIntent — no FK-based relation\n\t\t\t// resolution to perform at plan time. The adapter handles compilation.\n\t\t\tbreak;\n\n\t\tcase 'subquery':\n\t\t\t// Scalar subquery comparison — the adapter resolves the inner\n\t\t\t// QueryIntent directly; no planner-level relation analysis needed.\n\t\t\tbreak;\n\n\t\tcase 'range':\n\t\t\t// PostgreSQL range operator — scalar field check, no relation\n\t\t\t// analysis required; adapter emits the range SQL.\n\t\t\tbreak;\n\n\t\tcase 'jsonContains':\n\t\tcase 'jsonExists':\n\t\t\t// JSON containment / key-existence operators — scalar field checks\n\t\t\t// compiled entirely by the adapter.\n\t\t\tbreak;\n\n\t\tdefault: {\n\t\t\t// Exhaustiveness guard: if a new WhereIntent kind is added to the\n\t\t\t// union without a matching case here, TypeScript will flag this as\n\t\t\t// a type error at compile time, preventing silent no-ops.\n\t\t\tconst _exhaustive: never = where;\n\t\t\tthrow new Error(\n\t\t\t\t`processWhere: unhandled WhereIntent kind '${(_exhaustive as { kind: string }).kind}'`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction processRelationFilter(\n\trelationPath: string | readonly string[],\n\tsourceTable: string,\n\tmodel: ModelIR,\n\tstate: PlannerState,\n\topts: Required<PlanOptions>,\n\tintentPath: string,\n\tnestedWhere?: WhereIntent,\n\tmode?: 'some' | 'every' | 'none',\n): void {\n\tstate.relationsAnalyzed++;\n\n\t// Normalize relation path to array (SPEC-002: multi-hop support)\n\tconst relations = Array.isArray(relationPath) ? relationPath : [relationPath];\n\n\t// Process each relation in the chain\n\tlet currentSource = sourceTable;\n\tfor (let i = 0; i < relations.length; i++) {\n\t\tconst relationName = relations[i];\n\t\tif (!relationName) continue;\n\n\t\tconst isLastInChain = i === relations.length - 1;\n\t\tconst chainPath = `${intentPath}[${i}]`;\n\n\t\t// Find the relation\n\t\tconst relation = disambiguateRelation(\n\t\t\trelationName,\n\t\t\tcurrentSource,\n\t\t\tmodel,\n\t\t\tstate,\n\t\t\topts,\n\t\t\tchainPath,\n\t\t);\n\n\t\tif (!relation) {\n\t\t\treturn; // Error already added to warnings or exception thrown\n\t\t}\n\n\t\t// Track relation access for CTE extraction\n\t\tconst relPath = `${currentSource}.${relation.name}`;\n\t\tconst paths = state.relationAccessCounts.get(relPath) ?? [];\n\t\tpaths.push(chainPath);\n\t\tstate.relationAccessCounts.set(relPath, paths);\n\n\t\t// Determine filter strategy (only for last relation in chain)\n\t\tif (isLastInChain) {\n\t\t\tconst filterStrategy = determineFilterStrategy(\n\t\t\t\trelation,\n\t\t\t\topts,\n\t\t\t\tmode ?? 'some',\n\t\t\t);\n\n\t\t\tconst decisionId = generateDecisionId(state, 'filter-strategy');\n\t\t\t// Detect self-referential relation (source === target)\n\t\t\tconst isSelfRef = relation.source === relation.target;\n\t\t\t// SPEC-002: Include full path in context for multi-hop\n\t\t\tconst context: PlanDecision['context'] = {\n\t\t\t\tsourceTable: currentSource,\n\t\t\t\ttarget: relation.target,\n\t\t\t\trelation: relation.name,\n\t\t\t\tintentPath: chainPath,\n\t\t\t\t...(relations.length > 1 && { relationPath: relations.join('.') }),\n\t\t\t\t...(isSelfRef && { isSelfRef }),\n\t\t\t};\n\t\t\tstate.decisions.push({\n\t\t\t\tid: decisionId,\n\t\t\t\ttype: 'filter-strategy',\n\t\t\t\tcontext,\n\t\t\t\tchoice: filterStrategy,\n\t\t\t\treasoning: generateFilterReasoning(\n\t\t\t\t\trelation,\n\t\t\t\t\tfilterStrategy,\n\t\t\t\t\tmode,\n\t\t\t\t\tisSelfRef,\n\t\t\t\t),\n\t\t\t\talternatives: filterStrategy === 'exists' ? ['join'] : ['exists'],\n\t\t\t});\n\n\t\t\t// Check for potential row explosion warning\n\t\t\tif (filterStrategy === 'join' && relation.cardinality === 'many') {\n\t\t\t\tstate.warnings.push({\n\t\t\t\t\tcode: 'POTENTIAL_ROW_EXPLOSION',\n\t\t\t\t\tmessage: `Using JOIN on to-many relation \"${relation.name}\" may cause row multiplication`,\n\t\t\t\t\tsuggestion: `Consider using EXISTS strategy for relation \"${relation.name}\"`,\n\t\t\t\t\trelatedDecision: decisionId,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Process nested where on the final target\n\t\t\tif (nestedWhere) {\n\t\t\t\tprocessWhere(\n\t\t\t\t\tnestedWhere,\n\t\t\t\t\trelation.target,\n\t\t\t\t\tmodel,\n\t\t\t\t\tstate,\n\t\t\t\t\topts,\n\t\t\t\t\t`${intentPath}.where`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Move to next table in chain\n\t\tcurrentSource = relation.target;\n\t}\n}\n\n// ============================================================================\n// Include Processing\n// ============================================================================\n\nfunction processInclude(\n\tinclude: IncludeIntent,\n\tsourceTable: string,\n\tmodel: ModelIR,\n\tstate: PlannerState,\n\topts: Required<PlanOptions>,\n\tintentPath: string,\n\tdepth: number,\n\tancestorIsLeftJoin = false,\n): void {\n\tstate.relationsAnalyzed++;\n\n\t// Check depth\n\tif (depth > opts.maxIncludeDepth) {\n\t\tstate.warnings.push({\n\t\t\tcode: 'DEEP_NESTING',\n\t\t\tmessage: `Include depth ${depth} exceeds maximum ${opts.maxIncludeDepth}`,\n\t\t\tsuggestion: 'Consider flattening the query or increasing maxIncludeDepth',\n\t\t});\n\t}\n\n\t// Use via hint if provided, otherwise use relation name\n\tconst relationName = include.via ?? include.relation;\n\n\t// Resolve the relation\n\tconst relation = disambiguateRelation(\n\t\trelationName,\n\t\tsourceTable,\n\t\tmodel,\n\t\tstate,\n\t\topts,\n\t\tintentPath,\n\t\tinclude.via,\n\t);\n\n\tif (!relation) {\n\t\treturn;\n\t}\n\n\t// Check for circular includes\n\tconst includePath = `${sourceTable}.${relation.name}`;\n\tif (state.visitedIncludes.has(includePath)) {\n\t\tstate.warnings.push({\n\t\t\tcode: 'CIRCULAR_INCLUDE',\n\t\t\tmessage: `Circular include detected: ${includePath}`,\n\t\t\tsuggestion: 'Remove circular include to prevent infinite recursion',\n\t\t});\n\t\treturn;\n\t}\n\tstate.visitedIncludes.add(includePath);\n\n\t// Track relation access for CTE extraction\n\tconst relationPath = `${sourceTable}.${relation.name}`;\n\tconst paths = state.relationAccessCounts.get(relationPath) ?? [];\n\tpaths.push(intentPath);\n\tstate.relationAccessCounts.set(relationPath, paths);\n\n\t// CLI-012c: Check for recursive include on self-referential relations\n\tconst isRecursiveInclude =\n\t\t(!!include.recursive || !!relation.recursive) &&\n\t\trelation.source === relation.target;\n\n\t// Determine include strategy\n\t// Priority: 1) recursive → cte (if dialect supports it), 2) include.join → forces join strategy, 3) include.strategy override, 4) auto-detect\n\tlet includeStrategy: ResolvedIncludeStrategy;\n\tif (isRecursiveInclude) {\n\t\t// FIND-013: Guard recursive → cte against dialect capability.\n\t\t// selectSmartStrategy handles the general case, but processInclude has\n\t\t// an early-exit path that forces 'cte' before reaching it. A dialect\n\t\t// that declared supportsRecursiveCTE=false must not silently receive an\n\t\t// invalid plan.\n\t\tif (opts.dialectCapabilities?.supportsRecursiveCTE === false) {\n\t\t\tthrow new UnsupportedStrategyError(\n\t\t\t\t`Recursive includes require a dialect with supportsRecursiveCTE; ` +\n\t\t\t\t\t`current dialect (${opts.dialectCapabilities.name}) declared it unsupported.`,\n\t\t\t);\n\t\t}\n\t\tincludeStrategy = 'cte';\n\t} else if (include.join !== undefined) {\n\t\t// Explicit join type forces the 'join' strategy (inner or left JOIN)\n\t\tif (include.limit != null) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'include',\n\t\t\t\t`include.limit cannot be applied with the 'join' strategy because join ` +\n\t\t\t\t\t`cannot enforce per-parent-row limits. ` +\n\t\t\t\t\t`Use strategy: 'flat' (→ LATERAL) or strategy: 'cte' explicitly.`,\n\t\t\t);\n\t\t}\n\t\tincludeStrategy = 'join';\n\t} else if (include.strategy === 'flat') {\n\t\t// NQL v2.1: flat = exclude nested output (json_agg), planner picks best flat strategy\n\t\t// lateral only when per-row LIMIT is needed; otherwise join is simpler\n\t\t// Also use lateral when any nested child has a limit (LATERAL cascade required)\n\t\tconst needsLateral = include.limit != null || hasNestedLimit(include);\n\t\tincludeStrategy = selectSmartStrategy(\n\t\t\trelation,\n\t\t\topts.dialectCapabilities,\n\t\t\tfalse,\n\t\t\t/* excludeNested */ true,\n\t\t\t/* hasLimit */ needsLateral,\n\t\t);\n\t} else {\n\t\tincludeStrategy = determineIncludeStrategy(relation, opts);\n\t\t// FIND-014: include.limit cannot be enforced by the join strategy (which\n\t\t// performs a flat JOIN without per-parent-row limiting). Silently\n\t\t// dropping the limit produces unlimited children — incorrect behaviour.\n\t\t// Callers must explicitly request 'flat' (→ lateral) or 'cte' to get\n\t\t// per-parent limiting.\n\t\tif (include.limit != null && includeStrategy === 'join') {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'include',\n\t\t\t\t`include.limit cannot be applied with the 'join' strategy because join ` +\n\t\t\t\t\t`cannot enforce per-parent-row limits. ` +\n\t\t\t\t\t`Use strategy: 'flat' (→ LATERAL) or strategy: 'cte' explicitly.`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Pre-compute join type for include-strategy decision embedding\n\t// (only relevant when strategy is 'join')\n\t// When an ancestor used LEFT JOIN (optional relation), cascade LEFT to preserve\n\t// parent rows — even for relations that would normally be INNER (required).\n\t// An explicit join: 'inner' override on THIS hop resets the cascade for children.\n\tconst autoJoinType = determineJoinType(relation, opts, !!include.where);\n\tconst cascadedJoinType: 'inner' | 'left' =\n\t\tancestorIsLeftJoin && include.join === undefined ? 'left' : autoJoinType;\n\tconst explicitJoinType: 'inner' | 'left' | undefined =\n\t\tincludeStrategy === 'join' ? (include.join ?? cascadedJoinType) : undefined;\n\n\tconst includeDecisionId = generateDecisionId(state, 'include-strategy');\n\n\tstate.decisions.push({\n\t\tid: includeDecisionId,\n\t\ttype: 'include-strategy',\n\t\tcontext: {\n\t\t\tsourceTable,\n\t\t\ttarget: relation.target,\n\t\t\trelation: relation.name,\n\t\t\trelationType: relation.type,\n\t\t\tincludeAlias: include.relation,\n\t\t\tintentPath,\n\t\t\t// Foreign key info for json_agg compilation (Phase 3)\n\t\t\t...(relation.foreignKey !== undefined && {\n\t\t\t\tforeignKey: relation.foreignKey,\n\t\t\t}),\n\t\t},\n\t\tchoice: includeStrategy,\n\t\t// Embed joinType so the adapter's join handler can use it directly\n\t\t...(explicitJoinType !== undefined && { joinType: explicitJoinType }),\n\t\treasoning: isRecursiveInclude\n\t\t\t? `Recursive include on self-referential relation \"${relation.name}\" → forced CTE strategy`\n\t\t\t: generateIncludeReasoning(relation, includeStrategy),\n\t\talternatives: getAlternativeStrategies(\n\t\t\tincludeStrategy,\n\t\t\topts.dialectCapabilities,\n\t\t),\n\t});\n\n\t// CLI-012c: Warn if recursive is set but relation is not self-referential\n\tif (include.recursive && !isRecursiveInclude) {\n\t\tstate.warnings.push({\n\t\t\tcode: 'INVALID_RECURSIVE_INCLUDE',\n\t\t\tmessage: `recursive option on \"${relation.name}\" ignored: relation is not self-referential (source=${relation.source}, target=${relation.target})`,\n\t\t\tsuggestion: `Remove recursive option or use RecursiveIntent for cross-table recursion`,\n\t\t});\n\t}\n\n\t// CLI-012/CLI-012c: Create CTE when strategy is 'cte' (recursive or not)\n\tif (includeStrategy === 'cte') {\n\t\tconst cteName = `cte_${sourceTable}_${relation.name}`;\n\t\t// Check if CTE already exists (avoid duplicates from nested includes)\n\t\tconst existingCte = state.ctes.find((c) => c.name === cteName);\n\t\tif (!existingCte) {\n\t\t\tstate.ctes.push({\n\t\t\t\tname: cteName,\n\t\t\t\tpurpose: isRecursiveInclude\n\t\t\t\t\t? `Recursive include for self-referential \"${relation.name}\"`\n\t\t\t\t\t: `CTE for \"${relation.name}\" include`,\n\t\t\t\treferencedBy: [intentPath],\n\t\t\t\tsourceIntent: `${sourceTable}.${relation.name}`,\n\t\t\t\trecursive: isRecursiveInclude,\n\t\t\t});\n\t\t} else {\n\t\t\t// Add intentPath to existing CTE's referencedBy\n\t\t\t(existingCte.referencedBy as string[]).push(intentPath);\n\t\t}\n\t}\n\n\t// Emit join-type decision (only if using join strategy)\n\tif (includeStrategy === 'join' && explicitJoinType !== undefined) {\n\t\tconst joinDecisionId = generateDecisionId(state, 'join-type');\n\n\t\tstate.decisions.push({\n\t\t\tid: joinDecisionId,\n\t\t\ttype: 'join-type',\n\t\t\tcontext: {\n\t\t\t\tsourceTable,\n\t\t\t\ttarget: relation.target,\n\t\t\t\trelation: relation.name,\n\t\t\t\tintentPath,\n\t\t\t},\n\t\t\tchoice: explicitJoinType,\n\t\t\treasoning: generateJoinReasoning(\n\t\t\t\trelation,\n\t\t\t\texplicitJoinType,\n\t\t\t\t!!include.where,\n\t\t\t),\n\t\t\talternatives: explicitJoinType === 'left' ? ['inner'] : ['left'],\n\t\t});\n\t}\n\n\t// Process nested where\n\tif (include.where) {\n\t\tprocessWhere(\n\t\t\tinclude.where,\n\t\t\trelation.target,\n\t\t\tmodel,\n\t\t\tstate,\n\t\t\topts,\n\t\t\t`${intentPath}.where`,\n\t\t);\n\t}\n\n\t// Process nested includes\n\tif (include.include) {\n\t\t// Propagate LEFT JOIN cascade to children based on THIS hop's actual join type.\n\t\t// - If this hop emits LEFT JOIN → children inherit the cascade\n\t\t// - If this hop emits INNER JOIN (explicit or auto) → cascade resets\n\t\t// When strategy is not 'join' (json_agg, lateral, cte), explicitJoinType is\n\t\t// undefined → false → no cascade (non-join strategies don't affect the chain).\n\t\tconst nextAncestorIsLeftJoin = explicitJoinType === 'left';\n\t\tfor (let i = 0; i < include.include.length; i++) {\n\t\t\tconst nestedInc = include.include[i];\n\t\t\tif (nestedInc) {\n\t\t\t\tprocessInclude(\n\t\t\t\t\tnestedInc,\n\t\t\t\t\trelation.target,\n\t\t\t\t\tmodel,\n\t\t\t\t\tstate,\n\t\t\t\t\topts,\n\t\t\t\t\t`${intentPath}.include[${i}]`,\n\t\t\t\t\tdepth + 1,\n\t\t\t\t\tnextAncestorIsLeftJoin,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove from visited after processing (allow same relation at different depths)\n\tstate.visitedIncludes.delete(includePath);\n}\n\n// ============================================================================\n// Relation Resolution\n// ============================================================================\n\nfunction disambiguateRelation(\n\trelationName: string,\n\tsourceTable: string,\n\tmodel: ModelIR,\n\tstate: PlannerState,\n\topts: Required<PlanOptions>,\n\t_intentPath: string,\n\tviaHint?: string,\n): RelationIR | undefined {\n\t// Try direct lookup first\n\tconst directRelation = model.getRelation(`${sourceTable}.${relationName}`);\n\tif (directRelation) {\n\t\treturn directRelation;\n\t}\n\n\t// Check if this might be a target table name (ambiguous case)\n\tconst relationsToTarget = model\n\t\t.getRelationsFrom(sourceTable)\n\t\t.filter((r) => r.target === relationName);\n\n\tif (relationsToTarget.length === 0) {\n\t\t// Check for virtual recursive relations (ancestors/descendants)\n\t\t// These are auto-inferred from self-referential relations and handled by the compiler\n\t\tif (relationName === 'ancestors' || relationName === 'descendants') {\n\t\t\tconst selfReferentialRelations = model\n\t\t\t\t.getRelationsFrom(sourceTable)\n\t\t\t\t.filter((r) => r.source === r.target);\n\t\t\tif (selfReferentialRelations.length > 0) {\n\t\t\t\t// Virtual recursive relation - return the underlying self-referential relation\n\t\t\t\t// The compiler will handle the actual recursive CTE generation\n\t\t\t\treturn selfReferentialRelations[0];\n\t\t\t}\n\t\t}\n\n\t\t// No relation found\n\t\tstate.warnings.push({\n\t\t\tcode: 'AMBIGUOUS_RELATION',\n\t\t\tmessage: `Unknown relation \"${relationName}\" from table \"${sourceTable}\"`,\n\t\t\tsuggestion: `Check that the relation exists in the schema`,\n\t\t});\n\t\treturn undefined;\n\t}\n\n\tif (relationsToTarget.length === 1) {\n\t\t// Unambiguous - only one relation to target\n\t\treturn relationsToTarget[0];\n\t}\n\n\t// Multiple relations - need disambiguation\n\tconst options = relationsToTarget.map((r) => r.name);\n\n\t// Check for via hint\n\tif (viaHint) {\n\t\tconst resolved = relationsToTarget.find((r) => r.name === viaHint);\n\t\tif (resolved) {\n\t\t\treturn resolved;\n\t\t}\n\t}\n\n\t// Check disambiguate option\n\tconst disambiguateKey = `${sourceTable}.${relationName}`;\n\tconst disambiguated = opts.disambiguate[disambiguateKey];\n\tif (disambiguated) {\n\t\tconst resolved = relationsToTarget.find((r) => r.name === disambiguated);\n\t\tif (resolved) {\n\t\t\treturn resolved;\n\t\t}\n\t}\n\n\t// Ambiguous - throw error\n\tthrow new AmbiguousPlanError(sourceTable, relationName, options);\n}\n\n// ============================================================================\n// Strategy Determination\n// ============================================================================\n\nfunction determineFilterStrategy(\n\trelation: RelationIR,\n\topts: Required<PlanOptions>,\n\t_mode: 'some' | 'every' | 'none',\n): 'exists' | 'join' {\n\t// Forced strategy takes precedence\n\tif (opts.forceFilterStrategy) {\n\t\treturn opts.forceFilterStrategy;\n\t}\n\n\t// Use relation hint if not auto\n\tif (relation.filterStrategy !== 'auto') {\n\t\treturn relation.filterStrategy;\n\t}\n\n\t// Auto-determine based on cardinality and mode\n\tif (relation.cardinality === 'one') {\n\t\treturn 'join';\n\t}\n\n\t// For cardinality 'many', EXISTS is generally better\n\t// (avoids row explosion)\n\treturn 'exists';\n}\n\n/**\n * Resolved include strategy - the actual strategy to use (never 'auto').\n * This is what the compiler receives after planner decision.\n */\n\n/**\n * Determine the include strategy for a relation.\n *\n * Strategy selection logic (CORE-006):\n * 1. If relation has explicit strategy (not 'auto'), use it (after validation)\n * 2. If planner option has explicit strategy (not 'auto'), use it\n * 3. Smart auto selection based on:\n * - Relation type (hasOne/belongsTo → join, hasMany/belongsToMany → depends)\n * - Dialect capabilities (lateral, json_agg support)\n * - Recursive relations → cte\n *\n * @throws {UnsupportedStrategyError} if requested strategy not supported by dialect\n */\nfunction determineIncludeStrategy(\n\trelation: RelationIR,\n\topts: Required<PlanOptions>,\n\tisRecursive = false,\n): ResolvedIncludeStrategy {\n\tconst capabilities = opts.dialectCapabilities;\n\n\t// Helper to validate strategy against dialect capabilities\n\tconst validateStrategy = (\n\t\tstrategy: IncludeStrategy,\n\t): ResolvedIncludeStrategy => {\n\t\tif (strategy === 'auto') {\n\t\t\t// Should not happen, but fallback to join\n\t\t\treturn 'join';\n\t\t}\n\n\t\t// Validate against dialect capabilities if available\n\t\tif (capabilities) {\n\t\t\tif (strategy === 'lateral' && !capabilities.supportsLateralJoin) {\n\t\t\t\tthrow new UnsupportedStrategyError(\n\t\t\t\t\t`Strategy 'lateral' is not supported by ${capabilities.name}. ` +\n\t\t\t\t\t\t`Use 'join', 'subquery', or 'json_agg' instead.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (strategy === 'json_agg' && !capabilities.supportsJsonAgg) {\n\t\t\t\tthrow new UnsupportedStrategyError(\n\t\t\t\t\t`Strategy 'json_agg' is not supported by ${capabilities.name}. ` +\n\t\t\t\t\t\t`Use 'join', 'subquery', or 'lateral' instead.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (strategy === 'cte' && !capabilities.supportsRecursiveCTE) {\n\t\t\t\tthrow new UnsupportedStrategyError(\n\t\t\t\t\t`Strategy 'cte' is not supported by ${capabilities.name}. ` +\n\t\t\t\t\t\t`Use 'join' or 'subquery' instead.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn strategy;\n\t};\n\n\t// 1. Use relation hint if not auto (explicit override)\n\tif (relation.includeStrategy !== 'auto') {\n\t\treturn validateStrategy(relation.includeStrategy);\n\t}\n\n\t// 2. Use planner option if specified (CLI-010: runtime override)\n\tif (opts.defaultIncludeStrategy && opts.defaultIncludeStrategy !== 'auto') {\n\t\treturn validateStrategy(opts.defaultIncludeStrategy);\n\t}\n\n\t// 3. Smart auto selection based on relation type + dialect\n\treturn selectSmartStrategy(relation, capabilities, isRecursive);\n}\n\n/**\n * Check if any nested include (recursively) has a limit set.\n * Used to determine if an intermediate ancestor needs LATERAL for cascade.\n */\nfunction hasNestedLimit(include: IncludeIntent): boolean {\n\tif (!include.include || include.include.length === 0) return false;\n\tfor (const child of include.include) {\n\t\tif (child.limit != null) return true;\n\t\tif (hasNestedLimit(child)) return true;\n\t}\n\treturn false;\n}\n\n/**\n * Smart strategy selection based on relation characteristics and dialect.\n *\n * Selection algorithm:\n * - Recursive relations → 'cte' (if supported) or 'subquery'\n * - hasOne/belongsTo (to-one) → 'join' (always safe, single row)\n * - hasMany/belongsToMany (to-many):\n * - If dialect supports json_agg → 'json_agg' (single row per parent, no explosion)\n * - Else if dialect supports lateral → 'lateral' (good with LIMIT)\n * - Else → 'join' (let DB optimize, user can override to 'subquery' if needed)\n */\nfunction selectSmartStrategy(\n\t_relation: RelationIR,\n\tcapabilities: DialectCapabilities | undefined,\n\tisRecursive: boolean,\n\texcludeNested = false,\n\thasLimit = false,\n): ResolvedIncludeStrategy {\n\t// Recursive relations should use CTE\n\tif (isRecursive) {\n\t\tif (capabilities?.supportsRecursiveCTE !== false) {\n\t\t\treturn 'cte';\n\t\t}\n\t\t// Fallback for dialects without CTE support (rare)\n\t\treturn 'subquery';\n\t}\n\n\t// Default strategy for ALL relation types: json_agg\n\t// Rationale:\n\t// - json_agg: aggregates children into single JSON array, no row explosion\n\t// - Works for both to-one (hasOne, belongsTo) and to-many (hasMany)\n\t// - User can force JOIN via | flat modifier if data is too large for JSON\n\t// - lateral: only when per-row LIMIT is needed (top N children pattern)\n\t// - join: simple flat strategy, well-optimized by the database\n\n\tif (capabilities?.supportsJsonAgg && !excludeNested) {\n\t\treturn 'json_agg';\n\t}\n\n\t// LATERAL only when per-row LIMIT is needed — otherwise join is simpler and faster\n\tif (hasLimit && capabilities?.supportsLateralJoin) {\n\t\treturn 'lateral';\n\t}\n\n\t// Fallback: use join (database optimizer handles it)\n\t// User can explicitly request 'subquery' if row explosion is a concern\n\treturn 'join';\n}\n\n/**\n * Error thrown when requested include strategy is not supported by dialect.\n */\nexport class UnsupportedStrategyError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'UnsupportedStrategyError';\n\t}\n}\n\n/**\n * Get alternative strategies for a given strategy based on dialect capabilities.\n */\nfunction getAlternativeStrategies(\n\tstrategy: ResolvedIncludeStrategy,\n\tcapabilities: DialectCapabilities | undefined,\n): string[] {\n\tconst allStrategies: ResolvedIncludeStrategy[] = [\n\t\t'join',\n\t\t'subquery',\n\t\t'cte',\n\t\t'lateral',\n\t\t'json_agg',\n\t];\n\n\t// Filter out current strategy and unsupported ones\n\treturn allStrategies.filter((s) => {\n\t\tif (s === strategy) return false;\n\t\tif (!capabilities) return s === 'join' || s === 'subquery'; // No capabilities = only basic strategies\n\t\tif (s === 'lateral' && !capabilities.supportsLateralJoin) return false;\n\t\tif (s === 'json_agg' && !capabilities.supportsJsonAgg) return false;\n\t\tif (s === 'cte' && !capabilities.supportsRecursiveCTE) return false;\n\t\treturn true;\n\t});\n}\n\nfunction determineJoinType(\n\trelation: RelationIR,\n\topts: Required<PlanOptions>,\n\thasFilter: boolean,\n): 'left' | 'inner' {\n\t// Forced join type takes precedence\n\tif (opts.forceJoinType) {\n\t\treturn opts.forceJoinType;\n\t}\n\n\t// Use relation hint if not auto\n\tif (relation.joinDefault !== 'auto') {\n\t\treturn relation.joinDefault;\n\t}\n\n\t// Auto-determine based on optionality and filter presence\n\tif (relation.optionality === 'required') {\n\t\treturn 'inner';\n\t}\n\n\t// Optional relation with filter implies existence\n\tif (hasFilter) {\n\t\treturn 'inner';\n\t}\n\n\t// Optional without filter -> LEFT to preserve parent rows\n\treturn 'left';\n}\n\n// ============================================================================\n// Raw SQL Detection (Security Observability)\n// ============================================================================\n\n/**\n * Detects raw SQL expressions in the query intent and adds security warnings.\n * This provides observability for potentially unsafe SQL usage.\n */\nfunction detectRawSqlUsage(intent: QueryIntent, state: PlannerState): void {\n\t// Check SELECT expressions for raw SQL\n\tif (\n\t\tintent.select &&\n\t\t'type' in intent.select &&\n\t\tintent.select.type === 'expressions'\n\t) {\n\t\tfor (const col of intent.select.columns) {\n\t\t\t// Direct ExpressionIntent format - check if it's a raw expression\n\t\t\tif (isRawExpression(col)) {\n\t\t\t\tstate.warnings.push({\n\t\t\t\t\tcode: 'RAW_SQL_USAGE',\n\t\t\t\t\tmessage: `Raw SQL expression detected: \"${col.sql}\" (alias: ${col.as})`,\n\t\t\t\t\tsuggestion:\n\t\t\t\t\t\t'Raw SQL bypasses type safety and SQL injection protection. ' +\n\t\t\t\t\t\t'Ensure the SQL is safe and consider using built-in expression helpers instead.',\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ============================================================================\n// CTE Extraction\n// ============================================================================\n\nfunction extractCTEs(state: PlannerState, threshold: number): void {\n\t// PERF (FIND-053): build O(1) lookup structures once before the R-relation loop,\n\t// replacing O(R×D) linear scans (decisions.find + ctes.some) inside the loop.\n\tconst decisionByTableRelation = new Map<string, PlanDecision>();\n\tfor (const d of state.decisions) {\n\t\tif (d.type === 'include-strategy') {\n\t\t\tconst k = `${d.context?.sourceTable ?? ''}:${d.context?.relation ?? ''}`;\n\t\t\t// Keep first match (earliest decision wins)\n\t\t\tif (!decisionByTableRelation.has(k)) {\n\t\t\t\tdecisionByTableRelation.set(k, d);\n\t\t\t}\n\t\t}\n\t}\n\tconst cteNameSet = new Set(state.ctes.map((c) => c.name));\n\n\tfor (const [relationPath, intentPaths] of state.relationAccessCounts) {\n\t\tif (intentPaths.length >= threshold) {\n\t\t\tconst parts = relationPath.split('.');\n\t\t\tconst table = parts[0] ?? 'unknown';\n\t\t\tconst relation = parts[1] ?? 'unknown';\n\t\t\tconst cteName = `cte_${table}_${relation}`;\n\n\t\t\t// SPEC-002: Skip CTE extraction if the include strategy is 'json_agg'.\n\t\t\t// json_agg uses a subquery that doesn't benefit from CTEs and would conflict.\n\t\t\t// Other strategies (join, cte, separate) can still use CTE extraction.\n\t\t\tconst includeStrategyDecision = decisionByTableRelation.get(\n\t\t\t\t`${table}:${relation}`,\n\t\t\t);\n\t\t\tif (includeStrategyDecision?.choice === 'json_agg') {\n\t\t\t\t// json_agg strategy uses its own subquery - CTE extraction not needed\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Skip if CTE already exists (from include processing)\n\t\t\tif (cteNameSet.has(cteName)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tstate.ctes.push({\n\t\t\t\tname: cteName,\n\t\t\t\tpurpose: `${relation} relation accessed ${intentPaths.length} times`,\n\t\t\t\treferencedBy: Object.freeze(intentPaths.slice()),\n\t\t\t\tsourceIntent: relationPath,\n\t\t\t});\n\n\t\t\tconst decisionId = generateDecisionId(state, 'cte-extraction');\n\t\t\tstate.decisions.push({\n\t\t\t\tid: decisionId,\n\t\t\t\ttype: 'cte-extraction',\n\t\t\t\tcontext: {\n\t\t\t\t\tsourceTable: table,\n\t\t\t\t\trelation,\n\t\t\t\t},\n\t\t\t\tchoice: cteName,\n\t\t\t\treasoning: `Extracting ${relationPath} to CTE \"${cteName}\" because it is accessed ${intentPaths.length} times (threshold: ${threshold})`,\n\t\t\t\talternatives: ['inline'],\n\t\t\t});\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\nfunction generateDecisionId(state: PlannerState, type: DecisionType): string {\n\tstate.decisionCounters[type]++;\n\tconst counter = state.decisionCounters[type].toString().padStart(3, '0');\n\treturn `${type.replace('-', '')}-${counter}`;\n}\n\nfunction generateFilterReasoning(\n\trelation: RelationIR,\n\tstrategy: 'exists' | 'join',\n\tmode?: 'some' | 'every' | 'none',\n\tisSelfRef?: boolean,\n): string {\n\tconst modeText = mode ? ` (mode: ${mode})` : '';\n\tconst selfRefText = isSelfRef ? ' [self-referential]' : '';\n\n\tif (strategy === 'exists') {\n\t\treturn (\n\t\t\t`Relation ${relation.source}.${relation.name} has cardinality \"${relation.cardinality}\"${modeText}${selfRefText} - ` +\n\t\t\t`using EXISTS to avoid row explosion`\n\t\t);\n\t}\n\n\treturn (\n\t\t`Relation ${relation.source}.${relation.name} has cardinality \"${relation.cardinality}\"${modeText}${selfRefText} - ` +\n\t\t`using JOIN for efficient single-row access`\n\t);\n}\n\nfunction generateIncludeReasoning(\n\trelation: RelationIR,\n\tstrategy: ResolvedIncludeStrategy,\n): string {\n\tconst prefix = `Relation ${relation.source}.${relation.name} (${relation.type}, cardinality: ${relation.cardinality})`;\n\n\tswitch (strategy) {\n\t\tcase 'join':\n\t\t\treturn `${prefix} - using JOIN for efficient single-query fetch`;\n\t\tcase 'subquery':\n\t\t\treturn `${prefix} - using subquery query to avoid row multiplication`;\n\t\tcase 'cte':\n\t\t\treturn `${prefix} - using CTE for recursive/hierarchical traversal`;\n\t\tcase 'lateral':\n\t\t\treturn `${prefix} - using LATERAL JOIN for per-row correlated subquery (LIMIT per parent)`;\n\t\tcase 'json_agg':\n\t\t\treturn `${prefix} - using JSON aggregation to avoid row explosion`;\n\t}\n}\n\nfunction generateJoinReasoning(\n\trelation: RelationIR,\n\tjoinType: 'left' | 'inner',\n\t_hasFilter: boolean,\n): string {\n\tif (joinType === 'inner') {\n\t\tif (relation.optionality === 'required') {\n\t\t\treturn (\n\t\t\t\t`Relation ${relation.source}.${relation.name} is required - ` +\n\t\t\t\t`using INNER JOIN`\n\t\t\t);\n\t\t}\n\t\treturn (\n\t\t\t`Relation ${relation.source}.${relation.name} has filter - ` +\n\t\t\t`using INNER JOIN (filter implies existence)`\n\t\t);\n\t}\n\n\treturn (\n\t\t`Relation ${relation.source}.${relation.name} is optional without filter - ` +\n\t\t`using LEFT JOIN to preserve parent rows without matches`\n\t);\n}\n","/**\n * Adapter interface for database adapters.\n *\n * Type definitions live in @dbsp/types. This module re-exports them\n * and provides runtime functions and error classes.\n *\n * @module adapter\n */\n\n// Re-export all adapter types from @dbsp/types for backward compatibility\nexport type {\n\tAdapter,\n\tAdapterCapabilities,\n\tAdapterLogger,\n\tAdapterStreamOptions,\n\tAliasIncludedColumnsMode,\n\tAlterColumnOptions,\n\tBaseAdapter,\n\tCompiledQuery,\n\tCompileOnlyAdapter,\n\tCompileOptions,\n\tCompileResultWithIncludes,\n\tCompilingAdapter,\n\tCreateIndexOptions,\n\tDbCasing,\n\tDDLGeneratingAdapter,\n\tDropIndexOptions,\n\tDump,\n\tDumpMeta,\n\tExecutingAdapter,\n\tIndexColumnDef,\n\tIndexInfo,\n\tIndexMethod,\n\tIntrospectingAdapter,\n\tIntrospectionOptions,\n\tIntrospectionResult,\n\tRawSqlAdapter,\n\tStreamingAdapter,\n\tSubqueryIncludeInfo,\n\tTableDDLGeneratorAdapter,\n\tTransactionalAdapter,\n\tTruncateOptions,\n\tVacuumOptions,\n} from '@dbsp/types';\n\nimport type {\n\tAdapter,\n\tAdapterCapabilities,\n\tBaseAdapter,\n\tDDLGeneratingAdapter,\n\tExecutingAdapter,\n\tIntrospectingAdapter,\n\tRawSqlAdapter,\n\tStreamingAdapter,\n\tTransactionalAdapter,\n} from '@dbsp/types';\n\n// ============================================================================\n// Feature Detection Helpers (DX-104)\n// ============================================================================\n\n/**\n * Check if adapter supports execution.\n */\nexport function supportsExecution(\n\tadapter: BaseAdapter,\n): adapter is ExecutingAdapter {\n\treturn (\n\t\t'execute' in adapter &&\n\t\t'executeOne' in adapter &&\n\t\ttypeof (adapter as ExecutingAdapter).execute === 'function'\n\t);\n}\n\n/**\n * Check if adapter supports streaming.\n */\nexport function supportsStreaming(\n\tadapter: BaseAdapter,\n): adapter is StreamingAdapter {\n\treturn (\n\t\t'stream' in adapter &&\n\t\ttypeof (adapter as StreamingAdapter).stream === 'function'\n\t);\n}\n\n/**\n * Check if adapter supports introspection.\n */\nexport function supportsIntrospection(\n\tadapter: BaseAdapter,\n): adapter is IntrospectingAdapter {\n\treturn (\n\t\t'introspect' in adapter &&\n\t\ttypeof (adapter as IntrospectingAdapter).introspect === 'function'\n\t);\n}\n\n/**\n * Check if adapter supports transactions.\n */\nexport function supportsTransactions<DB>(\n\tadapter: BaseAdapter,\n): adapter is TransactionalAdapter<DB> {\n\treturn (\n\t\t'transaction' in adapter &&\n\t\t'withSchema' in adapter &&\n\t\ttypeof (adapter as TransactionalAdapter<DB>).transaction === 'function'\n\t);\n}\n\n/**\n * Check if adapter supports raw SQL execution.\n */\nexport function supportsRawSql(adapter: BaseAdapter): adapter is RawSqlAdapter {\n\treturn (\n\t\t'executeRaw' in adapter &&\n\t\ttypeof (adapter as RawSqlAdapter).executeRaw === 'function'\n\t);\n}\n\n/**\n * Check if adapter supports DDL generation.\n */\nexport function supportsDDLGeneration(\n\tadapter: BaseAdapter,\n): adapter is DDLGeneratingAdapter {\n\treturn (\n\t\t'generateDDL' in adapter &&\n\t\ttypeof (adapter as DDLGeneratingAdapter).generateDDL === 'function'\n\t);\n}\n\n// ============================================================================\n// Errors\n// ============================================================================\n\n/**\n * Error thrown when an operation requires an adapter but none was provided.\n */\nexport class AdapterRequiredError extends Error {\n\tconstructor(operation: string) {\n\t\tsuper(\n\t\t\t`Operation '${operation}' requires an adapter. ` +\n\t\t\t\t'Pass an adapter when creating the ORM: createOrm({ model, adapter })',\n\t\t);\n\t\tthis.name = 'AdapterRequiredError';\n\t}\n}\n\n/**\n * Error thrown when an operation requires a capability the adapter doesn't support.\n */\nexport class UnsupportedCapabilityError extends Error {\n\tconstructor(operation: string, capability: keyof AdapterCapabilities) {\n\t\tsuper(\n\t\t\t`Operation '${operation}' requires capability '${capability}' ` +\n\t\t\t\t'which is not supported by the current adapter.',\n\t\t);\n\t\tthis.name = 'UnsupportedCapabilityError';\n\t}\n}\n\n/**\n * Assert that an adapter supports a required capability.\n */\nexport function assertCapability(\n\tadapter: Adapter,\n\tcapability: keyof AdapterCapabilities,\n\toperation: string,\n): void {\n\tif (!adapter.capabilities[capability]) {\n\t\tthrow new UnsupportedCapabilityError(operation, capability);\n\t}\n}\n","import { validateIdentifier } from './errors.js';\n\n// ============================================================================\n// Structured PostgreSQL type-name grammar\n// ============================================================================\n\n/**\n * Fixed allowlist of known multi-word PostgreSQL base types (case-insensitive).\n * These are the only multi-word base types accepted by the structured grammar;\n * all other base types must be strict SQL identifiers (optionally schema-qualified).\n */\nconst MULTIWORD_BASE_TYPES: readonly string[] = [\n\t'timestamp with time zone',\n\t'timestamp without time zone',\n\t'time with time zone',\n\t'time without time zone',\n\t'double precision',\n\t'character varying',\n\t'bit varying',\n];\n\n/** Match a strict SQL identifier: letter or underscore, then letters/digits/underscores. */\nconst IDENT_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/**\n * Validate a PostgreSQL type name for use in CAST($N AS type[]).\n *\n * Accepted grammar (structured, not a broad character-class):\n * typeName = trim(base [modifier] [arraySuffix])\n *\n * arraySuffix = \"[]\" — at most ONE level; \"int4[][]\" is rejected as a\n * raw type-name input (array-ness is handled by the\n * batch-values layer which appends its own \"[]\").\n * modifier = \"(\" digits \")\" | \"(\" digits \",\" digits \")\"\n * — e.g. \"(255)\", \"(10,2)\"; any other parenthesised\n * content is rejected.\n * base = multiWordType | ident | ident \".\" ident\n * multiWordType = one of: \"timestamp with time zone\",\n * \"timestamp without time zone\",\n * \"time with time zone\",\n * \"time without time zone\",\n * \"double precision\",\n * \"character varying\",\n * \"bit varying\"\n * ident = [A-Za-z_][A-Za-z0-9_]*\n *\n * Examples that pass: int4, text, uuid, numeric(10,2), varchar(255),\n * timestamp with time zone, myschema.myenum, int4[].\n * Examples that throw: empty string, int4[][], int4) ; DROP TABLE x; --,\n * foo'bar, int4)); JOIN users ON true.\n *\n * @internal — exported for adapter compile-time revalidation only.\n */\nexport function validateTypeName(typeName: string): void {\n\tconst raw = typeName.trim();\n\tif (raw.length === 0) {\n\t\tthrow new Error(\n\t\t\t`batchValues: invalid type name '${typeName}'. Type names must not be empty.`,\n\t\t);\n\t}\n\n\tlet rest = raw;\n\n\t// ── Step 1: strip at most ONE trailing array suffix \"[]\" ─────────────────\n\t// More than one \"[]\" (e.g. \"int4[][]\") is rejected by the grammar: after\n\t// stripping one, the remaining rest must NOT end in \"[]\" again.\n\tif (rest.endsWith('[]')) {\n\t\trest = rest.slice(0, -2);\n\t\tif (rest.endsWith('[]')) {\n\t\t\tthrow new Error(\n\t\t\t\t`batchValues: invalid type name '${typeName}'. ` +\n\t\t\t\t\t'At most one array suffix \"[]\" is allowed as a raw type-name input. ' +\n\t\t\t\t\t'Use \"int4[]\" not \"int4[][]\".',\n\t\t\t);\n\t\t}\n\t}\n\n\t// ── Step 2: strip optional modifier \"(N)\" or \"(N,M)\" ─────────────────────\n\t// Only digits inside parens; any other parenthesised content is rejected.\n\tconst modifierMatch = rest.match(/\\(([^)]*)\\)$/);\n\tif (modifierMatch) {\n\t\tconst inner = modifierMatch[1] ?? '';\n\t\tif (!/^\\d+(?:,\\d+)?$/.test(inner)) {\n\t\t\tthrow new Error(\n\t\t\t\t`batchValues: invalid type name '${typeName}'. ` +\n\t\t\t\t\t`Type modifier must be \"(N)\" or \"(N,M)\" with digits only; got \"(${inner})\".`,\n\t\t\t);\n\t\t}\n\t\trest = rest.slice(0, rest.length - modifierMatch[0].length).trimEnd();\n\t}\n\n\t// ── Step 3: validate the base type ───────────────────────────────────────\n\tconst baseLower = rest.toLowerCase();\n\n\t// (a) Multi-word allowlist (case-insensitive)\n\tif (MULTIWORD_BASE_TYPES.includes(baseLower)) {\n\t\treturn; // valid\n\t}\n\n\t// (b) Strict identifier, optionally schema-qualified: ident | ident.ident\n\tconst parts = rest.split('.');\n\tif (parts.length > 2) {\n\t\tthrow new Error(\n\t\t\t`batchValues: invalid type name '${typeName}'. ` +\n\t\t\t\t'Schema-qualified types allow at most one dot (schema.type).',\n\t\t);\n\t}\n\tfor (const part of parts) {\n\t\tif (!IDENT_RE.test(part)) {\n\t\t\tthrow new Error(\n\t\t\t\t`batchValues: invalid type name '${typeName}'. ` +\n\t\t\t\t\t`Base type \"${part}\" is not a valid SQL identifier ` +\n\t\t\t\t\t'([A-Za-z_][A-Za-z0-9_]*) and is not in the multi-word type allowlist.',\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * BatchValuesRef — a virtual batch data source backed by unnest($1::type[], ...).\n *\n * Created via `orm.batchValues(data, columns, types, opts?)`.\n * Used as a source in `.from()` or `.join()` to operate on a set of\n * parameter-bound arrays without a real table.\n *\n * @example Batch UPDATE\n * ```typescript\n * const batch = orm.batchValues(\n * [ids, calleeIds],\n * ['id', 'callee_id'],\n * ['integer', 'integer'],\n * );\n * await orm.modify(calls)\n * .join(batch, { on: eq('calls.id', ref('batch.id')) })\n * .set({ callee_id: ref('batch.callee_id') })\n * .execute();\n * ```\n *\n * @example Batch lookup with ordinality\n * ```typescript\n * const requested = orm.batchValues(\n * [paths, names],\n * ['path', 'name'],\n * ['text', 'text'],\n * { ordinality: true },\n * );\n * await orm.from(requested)\n * .join('files', { on: eq('files.path', ref('requested.path')) })\n * .orderBy('requested.ord')\n * .all();\n * ```\n */\nexport type BatchValuesOptions = {\n\t/** Add WITH ORDINALITY -- appends an 'ord' column with row numbers */\n\treadonly ordinality?: boolean;\n\t/** Alias for the unnest source in SQL (default: 'batch') */\n\treadonly alias?: string;\n};\n\n/**\n * A virtual batch data source backed by `unnest($1::type[], $2::type[], ...)`.\n *\n * Not a QueryBuilder -- it is a lightweight descriptor passed to `.from()` or\n * `.join()`. The adapter compiles it to a RangeFunction AST node.\n */\nexport type BatchValuesRef = {\n\treadonly __kind: 'batchValues';\n\t/** Column-major data arrays: one array per column */\n\treadonly data: readonly unknown[][];\n\t/** Column names for the unnest alias clause */\n\treadonly columns: readonly string[];\n\t/** PostgreSQL type names for CAST ($1::type[]) -- e.g. 'integer', 'text' */\n\treadonly types: readonly string[];\n\t/** SQL alias used to reference this source (default: 'batch') */\n\treadonly alias: string;\n\t/** When true, WITH ORDINALITY is emitted -- adds an 'ord' column */\n\treadonly ordinality: boolean;\n};\n\n/**\n * Type guard for BatchValuesRef.\n */\nexport function isBatchValuesRef(value: unknown): value is BatchValuesRef {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'__kind' in value &&\n\t\t(value as BatchValuesRef).__kind === 'batchValues'\n\t);\n}\n\n/**\n * Factory function -- create a BatchValuesRef descriptor.\n *\n * @param data Column-major arrays: `[idsArray, namesArray, ...]`\n * @param columns Column names: `['id', 'name', ...]`\n * @param types PG type names: `['integer', 'text', ...]`\n * @param opts Optional: alias and ordinality flag\n */\nexport function batchValues(\n\tdata: readonly unknown[][],\n\tcolumns: readonly string[],\n\ttypes: readonly string[],\n\topts?: BatchValuesOptions,\n): BatchValuesRef {\n\tif (data.length !== columns.length || data.length !== types.length) {\n\t\tthrow new Error(\n\t\t\t'batchValues: data, columns, and types must have the same length ' +\n\t\t\t\t`(got ${data.length}, ${columns.length}, ${types.length})`,\n\t\t);\n\t}\n\tif (columns.length === 0) {\n\t\tthrow new Error('batchValues: at least one column is required');\n\t}\n\t// Security: validate type names to prevent SQL injection via CAST($N AS type[]).\n\t// Uses the type-name-safe validator (allows spaces, parens, brackets, dots)\n\t// so that complex types like 'varchar(255)', 'numeric(10,2)', 'int4[]',\n\t// and 'timestamp with time zone' are accepted while injection chars are rejected.\n\t// Normalize (trim) each type name before validation so that the stored descriptor\n\t// holds clean values — the adapter's compile-time array check (endsWith('[]'))\n\t// must see a trimmed string or it produces the wrong cast shape.\n\tconst normalizedTypes = types.map((t) => t.trim());\n\tfor (const t of normalizedTypes) {\n\t\tvalidateTypeName(t);\n\t}\n\t// Security: validate alias and column names centrally so BOTH the\n\t// orm.from(batchValues(...)) and orm...join(batchValues(...)) paths are\n\t// protected at the source. The deparser emits these as SQL identifiers\n\t// in AS alias(col1, col2) — an unvalidated name could inject SQL.\n\tconst alias = opts?.alias ?? 'batch';\n\tvalidateIdentifier(alias, 'alias');\n\tfor (const col of columns) {\n\t\tvalidateIdentifier(col, 'column');\n\t}\n\t// Defensive copies: freeze all returned arrays so post-construction mutation\n\t// of the caller's arrays cannot change what gets compiled.\n\t// Vector 1 (mutation): caller mutates original arrays after batchValues() returns.\n\t// Each data row is also copied so the caller cannot mutate individual arrays.\n\t// The inner Object.freeze returns `readonly unknown[]` but BatchValuesRef.data\n\t// declares `readonly unknown[][]` (inner arrays typed as mutable unknown[]).\n\t// The cast is safe: callers only read from data[], never write to inner arrays.\n\tconst frozenData: readonly unknown[][] = Object.freeze(\n\t\tdata.map((row) => Object.freeze([...row]) as unknown[]),\n\t);\n\tconst frozenColumns: readonly string[] = Object.freeze([...columns]);\n\t// Store normalized (trimmed) type names so the adapter's compile-time checks\n\t// (e.g. endsWith('[]')) work correctly without re-trimming at every call site.\n\tconst frozenTypes: readonly string[] = Object.freeze([...normalizedTypes]);\n\treturn Object.freeze({\n\t\t__kind: 'batchValues',\n\t\tdata: frozenData,\n\t\tcolumns: frozenColumns,\n\t\ttypes: frozenTypes,\n\t\talias,\n\t\tordinality: opts?.ordinality ?? false,\n\t});\n}\n","/**\n * @module expressions\n * Dialect-agnostic expression primitives for custom operators, functions, and type casts.\n *\n * These primitives allow constructing arbitrary SQL expressions in a safe, parameterized\n * way — without raw SQL concatenation. Designed as the foundation for dialect extensions\n * (e.g., pgvector, ParadeDB) and advanced query needs.\n *\n * @example\n * ```typescript\n * import { op, ref, param, cast, fn, literal } from '@dbsp/core';\n *\n * // pgvector cosine distance: vector <=> $1::vector\n * const dist = op('<=>', ref('embedding'), cast(param([0.1, 0.2, 0.3]), 'vector'));\n *\n * // Use in SELECT with alias\n * orm.select('items').column(dist.as('score'))\n *\n * // Use in WHERE\n * orm.select('items').where(dist.gte(0.5))\n *\n * // Use in ORDER BY\n * orm.select('items').orderBy(dist, 'asc')\n * ```\n */\n\nimport type {\n\tAggOrderByArg,\n\tArrayExpressionIntent,\n\tCastExpressionIntent,\n\tCustomFnExpressionIntent,\n\tCustomOpExpressionIntent,\n\tExpressionIntent,\n\tLiteralExpressionIntent,\n\tNamedArgExpressionIntent,\n\tParamExpressionIntent,\n\tRefExpressionIntent,\n\tStarExpressionIntent,\n\tUnaryExpressionIntent,\n\tWhereExpressionIntent,\n\tWhereIntent,\n} from '../intent-ast.js';\nimport type { ExpressionSpec } from './types.js';\n\n// ============================================================================\n// Validation patterns\n// ============================================================================\n\nconst OPERATOR_PATTERN = /^[a-zA-Z_<>=!@#%^&|~*+\\-/.]+$/;\nconst FUNCTION_NAME_PATTERN =\n\t/^[a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*$/;\nconst TYPE_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_ ]*(\\[\\])?$/;\n\n// ============================================================================\n// ExprInput type\n// ============================================================================\n\n/**\n * Accepted input types for op() and fn() arguments.\n * - `ExpressionRef` → used as-is\n * - `string` → implicitly converted to ref() (column reference)\n * - `number | boolean | readonly unknown[]` → implicitly converted to param() (bound value)\n *\n * Use `ref()` / `param()` explicitly for ambiguous cases (e.g., a string that is a value,\n * not a column name → use `literal()` instead).\n */\n/**\n * Accepted input types for op() and fn() arguments.\n * - `ExpressionRef` → used as-is\n * - `string` → implicitly converted to ref() (column reference)\n * - `number | boolean | readonly unknown[]` → implicitly converted to param() (bound value)\n * - `AggOrderByArg` → ORDER BY entry inside an aggregate (fn() only)\n *\n * Use `ref()` / `param()` explicitly for ambiguous cases (e.g., a string that is a value,\n * not a column name → use `literal()` instead).\n */\nexport type ExprInput =\n\t| ExpressionRef\n\t| ExpressionSpec\n\t| AggOrderByArg\n\t| string\n\t| number\n\t| boolean\n\t| readonly unknown[];\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\nfunction toExpressionIntent(input: ExprInput): ExpressionIntent {\n\t// ExpressionRef check first — fastest path for the common case.\n\tif (input instanceof ExpressionRef) return input.intent;\n\t// Duck-type check AFTER instanceof: SubqueryExpression.asExpr() returns a plain\n\t// { __expr: true, intent } object (not an ExpressionRef instance), so instanceof\n\t// would miss it. Order matters: instanceof must come first.\n\tif (\n\t\ttypeof input === 'object' &&\n\t\tinput !== null &&\n\t\t'__expr' in input &&\n\t\t(input as { __expr: unknown }).__expr === true &&\n\t\t'intent' in input\n\t) {\n\t\treturn (input as { intent: ExpressionIntent }).intent;\n\t}\n\tif (typeof input === 'string') {\n\t\treturn { kind: 'ref', column: input } satisfies RefExpressionIntent;\n\t}\n\treturn { kind: 'param', value: input } satisfies ParamExpressionIntent;\n}\n\n// ============================================================================\n// ExpressionRef — chainable wrapper around ExpressionIntent\n// ============================================================================\n\n/**\n * A chainable wrapper around an ExpressionIntent.\n *\n * Created by factory functions (`op`, `fn`, `ref`, `param`, `cast`, `literal`, `unary`).\n * Can be used in:\n * - `.column(expr.as('alias'))` — SELECT with alias\n * - `.where(expr.gte(0.5))` — WHERE with comparison\n * - `.orderBy(expr, 'asc')` — ORDER BY expression\n *\n * Implements the `ExpressionSpec` duck-type interface (`__expr: true`, `intent`).\n */\nexport class ExpressionRef {\n\treadonly __expr: true = true;\n\treadonly intent: ExpressionIntent;\n\n\tconstructor(intent: ExpressionIntent) {\n\t\tthis.intent = intent;\n\t}\n\n\t/**\n\t * Set an alias for this expression in SELECT.\n\t * Returns a new ExpressionRef — does not mutate.\n\t */\n\tas(alias: string): ExpressionRef {\n\t\treturn new ExpressionRef({\n\t\t\t...this.intent,\n\t\t\tas: alias,\n\t\t} as ExpressionIntent);\n\t}\n\n\t/** WHERE: expr = value */\n\teq(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'eq', value };\n\t}\n\n\t/** WHERE: expr != value */\n\tneq(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'neq', value };\n\t}\n\n\t/** WHERE: expr > value */\n\tgt(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'gt', value };\n\t}\n\n\t/** WHERE: expr >= value */\n\tgte(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'gte', value };\n\t}\n\n\t/** WHERE: expr < value */\n\tlt(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'lt', value };\n\t}\n\n\t/** WHERE: expr <= value */\n\tlte(value: unknown): WhereExpressionIntent {\n\t\treturn { kind: 'expression', expr: this.intent, operator: 'lte', value };\n\t}\n\n\t/**\n\t * Add a FILTER (WHERE ...) clause to this function expression.\n\t * Only valid on `fn()` expressions (customFn kind).\n\t * Returns a new ExpressionRef — does not mutate.\n\t *\n\t * @example fn('array_agg', ref('name')).filter(eq('active', true))\n\t * → array_agg(\"name\") FILTER (WHERE \"active\" = $1)\n\t * @throws Error if called on non-customFn expressions\n\t */\n\tfilter(condition: WhereIntent): ExpressionRef {\n\t\tif (this.intent.kind !== 'customFn') {\n\t\t\tthrow new Error(\n\t\t\t\t`filter() can only be used on function expressions created with fn(). Got kind: '${this.intent.kind}'`,\n\t\t\t);\n\t\t}\n\t\treturn new ExpressionRef({\n\t\t\t...this.intent,\n\t\t\tfilter: condition,\n\t\t} as CustomFnExpressionIntent);\n\t}\n}\n\n// ============================================================================\n// Factory functions\n// ============================================================================\n\n/**\n * Column reference — refers to a named column (or table.column).\n *\n * @example ref('embedding') → \"embedding\"\n * @example ref('t.score') → \"t\".\"score\"\n */\nexport function ref(column: string): ExpressionRef {\n\treturn new ExpressionRef({\n\t\tkind: 'ref',\n\t\tcolumn,\n\t} satisfies RefExpressionIntent);\n}\n\n/**\n * Parameterized value — automatically bound as $N.\n * Use for user-supplied values, vectors, dynamic data.\n *\n * @example param([0.1, 0.2]) → $1 (with value bound to $1)\n */\nexport function param(value: unknown): ExpressionRef {\n\treturn new ExpressionRef({\n\t\tkind: 'param',\n\t\tvalue,\n\t} satisfies ParamExpressionIntent);\n}\n\n/**\n * Type cast — compiles to expr::typeName or CAST(expr AS typeName).\n *\n * @example cast(param([0.1, 0.2]), 'vector') → $1::vector\n * @throws Error if typeName fails validation (injection guard)\n */\nexport function cast(expr: ExpressionRef, typeName: string): ExpressionRef {\n\tif (!TYPE_NAME_PATTERN.test(typeName)) {\n\t\tthrow new Error(`Invalid type name: ${typeName}`);\n\t}\n\treturn new ExpressionRef({\n\t\tkind: 'cast',\n\t\texpr: expr.intent,\n\t\ttypeName,\n\t} satisfies CastExpressionIntent);\n}\n\n/**\n * Custom binary operator — left OP right.\n * Implicit conversions: string → ref(), number/boolean/array → param().\n *\n * @example op('<=>', ref('embedding'), cast(param([0.1]), 'vector'))\n * @example op('<=>', 'embedding', [0.1, 0.2]) // implicit conversions\n * @throws Error if operator fails validation (injection guard)\n */\nexport function op(\n\toperator: string,\n\tleft: ExprInput,\n\tright: ExprInput,\n): ExpressionRef {\n\tif (!operator || !OPERATOR_PATTERN.test(operator)) {\n\t\tthrow new Error(`Invalid operator: ${operator}`);\n\t}\n\treturn new ExpressionRef({\n\t\tkind: 'customOp',\n\t\toperator,\n\t\tleft: toExpressionIntent(left),\n\t\tright: toExpressionIntent(right),\n\t} satisfies CustomOpExpressionIntent);\n}\n\n/**\n * Custom function call — name(args...).\n * Supports schema-qualified names (e.g., 'paradedb.score', 'ST_Distance').\n * Implicit conversions: string → ref(), number/boolean/array → param().\n *\n * @example fn('now') → now()\n * @example fn('paradedb.score', ref('id')) → paradedb.score(\"id\")\n * @throws Error if name fails validation (injection guard)\n */\n/**\n * Custom function call — name(args...).\n * Supports schema-qualified names (e.g., 'paradedb.score', 'ST_Distance').\n * Implicit conversions: string → ref(), number/boolean/array → param().\n *\n * Pass `aggOrderBy('col', 'asc')` args to add ORDER BY inside aggregates:\n * `fn('array_agg', ref('name'), aggOrderBy('path'))` → array_agg(\"name\" ORDER BY \"path\" ASC)\n *\n * @example fn('now') → now()\n * @example fn('paradedb.score', ref('id')) → paradedb.score(\"id\")\n * @example fn('array_agg', ref('name'), aggOrderBy('path')) → array_agg(\"name\" ORDER BY \"path\" ASC)\n * @throws Error if name fails validation (injection guard)\n */\nexport function fn(name: string, ...args: ExprInput[]): ExpressionRef {\n\tif (!name || !FUNCTION_NAME_PATTERN.test(name)) {\n\t\tthrow new Error(`Invalid function name: ${name}`);\n\t}\n\tconst regularArgs: ExpressionIntent[] = [];\n\tconst orderByArgs: AggOrderByArg[] = [];\n\tfor (const arg of args) {\n\t\tif (isAggOrderByArg(arg)) {\n\t\t\torderByArgs.push(arg);\n\t\t} else {\n\t\t\tregularArgs.push(toExpressionIntent(arg));\n\t\t}\n\t}\n\tconst intent: CustomFnExpressionIntent = {\n\t\tkind: 'customFn',\n\t\tname,\n\t\targs: regularArgs,\n\t\t...(orderByArgs.length > 0 ? { aggOrderBy: orderByArgs } : {}),\n\t};\n\treturn new ExpressionRef(intent);\n}\n\n/**\n * Literal value — inlined directly in SQL (not bound as parameter).\n * Use to distinguish SQL string literals from column references.\n *\n * | Call | SQL |\n * |------|-----|\n * | `literal(42)` | `42` (inline integer) |\n * | `literal('text')` | `'text'` (SQL string literal) |\n * | `literal(null)` | `NULL` |\n *\n * @example literal(1) → 1 (for: 1 - (col <=> vec))\n */\nexport function literal(\n\tvalue: string | number | boolean | null,\n): ExpressionRef {\n\treturn new ExpressionRef({\n\t\tkind: 'literal',\n\t\tvalue,\n\t} satisfies LiteralExpressionIntent);\n}\n\n/**\n * Unary operator — OP expr (prefix form).\n *\n * @example unary('NOT', ref('active')) → NOT \"active\"\n * @example unary('-', ref('score')) → -\"score\"\n * @throws Error if operator fails validation (injection guard)\n */\nexport function unary(operator: string, expr: ExprInput): ExpressionRef {\n\tif (!operator || !OPERATOR_PATTERN.test(operator)) {\n\t\tthrow new Error(`Invalid operator: ${operator}`);\n\t}\n\treturn new ExpressionRef({\n\t\tkind: 'unary',\n\t\toperator,\n\t\toperand: toExpressionIntent(expr),\n\t} satisfies UnaryExpressionIntent);\n}\n\n/**\n * Named argument for function calls: name => value.\n * Use inside fn() args to produce PostgreSQL named-argument syntax.\n *\n * @example namedArg('field', literal('name_searchable'))\n * → field => 'name_searchable'\n * @example namedArg('query_string', param('hello'))\n * → query_string => $1\n */\nexport function namedArg(name: string, value: ExprInput): ExpressionRef {\n\tif (!name || !FUNCTION_NAME_PATTERN.test(name)) {\n\t\tthrow new Error(`namedArg: invalid argument name: ${name}`);\n\t}\n\treturn new ExpressionRef({\n\t\tkind: 'namedArg',\n\t\tname,\n\t\tvalue: toExpressionIntent(value),\n\t} satisfies NamedArgExpressionIntent);\n}\n\n/** SQL wildcard (*) — use in fn('count', star()) for COUNT(*) */\nexport function star(): ExpressionRef {\n\treturn new ExpressionRef({ kind: 'star' } satisfies StarExpressionIntent);\n}\n\n/**\n * PostgreSQL ARRAY constructor: ARRAY[item1, item2, ...]\n *\n * @example array(literal(1), literal(2), literal(3)) → ARRAY[1, 2, 3]\n * @example array(ref('name'), ref('kind')) → ARRAY[\"name\", \"kind\"]\n */\nexport function array(...items: ExprInput[]): ExpressionRef {\n\treturn new ExpressionRef({\n\t\tkind: 'array',\n\t\telements: items.map(toExpressionIntent),\n\t} satisfies ArrayExpressionIntent);\n}\n\n// ============================================================================\n// Aggregate ORDER BY helpers (FR-9)\n// ============================================================================\n\n/**\n * Type guard for AggOrderByArg — distinguishes aggregate ORDER BY markers\n * from regular ExprInput values inside fn() argument lists.\n */\nfunction isAggOrderByArg(input: ExprInput): input is AggOrderByArg {\n\treturn (\n\t\ttypeof input === 'object' &&\n\t\tinput !== null &&\n\t\t!Array.isArray(input) &&\n\t\t!(input instanceof ExpressionRef) &&\n\t\t'__aggOrderBy' in input &&\n\t\t(input as AggOrderByArg).__aggOrderBy === true\n\t);\n}\n\n/**\n * Creates an ORDER BY marker for use as an argument to `fn()`.\n * When passed to `fn()`, the compiler places it in the aggregate's\n * ORDER BY clause instead of in the regular argument list.\n *\n * @example fn('array_agg', ref('name'), aggOrderBy('path')) → array_agg(\"name\" ORDER BY \"path\" ASC)\n * @example fn('array_agg', ref('name'), aggOrderBy('path', 'desc')) → array_agg(\"name\" ORDER BY \"path\" DESC)\n */\nexport function aggOrderBy(\n\tfield: string,\n\tdirection: 'asc' | 'desc' = 'asc',\n): AggOrderByArg {\n\treturn { __aggOrderBy: true, field, direction };\n}\n\n/**\n * Shorthand for `fn('array_agg', col, ...orderByArgs)`.\n *\n * @example arrayAgg(ref('name')) → array_agg(\"name\")\n * @example arrayAgg(ref('name'), aggOrderBy('path')) → array_agg(\"name\" ORDER BY \"path\" ASC)\n * @example arrayAgg('name', aggOrderBy('path', 'desc')) → array_agg(\"name\" ORDER BY \"path\" DESC)\n */\nexport function arrayAgg(\n\tcol: ExpressionRef | string,\n\t...rest: AggOrderByArg[]\n): ExpressionRef {\n\tconst colExpr = typeof col === 'string' ? ref(col) : col;\n\treturn fn('array_agg', colExpr, ...rest);\n}\n\n/**\n * Shorthand for `fn('string_agg', col, separator, ...orderByArgs)`.\n *\n * @example stringAgg(ref('name'), literal(',')) → string_agg(\"name\", ',')\n * @example stringAgg(ref('name'), literal(','), aggOrderBy('name')) → string_agg(\"name\", ',' ORDER BY \"name\" ASC)\n */\nexport function stringAgg(\n\tcol: ExpressionRef | string,\n\tseparator: ExpressionRef,\n\t...rest: AggOrderByArg[]\n): ExpressionRef {\n\tconst colExpr = typeof col === 'string' ? ref(col) : col;\n\treturn fn('string_agg', colExpr, separator, ...rest);\n}\n","import type {\n\tCaseExpressionIntent,\n\tExpressionIntent,\n\tWhereIntent,\n} from '@dbsp/types';\nimport { ExpressionRef } from './expressions.js';\n\nfunction toResultIntent(\n\tvalue: ExpressionRef | string | number | boolean | null | undefined,\n): ExpressionIntent {\n\tif (value instanceof ExpressionRef) {\n\t\treturn value.intent;\n\t}\n\tif (value === null || value === undefined) {\n\t\treturn { kind: 'literal', value: null } satisfies ExpressionIntent;\n\t}\n\tif (typeof value === 'string') {\n\t\treturn { kind: 'ref', column: value } satisfies ExpressionIntent;\n\t}\n\treturn { kind: 'literal', value } satisfies ExpressionIntent;\n}\n\nexport type CaseValue = ExpressionRef | string | number | boolean | null;\n\nexport class CaseBuilder {\n\tprivate readonly branches: ReadonlyArray<{\n\t\treadonly condition: WhereIntent;\n\t\treadonly result: ExpressionIntent;\n\t}>;\n\n\tconstructor(\n\t\tbranches: ReadonlyArray<{\n\t\t\treadonly condition: WhereIntent;\n\t\t\treadonly result: ExpressionIntent;\n\t\t}>,\n\t) {\n\t\tthis.branches = branches;\n\t}\n\n\twhen(condition: WhereIntent, thenValue: CaseValue): CaseBuilder {\n\t\treturn new CaseBuilder([\n\t\t\t...this.branches,\n\t\t\t{ condition, result: toResultIntent(thenValue) },\n\t\t]);\n\t}\n\n\telse(elseValue: CaseValue): ExpressionRef {\n\t\tconst intent: CaseExpressionIntent = {\n\t\t\tkind: 'case',\n\t\t\twhen: this.branches,\n\t\t\telse: toResultIntent(elseValue),\n\t\t};\n\t\treturn new ExpressionRef(intent as ExpressionIntent);\n\t}\n\n\tas(alias: string): ExpressionRef {\n\t\treturn this.toExpr().as(alias);\n\t}\n\n\ttoExpr(): ExpressionRef {\n\t\tconst intent: CaseExpressionIntent = {\n\t\t\tkind: 'case',\n\t\t\twhen: this.branches,\n\t\t};\n\t\treturn new ExpressionRef(intent as ExpressionIntent);\n\t}\n}\n\nexport function caseWhen(\n\tcondition: WhereIntent,\n\tthenValue: CaseValue,\n): CaseBuilder {\n\treturn new CaseBuilder([{ condition, result: toResultIntent(thenValue) }]);\n}\n","/**\n * Shared builder utilities for CTE and recursive query builders.\n */\n\nimport type { Adapter } from '@dbsp/types';\nimport { InvalidOperationError } from './errors.js';\n\n/**\n * Asserts that an adapter is present, throwing a descriptive error if not.\n *\n * @param adapter - The adapter instance (may be undefined)\n * @param operationName - The public API operation name, used in the error message\n * @returns The validated adapter\n */\nexport function requireAdapter(\n\tadapter: Adapter | undefined,\n\toperationName: string,\n): Adapter {\n\tif (!adapter) {\n\t\tthrow new InvalidOperationError(\n\t\t\toperationName,\n\t\t\t'This operation requires an adapter \\u2014 pass an adapter when creating the ORM',\n\t\t);\n\t}\n\treturn adapter;\n}\n","/**\n * CTE builder with unnest() support (BATCH-001 Block 5).\n *\n * Provides a fluent API for building CTE queries backed by unnest() arrays,\n * optionally with WITH ORDINALITY for 0-based indexing.\n *\n * @example\n * ```typescript\n * const result = orm.withCte('lookups')\n * .fromUnnest({ parent_file_id: [1, 2, 3], parent_name: ['Foo', 'Bar', 'Baz'] })\n * .withIndex('idx')\n * .query(orm.select('symbols'))\n * .dump();\n * ```\n */\n\nimport type {\n\tAdapter,\n\tCompiledQuery,\n\tCteQueryIntent,\n\tUnnestCteIntent,\n} from '@dbsp/types';\nimport { requireAdapter as requireAdapterUtil } from './builder-utils.js';\nimport { InvalidOperationError } from './errors.js';\nimport type { QueryBuilderImpl } from './query-builder.js';\nimport type { QueryBuilder } from './query-builder-types.js';\n\n// ============================================================================\n// CteBuilder\n// ============================================================================\n\n/**\n * Fluent builder for constructing a CTE definition backed by unnest() arrays.\n *\n * Obtain via `orm.withCte(name)`.\n */\nexport class CteBuilder {\n\tprivate readonly cteName: string;\n\tprivate readonly adapter: Adapter | undefined;\n\tprivate readonly schemaName: string | undefined;\n\tprivate unnestColumns: Record<string, readonly unknown[]> | undefined;\n\tprivate indexColumnName: string | undefined;\n\n\tconstructor(name: string, adapter?: Adapter, schemaName?: string) {\n\t\tthis.cteName = name;\n\t\tthis.adapter = adapter;\n\t\tthis.schemaName = schemaName;\n\t}\n\n\t/**\n\t * Provide the column arrays for the unnest() CTE.\n\t * All arrays must have the same length.\n\t *\n\t * @param columns - A record of column name → array of values.\n\t */\n\tfromUnnest(columns: Record<string, readonly unknown[]>): this {\n\t\tconst lengths = Object.values(columns).map((arr) => arr.length);\n\t\tif (lengths.length > 1 && !lengths.every((l) => l === lengths[0])) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'withCte',\n\t\t\t\t`Array length mismatch in CTE unnest columns: lengths are [${lengths.join(', ')}]`,\n\t\t\t);\n\t\t}\n\t\tthis.unnestColumns = columns;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add a 0-based ordinality index column (uses WITH ORDINALITY).\n\t *\n\t * @param columnName - The name of the index column in the CTE.\n\t */\n\twithIndex(columnName: string): this {\n\t\tthis.indexColumnName = columnName;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Attach an outer query and produce a CteQueryBuilder for execution.\n\t *\n\t * @param selectBuilder - A QueryBuilder (from orm.select(...))\n\t */\n\tquery<TResult = unknown>(\n\t\tselectBuilder: QueryBuilder<TResult>,\n\t): CteQueryBuilder<TResult> {\n\t\tif (!this.unnestColumns) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'withCte',\n\t\t\t\t'CTE requires a data source — call .fromUnnest() first',\n\t\t\t);\n\t\t}\n\n\t\tconst cteIntent: UnnestCteIntent = {\n\t\t\tkind: 'unnestCte',\n\t\t\tname: this.cteName,\n\t\t\tcolumns: this.unnestColumns,\n\t\t\t...(this.indexColumnName !== undefined && {\n\t\t\t\tindexColumn: this.indexColumnName,\n\t\t\t}),\n\t\t};\n\n\t\treturn new CteQueryBuilder<TResult>(\n\t\t\tcteIntent,\n\t\t\tselectBuilder as QueryBuilderImpl<TResult>,\n\t\t\tthis.adapter,\n\t\t\tthis.schemaName,\n\t\t);\n\t}\n}\n\n// ============================================================================\n// CteQueryBuilder\n// ============================================================================\n\n/**\n * Result of compiling a CTE query.\n */\nexport interface CteDump {\n\treadonly sql: string;\n\treadonly params: readonly unknown[];\n\treadonly intent: CteQueryIntent;\n}\n\n/**\n * Fluent builder for executing a WITH ... SELECT query.\n *\n * Produced by `CteBuilder.query()`.\n */\nexport class CteQueryBuilder<TResult = unknown> {\n\tprivate readonly cteIntent: UnnestCteIntent;\n\tprivate readonly outerBuilder: QueryBuilderImpl<TResult>;\n\tprivate readonly adapter: Adapter | undefined;\n\tprivate readonly schemaName: string | undefined;\n\n\tconstructor(\n\t\tcteIntent: UnnestCteIntent,\n\t\touterBuilder: QueryBuilderImpl<TResult>,\n\t\tadapter?: Adapter,\n\t\tschemaName?: string,\n\t) {\n\t\tthis.cteIntent = cteIntent;\n\t\tthis.outerBuilder = outerBuilder;\n\t\tthis.adapter = adapter;\n\t\tthis.schemaName = schemaName;\n\t}\n\n\t/**\n\t * Build the CteQueryIntent AST.\n\t */\n\tbuildIntent(): CteQueryIntent {\n\t\tconst queryIntent = this.outerBuilder.buildIntent();\n\t\treturn {\n\t\t\tkind: 'cteQuery',\n\t\t\tctes: [this.cteIntent],\n\t\t\tquery: queryIntent,\n\t\t};\n\t}\n\n\tprivate requireAdapter(): Adapter {\n\t\treturn requireAdapterUtil(this.adapter, 'withCte');\n\t}\n\n\t/**\n\t * Compile to SQL and return an observability dump.\n\t */\n\tdump(): CteDump {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions = this.schemaName\n\t\t\t? { schemaName: this.schemaName }\n\t\t\t: undefined;\n\n\t\tconst compiled: CompiledQuery = adapter.compileCteQuery(\n\t\t\tintent,\n\t\t\tcompileOptions,\n\t\t);\n\n\t\treturn {\n\t\t\tsql: compiled.sql,\n\t\t\tparams: compiled.parameters,\n\t\t\tintent,\n\t\t};\n\t}\n\n\t/**\n\t * Execute the CTE query and return all results.\n\t */\n\tasync all(): Promise<TResult[]> {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions = this.schemaName\n\t\t\t? { schemaName: this.schemaName }\n\t\t\t: undefined;\n\n\t\tconst compiled = adapter.compileCteQuery(\n\t\t\tintent,\n\t\t\tcompileOptions,\n\t\t) as CompiledQuery<TResult>;\n\n\t\treturn adapter.execute(compiled);\n\t}\n\n\t/**\n\t * Alias for all().\n\t */\n\texecute(): Promise<TResult[]> {\n\t\treturn this.all();\n\t}\n}\n","import type { DDLFeature, DialectCapabilities, ModelIR } from '@dbsp/types';\n\n// ---------------------------------------------------------------------------\n// FeatureChecker interface (OCP-001: Open/Closed for feature negotiation)\n// ---------------------------------------------------------------------------\n\n/**\n * Restricted key type: only keys of DialectCapabilities whose value is boolean\n * (or optional boolean). Prevents custom checkers from targeting non-boolean\n * fields (name, recursivePathStyle, identifierQuote, etc.) where a truthy\n * guard would silently break at runtime.\n */\nexport type DialectCapabilityFlag = Extract<\n\t{\n\t\t[K in keyof DialectCapabilities]: NonNullable<\n\t\t\tDialectCapabilities[K]\n\t\t> extends boolean\n\t\t\t? K\n\t\t\t: never;\n\t}[keyof DialectCapabilities],\n\tstring\n>;\n\n/**\n * A self-contained checker for a single DDL feature.\n * Add a new feature by appending a FeatureChecker to DEFAULT_FEATURE_CHECKERS\n * -- no edits to negotiateFeatures() required.\n *\n * Note: when multiple checkers target the same `capability`, all run in array\n * order and each can emit warnings/errors. Deduplication by capability is the\n * caller's responsibility.\n */\nexport interface FeatureChecker {\n\t/** Capability flag key — restricted to boolean-valued fields of DialectCapabilities. */\n\treadonly capability: DialectCapabilityFlag;\n\t/** DDLFeature name used in warn/error messages and behavior lookup. */\n\treadonly feature: DDLFeature;\n\t/**\n\t * Walk the ModelIR and return locations where this feature is used.\n\t * Return empty array if the feature is not used anywhere.\n\t */\n\tdetectUsage(model: ModelIR): readonly FeatureUsage[];\n}\n\n/** Location descriptor returned by FeatureChecker.detectUsage(). */\nexport interface FeatureUsage {\n\treadonly table?: string;\n\treadonly column?: string;\n\t/** Human-readable element label used in warn/error messages. */\n\treadonly detail: string;\n}\n\n// ---------------------------------------------------------------------------\n// Default registry -- one entry per supportsDDL* capability flag\n// ---------------------------------------------------------------------------\n\n/**\n * Default feature checkers -- mirrors the 16 supportsDDL* flags that\n * negotiateFeatures() previously checked inline.\n *\n * Each checker preserves exactly the same detection logic (same guards,\n * same element label format) that was previously inlined in negotiateFeatures().\n */\nexport const DEFAULT_FEATURE_CHECKERS: readonly FeatureChecker[] =\n\tObject.freeze<readonly FeatureChecker[]>([\n\t\t// -----------------------------------------------------------------------\n\t\t// Schema-level features\n\t\t// -----------------------------------------------------------------------\n\t\t{\n\t\t\tcapability: 'supportsDDLEnumTypes',\n\t\t\tfeature: 'enum',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.enums?.size) return [];\n\t\t\t\treturn [...model.enums.keys()].map((name) => ({ detail: name }));\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLSequences',\n\t\t\tfeature: 'sequence',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.sequences?.size) return [];\n\t\t\t\treturn [...model.sequences.keys()].map((name) => ({ detail: name }));\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLExtensions',\n\t\t\tfeature: 'extension',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.extensions?.length) return [];\n\t\t\t\treturn model.extensions.map((ext) => ({ detail: ext }));\n\t\t\t},\n\t\t},\n\n\t\t// -----------------------------------------------------------------------\n\t\t// Table-level features\n\t\t// -----------------------------------------------------------------------\n\t\t{\n\t\t\tcapability: 'supportsDDLPartitioning',\n\t\t\tfeature: 'partition',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tif (table.partition) {\n\t\t\t\t\t\tusages.push({ table: tableName, detail: tableName });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLComments',\n\t\t\tfeature: 'comment',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tif (table.comment) {\n\t\t\t\t\t\tusages.push({ table: tableName, detail: `${tableName} (table)` });\n\t\t\t\t\t}\n\t\t\t\t\tfor (const col of table.columns) {\n\t\t\t\t\t\tif (col.comment) {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tcolumn: col.name,\n\t\t\t\t\t\t\t\tdetail: `${tableName}.${col.name} (column)`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLCheckConstraints',\n\t\t\tfeature: 'checkConstraint',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tif (table.checkConstraints?.length) {\n\t\t\t\t\t\tfor (const chk of table.checkConstraints) {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tdetail: `${tableName}.${chk.name}`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLOnUpdateFK',\n\t\t\tfeature: 'onUpdateFK',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const fk of table.foreignKeys) {\n\t\t\t\t\t\tif (fk.onUpdate && fk.onUpdate !== 'NO ACTION') {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tdetail: `${tableName} FK → ${fk.references.table}`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLDeferredFK',\n\t\t\tfeature: 'deferredFK',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const fk of table.foreignKeys) {\n\t\t\t\t\t\tif (fk.deferred) {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tdetail: `${tableName} FK → ${fk.references.table}`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\n\t\t// -----------------------------------------------------------------------\n\t\t// Column-level features\n\t\t// -----------------------------------------------------------------------\n\t\t{\n\t\t\tcapability: 'supportsDDLIdentityColumns',\n\t\t\tfeature: 'identity',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const col of table.columns) {\n\t\t\t\t\t\tif (col.identity) {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tcolumn: col.name,\n\t\t\t\t\t\t\t\tdetail: `${tableName}.${col.name}`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLCollation',\n\t\t\tfeature: 'collation',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const col of table.columns) {\n\t\t\t\t\t\tif (col.collation) {\n\t\t\t\t\t\t\tusages.push({\n\t\t\t\t\t\t\t\ttable: tableName,\n\t\t\t\t\t\t\t\tcolumn: col.name,\n\t\t\t\t\t\t\t\tdetail: `${tableName}.${col.name}`,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\n\t\t// -----------------------------------------------------------------------\n\t\t// Index-level features\n\t\t// -----------------------------------------------------------------------\n\t\t{\n\t\t\tcapability: 'supportsDDLIndexMethods',\n\t\t\tfeature: 'indexMethod',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const idx of table.indexes) {\n\t\t\t\t\t\tif (idx.method && idx.method !== 'btree') {\n\t\t\t\t\t\t\tconst idxName = idx.name ?? `idx on ${tableName}`;\n\t\t\t\t\t\t\tusages.push({ table: tableName, detail: idxName });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLIndexOpclass',\n\t\t\tfeature: 'indexOpclass',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const idx of table.indexes) {\n\t\t\t\t\t\tif (idx.opclass && Object.keys(idx.opclass).length > 0) {\n\t\t\t\t\t\t\tconst idxName = idx.name ?? `idx on ${tableName}`;\n\t\t\t\t\t\t\tusages.push({ table: tableName, detail: idxName });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLIndexInclude',\n\t\t\tfeature: 'indexInclude',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const idx of table.indexes) {\n\t\t\t\t\t\tif (idx.include?.length) {\n\t\t\t\t\t\t\tconst idxName = idx.name ?? `idx on ${tableName}`;\n\t\t\t\t\t\t\tusages.push({ table: tableName, detail: idxName });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLPartialIndexes',\n\t\t\tfeature: 'partialIndex',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const idx of table.indexes) {\n\t\t\t\t\t\tif (idx.where) {\n\t\t\t\t\t\t\tconst idxName = idx.name ?? `idx on ${tableName}`;\n\t\t\t\t\t\t\tusages.push({ table: tableName, detail: idxName });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tcapability: 'supportsDDLExpressionIndexes',\n\t\t\tfeature: 'expressionIndex',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tfor (const idx of table.indexes) {\n\t\t\t\t\t\tif (idx.expressions?.length) {\n\t\t\t\t\t\t\tconst idxName = idx.name ?? `idx on ${tableName}`;\n\t\t\t\t\t\t\tusages.push({ table: tableName, detail: idxName });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\n\t\t// -----------------------------------------------------------------------\n\t\t// Row-Level Security\n\t\t// -----------------------------------------------------------------------\n\t\t{\n\t\t\tcapability: 'supportsDDLRowLevelSecurity',\n\t\t\tfeature: 'rowLevelSecurity',\n\t\t\tdetectUsage(model) {\n\t\t\t\tif (!model.tables) return [];\n\t\t\t\tconst usages: FeatureUsage[] = [];\n\t\t\t\tfor (const [tableName, table] of model.tables) {\n\t\t\t\t\tif (table.rlsEnabled || table.policies?.length) {\n\t\t\t\t\t\tusages.push({ table: tableName, detail: tableName });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn usages;\n\t\t\t},\n\t\t},\n\t]);\n","import { COLUMN_META } from './symbols.js';\nimport type { ColumnRef } from './table-ref.js';\n\n/**\n * Extract the column name from a ColumnRef or string.\n * @internal Shared helper — used by filters, functions, window-functions, typed-query-builder.\n */\nexport function getColumnName(\n\tfield: ColumnRef<string, string, unknown> | string,\n): string {\n\tif (typeof field === 'string') {\n\t\treturn field;\n\t}\n\tconst colName = field[COLUMN_META];\n\tif (colName === undefined) {\n\t\tthrow new Error('Invalid ColumnRef: missing COLUMN_META');\n\t}\n\treturn colName;\n}\n","/**\n * @module window-functions\n * Fluent builders for SQL window functions (ROW_NUMBER, RANK, SUM OVER, etc.).\n *\n * Extracted from filters.ts for SRP (Audit #19).\n *\n * @example\n * ```typescript\n * import { rowNumber, wSum, rank } from '@dbsp/core';\n *\n * // Ranking\n * rowNumber().orderBy('created_at', 'desc').as('rn')\n *\n * // Running total with partition\n * wSum('amount').partitionBy('user_id').orderBy('date').as('running_total')\n * ```\n */\n\nimport type { Mutable } from '@dbsp/types/internal';\nimport type {\n\tAggregateWindowIntent,\n\tOffsetWindowIntent,\n\tRankingWindowIntent,\n\tWindowIntent,\n} from '../intent-ast.js';\nimport { getColumnName } from './column-utils.js';\nimport type { ColumnRef } from './table-ref.js';\nimport type { ExpressionSpec } from './types.js';\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\n// ============================================================================\n// WindowBuilder\n// ============================================================================\n\n/**\n * Internal state for WindowBuilder.\n * Distinguishes between ranking (no field), aggregate (requires field), and offset (requires field).\n */\ntype WindowFunctionKind =\n\t| { type: 'ranking'; fn: 'row_number' | 'rank' | 'dense_rank' }\n\t| {\n\t\t\ttype: 'aggregate';\n\t\t\tfn: 'sum' | 'avg' | 'count' | 'min' | 'max';\n\t\t\tfield?: string;\n\t }\n\t| { type: 'offset'; fn: 'lag' | 'lead'; field: string };\n\n/**\n * Fluent builder for window functions.\n *\n * Create via factory functions: rowNumber(), rank(), sum(field), etc.\n * Chain with .partitionBy(), .orderBy(), then finalize with .as(alias).\n *\n * @example\n * ```typescript\n * // Ranking\n * rowNumber().orderBy('created_at', 'desc').as('rn')\n *\n * // Aggregate with partition\n * sum('amount').partitionBy('user_id').orderBy('date').as('running_total')\n *\n * // Multiple partition/order fields (chaining appends)\n * rank().partitionBy('dept').partitionBy('team').orderBy('salary', 'desc').as('rank')\n * ```\n */\nexport class WindowBuilder {\n\tprivate constructor(\n\t\tprivate readonly fnKind: WindowFunctionKind,\n\t\tprivate readonly partitions: readonly string[] = [],\n\t\tprivate readonly orders: readonly {\n\t\t\tfield: string;\n\t\t\tdirection: 'asc' | 'desc';\n\t\t}[] = [],\n\t) {}\n\n\t/**\n\t * Create a ranking window builder (row_number, rank, dense_rank)\n\t * @internal Use factory functions instead: rowNumber(), rank(), denseRank()\n\t */\n\tstatic ranking(fn: 'row_number' | 'rank' | 'dense_rank'): WindowBuilder {\n\t\treturn new WindowBuilder({ type: 'ranking', fn });\n\t}\n\n\t/**\n\t * Create an aggregate window builder (sum, avg, count, min, max)\n\t * @internal Use factory functions instead: sum(field), avg(field), etc.\n\t */\n\tstatic aggregate(\n\t\tfn: 'sum' | 'avg' | 'count' | 'min' | 'max',\n\t\tfield?: string,\n\t): WindowBuilder {\n\t\treturn new WindowBuilder({\n\t\t\ttype: 'aggregate',\n\t\t\tfn,\n\t\t\t...(field !== undefined ? { field } : {}),\n\t\t});\n\t}\n\n\t/**\n\t * Create an offset window builder (lag, lead)\n\t * @internal Use factory functions instead: lag(field), lead(field)\n\t */\n\tstatic offset(fn: 'lag' | 'lead', field: string): WindowBuilder {\n\t\treturn new WindowBuilder({ type: 'offset', fn, field });\n\t}\n\n\t/**\n\t * Add partition field(s) to the OVER clause.\n\t * Multiple calls APPEND fields (not replace).\n\t * Supports both string field names and ColumnRef (DX-040).\n\t *\n\t * @example\n\t * sum('amount').partitionBy('user_id').partitionBy('category')\n\t * // → PARTITION BY \"user_id\", \"category\"\n\t *\n\t * @example DX-040 with ColumnRef\n\t * rank().partitionBy(users.dept).orderBy(users.salary, 'desc')\n\t */\n\tpartitionBy(\n\t\t...fields: (string | ColumnRef<string, string, unknown>)[]\n\t): WindowBuilder {\n\t\tconst fieldNames = fields.map((f) =>\n\t\t\ttypeof f === 'string' ? f : getColumnName(f),\n\t\t);\n\t\treturn new WindowBuilder(\n\t\t\tthis.fnKind,\n\t\t\t[...this.partitions, ...fieldNames],\n\t\t\tthis.orders,\n\t\t);\n\t}\n\n\t/**\n\t * Add order field to the OVER clause.\n\t * Multiple calls APPEND fields (not replace).\n\t * Supports both string field names and ColumnRef (DX-040).\n\t *\n\t * @param field - Column name or ColumnRef to order by\n\t * @param direction - Sort direction: 'asc' (default) or 'desc'\n\t *\n\t * @example\n\t * rowNumber().orderBy('created_at').orderBy('id', 'desc')\n\t * // → ORDER BY \"created_at\" ASC, \"id\" DESC\n\t *\n\t * @example DX-040 with ColumnRef\n\t * rank().partitionBy(users.dept).orderBy(users.salary, 'desc')\n\t */\n\torderBy(\n\t\tfield: string | ColumnRef<string, string, unknown>,\n\t\tdirection: 'asc' | 'desc' = 'asc',\n\t): WindowBuilder {\n\t\tconst fieldName = typeof field === 'string' ? field : getColumnName(field);\n\t\treturn new WindowBuilder(this.fnKind, this.partitions, [\n\t\t\t...this.orders,\n\t\t\t{ field: fieldName, direction },\n\t\t]);\n\t}\n\n\t/**\n\t * Finalize the window expression with an alias.\n\t * Returns ExpressionSpec for use in columns().\n\t *\n\t * @param alias - Required alias for the result column\n\t *\n\t * @example\n\t * columns(['id', rowNumber().orderBy('date').as('rn')])\n\t */\n\tas(alias: string): ExpressionSpec {\n\t\treturn {\n\t\t\t__expr: true,\n\t\t\tintent: this.toWindowIntent(alias),\n\t\t};\n\t}\n\n\t/**\n\t * Convert builder state to WindowIntent — produces the correct discriminated branch.\n\t * - ranking → RankingWindowIntent (no field)\n\t * - aggregate → AggregateWindowIntent (field required; COUNT uses '*' when omitted)\n\t * - offset → OffsetWindowIntent (field required)\n\t */\n\tprivate toWindowIntent(alias: string): WindowIntent {\n\t\tconst over: Mutable<RankingWindowIntent['over']> = {};\n\t\tif (this.partitions.length > 0) {\n\t\t\tover.partitionBy = this.partitions;\n\t\t}\n\t\tif (this.orders.length > 0) {\n\t\t\tover.orderBy = this.orders;\n\t\t}\n\n\t\tif (this.fnKind.type === 'ranking') {\n\t\t\treturn {\n\t\t\t\tkind: 'window',\n\t\t\t\tfunction: this.fnKind.fn,\n\t\t\t\talias,\n\t\t\t\tover,\n\t\t\t} satisfies RankingWindowIntent;\n\t\t}\n\n\t\tif (this.fnKind.type === 'offset') {\n\t\t\treturn {\n\t\t\t\tkind: 'window',\n\t\t\t\tfunction: this.fnKind.fn,\n\t\t\t\tfield: this.fnKind.field,\n\t\t\t\talias,\n\t\t\t\tover,\n\t\t\t} satisfies OffsetWindowIntent;\n\t\t}\n\n\t\t// aggregate — COUNT(*) omits field (undefined); sum/avg/min/max always have a field\n\t\tconst { field } = this.fnKind;\n\t\treturn {\n\t\t\tkind: 'window',\n\t\t\tfunction: this.fnKind.fn,\n\t\t\t...(field !== undefined && { field }),\n\t\t\talias,\n\t\t\tover,\n\t\t} satisfies AggregateWindowIntent;\n\t}\n}\n\n// ============================================================================\n// Window Function Factory Functions\n// ============================================================================\n\n/**\n * ROW_NUMBER window function: sequential row number within partition\n *\n * @example\n * rowNumber().orderBy('created_at', 'desc').as('rn')\n * // → ROW_NUMBER() OVER (ORDER BY \"created_at\" DESC) AS \"rn\"\n */\nexport function rowNumber(): WindowBuilder {\n\treturn WindowBuilder.ranking('row_number');\n}\n\n/**\n * RANK window function: rank with gaps for ties\n *\n * @example\n * rank().partitionBy('category').orderBy('price').as('price_rank')\n * // → RANK() OVER (PARTITION BY \"category\" ORDER BY \"price\" ASC) AS \"price_rank\"\n */\nexport function rank(): WindowBuilder {\n\treturn WindowBuilder.ranking('rank');\n}\n\n/**\n * DENSE_RANK window function: rank without gaps\n *\n * @example\n * denseRank().partitionBy('dept').orderBy('salary', 'desc').as('salary_rank')\n * // → DENSE_RANK() OVER (PARTITION BY \"dept\" ORDER BY \"salary\" DESC) AS \"salary_rank\"\n */\nexport function denseRank(): WindowBuilder {\n\treturn WindowBuilder.ranking('dense_rank');\n}\n\n/**\n * SUM window function: running/cumulative sum\n *\n * @param field - Field to sum\n *\n * @example\n * wSum('amount').partitionBy('user_id').orderBy('date').as('running_total')\n * // → SUM(\"amount\") OVER (PARTITION BY \"user_id\" ORDER BY \"date\" ASC) AS \"running_total\"\n */\nexport function wSum(field: string): WindowBuilder {\n\treturn WindowBuilder.aggregate('sum', field);\n}\n\n/**\n * AVG window function: running/cumulative average\n *\n * @param field - Field to average\n *\n * @example\n * wAvg('price').partitionBy('category').as('avg_price')\n * // → AVG(\"price\") OVER (PARTITION BY \"category\") AS \"avg_price\"\n */\nexport function wAvg(field: string): WindowBuilder {\n\treturn WindowBuilder.aggregate('avg', field);\n}\n\n/**\n * COUNT window function: count within partition.\n * When called with no argument, produces COUNT(*) OVER (...).\n *\n * @param field - Optional field to count. Omit for COUNT(*).\n *\n * @example COUNT(*) OVER()\n * wCount().over({ partitionBy: ['project_id'] }).as('total')\n * // → COUNT(*) OVER (PARTITION BY \"project_id\") AS \"total\"\n *\n * @example COUNT(field) OVER()\n * wCount('id').partitionBy('category').as('items_in_category')\n * // → COUNT(\"id\") OVER (PARTITION BY \"category\") AS \"items_in_category\"\n */\nexport function wCount(field?: string): WindowBuilder {\n\treturn WindowBuilder.aggregate('count', field);\n}\n\n/**\n * MIN window function: minimum value within partition\n *\n * @param field - Field to find minimum of\n *\n * @example\n * wMin('price').partitionBy('category').as('min_price')\n * // → MIN(\"price\") OVER (PARTITION BY \"category\") AS \"min_price\"\n */\nexport function wMin(field: string): WindowBuilder {\n\treturn WindowBuilder.aggregate('min', field);\n}\n\n/**\n * MAX window function: maximum value within partition\n *\n * @param field - Field to find maximum of\n *\n * @example\n * wMax('price').partitionBy('category').as('max_price')\n * // → MAX(\"price\") OVER (PARTITION BY \"category\") AS \"max_price\"\n */\nexport function wMax(field: string): WindowBuilder {\n\treturn WindowBuilder.aggregate('max', field);\n}\n\n/**\n * LAG window function: access previous row value\n *\n * @param field - Field to access from previous row\n *\n * @example\n * lag('amount').orderBy('date').as('prev_amount')\n * // → LAG(\"amount\") OVER (ORDER BY \"date\" ASC) AS \"prev_amount\"\n */\nexport function lag(field: string): WindowBuilder {\n\treturn WindowBuilder.offset('lag', field);\n}\n\n/**\n * LEAD window function: access next row value\n *\n * @param field - Field to access from next row\n *\n * @example\n * lead('amount').orderBy('date').as('next_amount')\n * // → LEAD(\"amount\") OVER (ORDER BY \"date\" ASC) AS \"next_amount\"\n */\nexport function lead(field: string): WindowBuilder {\n\treturn WindowBuilder.offset('lead', field);\n}\n","/**\n * @module filters\n * Drizzle-like filter helpers for ergonomic WHERE clause building.\n *\n * These are pure factory functions that return WhereIntent objects.\n * They can be composed with and(), or(), not() for complex conditions.\n *\n * @example\n * ```typescript\n * import { eq, and, gt, like } from '@dbsp/core';\n *\n * // Simple equality\n * orm.select('users').where(eq('status', 'active'))\n *\n * // Combined conditions\n * orm.select('users').where(\n * and(\n * eq('status', 'active'),\n * gt('age', 18),\n * like('email', '%@example.com')\n * )\n * )\n * ```\n */\n\nimport type { Mutable } from '@dbsp/types/internal';\nimport type {\n\tComparisonOperator,\n\tQueryIntent,\n\tRecursiveExistsOptions,\n\tWhereAndIntent,\n\tWhereAnyIntent,\n\tWhereComparisonIntent,\n\tWhereExistsIntent,\n\tWhereInIntent,\n\tWhereIntent,\n\tWhereLikeIntent,\n\tWhereNotExistsIntent,\n\tWhereNotIntent,\n\tWhereNullIntent,\n\tWhereOrIntent,\n\tWhereRangeIntent,\n\tWhereRawExistsIntent,\n\tWhereRawNotExistsIntent,\n\tWhereRelationFilterIntent,\n} from '../intent-ast.js';\nimport { getColumnName } from './column-utils.js';\nimport { validateIdentifier } from './errors.js';\nimport type {\n\tSubqueryBuilder,\n\tSubqueryExpression,\n} from './subquery-builder.js';\nimport {\n\ttype ColumnRef,\n\tRELATION_META,\n\ttype RelationRef,\n} from './table-ref.js';\nimport type { AliasedExprColumn, ExpressionSpec } from './types.js';\n\n// ============================================================================\n// Type-Safe Column Reference Support (DX-040)\n// ============================================================================\n\n// ============================================================================\n// Distinct Field Helper (for aggregates)\n// ============================================================================\n\n/**\n * Represents a field with DISTINCT modifier for aggregate functions.\n *\n * @example\n * ```typescript\n * count(distinct('customerId')) // COUNT(DISTINCT customerId)\n * sum(distinct('amount'), 'uniqueSum') // SUM(DISTINCT amount) AS uniqueSum\n * ```\n */\nexport interface DistinctField {\n\treadonly field: string;\n\treadonly distinct: true;\n}\n\n/**\n * Helper to mark a field as DISTINCT for aggregate functions.\n *\n * @param field - The field name to apply DISTINCT to\n * @returns A DistinctField object that can be passed to aggregate functions\n *\n * @example\n * ```typescript\n * import { distinct } from '@dbsp/core';\n *\n * // COUNT(DISTINCT customerId)\n * orm.select('orders').count(distinct('customerId')).execute();\n *\n * // COUNT(DISTINCT customerId) AS unique_customers\n * orm.select('orders').count(distinct('customerId'), 'unique_customers').execute();\n *\n * // SUM(DISTINCT amount) - rare but valid SQL\n * orm.select('orders').sum(distinct('amount'), 'unique_total').execute();\n * ```\n */\nexport function distinct(field: string): DistinctField {\n\treturn { field, distinct: true };\n}\n\n/**\n * Type guard to check if a value is a DistinctField.\n */\nexport function isDistinctField(value: unknown): value is DistinctField {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'field' in value &&\n\t\t'distinct' in value &&\n\t\t(value as DistinctField).distinct === true\n\t);\n}\n\n// ============================================================================\n// Comparison Operators\n// ============================================================================\n\ntype ComparisonFilter = {\n\t<T extends string, C extends string, V>(\n\t\tfield: ColumnRef<T, C, V>,\n\t\tvalue: V,\n\t): WhereComparisonIntent;\n\t(field: string, value: unknown): WhereComparisonIntent;\n};\n\nfunction createComparisonFilter(\n\toperator: ComparisonOperator,\n): ComparisonFilter {\n\treturn (\n\t\tfield: ColumnRef<string, string, unknown> | string,\n\t\tvalue: unknown,\n\t): WhereComparisonIntent => ({\n\t\tkind: 'comparison',\n\t\tfield: getColumnName(field),\n\t\toperator,\n\t\tvalue,\n\t});\n}\n\n/**\n * Equals comparison: field = value\n *\n * @example eq('status', 'active') → status = 'active'\n * @example eq(users.name, 'John') → type-safe with ColumnRef (DX-040)\n */\nexport const eq: ComparisonFilter = createComparisonFilter('eq');\n\n/**\n * Not equals comparison: field != value\n *\n * @example neq('status', 'deleted') → status != 'deleted'\n * @example neq(users.status, 'deleted') → type-safe with ColumnRef (DX-040)\n */\nexport const neq: ComparisonFilter = createComparisonFilter('neq');\n\n/**\n * Greater than comparison: field > value\n *\n * @example gt('age', 18) → age > 18\n * @example gt(users.age, 18) → type-safe with ColumnRef (DX-040)\n */\nexport const gt: ComparisonFilter = createComparisonFilter('gt');\n\n/**\n * Greater than or equal comparison: field >= value\n *\n * @example gte('age', 18) → age >= 18\n * @example gte(users.age, 18) → type-safe with ColumnRef (DX-040)\n */\nexport const gte: ComparisonFilter = createComparisonFilter('gte');\n\n/**\n * Less than comparison: field < value\n *\n * @example lt('price', 100) → price < 100\n * @example lt(products.price, 100) → type-safe with ColumnRef (DX-040)\n */\nexport const lt: ComparisonFilter = createComparisonFilter('lt');\n\n/**\n * Less than or equal comparison: field <= value\n *\n * @example lte('price', 100) → price <= 100\n * @example lte(products.price, 100) → type-safe with ColumnRef (DX-040)\n */\nexport const lte: ComparisonFilter = createComparisonFilter('lte');\n\n/**\n * Null-safe inequality: field IS DISTINCT FROM value\n *\n * Unlike neq(), returns true when one side is NULL and the other is not.\n * Standard SQL (SQL:2003).\n *\n * @example isDistinctFrom('status', 'active') → status IS DISTINCT FROM 'active'\n * @example isDistinctFrom(users.status, null) → status IS DISTINCT FROM NULL\n */\nexport const isDistinctFrom: ComparisonFilter =\n\tcreateComparisonFilter('isDistinctFrom');\n\n// ============================================================================\n// String Operators\n// ============================================================================\n\n/**\n * LIKE pattern matching: field LIKE pattern\n *\n * @param field - Column name or ColumnRef (must be string type)\n * @param pattern - SQL LIKE pattern (use % for wildcards)\n * @param caseInsensitive - If true, uses ILIKE (PostgreSQL) or LOWER()\n *\n * @example like('name', '%john%') → name LIKE '%john%'\n * @example like('email', '%@example.com', true) → email ILIKE '%@example.com'\n * @example like(users.name, '%John%') → type-safe with ColumnRef (DX-040)\n */\nexport function like<T extends string, C extends string>(\n\tfield: ColumnRef<T, C, string>,\n\tpattern: string,\n\toptions?: boolean | { caseInsensitive?: boolean; escape?: string },\n): WhereLikeIntent;\nexport function like(\n\tfield: string,\n\tpattern: string,\n\toptions?: boolean | { caseInsensitive?: boolean; escape?: string },\n): WhereLikeIntent;\nexport function like(\n\tfield: ColumnRef<string, string, string> | string,\n\tpattern: string,\n\toptions?: boolean | { caseInsensitive?: boolean; escape?: string },\n): WhereLikeIntent {\n\tconst caseInsensitive =\n\t\ttypeof options === 'boolean' ? options : options?.caseInsensitive;\n\tconst escapeChar = typeof options === 'object' ? options.escape : undefined;\n\n\tconst intent: WhereLikeIntent = {\n\t\tkind: 'like',\n\t\tfield: getColumnName(field),\n\t\tpattern,\n\t};\n\tconst withCi =\n\t\tcaseInsensitive !== undefined ? { ...intent, caseInsensitive } : intent;\n\tif (escapeChar !== undefined) {\n\t\treturn { ...withCi, escape: escapeChar };\n\t}\n\treturn withCi;\n}\n\n// ============================================================================\n// Array Operators\n// ============================================================================\n\n/**\n * IN array check: field IN (values)\n *\n * @example inArray('status', ['active', 'pending']) → status IN ('active', 'pending')\n * @example inArray(users.role, ['admin', 'moderator']) → type-safe (DX-040)\n */\nexport function inArray<T extends string, C extends string, V>(\n\tfield: ColumnRef<T, C, V>,\n\tvalues: readonly V[],\n): WhereInIntent;\nexport function inArray(\n\tfield: string,\n\tvalues: readonly unknown[],\n): WhereInIntent;\nexport function inArray(\n\tfield: ColumnRef<string, string, unknown> | string,\n\tvalues: readonly unknown[],\n): WhereInIntent {\n\treturn { kind: 'in', field: getColumnName(field), values };\n}\n\n/**\n * IN subquery: field IN (SELECT ...)\n *\n * Creates a WHERE condition that checks if a field's value exists\n * in the result set of a subquery.\n *\n * @example\n * // Users who have posts\n * orm.select('users').where(inSubquery('id',\n * subquery('posts').select('userId')\n * )).all()\n * // SQL: SELECT * FROM users WHERE id = ANY(SELECT user_id FROM posts)\n */\nexport function inSubquery(\n\tfield: ColumnRef<string, string, unknown> | string,\n\tquery: SubqueryBuilder | SubqueryExpression,\n): WhereInIntent {\n\tconst expr =\n\t\t'build' in query\n\t\t\t? (query as SubqueryBuilder).build()\n\t\t\t: (query as SubqueryExpression);\n\treturn {\n\t\tkind: 'in',\n\t\tfield: getColumnName(field),\n\t\tsubquery: expr.toIntent(),\n\t};\n}\n\n/**\n * Array membership filter using PostgreSQL ANY() operator.\n * Compiles to: \"col\" = ANY($N::type[])\n *\n * Unlike inArray(), any() produces an explicit type-cast in the SQL.\n * Use this when you need guaranteed type safety with array parameters.\n *\n * @example\n * orm.select('symbols').where(any('id', [1, 2, 3])).all()\n * // SQL: SELECT * FROM \"symbols\" WHERE \"id\" = ANY($1::int[])\n */\nexport function any(\n\tfield: ColumnRef<string, string, unknown> | string,\n\tvalues: readonly unknown[],\n): WhereAnyIntent {\n\treturn { kind: 'any', field: getColumnName(field), values };\n}\n\n// ============================================================================\n// Null Operators\n// ============================================================================\n\n/**\n * IS NULL check: field IS NULL\n *\n * @example isNull('deletedAt') → deletedAt IS NULL\n * @example isNull(users.deletedAt) → type-safe (DX-040)\n */\nexport function isNull<T extends string, C extends string, V>(\n\tfield: ColumnRef<T, C, V>,\n): WhereNullIntent;\nexport function isNull(field: string): WhereNullIntent;\nexport function isNull(\n\tfield: ColumnRef<string, string, unknown> | string,\n): WhereNullIntent {\n\treturn { kind: 'null', field: getColumnName(field), operator: 'isNull' };\n}\n\n// ============================================================================\n// Range Operators (PostgreSQL)\n// ============================================================================\n\n/**\n * Range value for PostgreSQL range types.\n * @see WhereRangeIntent\n */\nimport type { RangeOperand, RangeValue } from '@dbsp/types';\n\nexport type { RangeOperand, RangeValue } from '@dbsp/types';\n\n/**\n * Range OVERLAPS check: field && range (PostgreSQL)\n * Tests if two ranges have any points in common.\n *\n * @example rangeOverlaps('dates', { lower: '2025-01-15', upper: '2025-01-20' })\n * → dates && '[2025-01-15,2025-01-20)'\n *\n * @param field - Column name containing a range type\n * @param value - Range value with lower/upper bounds\n */\nexport function rangeOverlaps(\n\tfield: string,\n\tvalue: RangeValue,\n): WhereRangeIntent {\n\treturn { kind: 'range', field, operator: 'overlaps', value };\n}\n\n/**\n * Range CONTAINS check: field @> value (PostgreSQL)\n * Tests if the range contains a point or another range.\n *\n * @example rangeContains('salary_range', 50000)\n * → salary_range @> 50000\n * @example rangeContains('date_range', { lower: '2025-01-01', upper: '2025-01-05' })\n * → date_range @> '[2025-01-01,2025-01-05)'\n *\n * @param field - Column name containing a range type\n * @param value - Scalar value or range to check containment\n */\nexport function rangeContains(\n\tfield: string,\n\tvalue: RangeOperand,\n): WhereRangeIntent {\n\treturn { kind: 'range', field, operator: 'contains', value };\n}\n\n/**\n * Range CONTAINED BY check: field <@ range (PostgreSQL)\n * Tests if the field's range is fully contained within another range.\n *\n * @example rangeContainedBy('event_dates', { lower: '2025-01-01', upper: '2025-12-31' })\n * → event_dates <@ '[2025-01-01,2025-12-31)'\n *\n * @param field - Column name containing a range type\n * @param value - Range that should contain the field's range\n */\nexport function rangeContainedBy(\n\tfield: string,\n\tvalue: RangeValue,\n): WhereRangeIntent {\n\treturn { kind: 'range', field, operator: 'containedBy', value };\n}\n\n/**\n * IS NOT NULL check: field IS NOT NULL\n *\n * @example isNotNull('email') → email IS NOT NULL\n * @example isNotNull(users.email) → type-safe (DX-040)\n */\nexport function isNotNull<T extends string, C extends string, V>(\n\tfield: ColumnRef<T, C, V>,\n): WhereNullIntent;\nexport function isNotNull(field: string): WhereNullIntent;\nexport function isNotNull(\n\tfield: ColumnRef<string, string, unknown> | string,\n): WhereNullIntent {\n\treturn { kind: 'null', field: getColumnName(field), operator: 'isNotNull' };\n}\n\n// ============================================================================\n// Logical Operators\n// ============================================================================\n\n/**\n * Logical AND: all conditions must match\n *\n * Accepts variadic arguments or a single array.\n *\n * @example and(eq('a', 1), gt('b', 2)) → a = 1 AND b > 2\n * @example and([eq('a', 1), gt('b', 2)]) → a = 1 AND b > 2\n */\nexport function and(\n\t...conditions: WhereIntent[] | [readonly WhereIntent[]]\n): WhereAndIntent {\n\t// Handle both variadic and array forms\n\tconst flatConditions =\n\t\tconditions.length === 1 && Array.isArray(conditions[0])\n\t\t\t? (conditions[0] as readonly WhereIntent[])\n\t\t\t: (conditions as WhereIntent[]);\n\n\treturn { kind: 'and', conditions: flatConditions };\n}\n\n/**\n * Logical OR: at least one condition must match\n *\n * Accepts variadic arguments or a single array.\n *\n * @example or(eq('status', 'active'), eq('status', 'pending'))\n * @example or([eq('status', 'active'), eq('status', 'pending')])\n */\nexport function or(\n\t...conditions: WhereIntent[] | [readonly WhereIntent[]]\n): WhereOrIntent {\n\t// Handle both variadic and array forms\n\tconst flatConditions =\n\t\tconditions.length === 1 && Array.isArray(conditions[0])\n\t\t\t? (conditions[0] as readonly WhereIntent[])\n\t\t\t: (conditions as WhereIntent[]);\n\n\treturn { kind: 'or', conditions: flatConditions };\n}\n\n/**\n * Logical NOT: condition must not match\n *\n * @example not(eq('deleted', true)) → NOT (deleted = true)\n */\nexport function not(condition: WhereIntent): WhereNotIntent {\n\treturn { kind: 'not', condition };\n}\n\n// ============================================================================\n// Relation Operators\n// ============================================================================\n\n/**\n * EXISTS subquery: filter by existence of related records\n *\n * @param relation - Relation name defined in schema\n * @param options - Optional nested filter on related records, with optional recursive options\n *\n * @example exists('posts') → EXISTS (SELECT 1 FROM posts WHERE ...)\n * @example exists('posts', { where: eq('published', true) })\n * @example exists('ancestors', { recursive: { direction: 'up', through: 'parent', maxDepth: 10 }, where: eq('name', 'Electronics') })\n */\nexport function exists(\n\trelation: string,\n\toptions?: {\n\t\twhere?: WhereIntent;\n\t\trecursive?: RecursiveExistsOptions;\n\t\tinclude?: Record<string, { join?: 'inner' | 'left' }>;\n\t},\n): WhereExistsIntent {\n\tconst result: Mutable<WhereExistsIntent> = { kind: 'exists', relation };\n\tif (options?.where !== undefined) {\n\t\tresult.where = options.where;\n\t}\n\tif (options?.recursive !== undefined) {\n\t\tresult.recursive = options.recursive;\n\t}\n\tif (options?.include !== undefined) {\n\t\tresult.include = options.include;\n\t}\n\treturn result;\n}\n\n/**\n * NOT EXISTS subquery: filter by absence of related records\n *\n * @param relation - Relation name defined in schema\n * @param options - Optional nested filter on related records, with optional recursive options\n *\n * @example notExists('comments') → NOT EXISTS (SELECT 1 FROM comments WHERE ...)\n * @example notExists('ancestors', { recursive: { direction: 'up', through: 'parent' }, where: eq('name', 'Obsolete') })\n */\nexport function notExists(\n\trelation: string,\n\toptions?: {\n\t\twhere?: WhereIntent;\n\t\trecursive?: RecursiveExistsOptions;\n\t\tinclude?: Record<string, { join?: 'inner' | 'left' }>;\n\t},\n): WhereNotExistsIntent {\n\tconst result: Mutable<WhereNotExistsIntent> = {\n\t\tkind: 'notExists',\n\t\trelation,\n\t};\n\tif (options?.where !== undefined) {\n\t\tresult.where = options.where;\n\t}\n\tif (options?.recursive !== undefined) {\n\t\tresult.recursive = options.recursive;\n\t}\n\tif (options?.include !== undefined) {\n\t\tresult.include = options.include;\n\t}\n\treturn result;\n}\n\n/**\n * EXISTS with an arbitrary subquery (not FK-resolved).\n *\n * Use when the subquery does not follow a declared schema relation.\n * Accepts a SubqueryBuilder (must have `.build()`) or any builder\n * exposing `buildIntent(): QueryIntent` (e.g. QueryBuilder).\n *\n * **Limitation:** correlated subqueries (using `outerRef()` inside the inner WHERE)\n * are NOT supported and will throw at compile time. For correlated EXISTS over an\n * FK-declared relation, use `exists('relation', { where: ... outerRef(...) })` instead.\n *\n * @param subquery - A SubqueryBuilder or any object with buildIntent()\n *\n * @example\n * // EXISTS (SELECT 1 FROM audit_log WHERE audit_log.entity_type = 'login')\n * // Uncorrelated: no reference to the outer row — inner filter is a plain value.\n * rawExists(subquery('audit_log').select('id').where(eq('entityType', 'login')))\n *\n * @example\n * // EXISTS with a full query builder — polymorphic table, no FK to source\n * rawExists(orm.select('sessions').where(and(eq('status', 'active'), gt('expiresAt', new Date()))))\n */\nexport function rawExists(\n\tsq: SubqueryBuilder | { buildIntent(): QueryIntent },\n): WhereRawExistsIntent {\n\tconst intent =\n\t\t'buildIntent' in sq\n\t\t\t? (sq as { buildIntent(): QueryIntent }).buildIntent()\n\t\t\t: (sq as SubqueryBuilder).build().toIntent();\n\treturn { kind: 'rawExists', subquery: intent };\n}\n\n/**\n * NOT EXISTS with an arbitrary subquery (not FK-resolved).\n *\n * Use when the subquery does not follow a declared schema relation.\n * Accepts a SubqueryBuilder (must have `.build()`) or any builder\n * exposing `buildIntent(): QueryIntent` (e.g. QueryBuilder).\n *\n * **Limitation:** correlated subqueries (using `outerRef()` inside the inner WHERE)\n * are NOT supported and will throw at compile time. For correlated NOT EXISTS over an\n * FK-declared relation, use `notExists('relation', { where: ... outerRef(...) })` instead.\n *\n * @param subquery - A SubqueryBuilder or any object with buildIntent()\n *\n * @example\n * // NOT EXISTS (SELECT 1 FROM bans WHERE bans.reason = 'spam')\n * // Uncorrelated: inner filter is a plain value, no reference to the outer row.\n * rawNotExists(subquery('bans').select('id').where(eq('reason', 'spam')))\n */\nexport function rawNotExists(\n\tsq: SubqueryBuilder | { buildIntent(): QueryIntent },\n): WhereRawNotExistsIntent {\n\tconst intent =\n\t\t'buildIntent' in sq\n\t\t\t? (sq as { buildIntent(): QueryIntent }).buildIntent()\n\t\t\t: (sq as SubqueryBuilder).build().toIntent();\n\treturn { kind: 'rawNotExists', subquery: intent };\n}\n\n// ============================================================================\n// Quantified Relation Filters (DX-040 Block 7)\n// ============================================================================\n\n/**\n * Get relation name from a RelationRef.\n * @internal\n */\nfunction getRelationName(\n\trel: RelationRef<string, unknown, 'belongsTo' | 'hasMany' | 'hasOne'>,\n): string {\n\tconst meta = rel[RELATION_META];\n\tif (!meta) {\n\t\tthrow new Error('Invalid RelationRef: missing RELATION_META');\n\t}\n\treturn meta.target;\n}\n\n/**\n * EVERY quantifier: filter parent by condition that ALL related records must match\n *\n * This generates SQL like: NOT EXISTS (SELECT 1 FROM related WHERE NOT condition)\n *\n * @param relation - RelationRef from schema (e.g., users.posts)\n * @param filter - Callback that receives relation and returns a filter condition\n *\n * @example\n * ```typescript\n * // Find users where ALL their posts are published\n * orm.from(users)\n * .where(every(users.posts, p => eq(p.published, true)))\n *\n * // SQL: ... WHERE NOT EXISTS (\n * // SELECT 1 FROM posts WHERE posts.author_id = users.id AND NOT (posts.published = true)\n * // )\n * ```\n */\nexport function every<TTarget extends string, TTargetType>(\n\trelation: RelationRef<TTarget, TTargetType[], 'hasMany'>,\n\tfilter: (rel: RelationRef<TTarget, TTargetType[], 'hasMany'>) => WhereIntent,\n): WhereRelationFilterIntent {\n\tconst relationName = getRelationName(relation);\n\tconst where = filter(relation);\n\treturn {\n\t\tkind: 'relationFilter',\n\t\trelation: relationName,\n\t\twhere,\n\t\tmode: 'every',\n\t};\n}\n\n/**\n * NONE quantifier: filter parent by condition that NO related records match\n *\n * This is equivalent to: NOT EXISTS (SELECT 1 FROM related WHERE condition)\n *\n * @param relation - RelationRef from schema (e.g., users.posts)\n * @param filter - Callback that receives relation and returns a filter condition\n *\n * @example\n * ```typescript\n * // Find users with no flagged posts\n * orm.from(users)\n * .where(none(users.posts, p => eq(p.flagged, true)))\n *\n * // SQL: ... WHERE NOT EXISTS (\n * // SELECT 1 FROM posts WHERE posts.author_id = users.id AND posts.flagged = true\n * // )\n * ```\n */\nexport function none<TTarget extends string, TTargetType>(\n\trelation: RelationRef<TTarget, TTargetType[], 'hasMany'>,\n\tfilter: (rel: RelationRef<TTarget, TTargetType[], 'hasMany'>) => WhereIntent,\n): WhereRelationFilterIntent {\n\tconst relationName = getRelationName(relation);\n\tconst where = filter(relation);\n\treturn {\n\t\tkind: 'relationFilter',\n\t\trelation: relationName,\n\t\twhere,\n\t\tmode: 'none',\n\t};\n}\n\n/**\n * SOME quantifier: filter parent by condition that at least one related record matches\n *\n * This is the default behavior for relation filters and is equivalent to EXISTS.\n *\n * @param relation - RelationRef from schema (e.g., users.posts)\n * @param filter - Callback that receives relation and returns a filter condition\n *\n * @example\n * ```typescript\n * // Find users with at least one published post\n * orm.from(users)\n * .where(some(users.posts, p => eq(p.published, true)))\n *\n * // SQL: ... WHERE EXISTS (\n * // SELECT 1 FROM posts WHERE posts.author_id = users.id AND posts.published = true\n * // )\n * ```\n */\nexport function some<TTarget extends string, TTargetType>(\n\trelation: RelationRef<TTarget, TTargetType[], 'hasMany'>,\n\tfilter: (rel: RelationRef<TTarget, TTargetType[], 'hasMany'>) => WhereIntent,\n): WhereRelationFilterIntent {\n\tconst relationName = getRelationName(relation);\n\tconst where = filter(relation);\n\treturn {\n\t\tkind: 'relationFilter',\n\t\trelation: relationName,\n\t\twhere,\n\t\tmode: 'some',\n\t};\n}\n\n// ============================================================================\n// Expression Helpers\n// ============================================================================\n\n/**\n * COALESCE expression: returns first non-null value from a list of fields\n *\n * Use this for locale fallback patterns (e.g., FR → EN → default)\n *\n * @param fields - Array of field names to check in order\n * @param as - Required alias for the result column\n *\n * @example\n * ```typescript\n * // Locale fallback: prefer French, fall back to English\n * coalesce(['name_fr', 'name_en'], 'display_name')\n * // → COALESCE(name_fr, name_en) AS display_name\n *\n * // Use in QueryBuilder select with expressions\n * orm.select('products')\n * .selectWithExpressions(['id', 'sku'], [\n * coalesce(['title_fr', 'title_en', 'title_default'], 'title')\n * ])\n * ```\n */\nexport function coalesce(\n\tfields: readonly string[],\n\tas: string,\n): ExpressionSpec {\n\tif (fields.length === 0) {\n\t\tthrow new Error('coalesce() requires at least one field');\n\t}\n\tif (!as || as.trim() === '') {\n\t\tthrow new Error('coalesce() requires a non-empty alias');\n\t}\n\t// FIND-008: Validate all field names and the alias as SQL identifiers\n\tfor (const f of fields) {\n\t\tvalidateIdentifier(f, 'column');\n\t}\n\tvalidateIdentifier(as, 'column');\n\treturn {\n\t\t__expr: true,\n\t\tintent: { kind: 'coalesce', fields, as },\n\t};\n}\n\n/**\n * Raw SQL expression (escape hatch for advanced use cases).\n *\n * @warning **SECURITY RISK: SQL INJECTION VULNERABILITY**\n *\n * This function bypasses ALL SQL injection protections. The SQL fragment\n * is inserted directly into queries without sanitization.\n *\n * **NEVER:**\n * - Interpolate user input: `raw(\\`WHERE name = '\\${userInput}'\\`, 'x')` ❌\n * - Use request parameters: `raw(req.query.field, 'x')` ❌\n * - Trust client-side data: `raw(formData.expression, 'x')` ❌\n *\n * **SAFE USAGE:**\n * - Hardcoded expressions: `raw('NOW()', 'current_time')` ✅\n * - Constants: `raw('price_cents / 100.0', 'price_dollars')` ✅\n * - Server-controlled values only\n *\n * For user-provided values, use parameterized queries via the standard\n * filter functions (eq, gt, like, etc.) which properly escape values.\n *\n * @param sqlFragment - Raw SQL fragment. **Must be safe - no user input!**\n * @param as - Required alias for the result column\n * @returns ExpressionSpec for use in select()\n *\n * @example\n * ```typescript\n * // SAFE: Hardcoded expressions\n * raw('NOW()', 'current_time')\n * // → NOW() AS current_time\n *\n * raw('price_cents / 100.0', 'price_dollars')\n * // → price_cents / 100.0 AS price_dollars\n *\n * // DANGEROUS - SQL INJECTION RISK!\n * // raw(`WHERE name = '${userInput}'`, 'x') // NEVER DO THIS!\n * ```\n *\n * @see {@link https://owasp.org/www-community/attacks/SQL_Injection | OWASP SQL Injection}\n * @see {@link https://cheatsheetseries.owasp.org/cheatsheets/Query_Parameterization_Cheat_Sheet.html | OWASP Parameterization}\n */\nexport function raw(sqlFragment: string, as: string): ExpressionSpec {\n\t// FIND-008: Validate the alias as a SQL identifier; sqlFragment is an intentional raw escape hatch\n\tvalidateIdentifier(as, 'column');\n\treturn {\n\t\t__expr: true,\n\t\tintent: { kind: 'raw', sql: sqlFragment, as },\n\t};\n}\n\n/**\n * Creates a column alias expression using native Kysely API.\n * Preferred over raw() for simple column aliasing as it's type-safe and dialect-portable.\n *\n * Uses Kysely's `eb.ref(column).as(alias)` internally - no raw SQL.\n *\n * @param column - Column name to select\n * @param alias - Alias for the result column\n * @returns ExpressionSpec for use in columns()\n *\n * @example\n * ```typescript\n * // Simple column alias\n * col('name', 'userName')\n * // → SELECT \"name\" AS \"userName\"\n *\n * // Multiple columns with aliases\n * orm.select('users').columns([\n * 'id',\n * col('name', 'userName'),\n * col('email', 'userEmail'),\n * ])\n * ```\n */\nexport function col(column: string, alias: string): ExpressionSpec {\n\t// FIND-008: Validate column name and alias as SQL identifiers (same strictness as coalesce)\n\tvalidateIdentifier(column, 'column');\n\tvalidateIdentifier(alias, 'column');\n\treturn {\n\t\t__expr: true,\n\t\tintent: { kind: 'columnAlias', column, alias },\n\t};\n}\n\n/**\n * Creates a relation column expression for selecting a column from a related table.\n * Auto-creates JOINs via the include mechanism and selects with custom alias.\n *\n * Uses native Kysely API internally - no raw SQL. The compiler resolves the relation\n * to its join alias and uses `eb.ref(alias.column).as(as)`.\n *\n * @param relation - Relation path to traverse (dot-separated for multi-level)\n * @param column - Column name to select from the target relation\n * @param as - Alias for the result column\n * @returns ExpressionSpec for use in columns()\n *\n * @example\n * ```typescript\n * // Select from direct relation\n * relationColumn('category', 'name', 'categoryName')\n * // → SELECT t1.\"name\" AS \"categoryName\" (with JOIN to categories)\n *\n * // Select from nested relation (multi-level path)\n * relationColumn('category.parent', 'name', 'parentName')\n * // → SELECT t2.\"name\" AS \"parentName\" (with JOINs through category to parent)\n *\n * // In a query\n * orm.select('products').columns([\n * 'name',\n * relationColumn('category', 'name', 'categoryName'),\n * ])\n * ```\n */\nexport function relationColumn<A extends string>(\n\trelation: string,\n\tcolumn: string,\n\tas: A,\n): AliasedExprColumn<A> {\n\t// FIND-008: Validate relation path segments, column, and alias as SQL identifiers.\n\t// relation may be dot-separated (e.g. 'category.parent') — validate each segment individually.\n\t// Keep the explicit empty guard so callers get the descriptive \"relation path\" message for ''.\n\t// Non-empty but invalid strings (whitespace, injection chars) are caught by validateIdentifier.\n\tif (!relation) {\n\t\tthrow new Error('relationColumn() requires a non-empty relation path');\n\t}\n\tfor (const segment of relation.split('.')) {\n\t\tvalidateIdentifier(segment, 'relation');\n\t}\n\t// Allow the wildcard '*' as a valid column value — the adapter compiler\n\t// handles it as A_Star (unquoted star) for relation.* expansion.\n\t// Any other column value must pass identifier validation.\n\tif (column !== '*') {\n\t\tvalidateIdentifier(column, 'column');\n\t}\n\tvalidateIdentifier(as as string, 'column');\n\treturn {\n\t\t__expr: true,\n\t\tintent: { kind: 'relationColumn', relation, column, as },\n\t} as unknown as AliasedExprColumn<A>;\n}\n\n// ============================================================================\n// Raw SQL Set Expression (for doUpdate() / set() mutations)\n// ============================================================================\n\n/**\n * Symbol to identify raw SQL expression values in set() / doUpdate()\n * @internal\n */\nexport const SQL_RAW_MARKER = Symbol.for('dbsp:raw-sql');\n\n/**\n * A raw SQL expression for use in mutation set values (doUpdate / set).\n * Created by the {@link sql} function.\n */\nexport interface SqlRawExpression {\n\treadonly [SQL_RAW_MARKER]: true;\n\treadonly sql: string;\n}\n\n/**\n * Create a raw SQL expression for use in `doUpdate()` and `set()` mutation values.\n *\n * @warning **SECURITY RISK: SQL INJECTION VULNERABILITY**\n * The SQL fragment is inserted **WITHOUT** parameterization.\n * Only use with hardcoded expressions — **NEVER** with user input.\n *\n * **SAFE USAGE:**\n * - Hardcoded functions: `sql('now()')` ✅\n * - Excluded references: `sql('excluded.count + 1')` ✅\n * - Server-controlled literals: `sql('gen_random_uuid()')` ✅\n *\n * **NEVER:**\n * - Interpolate user input: `` sql(`'${userInput}'`) `` ❌\n * - Use request parameters: `sql(req.query.expr)` ❌\n *\n * @param sqlFragment - Raw SQL fragment (must be safe — no user input!)\n * @returns SqlRawExpression for use in doUpdate() / set()\n *\n * @example\n * ```typescript\n * orm.upsert('files')\n * .values({ id: 1, name: 'test' })\n * .onConflict({ columns: ['id'] })\n * .doUpdate({ last_parsed: sql('now()'), count: sql('excluded.count + 1') })\n * .execute();\n *\n * orm.update('files')\n * .set({ last_parsed: sql('now()') })\n * .where(eq('id', 1))\n * .execute();\n * ```\n *\n * @see {@link https://owasp.org/www-community/attacks/SQL_Injection | OWASP SQL Injection}\n */\nexport function sql(sqlFragment: string): SqlRawExpression {\n\tif (!sqlFragment || sqlFragment.trim() === '') {\n\t\tthrow new Error('sql() requires a non-empty SQL fragment');\n\t}\n\treturn { [SQL_RAW_MARKER]: true, sql: sqlFragment };\n}\n\n/**\n * Type guard: check if a value is a raw SQL expression created by {@link sql}.\n */\nexport function isSqlRaw(value: unknown): value is SqlRawExpression {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\tSQL_RAW_MARKER in value &&\n\t\t(value as Record<symbol, unknown>)[SQL_RAW_MARKER] === true\n\t);\n}\n\n// ============================================================================\n// Window Functions (re-exported from window-functions.ts)\n// ============================================================================\n\nexport {\n\tdenseRank,\n\tlag,\n\tlead,\n\trank,\n\trowNumber,\n\tWindowBuilder,\n\twAvg,\n\twCount,\n\twMax,\n\twMin,\n\twSum,\n} from './window-functions.js';\n","/**\n * @dbsp/core — Full-Text Search Helpers (FR-5)\n *\n * High-level cross-DB-friendly helpers that wrap the low-level ParadeDB\n * expression primitives (bm25Search / score from adapter-pgsql) using only\n * core expression building blocks.\n *\n * These helpers are ParadeDB/PostgreSQL-first; other adapters are expected\n * to either support the same SQL or receive a capability error at runtime.\n */\n\nimport type { ExpressionRef } from './expressions.js';\nimport { array, fn, literal, namedArg, op, param, ref } from './expressions.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * A single field to include in a full-text search, with an optional boost weight.\n */\nexport type FullTextSearchField = {\n\t/** Column name in the BM25 index */\n\treadonly name: string;\n\t/** Boost multiplier (higher = more important). Default: 1.0 */\n\treadonly boost: number;\n};\n\n/**\n * Options for fullTextSearch().\n */\nexport type FullTextSearchOptions = {\n\t/** The query string (will be bound as a single $N parameter shared across all fields). */\n\treadonly query: unknown;\n\t/** Fields to search with per-field boost weights. */\n\treadonly fields: readonly FullTextSearchField[];\n\t/**\n\t * Table name or alias to qualify the left side of the @@@ operator.\n\t * Must match the exact table name (or alias) as it appears in the FROM clause.\n\t * In the standard ORM pipeline the root table has no alias, so pass the root table name.\n\t *\n\t * @example\n\t * fullTextSearch({ query, fields, tableAlias: 'symbols' })\n\t * // → \"symbols\" @@@ paradedb.boolean(...)\n\t */\n\treadonly tableAlias: string;\n};\n\n// ============================================================================\n// fullTextSearch()\n// ============================================================================\n\n/**\n * High-level full-text search filter for ParadeDB BM25 index.\n *\n * Produces:\n * ```sql\n * \"tableAlias\" @@@ paradedb.boolean(\n * should => ARRAY[\n * paradedb.boost(weight1, paradedb.parse(field => 'field1', query_string => $N)),\n * paradedb.boost(weight2, paradedb.parse(field => 'field2', query_string => $N)),\n * ...\n * ]\n * )\n * ```\n *\n * The same query value is bound to separate $N parameters, one per field.\n *\n * @param options.query - Query string (bound as a single parameter)\n * @param options.fields - Fields to search with per-field boost weights\n * @param options.tableAlias - Table name or alias as it appears in the FROM clause (required).\n * In the standard ORM pipeline the root table has no alias — pass the root table name directly.\n * @returns ExpressionRef for use in .where()\n *\n * @example\n * ```typescript\n * import { fullTextSearch } from '@dbsp/core';\n *\n * .where(fullTextSearch({\n * query: searchTerm,\n * tableAlias: 'symbols',\n * fields: [\n * { name: 'name', boost: 3.0 },\n * { name: 'doc', boost: 1.0 },\n * ],\n * }))\n * ```\n */\nexport function fullTextSearch({\n\tquery,\n\tfields,\n\ttableAlias,\n}: FullTextSearchOptions): ExpressionRef {\n\tconst queryParam = param(query);\n\tconst boostExprs = fields.map(({ name: fieldName, boost: weight }) =>\n\t\tfn(\n\t\t\t'paradedb.boost',\n\t\t\tliteral(weight),\n\t\t\tfn(\n\t\t\t\t'paradedb.parse',\n\t\t\t\tnamedArg('field', literal(fieldName)),\n\t\t\t\tnamedArg('query_string', queryParam),\n\t\t\t),\n\t\t),\n\t);\n\tconst booleanExpr = fn(\n\t\t'paradedb.boolean',\n\t\tnamedArg('should', array(...boostExprs)),\n\t);\n\treturn op('@@@', ref(tableAlias), booleanExpr);\n}\n\n// ============================================================================\n// textScore()\n// ============================================================================\n\n/**\n * BM25 relevance score expression for ParadeDB.\n *\n * Produces: paradedb.score(\"keyField\")\n *\n * Use in .columns() to include the score in results, and in .orderBy() to rank\n * results by relevance. Requires a BM25 index with the given key field on the table.\n *\n * @param keyField - The primary key field of the BM25 index (default: 'id')\n * @returns ExpressionRef for use in .columns() and .orderBy()\n *\n * @example\n * ```typescript\n * import { textScore } from '@dbsp/core';\n *\n * .columns(['*', textScore().as('score')])\n * .orderBy(textScore(), 'desc')\n * // SQL: SELECT *, paradedb.score(\"id\") AS \"score\" ... ORDER BY paradedb.score(\"id\") DESC\n * ```\n */\nexport function textScore(keyField = 'id'): ExpressionRef {\n\treturn fn('paradedb.score', ref(keyField));\n}\n","/**\n * Hook composition utilities (ARCH-008).\n * Provides compose/pipe for combining multiple hooks into one,\n * and priority-ordered registration helpers.\n */\n\nimport type {\n\tAfterMutationHook,\n\tAfterQueryHook,\n\tBeforeMutationHook,\n\tBeforeQueryHook,\n\tErrorHookContext,\n\tMutationHookContext,\n\tOnErrorHook,\n\tQueryHookContext,\n} from './hooks.js';\n\n// ============================================================================\n// Priority\n// ============================================================================\n\n/**\n * Priority levels for hook ordering.\n * Hooks with higher priority run first when sorted.\n */\nexport type HookPriority = 'critical' | 'high' | 'normal' | 'low';\n\nconst PRIORITY_ORDER: Record<HookPriority, number> = {\n\tcritical: 0,\n\thigh: 1,\n\tnormal: 2,\n\tlow: 3,\n};\n\n/**\n * A hook wrapped with an explicit priority for ordering.\n * Use {@link sortByPriority} to produce an ordered array.\n */\nexport type PrioritizedHook<TFn> = {\n\treadonly hook: TFn;\n\treadonly priority: HookPriority;\n};\n\n/**\n * Wraps a hook with a priority level for use with {@link sortByPriority}.\n *\n * @example\n * ```typescript\n * const hooks = [\n * withPriority(auditHook, 'low'),\n * withPriority(authHook, 'critical'),\n * ];\n * const ordered = sortByPriority(hooks); // authHook runs first\n * ```\n */\nexport function withPriority<TFn>(\n\thook: TFn,\n\tpriority: HookPriority,\n): PrioritizedHook<TFn> {\n\treturn { hook, priority };\n}\n\n/**\n * Sorts an array of prioritized hooks by priority (critical → high → normal → low).\n * Stable: hooks with the same priority retain their original relative order.\n *\n * @returns A new array of unwrapped hook functions in priority order.\n */\nexport function sortByPriority<TFn>(\n\thooks: readonly PrioritizedHook<TFn>[],\n): TFn[] {\n\treturn [...hooks]\n\t\t.sort((a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority])\n\t\t.map((p) => p.hook);\n}\n\n// ============================================================================\n// BeforeQueryHook composition\n// ============================================================================\n\n/**\n * Composes multiple {@link BeforeQueryHook}s into one (right-to-left execution).\n * The rightmost hook runs first; its output feeds into the next.\n * If a hook returns `undefined`, the current context is passed unchanged.\n *\n * @example\n * ```typescript\n * const composed = composeBeforeQueryHooks(loggingHook, tracingHook);\n * // tracingHook runs first, then loggingHook\n * ```\n */\nexport function composeBeforeQueryHooks(\n\t...hooks: BeforeQueryHook[]\n): BeforeQueryHook {\n\t// reverse so rightmost runs first\n\tconst ordered = [...hooks].reverse();\n\treturn async (ctx: QueryHookContext): Promise<QueryHookContext> => {\n\t\tlet current: QueryHookContext = ctx;\n\t\tfor (const hook of ordered) {\n\t\t\tconst result = await hook(current);\n\t\t\tif (result !== undefined) {\n\t\t\t\tcurrent = result;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n/**\n * Pipes multiple {@link BeforeQueryHook}s together (left-to-right execution).\n * The leftmost hook runs first; its output feeds into the next.\n * If a hook returns `undefined`, the current context is passed unchanged.\n *\n * @example\n * ```typescript\n * const piped = pipeBeforeQueryHooks(tracingHook, loggingHook);\n * // tracingHook runs first, then loggingHook\n * ```\n */\nexport function pipeBeforeQueryHooks(\n\t...hooks: BeforeQueryHook[]\n): BeforeQueryHook {\n\treturn async (ctx: QueryHookContext): Promise<QueryHookContext> => {\n\t\tlet current: QueryHookContext = ctx;\n\t\tfor (const hook of hooks) {\n\t\t\tconst result = await hook(current);\n\t\t\tif (result !== undefined) {\n\t\t\t\tcurrent = result;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n// ============================================================================\n// AfterQueryHook composition\n// ============================================================================\n\n/**\n * Composes multiple {@link AfterQueryHook}s into one (right-to-left execution).\n * The rightmost hook runs first; its output becomes the result for the next.\n * If a hook returns `undefined`, the current result is passed unchanged.\n */\nexport function composeAfterQueryHooks(\n\t...hooks: AfterQueryHook[]\n): AfterQueryHook {\n\tconst ordered = [...hooks].reverse();\n\treturn async <R>(ctx: QueryHookContext, result: R): Promise<R> => {\n\t\tlet current: R = result;\n\t\tfor (const hook of ordered) {\n\t\t\tconst next = await hook(ctx, current);\n\t\t\tif (next !== undefined) {\n\t\t\t\tcurrent = next as R;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n/**\n * Pipes multiple {@link AfterQueryHook}s together (left-to-right execution).\n * The leftmost hook runs first; its output becomes the result for the next.\n * If a hook returns `undefined`, the current result is passed unchanged.\n */\nexport function pipeAfterQueryHooks(\n\t...hooks: AfterQueryHook[]\n): AfterQueryHook {\n\treturn async <R>(ctx: QueryHookContext, result: R): Promise<R> => {\n\t\tlet current: R = result;\n\t\tfor (const hook of hooks) {\n\t\t\tconst next = await hook(ctx, current);\n\t\t\tif (next !== undefined) {\n\t\t\t\tcurrent = next as R;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n// ============================================================================\n// BeforeMutationHook composition\n// ============================================================================\n\n/**\n * Composes multiple {@link BeforeMutationHook}s into one (right-to-left execution).\n * If a hook returns `undefined`, the current context is passed unchanged.\n */\nexport function composeBeforeMutationHooks(\n\t...hooks: BeforeMutationHook[]\n): BeforeMutationHook {\n\tconst ordered = [...hooks].reverse();\n\treturn async <T>(\n\t\tctx: MutationHookContext<T>,\n\t): Promise<MutationHookContext<T>> => {\n\t\tlet current: MutationHookContext<T> = ctx;\n\t\tfor (const hook of ordered) {\n\t\t\tconst result = await hook(current);\n\t\t\tif (result !== undefined) {\n\t\t\t\tcurrent = result;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n/**\n * Pipes multiple {@link BeforeMutationHook}s together (left-to-right execution).\n * If a hook returns `undefined`, the current context is passed unchanged.\n */\nexport function pipeBeforeMutationHooks(\n\t...hooks: BeforeMutationHook[]\n): BeforeMutationHook {\n\treturn async <T>(\n\t\tctx: MutationHookContext<T>,\n\t): Promise<MutationHookContext<T>> => {\n\t\tlet current: MutationHookContext<T> = ctx;\n\t\tfor (const hook of hooks) {\n\t\t\tconst result = await hook(current);\n\t\t\tif (result !== undefined) {\n\t\t\t\tcurrent = result;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n// ============================================================================\n// AfterMutationHook composition\n// ============================================================================\n\n/**\n * Composes multiple {@link AfterMutationHook}s into one (right-to-left execution).\n * If a hook returns `undefined`, the current rows are passed unchanged.\n */\nexport function composeAfterMutationHooks(\n\t...hooks: AfterMutationHook[]\n): AfterMutationHook {\n\tconst ordered = [...hooks].reverse();\n\treturn async <T>(ctx: MutationHookContext<T>, result: T[]): Promise<T[]> => {\n\t\tlet current: T[] = result;\n\t\tfor (const hook of ordered) {\n\t\t\tconst next = await hook(ctx, current);\n\t\t\tif (next !== undefined) {\n\t\t\t\tcurrent = next;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n/**\n * Pipes multiple {@link AfterMutationHook}s together (left-to-right execution).\n * If a hook returns `undefined`, the current rows are passed unchanged.\n */\nexport function pipeAfterMutationHooks(\n\t...hooks: AfterMutationHook[]\n): AfterMutationHook {\n\treturn async <T>(ctx: MutationHookContext<T>, result: T[]): Promise<T[]> => {\n\t\tlet current: T[] = result;\n\t\tfor (const hook of hooks) {\n\t\t\tconst next = await hook(ctx, current);\n\t\t\tif (next !== undefined) {\n\t\t\t\tcurrent = next;\n\t\t\t}\n\t\t}\n\t\treturn current;\n\t};\n}\n\n// ============================================================================\n// OnErrorHook composition\n// ============================================================================\n\n/**\n * Composes multiple {@link OnErrorHook}s into one (right-to-left execution).\n * Each hook receives the error from the previous; if a hook returns `undefined`,\n * the current error is passed unchanged.\n */\nexport function composeOnErrorHooks(...hooks: OnErrorHook[]): OnErrorHook {\n\tconst ordered = [...hooks].reverse();\n\treturn async (ctx: ErrorHookContext): Promise<undefined | Error> => {\n\t\tlet currentCtx: ErrorHookContext = ctx;\n\t\tfor (const hook of ordered) {\n\t\t\tconst result = await hook(currentCtx);\n\t\t\tif (result !== undefined) {\n\t\t\t\t// Pass the transformed error forward via a new context\n\t\t\t\tcurrentCtx = { ...currentCtx, error: result };\n\t\t\t}\n\t\t}\n\t\treturn currentCtx.error;\n\t};\n}\n\n/**\n * Pipes multiple {@link OnErrorHook}s together (left-to-right execution).\n * Each hook receives the error from the previous; if a hook returns `undefined`,\n * the current error is passed unchanged.\n */\nexport function pipeOnErrorHooks(...hooks: OnErrorHook[]): OnErrorHook {\n\treturn async (ctx: ErrorHookContext): Promise<undefined | Error> => {\n\t\tlet currentCtx: ErrorHookContext = ctx;\n\t\tfor (const hook of hooks) {\n\t\t\tconst result = await hook(currentCtx);\n\t\t\tif (result !== undefined) {\n\t\t\t\tcurrentCtx = { ...currentCtx, error: result };\n\t\t\t}\n\t\t}\n\t\treturn currentCtx.error;\n\t};\n}\n","/**\n * @module hooks\n * Query/Mutation hook system for cross-cutting concerns.\n * Part of E17b: Query Hooks System.\n *\n * Hooks enable intercepting query/mutation execution for logging,\n * auditing, caching, data transformation, and tenant injection.\n *\n * @example\n * ```typescript\n * const hooks = createHookManager()\n * .beforeQuery(ctx => {\n * console.log(`Query on ${ctx.table}`);\n * return ctx;\n * })\n * .afterQuery((ctx, results) => {\n * console.log(`Got ${results.length} rows in ${ctx.duration}ms`);\n * return results;\n * });\n *\n * const orm = createOrm({ schema, adapter, hooks });\n * ```\n */\n\nimport type {\n\tBatchUpdateIntent,\n\tDeleteIntent,\n\tInsertIntent,\n\tQueryIntent,\n\tUpdateIntent,\n\tUpsertIntent,\n} from '../intent-ast.js';\n\n// ============================================================================\n// Hook Context Types\n// ============================================================================\n\n/** Query execution result types for afterQuery generics */\nexport type QueryResultType =\n\t| 'all'\n\t| 'first'\n\t| 'count'\n\t| 'exists'\n\t| 'aggregate';\n\n/**\n * Context passed to query hooks (beforeQuery/afterQuery).\n * Frozen via Object.freeze — hooks must return new objects to modify.\n */\nexport type QueryHookContext = {\n\treadonly table: string;\n\treadonly operation: 'select';\n\treadonly intent: QueryIntent;\n\treadonly schemaName?: string;\n\treadonly inTransaction?: boolean;\n\treadonly correlationId?: string;\n\treadonly resultType: QueryResultType;\n\treadonly isStreaming?: boolean;\n\t// Available in afterQuery only:\n\treadonly sql?: string;\n\t/** Query parameters. May contain PII — redact before logging. */\n\treadonly parameters?: readonly unknown[];\n\treadonly duration?: number;\n};\n\n/** Union of all mutation intent types */\n/** Union of all mutation intent types */\nexport type MutationIntent =\n\t| InsertIntent\n\t| UpdateIntent\n\t| BatchUpdateIntent\n\t| DeleteIntent\n\t| UpsertIntent;\n\n/** Mutation operation types */\nexport type MutationOperation =\n\t| 'insert'\n\t| 'update'\n\t| 'batchUpdate'\n\t| 'delete'\n\t| 'upsert';\n\n/**\n * Context passed to mutation hooks (beforeMutation/afterMutation).\n * Frozen via Object.freeze — hooks must return new objects to modify.\n */\nexport type MutationHookContext<T = unknown> = {\n\treadonly table: string;\n\treadonly operation: MutationOperation;\n\treadonly intent: MutationIntent;\n\treadonly schemaName?: string;\n\treadonly inTransaction?: boolean;\n\treadonly correlationId?: string;\n\treadonly cardinality: 'single' | 'bulk';\n\treadonly data?: T | T[] | Partial<T>;\n\t// Available in afterMutation only:\n\treadonly sql?: string;\n\t/** Query parameters. May contain PII — redact before logging. */\n\treadonly parameters?: readonly unknown[];\n\treadonly duration?: number;\n\treadonly affectedRows?: number;\n};\n\n/** Hook phase identifier */\nexport type HookPhase =\n\t| 'beforeQuery'\n\t| 'afterQuery'\n\t| 'beforeMutation'\n\t| 'afterMutation';\n\n/**\n * Context passed to onError hooks.\n */\nexport type ErrorHookContext = {\n\treadonly table: string;\n\treadonly operation: string;\n\treadonly error: Error;\n\treadonly intent: QueryIntent | MutationIntent;\n\treadonly phase: HookPhase;\n\treadonly sql?: string;\n\treadonly inTransaction?: boolean;\n};\n\n// ============================================================================\n// Hook Signatures\n// ============================================================================\n\n/** Hook invoked before query execution. Can modify intent via return. */\nexport type BeforeQueryHook = (\n\tctx: QueryHookContext,\n) => QueryHookContext | Promise<QueryHookContext> | undefined;\n\n/** Hook invoked after query execution. Can transform results via return. */\nexport type AfterQueryHook = <R>(\n\tctx: QueryHookContext,\n\tresult: R,\n) => R | Promise<R> | undefined;\n\n/** Hook invoked before mutation execution. Can modify context via return. */\nexport type BeforeMutationHook = <T>(\n\tctx: MutationHookContext<T>,\n) => MutationHookContext<T> | Promise<MutationHookContext<T>> | undefined;\n\n/** Hook invoked after mutation execution. Can transform RETURNING results. */\nexport type AfterMutationHook = <T>(\n\tctx: MutationHookContext<T>,\n\tresult: T[],\n) => T[] | Promise<T[]> | undefined;\n\n/** Hook invoked on query/mutation errors. Can transform the error. */\nexport type OnErrorHook = (\n\tctx: ErrorHookContext,\n) => undefined | Error | Promise<undefined | Error>;\n\n/**\n * Error handler for hook failures.\n * Returns 'continue' to skip failed hook, 'abort' to propagate error.\n */\nexport type HookErrorHandler = (\n\terror: Error,\n\thookName: string,\n\tctx: QueryHookContext | MutationHookContext,\n\tphase: string,\n) => 'continue' | 'abort';\n\n// ============================================================================\n// Hook Manager Interface\n// ============================================================================\n\n/** Immutable builder interface for registering hooks */\nexport interface HookManager {\n\tbeforeQuery(hook: BeforeQueryHook): HookManager;\n\tafterQuery(hook: AfterQueryHook): HookManager;\n\tbeforeMutation(hook: BeforeMutationHook): HookManager;\n\tafterMutation(hook: AfterMutationHook): HookManager;\n\tonError(hook: OnErrorHook): HookManager;\n\tfreeze(): HookManager;\n}\n\n// ============================================================================\n// Internal Hook Storage\n// ============================================================================\n\n/** @internal Hook storage — exposed for runner access */\nexport type HookStore = {\n\treadonly beforeQuery: readonly BeforeQueryHook[];\n\treadonly afterQuery: readonly AfterQueryHook[];\n\treadonly beforeMutation: readonly BeforeMutationHook[];\n\treadonly afterMutation: readonly AfterMutationHook[];\n\treadonly onError: readonly OnErrorHook[];\n\treadonly frozen: boolean;\n};\n\n// ============================================================================\n// Hook Manager Implementation\n// ============================================================================\n\nclass HookManagerImpl implements HookManager {\n\tprivate readonly store: HookStore;\n\n\tconstructor(store?: HookStore) {\n\t\tthis.store = store ?? {\n\t\t\tbeforeQuery: [],\n\t\t\tafterQuery: [],\n\t\t\tbeforeMutation: [],\n\t\t\tafterMutation: [],\n\t\t\tonError: [],\n\t\t\tfrozen: false,\n\t\t};\n\t}\n\n\tbeforeQuery(hook: BeforeQueryHook): HookManager {\n\t\tthis.assertNotFrozen();\n\t\treturn new HookManagerImpl({\n\t\t\t...this.store,\n\t\t\tbeforeQuery: [...this.store.beforeQuery, hook],\n\t\t});\n\t}\n\n\tafterQuery(hook: AfterQueryHook): HookManager {\n\t\tthis.assertNotFrozen();\n\t\treturn new HookManagerImpl({\n\t\t\t...this.store,\n\t\t\tafterQuery: [...this.store.afterQuery, hook],\n\t\t});\n\t}\n\n\tbeforeMutation(hook: BeforeMutationHook): HookManager {\n\t\tthis.assertNotFrozen();\n\t\treturn new HookManagerImpl({\n\t\t\t...this.store,\n\t\t\tbeforeMutation: [...this.store.beforeMutation, hook],\n\t\t});\n\t}\n\n\tafterMutation(hook: AfterMutationHook): HookManager {\n\t\tthis.assertNotFrozen();\n\t\treturn new HookManagerImpl({\n\t\t\t...this.store,\n\t\t\tafterMutation: [...this.store.afterMutation, hook],\n\t\t});\n\t}\n\n\tonError(hook: OnErrorHook): HookManager {\n\t\tthis.assertNotFrozen();\n\t\treturn new HookManagerImpl({\n\t\t\t...this.store,\n\t\t\tonError: [...this.store.onError, hook],\n\t\t});\n\t}\n\n\tfreeze(): HookManager {\n\t\tif (this.store.frozen) return this;\n\t\treturn new HookManagerImpl({ ...this.store, frozen: true });\n\t}\n\n\t/** @internal Access hook store for runner */\n\tgetStore(): HookStore {\n\t\treturn this.store;\n\t}\n\n\tprivate assertNotFrozen(): void {\n\t\tif (this.store.frozen) {\n\t\t\tthrow new Error(\n\t\t\t\t'HookManager is frozen — hooks cannot be added after ORM creation. ' +\n\t\t\t\t\t'Register all hooks before passing to createOrm().',\n\t\t\t);\n\t\t}\n\t}\n}\n\n// ============================================================================\n// Hook Runner\n// ============================================================================\n\n/**\n * @internal\n * Extracts the hook store from a HookManager.\n * Used by ORM internals to access hooks for execution.\n */\nexport function getHookStore(manager: HookManager): HookStore {\n\treturn (manager as HookManagerImpl).getStore();\n}\n\n// ============================================================================\n// Re-entrancy Guard (INV-07)\n// ============================================================================\n\n/**\n * @internal\n * Tracks hook stores that are currently executing hooks.\n * Prevents infinite loops when hooks issue queries/mutations.\n */\nconst activeHookStores = new WeakSet<HookStore>();\n\n/**\n * @internal\n * Marks a hook store as actively executing hooks.\n * Returns a cleanup function to call when done.\n */\nexport function enterHookExecution(store: HookStore): () => void {\n\tactiveHookStores.add(store);\n\treturn () => activeHookStores.delete(store);\n}\n\n/**\n * @internal\n * Executes `fn` within a re-entrancy guard.\n * While `fn` runs, `hasHooks(store)` returns false — preventing infinite loops\n * when hooks issue queries/mutations themselves.\n */\nexport async function withReentrancyGuard<R>(\n\tstore: HookStore,\n\tfn: (store: HookStore) => Promise<R>,\n): Promise<R> {\n\tconst exit = enterHookExecution(store);\n\ttry {\n\t\treturn await fn(store);\n\t} finally {\n\t\texit();\n\t}\n}\n\n/**\n * @internal\n * Checks whether a hook manager has any hooks registered\n * AND is not currently in a re-entrant execution.\n * Used for zero-cost optimization: skip hook execution when no hooks exist\n * or when called from within a hook (preventing infinite loops).\n */\nexport function hasHooks(store: HookStore): boolean {\n\t// Re-entrancy guard: if this store is already executing hooks, skip\n\tif (activeHookStores.has(store)) return false;\n\n\treturn (\n\t\tstore.beforeQuery.length > 0 ||\n\t\tstore.afterQuery.length > 0 ||\n\t\tstore.beforeMutation.length > 0 ||\n\t\tstore.afterMutation.length > 0 ||\n\t\tstore.onError.length > 0\n\t);\n}\n\n/**\n * @internal\n * Runs beforeQuery hooks in registration order (FIFO).\n * Returns the (potentially modified) context.\n * Context is frozen before each hook invocation.\n */\nexport async function runBeforeQueryHooks(\n\thooks: readonly BeforeQueryHook[],\n\tctx: QueryHookContext,\n\tonHookError?: HookErrorHandler,\n): Promise<QueryHookContext> {\n\tlet current = ctx;\n\tfor (const hook of hooks) {\n\t\tconst frozen = Object.freeze({ ...current });\n\t\ttry {\n\t\t\tconst result = await hook(frozen);\n\t\t\tif (result !== undefined && result !== null) {\n\t\t\t\tcurrent = result;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (onHookError) {\n\t\t\t\tconst action = onHookError(\n\t\t\t\t\terror as Error,\n\t\t\t\t\thook.name || 'anonymous',\n\t\t\t\t\tfrozen,\n\t\t\t\t\t'beforeQuery',\n\t\t\t\t);\n\t\t\t\tif (action === 'continue') continue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\treturn current;\n}\n\n/**\n * @internal\n * Runs afterQuery hooks in reverse registration order (LIFO — middleware semantics).\n * Returns the (potentially transformed) result.\n */\nexport async function runAfterQueryHooks<R>(\n\thooks: readonly AfterQueryHook[],\n\tctx: QueryHookContext,\n\tresult: R,\n\tonHookError?: HookErrorHandler,\n): Promise<R> {\n\tlet current = result;\n\t// LIFO order: last registered hook runs first\n\tfor (let i = hooks.length - 1; i >= 0; i--) {\n\t\tconst hook = hooks[i];\n\t\tif (!hook) continue;\n\t\tconst frozen = Object.freeze({ ...ctx });\n\t\ttry {\n\t\t\tconst transformed = await hook(frozen, current);\n\t\t\tif (transformed !== undefined && transformed !== null) {\n\t\t\t\tcurrent = transformed;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (onHookError) {\n\t\t\t\tconst action = onHookError(\n\t\t\t\t\terror as Error,\n\t\t\t\t\thook.name || 'anonymous',\n\t\t\t\t\tfrozen,\n\t\t\t\t\t'afterQuery',\n\t\t\t\t);\n\t\t\t\tif (action === 'continue') continue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\treturn current;\n}\n\n/**\n * @internal\n * Runs beforeMutation hooks in registration order (FIFO).\n */\nexport async function runBeforeMutationHooks<T>(\n\thooks: readonly BeforeMutationHook[],\n\tctx: MutationHookContext<T>,\n\tonHookError?: HookErrorHandler,\n): Promise<MutationHookContext<T>> {\n\tlet current = ctx;\n\tfor (const hook of hooks) {\n\t\tconst frozen = Object.freeze({ ...current });\n\t\ttry {\n\t\t\tconst result = await hook(frozen);\n\t\t\tif (result !== undefined && result !== null) {\n\t\t\t\tcurrent = result as MutationHookContext<T>;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (onHookError) {\n\t\t\t\tconst action = onHookError(\n\t\t\t\t\terror as Error,\n\t\t\t\t\thook.name || 'anonymous',\n\t\t\t\t\tfrozen,\n\t\t\t\t\t'beforeMutation',\n\t\t\t\t);\n\t\t\t\tif (action === 'continue') continue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\treturn current;\n}\n\n/**\n * @internal\n * Runs afterMutation hooks in reverse registration order (LIFO).\n */\nexport async function runAfterMutationHooks<T>(\n\thooks: readonly AfterMutationHook[],\n\tctx: MutationHookContext<T>,\n\tresult: T[],\n\tonHookError?: HookErrorHandler,\n): Promise<T[]> {\n\tlet current = result;\n\tfor (let i = hooks.length - 1; i >= 0; i--) {\n\t\tconst hook = hooks[i];\n\t\tif (!hook) continue;\n\t\tconst frozen = Object.freeze({ ...ctx });\n\t\ttry {\n\t\t\tconst transformed = await hook(frozen, current);\n\t\t\tif (transformed !== undefined && transformed !== null) {\n\t\t\t\tcurrent = transformed as T[];\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (onHookError) {\n\t\t\t\tconst action = onHookError(\n\t\t\t\t\terror as Error,\n\t\t\t\t\thook.name || 'anonymous',\n\t\t\t\t\tfrozen,\n\t\t\t\t\t'afterMutation',\n\t\t\t\t);\n\t\t\t\tif (action === 'continue') continue;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\treturn current;\n}\n\n/**\n * @internal\n * Runs onError hooks. Returns transformed error or original.\n */\nexport async function runOnErrorHooks(\n\thooks: readonly OnErrorHook[],\n\tctx: ErrorHookContext,\n): Promise<Error> {\n\tlet currentError = ctx.error;\n\tfor (const hook of hooks) {\n\t\tconst frozen = Object.freeze({ ...ctx, error: currentError });\n\t\ttry {\n\t\t\tconst result = await hook(frozen);\n\t\t\tif (result instanceof Error) {\n\t\t\t\tcurrentError = result;\n\t\t\t}\n\t\t} catch {\n\t\t\t// onError hooks should not throw; if they do, ignore and continue\n\t\t}\n\t}\n\treturn currentError;\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\n/**\n * Creates a new HookManager instance for registering query/mutation hooks.\n *\n * @example\n * ```typescript\n * const hooks = createHookManager()\n * .beforeQuery(ctx => { console.log(ctx.table); return ctx; })\n * .afterQuery((ctx, results) => results);\n * ```\n */\nexport function createHookManager(): HookManager {\n\treturn new HookManagerImpl();\n}\n","/**\n * @module subquery-builder\n * Subquery builder for scalar subquery expressions in WHERE clauses.\n * DX-012 Block 3\n */\n\nimport type {\n\tComparisonOperator,\n\tQueryIntent,\n\tSubqueryRefIntent,\n\tWhereIntent,\n\tWhereSubqueryIntent,\n} from '../intent-ast.js';\nimport type { ExpressionSpec } from './types.js';\n\n// ============================================================================\n// Subquery Builder\n// ============================================================================\n\n/**\n * Fluent builder for scalar subqueries.\n * Produces a SubqueryExpression that can be used with comparison operators.\n *\n * @example\n * // Basic scalar subquery\n * query('products')\n * .where({ price: { $eq: subquery('prices').select('max_price').where({ categoryId: outerRef('categoryId') }) } })\n *\n * // With aggregate\n * query('products')\n * .where({ avgRating: { $gt: subquery('reviews').where({ productId: outerRef('id') }).avg('rating') } })\n */\nexport class SubqueryBuilder {\n\tprivate readonly _from: string;\n\tprivate _select?: string;\n\tprivate _where?: WhereIntent;\n\tprivate _aggregate?: {\n\t\tfn: 'count' | 'sum' | 'avg' | 'min' | 'max';\n\t\tfield: string;\n\t};\n\n\tconstructor(table: string) {\n\t\tthis._from = table;\n\t}\n\n\t/**\n\t * Specify the field to select from the subquery.\n\t * For scalar subqueries, this should be a single field.\n\t */\n\tselect(field: string): SubqueryBuilder {\n\t\tconst clone = this.clone();\n\t\tclone._select = field;\n\t\treturn clone;\n\t}\n\n\t/**\n\t * Add a WHERE condition to the subquery.\n\t * Can include outerRef() to create correlated subqueries.\n\t */\n\twhere(condition: WhereIntent): SubqueryBuilder {\n\t\tconst clone = this.clone();\n\t\tclone._where = condition;\n\t\treturn clone;\n\t}\n\n\t// ========================================================================\n\t// Aggregate Methods\n\t// ========================================================================\n\n\t/**\n\t * COUNT aggregate - count rows in subquery\n\t */\n\tcount(field = '*'): SubqueryExpression {\n\t\tconst clone = this.clone();\n\t\tclone._aggregate = { fn: 'count', field };\n\t\treturn clone.build();\n\t}\n\n\t/**\n\t * SUM aggregate - sum values in subquery\n\t */\n\tsum(field: string): SubqueryExpression {\n\t\tconst clone = this.clone();\n\t\tclone._aggregate = { fn: 'sum', field };\n\t\treturn clone.build();\n\t}\n\n\t/**\n\t * AVG aggregate - average values in subquery\n\t */\n\tavg(field: string): SubqueryExpression {\n\t\tconst clone = this.clone();\n\t\tclone._aggregate = { fn: 'avg', field };\n\t\treturn clone.build();\n\t}\n\n\t/**\n\t * MIN aggregate - minimum value in subquery\n\t */\n\tmin(field: string): SubqueryExpression {\n\t\tconst clone = this.clone();\n\t\tclone._aggregate = { fn: 'min', field };\n\t\treturn clone.build();\n\t}\n\n\t/**\n\t * MAX aggregate - maximum value in subquery\n\t */\n\tmax(field: string): SubqueryExpression {\n\t\tconst clone = this.clone();\n\t\tclone._aggregate = { fn: 'max', field };\n\t\treturn clone.build();\n\t}\n\n\t// ========================================================================\n\t// Build Methods\n\t// ========================================================================\n\n\t/**\n\t * Build the SubqueryExpression for use in WHERE conditions.\n\t * Called automatically by aggregate methods or explicitly when using select().\n\t */\n\tbuild(): SubqueryExpression {\n\t\tif (!this._select && !this._aggregate) {\n\t\t\tthrow new Error(\n\t\t\t\t'Subquery must have either select() or an aggregate function',\n\t\t\t);\n\t\t}\n\n\t\t// Build a full QueryIntent — subqueries are queries with contextual validation\n\t\tconst selectField = this._select ?? this._aggregate?.field ?? '*';\n\n\t\tconst intent: QueryIntent = {\n\t\t\ttype: 'select',\n\t\t\tfrom: this._from,\n\t\t\t// Aggregate overrides plain field select\n\t\t\tselect: this._aggregate\n\t\t\t\t? {\n\t\t\t\t\t\ttype: 'aggregate',\n\t\t\t\t\t\taggregates: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfunction: this._aggregate.fn,\n\t\t\t\t\t\t\t\tfield: this._aggregate.field,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t}\n\t\t\t\t: { type: 'fields', fields: [selectField] },\n\t\t\t...(this._where && { where: this._where }),\n\t\t};\n\n\t\treturn new SubqueryExpression(intent);\n\t}\n\n\t/**\n\t * Get the intent for debugging/inspection.\n\t */\n\tdump(): QueryIntent {\n\t\treturn this.build().toIntent();\n\t}\n\n\t/**\n\t * Wrap this subquery as an ExpressionSpec for use as a SELECT column.\n\t * Shorthand for `.build().asExpr(alias)`.\n\t *\n\t * @param alias - Column alias for the result\n\t * @returns ExpressionSpec suitable for passing to .columns()\n\t *\n\t * @example\n\t * // SELECT id, (SELECT count(*) FROM calls WHERE symbol_id = s.id) AS call_count\n\t * query('symbols').columns([\n\t * 'id',\n\t * subquery('calls').where({ symbolId: outerRef('id') }).count().asExpr('call_count'),\n\t * ])\n\t */\n\tasExpr(alias: string): ExpressionSpec {\n\t\treturn this.build().asExpr(alias);\n\t}\n\n\t/**\n\t * Create a clone of this builder (immutable pattern).\n\t */\n\tprivate clone(): SubqueryBuilder {\n\t\tconst clone = new SubqueryBuilder(this._from);\n\t\tif (this._select !== undefined) clone._select = this._select;\n\t\tif (this._where !== undefined) clone._where = this._where;\n\t\tif (this._aggregate !== undefined) clone._aggregate = this._aggregate;\n\t\treturn clone;\n\t}\n}\n\n// ============================================================================\n// Subquery Expression\n// ============================================================================\n\n/**\n * Result of building a subquery.\n * This can be used as a value in comparison operations.\n */\nexport class SubqueryExpression {\n\treadonly _type = 'subquery' as const;\n\treadonly intent: QueryIntent;\n\n\tconstructor(intent: QueryIntent) {\n\t\tthis.intent = intent;\n\t}\n\n\t/**\n\t * Get the underlying intent.\n\t */\n\ttoIntent(): QueryIntent {\n\t\treturn this.intent;\n\t}\n\n\t/**\n\t * Create a WhereSubqueryIntent for comparison.\n\t * Used internally by object filter syntax.\n\t */\n\ttoWhereIntent(\n\t\tfield: string,\n\t\toperator: ComparisonOperator,\n\t): WhereSubqueryIntent {\n\t\treturn {\n\t\t\tkind: 'subquery',\n\t\t\tfield,\n\t\t\toperator,\n\t\t\tsubquery: this.intent,\n\t\t};\n\t}\n\n\t/**\n\t * Wrap this subquery as an ExpressionSpec for use as a SELECT column.\n\t *\n\t * @param alias - Column alias for the result (required: SELECT expressions need a name)\n\t * @returns ExpressionSpec suitable for passing to .columns()\n\t *\n\t * @example\n\t * // SELECT id, (SELECT count(*) FROM calls WHERE calls.symbol_id = s.id) AS call_count\n\t * // FROM symbols s\n\t * query('symbols').columns([\n\t * 'id',\n\t * subquery('calls').count().asExpr('call_count'),\n\t * ])\n\t */\n\tasExpr(alias: string): ExpressionSpec {\n\t\treturn {\n\t\t\t__expr: true,\n\t\t\tintent: { kind: 'subquery', query: this.intent, as: alias },\n\t\t};\n\t}\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Create a scalar subquery builder.\n *\n * @param table - Table name for the subquery\n * @returns SubqueryBuilder for method chaining\n *\n * @example\n * // Find products where price equals max price in category\n * query('products').where({\n * price: {\n * $eq: subquery('products')\n * .select('price')\n * .where({ categoryId: outerRef('categoryId') })\n * .max('price')\n * }\n * })\n */\nexport function subquery(table: string): SubqueryBuilder {\n\treturn new SubqueryBuilder(table);\n}\n\n/**\n * Create a reference to a parent query column.\n * Used in subquery WHERE conditions to create correlated subqueries.\n *\n * @param column - Column name (e.g., 'id') or qualified name (e.g., 't0.id')\n * @returns SubqueryRefIntent\n *\n * @example\n * // Reference parent 'id' column in subquery\n * subquery('reviews').where({ productId: outerRef('id') })\n */\nexport function outerRef(column: string): SubqueryRefIntent {\n\t// `outer: true` is the discriminator that distinguishes this genuine\n\t// outer-query reference from an inner `ref()` (RefExpressionIntent), which\n\t// has the same structural shape `{ kind: 'ref', column }`. Without the\n\t// marker, any subquery using `ref('a').gt(ref('b'))` as an inner WHERE\n\t// condition would be falsely rejected as \"correlated subquery not supported\".\n\t//\n\t// `SubqueryRefIntent` now declares `readonly outer?: true` so the object\n\t// literal is type-safe and no cast is needed.\n\treturn {\n\t\tkind: 'ref',\n\t\tcolumn,\n\t\touter: true,\n\t};\n}\n\n// ============================================================================\n// Type Guard\n// ============================================================================\n\n/**\n * Check if a value is a SubqueryExpression.\n * Used to detect subqueries in object filter processing.\n */\nexport function isSubqueryExpression(\n\tvalue: unknown,\n): value is SubqueryExpression {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'_type' in value &&\n\t\t(value as Record<string, unknown>)._type === 'subquery'\n\t);\n}\n","/**\n * @module object-filter\n * Object filter syntax for ergonomic WHERE clause building.\n *\n * Converts Prisma/Drizzle-like object syntax to WhereIntent:\n * - `{ status: 'active' }` → `eq('status', 'active')`\n * - `{ age: { $gt: 18 } }` → `gt('age', 18)`\n * - `{ status: 'active', role: 'admin' }` → `and(eq('status', 'active'), eq('role', 'admin'))`\n *\n * @example\n * ```typescript\n * import { createOrm } from '@dbsp/core';\n *\n * // Object syntax (new)\n * orm.select('users').where({ status: 'active', age: { $gte: 18 } })\n *\n * // Equivalent to (legacy)\n * orm.select('users').where(and(eq('status', 'active'), gte('age', 18)))\n * ```\n */\n\nimport type {\n\tComparisonOperator,\n\tWhereAndIntent,\n\tWhereComparisonIntent,\n\tWhereInIntent,\n\tWhereIntent,\n\tWhereLikeIntent,\n\tWhereNullIntent,\n\tWhereSubqueryIntent,\n} from '../intent-ast.js';\nimport { InvalidOperationError } from './errors.js';\nimport {\n\tisSubqueryExpression,\n\ttype SubqueryExpression,\n} from './subquery-builder.js';\n\n// ============================================================================\n// Operator Types\n// ============================================================================\n\n/**\n * Comparison operators for object filter syntax.\n * Use `$` prefix to distinguish from field names.\n * Values can be literal values or SubqueryExpression for scalar subqueries.\n */\nexport interface FilterOperators<T = unknown> {\n\t/** Equals (explicit) - value or subquery */\n\treadonly $eq?: T | SubqueryExpression;\n\t/** Not equals - value or subquery */\n\treadonly $neq?: T | SubqueryExpression;\n\t/** Greater than - value or subquery */\n\treadonly $gt?: T | SubqueryExpression;\n\t/** Greater than or equal - value or subquery */\n\treadonly $gte?: T | SubqueryExpression;\n\t/** Less than - value or subquery */\n\treadonly $lt?: T | SubqueryExpression;\n\t/** Less than or equal - value or subquery */\n\treadonly $lte?: T | SubqueryExpression;\n\t/** In array */\n\treadonly $in?: readonly T[];\n\t/** LIKE pattern matching */\n\treadonly $like?: string;\n\t/** Case-insensitive LIKE (ILIKE in PostgreSQL) */\n\treadonly $ilike?: string;\n\t/** IS NOT NULL check */\n\treadonly $notNull?: true;\n}\n\n/**\n * Filter value for a single field.\n * Can be:\n * - Direct value (equality)\n * - null (IS NULL)\n * - Operator object ({ $gt: 18 })\n */\nexport type FilterValue<T = unknown> = T | null | FilterOperators<T>;\n\n/**\n * Object filter type for WHERE clause.\n * Maps field names to filter values.\n *\n * @typeParam T - The row type for type-safe field names.\n *\n * @example\n * ```typescript\n * // Simple equality\n * const filter: WhereFilter<User> = { status: 'active' };\n *\n * // With operators\n * const filter: WhereFilter<User> = {\n * status: 'active',\n * age: { $gte: 18 },\n * email: { $like: '%@example.com' },\n * };\n * ```\n */\nexport type WhereFilter<T = Record<string, unknown>> = {\n\treadonly [K in keyof T]?: FilterValue<T[K]>;\n};\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Check if a value is a WhereIntent (not an object filter).\n */\nexport function isWhereIntent(value: unknown): value is WhereIntent {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t'kind' in value &&\n\t\ttypeof (value as Record<string, unknown>).kind === 'string'\n\t);\n}\n\n/**\n * Check if a value is an operator object (has $-prefixed keys).\n */\nfunction isOperatorObject(value: unknown): value is FilterOperators {\n\tif (typeof value !== 'object' || value === null) {\n\t\treturn false;\n\t}\n\tconst keys = Object.keys(value);\n\treturn keys.length > 0 && keys.every((k) => k.startsWith('$'));\n}\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\n/**\n * Convert a single field-value pair to WhereIntent.\n */\nfunction convertFieldValue(field: string, value: FilterValue): WhereIntent {\n\t// Handle null → isNull\n\tif (value === null) {\n\t\treturn {\n\t\t\tkind: 'null',\n\t\t\tfield,\n\t\t\toperator: 'isNull',\n\t\t} satisfies WhereNullIntent;\n\t}\n\n\t// Handle operator object\n\tif (isOperatorObject(value)) {\n\t\treturn convertOperatorObject(field, value);\n\t}\n\n\t// Handle direct value → equality\n\treturn {\n\t\tkind: 'comparison',\n\t\tfield,\n\t\toperator: 'eq',\n\t\tvalue,\n\t} satisfies WhereComparisonIntent;\n}\n\n/**\n * Create a comparison intent (value or subquery).\n */\nfunction createComparisonIntent(\n\tfield: string,\n\toperator: ComparisonOperator,\n\tvalue: unknown,\n): WhereIntent {\n\tif (isSubqueryExpression(value)) {\n\t\treturn value.toWhereIntent(field, operator) satisfies WhereSubqueryIntent;\n\t}\n\treturn {\n\t\tkind: 'comparison',\n\t\tfield,\n\t\toperator,\n\t\tvalue,\n\t} satisfies WhereComparisonIntent;\n}\n\n/**\n * Convert an operator object to WhereIntent.\n */\nfunction convertOperatorObject(\n\tfield: string,\n\tops: FilterOperators,\n): WhereIntent {\n\tconst conditions: WhereIntent[] = [];\n\n\t// $eq\n\tif (Object.hasOwn(ops, '$eq') && ops.$eq !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'eq', ops.$eq));\n\t}\n\n\t// $neq\n\tif (Object.hasOwn(ops, '$neq') && ops.$neq !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'neq', ops.$neq));\n\t}\n\n\t// $gt\n\tif (Object.hasOwn(ops, '$gt') && ops.$gt !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'gt', ops.$gt));\n\t}\n\n\t// $gte\n\tif (Object.hasOwn(ops, '$gte') && ops.$gte !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'gte', ops.$gte));\n\t}\n\n\t// $lt\n\tif (Object.hasOwn(ops, '$lt') && ops.$lt !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'lt', ops.$lt));\n\t}\n\n\t// $lte\n\tif (Object.hasOwn(ops, '$lte') && ops.$lte !== undefined) {\n\t\tconditions.push(createComparisonIntent(field, 'lte', ops.$lte));\n\t}\n\n\t// $in\n\tif (Object.hasOwn(ops, '$in') && ops.$in !== undefined) {\n\t\tconditions.push({\n\t\t\tkind: 'in',\n\t\t\tfield,\n\t\t\tvalues: ops.$in,\n\t\t} satisfies WhereInIntent);\n\t}\n\n\t// $like\n\tif (Object.hasOwn(ops, '$like') && ops.$like !== undefined) {\n\t\tconditions.push({\n\t\t\tkind: 'like',\n\t\t\tfield,\n\t\t\tpattern: ops.$like,\n\t\t} satisfies WhereLikeIntent);\n\t}\n\n\t// $ilike (case-insensitive)\n\tif (Object.hasOwn(ops, '$ilike') && ops.$ilike !== undefined) {\n\t\tconditions.push({\n\t\t\tkind: 'like',\n\t\t\tfield,\n\t\t\tpattern: ops.$ilike,\n\t\t\tcaseInsensitive: true,\n\t\t} satisfies WhereLikeIntent);\n\t}\n\n\t// $notNull\n\tif (Object.hasOwn(ops, '$notNull') && ops.$notNull === true) {\n\t\tconditions.push({\n\t\t\tkind: 'null',\n\t\t\tfield,\n\t\t\toperator: 'isNotNull',\n\t\t} satisfies WhereNullIntent);\n\t}\n\n\t// Return single condition or AND\n\tif (conditions.length === 0) {\n\t\tthrow new Error(\n\t\t\t`Invalid filter: operator object for field \"${field}\" has no recognized operators`,\n\t\t);\n\t}\n\n\tif (conditions.length === 1) {\n\t\t// Type assertion safe: length check guarantees element exists\n\t\treturn conditions[0] as WhereIntent;\n\t}\n\n\treturn { kind: 'and', conditions } satisfies WhereAndIntent;\n}\n\n// Keys that must never appear in a filter object — they target prototype slots\n// and can poison object properties on older engines. Defined at module scope\n// so the Set is allocated once, not per call.\nconst FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\n\n/**\n * Convert an object filter to WhereIntent.\n *\n * @param filter - Object filter with field-value pairs\n * @returns WhereIntent for use in QueryBuilder.where()\n *\n * @example\n * ```typescript\n * // Single field\n * objectToWhereIntent({ status: 'active' })\n * // → { kind: 'comparison', field: 'status', operator: 'eq', value: 'active' }\n *\n * // Multiple fields (AND)\n * objectToWhereIntent({ status: 'active', role: 'admin' })\n * // → { kind: 'and', conditions: [...] }\n *\n * // With operators\n * objectToWhereIntent({ age: { $gte: 18, $lt: 65 } })\n * // → { kind: 'and', conditions: [gte, lt] }\n * ```\n */\nexport function objectToWhereIntent(\n\tfilter: WhereFilter<Record<string, unknown>>,\n): WhereIntent {\n\t// FIND-005: Reject prototype-poisoning keys before any processing.\n\t// Object.keys() already returns only own enumerable properties — the\n\t// hasOwn check below was redundant and has been removed.\n\tfor (const key of Object.keys(filter)) {\n\t\tif (FORBIDDEN_KEYS.has(key)) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'where',\n\t\t\t\t`Filter key not allowed: ${key}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst entries = Object.entries(filter);\n\n\tif (entries.length === 0) {\n\t\tthrow new Error('Invalid filter: empty object');\n\t}\n\n\tconst conditions: WhereIntent[] = entries.map(([field, value]) =>\n\t\tconvertFieldValue(field, value as FilterValue),\n\t);\n\n\t// Single condition → return directly\n\tif (conditions.length === 1) {\n\t\t// Type assertion safe: length check guarantees element exists\n\t\treturn conditions[0] as WhereIntent;\n\t}\n\n\t// Multiple conditions → AND\n\treturn { kind: 'and', conditions } satisfies WhereAndIntent;\n}\n","/**\n * @fileoverview Core DX layer type definitions.\n *\n * Contains shared types used across the query builder, ORM instance,\n * and other DX components: column specs, ordering, includes, hierarchy, etc.\n *\n * Split files are re-exported for backward compatibility:\n * - pagination-types.ts: Pagination and streaming types\n * - query-builder-types.ts: QueryBuilder interface\n * - orm-instance-types.ts: OrmInstance and OrmOptions\n *\n * @module types\n * @since DX-001\n */\n\nimport type {\n\tExpressionIntent,\n\tSelectIntent,\n\tWhereIntent,\n} from '../intent-ast.js';\n\n// ============================================================================\n// Re-exports from split files (backward compatibility)\n// ============================================================================\n\nexport type {\n\tOrmInstance,\n\tOrmInstanceInternal,\n\tOrmOptions,\n\tOrmOptionsWithAdapter,\n\tOrmOptionsWithModel,\n\tOrmOptionsWithSchema,\n\tSelectExpressionResult,\n} from './orm-instance-types.js';\nexport type {\n\tCursorPaginatedResult,\n\tCursorPaginateOptions,\n\tPaginatedResult,\n\tPaginateOptions,\n\tStreamOptions,\n} from './pagination-types.js';\nexport type { DumpMetaInput, QueryBuilder } from './query-builder-types.js';\n\n// ============================================================================\n// Expression & Column Types\n// ============================================================================\n\n/**\n * A wrapper around an ExpressionIntent that marks it for use in columns().\n * The __expr marker allows runtime detection of expression vs string columns.\n *\n * Create these using helper functions like coalesce() or raw().\n */\nexport interface ExpressionSpec {\n\treadonly __expr: true;\n\treadonly intent: ExpressionIntent;\n}\n\n/**\n * An ExpressionSpec that carries its alias as a phantom type parameter.\n * This allows .columns() to extend the result type with the aliased property.\n *\n * Created by relationColumn(relation, column, alias) when the alias is a\n * string literal — TypeScript captures the exact string type, enabling\n * .columns() to extend TResult with { [alias]: TValue }.\n *\n * @typeParam TAlias - The string literal type of the alias\n * @typeParam TValue - The value type (defaults to unknown)\n */\nexport interface AliasedExprColumn<TAlias extends string, TValue = unknown>\n\textends ExpressionSpec {\n\t/** @internal phantom brand — never set at runtime */\n\treadonly __alias: TAlias;\n\t/** @internal phantom brand — never set at runtime */\n\treadonly __value: TValue;\n}\n\n/**\n * A column specification - either a field name or an expression.\n *\n * @example\n * ```typescript\n * // Simple field\n * 'id'\n *\n * // Expression (via coalesce helper)\n * coalesce(['name_fr', 'name_en'], 'name')\n * ```\n */\nexport type ColumnSpec = string | ExpressionSpec;\n\n/**\n * Type guard to check if a ColumnSpec is an ExpressionSpec.\n */\nexport function isExpressionSpec(spec: ColumnSpec): spec is ExpressionSpec {\n\treturn (\n\t\ttypeof spec === 'object' &&\n\t\tspec !== null &&\n\t\t'__expr' in spec &&\n\t\tspec.__expr === true\n\t);\n}\n\n// ============================================================================\n// Aggregate Types\n// ============================================================================\n\n/**\n * Options for aggregate functions.\n */\nexport interface AggregateOptions {\n\t/**\n\t * Field to aggregate (required for SUM, AVG, MIN, MAX; optional for COUNT).\n\t */\n\treadonly field?: string;\n\t/**\n\t * Alias for the result column.\n\t */\n\treadonly as?: string;\n}\n\n// ============================================================================\n// Relation Hints\n// ============================================================================\n\n/**\n * Mapping of target table to preferred relation name.\n * Used to resolve ambiguous relations automatically.\n *\n * @example\n * ```typescript\n * const hints: RelationHints = {\n * posts: 'authoredPosts', // When including 'posts', use 'authoredPosts' relation\n * };\n * ```\n */\nexport type RelationHints = Readonly<Record<string, string>>;\n\n// ============================================================================\n// OrderBy Shorthand Types (DX-024)\n// ============================================================================\n\n/**\n * Sort direction for orderBy (re-exported from @dbsp/types).\n */\nimport type { SortDirection } from '@dbsp/types';\n\nexport type { SortDirection } from '@dbsp/types';\n\n/**\n * Where to place NULL values in sort order.\n */\nexport type NullsPosition = 'first' | 'last';\n\n/**\n * Object form for orderBy - map of field to direction.\n *\n * @example\n * ```typescript\n * { created_at: 'desc', name: 'asc' }\n * ```\n */\nexport type OrderByRecord = Readonly<Record<string, SortDirection>>;\n\n/**\n * Advanced orderBy specification with nulls handling.\n *\n * @example\n * ```typescript\n * { column: 'created_at', direction: 'desc', nulls: 'last' }\n * ```\n */\nexport interface OrderBySpec {\n\treadonly column: string;\n\treadonly direction?: SortDirection;\n\treadonly nulls?: NullsPosition;\n}\n\n/**\n * All valid orderBy input types.\n */\nexport type OrderByInput =\n\t| string // Simple: 'field'\n\t| OrderByRecord // Object: { field: 'desc' }\n\t| readonly OrderBySpec[]; // Array: [{ column, direction, nulls }]\n\n// ============================================================================\n// Include Types\n// ============================================================================\n\n/**\n * Options for the include() method on QueryBuilder.\n * Maps to IncludeIntent fields with developer-friendly naming.\n */\nexport interface IncludeOptions {\n\t/**\n\t * Explicit relation name for disambiguation.\n\t * Use when multiple relations exist between same tables.\n\t *\n\t * @example\n\t * ```typescript\n\t * // User has authoredPosts and reviewedPosts relations to Post\n\t * query('users').include('posts', { via: 'authoredPosts' })\n\t * ```\n\t */\n\treadonly via?: string;\n\n\t/**\n\t * Filter conditions on related records.\n\t */\n\treadonly where?: WhereIntent;\n\n\t/**\n\t * What columns to select from related records.\n\t */\n\treadonly select?: SelectIntent;\n\n\t/**\n\t * Nested includes for deep loading.\n\t */\n\treadonly include?: readonly NestedInclude[];\n\n\t/**\n\t * Join type for the include when using the 'join' strategy.\n\t * - 'left' (default): LEFT JOIN — all root rows returned, NULL for unmatched relations\n\t * - 'inner': INNER JOIN — only root rows WITH a matching related record are returned\n\t *\n\t * Forces the 'join' include strategy (overrides auto-selection).\n\t *\n\t * @example\n\t * include('file', { join: 'inner' })\n\t * // → INNER JOIN files ON files.id = symbols.file_id\n\t */\n\treadonly join?: 'inner' | 'left';\n}\n\n/**\n * Options for recursive include traversal on self-referential relations.\n *\n * @example\n * ```typescript\n * // Traverse ancestors (nested format)\n * query('categories').where(eq('id', 5)).include('parent', {\n * recursive: true,\n * direction: 'ancestors'\n * })\n *\n * // Traverse descendants (flat format with depth)\n * query('categories').where(eq('id', 1)).include('children', {\n * recursive: true,\n * direction: 'descendants',\n * flat: true,\n * maxDepth: 10\n * })\n * ```\n */\nexport interface RecursiveIncludeOptions extends IncludeOptions {\n\t/**\n\t * Enable recursive CTE traversal.\n\t * MUST be `true` when using recursive options.\n\t */\n\treadonly recursive: true;\n\n\t/**\n\t * Direction of traversal.\n\t * - 'ancestors': Traverse up the hierarchy (parent → grandparent → ...)\n\t * - 'descendants': Traverse down the hierarchy (children → grandchildren → ...)\n\t *\n\t * REQUIRED when `recursive: true`.\n\t */\n\treadonly direction: 'ancestors' | 'descendants';\n\n\t/**\n\t * Output format.\n\t * - false (default): Nested object structure (parent: { parent: { ... } })\n\t * - true: Flat array with depth field ([{ id: 2, depth: 1 }, { id: 1, depth: 2 }])\n\t *\n\t * When flat=true, property is renamed: parent → ancestors, children → descendants\n\t */\n\treadonly flat?: boolean;\n\n\t/**\n\t * Exclude the source node from results.\n\t * @default false\n\t */\n\treadonly omitSelf?: boolean;\n\n\t/**\n\t * Maximum traversal depth.\n\t * @default 100 (safety limit)\n\t */\n\treadonly maxDepth?: number;\n\n\t/**\n\t * Include depth column in results.\n\t * Automatically true when flat=true.\n\t */\n\treadonly includeDepth?: boolean;\n}\n\n/**\n * Union type for include options: regular or recursive.\n */\nexport type IncludeOptionsWithRecursive =\n\t| IncludeOptions\n\t| RecursiveIncludeOptions;\n\n/**\n * Include with relation name for nested includes.\n * Used when building nested include hierarchies.\n */\nexport interface NestedInclude extends IncludeOptions {\n\t/**\n\t * The relation name or target table for this nested include.\n\t */\n\treadonly relation: string;\n}\n\n// ============================================================================\n// Hierarchy Types (DX-022)\n// ============================================================================\n\n/**\n * Options for hierarchy traversal shortcuts (ancestors, descendants, subtree).\n */\nexport interface HierarchyOptions {\n\t/**\n\t * The column that references the parent node (for adjacency list pattern).\n\t * @example 'parentCategoryId', 'parentId', 'managerId'\n\t */\n\treadonly parentId: string;\n\n\t/**\n\t * The column that identifies a node (default: 'id').\n\t */\n\treadonly nodeId?: string;\n\n\t/**\n\t * Optional CTE name (default: auto-generated based on table name).\n\t */\n\treadonly cteName?: string;\n}\n\n/**\n * Options for listAncestors/listDescendants methods (DX-022).\n * These methods execute immediately and return flat arrays.\n */\nexport interface ListHierarchyOptions {\n\t/**\n\t * The column that references the parent node (for adjacency list pattern).\n\t * This is used to auto-detect the self-referential relation.\n\t * @example 'parentCategoryId', 'parentId', 'managerId'\n\t */\n\treadonly parentId: string;\n\n\t/**\n\t * The column that identifies a node (default: 'id').\n\t */\n\treadonly nodeId?: string;\n\n\t/**\n\t * Maximum depth to traverse (default: 100).\n\t */\n\treadonly maxDepth?: number;\n}\n","/**\n * IntentBuilder - Builds QueryIntent AST from builder state.\n *\n * DX-103: Extracted from QueryBuilderImpl to separate intent construction\n * from execution, hydration, and other concerns.\n *\n * @module intent-builder\n */\n\nimport type { Mutable } from '@dbsp/types/internal';\nimport type {\n\tAggregateIntent,\n\tColumnExpressionIntent,\n\tExpressionIntent,\n\tIncludeIntent,\n\tIncludeRecursiveOptions,\n\tOrderByIntent,\n\tQueryIntent,\n\tSelectAggregateIntent,\n\tSelectIntent,\n\tWhereIntent,\n} from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\n\nimport { InvalidOperationError } from './errors.js';\nimport { and } from './filters.js';\nimport {\n\tisWhereIntent,\n\tobjectToWhereIntent,\n\ttype WhereFilter,\n} from './object-filter.js';\nimport {\n\ttype AggregateOptions,\n\ttype ColumnSpec,\n\ttype ExpressionSpec,\n\ttype IncludeOptionsWithRecursive,\n\tisExpressionSpec,\n\ttype NestedInclude,\n\ttype OrderByRecord,\n\ttype OrderBySpec,\n\ttype RecursiveIncludeOptions,\n\ttype RelationHints,\n\ttype SortDirection,\n} from './types.js';\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Check if options indicate a recursive include.\n */\nexport function isRecursiveIncludeOptions(\n\toptions?: IncludeOptionsWithRecursive,\n): options is RecursiveIncludeOptions {\n\treturn (\n\t\toptions !== undefined &&\n\t\t'recursive' in options &&\n\t\toptions.recursive === true\n\t);\n}\n\n/**\n * Convert IncludeOptions to IncludeIntent.\n * Handles exactOptionalPropertyTypes by only including defined properties.\n */\nexport function includeOptionsToIntent(\n\trelation: string,\n\toptions?: IncludeOptionsWithRecursive,\n): IncludeIntent {\n\tif (!options) {\n\t\treturn { relation };\n\t}\n\n\tconst intent: Mutable<IncludeIntent> = { relation };\n\n\tif (options.via !== undefined) {\n\t\tintent.via = options.via;\n\t}\n\tif (options.where !== undefined) {\n\t\tintent.where = options.where;\n\t}\n\tif (options.select !== undefined) {\n\t\tintent.select = options.select;\n\t}\n\tif (options.include !== undefined && options.include.length > 0) {\n\t\tintent.include = options.include.map((nested) =>\n\t\t\tnestedIncludeToIntent(nested),\n\t\t);\n\t}\n\n\tif (options.join !== undefined) {\n\t\tintent.join = options.join;\n\t}\n\n\t// Handle recursive options (DX-017)\n\tif (isRecursiveIncludeOptions(options)) {\n\t\tconst recursiveOpts: Mutable<IncludeRecursiveOptions> = {};\n\t\t// Only set maxDepth if defined\n\t\tif (options.maxDepth !== undefined) {\n\t\t\trecursiveOpts.maxDepth = options.maxDepth;\n\t\t}\n\t\t// Convert includeDepth to track.depth\n\t\tif (options.includeDepth) {\n\t\t\trecursiveOpts.track = { depth: true };\n\t\t}\n\t\tintent.recursive = recursiveOpts;\n\t}\n\n\treturn intent as IncludeIntent;\n}\n\n/**\n * Convert NestedInclude to IncludeIntent.\n */\nexport function nestedIncludeToIntent(nested: NestedInclude): IncludeIntent {\n\tconst intent: Mutable<IncludeIntent> = { relation: nested.relation };\n\n\tif (nested.via !== undefined) {\n\t\tintent.via = nested.via;\n\t}\n\tif (nested.where !== undefined) {\n\t\tintent.where = nested.where;\n\t}\n\tif (nested.select !== undefined) {\n\t\tintent.select = nested.select;\n\t}\n\tif (nested.include !== undefined && nested.include.length > 0) {\n\t\tintent.include = nested.include.map((n) => nestedIncludeToIntent(n));\n\t}\n\n\treturn intent as IncludeIntent;\n}\n\n/**\n * Parse dot notation include into nested IncludeIntent.\n *\n * @example\n * 'posts.comments.author' becomes:\n * { relation: 'posts', include: [{ relation: 'comments', include: [{ relation: 'author' }] }] }\n */\nexport function parseDotNotationInclude(\n\tpath: string,\n\toptions?: IncludeOptionsWithRecursive,\n): IncludeIntent {\n\tconst parts = path.split('.');\n\tif (parts.length === 0) {\n\t\tthrow new Error('Invalid include path');\n\t}\n\n\t// Build from the end (deepest level) to the beginning\n\t// Options apply to the deepest (last) relation\n\tconst lastPart = parts[parts.length - 1];\n\tif (!lastPart) {\n\t\tthrow new Error('Invalid include path: empty segment');\n\t}\n\tlet current: IncludeIntent = includeOptionsToIntent(lastPart, options);\n\n\t// Work backwards through the path, wrapping each level.\n\t// Propagate the `join` option to intermediate wrappers so the planner\n\t// picks the join strategy for ALL hops, not just the leaf.\n\t// Without this, `.include('a.b', {join:'inner'})` produces an outer 'a'\n\t// with no join → json_agg strategy → 'a' table not in outer FROM →\n\t// the leaf 'b' JOIN ON clause references a table missing from outer FROM.\n\tfor (let i = parts.length - 2; i >= 0; i--) {\n\t\tconst part = parts[i];\n\t\tif (!part) continue;\n\t\tcurrent =\n\t\t\toptions?.join !== undefined\n\t\t\t\t? { relation: part, join: options.join, include: [current] }\n\t\t\t\t: { relation: part, include: [current] };\n\t}\n\n\treturn current;\n}\n\n/**\n * Validate recursive include options.\n * Throws InvalidOperationError if:\n * - Relation is not self-referential (source !== target)\n * - Direction is missing\n * - Direction conflicts with relation cardinality\n */\nexport function validateRecursiveInclude(\n\tmodel: ModelIR,\n\tsourceTable: string,\n\trelationName: string,\n\toptions: RecursiveIncludeOptions,\n): void {\n\t// Get the relation from the model\n\tconst qualifiedName = `${sourceTable}.${relationName}`;\n\tconst relation = model.getRelation(qualifiedName);\n\n\tif (!relation) {\n\t\t// Let the planner handle the \"relation not found\" error\n\t\treturn;\n\t}\n\n\t// Check if direction is provided (INV-2)\n\tif (!options.direction) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'recursive include',\n\t\t\t`'direction' is required when using recursive: true. ` +\n\t\t\t\t`Use 'ancestors' for parent traversal or 'descendants' for children traversal.`,\n\t\t);\n\t}\n\n\t// Check if relation is self-referential (INV-1, PRE-1)\n\tif (relation.source !== relation.target) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'recursive include',\n\t\t\t`Recursive include requires a self-referential relation. ` +\n\t\t\t\t`Relation '${relationName}' connects '${relation.source}' to '${relation.target}', ` +\n\t\t\t\t`but both must be the same table for recursive traversal.`,\n\t\t);\n\t}\n\n\t// Check direction vs relation type (PRE-2, PRE-3, ERR-3)\n\t// ancestors requires belongsTo/hasOne (to-one), descendants requires hasMany (to-many)\n\tconst { direction } = options;\n\tconst relType = relation.type;\n\n\tif (direction === 'ancestors') {\n\t\t// ancestors traversal: follow the \"parent\" direction (N:1 or 1:1)\n\t\t// The relation should be belongsTo or hasOne (e.g., category -> parent category)\n\t\tif (relType === 'hasMany' || relType === 'belongsToMany') {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'recursive include',\n\t\t\t\t`Direction 'ancestors' requires a to-one relation (belongsTo or hasOne). ` +\n\t\t\t\t\t`Relation '${relationName}' has type '${relType}'. ` +\n\t\t\t\t\t`Use 'descendants' for hasMany/belongsToMany relations.`,\n\t\t\t);\n\t\t}\n\t} else if (direction === 'descendants') {\n\t\t// descendants traversal: follow the \"children\" direction (1:N)\n\t\t// The relation should be hasMany (e.g., category -> child categories)\n\t\tif (relType === 'belongsTo' || relType === 'hasOne') {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'recursive include',\n\t\t\t\t`Direction 'descendants' requires a to-many relation (hasMany). ` +\n\t\t\t\t\t`Relation '${relationName}' has type '${relType}'. ` +\n\t\t\t\t\t`Use 'ancestors' for belongsTo/hasOne relations.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\n// ============================================================================\n// RecursiveIncludeConfig\n// ============================================================================\n\n/**\n * Configuration for a recursive include.\n * Stores the relation name and recursive options for later processing.\n */\nexport interface RecursiveIncludeConfig {\n\treadonly relation: string;\n\treadonly options: RecursiveIncludeOptions;\n}\n\n// ============================================================================\n// IntentBuilderState\n// ============================================================================\n\n/**\n * Internal state for intent building.\n * Encapsulates all the mutable state that gets accumulated via builder methods.\n * Note: Optional properties explicitly allow undefined for exactOptionalPropertyTypes compliance.\n */\nexport interface IntentBuilderState {\n\treadonly from: string;\n\tselectIntent?: SelectIntent | undefined;\n\twhereIntents: WhereIntent[];\n\thavingIntents: WhereIntent[];\n\tincludes: IncludeIntent[];\n\trecursiveIncludes: RecursiveIncludeConfig[];\n\taggregates: AggregateIntent[];\n\tgroupByFields: string[];\n\torderByIntents: OrderByIntent[];\n\tlimitValue?: number | undefined;\n\toffsetValue?: number | undefined;\n\tisDistinct?: boolean | undefined;\n}\n\n// ============================================================================\n// IntentBuilder\n// ============================================================================\n\n/**\n * Builds QueryIntent AST from accumulated state.\n *\n * This class is responsible for:\n * - Accumulating filter, select, include, and ordering state\n * - Converting builder method calls to intent AST nodes\n * - Building the final QueryIntent for planning\n *\n * @typeParam TResult - The expected result type (for type inference)\n */\nexport class IntentBuilder<TResult = unknown> {\n\tprivate readonly model: ModelIR;\n\tprivate readonly relationHints: RelationHints;\n\treadonly state: IntentBuilderState;\n\n\tconstructor(\n\t\tmodel: ModelIR,\n\t\tfrom: string,\n\t\trelationHints: RelationHints = {},\n\t\tinitialState?: Partial<IntentBuilderState>,\n\t) {\n\t\tthis.model = model;\n\t\tthis.relationHints = relationHints;\n\t\tthis.state = {\n\t\t\tfrom,\n\t\t\twhereIntents: initialState?.whereIntents\n\t\t\t\t? [...initialState.whereIntents]\n\t\t\t\t: [],\n\t\t\thavingIntents: initialState?.havingIntents\n\t\t\t\t? [...initialState.havingIntents]\n\t\t\t\t: [],\n\t\t\tincludes: initialState?.includes ? [...initialState.includes] : [],\n\t\t\trecursiveIncludes: initialState?.recursiveIncludes\n\t\t\t\t? [...initialState.recursiveIncludes]\n\t\t\t\t: [],\n\t\t\taggregates: initialState?.aggregates ? [...initialState.aggregates] : [],\n\t\t\tgroupByFields: initialState?.groupByFields\n\t\t\t\t? [...initialState.groupByFields]\n\t\t\t\t: [],\n\t\t\torderByIntents: initialState?.orderByIntents\n\t\t\t\t? [...initialState.orderByIntents]\n\t\t\t\t: [],\n\t\t\tselectIntent: initialState?.selectIntent,\n\t\t\tlimitValue: initialState?.limitValue,\n\t\t\toffsetValue: initialState?.offsetValue,\n\t\t\tisDistinct: initialState?.isDistinct,\n\t\t};\n\t}\n\n\t/**\n\t * Add an include to the builder.\n\t */\n\taddInclude(relation: string, options?: IncludeOptionsWithRecursive): void {\n\t\t// Validate recursive includes (self-referential relations)\n\t\tif (isRecursiveIncludeOptions(options)) {\n\t\t\tvalidateRecursiveInclude(this.model, this.state.from, relation, options);\n\t\t\t// Note: recursive options are now converted to IncludeIntent.recursive\n\t\t\t// by includeOptionsToIntent, no longer stored separately\n\t\t}\n\n\t\t// Support dot notation for nested includes: 'posts.comments.author'\n\t\tif (relation.includes('.')) {\n\t\t\tthis.state.includes.push(parseDotNotationInclude(relation, options));\n\t\t} else {\n\t\t\tthis.state.includes.push(includeOptionsToIntent(relation, options));\n\t\t}\n\t}\n\n\t/**\n\t * Set column selection.\n\t */\n\tsetColumns(columns: readonly ColumnSpec[]): void {\n\t\t// Build columns array (direct ExpressionIntent format - NQL compatible)\n\t\tconst expressionColumns: ExpressionIntent[] = [];\n\t\tlet hasExpressions = false;\n\n\t\tfor (const col of columns) {\n\t\t\tif (isExpressionSpec(col)) {\n\t\t\t\thasExpressions = true;\n\t\t\t\texpressionColumns.push((col as ExpressionSpec).intent);\n\t\t\t} else {\n\t\t\t\t// Simple field → ColumnExpressionIntent (kind: 'column')\n\t\t\t\texpressionColumns.push({ kind: 'column', column: col as string });\n\t\t\t}\n\t\t}\n\n\t\t// Use SelectWithExpressionsIntent if we have any expressions\n\t\tif (hasExpressions) {\n\t\t\tthis.state.selectIntent = {\n\t\t\t\ttype: 'expressions',\n\t\t\t\tcolumns: expressionColumns,\n\t\t\t};\n\t\t} else {\n\t\t\t// Simple fields only - extract field names\n\t\t\tconst fields = expressionColumns.map(\n\t\t\t\t(c) => (c as ColumnExpressionIntent).column,\n\t\t\t);\n\t\t\tthis.state.selectIntent = { type: 'fields', fields };\n\t\t}\n\t}\n\n\t/**\n\t * Add a WHERE condition.\n\t */\n\taddWhere(condition: WhereIntent | WhereFilter<TResult>): void {\n\t\t// Convert object filter to WhereIntent if needed\n\t\tconst intent = isWhereIntent(condition)\n\t\t\t? condition\n\t\t\t: objectToWhereIntent(condition as WhereFilter<Record<string, unknown>>);\n\t\tthis.state.whereIntents.push(intent);\n\t}\n\n\t/**\n\t * Add an aggregate function.\n\t * DX-034: Now supports distinct flag for COUNT(DISTINCT field), etc.\n\t */\n\taddAggregate(\n\t\tfunc: 'count' | 'sum' | 'avg' | 'min' | 'max',\n\t\tfield?: string,\n\t\toptions?: AggregateOptions & { distinct?: boolean },\n\t): void {\n\t\tconst resolvedField = field ?? options?.field;\n\t\tconst as = options?.as;\n\t\tconst distinct = options?.distinct ? true : undefined;\n\n\t\tlet agg: AggregateIntent;\n\t\tif (func === 'count') {\n\t\t\t// count may omit field (defaults to '*')\n\t\t\tagg = {\n\t\t\t\tfunction: 'count',\n\t\t\t\t...(resolvedField !== undefined && { field: resolvedField }),\n\t\t\t\t...(as !== undefined && { as }),\n\t\t\t\t...(distinct !== undefined && { distinct }),\n\t\t\t};\n\t\t} else {\n\t\t\t// all other aggregates require field\n\t\t\tagg = {\n\t\t\t\tfunction: func,\n\t\t\t\tfield: resolvedField ?? '',\n\t\t\t\t...(as !== undefined && { as }),\n\t\t\t\t...(distinct !== undefined && { distinct }),\n\t\t\t};\n\t\t}\n\t\tthis.state.aggregates.push(agg);\n\t}\n\n\t/**\n\t * Add GROUP BY fields.\n\t */\n\taddGroupBy(fields: readonly string[]): void {\n\t\tthis.state.groupByFields.push(...fields);\n\t}\n\n\t/**\n\t * Add a HAVING condition for filtering on aggregates.\n\t * DX-034: HAVING is applied after GROUP BY.\n\t */\n\taddHaving(condition: WhereIntent): void {\n\t\tthis.state.havingIntents.push(condition);\n\t}\n\n\t/**\n\t * Set SELECT DISTINCT mode.\n\t * DX-034: Deduplicates result rows.\n\t */\n\tsetDistinct(value: boolean = true): void {\n\t\tthis.state.isDistinct = value;\n\t}\n\n\t/**\n\t * Add ORDER BY clauses.\n\t */\n\taddOrderBy(\n\t\tfieldOrRecordOrSpecs: string | OrderByRecord | readonly OrderBySpec[],\n\t\tdirection?: SortDirection,\n\t): void {\n\t\t// String form: orderBy('field') or orderBy('field', 'desc')\n\t\tif (typeof fieldOrRecordOrSpecs === 'string') {\n\t\t\tthis.state.orderByIntents.push({\n\t\t\t\tfield: fieldOrRecordOrSpecs,\n\t\t\t\tdirection: direction ?? 'asc',\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\t// Array form: orderBy([{ column, direction, nulls }])\n\t\tif (Array.isArray(fieldOrRecordOrSpecs)) {\n\t\t\tfor (const spec of fieldOrRecordOrSpecs) {\n\t\t\t\tthis.state.orderByIntents.push({\n\t\t\t\t\tfield: spec.column,\n\t\t\t\t\tdirection: spec.direction ?? 'asc',\n\t\t\t\t\tnulls: spec.nulls,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Object form: orderBy({ field1: 'desc', field2: 'asc' })\n\t\tfor (const [field, dir] of Object.entries(fieldOrRecordOrSpecs)) {\n\t\t\tthis.state.orderByIntents.push({\n\t\t\t\tfield,\n\t\t\t\tdirection: dir,\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Set LIMIT value.\n\t */\n\tsetLimit(count: number): void {\n\t\tthis.state.limitValue = count;\n\t}\n\n\t/**\n\t * Set OFFSET value.\n\t */\n\tsetOffset(count: number): void {\n\t\tthis.state.offsetValue = count;\n\t}\n\n\t/**\n\t * Build the QueryIntent from accumulated state.\n\t * Handles exactOptionalPropertyTypes by only including defined properties.\n\t */\n\tbuildIntent(): QueryIntent {\n\t\tconst intent: Mutable<QueryIntent> = {\n\t\t\ttype: 'select',\n\t\t\tfrom: this.state.from,\n\t\t};\n\n\t\t// Handle aggregates - convert to SelectAggregateIntent\n\t\tif (this.state.aggregates.length > 0) {\n\t\t\tconst aggregateSelect: Mutable<SelectAggregateIntent> = {\n\t\t\t\ttype: 'aggregate',\n\t\t\t\taggregates: [...this.state.aggregates],\n\t\t\t};\n\t\t\t// Add group by fields to the select for projection\n\t\t\tif (this.state.groupByFields.length > 0) {\n\t\t\t\taggregateSelect.fields = [...this.state.groupByFields];\n\t\t\t}\n\t\t\tintent.select = aggregateSelect as SelectAggregateIntent;\n\t\t} else if (this.state.selectIntent !== undefined) {\n\t\t\tintent.select = this.state.selectIntent;\n\t\t}\n\n\t\t// Combine multiple where conditions with AND\n\t\tif (this.state.whereIntents.length === 1) {\n\t\t\tconst singleWhere = this.state.whereIntents[0];\n\t\t\tif (singleWhere !== undefined) {\n\t\t\t\tintent.where = singleWhere;\n\t\t\t}\n\t\t} else if (this.state.whereIntents.length > 1) {\n\t\t\tintent.where = and(...this.state.whereIntents);\n\t\t}\n\n\t\tif (this.state.includes.length > 0) {\n\t\t\tintent.include = this.state.includes;\n\t\t}\n\n\t\tif (this.state.groupByFields.length > 0) {\n\t\t\tintent.groupBy = [...this.state.groupByFields];\n\t\t}\n\n\t\t// DX-034: HAVING clause for filtering on aggregates\n\t\tif (this.state.havingIntents.length === 1) {\n\t\t\tconst singleHaving = this.state.havingIntents[0];\n\t\t\tif (singleHaving !== undefined) {\n\t\t\t\tintent.having = singleHaving;\n\t\t\t}\n\t\t} else if (this.state.havingIntents.length > 1) {\n\t\t\tintent.having = and(...this.state.havingIntents);\n\t\t}\n\n\t\t// DX-034: SELECT DISTINCT\n\t\tif (this.state.isDistinct) {\n\t\t\tintent.distinct = true;\n\t\t}\n\n\t\tif (this.state.orderByIntents.length > 0) {\n\t\t\tintent.orderBy = [...this.state.orderByIntents];\n\t\t}\n\n\t\tif (this.state.limitValue !== undefined) {\n\t\t\tintent.limit = this.state.limitValue;\n\t\t}\n\n\t\tif (this.state.offsetValue !== undefined) {\n\t\t\tintent.offset = this.state.offsetValue;\n\t\t}\n\n\t\treturn intent as QueryIntent;\n\t}\n\n\t/**\n\t * Apply relation hints to includes that don't have explicit `via`.\n\t */\n\tapplyRelationHints(intent: QueryIntent): QueryIntent {\n\t\tif (!intent.include || Object.keys(this.relationHints).length === 0) {\n\t\t\treturn intent;\n\t\t}\n\n\t\tconst updatedIncludes = intent.include.map((inc) =>\n\t\t\tthis.applyHintToInclude(inc),\n\t\t);\n\n\t\treturn {\n\t\t\t...intent,\n\t\t\tinclude: updatedIncludes,\n\t\t};\n\t}\n\n\t/**\n\t * Apply relation hint to a single include (recursively).\n\t */\n\tprivate applyHintToInclude(inc: IncludeIntent): IncludeIntent {\n\t\t// If already has explicit via, don't override\n\t\tif (inc.via !== undefined) {\n\t\t\t// But still process nested includes\n\t\t\tif (inc.include && inc.include.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\t...inc,\n\t\t\t\t\tinclude: inc.include.map((nested) => this.applyHintToInclude(nested)),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn inc;\n\t\t}\n\n\t\t// Check if we have a hint for this target\n\t\tconst hint = this.relationHints[inc.relation];\n\t\tconst result: IncludeIntent = hint ? { ...inc, via: hint } : inc;\n\n\t\t// Process nested includes\n\t\tif (result.include && result.include.length > 0) {\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tinclude: result.include.map((nested) =>\n\t\t\t\t\tthis.applyHintToInclude(nested),\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Clone the current state for immutable builder pattern.\n\t */\n\tclone(): IntentBuilder<TResult> {\n\t\treturn new IntentBuilder<TResult>(\n\t\t\tthis.model,\n\t\t\tthis.state.from,\n\t\t\t{ ...this.relationHints },\n\t\t\t{\n\t\t\t\tselectIntent: this.state.selectIntent,\n\t\t\t\twhereIntents: [...this.state.whereIntents],\n\t\t\t\thavingIntents: [...this.state.havingIntents],\n\t\t\t\tincludes: [...this.state.includes],\n\t\t\t\trecursiveIncludes: [...this.state.recursiveIncludes],\n\t\t\t\taggregates: [...this.state.aggregates],\n\t\t\t\tgroupByFields: [...this.state.groupByFields],\n\t\t\t\torderByIntents: [...this.state.orderByIntents],\n\t\t\t\tlimitValue: this.state.limitValue,\n\t\t\t\toffsetValue: this.state.offsetValue,\n\t\t\t\tisDistinct: this.state.isDistinct,\n\t\t\t},\n\t\t);\n\t}\n}\n","/**\n * DX-023: Lightweight ModelIR Definition\n *\n * Provides a simplified API for defining relations when using Kysely's Database type.\n * Instead of verbose column definitions, developers can focus solely on relations\n * using shorthand syntax with automatic FK inference.\n *\n * @example\n * ```typescript\n * import { defineModel } from '@dbsp/core';\n *\n * interface Database {\n * users: { id: number; name: string; };\n * posts: { id: number; user_id: number; title: string; };\n * }\n *\n * const model = defineModel<Database>({\n * relations: {\n * 'users.posts': '1:N',\n * 'posts.author': ['N:1', 'users'],\n * },\n * });\n * ```\n */\n\nimport { singularize } from '../conventions.js';\nimport type {\n\tCardinality as ModelCardinality,\n\tModelIR,\n\tOptionality,\n\tRelationIR,\n\tRelationType,\n\tTableIR,\n} from '../index.js';\n\n// Re-export for backwards compatibility\nexport { singularize };\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Cardinality shorthand notation.\n *\n * | Shorthand | Relation Type | Source Side | Target Side |\n * |-----------|---------------|-------------|-------------|\n * | `'1:N'` | hasMany | one | many |\n * | `'N:1'` | belongsTo | many | one |\n * | `'1:1'` | hasOne | one | one |\n * | `'M:N'` | belongsToMany | many | many |\n */\nexport type CardinalityShorthand = '1:N' | 'N:1' | '1:1' | 'M:N';\n\n/**\n * Object form for relation definition with full control.\n */\nexport interface RelationObjectDef {\n\t/** Cardinality shorthand */\n\treadonly cardinality: CardinalityShorthand;\n\t/** Explicit foreign key column(s) */\n\treadonly fk?: string | readonly string[];\n\t/** Explicit target table (if different from inferred) */\n\treadonly target?: string;\n\t/** Junction table for M:N relations */\n\treadonly through?: string;\n}\n\n/**\n * Tuple form for relation definition: [cardinality, target]\n */\nexport type RelationTupleDef = readonly [CardinalityShorthand, string];\n\n/**\n * All supported forms for relation definition.\n *\n * - **Simple:** `'1:N'` - target inferred from relation name\n * - **Tuple:** `['N:1', 'users']` - explicit target\n * - **Object:** `{ cardinality: '1:N', fk: 'order_uuid' }` - full control\n */\nexport type RelationShorthand =\n\t| CardinalityShorthand\n\t| RelationTupleDef\n\t| RelationObjectDef;\n\n/**\n * Relation key format: `'sourceTable.relationName'`\n */\nexport type RelationKey<DB> =\n\tDB extends Record<string, unknown>\n\t\t? `${Extract<keyof DB, string>}.${string}`\n\t\t: string;\n\n/**\n * Lightweight relations definition with type-safe keys.\n */\nexport type LightweightRelationsDef<DB> = {\n\treadonly [K in RelationKey<DB>]?: RelationShorthand;\n};\n\n/**\n * Options for defineModel function.\n */\nexport interface DefineModelOptions<DB> {\n\t/** Relation definitions using shorthand syntax */\n\treadonly relations: LightweightRelationsDef<DB>;\n}\n\n// ============================================================================\n// Errors\n// ============================================================================\n\n/**\n * Error thrown when a relation definition is invalid.\n *\n * @example\n * ```typescript\n * defineModel<DB>({ relations: { 'users.posts': '2:N' } });\n * // Throws: InvalidRelationDefinitionError: Invalid cardinality '2:N'\n * ```\n */\nexport class InvalidRelationDefinitionError extends Error {\n\toverride readonly name = 'InvalidRelationDefinitionError' as const;\n\n\t/** The relation key that caused the error */\n\treadonly relationKey: string;\n\n\t/** Specific reason for the error */\n\treadonly reason: string;\n\n\t/** Suggested fix, if available */\n\treadonly suggestion?: string;\n\n\tconstructor(opts: {\n\t\trelationKey: string;\n\t\treason: string;\n\t\tsuggestion?: string;\n\t}) {\n\t\tlet message = `Invalid relation definition for '${opts.relationKey}': ${opts.reason}`;\n\t\tif (opts.suggestion) {\n\t\t\tmessage += `\\n\\nSuggestion: ${opts.suggestion}`;\n\t\t}\n\n\t\tsuper(message);\n\t\tthis.relationKey = opts.relationKey;\n\t\tthis.reason = opts.reason;\n\t\tif (opts.suggestion) {\n\t\t\tthis.suggestion = opts.suggestion;\n\t\t}\n\n\t\tObject.setPrototypeOf(this, InvalidRelationDefinitionError.prototype);\n\t}\n}\n\n// ============================================================================\n// Parsing\n// ============================================================================\n\n/**\n * Valid cardinality values.\n */\nconst VALID_CARDINALITIES = new Set<string>(['1:N', 'N:1', '1:1', 'M:N']);\n\n/**\n * Maps cardinality shorthand to relation type.\n */\nconst CARDINALITY_TO_TYPE: Record<CardinalityShorthand, RelationType> = {\n\t'1:N': 'hasMany',\n\t'N:1': 'belongsTo',\n\t'1:1': 'hasOne',\n\t'M:N': 'belongsToMany',\n};\n\n/**\n * Maps cardinality shorthand to ModelIR cardinality.\n * ModelIR uses 'one' or 'many' to describe the target side cardinality.\n */\nconst CARDINALITY_TO_MODEL: Record<CardinalityShorthand, ModelCardinality> = {\n\t'1:N': 'many', // Target side is many\n\t'N:1': 'one', // Target side is one\n\t'1:1': 'one', // Target side is one\n\t'M:N': 'many', // Target side is many\n};\n\n/**\n * Type guard for CardinalityShorthand.\n */\nexport function isCardinalityShorthand(\n\tvalue: unknown,\n): value is CardinalityShorthand {\n\treturn typeof value === 'string' && VALID_CARDINALITIES.has(value);\n}\n\n/**\n * Type guard for RelationTupleDef.\n */\nexport function isRelationTupleDef(value: unknown): value is RelationTupleDef {\n\treturn (\n\t\tArray.isArray(value) &&\n\t\tvalue.length === 2 &&\n\t\tisCardinalityShorthand(value[0]) &&\n\t\ttypeof value[1] === 'string'\n\t);\n}\n\n/**\n * Type guard for RelationObjectDef.\n */\nexport function isRelationObjectDef(\n\tvalue: unknown,\n): value is RelationObjectDef {\n\tif (typeof value !== 'object' || value === null || Array.isArray(value)) {\n\t\treturn false;\n\t}\n\tconst obj = value as Record<string, unknown>;\n\treturn isCardinalityShorthand(obj.cardinality);\n}\n\n/**\n * Parsed relation key information.\n */\nexport interface ParsedRelationKey {\n\treadonly sourceTable: string;\n\treadonly relationName: string;\n}\n\n/**\n * Parses a relation key into source table and relation name.\n *\n * @param key - The relation key in format 'sourceTable.relationName'\n * @returns Parsed key components\n * @throws InvalidRelationDefinitionError if key format is invalid\n */\nexport function parseRelationKey(key: string): ParsedRelationKey {\n\tconst dotIndex = key.indexOf('.');\n\tif (dotIndex === -1 || dotIndex === 0 || dotIndex === key.length - 1) {\n\t\tthrow new InvalidRelationDefinitionError({\n\t\t\trelationKey: key,\n\t\t\treason: \"Invalid key format. Expected 'sourceTable.relationName'\",\n\t\t\tsuggestion: \"Use format like 'users.posts' or 'posts.author'\",\n\t\t});\n\t}\n\n\treturn {\n\t\tsourceTable: key.slice(0, dotIndex),\n\t\trelationName: key.slice(dotIndex + 1),\n\t};\n}\n\n/**\n * Parsed relation definition.\n */\nexport interface ParsedRelationDef {\n\treadonly cardinality: CardinalityShorthand;\n\treadonly relationType: RelationType;\n\treadonly modelCardinality: ModelCardinality;\n\treadonly target: string | undefined;\n\treadonly fk: string | readonly string[] | undefined;\n\treadonly through: string | undefined;\n}\n\n/**\n * Parses a relation shorthand value into its components.\n *\n * @param key - The relation key for error messages\n * @param value - The relation shorthand value\n * @returns Parsed relation definition\n * @throws InvalidRelationDefinitionError if value is invalid\n */\nexport function parseRelationDef(\n\tkey: string,\n\tvalue: RelationShorthand,\n): ParsedRelationDef {\n\t// Form 1: Simple shorthand - '1:N'\n\tif (isCardinalityShorthand(value)) {\n\t\treturn {\n\t\t\tcardinality: value,\n\t\t\trelationType: CARDINALITY_TO_TYPE[value],\n\t\t\tmodelCardinality: CARDINALITY_TO_MODEL[value],\n\t\t\ttarget: undefined,\n\t\t\tfk: undefined,\n\t\t\tthrough: undefined,\n\t\t};\n\t}\n\n\t// Form 2: Tuple - ['N:1', 'users']\n\tif (isRelationTupleDef(value)) {\n\t\tconst [cardinality, target] = value;\n\t\treturn {\n\t\t\tcardinality,\n\t\t\trelationType: CARDINALITY_TO_TYPE[cardinality],\n\t\t\tmodelCardinality: CARDINALITY_TO_MODEL[cardinality],\n\t\t\ttarget,\n\t\t\tfk: undefined,\n\t\t\tthrough: undefined,\n\t\t};\n\t}\n\n\t// Form 3: Object - { cardinality: '1:N', fk: 'order_uuid' }\n\tif (isRelationObjectDef(value)) {\n\t\tconst { cardinality, fk, target, through } = value;\n\t\treturn {\n\t\t\tcardinality,\n\t\t\trelationType: CARDINALITY_TO_TYPE[cardinality],\n\t\t\tmodelCardinality: CARDINALITY_TO_MODEL[cardinality],\n\t\t\ttarget,\n\t\t\tfk,\n\t\t\tthrough,\n\t\t};\n\t}\n\n\t// Invalid format\n\tconst valueStr =\n\t\ttypeof value === 'object' ? JSON.stringify(value) : String(value);\n\tthrow new InvalidRelationDefinitionError({\n\t\trelationKey: key,\n\t\treason: `Invalid relation definition format: ${valueStr}`,\n\t\tsuggestion:\n\t\t\t\"Use one of: '1:N', ['N:1', 'targetTable'], or { cardinality: '1:N', fk: 'column' }\",\n\t});\n}\n\n// ============================================================================\n// FK Inference\n// ============================================================================\n\n/**\n * Infers the foreign key column name based on convention.\n *\n * Convention: `{singular_table_name}_id`\n *\n * For hasMany/hasOne (1:N, 1:1): FK is on target table, named after source\n * For belongsTo (N:1): FK is on source table, named after target\n * For belongsToMany (M:N): FKs are on junction table\n *\n * @param tableName - The table name to base the FK on\n * @returns Inferred FK column name\n */\nexport function inferForeignKey(tableName: string): string {\n\tconst singular = singularize(tableName);\n\t// Convert to snake_case if needed (handle camelCase table names)\n\tconst snakeCase = singular.replace(/([A-Z])/g, '_$1').toLowerCase();\n\t// Remove leading underscore if present\n\tconst cleanSnakeCase = snakeCase.startsWith('_')\n\t\t? snakeCase.slice(1)\n\t\t: snakeCase;\n\treturn `${cleanSnakeCase}_id`;\n}\n\n// ============================================================================\n// ModelIR Builder\n// ============================================================================\n\n/**\n * Builds a ModelIR from lightweight relation definitions.\n *\n * @param options - The defineModel options\n * @returns A ModelIR instance\n */\nexport function defineModel<DB = Record<string, unknown>>(\n\toptions: DefineModelOptions<DB>,\n): ModelIR {\n\tconst { relations } = options;\n\n\t// Collect all tables from relation keys\n\tconst tableNames = new Set<string>();\n\tconst relationEntries: Array<{\n\t\tkey: string;\n\t\tparsed: ParsedRelationKey;\n\t\tdef: ParsedRelationDef;\n\t}> = [];\n\n\t// First pass: parse all relation definitions and collect table names\n\tfor (const [key, value] of Object.entries(relations)) {\n\t\tif (value === undefined) continue;\n\n\t\tconst parsed = parseRelationKey(key);\n\t\tconst def = parseRelationDef(key, value as RelationShorthand);\n\n\t\ttableNames.add(parsed.sourceTable);\n\n\t\t// Determine target table\n\t\tlet target = def.target;\n\t\tif (target === undefined) {\n\t\t\t// Infer target from relation name\n\t\t\ttarget = parsed.relationName;\n\t\t}\n\t\ttableNames.add(target);\n\n\t\t// Validate M:N has through\n\t\tif (def.cardinality === 'M:N' && def.through === undefined) {\n\t\t\tthrow new InvalidRelationDefinitionError({\n\t\t\t\trelationKey: key,\n\t\t\t\treason:\n\t\t\t\t\t\"M:N relations require a 'through' option specifying the junction table\",\n\t\t\t\tsuggestion: `Use { cardinality: 'M:N', through: 'junction_table' }`,\n\t\t\t});\n\t\t}\n\n\t\t// Add junction table if M:N\n\t\tif (def.through !== undefined) {\n\t\t\ttableNames.add(def.through);\n\t\t}\n\n\t\trelationEntries.push({ key, parsed, def });\n\t}\n\n\t// Build tables map (minimal: just table name, no columns)\n\t// We infer that each table has an 'id' primary key by convention\n\tconst tables = new Map<string, TableIR>();\n\tfor (const name of tableNames) {\n\t\ttables.set(name, {\n\t\t\tname,\n\t\t\tcolumns: [],\n\t\t\tprimaryKey: 'id',\n\t\t\tforeignKeys: [],\n\t\t\tindexes: [],\n\t\t});\n\t}\n\n\t// Build relations map\n\tconst relationsMap = new Map<string, RelationIR>();\n\n\tfor (const { key, parsed, def } of relationEntries) {\n\t\t// Determine target\n\t\tconst target = def.target ?? parsed.relationName;\n\n\t\t// Determine FK\n\t\tlet foreignKey = def.fk;\n\t\tif (foreignKey === undefined) {\n\t\t\t// Infer FK based on relation type\n\t\t\tif (def.relationType === 'belongsTo') {\n\t\t\t\t// FK is on source table, named after target\n\t\t\t\tforeignKey = inferForeignKey(target);\n\t\t\t} else if (\n\t\t\t\tdef.relationType === 'hasMany' ||\n\t\t\t\tdef.relationType === 'hasOne'\n\t\t\t) {\n\t\t\t\t// FK is on target table, named after source\n\t\t\t\tforeignKey = inferForeignKey(parsed.sourceTable);\n\t\t\t}\n\t\t\t// For belongsToMany, FKs are typically inferred from the junction table\n\t\t\t// and would need explicit definition\n\t\t}\n\n\t\t// Determine optionality (default to optional for now)\n\t\tconst optionality: Optionality =\n\t\t\tdef.relationType === 'belongsTo' ? 'optional' : 'required';\n\n\t\tconst qualifiedName = key;\n\t\tconst relation: RelationIR = {\n\t\t\tname: parsed.relationName,\n\t\t\ttype: def.relationType,\n\t\t\tsource: parsed.sourceTable,\n\t\t\ttarget,\n\t\t\tthrough: def.through,\n\t\t\tforeignKey: foreignKey,\n\t\t\tcardinality: def.modelCardinality,\n\t\t\toptionality,\n\t\t\tincludeStrategy: 'auto',\n\t\t\tfilterStrategy: 'auto',\n\t\t\tjoinDefault: 'auto',\n\t\t};\n\n\t\trelationsMap.set(qualifiedName, relation);\n\t}\n\n\t// Create ModelIR implementation\n\treturn new LightweightModelIR(tables, relationsMap);\n}\n\n/**\n * Lightweight ModelIR implementation.\n */\nclass LightweightModelIR implements ModelIR {\n\treadonly tables: ReadonlyMap<string, TableIR>;\n\treadonly relations: ReadonlyMap<string, RelationIR>;\n\n\tconstructor(\n\t\ttables: ReadonlyMap<string, TableIR>,\n\t\trelations: ReadonlyMap<string, RelationIR>,\n\t) {\n\t\tthis.tables = tables;\n\t\tthis.relations = relations;\n\t}\n\n\tgetTable(name: string): TableIR | undefined {\n\t\treturn this.tables.get(name);\n\t}\n\n\tgetRelation(qualifiedName: string): RelationIR | undefined {\n\t\treturn this.relations.get(qualifiedName);\n\t}\n\n\tgetRelationsFrom(sourceTable: string): readonly RelationIR[] {\n\t\tconst result: RelationIR[] = [];\n\t\tfor (const [key, relation] of this.relations) {\n\t\t\tif (key.startsWith(`${sourceTable}.`)) {\n\t\t\t\tresult.push(relation);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tgetRelationsTo(targetTable: string): readonly RelationIR[] {\n\t\tconst result: RelationIR[] = [];\n\t\tfor (const relation of this.relations.values()) {\n\t\t\tif (relation.target === targetTable) {\n\t\t\t\tresult.push(relation);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tisAmbiguous(\n\t\tsourceTable: string,\n\t\ttargetTable: string,\n\t): { ambiguous: boolean; options: readonly string[] } {\n\t\tconst relationsToTarget: string[] = [];\n\t\tfor (const [key, relation] of this.relations) {\n\t\t\tif (\n\t\t\t\tkey.startsWith(`${sourceTable}.`) &&\n\t\t\t\trelation.target === targetTable\n\t\t\t) {\n\t\t\t\trelationsToTarget.push(relation.name);\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tambiguous: relationsToTarget.length > 1,\n\t\t\toptions: relationsToTarget,\n\t\t};\n\t}\n}\n","/**\n * @module mutation-builders\n * Mutation builders for insert, update, and delete operations.\n * Part of DX-010: Mutations.\n */\n\nimport type { Adapter, CompiledQuery, CompileOptions } from '../adapter.js';\nimport type {\n\tBatchUpdateIntent,\n\tDeleteIntent,\n\tInsertIntent,\n\tUpdateIntent,\n\tUpsertConflictAction,\n\tUpsertConflictTarget,\n\tUpsertIntent,\n\tWhereIntent,\n} from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport {\n\tExecutionError,\n\tInvalidOperationError,\n\tUnsafeOperationError,\n} from './errors.js';\nimport type {\n\tHookErrorHandler,\n\tHookStore,\n\tMutationHookContext,\n\tMutationOperation,\n} from './hooks.js';\nimport {\n\thasHooks,\n\trunAfterMutationHooks,\n\trunBeforeMutationHooks,\n\trunOnErrorHooks,\n\twithReentrancyGuard,\n} from './hooks.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Dump output for mutations.\n * Similar to query Dump but without plan (mutations don't use the planner).\n */\nexport interface MutationDump {\n\t/** Compiled SQL string */\n\treadonly sql: string;\n\t/** Bound parameter values */\n\treadonly parameters: readonly unknown[];\n\t/** The mutation intent */\n\treadonly intent:\n\t\t| InsertIntent\n\t\t| UpdateIntent\n\t\t| BatchUpdateIntent\n\t\t| DeleteIntent\n\t\t| UpsertIntent;\n\t/** Optional metadata */\n\treadonly meta?: {\n\t\treadonly schema?: string;\n\t\treadonly compiledAt?: Date;\n\t};\n}\n\n/** Shared base options for all mutation builders */\ntype MutationBaseOpts = {\n\ttable: string;\n\tmodel: ModelIR;\n\tadapter?: Adapter | undefined;\n\tschemaName?: string | undefined;\n\thookStore?: HookStore | undefined;\n\tonHookError?: HookErrorHandler | undefined;\n\tinTransaction?: boolean | undefined;\n};\n\n// ============================================================================\n// Abstract Base\n// ============================================================================\n\n/**\n * Abstract base class for mutation builders.\n * Consolidates shared fields, adapter validation, dump(), and execute() logic.\n *\n * Subclasses implement:\n * - `buildIntent()`: construct the mutation-specific intent\n * - `compileIntent()`: call the correct adapter.compile* method\n * - `operationName`: label used in error messages\n */\nabstract class MutationBuilderBase<\n\tT,\n\tTIntent extends\n\t\t| InsertIntent\n\t\t| UpdateIntent\n\t\t| BatchUpdateIntent\n\t\t| DeleteIntent\n\t\t| UpsertIntent,\n> {\n\tprotected readonly table: string;\n\tprotected readonly model: ModelIR;\n\tprotected readonly adapter: Adapter | undefined;\n\tprotected readonly schemaName: string | undefined;\n\tprotected readonly returningColumns: readonly string[] | undefined;\n\tprotected readonly hookStore: HookStore | undefined;\n\tprotected readonly onHookError: HookErrorHandler | undefined;\n\tprotected readonly inTransaction: boolean | undefined;\n\n\tprotected constructor(\n\t\topts: MutationBaseOpts & {\n\t\t\treturning?: readonly string[] | undefined;\n\t\t},\n\t) {\n\t\tthis.table = opts.table;\n\t\tthis.model = opts.model;\n\t\tthis.adapter = opts.adapter;\n\t\tthis.schemaName = opts.schemaName;\n\t\tthis.returningColumns = opts.returning;\n\t\tthis.hookStore = opts.hookStore;\n\t\tthis.onHookError = opts.onHookError;\n\t\tthis.inTransaction = opts.inTransaction;\n\t}\n\n\t/** Label used in ExecutionError messages (e.g. 'insert', 'update'). */\n\tprotected abstract readonly operationName: string;\n\n\t/** Construct the mutation-specific intent AST node. */\n\tprotected abstract buildIntent(): TIntent;\n\n\t/** Delegate to the adapter's mutation-specific compile method. */\n\tprotected abstract compileIntent(\n\t\tadapter: Adapter,\n\t\tintent: TIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery;\n\n\tprotected get baseOpts(): MutationBaseOpts {\n\t\treturn {\n\t\t\ttable: this.table,\n\t\t\tmodel: this.model,\n\t\t\tadapter: this.adapter,\n\t\t\tschemaName: this.schemaName,\n\t\t\thookStore: this.hookStore,\n\t\t\tonHookError: this.onHookError,\n\t\t\tinTransaction: this.inTransaction,\n\t\t};\n\t}\n\n\t/** Require a configured adapter or throw. */\n\tprotected requireAdapter(operation: string): Adapter {\n\t\tif (!this.adapter) {\n\t\t\tthrow new ExecutionError({\n\t\t\t\toperation,\n\t\t\t\treason: 'Adapter not configured',\n\t\t\t\tfix: 'Pass adapter option when creating ORM: createOrm({ model, adapter })',\n\t\t\t});\n\t\t}\n\t\treturn this.adapter;\n\t}\n\n\tdump(extraOptions?: CompileOptions): MutationDump {\n\t\tconst adapter = this.requireAdapter('dump');\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions: CompileOptions = {\n\t\t\t...(this.schemaName !== undefined && { schemaName: this.schemaName }),\n\t\t\t...extraOptions,\n\t\t};\n\t\tconst compiled = this.compileIntent(\n\t\t\tadapter,\n\t\t\tintent,\n\t\t\tObject.keys(compileOptions).length > 0 ? compileOptions : undefined,\n\t\t);\n\n\t\tconst meta: { compiledAt: Date; schema?: string } = {\n\t\t\tcompiledAt: new Date(),\n\t\t};\n\t\tif (this.schemaName !== undefined) {\n\t\t\tmeta.schema = this.schemaName;\n\t\t}\n\n\t\treturn {\n\t\t\tsql: compiled.sql,\n\t\t\tparameters: compiled.parameters,\n\t\t\tintent,\n\t\t\tmeta,\n\t\t};\n\t}\n\n\tasync execute(): Promise<T> {\n\t\tconst adapter = this.requireAdapter(this.operationName);\n\n\t\t// Fast path: no hooks registered\n\t\tif (!this.hookStore || !hasHooks(this.hookStore)) {\n\t\t\treturn this.executeWithoutHooks(adapter);\n\t\t}\n\n\t\treturn this.executeWithHooks(adapter);\n\t}\n\n\tprivate async executeWithoutHooks(adapter: Adapter): Promise<T> {\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions = this.schemaName\n\t\t\t? { schemaName: this.schemaName }\n\t\t\t: undefined;\n\t\tconst compiled = this.compileIntent(adapter, intent, compileOptions);\n\n\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\tconst result = await adapter.execute(compiled);\n\t\t\treturn result as T;\n\t\t}\n\t\tawait adapter.execute(compiled);\n\t\treturn undefined as T;\n\t}\n\n\tprivate async executeWithHooks(adapter: Adapter): Promise<T> {\n\t\tconst store = this.hookStore;\n\t\tif (!store) throw new Error('executeWithHooks called without hookStore');\n\t\t// INV-07: Re-entrancy guard\n\t\treturn withReentrancyGuard(store, (s) =>\n\t\t\tthis.executeWithHooksInner(adapter, s),\n\t\t);\n\t}\n\n\tprivate async executeWithHooksInner(\n\t\tadapter: Adapter,\n\t\tstore: HookStore,\n\t): Promise<T> {\n\t\tconst intent = this.buildIntent();\n\t\tconst operation = intent.type as MutationOperation;\n\t\tconst startTime = Date.now();\n\n\t\t// Determine cardinality and data from intent\n\t\tconst { cardinality, data } = this.extractIntentData(intent);\n\n\t\t// Build before-mutation context (no sql/duration yet)\n\t\tlet ctx: MutationHookContext = Object.freeze({\n\t\t\ttable: this.table,\n\t\t\toperation,\n\t\t\tintent,\n\t\t\tcardinality,\n\t\t\tdata,\n\t\t\t...(this.schemaName !== undefined ? { schemaName: this.schemaName } : {}),\n\t\t\t...(this.inTransaction ? { inTransaction: true } : {}),\n\t\t});\n\n\t\ttry {\n\t\t\t// Run beforeMutation hooks (FIFO)\n\t\t\tif (store.beforeMutation.length > 0) {\n\t\t\t\tctx = await runBeforeMutationHooks(\n\t\t\t\t\tstore.beforeMutation,\n\t\t\t\t\tctx,\n\t\t\t\t\tthis.onHookError,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Compile and execute\n\t\t\tconst compileOptions = this.schemaName\n\t\t\t\t? { schemaName: this.schemaName }\n\t\t\t\t: undefined;\n\t\t\tconst compiled = this.compileIntent(adapter, intent, compileOptions);\n\t\t\tconst duration = Date.now() - startTime;\n\n\t\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\t\tconst result = await adapter.execute(compiled);\n\n\t\t\t\t// Build after-mutation context with sql/duration\n\t\t\t\tconst afterCtx: MutationHookContext = Object.freeze({\n\t\t\t\t\t...ctx,\n\t\t\t\t\tsql: compiled.sql,\n\t\t\t\t\tparameters: compiled.parameters,\n\t\t\t\t\tduration,\n\t\t\t\t});\n\n\t\t\t\t// Run afterMutation hooks (LIFO)\n\t\t\t\tif (store.afterMutation.length > 0) {\n\t\t\t\t\tconst transformed = await runAfterMutationHooks(\n\t\t\t\t\t\tstore.afterMutation,\n\t\t\t\t\t\tafterCtx,\n\t\t\t\t\t\tresult as unknown[],\n\t\t\t\t\t\tthis.onHookError,\n\t\t\t\t\t);\n\t\t\t\t\treturn transformed as T;\n\t\t\t\t}\n\t\t\t\treturn result as T;\n\t\t\t}\n\n\t\t\tawait adapter.execute(compiled);\n\n\t\t\t// Even without RETURNING, fire afterMutation with empty results\n\t\t\tif (store.afterMutation.length > 0) {\n\t\t\t\tconst afterCtx: MutationHookContext = Object.freeze({\n\t\t\t\t\t...ctx,\n\t\t\t\t\tsql: compiled.sql,\n\t\t\t\t\tparameters: compiled.parameters,\n\t\t\t\t\tduration,\n\t\t\t\t});\n\t\t\t\tawait runAfterMutationHooks(\n\t\t\t\t\tstore.afterMutation,\n\t\t\t\t\tafterCtx,\n\t\t\t\t\t[],\n\t\t\t\t\tthis.onHookError,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn undefined as T;\n\t\t} catch (error) {\n\t\t\t// Run onError hooks\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tconst errorCtx = {\n\t\t\t\t\ttable: this.table,\n\t\t\t\t\toperation,\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent,\n\t\t\t\t\tphase: 'beforeMutation' as const,\n\t\t\t\t\t...(this.schemaName !== undefined\n\t\t\t\t\t\t? { schemaName: this.schemaName }\n\t\t\t\t\t\t: {}),\n\t\t\t\t};\n\t\t\t\tconst transformed = await runOnErrorHooks(store.onError, errorCtx);\n\t\t\t\tthrow transformed;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/** Extract cardinality and data from mutation intent */\n\tprivate extractIntentData(intent: TIntent): {\n\t\tcardinality: 'single' | 'bulk';\n\t\tdata: unknown;\n\t} {\n\t\tif (intent.type === 'insert' || intent.type === 'upsert') {\n\t\t\tconst values = (intent as InsertIntent | UpsertIntent).values;\n\t\t\treturn {\n\t\t\t\tcardinality: values.length > 1 ? 'bulk' : 'single',\n\t\t\t\tdata: values.length > 1 ? values : values[0],\n\t\t\t};\n\t\t}\n\t\tif (intent.type === 'update') {\n\t\t\treturn {\n\t\t\t\tcardinality: 'single',\n\t\t\t\tdata: (intent as UpdateIntent).set,\n\t\t\t};\n\t\t}\n\t\tif (intent.type === 'batchUpdate') {\n\t\t\tconst updates = (intent as BatchUpdateIntent).updates;\n\t\t\treturn {\n\t\t\t\tcardinality: 'bulk',\n\t\t\t\tdata: updates,\n\t\t\t};\n\t\t}\n\t\t// delete — no data\n\t\treturn { cardinality: 'single', data: undefined };\n\t}\n}\n\n// ============================================================================\n// Insert Builder\n// ============================================================================\n\n/**\n * Builder for INSERT operations.\n * Immutable - each method returns a new builder instance.\n */\nexport class InsertBuilder<T = void> extends MutationBuilderBase<\n\tT,\n\tInsertIntent\n> {\n\tprivate readonly valuesData: readonly Record<string, unknown>[];\n\n\tprotected readonly operationName = 'insert';\n\n\tconstructor(\n\t\topts: MutationBaseOpts & {\n\t\t\tvalues?: readonly Record<string, unknown>[] | undefined;\n\t\t\treturning?: readonly string[] | undefined;\n\t\t},\n\t) {\n\t\tsuper(opts);\n\t\tthis.valuesData = opts.values ?? [];\n\t}\n\n\t/**\n\t * Set values to insert.\n\t * Accepts a single object or an array for bulk insert.\n\t */\n\tvalues(\n\t\tdata: Record<string, unknown> | readonly Record<string, unknown>[],\n\t): InsertBuilder<T> {\n\t\tconst valueArray = Array.isArray(data) ? data : [data];\n\t\treturn new InsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: valueArray,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Specify columns to return after insert (DX-026).\n\t * Requires adapter support for RETURNING clause.\n\t *\n\t * @example\n\t * ```typescript\n\t * const inserted = await orm.insert(User)\n\t * .values({ name: 'Alice', email: 'alice@example.com' })\n\t * .returning(['id', 'created_at'])\n\t * .execute();\n\t * // inserted = [{ id: 1, created_at: '2024-01-01T00:00:00Z' }]\n\t * ```\n\t */\n\treturning<R = Record<string, unknown>>(\n\t\tcolumns: readonly (keyof R & string)[],\n\t): InsertBuilder<R[]> {\n\t\treturn new InsertBuilder<R[]>({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\treturning: columns,\n\t\t});\n\t}\n\n\tprotected buildIntent(): InsertIntent {\n\t\tif (this.valuesData.length === 0) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'insert',\n\t\t\t\t'No values provided for insert',\n\t\t\t);\n\t\t}\n\n\t\tconst intent: InsertIntent = {\n\t\t\ttype: 'insert',\n\t\t\ttable: this.table,\n\t\t\tvalues: this.valuesData,\n\t\t};\n\n\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\treturn { ...intent, returning: this.returningColumns };\n\t\t}\n\n\t\treturn intent;\n\t}\n\n\tprotected compileIntent(\n\t\tadapter: Adapter,\n\t\tintent: InsertIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn adapter.compileInsert(intent, options);\n\t}\n}\n\n// ============================================================================\n// Update Builder\n// ============================================================================\n\n/**\n * Builder for UPDATE operations.\n * Immutable - each method returns a new builder instance.\n */\nexport class UpdateBuilder<T = void> extends MutationBuilderBase<\n\tT,\n\tUpdateIntent | BatchUpdateIntent\n> {\n\tprivate readonly setData: Record<string, unknown>;\n\tprivate readonly whereIntent: WhereIntent | undefined;\n\tprivate readonly allowAllFlag: boolean;\n\tprivate readonly batchMatchColumns: readonly string[] | undefined;\n\tprivate readonly batchData: readonly Record<string, unknown>[] | undefined;\n\n\tprotected readonly operationName = 'update';\n\n\tconstructor(\n\t\topts: MutationBaseOpts & {\n\t\t\tset?: Record<string, unknown> | undefined;\n\t\t\twhere?: WhereIntent | undefined;\n\t\t\tallowAll?: boolean | undefined;\n\t\t\treturning?: readonly string[] | undefined;\n\t\t\tbatchMatchColumns?: readonly string[] | undefined;\n\t\t\tbatchData?: readonly Record<string, unknown>[] | undefined;\n\t\t},\n\t) {\n\t\tsuper(opts);\n\t\tthis.setData = opts.set ?? {};\n\t\tthis.whereIntent = opts.where;\n\t\tthis.allowAllFlag = opts.allowAll ?? false;\n\t\tthis.batchMatchColumns = opts.batchMatchColumns;\n\t\tthis.batchData = opts.batchData;\n\t}\n\n\t/**\n\t * Set fields to update.\n\t * Multiple calls merge fields (last value wins).\n\t * When combined with batchSet(), these become scalar SET assignments applied to all rows.\n\t */\n\tset(data: Record<string, unknown>): UpdateBuilder<T> {\n\t\treturn new UpdateBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tset: { ...this.setData, ...data },\n\t\t\twhere: this.whereIntent,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\treturning: this.returningColumns,\n\t\t\tbatchMatchColumns: this.batchMatchColumns,\n\t\t\tbatchData: this.batchData,\n\t\t});\n\t}\n\n\t/**\n\t * Add WHERE condition.\n\t */\n\twhere(condition: WhereIntent): UpdateBuilder<T> {\n\t\treturn new UpdateBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tset: this.setData,\n\t\t\twhere: condition,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\treturning: this.returningColumns,\n\t\t\tbatchMatchColumns: this.batchMatchColumns,\n\t\t\tbatchData: this.batchData,\n\t\t});\n\t}\n\n\t/**\n\t * Specify columns to return after update (DX-026).\n\t * Requires adapter support for RETURNING clause.\n\t *\n\t * @example\n\t * ```typescript\n\t * const updated = await orm.update(User)\n\t * .set({ status: 'active' })\n\t * .where({ type: 'comparison', field: 'id', operator: '=', value: 1 })\n\t * .returning(['id', 'status', 'updated_at'])\n\t * .execute();\n\t * ```\n\t */\n\treturning<R = Record<string, unknown>>(\n\t\tcolumns: readonly (keyof R & string)[],\n\t): UpdateBuilder<R[]> {\n\t\treturn new UpdateBuilder<R[]>({\n\t\t\t...this.baseOpts,\n\t\t\tset: this.setData,\n\t\t\twhere: this.whereIntent,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\treturning: columns,\n\t\t\tbatchMatchColumns: this.batchMatchColumns,\n\t\t\tbatchData: this.batchData,\n\t\t});\n\t}\n\n\t/**\n\t * Batch update multiple rows using unnest FROM strategy (BATCH-001).\n\t *\n\t * Generates:\n\t * UPDATE \"table\" SET \"col\" = t.\"col\"\n\t * FROM unnest(CAST($1 AS type[]), CAST($2 AS type[])) AS t(\"match_col\", \"col\")\n\t * WHERE \"table\".\"match_col\" = t.\"match_col\"\n\t *\n\t * Can be chained with .set() for scalar values applied to all rows.\n\t *\n\t * @param matchColumn - Column(s) used to identify rows to update\n\t * @param data - Array of row objects containing match + update column values\n\t *\n\t * @example\n\t * ```typescript\n\t * await orm.update('calls')\n\t * .batchSet('id', [{ id: 10, callee_id: 42 }, { id: 20, callee_id: 43 }])\n\t * .execute();\n\t * ```\n\t */\n\tbatchSet(\n\t\tmatchColumn: string | string[],\n\t\tdata: Record<string, unknown>[],\n\t): UpdateBuilder<T> {\n\t\tconst matchColumns = Array.isArray(matchColumn)\n\t\t\t? matchColumn\n\t\t\t: [matchColumn];\n\t\treturn new UpdateBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tset: this.setData,\n\t\t\twhere: this.whereIntent,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\treturning: this.returningColumns,\n\t\t\tbatchMatchColumns: matchColumns,\n\t\t\tbatchData: data,\n\t\t});\n\t}\n\n\tprotected buildIntent(): UpdateIntent | BatchUpdateIntent {\n\t\t// Batch path\n\t\tif (this.batchMatchColumns && this.batchData) {\n\t\t\tif (this.batchData.length === 0) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'update',\n\t\t\t\t\t'batchSet requires at least one row',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst intent: BatchUpdateIntent = {\n\t\t\t\ttype: 'batchUpdate',\n\t\t\t\ttable: this.table,\n\t\t\t\tmatchColumns: this.batchMatchColumns,\n\t\t\t\tupdates: this.batchData,\n\t\t\t};\n\n\t\t\tif (Object.keys(this.setData).length > 0) {\n\t\t\t\tObject.assign(intent, { scalarSet: this.setData });\n\t\t\t}\n\t\t\tif (this.whereIntent) {\n\t\t\t\tObject.assign(intent, { where: this.whereIntent });\n\t\t\t}\n\t\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\t\tObject.assign(intent, { returning: this.returningColumns });\n\t\t\t}\n\n\t\t\treturn intent;\n\t\t}\n\n\t\t// Regular update path\n\t\tif (Object.keys(this.setData).length === 0) {\n\t\t\tthrow new InvalidOperationError('update', 'No fields to update');\n\t\t}\n\n\t\tif (!this.whereIntent && !this.allowAllFlag) {\n\t\t\tthrow new UnsafeOperationError(\n\t\t\t\t'update',\n\t\t\t\t'WHERE clause required. Use updateAll() for full-table updates.',\n\t\t\t);\n\t\t}\n\n\t\tconst intent: UpdateIntent = {\n\t\t\ttype: 'update',\n\t\t\ttable: this.table,\n\t\t\tset: this.setData,\n\t\t};\n\n\t\tif (this.whereIntent) {\n\t\t\tObject.assign(intent, { where: this.whereIntent });\n\t\t}\n\t\tif (this.allowAllFlag) {\n\t\t\tObject.assign(intent, { allowAll: true });\n\t\t}\n\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\tObject.assign(intent, { returning: this.returningColumns });\n\t\t}\n\n\t\treturn intent;\n\t}\n\n\tprotected compileIntent(\n\t\tadapter: Adapter,\n\t\tintent: UpdateIntent | BatchUpdateIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\tif (intent.type === 'batchUpdate') {\n\t\t\treturn adapter.compileBatchUpdate(intent, options);\n\t\t}\n\t\treturn adapter.compileUpdate(intent, options);\n\t}\n}\n\n// ============================================================================\n// Delete Builder\n// ============================================================================\n\n/**\n * Builder for DELETE operations.\n * Immutable - each method returns a new builder instance.\n */\nexport class DeleteBuilder<T = void> extends MutationBuilderBase<\n\tT,\n\tDeleteIntent\n> {\n\tprivate readonly whereIntent: WhereIntent | undefined;\n\tprivate readonly allowAllFlag: boolean;\n\tprivate readonly cascadeRelations: boolean | readonly string[] | undefined;\n\n\tprotected readonly operationName = 'delete';\n\n\tconstructor(\n\t\topts: MutationBaseOpts & {\n\t\t\twhere?: WhereIntent | undefined;\n\t\t\tallowAll?: boolean | undefined;\n\t\t\tcascade?: boolean | readonly string[] | undefined;\n\t\t\treturning?: readonly string[] | undefined;\n\t\t},\n\t) {\n\t\tsuper(opts);\n\t\tthis.whereIntent = opts.where;\n\t\tthis.allowAllFlag = opts.allowAll ?? false;\n\t\tthis.cascadeRelations = opts.cascade;\n\t}\n\n\t/**\n\t * Add WHERE condition.\n\t */\n\twhere(condition: WhereIntent): DeleteBuilder<T> {\n\t\treturn new DeleteBuilder({\n\t\t\t...this.baseOpts,\n\t\t\twhere: condition,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\tcascade: this.cascadeRelations,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Enable cascade delete.\n\t * Without arguments: deletes ALL related records.\n\t * With array: deletes only specified relations.\n\t */\n\tcascade(relations?: readonly string[]): DeleteBuilder<T> {\n\t\treturn new DeleteBuilder({\n\t\t\t...this.baseOpts,\n\t\t\twhere: this.whereIntent,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\tcascade: relations ?? true,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Specify columns to return after delete (DX-026).\n\t * Requires adapter support for RETURNING clause.\n\t *\n\t * @example\n\t * ```typescript\n\t * const deleted = await orm.delete(User)\n\t * .where({ type: 'comparison', field: 'id', operator: '=', value: 1 })\n\t * .returning(['id', 'email'])\n\t * .execute();\n\t * ```\n\t */\n\treturning<R = Record<string, unknown>>(\n\t\tcolumns: readonly (keyof R & string)[],\n\t): DeleteBuilder<R[]> {\n\t\treturn new DeleteBuilder<R[]>({\n\t\t\t...this.baseOpts,\n\t\t\twhere: this.whereIntent,\n\t\t\tallowAll: this.allowAllFlag,\n\t\t\tcascade: this.cascadeRelations,\n\t\t\treturning: columns,\n\t\t});\n\t}\n\n\tprotected buildIntent(): DeleteIntent {\n\t\tif (!this.whereIntent && !this.allowAllFlag) {\n\t\t\tthrow new UnsafeOperationError(\n\t\t\t\t'delete',\n\t\t\t\t'WHERE clause required. Use deleteAll() for full-table deletes.',\n\t\t\t);\n\t\t}\n\n\t\tconst intent: DeleteIntent = {\n\t\t\ttype: 'delete',\n\t\t\ttable: this.table,\n\t\t};\n\n\t\tif (this.whereIntent) {\n\t\t\tObject.assign(intent, { where: this.whereIntent });\n\t\t}\n\t\tif (this.allowAllFlag) {\n\t\t\tObject.assign(intent, { allowAll: true });\n\t\t}\n\t\tif (this.cascadeRelations !== undefined) {\n\t\t\tObject.assign(intent, { cascade: this.cascadeRelations });\n\t\t}\n\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\tObject.assign(intent, { returning: this.returningColumns });\n\t\t}\n\n\t\treturn intent;\n\t}\n\n\tprotected compileIntent(\n\t\tadapter: Adapter,\n\t\tintent: DeleteIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn adapter.compileDelete(intent, options);\n\t}\n}\n\n// ============================================================================\n// Upsert Builder (DX-026)\n// ============================================================================\n\n/**\n * Builder for UPSERT operations (INSERT ... ON CONFLICT ... DO UPDATE/NOTHING).\n * Immutable - each method returns a new builder instance.\n *\n * @example\n * ```typescript\n * // Basic upsert with doUpdate\n * await orm.upsert(User)\n * .values({ id: 1, name: 'Alice', email: 'alice@example.com' })\n * .onConflict(['id'])\n * .doUpdate({ name: 'Alice Updated' })\n * .execute();\n *\n * // Upsert with doNothing\n * await orm.upsert(User)\n * .values({ id: 1, name: 'Alice' })\n * .onConflict(['id'])\n * .doNothing()\n * .execute();\n *\n * // Upsert with constraint name\n * await orm.upsert(User)\n * .values({ id: 1, name: 'Alice' })\n * .onConflictConstraint('users_pkey')\n * .doUpdate() // Auto-update non-conflict columns\n * .returning(['id', 'updated_at'])\n * .execute();\n * ```\n */\nexport class UpsertBuilder<T = void> extends MutationBuilderBase<\n\tT,\n\tUpsertIntent\n> {\n\tprivate readonly valuesData: readonly Record<string, unknown>[];\n\tprivate readonly conflictTarget: UpsertConflictTarget | undefined;\n\tprivate readonly conflictAction: UpsertConflictAction | undefined;\n\n\tprotected readonly operationName = 'upsert';\n\n\tconstructor(\n\t\topts: MutationBaseOpts & {\n\t\t\tvalues?: readonly Record<string, unknown>[] | undefined;\n\t\t\tonConflict?: UpsertConflictTarget | undefined;\n\t\t\taction?: UpsertConflictAction | undefined;\n\t\t\treturning?: readonly string[] | undefined;\n\t\t},\n\t) {\n\t\tsuper(opts);\n\t\tthis.valuesData = opts.values ?? [];\n\t\tthis.conflictTarget = opts.onConflict;\n\t\tthis.conflictAction = opts.action;\n\t}\n\n\t/**\n\t * Set values to insert.\n\t * Accepts a single object or an array for bulk upsert.\n\t */\n\tvalues(\n\t\tdata: Record<string, unknown> | readonly Record<string, unknown>[],\n\t): UpsertBuilder<T> {\n\t\tconst valueArray = Array.isArray(data) ? data : [data];\n\t\treturn new UpsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: valueArray,\n\t\t\tonConflict: this.conflictTarget,\n\t\t\taction: this.conflictAction,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Specify conflict target by column names.\n\t * These columns determine conflict detection.\n\t */\n\tonConflict(columns: readonly string[]): UpsertBuilder<T> {\n\t\treturn new UpsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: { columns },\n\t\t\taction: this.conflictAction,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Specify conflict target by constraint name.\n\t * Alternative to onConflict() for named constraints.\n\t */\n\tonConflictConstraint(constraintName: string): UpsertBuilder<T> {\n\t\treturn new UpsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: { constraint: constraintName },\n\t\t\taction: this.conflictAction,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * On conflict, update the specified fields.\n\t * If no fields specified, auto-updates all non-conflict columns.\n\t *\n\t * @param set - Optional fields to update on conflict\n\t * @param where - Optional condition for the update\n\t */\n\tdoUpdate(\n\t\tset?: Record<string, unknown>,\n\t\twhere?: WhereIntent,\n\t): UpsertBuilder<T> {\n\t\tconst action: UpsertConflictAction = {\n\t\t\ttype: 'doUpdate',\n\t\t\t...(set && { set }),\n\t\t\t...(where && { where }),\n\t\t};\n\t\treturn new UpsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: this.conflictTarget,\n\t\t\taction,\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * On conflict, do nothing (skip the insert).\n\t */\n\tdoNothing(): UpsertBuilder<T> {\n\t\treturn new UpsertBuilder({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: this.conflictTarget,\n\t\t\taction: { type: 'doNothing' },\n\t\t\treturning: this.returningColumns,\n\t\t});\n\t}\n\n\t/**\n\t * Specify columns to return after upsert (DX-026).\n\t * Requires adapter support for RETURNING clause.\n\t */\n\treturning<R = Record<string, unknown>>(\n\t\tcolumns: readonly (keyof R & string)[],\n\t): UpsertBuilder<R[]> {\n\t\treturn new UpsertBuilder<R[]>({\n\t\t\t...this.baseOpts,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: this.conflictTarget,\n\t\t\taction: this.conflictAction,\n\t\t\treturning: columns,\n\t\t});\n\t}\n\n\tprotected buildIntent(): UpsertIntent {\n\t\tif (this.valuesData.length === 0) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'upsert',\n\t\t\t\t'No values provided for upsert',\n\t\t\t);\n\t\t}\n\n\t\tif (!this.conflictTarget) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'upsert',\n\t\t\t\t'No conflict target specified. Use onConflict() or onConflictConstraint().',\n\t\t\t);\n\t\t}\n\n\t\tif (!this.conflictAction) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'upsert',\n\t\t\t\t'No conflict action specified. Use doUpdate() or doNothing().',\n\t\t\t);\n\t\t}\n\n\t\tconst intent: UpsertIntent = {\n\t\t\ttype: 'upsert',\n\t\t\ttable: this.table,\n\t\t\tvalues: this.valuesData,\n\t\t\tonConflict: this.conflictTarget,\n\t\t\taction: this.conflictAction,\n\t\t};\n\n\t\tif (this.returningColumns && this.returningColumns.length > 0) {\n\t\t\treturn { ...intent, returning: this.returningColumns };\n\t\t}\n\n\t\treturn intent;\n\t}\n\n\tprotected compileIntent(\n\t\tadapter: Adapter,\n\t\tintent: UpsertIntent,\n\t\toptions?: CompileOptions,\n\t): CompiledQuery {\n\t\treturn adapter.compileUpsert(intent, options);\n\t}\n}\n","import type {\n\tDDLFeature,\n\tDialectCapabilities,\n\tFeatureBehaviorConfig,\n\tFeatureWarning,\n\tModelIR,\n\tUnsupportedFeatureBehavior,\n} from '@dbsp/types';\n\n/** Error thrown when behavior = 'error' and unsupported feature detected */\nexport class UnsupportedFeatureError extends Error {\n\tconstructor(\n\t\treadonly feature: string,\n\t\treadonly adapter: string,\n\t\treadonly element: string,\n\t) {\n\t\tsuper(\n\t\t\t`Unsupported feature \"${feature}\" on adapter \"${adapter}\" for \"${element}\"`,\n\t\t);\n\t\tthis.name = 'UnsupportedFeatureError';\n\t}\n}\n\nimport {\n\tDEFAULT_FEATURE_CHECKERS,\n\ttype FeatureChecker,\n} from './feature-checkers.js';\n\nexport type { FeatureChecker, FeatureUsage } from './feature-checkers.js';\nexport { DEFAULT_FEATURE_CHECKERS } from './feature-checkers.js';\n\nexport interface NegotiationResult {\n\treadonly warnings: readonly FeatureWarning[];\n}\n\n/** Resolve effective behavior for a specific feature */\nfunction resolveBehavior(\n\tfeature: DDLFeature,\n\tconfig: UnsupportedFeatureBehavior | FeatureBehaviorConfig,\n): UnsupportedFeatureBehavior {\n\tif (typeof config === 'string') return config;\n\treturn config.overrides?.[feature] ?? config.default;\n}\n\n/**\n * Cross-check ModelIR features against DialectCapabilities.\n * Emits warnings or throws based on UnsupportedFeatureBehavior.\n *\n * INV-06: MUST NOT modify the ModelIR.\n * ERR-02: error mode throws on FIRST unsupported feature (fail-fast).\n * ERR-03: warning mode collects ALL warnings.\n *\n * OCP-001: extend by adding FeatureChecker entries to DEFAULT_FEATURE_CHECKERS\n * (or pass a custom checkers array) -- no edits to this function required.\n */\nexport function negotiateFeatures(\n\tmodel: ModelIR,\n\tcapabilities: DialectCapabilities,\n\tbehavior: UnsupportedFeatureBehavior | FeatureBehaviorConfig = 'warning',\n\tcheckers: readonly FeatureChecker[] = DEFAULT_FEATURE_CHECKERS,\n): NegotiationResult {\n\tconst warnings: FeatureWarning[] = [];\n\tconst adapterName = capabilities.name;\n\n\tfor (const checker of checkers) {\n\t\tif (capabilities[checker.capability]) continue; // supported\n\t\tconst usages = checker.detectUsage(model);\n\t\tif (usages.length === 0) continue; // not used\n\t\tconst effectiveBehavior = resolveBehavior(checker.feature, behavior);\n\t\tif (effectiveBehavior === 'ignore') continue;\n\t\tfor (const usage of usages) {\n\t\t\tif (effectiveBehavior === 'error') {\n\t\t\t\tthrow new UnsupportedFeatureError(\n\t\t\t\t\tchecker.feature,\n\t\t\t\t\tadapterName,\n\t\t\t\t\tusage.detail,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// warning mode\n\t\t\tconst message = `Unsupported feature \"${checker.feature}\" on adapter \"${adapterName}\" for \"${usage.detail}\"`;\n\t\t\twarnings.push({\n\t\t\t\tfeature: checker.feature,\n\t\t\t\tadapter: adapterName,\n\t\t\t\telement: usage.detail,\n\t\t\t\tmessage,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { warnings };\n}\n","/**\n * @fileoverview NQL template literal integration for type-safe queries (DX-040 Block 8).\n *\n * Provides a type-safe way to use NQL queries with explicit type annotation:\n * ```typescript\n * const users = await orm.nql<{ name: string; email: string }>`users | select name, email`.all();\n * ```\n *\n * Each `${value}` interpolation is escaped into a safe NQL literal (string/number/boolean/null).\n * Untrusted string input cannot inject NQL structure because it is always quoted and\n * single-quotes inside are doubled (`''`). For dynamic structural fragments (table names,\n * column names, ORDER BY direction) use the builder API (`orm.select()`). See #134 for\n * upcoming `:param` binding and a `nqlRaw()` escape hatch.\n *\n * @module nql\n * @since DX-040\n */\n\nimport { type NqlCompilerOptions, compile as nqlCompile } from '@dbsp/nql';\nimport type { Adapter, Dump } from '../adapter.js';\nimport type { QueryIntent } from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanReport } from '../planner.js';\nimport { plan as executePlan } from '../planner.js';\nimport type { DumpMetaInput } from './query-builder-types.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * NQL query builder with type-safe result.\n *\n * @typeParam T - The expected result row type\n */\nexport interface NqlBuilder<T> {\n\t/** Execute query and return all results */\n\tall(): Promise<T[]>;\n\t/** Execute query and return first result or null */\n\tfirst(): Promise<T | null>;\n\t/** Get the IntentIR for debugging */\n\ttoIntentIR(): QueryIntent;\n\t/** Get the execution plan */\n\tplan(): PlanReport;\n\t/** Get full dump (plan + SQL + params) */\n\tdump(meta?: DumpMetaInput): Dump;\n}\n\n/**\n * NQL template tag function type.\n *\n * @example\n * ```typescript\n * orm.nql<{ name: string }>`users | select name`\n * ```\n */\nexport type NqlTag = <T>(\n\tstrings: TemplateStringsArray,\n\t...values: unknown[]\n) => NqlBuilder<T>;\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Convert a JS value into a safe NQL literal token string.\n *\n * Supported types:\n * - `string` → single-quoted NQL string literal; embedded single-quotes are doubled (`''`),\n * matching the NQL StringLiteral token pattern `/'(?:[^']|'')*'/`.\n * Values containing a raw newline are rejected (Chevrotain StringLiteral\n * has no `line_breaks: true`, so newlines would produce a lex error).\n * - finite, non-exponential `number` → bare numeric literal (e.g. `42`, `3.14`, `-5`).\n * Negative numbers are emitted as a leading minus followed by the absolute\n * value, which NQL parses as unary-minus + number. Note: negative numbers\n * are only valid in comparison/value positions — `limit`/`offset` expect a\n * bare NumberLiteral and will parse-error on a leading minus.\n * `NaN`, `Infinity`, and numbers whose JS string form uses exponential\n * notation (magnitude ≥ 1e21 or absolute value < ~1e-6, e.g. `1e21`,\n * `1e-7`) are rejected — NQL NumberLiteral is `/\\d+(\\.\\d+)?/` (no exponent).\n * - `boolean` → `true` or `false` (matches NQL True/False tokens, case-insensitive).\n * - `null` → `null` (matches NQL Null token).\n * - All other types throw a descriptive Error.\n *\n * @param value - The JS value to convert\n * @param index - Zero-based interpolation position (for error messages)\n * @returns Safe NQL literal string\n * @internal\n */\nexport function toNqlLiteral(value: unknown, index: number): string {\n\tif (value === null) {\n\t\treturn 'null';\n\t}\n\tswitch (typeof value) {\n\t\tcase 'boolean':\n\t\t\treturn value ? 'true' : 'false';\n\t\tcase 'number': {\n\t\t\tif (!Number.isFinite(value)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`nql\\`...\\`: cannot interpolate non-finite number (${value}) at position ${index}. ` +\n\t\t\t\t\t\t'Only finite numbers are supported. ' +\n\t\t\t\t\t\t'For dynamic NQL structure use the builder API (orm.select()). See issue #134.',\n\t\t\t\t);\n\t\t\t}\n\t\t\t// NQL NumberLiteral is digits-only; negatives are parsed as unary minus + number.\n\t\t\t// Emit the minus separately so the lexer tokenises it correctly.\n\t\t\tconst s = value < 0 ? `-${Math.abs(value)}` : String(value);\n\t\t\t// Reject any value whose string form uses exponential notation (e.g. 1e21, 1e-7).\n\t\t\t// NQL NumberLiteral pattern /\\d+(\\.\\d+)?/ has no exponent support; emitting\n\t\t\t// such a token produces an opaque downstream parse error.\n\t\t\tif (/[eE]/.test(s)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`nql\\`...\\`: number ${value} at position ${index} has no exact NQL numeric literal form (exponential notation). ` +\n\t\t\t\t\t\t'Convert it yourself or use the builder API (orm.select()). See issue #134.',\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn s;\n\t\t}\n\t\tcase 'string': {\n\t\t\tif (value.includes('\\n') || value.includes('\\r')) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`nql\\`...\\`: cannot interpolate a string containing a newline at position ${index}. ` +\n\t\t\t\t\t\t'NQL string literals do not support raw newline characters. ' +\n\t\t\t\t\t\t'For dynamic NQL structure use the builder API (orm.select()). See issue #134.',\n\t\t\t\t);\n\t\t\t}\n\t\t\t// SQL-style quoting: wrap in single-quotes, double any embedded single-quote.\n\t\t\t// Matches NQL StringLiteral pattern: /'(?:[^']|'')*'/\n\t\t\tconst escaped = value.replaceAll(\"'\", \"''\");\n\t\t\treturn `'${escaped}'`;\n\t\t}\n\t\tdefault: {\n\t\t\tconst typeName = value === undefined ? 'undefined' : typeof value;\n\t\t\tthrow new Error(\n\t\t\t\t`nql\\`...\\`: cannot interpolate value of type \"${typeName}\" at position ${index}. ` +\n\t\t\t\t\t'Only string, number, boolean, and null are supported; ' +\n\t\t\t\t\t'for dynamic NQL fragments use the builder API (orm.select()). See issue #134.',\n\t\t\t);\n\t\t}\n\t}\n}\n\n/**\n * Create an NQL template tag function.\n *\n * Each `${value}` in the template is escaped into a safe NQL literal before parsing.\n * Supported interpolation types: `string`, `number`, `boolean`, `null`.\n * Untrusted string input is therefore safe from NQL-syntax injection — it is always\n * wrapped in single-quotes with embedded quotes doubled (`''`).\n * For dynamic structural fragments (table names, column names, ORDER BY direction)\n * use the builder API (`orm.select()`). See issue #134 for upcoming `:param` binding.\n *\n * @param schemaDefinition - Schema definition for validation\n * @param model - ModelIR for plan execution\n * @param adapter - Optional adapter for query execution\n * @param schemaName - Optional schema name for multi-tenant queries\n * @returns NQL template tag function\n */\nexport function createNqlTag(\n\tschemaDefinition: unknown,\n\tmodel: ModelIR,\n\tadapter?: Adapter<unknown>,\n\tschemaName?: string,\n): NqlTag {\n\treturn function nql<T>(\n\t\tstrings: TemplateStringsArray,\n\t\t...values: unknown[]\n\t): NqlBuilder<T> {\n\t\t// Reconstruct the query string from template literal, escaping each\n\t\t// interpolated value into a safe NQL literal via toNqlLiteral.\n\t\t// Note: strings[0] is always defined for template literals.\n\t\tlet query: string = strings[0] ?? '';\n\t\tfor (let i = 0; i < values.length; i++) {\n\t\t\tquery += toNqlLiteral(values[i], i) + (strings[i + 1] ?? '');\n\t\t}\n\n\t\treturn new NqlBuilderImpl<T>(\n\t\t\tquery,\n\t\t\tschemaDefinition,\n\t\t\tmodel,\n\t\t\tadapter,\n\t\t\tschemaName,\n\t\t);\n\t};\n}\n\n/**\n * NQL builder implementation.\n * @internal\n */\nclass NqlBuilderImpl<T> implements NqlBuilder<T> {\n\tprivate _intent: QueryIntent | undefined;\n\tprivate readonly query: string;\n\tprivate readonly schemaDefinition: unknown;\n\tprivate readonly model: ModelIR;\n\t// biome-ignore lint/correctness/noUnusedPrivateClassMembers: Reserved for future schema-scoping support\n\tprivate readonly _schemaName: string | undefined;\n\tprivate readonly adapter: Adapter<unknown> | undefined;\n\n\tconstructor(\n\t\tquery: string,\n\t\tschemaDefinition: unknown,\n\t\tmodel: ModelIR,\n\t\tadapter: Adapter<unknown> | undefined,\n\t\tschemaName: string | undefined,\n\t) {\n\t\tthis.query = query;\n\t\tthis.schemaDefinition = schemaDefinition;\n\t\tthis.model = model;\n\t\tthis.adapter = adapter;\n\t\tthis._schemaName = schemaName;\n\t}\n\n\tprivate compile(): QueryIntent {\n\t\tif (this._intent) {\n\t\t\treturn this._intent;\n\t\t}\n\n\t\t// Extract dynamic pseudo-column keywords from model configuration\n\t\tconst compilerOptions = extractPseudoColumnKeywords(this.model);\n\n\t\t// Use integrated @dbsp/nql compiler with dynamic keywords\n\t\tconst result = nqlCompile(\n\t\t\tthis.query,\n\t\t\tthis.schemaDefinition,\n\t\t\tundefined,\n\t\t\tcompilerOptions,\n\t\t);\n\t\tif (!result.success) {\n\t\t\tconst errors =\n\t\t\t\tresult.errors?.map((e) => e.message).join(', ') ?? 'Unknown error';\n\t\t\tthrow new Error(`NQL compilation failed: ${errors}`);\n\t\t}\n\t\tif (result.ast?.mutation && !result.ast?.query) {\n\t\t\tthrow new Error(\n\t\t\t\t'INSERT/UPDATE/DELETE/UPSERT not yet supported via the nql`...` tagged template. ' +\n\t\t\t\t\t'Use orm.insert(table, data) / orm.update(table, set) / orm.delete(table) / orm.upsert(table, data) instead. ' +\n\t\t\t\t\t'Tracking: https://github.com/oorabona/db-semantic-planner/issues/113',\n\t\t\t);\n\t\t}\n\t\tif (!result.ast?.query) {\n\t\t\tthrow new Error('NQL compilation failed: no query AST produced');\n\t\t}\n\n\t\t// Type assertion: NQL imports QueryIntent from @dbsp/types (ARCH-007),\n\t\t// structurally identical to core's re-export.\n\t\tthis._intent = result.ast.query as QueryIntent;\n\t\treturn this._intent;\n\t}\n\n\ttoIntentIR(): QueryIntent {\n\t\treturn this.compile();\n\t}\n\n\tplan(): PlanReport {\n\t\tconst intent = this.compile();\n\t\treturn executePlan(intent, this.model);\n\t}\n\n\tdump(meta?: DumpMetaInput): Dump {\n\t\tconst planReport = this.plan();\n\n\t\tif (!this.adapter) {\n\t\t\treturn {\n\t\t\t\tplan: planReport,\n\t\t\t\tsql: '[No adapter - SQL not available]',\n\t\t\t\tparams: [],\n\t\t\t\t...(meta !== undefined && { meta }),\n\t\t\t};\n\t\t}\n\n\t\tconst compiled = this.adapter.compile<T>(planReport);\n\n\t\ttry {\n\t\t\treturn this.adapter.createDump(planReport, compiled, meta);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\terr instanceof Error &&\n\t\t\t\terr.message.toLowerCase().includes('not implemented')\n\t\t\t) {\n\t\t\t\t// Fallback for mock adapters that don't implement createDump\n\t\t\t\tconst base: Dump = {\n\t\t\t\t\tplan: planReport,\n\t\t\t\t\tsql: compiled.sql,\n\t\t\t\t\tparams: compiled.parameters as readonly unknown[],\n\t\t\t\t};\n\t\t\t\tif (meta !== undefined) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...base,\n\t\t\t\t\t\tmeta: {\n\t\t\t\t\t\t\t...(meta.queryName !== undefined && {\n\t\t\t\t\t\t\t\tqueryName: meta.queryName,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t...(meta.correlationId !== undefined && {\n\t\t\t\t\t\t\t\tcorrelationId: meta.correlationId,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn base;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync all(): Promise<T[]> {\n\t\tif (!this.adapter) {\n\t\t\tthrow new Error(\n\t\t\t\t'Cannot execute query: no adapter configured. ' +\n\t\t\t\t\t'Pass an adapter to createOrm() or use .toIntentIR() / .plan() for debugging.',\n\t\t\t);\n\t\t}\n\n\t\tconst planReport = this.plan();\n\t\tconst compiled = this.adapter.compile<T>(planReport);\n\t\treturn this.adapter.execute(compiled);\n\t}\n\n\tasync first(): Promise<T | null> {\n\t\tconst rows = await this.all();\n\t\treturn rows[0] ?? null;\n\t}\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\n/**\n * Extract pseudo-column keywords from model configuration.\n * Collects all configured roles and recursive keywords from all tables'\n * pseudoColumns metadata, falling back to defaults if no configuration exists.\n */\nexport function extractPseudoColumnKeywords(\n\tmodel: ModelIR,\n): NqlCompilerOptions | undefined {\n\tconst allKeywords = new Set<string>();\n\tconst recursiveKeywords = new Set<string>();\n\n\tfor (const table of model.tables.values()) {\n\t\tif (!table.pseudoColumns) continue;\n\t\tfor (const pc of table.pseudoColumns) {\n\t\t\tallKeywords.add(pc.parentRole.toLowerCase());\n\t\t\tallKeywords.add(pc.childRole.toLowerCase());\n\t\t\tallKeywords.add(pc.ascendantKeyword.toLowerCase());\n\t\t\tallKeywords.add(pc.descendantKeyword.toLowerCase());\n\t\t\trecursiveKeywords.add(pc.ascendantKeyword.toLowerCase());\n\t\t\trecursiveKeywords.add(pc.descendantKeyword.toLowerCase());\n\t\t}\n\t}\n\n\t// No pseudo-columns configured → let compiler use defaults\n\tif (allKeywords.size === 0) return undefined;\n\n\treturn {\n\t\tpseudoColumnKeywords: [...allKeywords],\n\t\trecursiveKeywords: [...recursiveKeywords],\n\t};\n}\n","/**\n * @module dx/hierarchy-helpers\n * Pure helper functions for recursive/hierarchical query support.\n */\n\nimport type { ModelIR } from '../model-ir.js';\n\n/**\n * Extract a named field from a recursive query result.\n *\n * Recursive includes (`ancestors` / `descendants`) add a dynamic property to each row.\n * This helper safely extracts that property without `as any` casts.\n *\n * @internal\n */\nexport function extractRecursiveField<T>(\n\tresult: T | null | undefined,\n\tfield: 'ancestors' | 'descendants',\n): T[] {\n\tif (result == null) return [];\n\tconst row = result as Record<string, unknown>;\n\treturn (row[field] as T[]) ?? [];\n}\n\n/**\n * Find a self-referential relation on a table that matches the desired direction.\n *\n * @param model - The model IR\n * @param table - The table name\n * @param direction - 'ancestors' (needs belongsTo/hasOne) or 'descendants' (needs hasMany)\n * @returns The matching relation or null if not found\n */\nexport function findSelfRefRelation(\n\tmodel: ModelIR,\n\ttable: string,\n\tdirection: 'ancestors' | 'descendants',\n): { name: string; type: string } | null {\n\t// Get all relations from this table\n\tconst tableRelations = model.getRelationsFrom(table);\n\tif (!tableRelations || tableRelations.length === 0) {\n\t\treturn null;\n\t}\n\n\t// Find self-referential relations that match the direction\n\tfor (const relation of tableRelations) {\n\t\t// Must be self-referential\n\t\tif (relation.source !== relation.target) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check if direction matches relation type\n\t\tif (direction === 'ancestors') {\n\t\t\t// Need belongsTo or hasOne for ancestor traversal\n\t\t\tif (relation.type === 'belongsTo' || relation.type === 'hasOne') {\n\t\t\t\treturn { name: relation.name, type: relation.type };\n\t\t\t}\n\t\t} else {\n\t\t\t// Need hasMany for descendant traversal\n\t\t\tif (relation.type === 'hasMany') {\n\t\t\t\treturn { name: relation.name, type: relation.type };\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n","/**\n * Pagination implementation extracted from QueryBuilderImpl.\n *\n * Free functions that accept a QueryBuilderImpl instance and implement the\n * paginate / cursorPaginate logic. They access only fields and methods\n * declared @internal public on QueryBuilderImpl.\n *\n * @internal\n */\n\nimport type { OrderByIntent, WhereIntent } from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport { InvalidOperationError } from './errors.js';\nimport type { QueryBuilderImpl } from './query-builder.js';\nimport type {\n\tCursorPaginatedResult,\n\tCursorPaginateOptions,\n\tPaginatedResult,\n\tPaginateOptions,\n\tSortDirection,\n} from './types.js';\n\n// ---------------------------------------------------------------------------\n// Internal cursor key resolver\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the cursor key for an orderBy entry.\n * Returns null for expression-based entries without an alias (FIND-019).\n */\nfunction resolveCursorKey(orderBy: OrderByIntent): string | null {\n\tif (typeof orderBy === 'string') return orderBy;\n\tif (typeof orderBy.field === 'string') return orderBy.field;\n\tconst alias = (orderBy as { alias?: string }).alias;\n\treturn alias ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// buildCursorConditions\n// ---------------------------------------------------------------------------\n\n/**\n * Build cursor conditions for cursor pagination.\n * FIND-019: expression-based orderBy (fn(), caseWhen()) has no .field — require\n * alias or return null so the caller skips the condition gracefully.\n *\n * @internal\n */\nexport function buildCursorConditions<TResult>(\n\tbuilder: QueryBuilderImpl<TResult>,\n\tcursorValues: Record<string, unknown>,\n\tdirection: 'forward' | 'backward',\n): WhereIntent | null {\n\tif (builder.orderByIntents.length === 1) {\n\t\tconst orderBy = builder.orderByIntents[0];\n\t\tif (!orderBy) return null;\n\n\t\tconst field = resolveCursorKey(orderBy);\n\t\tif (field === null) return null;\n\n\t\tconst sortDir =\n\t\t\ttypeof orderBy === 'string'\n\t\t\t\t? 'asc'\n\t\t\t\t: ((orderBy.direction as string) ?? 'asc');\n\t\tconst cursorValue = cursorValues[field];\n\n\t\tif (cursorValue === undefined) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst isAsc =\n\t\t\tsortDir === 'asc' ? direction === 'forward' : direction === 'backward';\n\t\treturn {\n\t\t\tkind: 'comparison',\n\t\t\tfield,\n\t\t\toperator: isAsc ? 'gt' : 'lt',\n\t\t\tvalue: cursorValue,\n\t\t};\n\t}\n\n\tconst conditions: WhereIntent[] = [];\n\n\tfor (let i = 0; i < builder.orderByIntents.length; i++) {\n\t\tconst parts: WhereIntent[] = [];\n\n\t\tfor (let j = 0; j <= i; j++) {\n\t\t\tconst orderBy = builder.orderByIntents[j];\n\t\t\tif (!orderBy) continue;\n\n\t\t\tconst field = resolveCursorKey(orderBy);\n\t\t\tif (field === null) continue;\n\n\t\t\tconst sortDir =\n\t\t\t\ttypeof orderBy === 'string'\n\t\t\t\t\t? 'asc'\n\t\t\t\t\t: ((orderBy.direction as string) ?? 'asc');\n\t\t\tconst cursorValue = cursorValues[field];\n\n\t\t\tif (cursorValue === undefined) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (j < i) {\n\t\t\t\tparts.push({\n\t\t\t\t\tkind: 'comparison',\n\t\t\t\t\tfield,\n\t\t\t\t\toperator: 'eq',\n\t\t\t\t\tvalue: cursorValue,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst isAsc =\n\t\t\t\t\tsortDir === 'asc'\n\t\t\t\t\t\t? direction === 'forward'\n\t\t\t\t\t\t: direction === 'backward';\n\t\t\t\tparts.push({\n\t\t\t\t\tkind: 'comparison',\n\t\t\t\t\tfield,\n\t\t\t\t\toperator: isAsc ? 'gt' : 'lt',\n\t\t\t\t\tvalue: cursorValue,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (parts.length > 0) {\n\t\t\tconditions.push(\n\t\t\t\tparts.length === 1\n\t\t\t\t\t? (parts[0] as WhereIntent)\n\t\t\t\t\t: { kind: 'and', conditions: parts },\n\t\t\t);\n\t\t}\n\t}\n\n\tif (conditions.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst firstCondition = conditions[0];\n\treturn conditions.length === 1 && firstCondition !== undefined\n\t\t? firstCondition\n\t\t: { kind: 'or', conditions };\n}\n\n// ---------------------------------------------------------------------------\n// buildCursor\n// ---------------------------------------------------------------------------\n\n/**\n * Build cursor from a row using orderBy fields.\n * FIND-019: expression-based orderBy entries (fn(), caseWhen(), etc.) have no\n * .field string. Require an explicit alias or throw.\n *\n * @internal\n */\nexport function buildCursor<TResult>(\n\tbuilder: QueryBuilderImpl<TResult>,\n\trow: Record<string, unknown>,\n): string {\n\tconst cursorData: Record<string, unknown> = Object.create(null);\n\n\tfor (const orderBy of builder.orderByIntents) {\n\t\tif (!orderBy) continue;\n\t\tif (typeof orderBy === 'string') {\n\t\t\tcursorData[orderBy] = row[orderBy];\n\t\t} else {\n\t\t\tconst field = orderBy.field;\n\t\t\tif (typeof field === 'string') {\n\t\t\t\tcursorData[field] = row[field];\n\t\t\t} else {\n\t\t\t\tconst alias = (orderBy as { alias?: string }).alias;\n\t\t\t\tif (!alias) {\n\t\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t\t'cursorPaginate',\n\t\t\t\t\t\t'cursorPaginate requires orderBy entries with a string column name or an explicit alias. ' +\n\t\t\t\t\t\t\t'Use .orderBy(fn(...).as(\"alias\")) or .orderBy(\"column\") to enable cursor-based pagination.',\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcursorData[alias] = row[alias];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn Buffer.from(JSON.stringify(cursorData), 'utf-8').toString('base64');\n}\n\n// ---------------------------------------------------------------------------\n// paginate\n// ---------------------------------------------------------------------------\n\n/**\n * Execute offset-based pagination for a QueryBuilderImpl.\n *\n * @internal\n */\nexport async function paginate<TResult>(\n\tbuilder: QueryBuilderImpl<TResult>,\n\toptions?: PaginateOptions,\n): Promise<PaginatedResult<TResult>> {\n\tconst page = options?.page ?? 1;\n\tconst perPage = options?.perPage ?? 20;\n\tconst withCount = options?.withCount ?? true;\n\n\tif (!Number.isSafeInteger(page) || page < 1) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'paginate',\n\t\t\t'page must be a positive safe integer. Use page: 1 for the first page',\n\t\t);\n\t}\n\tif (!Number.isSafeInteger(perPage) || perPage < 1) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'paginate',\n\t\t\t'perPage must be a positive safe integer',\n\t\t);\n\t}\n\n\tconst offset = (page - 1) * perPage;\n\n\tconst paginatedBuilder = builder.clone();\n\tpaginatedBuilder.limitValue = perPage;\n\tpaginatedBuilder.offsetValue = offset;\n\n\tconst data = await paginatedBuilder.all();\n\n\tlet total: number | undefined;\n\tlet totalPages: number | undefined;\n\n\tif (withCount) {\n\t\t// FIND-018 (M-1 fix): when groupBy or explicit joins are present, compile\n\t\t// the base query as a subquery and wrap it with SELECT COUNT(*) FROM (...)\n\t\t// to always get a single scalar regardless of query shape.\n\t\t// For simple queries (no groupBy, no joins), the direct COUNT(*) path\n\t\t// is retained for efficiency.\n\t\tconst adapter = builder.getConfiguredAdapter();\n\t\tconst compileOptions: { schemaName?: string; model: ModelIR } = {\n\t\t\tmodel: builder.ctx.model,\n\t\t};\n\t\tif (builder.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = builder.ctx.schemaName;\n\t\t}\n\n\t\tconst hasGroupBy = builder.groupByFields.length > 0;\n\t\tconst hasJoins = builder.joinIntents.length > 0;\n\n\t\tif (hasGroupBy || hasJoins) {\n\t\t\tconst baseBuilder = builder.clone();\n\t\t\tbaseBuilder.limitValue = undefined;\n\t\t\tbaseBuilder.offsetValue = undefined;\n\t\t\tbaseBuilder.orderByIntents.splice(0);\n\t\t\tbaseBuilder.includes.splice(0);\n\t\t\tbaseBuilder.recursiveIncludes.splice(0);\n\t\t\tbaseBuilder.aggregates.splice(0);\n\t\t\tbaseBuilder.selectIntent = undefined;\n\n\t\t\tconst basePlan = baseBuilder.plan();\n\t\t\tconst baseCompiled = adapter.compile(basePlan, compileOptions);\n\n\t\t\tconst wrapSql = `SELECT COUNT(*) AS \"_count\" FROM (${baseCompiled.sql}) _count_subq`;\n\t\t\tconst wrapResult = (await adapter.execute({\n\t\t\t\tsql: wrapSql,\n\t\t\t\tparameters: baseCompiled.parameters,\n\t\t\t})) as Array<{ _count: string | number }>;\n\t\t\ttotal = Number(wrapResult[0]?._count ?? 0);\n\t\t} else {\n\t\t\tconst countBuilder = builder.clone() as unknown as QueryBuilderImpl<{\n\t\t\t\t_count: number;\n\t\t\t}>;\n\t\t\tcountBuilder.limitValue = undefined;\n\t\t\tcountBuilder.offsetValue = undefined;\n\t\t\tcountBuilder.orderByIntents.splice(0);\n\t\t\tcountBuilder.aggregates.splice(0, countBuilder.aggregates.length, {\n\t\t\t\tfunction: 'count',\n\t\t\t\tas: '_count',\n\t\t\t});\n\t\t\tcountBuilder.includes.splice(0);\n\t\t\tcountBuilder.recursiveIncludes.splice(0);\n\t\t\tcountBuilder.selectIntent = undefined;\n\n\t\t\tconst countResult = await countBuilder.all();\n\t\t\ttotal = Number(countResult[0]?._count ?? 0);\n\t\t}\n\t\ttotalPages = Math.ceil(total / perPage);\n\t}\n\n\tconst hasNextPage = withCount\n\t\t? page < (totalPages ?? 1)\n\t\t: data.length === perPage;\n\tconst hasPrevPage = page > 1;\n\n\treturn {\n\t\tdata,\n\t\tpagination: {\n\t\t\tpage,\n\t\t\tperPage,\n\t\t\t...(total !== undefined && { total }),\n\t\t\t...(totalPages !== undefined && { totalPages }),\n\t\t\thasNextPage,\n\t\t\thasPrevPage,\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// cursorPaginate\n// ---------------------------------------------------------------------------\n\n/**\n * Execute cursor-based pagination for a QueryBuilderImpl.\n *\n * @internal\n */\nexport async function cursorPaginate<TResult>(\n\tbuilder: QueryBuilderImpl<TResult>,\n\toptions?: CursorPaginateOptions,\n): Promise<CursorPaginatedResult<TResult>> {\n\tconst limit = options?.limit ?? 20;\n\tconst cursor = options?.cursor ?? null;\n\tconst direction = options?.direction ?? 'forward';\n\n\t// FIND-021: Validate limit is a safe non-negative integer (0 is accepted — returns empty page)\n\tif (!Number.isSafeInteger(limit) || limit < 0) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'cursorPaginate',\n\t\t\t'limit must be a non-negative safe integer',\n\t\t);\n\t}\n\n\t// Require orderBy for stable cursor pagination\n\tif (builder.orderByIntents.length === 0) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'cursorPaginate',\n\t\t\t'Cursor pagination requires an orderBy clause. Add .orderBy(\"id\") or similar before .cursorPaginate()',\n\t\t);\n\t}\n\n\t// Decode cursor if provided\n\tlet cursorValues: Record<string, unknown> | null = null;\n\tif (cursor) {\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(Buffer.from(cursor, 'base64').toString('utf-8'));\n\t\t} catch {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'cursorPaginate',\n\t\t\t\t'Invalid cursor format. Use a cursor returned from a previous cursorPaginate() call',\n\t\t\t);\n\t\t}\n\t\t// FIND-004: Validate cursor decodes to a plain object (not array/primitive)\n\t\tif (\n\t\t\ttypeof parsed !== 'object' ||\n\t\t\tparsed === null ||\n\t\t\tArray.isArray(parsed)\n\t\t) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'cursorPaginate',\n\t\t\t\t'Invalid cursor: must decode to an object',\n\t\t\t);\n\t\t}\n\t\t// Use Object.create(null)-safe iteration to avoid prototype pollution\n\t\tconst safeValues: Record<string, unknown> = Object.create(null);\n\t\tfor (const key of Object.keys(parsed)) {\n\t\t\tif (Object.hasOwn(parsed as Record<string, unknown>, key)) {\n\t\t\t\t(safeValues as Record<string, unknown>)[key] = (\n\t\t\t\t\tparsed as Record<string, unknown>\n\t\t\t\t)[key];\n\t\t\t}\n\t\t}\n\t\tcursorValues = safeValues;\n\t}\n\n\t// Build cursor conditions based on orderBy fields\n\tconst paginatedBuilder = builder.clone();\n\tif (cursorValues) {\n\t\tconst cursorConditions = buildCursorConditions(\n\t\t\tbuilder,\n\t\t\tcursorValues,\n\t\t\tdirection,\n\t\t);\n\t\tif (cursorConditions) {\n\t\t\tpaginatedBuilder.whereIntents.push(cursorConditions);\n\t\t}\n\t}\n\n\t// FIND-020: For backward pagination, invert every ORDER BY direction so the\n\t// DB returns rows immediately BEFORE the cursor. We then reverse the result\n\t// slice to restore the original ordering for the caller.\n\tif (direction === 'backward') {\n\t\tpaginatedBuilder.orderByIntents.splice(\n\t\t\t0,\n\t\t\tpaginatedBuilder.orderByIntents.length,\n\t\t\t...paginatedBuilder.orderByIntents.map((ob) => ({\n\t\t\t\t...ob,\n\t\t\t\tdirection: (ob.direction === 'asc' ? 'desc' : 'asc') as SortDirection,\n\t\t\t})),\n\t\t);\n\t}\n\n\t// Fetch one extra to determine if there's a next page\n\tpaginatedBuilder.limitValue = limit + 1;\n\n\t// Execute query\n\tconst rawResults = await paginatedBuilder.all();\n\n\tconst hasMore = rawResults.length > limit;\n\tconst sliced = hasMore ? rawResults.slice(0, limit) : rawResults;\n\n\t// For backward direction, reverse results to restore original ordering\n\tconst data = direction === 'backward' ? sliced.slice().reverse() : sliced;\n\n\tconst nextCursor =\n\t\thasMore && data.length > 0\n\t\t\t? buildCursor(builder, data[data.length - 1] as Record<string, unknown>)\n\t\t\t: null;\n\tconst prevCursor =\n\t\tdata.length > 0\n\t\t\t? buildCursor(builder, data[0] as Record<string, unknown>)\n\t\t\t: null;\n\n\treturn {\n\t\tdata,\n\t\tnextCursor,\n\t\tprevCursor:\n\t\t\tdirection === 'forward' ? (cursor ? prevCursor : null) : prevCursor,\n\t\thasNextPage: direction === 'forward' ? hasMore : cursor !== null,\n\t\thasPrevPage: direction === 'forward' ? cursor !== null : hasMore,\n\t};\n}\n","/**\n * Shared hydration utilities for json_agg include results.\n *\n * Extracted from ResultHydrator and QueryBuilderImpl to avoid duplication (DRY).\n */\nimport type { PlanReport } from '../planner.js';\n\n/**\n * Hydrate json_agg include columns in query results.\n *\n * Parses `{relation}_json` columns from json_agg subqueries into proper\n * nested objects/arrays, handles CamelCasePlugin column name transforms,\n * and unwraps to-one relations from arrays to single objects.\n */\nexport function hydrateJsonAggIncludes<T>(\n\tresults: T[],\n\tplanReport: PlanReport,\n): void {\n\t// Find all json_agg include decisions\n\tconst jsonAggDecisions = planReport.decisions.filter(\n\t\t(d) => d.type === 'include-strategy' && d.choice === 'json_agg',\n\t);\n\n\tif (jsonAggDecisions.length === 0) {\n\t\treturn;\n\t}\n\n\t// Build map of relation names -> relation type\n\t// The adapter compiler uses the canonical relation name (context.relation) for\n\t// the JSON column alias (e.g., 'author_posts' → 'author_posts_json').\n\t// We also track the includeAlias (user-provided name) for fallback matching.\n\t// STRAT-SIMPLIFY: Track to-one relations for [0] extraction\n\tconst relationInfo = new Map<\n\t\tstring,\n\t\t{ isToOne: boolean; includeAlias?: string; canonicalName?: string }\n\t>();\n\tfor (const decision of jsonAggDecisions) {\n\t\tconst canonicalName = decision.context?.relation;\n\t\tconst includeAlias = decision.context?.includeAlias;\n\t\tconst relationType = decision.context?.relationType;\n\t\tconst isToOne = relationType === 'belongsTo' || relationType === 'hasOne';\n\n\t\t// Primary key: canonical relation name (matches adapter SQL alias)\n\t\tif (typeof canonicalName === 'string') {\n\t\t\trelationInfo.set(canonicalName, {\n\t\t\t\tisToOne,\n\t\t\t\tincludeAlias:\n\t\t\t\t\ttypeof includeAlias === 'string' ? includeAlias : canonicalName,\n\t\t\t\tcanonicalName,\n\t\t\t});\n\t\t} else if (typeof includeAlias === 'string') {\n\t\t\t// Fallback: use includeAlias if no canonical name\n\t\t\trelationInfo.set(includeAlias, { isToOne, includeAlias });\n\t\t}\n\t}\n\n\tif (relationInfo.size === 0) {\n\t\treturn;\n\t}\n\n\t// Process each result row\n\tfor (const row of results) {\n\t\tif (typeof row !== 'object' || row === null) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst record = row as Record<string, unknown>;\n\n\t\tfor (const [relationName, info] of relationInfo) {\n\t\t\t// The adapter generates the JSON column alias from the canonical relation name\n\t\t\t// (e.g., 'author_posts' → 'author_posts_json'). The naming plugin may\n\t\t\t// transform it to camelCase (e.g., 'authorPostsJson').\n\t\t\t// We try both the canonical name and the includeAlias as base names.\n\t\t\tconst candidates = [relationName];\n\t\t\tif (info.includeAlias && info.includeAlias !== relationName) {\n\t\t\t\tcandidates.push(info.includeAlias);\n\t\t\t}\n\n\t\t\tlet actualColumnName: string | null = null;\n\t\t\tfor (const baseName of candidates) {\n\t\t\t\tconst snakeJson = `${baseName}_json`;\n\t\t\t\tconst camelJson = snakeJson.replace(/_([a-z])/g, (_, c: string) =>\n\t\t\t\t\tc.toUpperCase(),\n\t\t\t\t);\n\t\t\t\tif (snakeJson in record) {\n\t\t\t\t\tactualColumnName = snakeJson;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (camelJson in record) {\n\t\t\t\t\tactualColumnName = camelJson;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (actualColumnName) {\n\t\t\t\tconst jsonValue = record[actualColumnName];\n\n\t\t\t\t// Parse JSON if it's a string\n\t\t\t\tlet parsed: unknown;\n\t\t\t\tif (typeof jsonValue === 'string') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tparsed = JSON.parse(jsonValue);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tparsed = info.isToOne ? null : [];\n\t\t\t\t\t}\n\t\t\t\t} else if (Array.isArray(jsonValue)) {\n\t\t\t\t\tparsed = jsonValue;\n\t\t\t\t} else if (jsonValue === null || jsonValue === undefined) {\n\t\t\t\t\tparsed = info.isToOne ? null : [];\n\t\t\t\t} else {\n\t\t\t\t\tparsed = jsonValue;\n\t\t\t\t}\n\n\t\t\t\t// STRAT-SIMPLIFY: For to-one relations, unwrap array to single object\n\t\t\t\tif (info.isToOne && Array.isArray(parsed)) {\n\t\t\t\t\tparsed = parsed.length > 0 ? parsed[0] : null;\n\t\t\t\t}\n\n\t\t\t\t// Set property using includeAlias (user-facing name, e.g., 'posts')\n\t\t\t\t// and remove the raw JSON column\n\t\t\t\tconst outputKey = info.includeAlias ?? relationName;\n\t\t\t\trecord[outputKey] = parsed;\n\t\t\t\tdelete record[actualColumnName];\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * ResultHydrator - Handles result hydration and recursive include processing.\n *\n * DX-103: Extracted from QueryBuilderImpl to subquery hydration logic\n * from intent building and query execution.\n *\n * @module result-hydrator\n */\n\nimport type { Mutable } from '@dbsp/types/internal';\nimport type {\n\tAdapter,\n\tCompileOptions,\n\tSubqueryIncludeInfo,\n} from '../adapter.js';\nimport type { RecursiveIntent, WhereIntent } from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanReport } from '../planner.js';\nimport { planRecursive } from '../planner.js';\nimport { RelationNotFoundError } from './errors.js';\nimport { hydrateJsonAggIncludes as hydrateJsonAggIncludesShared } from './hydration-utils.js';\nimport type { RecursiveIncludeConfig } from './intent-builder.js';\n\n// ============================================================================\n// Helper Types\n// ============================================================================\n\n/** A database result row — typed loosely since row shapes are dynamic. */\ntype ResultRow = Record<string, unknown>;\n\n/**\n * Options for hydrating includes.\n * Requires model (unlike CompileOptions where it's optional).\n */\nexport type HydrateOptions = Omit<CompileOptions, 'model'> & { model: ModelIR };\n\n// ============================================================================\n// ResultHydrator\n// ============================================================================\n\n/**\n * Handles result hydration including:\n * - Subquery include hydration for hasMany relations\n * - Recursive include processing via CTEs\n * - Building nested hierarchies from flat results\n *\n * @typeParam TResult - The expected result type\n */\n\n/**\n * NUL byte (U+0000) used as the composite-key separator. Kept as a named\n * constant because literal control characters are invisible in diffs and\n * can be corrupted by editor normalization.\n */\nconst COMPOSITE_KEY_SEP = '\\0';\n\nexport class ResultHydrator<TResult = unknown> {\n\tprivate readonly model: ModelIR;\n\tprivate readonly from: string;\n\tprivate readonly schemaName: string | undefined;\n\n\tconstructor(model: ModelIR, from: string, schemaName?: string) {\n\t\tthis.model = model;\n\t\tthis.from = from;\n\t\tthis.schemaName = schemaName;\n\t}\n\n\t/**\n\t * Hydrate subquery includes (hasMany relations) into main results.\n\t */\n\tasync hydrateIncludes(\n\t\tresults: TResult[],\n\t\tsubqueryIncludes: readonly SubqueryIncludeInfo[],\n\t\tadapter: Adapter,\n\t\tcompileOptions: HydrateOptions,\n\t): Promise<void> {\n\t\tif (results.length === 0) return;\n\n\t\tfor (const includeInfo of subqueryIncludes) {\n\t\t\t// Extract parent IDs from results using sourceKey.\n\t\t\t// PERF (FIND-054): single-pass for-loop avoids the intermediate array\n\t\t\t// that .map().filter() allocates (2 passes + length-N temp array).\n\t\t\tconst parentIds: unknown[] = [];\n\t\t\tfor (const r of results) {\n\t\t\t\tconst id = this.extractKeyValue(\n\t\t\t\t\tr as Record<string, unknown>,\n\t\t\t\t\tincludeInfo.sourceKey,\n\t\t\t\t);\n\t\t\t\tif (id !== undefined && id !== null) parentIds.push(id);\n\t\t\t}\n\n\t\t\tif (parentIds.length === 0) continue;\n\n\t\t\t// Compile and execute the include query\n\t\t\tconst includeQuery = adapter.compileSubqueryInclude(\n\t\t\t\tincludeInfo,\n\t\t\t\tparentIds,\n\t\t\t\tcompileOptions,\n\t\t\t);\n\t\t\tconst childResults = await adapter.execute(includeQuery);\n\n\t\t\t// Group children by foreign key\n\t\t\tconst childrenByParentId = new Map<unknown, unknown[]>();\n\t\t\tfor (const child of childResults) {\n\t\t\t\tconst parentId = this.extractKeyValue(\n\t\t\t\t\tchild as Record<string, unknown>,\n\t\t\t\t\tincludeInfo.foreignKey,\n\t\t\t\t);\n\t\t\t\tif (parentId !== undefined) {\n\t\t\t\t\tconst existing = childrenByParentId.get(parentId);\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\texisting.push(child);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tchildrenByParentId.set(parentId, [child]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Attach children to parent objects\n\t\t\t// For to-one relations (belongsTo/hasOne), unwrap to single object\n\t\t\tconst isToOne =\n\t\t\t\tincludeInfo.relationType === 'belongsTo' ||\n\t\t\t\tincludeInfo.relationType === 'hasOne';\n\t\t\tfor (const result of results) {\n\t\t\t\tconst parentId = this.extractKeyValue(\n\t\t\t\t\tresult as Record<string, unknown>,\n\t\t\t\t\tincludeInfo.sourceKey,\n\t\t\t\t);\n\t\t\t\tconst children = childrenByParentId.get(parentId) ?? [];\n\t\t\t\t(result as Record<string, unknown>)[includeInfo.relationName] = isToOne\n\t\t\t\t\t? (children[0] ?? null)\n\t\t\t\t\t: children;\n\t\t\t}\n\n\t\t\t// Process nested includes recursively if present\n\t\t\tif (includeInfo.nestedIncludes && includeInfo.nestedIncludes.length > 0) {\n\t\t\t\t// Flatten all children for nested hydration.\n\t\t\t\t// PERF (FIND-055): avoid Array.from().flat() which allocates an array-of-arrays\n\t\t\t\t// then flattens it; a double for-loop uses a single allocation.\n\t\t\t\tconst allChildren: Record<string, unknown>[] = [];\n\t\t\t\tfor (const arr of childrenByParentId.values()) {\n\t\t\t\t\tfor (const item of arr)\n\t\t\t\t\t\tallChildren.push(item as Record<string, unknown>);\n\t\t\t\t}\n\t\t\t\tif (allChildren.length > 0) {\n\t\t\t\t\tawait this.hydrateIncludes(\n\t\t\t\t\t\tallChildren as TResult[],\n\t\t\t\t\t\tincludeInfo.nestedIncludes,\n\t\t\t\t\t\tadapter,\n\t\t\t\t\t\tcompileOptions,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Hydrate JOIN includes by grouping dot-prefixed columns into nested objects.\n\t * E2E-004: JOIN strategy for to-one relations returns columns like \"author.id\", \"author.name\".\n\t */\n\thydrateJoinIncludes(results: TResult[], planReport: PlanReport): void {\n\t\t// Find all JOIN include decisions (to-one relations)\n\t\tconst joinDecisions = planReport.decisions.filter(\n\t\t\t(d) => d.type === 'include-strategy' && d.choice === 'join',\n\t\t);\n\n\t\tif (joinDecisions.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Get relation names from decisions\n\t\tconst joinInfos = joinDecisions\n\t\t\t.map((d) => d.context?.relation)\n\t\t\t.filter((r): r is string => typeof r === 'string')\n\t\t\t.map((relation) => ({ relation, prefix: `${relation}.` }));\n\n\t\tif (joinInfos.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// PERF (FIND-050): build the key index ONCE per relation from the first valid row,\n\t\t// rather than scanning Object.keys() on every row × every relation (O(N×R×K)).\n\t\t// Assumption: all rows share the same projection (fixed SELECT list) — safe for\n\t\t// SQL queries where the column set is determined at compile time.\n\t\t// Guard: if a key from the cache is absent on a given row, it is silently skipped.\n\t\ttype JoinInfo = {\n\t\t\trelation: string;\n\t\t\tprefix: string;\n\t\t\tcachedKeys: string[] | null;\n\t\t};\n\t\tconst joinInfosWithCache: JoinInfo[] = joinInfos.map((info) => ({\n\t\t\t...info,\n\t\t\tcachedKeys: null,\n\t\t}));\n\n\t\tif (results.length > 0) {\n\t\t\t// Find first non-null row to build the key cache\n\t\t\tconst firstRow = results.find(\n\t\t\t\t(r): r is TResult & object => typeof r === 'object' && r !== null,\n\t\t\t);\n\t\t\tif (firstRow) {\n\t\t\t\tconst firstRecord = firstRow as Record<string, unknown>;\n\t\t\t\tconst allKeys = Object.keys(firstRecord);\n\t\t\t\tfor (const info of joinInfosWithCache) {\n\t\t\t\t\tinfo.cachedKeys = allKeys.filter((k) => k.startsWith(info.prefix));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Process each result row\n\t\tfor (const row of results) {\n\t\t\tif (typeof row !== 'object' || row === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst record = row as Record<string, unknown>;\n\n\t\t\tfor (const info of joinInfosWithCache) {\n\t\t\t\t// Use cached keys; fall back to live scan if cache is empty (heterogeneous rows)\n\t\t\t\tconst keys =\n\t\t\t\t\tinfo.cachedKeys && info.cachedKeys.length > 0\n\t\t\t\t\t\t? info.cachedKeys\n\t\t\t\t\t\t: Object.keys(record).filter((k) => k.startsWith(info.prefix));\n\n\t\t\t\tif (keys.length === 0) continue;\n\n\t\t\t\tconst nestedObj: Record<string, unknown> = {};\n\t\t\t\tlet allNull = true;\n\n\t\t\t\t// Build nested object and delete prefixed keys in a single pass —\n\t\t\t\t// no keysToDelete array needed.\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\tconst val = record[key];\n\t\t\t\t\tif (val !== undefined) {\n\t\t\t\t\t\t// Guard: key present on this row\n\t\t\t\t\t\tnestedObj[key.slice(info.prefix.length)] = val;\n\t\t\t\t\t\tdelete record[key];\n\t\t\t\t\t\tif (val !== null) allNull = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// If all values are null, the related entity doesn't exist (LEFT JOIN returned no match)\n\t\t\t\trecord[info.relation] = allNull ? null : nestedObj;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Hydrate json_agg includes by parsing JSON columns and renaming them.\n\t * E2E-004: json_agg strategy returns data as JSON string in *_json columns.\n\t * STRAT-SIMPLIFY: For to-one relations (belongsTo/hasOne), unwrap array to single object.\n\t */\n\thydrateJsonAggIncludes(results: TResult[], planReport: PlanReport): void {\n\t\thydrateJsonAggIncludesShared(results, planReport);\n\t}\n\n\t/**\n\t * Process recursive includes via CTEs.\n\t */\n\tasync processRecursiveIncludes(\n\t\tresults: unknown[],\n\t\trecursiveIncludes: readonly RecursiveIncludeConfig[],\n\t\tadapter: Adapter,\n\t): Promise<void> {\n\t\tif (results.length === 0) return;\n\n\t\tfor (const config of recursiveIncludes) {\n\t\t\tawait this.processOneRecursiveInclude(\n\t\t\t\tresults as ResultRow[],\n\t\t\t\tconfig,\n\t\t\t\tadapter,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Process a single recursive include.\n\t */\n\tprivate async processOneRecursiveInclude(\n\t\tresults: ResultRow[],\n\t\tconfig: RecursiveIncludeConfig,\n\t\tadapter: Adapter,\n\t): Promise<void> {\n\t\tconst { relation, options } = config;\n\t\tconst {\n\t\t\tdirection,\n\t\t\tflat = false,\n\t\t\tomitSelf = false,\n\t\t\tmaxDepth = 100,\n\t\t\tincludeDepth = false,\n\t\t} = options;\n\n\t\t// Get relation metadata\n\t\tconst qualifiedName = `${this.from}.${relation}`;\n\t\tconst relationMeta = this.model.getRelation(qualifiedName);\n\t\tif (!relationMeta) {\n\t\t\t// Get available relations for helpful error message\n\t\t\tconst tableRelations = this.model.getRelationsFrom(this.from);\n\t\t\tconst available = tableRelations?.map((r) => r.name) ?? [];\n\t\t\tthrow new RelationNotFoundError({\n\t\t\t\ttable: this.from,\n\t\t\t\trequested: relation,\n\t\t\t\tavailable,\n\t\t\t});\n\t\t}\n\n\t\t// Determine the foreign key column from relation metadata\n\t\tconst fkColumn = this.getForeignKeyColumn(relationMeta.foreignKey);\n\n\t\t// Collect IDs from the main results (primary key values)\n\t\t// For ancestors: we start from the record's own ID and traverse up via parent\n\t\t// For descendants: we start from the record's own ID and traverse down via children\n\t\tconst startIds = results\n\t\t\t.map((r) => r.id as unknown)\n\t\t\t.filter((id) => id !== undefined && id !== null);\n\n\t\tif (startIds.length === 0) return;\n\n\t\t// Build RecursiveIntent\n\t\tconst cteName = `_recursive_${relation}_${direction}`;\n\t\tconst recursiveIntent = this.buildRecursiveIntent(\n\t\t\tcteName,\n\t\t\trelationMeta,\n\t\t\tstartIds,\n\t\t\tdirection,\n\t\t\tmaxDepth,\n\t\t\tincludeDepth,\n\t\t);\n\n\t\t// Plan and compile the recursive query\n\t\tconst report = planRecursive(recursiveIntent, this.model);\n\n\t\t// Build compile options with exactOptionalPropertyTypes compliance\n\t\tconst compileOptions: { schemaName?: string } = {};\n\t\tif (this.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.schemaName;\n\t\t}\n\n\t\tconst compiledRecursive = adapter.compileRecursive(\n\t\t\treport,\n\t\t\tthis.model,\n\t\t\tcompileOptions,\n\t\t);\n\n\t\t// Execute\n\t\tconst recursiveRows = (await adapter.execute(compiledRecursive)) as Record<\n\t\t\tstring,\n\t\t\tunknown\n\t\t>[];\n\n\t\t// Merge results back into main results\n\t\tthis.mergeRecursiveResults(\n\t\t\tresults,\n\t\t\trecursiveRows,\n\t\t\trelation,\n\t\t\tdirection,\n\t\t\tfkColumn,\n\t\t\tflat,\n\t\t\tomitSelf,\n\t\t);\n\t}\n\n\t/**\n\t * Build a RecursiveIntent for CTE execution.\n\t */\n\tprivate buildRecursiveIntent(\n\t\tcteName: string,\n\t\trelationMeta: ReturnType<ModelIR['getRelation']> & object,\n\t\tstartIds: unknown[],\n\t\tdirection: 'ancestors' | 'descendants',\n\t\tmaxDepth: number,\n\t\tincludeDepth: boolean,\n\t): RecursiveIntent {\n\t\tconst { source, foreignKey } = relationMeta;\n\n\t\t// Get the foreign key as a string (use first element if array)\n\t\tconst fkColumn = this.getForeignKeyColumn(foreignKey);\n\n\t\t// For self-referential relations:\n\t\t// - ancestors: traverse via parent (belongsTo) - follow foreignKey to parent\n\t\t// - descendants: traverse via children (hasMany) - find rows where foreignKey = our id\n\n\t\t// Build the start WHERE clause to filter by the starting IDs\n\t\tconst startWhere: WhereIntent =\n\t\t\tstartIds.length === 1\n\t\t\t\t? {\n\t\t\t\t\t\tkind: 'comparison',\n\t\t\t\t\t\tfield: 'id',\n\t\t\t\t\t\toperator: 'eq',\n\t\t\t\t\t\tvalue: startIds[0],\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tkind: 'in',\n\t\t\t\t\t\tfield: 'id',\n\t\t\t\t\t\tvalues: startIds as (string | number | boolean)[],\n\t\t\t\t\t};\n\n\t\t// Build traversal config based on direction\n\t\tconst traversal = this.buildTraversalConfig(source, fkColumn, direction);\n\n\t\t// Build the intent\n\t\tconst intent: Mutable<RecursiveIntent> = {\n\t\t\ttype: 'recursive',\n\t\t\tcteName,\n\t\t\tstart: {\n\t\t\t\tfrom: source,\n\t\t\t\tnodeIdExpr: { kind: 'column', name: 'id' },\n\t\t\t\twhere: startWhere,\n\t\t\t},\n\t\t\ttraversal,\n\t\t\tmaxDepth,\n\t\t};\n\n\t\t// Add depth tracking if requested\n\t\tif (includeDepth) {\n\t\t\tintent.track = { depth: {} };\n\t\t}\n\n\t\treturn intent as RecursiveIntent;\n\t}\n\n\t/**\n\t * Get the foreign key column name from relation metadata.\n\t */\n\tprivate getForeignKeyColumn(\n\t\tforeignKey: string | readonly string[] | undefined,\n\t): string {\n\t\tif (!foreignKey) {\n\t\t\treturn 'parent_id'; // Default convention for self-referential\n\t\t}\n\t\tif (typeof foreignKey === 'string') {\n\t\t\treturn foreignKey;\n\t\t}\n\t\t// It's a readonly array - use first column for composite FK\n\t\tconst first = foreignKey[0];\n\t\treturn first ?? 'parent_id'; // Fallback for empty array\n\t}\n\n\t/**\n\t * Build traversal config for recursive CTE.\n\t */\n\tprivate buildTraversalConfig(\n\t\tnodeTable: string,\n\t\tparentIdColumn: string,\n\t\tdirection: 'ancestors' | 'descendants',\n\t): RecursiveIntent['traversal'] {\n\t\t// For self-referential adjacency list:\n\t\t// - ancestors: currentRow.foreignKey = nextRow.id (follow parent pointer)\n\t\t// - descendants: currentRow.id = nextRow.foreignKey (find children)\n\t\treturn {\n\t\t\tkind: 'adjacency',\n\t\t\tnodeTable,\n\t\t\tnodeId: 'id',\n\t\t\tparentId: parentIdColumn,\n\t\t\tdirection,\n\t\t};\n\t}\n\n\t/**\n\t * Merge recursive results back into main results.\n\t */\n\tprivate mergeRecursiveResults(\n\t\tresults: ResultRow[],\n\t\trecursiveRows: ResultRow[],\n\t\trelation: string,\n\t\tdirection: 'ancestors' | 'descendants',\n\t\tforeignKey: string,\n\t\tflat: boolean,\n\t\tomitSelf: boolean,\n\t): void {\n\t\t// Build a map from start ID to recursive results\n\t\tconst resultsByStartId = new Map<unknown, ResultRow[]>();\n\n\t\tfor (const row of recursiveRows) {\n\t\t\t// The recursive CTE returns rows with a _start_id or similar marker\n\t\t\t// For now, we group by the root ID that started the traversal\n\t\t\tconst startId = row._root_id ?? row.id;\n\t\t\tconst existing = resultsByStartId.get(startId) ?? [];\n\n\t\t\t// Apply omitSelf filter\n\t\t\tif (omitSelf && row.depth === 0) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\texisting.push(row);\n\t\t\tresultsByStartId.set(startId, existing);\n\t\t}\n\n\t\t// Determine output property name based on direction\n\t\tconst outputProperty =\n\t\t\tdirection === 'ancestors'\n\t\t\t\t? relation === 'parent'\n\t\t\t\t\t? 'ancestors'\n\t\t\t\t\t: `${relation}_ancestors`\n\t\t\t\t: relation === 'children'\n\t\t\t\t\t? 'descendants'\n\t\t\t\t\t: `${relation}_descendants`;\n\n\t\t// Attach to main results\n\t\tfor (const result of results) {\n\t\t\tconst id = result.id as unknown;\n\t\t\tconst recursiveData = resultsByStartId.get(id) ?? [];\n\n\t\t\tif (flat) {\n\t\t\t\t// Flat: array of all results\n\t\t\t\tresult[outputProperty] = recursiveData;\n\t\t\t} else {\n\t\t\t\t// Nested: build tree structure\n\t\t\t\tresult[outputProperty] = this.buildNestedHierarchy(\n\t\t\t\t\trecursiveData,\n\t\t\t\t\tdirection,\n\t\t\t\t\tforeignKey,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Build nested hierarchy from flat recursive results.\n\t */\n\tprivate buildNestedHierarchy(\n\t\trows: ResultRow[],\n\t\tdirection: 'ancestors' | 'descendants',\n\t\tforeignKey: string,\n\t): ResultRow | ResultRow[] | null {\n\t\tif (rows.length === 0) return direction === 'ancestors' ? null : [];\n\n\t\t// Sort by depth\n\t\tconst sorted = [...rows].sort(\n\t\t\t(a, b) => ((a.depth as number) ?? 0) - ((b.depth as number) ?? 0),\n\t\t);\n\n\t\tif (direction === 'ancestors') {\n\t\t\t// For ancestors, build a chain: self -> parent -> grandparent\n\t\t\t// Return the immediate parent with nested ancestors\n\t\t\tlet current = null;\n\t\t\tfor (let i = sorted.length - 1; i >= 0; i--) {\n\t\t\t\tconst row = sorted[i];\n\t\t\t\tconst node = { ...row };\n\t\t\t\tif (current !== null) {\n\t\t\t\t\tnode[direction === 'ancestors' ? 'parent' : 'children'] = current;\n\t\t\t\t}\n\t\t\t\tcurrent = node;\n\t\t\t}\n\t\t\treturn current;\n\t\t}\n\n\t\t// For descendants, build a tree structure\n\t\tconst nodeMap = new Map<unknown, ResultRow>();\n\t\tconst roots: ResultRow[] = [];\n\n\t\tfor (const row of sorted) {\n\t\t\tconst node = { ...row, children: [] };\n\t\t\tnodeMap.set(row.id, node);\n\n\t\t\tconst parentId = row[foreignKey] as unknown;\n\t\t\tif (parentId !== null && parentId !== undefined) {\n\t\t\t\tconst parent = nodeMap.get(parentId);\n\t\t\t\tif (parent) {\n\t\t\t\t\t(parent.children as ResultRow[]).push(node);\n\t\t\t\t} else {\n\t\t\t\t\troots.push(node);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\troots.push(node);\n\t\t\t}\n\t\t}\n\n\t\treturn roots;\n\t}\n\n\t/**\n\t * Extract a key value from an object, handling composite keys.\n\t *\n\t * Fast path: NUL-byte separator for the common case of string/number PKs\n\t * (~5× faster than JSON.stringify). Fallback: if any serialized part\n\t * contains a NUL byte (e.g. bytea PKs stored as strings), two distinct\n\t * keys could collide under the fast path — use JSON.stringify in that\n\t * case (slower but collision-safe for any value content).\n\t */\n\tprivate extractKeyValue(\n\t\tobj: Record<string, unknown>,\n\t\tkey: string | readonly string[],\n\t): unknown {\n\t\tif (typeof key === 'string') {\n\t\t\treturn obj[key];\n\t\t}\n\t\t// Composite key: build a string key for Map grouping.\n\t\tconst values = key.map((k) => obj[k]);\n\t\t// Return undefined if any component is missing\n\t\tif (values.some((v) => v === undefined || v === null)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst parts = values.map((v) => String(v));\n\t\tif (parts.some((p) => p.includes(COMPOSITE_KEY_SEP))) {\n\t\t\t// Collision-safe fallback — slower but correct for any value content.\n\t\t\t// Stringify `parts` (already normalized to strings via String(v))\n\t\t\t// rather than `values` because JSON.stringify throws on bigint,\n\t\t\t// and composite PKs may legitimately contain bigint values.\n\t\t\treturn JSON.stringify(parts);\n\t\t}\n\t\treturn parts.join(COMPOSITE_KEY_SEP);\n\t}\n}\n","/**\n * @fileoverview SetOperationBuilder — fluent API for UNION / INTERSECT / EXCEPT.\n *\n * Returned by `.union()`, `.unionAll()`, `.intersect()`, `.except()` on QueryBuilder.\n * Stores a SetOperationIntent tree and provides dump() + execute helpers.\n *\n * Architecture note: SQL compilation is delegated to the adapter via\n * `adapter.compileSetOperation()` so that `@dbsp/core` remains DB-agnostic.\n */\n\nimport type { Adapter, Dump, DumpMeta } from '../adapter.js';\nimport type {\n\tQueryIntent,\n\tSetOperationIntent,\n\tSetOperationType,\n} from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport { ExecutionError } from './errors.js';\nimport type { QueryBuilder } from './types.js';\n\n// ============================================================================\n// Public interface\n// ============================================================================\n\n/**\n * Fluent builder for set operations (UNION / INTERSECT / EXCEPT).\n *\n * @typeParam TResult - Result row type\n *\n * @example\n * ```typescript\n * const q1 = orm.select('employees').where(eq('active', true));\n * const q2 = orm.select('contractors').where(eq('active', true));\n *\n * // UNION (deduplicates rows)\n * const dump = q1.union(q2).dump();\n *\n * // UNION ALL (keeps duplicates)\n * const rows = await q1.unionAll(q2).all();\n *\n * // Chain: (q1 UNION q2) INTERSECT q3\n * const nested = q1.union(q2).intersect(q3);\n * ```\n */\nexport interface SetOperationBuilder<TResult = unknown> {\n\t/** Combine via UNION (deduplicates rows). */\n\tunion(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Combine via UNION ALL (keeps duplicates). */\n\tunionAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Combine via INTERSECT (rows in both). */\n\tintersect(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Combine via INTERSECT ALL (rows in both, with duplicates). */\n\tintersectAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Combine via EXCEPT (rows in left but not right). */\n\texcept(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Combine via EXCEPT ALL (rows in left but not right, with duplicates). */\n\texceptAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult>;\n\n\t/** Compile to SQL and return a Dump (no execution). Requires adapter. */\n\tdump(): Dump;\n\n\t/** Execute and return all rows. Requires adapter. */\n\tall(): Promise<TResult[]>;\n\n\t/** Execute and return first row. Requires adapter. */\n\tfirst(): Promise<TResult | undefined>;\n\n\t/** The underlying SetOperationIntent (for inspection / testing). */\n\treadonly intent: SetOperationIntent;\n}\n\n// ============================================================================\n// Builder context interface\n// ============================================================================\n\n/** Minimal interface to extract a QueryIntent from a builder. @internal */\nexport interface QueryIntentSource {\n\tbuildIntent(): QueryIntent;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/** @internal */\nexport class SetOperationBuilderImpl<TResult = unknown>\n\timplements SetOperationBuilder<TResult>\n{\n\treadonly intent: SetOperationIntent;\n\tprivate readonly model: ModelIR;\n\tprivate readonly adapter: Adapter | undefined;\n\tprivate readonly schemaName: string | undefined;\n\n\tconstructor(\n\t\tintent: SetOperationIntent,\n\t\tmodel: ModelIR,\n\t\tadapter?: Adapter,\n\t\tschemaName?: string,\n\t) {\n\t\tthis.intent = intent;\n\t\tthis.model = model;\n\t\tthis.adapter = adapter;\n\t\tthis.schemaName = schemaName;\n\t}\n\n\tunion(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('union', false, other);\n\t}\n\n\tunionAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('union', true, other);\n\t}\n\n\tintersect(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('intersect', false, other);\n\t}\n\n\tintersectAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('intersect', true, other);\n\t}\n\n\texcept(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('except', false, other);\n\t}\n\n\texceptAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn this.combine('except', true, other);\n\t}\n\n\tprivate combine(\n\t\top: SetOperationType,\n\t\tall: boolean,\n\t\tother: QueryBuilder<TResult>,\n\t): SetOperationBuilder<TResult> {\n\t\tconst rightIntent = (other as unknown as QueryIntentSource).buildIntent();\n\t\tconst newIntent: SetOperationIntent = {\n\t\t\tkind: 'setOperation',\n\t\t\top,\n\t\t\tall,\n\t\t\tleft: this.intent,\n\t\t\tright: rightIntent,\n\t\t};\n\t\treturn new SetOperationBuilderImpl<TResult>(\n\t\t\tnewIntent,\n\t\t\tthis.model,\n\t\t\tthis.adapter,\n\t\t\tthis.schemaName,\n\t\t);\n\t}\n\n\tdump(): Dump {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst compiled = adapter.compileSetOperation(this.intent, this.model);\n\t\t// Set operations bypass the semantic planner — no PlanReport is produced.\n\t\t// compiledAt is always included so observability hooks that read\n\t\t// dump.meta?.compiledAt receive a consistent shape regardless of query type.\n\t\tconst meta: DumpMeta = {\n\t\t\tcompiledAt: new Date(),\n\t\t\t...(this.schemaName !== undefined ? { schema: this.schemaName } : {}),\n\t\t};\n\t\treturn {\n\t\t\tsql: compiled.sql,\n\t\t\tparams: compiled.parameters,\n\t\t\tmeta,\n\t\t};\n\t}\n\n\tasync all(): Promise<TResult[]> {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst compiled = adapter.compileSetOperation(this.intent, this.model);\n\t\treturn adapter.execute(compiled) as Promise<TResult[]>;\n\t}\n\n\tasync first(): Promise<TResult | undefined> {\n\t\tconst rows = await this.all();\n\t\treturn rows[0];\n\t}\n\n\tprivate requireAdapter(): Adapter {\n\t\tif (!this.adapter) {\n\t\t\tthrow new ExecutionError({\n\t\t\t\toperation: 'set operation execution',\n\t\t\t\treason: 'Adapter not configured',\n\t\t\t\tfix: 'Pass an adapter to createOrm({ adapter: yourAdapter })',\n\t\t\t});\n\t\t}\n\t\treturn this.adapter;\n\t}\n}\n\n// ============================================================================\n// Factory helper\n// ============================================================================\n\n/**\n * Build a SetOperationIntent from two query intent sources.\n * @internal\n */\nexport function buildSetOperationIntent(\n\top: SetOperationType,\n\tall: boolean,\n\tleft: QueryIntentSource,\n\tright: QueryIntentSource,\n): SetOperationIntent {\n\treturn {\n\t\tkind: 'setOperation',\n\t\top,\n\t\tall,\n\t\tleft: left.buildIntent(),\n\t\tright: right.buildIntent(),\n\t};\n}\n","/**\n * Stream implementation extracted from QueryBuilderImpl.\n *\n * Free function that accepts a QueryBuilderImpl instance and implements the\n * stream() logic. It accesses only fields and methods declared\n * @internal public on QueryBuilderImpl.\n *\n * @internal\n */\n\nimport type { Dump } from '../adapter.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanOptions } from '../planner.js';\nimport type { QueryHookContext } from './hooks.js';\nimport {\n\thasHooks,\n\trunBeforeQueryHooks,\n\trunOnErrorHooks,\n\twithReentrancyGuard,\n} from './hooks.js';\nimport type { QueryBuilderImpl } from './query-builder.js';\nimport type { StreamOptions } from './types.js';\n\n/**\n * Create a lazy AsyncIterableIterator for streaming query results.\n *\n * Extracted from QueryBuilderImpl.stream(). All hook semantics, lazy\n * compilation, and onStart callback behaviour are preserved identically.\n *\n * @internal\n */\nexport function stream<TResult>(\n\tbuilder: QueryBuilderImpl<TResult>,\n\toptions?: StreamOptions,\n): AsyncIterableIterator<TResult> {\n\tconst adapter = builder.getConfiguredAdapter();\n\n\t// Only pass chunkSize to adapter; onStart is handled in the wrapper\n\tconst adapterOptions =\n\t\toptions?.chunkSize !== undefined\n\t\t\t? { chunkSize: options.chunkSize }\n\t\t\t: undefined;\n\n\t// E17b: Fire beforeQuery hook with isStreaming=true (afterQuery does NOT fire for streams)\n\tconst hookStore = builder.ctx.hookStore;\n\tconst onHookError = builder.ctx.onHookError;\n\tconst table = builder.from;\n\tconst schemaName = builder.ctx.schemaName;\n\tconst txFlag = builder.ctx.inTransaction;\n\n\t// Capture builder references needed inside the lazy iterator closure.\n\t// These are captured once to avoid re-reading mutable builder state on\n\t// every next() call (the builder could theoretically be modified between\n\t// iterator creation and first consumption).\n\tconst onStartCallback = options?.onStart;\n\n\t// FIND-017: dumpResult (planning + compilation) MUST happen AFTER\n\t// beforeQuery hooks run, because hooks can modify the intent (e.g. inject\n\t// a tenant WHERE clause). Moving compilation inside the lazy iterator's\n\t// first-next guard ensures hook changes are reflected in the executed SQL.\n\tlet compiledQuery: { sql: string; parameters: readonly unknown[] } | null =\n\t\tnull;\n\tlet capturedDump: Dump | null = null;\n\tlet adapterIterator: AsyncIterableIterator<TResult> | null = null;\n\tlet onStartCalled = false;\n\tlet hooksFired = false;\n\n\tconst lazyIterator: AsyncIterableIterator<TResult> = {\n\t\t[Symbol.asyncIterator]() {\n\t\t\treturn this;\n\t\t},\n\t\tasync next() {\n\t\t\t// E17b: Fire beforeQuery on first iteration (lazy), then compile with\n\t\t\t// the hook-modified intent.\n\t\t\tif (!hooksFired) {\n\t\t\t\thooksFired = true;\n\n\t\t\t\tif (hookStore && hasHooks(hookStore)) {\n\t\t\t\t\t// Build raw intent (without defaultFilters) — hooks see raw intent\n\t\t\t\t\tconst rawIntent = builder.buildIntent(false);\n\t\t\t\t\tconst ctx: QueryHookContext = {\n\t\t\t\t\t\ttable,\n\t\t\t\t\t\toperation: 'select',\n\t\t\t\t\t\tintent: rawIntent,\n\t\t\t\t\t\tresultType: 'all',\n\t\t\t\t\t\tisStreaming: true,\n\t\t\t\t\t\t...(schemaName !== undefined && { schemaName }),\n\t\t\t\t\t\t...(txFlag && { inTransaction: true }),\n\t\t\t\t\t};\n\n\t\t\t\t\tlet hookIntent = rawIntent;\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// INV-07: Re-entrancy guard — prevent infinite loops from hooks issuing queries\n\t\t\t\t\t\tconst afterHookCtx = await withReentrancyGuard(hookStore, (s) =>\n\t\t\t\t\t\t\trunBeforeQueryHooks(s.beforeQuery, ctx, onHookError),\n\t\t\t\t\t\t);\n\t\t\t\t\t\thookIntent = afterHookCtx.intent;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (hookStore.onError.length > 0) {\n\t\t\t\t\t\t\tthrow await runOnErrorHooks(hookStore.onError, {\n\t\t\t\t\t\t\t\ttable,\n\t\t\t\t\t\t\t\toperation: 'select',\n\t\t\t\t\t\t\t\terror: error as Error,\n\t\t\t\t\t\t\t\tintent: rawIntent,\n\t\t\t\t\t\t\t\tphase: 'beforeQuery',\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply defaultFilters AFTER hooks (INV-01: cannot be bypassed)\n\t\t\t\t\tconst intentAfterDefaults =\n\t\t\t\t\t\tbuilder.applyDefaultFiltersToIntent(hookIntent);\n\t\t\t\t\tconst intentWithHints =\n\t\t\t\t\t\tbuilder.applyRelationHints(intentAfterDefaults);\n\t\t\t\t\tconst planOptions: PlanOptions = {\n\t\t\t\t\t\t...(builder.ctx.dialectCapabilities && {\n\t\t\t\t\t\t\tdialectCapabilities: builder.ctx.dialectCapabilities,\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t...builder.ctx.planOptionsOverride,\n\t\t\t\t\t};\n\t\t\t\t\tconst planReport = builder.planWithAmbiguityHandling(\n\t\t\t\t\t\tintentWithHints,\n\t\t\t\t\t\tplanOptions,\n\t\t\t\t\t);\n\t\t\t\t\tconst compileOptions: { schemaName?: string; model: ModelIR } = {\n\t\t\t\t\t\tmodel: builder.ctx.model,\n\t\t\t\t\t};\n\t\t\t\t\tif (schemaName !== undefined) {\n\t\t\t\t\t\tcompileOptions.schemaName = schemaName;\n\t\t\t\t\t}\n\t\t\t\t\tconst compiled = adapter.compile(planReport, compileOptions);\n\t\t\t\t\tcompiledQuery = compiled;\n\t\t\t\t\tcapturedDump = adapter.createDump(planReport, compiled);\n\t\t\t\t\tif (\n\t\t\t\t\t\tcapturedDump.meta?.schema === undefined &&\n\t\t\t\t\t\tschemaName !== undefined\n\t\t\t\t\t) {\n\t\t\t\t\t\tcapturedDump = {\n\t\t\t\t\t\t\t...capturedDump,\n\t\t\t\t\t\t\tmeta: { ...capturedDump.meta, schema: schemaName },\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// No hooks: compute dump eagerly (same as original fast path)\n\t\t\t\t\tconst dumpResult = builder.dump();\n\t\t\t\t\tcompiledQuery = {\n\t\t\t\t\t\tsql: dumpResult.sql,\n\t\t\t\t\t\tparameters: dumpResult.params as readonly unknown[],\n\t\t\t\t\t};\n\t\t\t\t\tcapturedDump = dumpResult;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Initialize adapter iterator lazily (compiledQuery is now set)\n\t\t\tif (!adapterIterator) {\n\t\t\t\t// compiledQuery is guaranteed non-null: hooksFired is true at this\n\t\t\t\t// point, meaning the block above has completed and set compiledQuery.\n\t\t\t\tadapterIterator = adapter.stream<TResult>(\n\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: invariant — hooksFired=true means the block above set compiledQuery before reaching this branch\n\t\t\t\t\tcompiledQuery!,\n\t\t\t\t\tadapterOptions,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Call onStart only once, on first next() call\n\t\t\tif (!onStartCalled && onStartCallback && capturedDump) {\n\t\t\t\tonStartCalled = true;\n\t\t\t\tonStartCallback(capturedDump);\n\t\t\t}\n\n\t\t\treturn adapterIterator.next();\n\t\t},\n\t\tasync return(value?: TResult) {\n\t\t\tif (adapterIterator?.return) {\n\t\t\t\treturn adapterIterator.return(value);\n\t\t\t}\n\t\t\treturn { done: true as const, value: undefined };\n\t\t},\n\t\tasync throw(error?: unknown) {\n\t\t\t// E17b: Fire onError for stream errors\n\t\t\tif (hookStore && hookStore.onError.length > 0 && error instanceof Error) {\n\t\t\t\tconst rawIntent = builder.buildIntent(false);\n\t\t\t\tconst finalError = await runOnErrorHooks(hookStore.onError, {\n\t\t\t\t\ttable,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror,\n\t\t\t\t\tintent: rawIntent,\n\t\t\t\t\tphase: 'afterQuery',\n\t\t\t\t});\n\t\t\t\tthrow finalError;\n\t\t\t}\n\t\t\tif (adapterIterator?.throw) {\n\t\t\t\treturn adapterIterator.throw(error);\n\t\t\t}\n\t\t\tthrow error;\n\t\t},\n\t};\n\n\treturn lazyIterator;\n}\n","/* biome-ignore-all lint/style/noNonNullAssertion: Builder internals use non-null assertions on validated state */\nimport type { Mutable } from '@dbsp/types/internal';\nimport type { Adapter, Dump } from '../adapter.js';\nimport type {\n\tAggregateIntent,\n\tColumnExpressionIntent,\n\tExpressionIntent,\n\tIncludeIntent,\n\tJoinIntent,\n\tOrderByIntent,\n\tQueryIntent,\n\tSelectAggregateIntent,\n\tSelectIntent,\n\tWhereIntent,\n} from '../intent-ast.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanOptions, PlanReport } from '../planner.js';\nimport { AmbiguousPlanError, plan } from '../planner.js';\nimport type { BatchValuesRef } from './batch-values.js';\nimport { isBatchValuesRef } from './batch-values.js';\nimport {\n\tAmbiguousRelationError,\n\tExecutionError,\n\tInvalidOperationError,\n\tNotFoundError,\n\tvalidateIdentifier,\n} from './errors.js';\nimport { ExpressionRef } from './expressions.js';\nimport {\n\tand,\n\ttype DistinctField,\n\teq,\n\tinArray,\n\tisDistinctField,\n} from './filters.js';\nimport {\n\ttype HookStore,\n\thasHooks,\n\ttype QueryHookContext,\n\ttype QueryResultType,\n\trunAfterQueryHooks,\n\trunBeforeQueryHooks,\n\trunOnErrorHooks,\n\twithReentrancyGuard,\n} from './hooks.js';\nimport {\n\tincludeOptionsToIntent,\n\tisRecursiveIncludeOptions,\n\tparseDotNotationInclude,\n\ttype RecursiveIncludeConfig,\n\tvalidateRecursiveInclude,\n} from './intent-builder.js';\nimport {\n\tisWhereIntent,\n\tobjectToWhereIntent,\n\ttype WhereFilter,\n} from './object-filter.js';\nimport * as paginationImpl from './pagination-impl.js';\nimport type { QueryBuilderContext } from './query-builder-context.js';\nimport type { DumpMetaInput } from './query-builder-types.js';\nimport { ResultHydrator } from './result-hydrator.js';\nimport {\n\tbuildSetOperationIntent,\n\ttype QueryIntentSource,\n\ttype SetOperationBuilder,\n\tSetOperationBuilderImpl,\n} from './set-operation-builder.js';\nimport * as streamImpl from './stream-impl.js';\nimport {\n\ttype AggregateOptions,\n\ttype AliasedExprColumn,\n\ttype ColumnSpec,\n\ttype CursorPaginatedResult,\n\ttype CursorPaginateOptions,\n\ttype ExpressionSpec,\n\ttype IncludeOptionsWithRecursive,\n\tisExpressionSpec,\n\ttype OrderByRecord,\n\ttype OrderBySpec,\n\ttype PaginatedResult,\n\ttype PaginateOptions,\n\ttype QueryBuilder,\n\ttype RelationHints,\n\ttype SortDirection,\n\ttype StreamOptions,\n} from './types.js';\n/**\n * Internal query builder implementation.\n */\nexport class QueryBuilderImpl<TResult = unknown>\n\timplements QueryBuilder<TResult>\n{\n\t/** @internal — read by stream-impl and pagination-impl */\n\treadonly ctx: QueryBuilderContext;\n\t/** @internal — read by stream-impl */\n\treadonly from: string;\n\t/** @internal — mutated by pagination-impl on clones */\n\treadonly includes: IncludeIntent[] = [];\n\t/** @internal — mutated by pagination-impl on clones */\n\treadonly recursiveIncludes: RecursiveIncludeConfig[] = [];\n\tprivate readonly relationHints: RelationHints;\n\t/** @internal — mutated by pagination-impl on clones */\n\tselectIntent: SelectIntent | undefined = undefined;\n\t/** @internal — mutated by pagination-impl on clones */\n\twhereIntents: WhereIntent[] = [];\n\tprivate strictModeOverride: boolean | undefined = undefined;\n\t/** @internal — mutated by pagination-impl on clones */\n\taggregates: AggregateIntent[] = [];\n\t/** @internal — read by pagination-impl */\n\tgroupByFields: string[] = [];\n\t/** @internal — read by pagination-impl and cursor helpers */\n\torderByIntents: OrderByIntent[] = [];\n\t/** @internal — mutated by pagination-impl on clones */\n\tlimitValue: number | undefined = undefined;\n\t/** @internal — mutated by pagination-impl on clones */\n\toffsetValue: number | undefined = undefined;\n\tprivate havingIntents: WhereIntent[] = [];\n\tprivate isDistinctQuery = false;\n\tprivate distinctOnColumns: string[] = [];\n\tprivate skipDefaultFilters = false;\n\tprivate lockIntent: import('@dbsp/types').LockIntent | undefined = undefined;\n\t/** @internal — read by pagination-impl */\n\tjoinIntents: JoinIntent[] = [];\n\t/** When set, FROM clause is a BatchValues unnest() source, not a table */\n\tbatchValuesSource?: import('@dbsp/types').BatchValuesJoinPayload;\n\n\tconstructor(\n\t\tctx: QueryBuilderContext,\n\t\tfrom: string,\n\t\trelationHints: RelationHints = {},\n\t) {\n\t\tthis.ctx = ctx;\n\t\tthis.from = from;\n\t\tthis.relationHints = relationHints;\n\t}\n\n\tinclude(\n\t\trelation: string,\n\t\toptions?: IncludeOptionsWithRecursive,\n\t): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\n\t\t// Validate recursive includes (DX-017)\n\t\tif (isRecursiveIncludeOptions(options)) {\n\t\t\tvalidateRecursiveInclude(this.ctx.model, this.from, relation, options);\n\t\t\t// DX-017: No longer store separately - let includeOptionsToIntent handle conversion\n\t\t}\n\n\t\t// Support dot notation for nested includes: 'posts.comments.author'\n\t\tif (relation.includes('.')) {\n\t\t\tbuilder.includes.push(parseDotNotationInclude(relation, options));\n\t\t} else {\n\t\t\tbuilder.includes.push(includeOptionsToIntent(relation, options));\n\t\t}\n\t\treturn builder;\n\t}\n\n\t// Overload: typed columns (string keys only) → Pick<TResult, K>\n\tcolumns<K extends keyof TResult & string>(\n\t\tcolumns: readonly K[],\n\t): QueryBuilder<Pick<TResult, K>>;\n\t// Overload: mixed strings + AliasedExprColumn → extends result type with aliased props\n\tcolumns<\n\t\tconst T extends readonly (\n\t\t\t| (keyof TResult & string)\n\t\t\t| AliasedExprColumn<string>\n\t\t)[],\n\t>(\n\t\tcolumns: T,\n\t): QueryBuilder<\n\t\tPick<TResult, Extract<T[number], keyof TResult & string>> & {\n\t\t\t[E in Extract<\n\t\t\t\tT[number],\n\t\t\t\tAliasedExprColumn<string>\n\t\t\t> as E['__alias']]: E['__value'];\n\t\t}\n\t>;\n\t// Overload: mixed columns (strings + expressions) → TResult\n\tcolumns(columns: readonly ColumnSpec[]): QueryBuilder<TResult>;\n\t// Implementation — cast to TResult to match the most general overload signature.\n\t// The overloads above refine the type; the implementation signature is intentionally\n\t// broad to satisfy all three overloads (TypeScript requires an assignable\n\t// implementation signature).\n\t// biome-ignore lint/suspicious/noExplicitAny: implementation signature accepts erased type — public overloads above guarantee the correct narrowed return type for callers\n\tcolumns(columns: readonly ColumnSpec[]): QueryBuilder<any> {\n\t\tconst builder = this.clone();\n\n\t\t// Build columns array (direct ExpressionIntent format - NQL compatible)\n\t\tconst expressionColumns: ExpressionIntent[] = [];\n\t\tlet hasExpressions = false;\n\n\t\tfor (const col of columns) {\n\t\t\tif (isExpressionSpec(col)) {\n\t\t\t\thasExpressions = true;\n\t\t\t\texpressionColumns.push(col.intent);\n\t\t\t} else {\n\t\t\t\t// Simple field → ColumnExpressionIntent (kind: 'column')\n\t\t\t\texpressionColumns.push({ kind: 'column', column: col });\n\t\t\t}\n\t\t}\n\n\t\t// Use SelectWithExpressionsIntent if we have any expressions\n\t\tif (hasExpressions) {\n\t\t\tbuilder.selectIntent = {\n\t\t\t\ttype: 'expressions',\n\t\t\t\tcolumns: expressionColumns,\n\t\t\t};\n\t\t} else {\n\t\t\t// Simple fields only - extract field names\n\t\t\tconst fields = expressionColumns.map(\n\t\t\t\t(c) => (c as ColumnExpressionIntent).column,\n\t\t\t);\n\t\t\tbuilder.selectIntent = { type: 'fields', fields };\n\t\t}\n\n\t\t// Cast is safe: the public overloads above guarantee the correct narrowed type.\n\t\t// biome-ignore lint/suspicious/noExplicitAny: implementation signature cast — public overloads above guarantee the correct narrowed type for callers\n\t\treturn builder as QueryBuilder<any>;\n\t}\n\n\tcoalesce<K extends keyof TResult & string, Alias extends string>(\n\t\tfields: readonly K[],\n\t\tas: Alias,\n\t): QueryBuilder<TResult & { [P in Alias]: NonNullable<TResult[K]> }> {\n\t\tconst builder = this.clone();\n\n\t\t// Create CoalesceExpressionIntent\n\t\tconst coalesceIntent: ExpressionIntent = {\n\t\t\tkind: 'coalesce',\n\t\t\tfields: fields as readonly string[],\n\t\t\tas,\n\t\t};\n\n\t\t// If we already have a SelectWithExpressionsIntent, add to it\n\t\tif (builder.selectIntent?.type === 'expressions') {\n\t\t\tbuilder.selectIntent = {\n\t\t\t\ttype: 'expressions',\n\t\t\t\tcolumns: [...builder.selectIntent.columns, coalesceIntent],\n\t\t\t};\n\t\t} else if (builder.selectIntent?.type === 'fields') {\n\t\t\t// Convert fields to expressions and add coalesce\n\t\t\tconst fieldExpressions: ExpressionIntent[] =\n\t\t\t\tbuilder.selectIntent.fields.map(\n\t\t\t\t\t(field) => ({ kind: 'column', column: field }) as ExpressionIntent,\n\t\t\t\t);\n\t\t\tbuilder.selectIntent = {\n\t\t\t\ttype: 'expressions',\n\t\t\t\tcolumns: [...fieldExpressions, coalesceIntent],\n\t\t\t};\n\t\t} else {\n\t\t\t// No select intent yet - start with coalesce only\n\t\t\t// This means SELECT * plus the coalesce column\n\t\t\tbuilder.selectIntent = {\n\t\t\t\ttype: 'expressions',\n\t\t\t\tcolumns: [coalesceIntent],\n\t\t\t};\n\t\t}\n\n\t\t// SAFETY: coalesce() adds a computed column to the result type.\n\t\t// The runtime value is identical (same QueryBuilderImpl), only the\n\t\t// phantom TResult type parameter changes — invariant in QueryBuilder,\n\t\t// hence the double cast.\n\t\treturn builder as unknown as QueryBuilder<\n\t\t\tTResult & { [P in Alias]: NonNullable<TResult[K]> }\n\t\t>;\n\t}\n\n\tcount(\n\t\tfieldOrOptions?: AggregateOptions | string | DistinctField,\n\t\tas?: string,\n\t): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\n\t\tlet field: string | undefined;\n\t\tlet alias: string | undefined = as;\n\t\tlet distinct: boolean | undefined;\n\n\t\tif (fieldOrOptions === undefined) {\n\t\t\t// count() - COUNT(*)\n\t\t} else if (typeof fieldOrOptions === 'string') {\n\t\t\t// count('field', 'alias') - COUNT(field)\n\t\t\tfield = fieldOrOptions;\n\t\t} else if (isDistinctField(fieldOrOptions)) {\n\t\t\t// count(distinct('field'), 'alias') - COUNT(DISTINCT field)\n\t\t\tfield = fieldOrOptions.field;\n\t\t\tdistinct = true;\n\t\t} else {\n\t\t\t// count({ field, as }) - AggregateOptions\n\t\t\tfield = fieldOrOptions.field;\n\t\t\talias = fieldOrOptions.as ?? as;\n\t\t}\n\n\t\tconst agg: AggregateIntent = {\n\t\t\tfunction: 'count',\n\t\t\t...(field !== undefined && { field }),\n\t\t\t...(alias !== undefined && { as: alias }),\n\t\t\t...(distinct !== undefined && { distinct }),\n\t\t};\n\t\tbuilder.aggregates.push(agg);\n\t\treturn builder;\n\t}\n\n\tsum(field: string | DistinctField, as?: string): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tconst isDistinct = isDistinctField(field);\n\t\tconst fieldName = isDistinct ? field.field : field;\n\t\tconst agg: AggregateIntent = {\n\t\t\tfunction: 'sum',\n\t\t\tfield: fieldName,\n\t\t\t...(isDistinct && { distinct: true }),\n\t\t\t...(as !== undefined && { as }),\n\t\t};\n\t\tbuilder.aggregates.push(agg);\n\t\treturn builder;\n\t}\n\n\tavg(field: string | DistinctField, as?: string): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tconst isDistinct = isDistinctField(field);\n\t\tconst fieldName = isDistinct ? field.field : field;\n\t\tconst agg: AggregateIntent = {\n\t\t\tfunction: 'avg',\n\t\t\tfield: fieldName,\n\t\t\t...(isDistinct && { distinct: true }),\n\t\t\t...(as !== undefined && { as }),\n\t\t};\n\t\tbuilder.aggregates.push(agg);\n\t\treturn builder;\n\t}\n\n\tmin(field: string, as?: string): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tconst agg: AggregateIntent = {\n\t\t\tfunction: 'min',\n\t\t\tfield,\n\t\t\t...(as !== undefined && { as }),\n\t\t};\n\t\tbuilder.aggregates.push(agg);\n\t\treturn builder;\n\t}\n\n\tmax(field: string, as?: string): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tconst agg: AggregateIntent = {\n\t\t\tfunction: 'max',\n\t\t\tfield,\n\t\t\t...(as !== undefined && { as }),\n\t\t};\n\t\tbuilder.aggregates.push(agg);\n\t\treturn builder;\n\t}\n\n\tgroupBy(fields: readonly string[]): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.groupByFields.push(...fields);\n\t\treturn builder;\n\t}\n\n\thaving(condition: WhereIntent): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.havingIntents.push(condition);\n\t\treturn builder;\n\t}\n\n\tdistinct(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.isDistinctQuery = true;\n\t\treturn builder;\n\t}\n\n\t/**\n\t * Apply PostgreSQL DISTINCT ON (...) to the query.\n\t *\n\t * @param columns - One or more column names to deduplicate on\n\t * @returns A new QueryBuilder with DISTINCT ON applied\n\t *\n\t * @example\n\t * ```typescript\n\t * orm.select('users').distinctOn('department').all();\n\t * // SQL: SELECT DISTINCT ON (\"department\") * FROM \"users\"\n\t *\n\t * orm.select('logs').distinctOn('user_id', 'action').all();\n\t * // SQL: SELECT DISTINCT ON (\"user_id\", \"action\") * FROM \"logs\"\n\t * ```\n\t */\n\tdistinctOn(...columns: string[]): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.distinctOnColumns = columns;\n\t\treturn builder;\n\t}\n\n\t// --------------------------------------------------------------------------\n\t// Row-level locking (E15)\n\t// --------------------------------------------------------------------------\n\n\tforUpdate(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = {\n\t\t\tstrength: 'forUpdate',\n\t\t\twaitPolicy: builder.lockIntent?.waitPolicy ?? 'block',\n\t\t};\n\t\treturn builder;\n\t}\n\n\tforShare(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = {\n\t\t\tstrength: 'forShare',\n\t\t\twaitPolicy: builder.lockIntent?.waitPolicy ?? 'block',\n\t\t};\n\t\treturn builder;\n\t}\n\n\tforNoKeyUpdate(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = {\n\t\t\tstrength: 'forNoKeyUpdate',\n\t\t\twaitPolicy: builder.lockIntent?.waitPolicy ?? 'block',\n\t\t};\n\t\treturn builder;\n\t}\n\n\tforKeyShare(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = {\n\t\t\tstrength: 'forKeyShare',\n\t\t\twaitPolicy: builder.lockIntent?.waitPolicy ?? 'block',\n\t\t};\n\t\treturn builder;\n\t}\n\n\tlock(\n\t\tstrength: import('@dbsp/types').LockStrength,\n\t\twaitPolicy?: import('@dbsp/types').LockWaitPolicy,\n\t): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = { strength, waitPolicy: waitPolicy ?? 'block' };\n\t\treturn builder;\n\t}\n\n\tskipLocked(): QueryBuilder<TResult> {\n\t\tif (!this.lockIntent) {\n\t\t\tthrow new Error(\n\t\t\t\t'skipLocked() requires a preceding lock method (forUpdate, forShare, etc.)',\n\t\t\t);\n\t\t}\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = { ...this.lockIntent, waitPolicy: 'skipLocked' };\n\t\treturn builder;\n\t}\n\n\tnoWait(): QueryBuilder<TResult> {\n\t\tif (!this.lockIntent) {\n\t\t\tthrow new Error(\n\t\t\t\t'noWait() requires a preceding lock method (forUpdate, forShare, etc.)',\n\t\t\t);\n\t\t}\n\t\tconst builder = this.clone();\n\t\tbuilder.lockIntent = { ...this.lockIntent, waitPolicy: 'noWait' };\n\t\treturn builder;\n\t}\n\n\torderBy(\n\t\tfieldOrRecordOrSpecs:\n\t\t\t| string\n\t\t\t| OrderByRecord\n\t\t\t| readonly OrderBySpec[]\n\t\t\t| ExpressionRef\n\t\t\t| ExpressionSpec,\n\t\tdirection?: SortDirection,\n\t\toptions?: { nulls?: import('./types.js').NullsPosition },\n\t): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\n\t\t// ExpressionRef form: orderBy(expr) or orderBy(expr, 'desc') or orderBy(expr, 'desc', { nulls: 'last' })\n\t\tif (fieldOrRecordOrSpecs instanceof ExpressionRef) {\n\t\t\tbuilder.orderByIntents.push({\n\t\t\t\texpression: fieldOrRecordOrSpecs.intent,\n\t\t\t\tdirection: direction ?? 'asc',\n\t\t\t\t...(options?.nulls !== undefined ? { nulls: options.nulls } : {}),\n\t\t\t});\n\t\t\treturn builder;\n\t\t}\n\n\t\t// ExpressionSpec form: orderBy(relationColumn(...)) or other plain ExpressionSpec objects\n\t\tif (isExpressionSpec(fieldOrRecordOrSpecs as ColumnSpec)) {\n\t\t\tbuilder.orderByIntents.push({\n\t\t\t\texpression: (fieldOrRecordOrSpecs as { intent: ExpressionIntent })\n\t\t\t\t\t.intent,\n\t\t\t\tdirection: direction ?? 'asc',\n\t\t\t\t...(options?.nulls !== undefined ? { nulls: options.nulls } : {}),\n\t\t\t});\n\t\t\treturn builder;\n\t\t}\n\n\t\t// String form: orderBy('field') or orderBy('field', 'desc') or orderBy('field', 'desc', { nulls: 'last' })\n\t\tif (typeof fieldOrRecordOrSpecs === 'string') {\n\t\t\tbuilder.orderByIntents.push({\n\t\t\t\tfield: fieldOrRecordOrSpecs,\n\t\t\t\tdirection: direction ?? 'asc',\n\t\t\t\t...(options?.nulls !== undefined ? { nulls: options.nulls } : {}),\n\t\t\t});\n\t\t\treturn builder;\n\t\t}\n\n\t\t// Array form: orderBy([{ column, direction, nulls }])\n\t\tif (Array.isArray(fieldOrRecordOrSpecs)) {\n\t\t\tfor (const spec of fieldOrRecordOrSpecs) {\n\t\t\t\tbuilder.orderByIntents.push({\n\t\t\t\t\tfield: spec.column,\n\t\t\t\t\tdirection: spec.direction ?? 'asc',\n\t\t\t\t\tnulls: spec.nulls,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn builder;\n\t\t}\n\n\t\t// Object form: orderBy({ field1: 'desc', field2: 'asc' })\n\t\tfor (const [field, dir] of Object.entries(fieldOrRecordOrSpecs)) {\n\t\t\tbuilder.orderByIntents.push({\n\t\t\t\tfield,\n\t\t\t\tdirection: dir,\n\t\t\t});\n\t\t}\n\t\treturn builder;\n\t}\n\n\tlimit(count: number): QueryBuilder<TResult> {\n\t\tif (!Number.isSafeInteger(count) || count < 0) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'limit',\n\t\t\t\t'limit must be a non-negative safe integer',\n\t\t\t);\n\t\t}\n\t\tconst builder = this.clone();\n\t\tbuilder.limitValue = count;\n\t\treturn builder;\n\t}\n\n\toffset(count: number): QueryBuilder<TResult> {\n\t\tif (!Number.isSafeInteger(count) || count < 0) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'offset',\n\t\t\t\t'offset must be a non-negative safe integer',\n\t\t\t);\n\t\t}\n\t\tconst builder = this.clone();\n\t\tbuilder.offsetValue = count;\n\t\treturn builder;\n\t}\n\n\twhere(condition: WhereIntent | WhereFilter<TResult>): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\t// Detect ExpressionRef used as a standalone boolean WHERE predicate.\n\t\t// op('!=', exprRef('a'), exprRef('b')) returns ExpressionRef which has __expr:true\n\t\t// but no `kind` property, so isWhereIntent() returns false and objectToWhereIntent()\n\t\t// would map `__expr: true` as a column field. Handle this before the WhereIntent check.\n\t\tif (condition instanceof ExpressionRef) {\n\t\t\t// Wrap the expression intent in a WhereExpressionIntent with no value/operator.\n\t\t\t// The WHERE handler detects this and emits the expression node directly.\n\t\t\tconst whereExpr = {\n\t\t\t\tkind: 'expression',\n\t\t\t\texpr: condition.intent,\n\t\t\t} as unknown as WhereIntent;\n\t\t\tbuilder.whereIntents.push(whereExpr);\n\t\t\treturn builder;\n\t\t}\n\t\t// Convert object filter to WhereIntent if needed\n\t\tconst intent = isWhereIntent(condition)\n\t\t\t? condition\n\t\t\t: objectToWhereIntent(condition as WhereFilter<Record<string, unknown>>);\n\t\tbuilder.whereIntents.push(intent);\n\t\treturn builder;\n\t}\n\n\tjoin(\n\t\trelationOrTableOrBatch: string | BatchValuesRef,\n\t\topts?: { type?: 'inner' | 'left'; on?: WhereIntent; as?: string },\n\t): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tconst type = opts?.type ?? 'inner';\n\n\t\tif (isBatchValuesRef(relationOrTableOrBatch)) {\n\t\t\tconst bv = relationOrTableOrBatch;\n\t\t\tif (!opts?.on) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'join(batchValuesRef): an `on` condition is required for BatchValues joins',\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Validate all identifiers that reach SQL as quoted names in the\n\t\t\t// unnest() RangeFunction: source alias, column aliases, and the\n\t\t\t// explicit join alias override (opts.as).\n\t\t\tvalidateIdentifier(bv.alias, 'alias');\n\t\t\tfor (const col of bv.columns) {\n\t\t\t\tvalidateIdentifier(col, 'column');\n\t\t\t}\n\t\t\tif (opts.as !== undefined) {\n\t\t\t\tvalidateIdentifier(opts.as, 'alias');\n\t\t\t}\n\t\t\tconst joinIntent: JoinIntent = {\n\t\t\t\tbatchValues: {\n\t\t\t\t\tdata: bv.data,\n\t\t\t\t\tcolumns: bv.columns,\n\t\t\t\t\ttypes: bv.types,\n\t\t\t\t\talias: bv.alias,\n\t\t\t\t\tordinality: bv.ordinality,\n\t\t\t\t},\n\t\t\t\ton: opts.on,\n\t\t\t\ttype,\n\t\t\t\t...(opts.as !== undefined ? { alias: opts.as } : { alias: bv.alias }),\n\t\t\t};\n\t\t\tbuilder.joinIntents.push(joinIntent);\n\t\t} else {\n\t\t\t// FIND-011: Validate string table/relation argument\n\t\t\tvalidateIdentifier(relationOrTableOrBatch, 'table');\n\t\t\t// FIND-008: Validate the as alias when provided\n\t\t\tif (opts?.as !== undefined) {\n\t\t\t\tvalidateIdentifier(opts.as, 'alias');\n\t\t\t}\n\t\t\tconst joinIntent: JoinIntent = opts?.on\n\t\t\t\t? {\n\t\t\t\t\t\ttable: relationOrTableOrBatch,\n\t\t\t\t\t\ton: opts.on,\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\t...(opts.as !== undefined && { alias: opts.as }),\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\trelation: relationOrTableOrBatch,\n\t\t\t\t\t\ttype,\n\t\t\t\t\t\t...(opts?.as !== undefined && { alias: opts.as }),\n\t\t\t\t\t};\n\t\t\tbuilder.joinIntents.push(joinIntent);\n\t\t}\n\t\treturn builder;\n\t}\n\n\twithStrictMode(strict: boolean): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.strictModeOverride = strict;\n\t\treturn builder;\n\t}\n\n\twithRelationHint(target: string, relation: string): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\t(builder.relationHints as Record<string, string>)[target] = relation;\n\t\treturn builder;\n\t}\n\n\twithPlanOptions(options: PlanOptions): QueryBuilder<TResult> {\n\t\treturn this.cloneWithCtxOverride({\n\t\t\tplanOptionsOverride: {\n\t\t\t\t...this.ctx.planOptionsOverride,\n\t\t\t\t...options,\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Get effective strict mode (override takes precedence over ORM-level).\n\t */\n\tprivate getEffectiveStrictMode(): boolean {\n\t\treturn this.strictModeOverride !== undefined\n\t\t\t? this.strictModeOverride\n\t\t\t: this.ctx.strictMode;\n\t}\n\n\tplan(): PlanReport {\n\t\tconst intent = this.buildIntent();\n\n\t\t// E15: Warn when lock is used outside a transaction context\n\t\tif (intent.lock && !this.ctx.inTransaction) {\n\t\t\tconsole.warn(\n\t\t\t\t'[dbsp] Row-level lock (FOR UPDATE/SHARE) used outside a transaction. ' +\n\t\t\t\t\t'Locks are only effective within a transaction.',\n\t\t\t);\n\t\t}\n\n\t\t// Apply relation hints to includes before planning\n\t\tconst intentWithHints = this.applyRelationHints(intent);\n\n\t\t// Build plan options: dialectCapabilities + per-query overrides\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...(this.ctx.dialectCapabilities && {\n\t\t\t\tdialectCapabilities: this.ctx.dialectCapabilities,\n\t\t\t}),\n\t\t\t// planOptions (global + per-query) take highest precedence\n\t\t\t...this.ctx.planOptionsOverride,\n\t\t};\n\n\t\ttry {\n\t\t\treturn plan(intentWithHints, this.ctx.model, planOptions);\n\t\t} catch (error) {\n\t\t\tif (error instanceof AmbiguousPlanError) {\n\t\t\t\treturn this.handleAmbiguity(error, intentWithHints, planOptions);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync all(): Promise<TResult[]> {\n\t\tconst adapter = this.getConfiguredAdapter();\n\n\t\t// E17b: Hook-aware execution path\n\t\tif (this.ctx.hookStore && hasHooks(this.ctx.hookStore)) {\n\t\t\treturn this.executeWithHooks(adapter, 'all');\n\t\t}\n\n\t\t// Fast path: no hooks — existing behavior, zero overhead\n\t\tconst planReport = this.plan();\n\n\t\t// Build compile options with exactOptionalPropertyTypes compliance\n\t\tconst compileOptions: {\n\t\t\tschemaName?: string;\n\t\t\tmodel: ModelIR;\n\t\t} = { model: this.ctx.model };\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\n\t\t// Use compileWithIncludes to get subquery include info for hasMany relations\n\t\tconst compiledWithIncludes = adapter.compileWithIncludes(\n\t\t\tplanReport,\n\t\t\tcompileOptions,\n\t\t);\n\t\tconst mainResults = (await adapter.execute(\n\t\t\tcompiledWithIncludes.main,\n\t\t)) as TResult[];\n\n\t\t// Create hydrator for result transformation (AUD-005)\n\t\tconst hydrator = new ResultHydrator<TResult>(\n\t\t\tthis.ctx.model,\n\t\t\tthis.from,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\n\t\t// E2E-004: Hydrate json_agg includes by parsing JSON columns\n\t\thydrator.hydrateJsonAggIncludes(mainResults, planReport);\n\n\t\t// E2E-004: Hydrate JOIN includes by grouping dot-prefixed columns\n\t\thydrator.hydrateJoinIncludes(mainResults, planReport);\n\n\t\t// Process subquery includes (hasMany hydration - DX-033)\n\t\tif (compiledWithIncludes.subqueryIncludes.length > 0) {\n\t\t\tawait hydrator.hydrateIncludes(\n\t\t\t\tmainResults,\n\t\t\t\tcompiledWithIncludes.subqueryIncludes,\n\t\t\t\tadapter,\n\t\t\t\tcompileOptions,\n\t\t\t);\n\t\t}\n\n\t\t// Process recursive includes if any\n\t\tif (this.recursiveIncludes.length > 0) {\n\t\t\tawait hydrator.processRecursiveIncludes(\n\t\t\t\tmainResults,\n\t\t\t\tthis.recursiveIncludes,\n\t\t\t\tadapter,\n\t\t\t);\n\t\t}\n\n\t\treturn mainResults;\n\t}\n\n\tasync first(): Promise<TResult | undefined> {\n\t\t// E17b: Hook-aware path — hooks see resultType='first'\n\t\tif (this.ctx.hookStore && hasHooks(this.ctx.hookStore)) {\n\t\t\tconst adapter = this.getConfiguredAdapter();\n\t\t\tconst rows = await this.executeWithHooks<TResult[]>(adapter, 'first');\n\t\t\treturn rows[0];\n\t\t}\n\t\tconst rows = await this.all();\n\t\treturn rows[0];\n\t}\n\n\tasync firstOrThrow(): Promise<TResult> {\n\t\tconst result = await this.first();\n\t\tif (result === undefined) {\n\t\t\tthrow new NotFoundError(this.from);\n\t\t}\n\t\treturn result;\n\t}\n\n\tasync byId(\n\t\tvalue: string | number | Record<string, unknown>,\n\t): Promise<TResult | undefined> {\n\t\tconst condition = this.buildPkCondition(value);\n\t\treturn this.where(condition).first();\n\t}\n\n\tasync byIdOrThrow(\n\t\tvalue: string | number | Record<string, unknown>,\n\t): Promise<TResult> {\n\t\tconst result = await this.byId(value);\n\t\tif (result === undefined) {\n\t\t\tthrow new NotFoundError(\n\t\t\t\tthis.from,\n\t\t\t\t`No record found with the specified primary key`,\n\t\t\t);\n\t\t}\n\t\treturn result;\n\t}\n\n\tasync byIds(values: readonly (string | number)[]): Promise<TResult[]> {\n\t\tif (values.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t\treturn this.where(inArray(this.getSimplePkColumn(), [...values])).all();\n\t}\n\n\t/**\n\t * Get the simple primary key column name for the current table.\n\t * Returns the first PK column if composite, falls back to 'id' if undefined.\n\t */\n\tprivate getSimplePkColumn(): string {\n\t\tconst table = this.ctx.model.getTable(this.from);\n\t\tconst pk = table?.primaryKey;\n\t\tif (typeof pk === 'string') {\n\t\t\treturn pk;\n\t\t}\n\t\tif (Array.isArray(pk) && pk.length > 0) {\n\t\t\treturn pk[0]!;\n\t\t}\n\t\treturn 'id'; // fallback for legacy schemas without explicit PK\n\t}\n\n\t/**\n\t * Build a where condition for a primary key lookup.\n\t * Supports simple PKs (string | number) and composite PKs (object).\n\t */\n\tprivate buildPkCondition(\n\t\tvalue: string | number | Record<string, unknown>,\n\t): WhereIntent {\n\t\tif (typeof value === 'string' || typeof value === 'number') {\n\t\t\t// Simple PK - use schema-defined PK column\n\t\t\treturn eq(this.getSimplePkColumn(), value);\n\t\t}\n\t\t// FIND-009: Validate composite PK keys against schema-defined primary key columns\n\t\tconst table = this.ctx.model.getTable(this.from);\n\t\tif (!table) {\n\t\t\tthrow new InvalidOperationError('byId', 'Unknown table');\n\t\t}\n\t\tconst rawPk = table.primaryKey ?? [];\n\t\tconst knownPkCols = new Set(typeof rawPk === 'string' ? [rawPk] : rawPk);\n\t\t// Composite PK - validate keys then build AND condition\n\t\tconst entries = Object.entries(value);\n\t\tif (entries.length === 0) {\n\t\t\tthrow new Error('Composite primary key cannot be empty');\n\t\t}\n\t\tif (knownPkCols.size > 0) {\n\t\t\tfor (const key of Object.keys(value)) {\n\t\t\t\tif (!knownPkCols.has(key)) {\n\t\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t\t'byId',\n\t\t\t\t\t\t`Unknown primary key column: ${key}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (entries.length === 1) {\n\t\t\tconst entry = entries[0];\n\t\t\tif (!entry) {\n\t\t\t\tthrow new Error('Composite primary key entry missing');\n\t\t\t}\n\t\t\tconst [field, fieldValue] = entry;\n\t\t\treturn eq(field, fieldValue);\n\t\t}\n\t\tconst conditions = entries.map(([field, fieldValue]) =>\n\t\t\teq(field, fieldValue),\n\t\t);\n\t\treturn and(...conditions);\n\t}\n\n\tdump(meta?: DumpMetaInput): Dump {\n\t\tconst adapter = this.getConfiguredAdapter();\n\t\tconst planReport = this.plan();\n\n\t\t// Build compile options with exactOptionalPropertyTypes compliance\n\t\tconst compileOptions: {\n\t\t\tschemaName?: string;\n\t\t\tmodel: ModelIR;\n\t\t} = { model: this.ctx.model };\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\n\t\tconst compiled = adapter.compile(planReport, compileOptions);\n\n\t\t// Build DumpMeta: adapter-level schema + caller-supplied queryName/correlationId\n\t\tconst dumpMeta: DumpMetaInput = {\n\t\t\t...(meta?.queryName !== undefined && { queryName: meta.queryName }),\n\t\t\t...(meta?.correlationId !== undefined && {\n\t\t\t\tcorrelationId: meta.correlationId,\n\t\t\t}),\n\t\t};\n\n\t\t// Use adapter.createDump() to properly capture adapter's schema\n\t\t// Then merge with context schema if needed\n\t\tconst dump = adapter.createDump(planReport, compiled, dumpMeta);\n\n\t\t// If adapter didn't set schema but context has one, add it\n\t\tif (dump.meta?.schema === undefined && this.ctx.schemaName !== undefined) {\n\t\t\treturn {\n\t\t\t\t...dump,\n\t\t\t\tmeta: {\n\t\t\t\t\t...dump.meta,\n\t\t\t\t\tschema: this.ctx.schemaName,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn dump;\n\t}\n\n\tasync exists(): Promise<boolean> {\n\t\tconst adapter = this.getConfiguredAdapter();\n\n\t\t// E17b: Hook-aware path for exists()\n\t\tif (this.ctx.hookStore && hasHooks(this.ctx.hookStore)) {\n\t\t\t// INV-07: Re-entrancy guard\n\t\t\treturn withReentrancyGuard(this.ctx.hookStore, (s) =>\n\t\t\t\tthis.existsWithHooks(adapter, s),\n\t\t\t);\n\t\t}\n\n\t\t// Fast path: no hooks\n\t\tconst existsIntent = this.buildExistsIntent();\n\t\tconst intentWithHints = this.applyRelationHints(existsIntent);\n\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...(this.ctx.dialectCapabilities && {\n\t\t\t\tdialectCapabilities: this.ctx.dialectCapabilities,\n\t\t\t}),\n\t\t\t...this.ctx.planOptionsOverride,\n\t\t};\n\n\t\tconst planReport = this.planWithAmbiguityHandling(\n\t\t\tintentWithHints,\n\t\t\tplanOptions,\n\t\t);\n\n\t\tconst compileOptions: {\n\t\t\tschemaName?: string;\n\t\t\tmodel: ModelIR;\n\t\t} = { model: this.ctx.model };\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\n\t\tconst compiled = adapter.compile(planReport, compileOptions);\n\t\tconst rows = await adapter.execute(compiled);\n\t\treturn (\n\t\t\trows.length > 0 && (rows[0] as Record<string, unknown>).exists === true\n\t\t);\n\t}\n\n\tprivate async existsWithHooks(\n\t\tadapter: Adapter,\n\t\tstore: HookStore,\n\t): Promise<boolean> {\n\t\tconst startTime = Date.now();\n\n\t\t// Build raw intent (without defaultFilters) for hooks\n\t\tconst rawIntent = this.buildIntent(false);\n\t\tconst beforeCtx: QueryHookContext = {\n\t\t\ttable: this.from,\n\t\t\toperation: 'select',\n\t\t\tintent: rawIntent,\n\t\t\tresultType: 'exists',\n\t\t\t...(this.ctx.schemaName !== undefined && {\n\t\t\t\tschemaName: this.ctx.schemaName,\n\t\t\t}),\n\t\t\t...(this.ctx.inTransaction && { inTransaction: true }),\n\t\t};\n\n\t\t// Run beforeQuery hooks\n\t\tlet intent: QueryIntent;\n\t\ttry {\n\t\t\tconst afterHookCtx = await runBeforeQueryHooks(\n\t\t\t\tstore.beforeQuery,\n\t\t\t\tbeforeCtx,\n\t\t\t\tthis.ctx.onHookError,\n\t\t\t);\n\t\t\tintent = afterHookCtx.intent;\n\t\t} catch (error) {\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tthrow await runOnErrorHooks(store.onError, {\n\t\t\t\t\ttable: this.from,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent: rawIntent,\n\t\t\t\t\tphase: 'beforeQuery',\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\t// Apply defaultFilters AFTER hooks (INV-01)\n\t\tintent = this.applyDefaultFiltersToIntent(intent);\n\n\t\t// Build exists-wrapped intent from the (potentially modified) intent\n\t\tconst existsIntent = this.buildExistsIntentFromIntent(intent);\n\t\tconst intentWithHints = this.applyRelationHints(existsIntent);\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...(this.ctx.dialectCapabilities && {\n\t\t\t\tdialectCapabilities: this.ctx.dialectCapabilities,\n\t\t\t}),\n\t\t\t...this.ctx.planOptionsOverride,\n\t\t};\n\t\tconst planReport = this.planWithAmbiguityHandling(\n\t\t\tintentWithHints,\n\t\t\tplanOptions,\n\t\t);\n\t\tconst compileOptions: { schemaName?: string; model: ModelIR } = {\n\t\t\tmodel: this.ctx.model,\n\t\t};\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\t\tconst compiled = adapter.compile(planReport, compileOptions);\n\t\tconst rows = await adapter.execute(compiled);\n\t\tconst result =\n\t\t\trows.length > 0 && (rows[0] as Record<string, unknown>).exists === true;\n\n\t\t// afterQuery with boolean result\n\t\tconst afterCtx: QueryHookContext = {\n\t\t\ttable: this.from,\n\t\t\toperation: 'select',\n\t\t\tintent,\n\t\t\tresultType: 'exists',\n\t\t\tsql: compiled.sql,\n\t\t\tparameters: compiled.parameters,\n\t\t\tduration: Date.now() - startTime,\n\t\t\t...(this.ctx.schemaName !== undefined && {\n\t\t\t\tschemaName: this.ctx.schemaName,\n\t\t\t}),\n\t\t};\n\t\ttry {\n\t\t\treturn await runAfterQueryHooks(\n\t\t\t\tstore.afterQuery,\n\t\t\t\tafterCtx,\n\t\t\t\tresult,\n\t\t\t\tthis.ctx.onHookError,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tthrow await runOnErrorHooks(store.onError, {\n\t\t\t\t\ttable: this.from,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent,\n\t\t\t\t\tphase: 'afterQuery',\n\t\t\t\t\tsql: compiled.sql,\n\t\t\t\t});\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\texistsDump(): Dump {\n\t\tconst adapter = this.getConfiguredAdapter();\n\t\tconst existsIntent = this.buildExistsIntent();\n\t\tconst intentWithHints = this.applyRelationHints(existsIntent);\n\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...(this.ctx.dialectCapabilities && {\n\t\t\t\tdialectCapabilities: this.ctx.dialectCapabilities,\n\t\t\t}),\n\t\t\t...this.ctx.planOptionsOverride,\n\t\t};\n\n\t\tconst planReport = this.planWithAmbiguityHandling(\n\t\t\tintentWithHints,\n\t\t\tplanOptions,\n\t\t);\n\n\t\tconst compileOptions: {\n\t\t\tschemaName?: string;\n\t\t\tmodel: ModelIR;\n\t\t} = { model: this.ctx.model };\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\n\t\tconst compiled = adapter.compile(planReport, compileOptions);\n\t\tconst dump = adapter.createDump(planReport, compiled);\n\n\t\tif (dump.meta?.schema === undefined && this.ctx.schemaName !== undefined) {\n\t\t\treturn {\n\t\t\t\t...dump,\n\t\t\t\tmeta: {\n\t\t\t\t\t...dump.meta,\n\t\t\t\t\tschema: this.ctx.schemaName,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn dump;\n\t}\n\n\texecute(): Promise<TResult[]> {\n\t\treturn this.all();\n\t}\n\n\tstream(options?: StreamOptions): AsyncIterableIterator<TResult> {\n\t\treturn streamImpl.stream(this, options);\n\t}\n\n\t/**\n\t * Execute the query with offset-based pagination.\n\t */\n\tasync paginate(options?: PaginateOptions): Promise<PaginatedResult<TResult>> {\n\t\treturn paginationImpl.paginate(this, options);\n\t}\n\n\t/**\n\t * Execute the query with cursor-based pagination.\n\t */\n\tasync cursorPaginate(\n\t\toptions?: CursorPaginateOptions,\n\t): Promise<CursorPaginatedResult<TResult>> {\n\t\treturn paginationImpl.cursorPaginate(this, options);\n\t}\n\n\t/**\n\t * Get configured adapter, throwing if not configured.\n\t * @throws {ExecutionError} If adapter is not configured\n\t * @returns The configured adapter instance\n\t */\n\t/** @internal — called by pagination-impl and stream-impl */\n\tgetConfiguredAdapter(): Adapter {\n\t\tif (!this.ctx.adapter) {\n\t\t\tthrow new ExecutionError({\n\t\t\t\toperation: 'query execution',\n\t\t\t\treason: 'Adapter not configured',\n\t\t\t\tfix: 'Pass an adapter to createOrm({ adapter: yourAdapter })',\n\t\t\t});\n\t\t}\n\t\treturn this.ctx.adapter;\n\t}\n\n\t/**\n\t * Apply relation hints to includes that don't have explicit `via`.\n\t */\n\t/** @internal — called by stream-impl */\n\tapplyRelationHints(intent: QueryIntent): QueryIntent {\n\t\tif (!intent.include || Object.keys(this.relationHints).length === 0) {\n\t\t\treturn intent;\n\t\t}\n\n\t\tconst updatedIncludes = intent.include.map((inc) =>\n\t\t\tthis.applyHintToInclude(inc),\n\t\t);\n\n\t\treturn {\n\t\t\t...intent,\n\t\t\tinclude: updatedIncludes,\n\t\t};\n\t}\n\n\t/**\n\t * Apply relation hint to a single include (recursively).\n\t */\n\tprivate applyHintToInclude(inc: IncludeIntent): IncludeIntent {\n\t\t// If already has explicit via, don't override\n\t\tif (inc.via !== undefined) {\n\t\t\t// But still process nested includes\n\t\t\tif (inc.include && inc.include.length > 0) {\n\t\t\t\treturn {\n\t\t\t\t\t...inc,\n\t\t\t\t\tinclude: inc.include.map((nested) => this.applyHintToInclude(nested)),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn inc;\n\t\t}\n\n\t\t// Check if we have a hint for this target\n\t\tconst hint = this.relationHints[inc.relation];\n\t\tconst result: IncludeIntent = hint ? { ...inc, via: hint } : inc;\n\n\t\t// Process nested includes\n\t\tif (result.include && result.include.length > 0) {\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\tinclude: result.include.map((nested) =>\n\t\t\t\t\tthis.applyHintToInclude(nested),\n\t\t\t\t),\n\t\t\t};\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Build the QueryIntent from current state.\n\t * Handles exactOptionalPropertyTypes by only including defined properties.\n\t */\n\t/** @internal Used by CteQueryBuilder to access query intent without executing. */\n\tbuildIntent(applyDefaultFilters = true): QueryIntent {\n\t\tconst intent: Mutable<QueryIntent> = {\n\t\t\ttype: 'select',\n\t\t\tfrom: this.from,\n\t\t};\n\n\t\t// Handle aggregates - convert to SelectAggregateIntent\n\t\tif (this.aggregates.length > 0) {\n\t\t\tconst aggregateSelect: Mutable<SelectAggregateIntent> = {\n\t\t\t\ttype: 'aggregate',\n\t\t\t\taggregates: [...this.aggregates],\n\t\t\t};\n\t\t\t// Add group by fields to the select for projection\n\t\t\tif (this.groupByFields.length > 0) {\n\t\t\t\taggregateSelect.fields = [...this.groupByFields];\n\t\t\t}\n\t\t\tintent.select = aggregateSelect as SelectAggregateIntent;\n\t\t} else if (this.selectIntent !== undefined) {\n\t\t\tintent.select = this.selectIntent;\n\t\t}\n\n\t\t// Combine default filter (soft delete) with user-provided where conditions\n\t\tconst allWhereIntents: WhereIntent[] = [];\n\n\t\t// Prepend default filter for this table (if configured and not skipped)\n\t\tif (applyDefaultFilters) {\n\t\t\tconst tableDefaultFilter =\n\t\t\t\t!this.skipDefaultFilters && this.ctx.defaultFilters\n\t\t\t\t\t? this.ctx.defaultFilters[this.from]\n\t\t\t\t\t: undefined;\n\t\t\tif (tableDefaultFilter) {\n\t\t\t\tallWhereIntents.push(tableDefaultFilter);\n\t\t\t}\n\t\t}\n\n\t\t// Add user-provided filters\n\t\tallWhereIntents.push(...this.whereIntents);\n\n\t\t// Combine with AND\n\t\tif (allWhereIntents.length === 1) {\n\t\t\tconst singleWhere = allWhereIntents[0];\n\t\t\tif (singleWhere !== undefined) {\n\t\t\t\tintent.where = singleWhere;\n\t\t\t}\n\t\t} else if (allWhereIntents.length > 1) {\n\t\t\tintent.where = and(...allWhereIntents);\n\t\t}\n\n\t\t// Combine multiple having conditions with AND (DX-034)\n\t\tif (this.havingIntents.length === 1) {\n\t\t\tconst singleHaving = this.havingIntents[0];\n\t\t\tif (singleHaving !== undefined) {\n\t\t\t\tintent.having = singleHaving;\n\t\t\t}\n\t\t} else if (this.havingIntents.length > 1) {\n\t\t\tintent.having = and(...this.havingIntents);\n\t\t}\n\n\t\t// Add SELECT DISTINCT flag (DX-034)\n\t\tif (this.isDistinctQuery) {\n\t\t\tintent.distinct = true;\n\t\t}\n\n\t\t// Add DISTINCT ON columns (PostgreSQL-specific)\n\t\tif (this.distinctOnColumns.length > 0) {\n\t\t\tintent.distinctOn = [...this.distinctOnColumns];\n\t\t}\n\n\t\tif (this.includes.length > 0) {\n\t\t\tintent.include = this.includes;\n\t\t}\n\t\tif (this.groupByFields.length > 0) {\n\t\t\tintent.groupBy = [...this.groupByFields];\n\t\t}\n\t\tif (this.orderByIntents.length > 0) {\n\t\t\tintent.orderBy = [...this.orderByIntents];\n\t\t}\n\t\tif (this.limitValue !== undefined) {\n\t\t\tintent.limit = this.limitValue;\n\t\t}\n\t\tif (this.offsetValue !== undefined) {\n\t\t\tintent.offset = this.offsetValue;\n\t\t}\n\n\t\t// Lock clause (E15)\n\t\tif (this.lockIntent) {\n\t\t\tif (this.groupByFields.length > 0) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'lock',\n\t\t\t\t\t'FOR UPDATE/SHARE is incompatible with GROUP BY',\n\t\t\t\t);\n\t\t\t}\n\t\t\tintent.lock = this.lockIntent;\n\t\t}\n\n\t\t// JOIN clauses (FR-10)\n\t\tif (this.joinIntents.length > 0) {\n\t\t\tintent.joins = [...this.joinIntents];\n\t\t}\n\n\t\t// BatchValues as primary FROM source\n\t\tif (this.batchValuesSource) {\n\t\t\tintent.batchValuesSource = this.batchValuesSource;\n\t\t}\n\n\t\treturn intent as QueryIntent;\n\t}\n\n\t/**\n\t * Apply defaultFilters to an intent (E17b: applied AFTER hooks for INV-01).\n\t * @internal\n\t */\n\t/** @internal — called by stream-impl */\n\tapplyDefaultFiltersToIntent(intent: QueryIntent): QueryIntent {\n\t\tif (this.skipDefaultFilters || !this.ctx.defaultFilters) return intent;\n\t\tconst tableDefaultFilter = this.ctx.defaultFilters[this.from];\n\t\tif (!tableDefaultFilter) return intent;\n\n\t\tconst existingWhere = intent.where;\n\t\tconst newWhere = existingWhere\n\t\t\t? and(tableDefaultFilter, existingWhere)\n\t\t\t: tableDefaultFilter;\n\n\t\treturn { ...intent, where: newWhere };\n\t}\n\n\t/**\n\t * Execute a query with hook interception (E17b).\n\t * Flow: buildIntent(raw) → beforeQuery → defaultFilters → plan → execute → hydrate → afterQuery\n\t * @internal\n\t */\n\tprivate async executeWithHooks<R>(\n\t\tadapter: Adapter,\n\t\tresultType: QueryResultType,\n\t): Promise<R> {\n\t\tconst store = this.ctx.hookStore;\n\t\tif (!store) throw new Error('executeWithHooks called without hookStore');\n\t\t// INV-07: Re-entrancy guard — prevent infinite loops from hooks issuing queries\n\t\treturn withReentrancyGuard(store, (s) =>\n\t\t\tthis.executeWithHooksInner<R>(adapter, resultType, s),\n\t\t);\n\t}\n\n\tprivate async executeWithHooksInner<R>(\n\t\tadapter: Adapter,\n\t\tresultType: QueryResultType,\n\t\tstore: HookStore,\n\t): Promise<R> {\n\t\tconst startTime = Date.now();\n\n\t\t// 1. Build intent WITHOUT defaultFilters — hooks see raw intent\n\t\tconst rawIntent = this.buildIntent(false);\n\n\t\t// 2. Build beforeQuery context\n\t\tconst beforeCtx: QueryHookContext = {\n\t\t\ttable: this.from,\n\t\t\toperation: 'select',\n\t\t\tintent: rawIntent,\n\t\t\tresultType,\n\t\t\t...(this.ctx.schemaName !== undefined && {\n\t\t\t\tschemaName: this.ctx.schemaName,\n\t\t\t}),\n\t\t\t...(this.ctx.inTransaction && { inTransaction: true }),\n\t\t};\n\n\t\t// 3. Run beforeQuery hooks (FIFO) — may modify intent\n\t\tlet intent: QueryIntent;\n\t\ttry {\n\t\t\tconst afterHookCtx = await runBeforeQueryHooks(\n\t\t\t\tstore.beforeQuery,\n\t\t\t\tbeforeCtx,\n\t\t\t\tthis.ctx.onHookError,\n\t\t\t);\n\t\t\tintent = afterHookCtx.intent;\n\t\t} catch (error) {\n\t\t\t// Run onError hooks for beforeQuery failures\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tconst finalError = await runOnErrorHooks(store.onError, {\n\t\t\t\t\ttable: this.from,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent: rawIntent,\n\t\t\t\t\tphase: 'beforeQuery',\n\t\t\t\t});\n\t\t\t\tthrow finalError;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\t// 4. Apply defaultFilters AFTER hooks (INV-01: cannot be bypassed)\n\t\tintent = this.applyDefaultFiltersToIntent(intent);\n\n\t\t// 5. Apply relation hints and plan\n\t\tconst intentWithHints = this.applyRelationHints(intent);\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...(this.ctx.dialectCapabilities && {\n\t\t\t\tdialectCapabilities: this.ctx.dialectCapabilities,\n\t\t\t}),\n\t\t\t...this.ctx.planOptionsOverride,\n\t\t};\n\n\t\tconst planReport = this.planWithAmbiguityHandling(\n\t\t\tintentWithHints,\n\t\t\tplanOptions,\n\t\t);\n\n\t\t// 6. Compile and execute\n\t\tconst compileOptions: { schemaName?: string; model: ModelIR } = {\n\t\t\tmodel: this.ctx.model,\n\t\t};\n\t\tif (this.ctx.schemaName !== undefined) {\n\t\t\tcompileOptions.schemaName = this.ctx.schemaName;\n\t\t}\n\n\t\tconst compiledWithIncludes = adapter.compileWithIncludes(\n\t\t\tplanReport,\n\t\t\tcompileOptions,\n\t\t);\n\n\t\tlet mainResults: TResult[];\n\t\ttry {\n\t\t\tmainResults = (await adapter.execute(\n\t\t\t\tcompiledWithIncludes.main,\n\t\t\t)) as TResult[];\n\t\t} catch (error) {\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tconst finalError = await runOnErrorHooks(store.onError, {\n\t\t\t\t\ttable: this.from,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent,\n\t\t\t\t\tphase: 'afterQuery',\n\t\t\t\t\tsql: compiledWithIncludes.main.sql,\n\t\t\t\t});\n\t\t\t\tthrow finalError;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\n\t\t// 7. Hydrate\n\t\tconst hydrator = new ResultHydrator<TResult>(\n\t\t\tthis.ctx.model,\n\t\t\tthis.from,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t\thydrator.hydrateJsonAggIncludes(mainResults, planReport);\n\t\thydrator.hydrateJoinIncludes(mainResults, planReport);\n\t\tif (compiledWithIncludes.subqueryIncludes.length > 0) {\n\t\t\tawait hydrator.hydrateIncludes(\n\t\t\t\tmainResults,\n\t\t\t\tcompiledWithIncludes.subqueryIncludes,\n\t\t\t\tadapter,\n\t\t\t\tcompileOptions,\n\t\t\t);\n\t\t}\n\t\tif (this.recursiveIncludes.length > 0) {\n\t\t\tawait hydrator.processRecursiveIncludes(\n\t\t\t\tmainResults,\n\t\t\t\tthis.recursiveIncludes,\n\t\t\t\tadapter,\n\t\t\t);\n\t\t}\n\n\t\t// 8. Build afterQuery context with timing + SQL info\n\t\tconst duration = Date.now() - startTime;\n\t\tconst afterCtx: QueryHookContext = {\n\t\t\ttable: this.from,\n\t\t\toperation: 'select',\n\t\t\tintent,\n\t\t\tresultType,\n\t\t\tsql: compiledWithIncludes.main.sql,\n\t\t\tparameters: compiledWithIncludes.main.parameters,\n\t\t\tduration,\n\t\t\t...(this.ctx.schemaName !== undefined && {\n\t\t\t\tschemaName: this.ctx.schemaName,\n\t\t\t}),\n\t\t};\n\n\t\t// 9. Run afterQuery hooks (LIFO) — may transform results\n\t\ttry {\n\t\t\t// SAFETY: R defaults to TResult[] from callers; afterQuery hooks may\n\t\t\t// transform the shape, hence the generic. The double cast bridges\n\t\t\t// the gap between the concrete TResult[] and the generic R.\n\t\t\tconst finalResults = await runAfterQueryHooks(\n\t\t\t\tstore.afterQuery,\n\t\t\t\tafterCtx,\n\t\t\t\tmainResults as unknown as R,\n\t\t\t\tthis.ctx.onHookError,\n\t\t\t);\n\t\t\treturn finalResults;\n\t\t} catch (error) {\n\t\t\tif (store.onError.length > 0) {\n\t\t\t\tconst finalError = await runOnErrorHooks(store.onError, {\n\t\t\t\t\ttable: this.from,\n\t\t\t\t\toperation: 'select',\n\t\t\t\t\terror: error as Error,\n\t\t\t\t\tintent,\n\t\t\t\t\tphase: 'afterQuery',\n\t\t\t\t\tsql: compiledWithIncludes.main.sql,\n\t\t\t\t});\n\t\t\t\tthrow finalError;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Build an existence-check intent from current state.\n\t * Strips orderBy and include (irrelevant), preserves groupBy/having/offset.\n\t */\n\tprivate buildExistsIntent(): QueryIntent {\n\t\tconst baseIntent = this.buildIntent();\n\t\tconst {\n\t\t\torderBy: _orderBy,\n\t\t\tinclude: _include,\n\t\t\t...rest\n\t\t} = baseIntent as QueryIntent & {\n\t\t\torderBy?: unknown;\n\t\t\tinclude?: unknown;\n\t\t};\n\t\treturn {\n\t\t\t...rest,\n\t\t\texistsWrap: true,\n\t\t\tlimit: 1,\n\t\t};\n\t}\n\n\t/**\n\t * Build exists-wrapped intent from a pre-built intent (E17b: for hook-aware path).\n\t * @internal\n\t */\n\tprivate buildExistsIntentFromIntent(baseIntent: QueryIntent): QueryIntent {\n\t\tconst {\n\t\t\torderBy: _orderBy,\n\t\t\tinclude: _include,\n\t\t\t...rest\n\t\t} = baseIntent as QueryIntent & {\n\t\t\torderBy?: unknown;\n\t\t\tinclude?: unknown;\n\t\t};\n\t\treturn {\n\t\t\t...rest,\n\t\t\texistsWrap: true,\n\t\t\tlimit: 1,\n\t\t};\n\t}\n\n\t/**\n\t * Handle ambiguity based on strict mode setting.\n\t */\n\n\t/**\n\t * Thin wrapper around the planner that applies the same ambiguity-handling\n\t * logic as `plan()` (the builder method). Used by exists/existsDump paths\n\t * which build their own planOptions and therefore cannot call `this.plan()`\n\t * directly (which would rebuild the intent from scratch).\n\t *\n\t * FIND-016: exists() / existsDump() called the raw planner function directly,\n\t * bypassing the ambiguity catch that lives in the builder's plan() wrapper.\n\t */\n\t/** @internal — called by stream-impl */\n\tplanWithAmbiguityHandling(\n\t\tintent: QueryIntent,\n\t\tplanOptions: PlanOptions,\n\t): PlanReport {\n\t\ttry {\n\t\t\treturn plan(intent, this.ctx.model, planOptions);\n\t\t} catch (error) {\n\t\t\tif (error instanceof AmbiguousPlanError) {\n\t\t\t\treturn this.handleAmbiguity(error, intent, planOptions);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate handleAmbiguity(\n\t\terror: AmbiguousPlanError,\n\t\tintent: QueryIntent,\n\t\tbasePlanOptions: PlanOptions = {},\n\t): PlanReport {\n\t\tif (this.getEffectiveStrictMode()) {\n\t\t\t// Strict mode: convert to AmbiguousRelationError and throw\n\t\t\tthrow new AmbiguousRelationError(\n\t\t\t\terror.sourceTable,\n\t\t\t\terror.targetTable,\n\t\t\t\terror.options,\n\t\t\t);\n\t\t}\n\n\t\t// Lenient mode: deterministic tie-break — sort alphabetically so that\n\t\t// schema definition order does not influence which relation is chosen.\n\t\t// This ensures stable query results across schema refactoring.\n\t\t// FIND-015: picking options[0] without sorting is non-deterministic.\n\t\tconst sortedOptions = error.options.slice().sort();\n\t\tconst firstRelation = sortedOptions[0];\n\t\tif (!firstRelation) {\n\t\t\tthrow error; // Safety: should never happen\n\t\t}\n\n\t\tconst disambiguateKey = `${error.sourceTable}.${error.targetTable}`;\n\t\tconst planOptions: PlanOptions = {\n\t\t\t...basePlanOptions,\n\t\t\tdisambiguate: {\n\t\t\t\t...basePlanOptions.disambiguate,\n\t\t\t\t[disambiguateKey]: firstRelation, // alphabetically-first (see sortedOptions)\n\t\t\t},\n\t\t};\n\n\t\t// Re-plan with disambiguation\n\t\tconst result = plan(intent, this.ctx.model, planOptions);\n\n\t\t// Add warning about automatic disambiguation.\n\t\t// The chosen relation is the alphabetically-first name (deterministic\n\t\t// tie-break), not insertion order, so schema refactoring cannot silently\n\t\t// change query results.\n\t\tconst warning = {\n\t\t\tcode: 'AMBIGUOUS_RELATION' as const,\n\t\t\tmessage:\n\t\t\t\t`Ambiguous relation to '${error.targetTable}' from '${error.sourceTable}' ` +\n\t\t\t\t`was automatically resolved to '${firstRelation}' (alphabetical tie-break). ` +\n\t\t\t\t`Available options: ${sortedOptions.join(', ')}.`,\n\t\t\tsuggestion: `Use { via: '${firstRelation}' } or another option to make this explicit.`,\n\t\t};\n\n\t\treturn {\n\t\t\t...result,\n\t\t\twarnings: [...result.warnings, warning],\n\t\t};\n\t}\n\n\t/**\n\t * Create a shallow clone of this builder.\n\t *\n\t * The cloned builder owns its own `planOptionsOverride` object reference so\n\t * per-builder overrides do not leak across clones; all other ctx fields are\n\t * intentionally shared by reference — model / adapter / hookStore are part\n\t * of the ORM instance's stable configuration and are treated as read-only\n\t * for the lifetime of the builder chain.\n\t *\n\t * @internal — called by pagination-impl and stream-impl\n\t */\n\tclone(): QueryBuilderImpl<TResult> {\n\t\t// Shallow-clone planOptionsOverride so the cloned builder owns its own\n\t\t// reference and per-builder overrides do not leak across clones.\n\t\treturn this.cloneWithCtxOverride(\n\t\t\tthis.ctx.planOptionsOverride !== undefined\n\t\t\t\t? { planOptionsOverride: { ...this.ctx.planOptionsOverride } }\n\t\t\t\t: {},\n\t\t);\n\t}\n\n\t/**\n\t * Build a new builder whose ctx merges `ctxOverride` over the source ctx.\n\t * Pure merge: callers own the policy of what to spread/clone.\n\t *\n\t * @internal — used by clone() and withPlanOptions().\n\t */\n\tprivate cloneWithCtxOverride(\n\t\tctxOverride: Partial<QueryBuilderContext>,\n\t): QueryBuilderImpl<TResult> {\n\t\tconst builder = new QueryBuilderImpl<TResult>(\n\t\t\t{ ...this.ctx, ...ctxOverride },\n\t\t\tthis.from,\n\t\t\t{\n\t\t\t\t...this.relationHints,\n\t\t\t},\n\t\t);\n\t\t// Clone array state\n\t\tbuilder.includes.push(...this.includes);\n\t\tbuilder.recursiveIncludes.push(...this.recursiveIncludes);\n\t\tbuilder.whereIntents.push(...this.whereIntents);\n\t\tbuilder.havingIntents.push(...this.havingIntents);\n\t\tbuilder.aggregates.push(...this.aggregates);\n\t\tbuilder.groupByFields.push(...this.groupByFields);\n\t\tbuilder.orderByIntents.push(...this.orderByIntents);\n\t\t// Clone scalar state\n\t\tbuilder.selectIntent = this.selectIntent;\n\t\tbuilder.isDistinctQuery = this.isDistinctQuery;\n\t\tbuilder.distinctOnColumns = [...this.distinctOnColumns];\n\t\tbuilder.skipDefaultFilters = this.skipDefaultFilters;\n\t\tbuilder.strictModeOverride = this.strictModeOverride;\n\t\tbuilder.limitValue = this.limitValue;\n\t\tbuilder.offsetValue = this.offsetValue;\n\t\tbuilder.lockIntent = this.lockIntent;\n\t\tbuilder.joinIntents.push(...this.joinIntents);\n\t\tif (this.batchValuesSource) {\n\t\t\tbuilder.batchValuesSource = this.batchValuesSource;\n\t\t}\n\t\treturn builder;\n\t}\n\n\t/**\n\t * Disable default filters (e.g., soft delete) for this query.\n\t * Use when you need to query deleted/inactive records.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Query all products including soft-deleted ones\n\t * const allProducts = await orm\n\t * .select('products')\n\t * .withoutDefaultFilters()\n\t * .all();\n\t * ```\n\t */\n\t// --------------------------------------------------------------------------\n\t// Set operations (UNION / INTERSECT / EXCEPT)\n\t// --------------------------------------------------------------------------\n\n\tunion(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'union',\n\t\t\t\tfalse,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\tunionAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'union',\n\t\t\t\ttrue,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\tintersect(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'intersect',\n\t\t\t\tfalse,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\tintersectAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'intersect',\n\t\t\t\ttrue,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\texcept(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'except',\n\t\t\t\tfalse,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\texceptAll(other: QueryBuilder<TResult>): SetOperationBuilder<TResult> {\n\t\treturn new SetOperationBuilderImpl(\n\t\t\tbuildSetOperationIntent(\n\t\t\t\t'except',\n\t\t\t\ttrue,\n\t\t\t\tthis,\n\t\t\t\tother as unknown as QueryIntentSource,\n\t\t\t),\n\t\t\tthis.ctx.model,\n\t\t\tthis.ctx.adapter,\n\t\t\tthis.ctx.schemaName,\n\t\t);\n\t}\n\n\twithoutDefaultFilters(): QueryBuilder<TResult> {\n\t\tconst builder = this.clone();\n\t\tbuilder.skipDefaultFilters = true;\n\t\treturn builder;\n\t}\n}\n","/**\n * Raw CTE builder — WITH RECURSIVE support via explicit base/step query builders (FR-8).\n *\n * Provides a fluent API for building arbitrary WITH RECURSIVE queries from\n * a base (anchor) QueryBuilder and a step (recursive) QueryBuilder.\n *\n * @example\n * ```typescript\n * const chain = orm.recursive('parent_chain', {\n * base: orm.select('symbols').where(eq('id', rootId)),\n * step: orm.select('parent_chain'),\n * maxDepth: 10,\n * unionAll: true,\n * });\n * const results = await chain.columns(['id', 'name', 'depth']).orderBy('depth').all();\n * ```\n */\n\nimport type {\n\tAdapter,\n\tCompiledQuery,\n\tCteQueryIntent,\n\tOrderByIntent,\n\tQueryIntent,\n\tRawCteIntent,\n\tSelectWithExpressionsIntent,\n\tWhereIntent,\n} from '@dbsp/types';\nimport { requireAdapter as requireAdapterUtil } from './builder-utils.js';\nimport type { QueryBuilderImpl } from './query-builder.js';\nimport type { QueryBuilder } from './query-builder-types.js';\n\n/**\n * Options for `orm.recursive()`.\n */\nexport interface RecursiveOptions {\n\t/** Base (anchor) query — produces the starting rows. */\n\treadonly base: QueryBuilder<unknown>;\n\t/** Recursive step query — references the CTE name as its FROM table. */\n\treadonly step: QueryBuilder<unknown>;\n\t/** Maximum recursion depth (guards against infinite loops). */\n\treadonly maxDepth?: number;\n\t/**\n\t * Column name in the step query that tracks depth (used with maxDepth).\n\t * When set, injects WHERE <depthColumn> < maxDepth into the step during compilation.\n\t * @default 'depth'\n\t */\n\treadonly depthColumn?: string;\n\t/** When true (default), use UNION ALL. When false, use UNION (deduplicates). */\n\treadonly unionAll?: boolean;\n}\n\n/**\n * Result of compiling a recursive CTE query.\n */\nexport interface RecursiveDump {\n\treadonly sql: string;\n\treadonly params: readonly unknown[];\n\treadonly intent: CteQueryIntent;\n}\n\n/**\n * Fluent builder for constructing and executing a WITH RECURSIVE query.\n *\n * Obtain via `orm.recursive(name, options)`.\n */\nexport class RawCteQueryBuilder<TResult = unknown> {\n\tprivate readonly cteName: string;\n\tprivate readonly rawCteIntent: RawCteIntent;\n\tprivate readonly adapter: Adapter | undefined;\n\tprivate readonly schemaName: string | undefined;\n\n\tprivate outerSelect: SelectWithExpressionsIntent | undefined;\n\tprivate outerWhere: WhereIntent | undefined;\n\tprivate outerOrderBy: OrderByIntent[] | undefined;\n\tprivate outerLimit: number | undefined;\n\tprivate outerOffset: number | undefined;\n\n\tconstructor(\n\t\tcteName: string,\n\t\trawCteIntent: RawCteIntent,\n\t\tadapter?: Adapter,\n\t\tschemaName?: string,\n\t) {\n\t\tthis.cteName = cteName;\n\t\tthis.rawCteIntent = rawCteIntent;\n\t\tthis.adapter = adapter;\n\t\tthis.schemaName = schemaName;\n\t}\n\n\t/**\n\t * Select specific columns from the CTE result.\n\t */\n\tcolumns(cols: readonly string[]): this {\n\t\tthis.outerSelect = {\n\t\t\ttype: 'expressions',\n\t\t\tcolumns: cols.map((column) => ({ kind: 'column', column })),\n\t\t};\n\t\treturn this;\n\t}\n\n\t/**\n\t * Filter the outer query result.\n\t */\n\twhere(condition: WhereIntent): this {\n\t\tthis.outerWhere = condition;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Order the outer query result.\n\t */\n\torderBy(column: string, direction: 'asc' | 'desc' = 'asc'): this {\n\t\tconst clause: OrderByIntent = { field: column, direction };\n\t\tthis.outerOrderBy = [...(this.outerOrderBy ?? []), clause];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Limit the number of rows returned.\n\t */\n\tlimit(n: number): this {\n\t\tthis.outerLimit = n;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Skip the first N rows.\n\t */\n\toffset(n: number): this {\n\t\tthis.outerOffset = n;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Build the CteQueryIntent AST.\n\t */\n\tbuildIntent(): CteQueryIntent {\n\t\tconst outerIntent: QueryIntent = {\n\t\t\ttype: 'select',\n\t\t\tfrom: this.cteName,\n\t\t\t...(this.outerSelect !== undefined && { select: this.outerSelect }),\n\t\t\t...(this.outerWhere !== undefined && { where: this.outerWhere }),\n\t\t\t...(this.outerOrderBy !== undefined && { orderBy: this.outerOrderBy }),\n\t\t\t...(this.outerLimit !== undefined && { limit: this.outerLimit }),\n\t\t\t...(this.outerOffset !== undefined && { offset: this.outerOffset }),\n\t\t};\n\n\t\treturn {\n\t\t\tkind: 'cteQuery',\n\t\t\tctes: [this.rawCteIntent],\n\t\t\tquery: outerIntent,\n\t\t};\n\t}\n\n\tprivate requireAdapter(): Adapter {\n\t\treturn requireAdapterUtil(this.adapter, 'recursive');\n\t}\n\n\t/**\n\t * Compile to SQL and return an observability dump.\n\t */\n\tdump(): RecursiveDump {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions = this.schemaName\n\t\t\t? { schemaName: this.schemaName }\n\t\t\t: undefined;\n\t\tconst compiled: CompiledQuery = adapter.compileCteQuery(\n\t\t\tintent,\n\t\t\tcompileOptions,\n\t\t);\n\t\treturn {\n\t\t\tsql: compiled.sql,\n\t\t\tparams: compiled.parameters,\n\t\t\tintent,\n\t\t};\n\t}\n\n\t/**\n\t * Execute the recursive CTE query and return all matching rows.\n\t */\n\tasync all(): Promise<TResult[]> {\n\t\tconst adapter = this.requireAdapter();\n\t\tconst intent = this.buildIntent();\n\t\tconst compileOptions = this.schemaName\n\t\t\t? { schemaName: this.schemaName }\n\t\t\t: undefined;\n\t\tconst compiled = adapter.compileCteQuery(\n\t\t\tintent,\n\t\t\tcompileOptions,\n\t\t) as CompiledQuery<TResult>;\n\t\treturn adapter.execute(compiled);\n\t}\n\n\t/**\n\t * Alias for `all()`.\n\t */\n\texecute(): Promise<TResult[]> {\n\t\treturn this.all();\n\t}\n}\n\n/**\n * Create a RawCteQueryBuilder from named builder instances.\n */\nexport function createRawCteBuilder<TResult = unknown>(\n\tcteName: string,\n\toptions: RecursiveOptions,\n\tadapter?: Adapter,\n\tschemaName?: string,\n): RawCteQueryBuilder<TResult> {\n\tconst baseIntent = (\n\t\toptions.base as unknown as QueryBuilderImpl<unknown>\n\t).buildIntent();\n\tconst stepIntent = (\n\t\toptions.step as unknown as QueryBuilderImpl<unknown>\n\t).buildIntent();\n\n\tconst rawCteIntent: RawCteIntent = {\n\t\tkind: 'rawCte',\n\t\tname: cteName,\n\t\tbase: baseIntent,\n\t\tstep: stepIntent,\n\t\tunionAll: options.unionAll ?? true,\n\t\t...(options.maxDepth !== undefined && { maxDepth: options.maxDepth }),\n\t\t...(options.depthColumn !== undefined && {\n\t\t\tdepthColumn: options.depthColumn,\n\t\t}),\n\t};\n\n\treturn new RawCteQueryBuilder<TResult>(\n\t\tcteName,\n\t\trawCteIntent,\n\t\tadapter,\n\t\tschemaName,\n\t);\n}\n","import type { Adapter } from '../adapter.js';\nimport type { DialectCapabilities } from '../dialects/index.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanOptions } from '../planner.js';\nimport type { BatchValuesOptions, BatchValuesRef } from './batch-values.js';\nimport { batchValues } from './batch-values.js';\nimport { CteBuilder } from './cte-builder.js';\nimport { InvalidOperationError, validateIdentifier } from './errors.js';\nimport { eq } from './filters.js';\nimport {\n\textractRecursiveField,\n\tfindSelfRefRelation,\n} from './hierarchy-helpers.js';\nimport type { HookErrorHandler, HookStore } from './hooks.js';\nimport {\n\tDeleteBuilder,\n\tInsertBuilder,\n\tUpdateBuilder,\n\tUpsertBuilder,\n} from './mutation-builders.js';\nimport { createNqlTag, type NqlTag } from './nql.js';\nimport type { SelectExpressionResult } from './orm-instance-types.js';\nimport { QueryBuilderImpl } from './query-builder.js';\nimport type { QueryBuilderContext } from './query-builder-context.js';\nimport {\n\tcreateRawCteBuilder,\n\ttype RawCteQueryBuilder,\n\ttype RecursiveOptions,\n} from './raw-cte-builder.js';\nimport type { DefaultFilters } from './schema.js';\nimport { TABLE_META } from './symbols.js';\nimport type {\n\tAlterColumnOptions,\n\tCreateIndexOptions,\n\tDropIndexOptions,\n\tIndexInfo,\n\tTableDDL,\n\tTruncateOptions,\n\tVacuumOptions,\n} from './table-ddl-types.js';\nimport type { InferTableRow, TableRef } from './table-ref.js';\nimport type {\n\tExpressionSpec,\n\tListHierarchyOptions,\n\tOrmInstance,\n\tOrmInstanceInternal,\n\tQueryBuilder,\n\tRelationHints,\n} from './types.js';\n\n/**\n * Quote a PostgreSQL identifier (table/schema/column name).\n * Simple double-quoting — no validation, validation is caller's responsibility.\n */\n\n/**\n * Build the qualified table reference string for DDL statements.\n */\n\n/**\n * Build the DDL methods object for a specific table.\n */\n// ─── DDL SQL generation helpers ──────────────────────────────────────────────\n\n/** Double-quote a PostgreSQL identifier. */\nfunction quoteIdent(name: string): string {\n\treturn `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\n/** Build a qualified `\"schema\".\"table\"` or `\"table\"` reference. */\nfunction buildQualifiedTable(\n\ttableName: string,\n\tschemaName: string | undefined,\n): string {\n\treturn schemaName\n\t\t? `${quoteIdent(schemaName)}.${quoteIdent(tableName)}`\n\t\t: quoteIdent(tableName);\n}\n\nfunction generateTruncateSQL(\n\ttableName: string,\n\tschemaName: string | undefined,\n\toptions: TruncateOptions | undefined,\n): string {\n\tconst parts = [`TRUNCATE ${buildQualifiedTable(tableName, schemaName)}`];\n\tif (options?.restartIdentity) parts.push('RESTART IDENTITY');\n\tif (options?.cascade) parts.push('CASCADE');\n\treturn parts.join(' ');\n}\n\nfunction generateVacuumSQL(\n\ttableName: string,\n\tschemaName: string | undefined,\n\toptions: VacuumOptions | undefined,\n): string {\n\tconst modifiers: string[] = [];\n\tif (options?.full) modifiers.push('FULL');\n\tif (options?.analyze) modifiers.push('ANALYZE');\n\tconst mod = modifiers.length > 0 ? `(${modifiers.join(', ')}) ` : '';\n\treturn `VACUUM ${mod}${buildQualifiedTable(tableName, schemaName)}`;\n}\n\nfunction generateAlterColumnSQL(\n\ttableName: string,\n\tcolumn: string,\n\tschemaName: string | undefined,\n\toptions: AlterColumnOptions,\n): string {\n\tconst tbl = buildQualifiedTable(tableName, schemaName);\n\tconst col = quoteIdent(column);\n\tconst clauses: string[] = [];\n\n\tif (options.type !== undefined) {\n\t\tlet clause = `ALTER COLUMN ${col} TYPE ${options.type}`;\n\t\tif (options.using !== undefined) {\n\t\t\tclause += ` USING ${options.using}`;\n\t\t}\n\t\tclauses.push(clause);\n\t}\n\tif (options.setNotNull === true) {\n\t\tclauses.push(`ALTER COLUMN ${col} SET NOT NULL`);\n\t} else if (options.setNotNull === false) {\n\t\tclauses.push(`ALTER COLUMN ${col} DROP NOT NULL`);\n\t}\n\tif (options.dropDefault === true) {\n\t\tclauses.push(`ALTER COLUMN ${col} DROP DEFAULT`);\n\t} else if (options.setDefault !== undefined) {\n\t\tclauses.push(`ALTER COLUMN ${col} SET DEFAULT ${options.setDefault}`);\n\t}\n\tif (clauses.length === 0) {\n\t\tthrow new InvalidOperationError(\n\t\t\t'alterColumn',\n\t\t\t'At least one alteration option must be specified.',\n\t\t);\n\t}\n\treturn `ALTER TABLE ${tbl} ${clauses.join(', ')}`;\n}\n\nfunction generateCreateIndexSQL(\n\ttableName: string,\n\tschemaName: string | undefined,\n\topts: CreateIndexOptions,\n): string {\n\tconst tbl = buildQualifiedTable(tableName, schemaName);\n\tconst parts: string[] = ['CREATE'];\n\tif (opts.unique) parts.push('UNIQUE');\n\tparts.push('INDEX');\n\tif (opts.concurrently) parts.push('CONCURRENTLY');\n\tif (opts.ifNotExists) parts.push('IF NOT EXISTS');\n\tparts.push(quoteIdent(opts.name));\n\tparts.push('ON');\n\tparts.push(tbl);\n\tif (opts.method) parts.push(`USING ${opts.method}`);\n\n\tconst colDefs = opts.columns.map((col) => {\n\t\tif (typeof col === 'string') {\n\t\t\tconst quotedCol = quoteIdent(col);\n\t\t\tconst op = opts.opclass?.[col] != null ? ` ${opts.opclass[col]}` : '';\n\t\t\treturn `${quotedCol}${op}`;\n\t\t}\n\t\tconst op = col.opclass != null ? ` ${col.opclass}` : '';\n\t\treturn `(${col.expression})${op}`;\n\t});\n\tparts.push(`(${colDefs.join(', ')})`);\n\n\tif (opts.include && opts.include.length > 0) {\n\t\tparts.push(\n\t\t\t`INCLUDE (${opts.include.map((c) => quoteIdent(c)).join(', ')})`,\n\t\t);\n\t}\n\tif (opts.with && Object.keys(opts.with).length > 0) {\n\t\tconst withClauses = Object.entries(opts.with)\n\t\t\t.map(([k, v]) => `${k} = ${v}`)\n\t\t\t.join(', ');\n\t\tparts.push(`WITH (${withClauses})`);\n\t}\n\tif (opts.where) parts.push(`WHERE ${opts.where}`);\n\treturn parts.join(' ');\n}\n\nfunction generateDropIndexSQL(\n\tname: string,\n\tschemaName: string | undefined,\n\toptions: DropIndexOptions | undefined,\n): string {\n\tconst parts: string[] = ['DROP INDEX'];\n\tif (options?.concurrently) parts.push('CONCURRENTLY');\n\tif (options?.ifExists) parts.push('IF EXISTS');\n\tconst sc = options?.schema ?? schemaName;\n\tparts.push(sc ? `${quoteIdent(sc)}.${quoteIdent(name)}` : quoteIdent(name));\n\tif (options?.cascade) parts.push('CASCADE');\n\treturn parts.join(' ');\n}\n\n// ─── indexes sub-API builder ──────────────────────────────────────────────────\n\nfunction buildIndexAPI(\n\ttableName: string,\n\tschemaName: string | undefined,\n\tadapter: Adapter<unknown> | undefined,\n\trequireAdapter: () => Adapter<unknown>,\n): TableDDL['indexes'] {\n\treturn {\n\t\tasync create(opts: CreateIndexOptions): Promise<void> {\n\t\t\tconst a = requireAdapter();\n\t\t\tif (opts.concurrently && a.inTransaction) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'createIndex',\n\t\t\t\t\t'CREATE INDEX CONCURRENTLY cannot run inside a transaction block',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst sql = a.generateCreateIndex\n\t\t\t\t? a.generateCreateIndex(tableName, opts, schemaName)\n\t\t\t\t: generateCreateIndexSQL(tableName, schemaName, opts);\n\t\t\tawait a.executeDDL?.(sql);\n\t\t},\n\n\t\tasync drop(name: string, options?: DropIndexOptions): Promise<void> {\n\t\t\tconst a = requireAdapter();\n\t\t\tif (options?.concurrently && a.inTransaction) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'dropIndex',\n\t\t\t\t\t'DROP INDEX CONCURRENTLY cannot run inside a transaction block',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst sql = a.generateDropIndex\n\t\t\t\t? a.generateDropIndex(name, options)\n\t\t\t\t: generateDropIndexSQL(name, schemaName, options);\n\t\t\tawait a.executeDDL?.(sql);\n\t\t},\n\n\t\tasync list(options?: { namePattern?: string }): Promise<IndexInfo[]> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'indexes.list',\n\t\t\t\t\t'indexes.list() requires an adapter.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (adapter.listIndexes) {\n\t\t\t\treturn adapter.listIndexes(tableName, schemaName, options);\n\t\t\t}\n\t\t\t// Fallback for adapters without listIndexes: use executeRaw if available\n\t\t\tconst sql =\n\t\t\t\t`SELECT indexname AS name, indexdef AS definition, ` +\n\t\t\t\t`(SELECT indisunique FROM pg_index WHERE indexrelid = (SELECT oid FROM pg_class WHERE relname = indexname)) AS unique, ` +\n\t\t\t\t`CASE WHEN indexdef LIKE '%USING %' THEN split_part(indexdef, 'USING ', 2) ELSE 'btree' END AS method ` +\n\t\t\t\t`FROM pg_indexes WHERE tablename = '${tableName.replace(/'/g, \"''\")}' ` +\n\t\t\t\t(schemaName\n\t\t\t\t\t? `AND schemaname = '${schemaName.replace(/'/g, \"''\")}' `\n\t\t\t\t\t: '') +\n\t\t\t\t`ORDER BY indexname`;\n\t\t\tif ('executeRaw' in adapter && typeof adapter.executeRaw === 'function') {\n\t\t\t\tconst rows = await (\n\t\t\t\t\tadapter.executeRaw as (\n\t\t\t\t\t\tsql: string,\n\t\t\t\t\t\tparams: unknown[],\n\t\t\t\t\t) => Promise<unknown[]>\n\t\t\t\t)(sql, []);\n\t\t\t\treturn rows as IndexInfo[];\n\t\t\t}\n\t\t\t// Fallback: use executeDDL (adapter must handle SELECT)\n\t\t\tif (adapter.executeDDL) await adapter.executeDDL(sql);\n\t\t\treturn [];\n\t\t},\n\n\t\tasync exists(name: string): Promise<boolean> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'indexes.exists',\n\t\t\t\t\t'indexes.exists() requires an adapter.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!adapter.indexExists) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'indexes.exists',\n\t\t\t\t\t'indexes.exists() requires an adapter that implements indexExists().',\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn adapter.indexExists(name, tableName, schemaName);\n\t\t},\n\t};\n}\n\n// ─── Public assembler ─────────────────────────────────────────────────────────\n\n/**\n * Build the DDL methods object for a specific table.\n */\nfunction buildTableDDL(\n\ttableName: string,\n\tschemaName: string | undefined,\n\tadapter: Adapter<unknown> | undefined,\n): TableDDL {\n\tfunction requireAdapter(): Adapter<unknown> {\n\t\tif (!adapter?.executeDDL) {\n\t\t\tthrow new InvalidOperationError(\n\t\t\t\t'table DDL',\n\t\t\t\t'executeDDL() requires an adapter that supports DDL execution. ' +\n\t\t\t\t\t'Pass an adapter with executeDDL when creating the ORM.',\n\t\t\t);\n\t\t}\n\t\treturn adapter;\n\t}\n\n\treturn {\n\t\tasync truncate(options?: TruncateOptions): Promise<void> {\n\t\t\tconst a = requireAdapter();\n\t\t\tconst sql = a.generateTruncate\n\t\t\t\t? a.generateTruncate(tableName, schemaName, options)\n\t\t\t\t: generateTruncateSQL(tableName, schemaName, options);\n\t\t\tawait a.executeDDL?.(sql);\n\t\t},\n\n\t\tasync vacuum(options?: VacuumOptions): Promise<void> {\n\t\t\tconst a = requireAdapter();\n\t\t\tif (a.inTransaction) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'vacuum',\n\t\t\t\t\t'VACUUM cannot run inside a transaction block',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst sql = a.generateVacuum\n\t\t\t\t? a.generateVacuum(tableName, schemaName, options)\n\t\t\t\t: generateVacuumSQL(tableName, schemaName, options);\n\t\t\tawait a.executeDDL?.(sql);\n\t\t},\n\n\t\tasync alterColumn(\n\t\t\tcolumn: string,\n\t\t\toptions: AlterColumnOptions,\n\t\t): Promise<void> {\n\t\t\tvalidateIdentifier(tableName, 'table');\n\t\t\tvalidateIdentifier(column, 'column');\n\t\t\tconst a = requireAdapter();\n\t\t\tconst sql = a.generateAlterColumn\n\t\t\t\t? a.generateAlterColumn(tableName, column, options, schemaName)\n\t\t\t\t: generateAlterColumnSQL(tableName, column, schemaName, options);\n\t\t\tawait a.executeDDL?.(sql);\n\t\t},\n\n\t\tindexes: buildIndexAPI(tableName, schemaName, adapter, requireAdapter),\n\n\t\tasync storageSize(): Promise<number> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'storageSize',\n\t\t\t\t\t'storageSize() requires an adapter.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!adapter.storageSize) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'storageSize',\n\t\t\t\t\t'storageSize() requires an adapter that implements storageSize().',\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn adapter.storageSize(tableName, schemaName);\n\t\t},\n\t};\n}\n\n/**\n * Wrap a tables proxy (from createTablesProxy or schema.tables) with DDL methods.\n * The returned proxy intercepts property access on each table name and augments\n * the returned TableRef object with a `TableDDL` mixin.\n */\nexport function wrapTablesProxyWithDDL(\n\ttablesProxy: object,\n\tadapter: Adapter<unknown> | undefined,\n\tschemaName: string | undefined,\n): object {\n\t// Cache augmented table objects to preserve referential equality\n\tconst cache = new Map<string, object>();\n\n\treturn new Proxy(tablesProxy, {\n\t\tget(target, prop, receiver) {\n\t\t\t// Pass through Symbol and non-string properties unchanged\n\t\t\tif (typeof prop !== 'string') {\n\t\t\t\treturn Reflect.get(target, prop, receiver);\n\t\t\t}\n\n\t\t\tif (cache.has(prop)) {\n\t\t\t\treturn cache.get(prop);\n\t\t\t}\n\n\t\t\tconst tableRef = Reflect.get(target, prop, receiver);\n\t\t\tif (tableRef === undefined || tableRef === null) {\n\t\t\t\treturn tableRef;\n\t\t\t}\n\n\t\t\t// Augment the TableRef with DDL methods\n\t\t\tconst ddl = buildTableDDL(prop, schemaName, adapter);\n\t\t\tconst augmented = Object.assign(Object.create(null), tableRef, ddl);\n\t\t\tcache.set(prop, augmented);\n\t\t\treturn augmented;\n\t\t},\n\t});\n}\n\n/**\n * Internal factory for creating ORM instances.\n * Supports optional schema name for multi-tenant scenarios.\n *\n * @typeParam DB - Database schema type (passed through from createOrm)\n */\nexport function createOrmInstance<DB = Record<string, unknown>>(\n\tmodel: ModelIR,\n\tstrictMode: boolean,\n\trelationHints: RelationHints,\n\tadapter?: Adapter<DB>,\n\tschemaName?: string,\n\tdialectCapabilities?: DialectCapabilities,\n\tschemaDefinition?: unknown,\n\tglobalPlanOptions?: PlanOptions,\n\tdefaultFilters?: DefaultFilters,\n\thookStore?: HookStore,\n\tonHookError?: HookErrorHandler,\n\tinTransaction?: boolean,\n\ttablesProxy?: object,\n): OrmInstanceInternal<DB> {\n\t// Create NQL template tag (DX-040)\n\t// NQL compiler is now integrated directly - @dbsp/nql is imported in nql.ts\n\tconst nql: NqlTag = createNqlTag(\n\t\tschemaDefinition,\n\t\tmodel,\n\t\tadapter as Adapter<unknown> | undefined,\n\t\tschemaName,\n\t);\n\n\t// Helper: build a MutationBuilder options object (shared across mutation methods)\n\tconst mutationOpts = {\n\t\tmodel,\n\t\tadapter,\n\t\tschemaName,\n\t\thookStore,\n\t\tonHookError,\n\t\tinTransaction,\n\t} as const;\n\n\t// Context bag for QueryBuilderImpl — eliminates the 12-param positional constructor\n\tconst queryCtx: QueryBuilderContext = {\n\t\tmodel,\n\t\tstrictMode,\n\t\t...(adapter !== undefined ? { adapter: adapter as Adapter<unknown> } : {}),\n\t\t...(schemaName !== undefined ? { schemaName } : {}),\n\t\t...(dialectCapabilities !== undefined ? { dialectCapabilities } : {}),\n\t\t...(globalPlanOptions !== undefined\n\t\t\t? { planOptionsOverride: globalPlanOptions }\n\t\t\t: {}),\n\t\t...(defaultFilters !== undefined ? { defaultFilters } : {}),\n\t\t...(hookStore !== undefined ? { hookStore } : {}),\n\t\t...(onHookError !== undefined ? { onHookError } : {}),\n\t\t...(inTransaction !== undefined ? { inTransaction } : {}),\n\t};\n\n\t// Wrap the tables proxy to augment each table access with DDL methods\n\tconst tablesDDLProxy = wrapTablesProxyWithDDL(\n\t\ttablesProxy ?? {},\n\t\tadapter as Adapter<unknown> | undefined,\n\t\tschemaName,\n\t);\n\n\treturn {\n\t\tstrictMode,\n\t\tnql,\n\t\ttables: tablesDDLProxy as OrmInstance<DB>['tables'],\n\t\t// biome-ignore lint/suspicious/noExplicitAny: polymorphic constraint — TTable is inferred by callers; TableRef generics are statically erased in this implementation signature\n\t\tfrom<TTable extends TableRef<any, any, any>>(\n\t\t\ttable: TTable | BatchValuesRef,\n\t\t):\n\t\t\t| QueryBuilder<InferTableRow<TTable>>\n\t\t\t| QueryBuilder<Record<string, unknown>> {\n\t\t\t// BatchValuesRef path\n\t\t\tif (\n\t\t\t\ttypeof table === 'object' &&\n\t\t\t\ttable !== null &&\n\t\t\t\t'__kind' in table &&\n\t\t\t\t(table as unknown as BatchValuesRef).__kind === 'batchValues'\n\t\t\t) {\n\t\t\t\tconst bv = table as unknown as BatchValuesRef;\n\t\t\t\tconst builder = new QueryBuilderImpl<Record<string, unknown>>(\n\t\t\t\t\tqueryCtx,\n\t\t\t\t\tbv.alias,\n\t\t\t\t\trelationHints,\n\t\t\t\t);\n\t\t\t\tbuilder.batchValuesSource = {\n\t\t\t\t\tdata: bv.data,\n\t\t\t\t\tcolumns: bv.columns,\n\t\t\t\t\ttypes: bv.types,\n\t\t\t\t\talias: bv.alias,\n\t\t\t\t\tordinality: bv.ordinality,\n\t\t\t\t};\n\t\t\t\treturn builder;\n\t\t\t}\n\t\t\tconst tableRef = table as TTable;\n\t\t\tconst tableName = tableRef[TABLE_META];\n\t\t\tif (tableName === undefined) {\n\t\t\t\tthrow new Error('Invalid TableRef: missing TABLE_META symbol');\n\t\t\t}\n\t\t\treturn new QueryBuilderImpl<InferTableRow<TTable>>(\n\t\t\t\tqueryCtx,\n\t\t\t\ttableName as string,\n\t\t\t\trelationHints,\n\t\t\t);\n\t\t},\n\t\tselect<K extends keyof DB & string, TResult = DB[K]>(\n\t\t\tfrom: K,\n\t\t): QueryBuilder<TResult> {\n\t\t\treturn new QueryBuilderImpl<TResult>(\n\t\t\t\tqueryCtx,\n\t\t\t\tfrom as string,\n\t\t\t\trelationHints,\n\t\t\t);\n\t\t},\n\t\twithSchema(schemaName: string): OrmInstanceInternal<DB> {\n\t\t\t// Always validate schema name — even without an adapter — to prevent injection\n\t\t\tvalidateIdentifier(schemaName, 'schema');\n\t\t\tif (adapter) {\n\t\t\t\tadapter.validateIdentifier(schemaName, 'schema');\n\t\t\t}\n\t\t\t// Create a schema-scoped adapter if we have one\n\t\t\tconst scopedAdapter = adapter?.withSchema(schemaName);\n\t\t\treturn createOrmInstance(\n\t\t\t\tmodel,\n\t\t\t\tstrictMode,\n\t\t\t\trelationHints,\n\t\t\t\tscopedAdapter as Adapter<DB> | undefined,\n\t\t\t\tschemaName,\n\t\t\t\tdialectCapabilities,\n\t\t\t\tschemaDefinition,\n\t\t\t\tglobalPlanOptions,\n\t\t\t\tdefaultFilters,\n\t\t\t\thookStore,\n\t\t\t\tonHookError,\n\t\t\t\tinTransaction,\n\t\t\t\ttablesProxy,\n\t\t\t);\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Hierarchy List Methods (DX-022)\n\t\t// Returns flat arrays, uses include() with recursive: true internally\n\t\t// =====================================================================\n\n\t\t/**\n\t\t * List all ancestors of a node as a flat array.\n\t\t * Uses the new include({ recursive: true }) API internally.\n\t\t *\n\t\t * @param table - The table name\n\t\t * @param nodeIdValue - The starting node's ID value\n\t\t * @param options - Options including parentId column name\n\t\t * @returns Promise resolving to array of ancestor records\n\t\t */\n\t\tasync listAncestors<TResult = unknown>(\n\t\t\ttable: string,\n\t\t\tnodeIdValue: unknown,\n\t\t\toptions: ListHierarchyOptions,\n\t\t): Promise<TResult[]> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'listAncestors() requires an adapter. ' +\n\t\t\t\t\t\t'Pass an adapter when creating the ORM.',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// FIND-001: Validate table against known tables before use in error messages\n\t\t\tif (!model.getTable(table)) {\n\t\t\t\tthrow new InvalidOperationError('listAncestors', 'Table not found');\n\t\t\t}\n\n\t\t\t// FIND-007: Cap maxDepth to prevent infinite/excessive recursion.\n\t\t\t// Use isSafeInteger to reject fractional values (e.g. 1.5) that\n\t\t\t// Number.isFinite would accept.\n\t\t\tconst MAX_RECURSION_DEPTH = 1000;\n\t\t\tconst rawMaxDepth = options.maxDepth ?? 100;\n\t\t\tif (!Number.isSafeInteger(rawMaxDepth) || rawMaxDepth < 1) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'listAncestors',\n\t\t\t\t\t'maxDepth must be a positive safe integer',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst safeMaxDepth = Math.min(rawMaxDepth, MAX_RECURSION_DEPTH);\n\n\t\t\t// Find the self-referential relation that matches the parent direction\n\t\t\tconst selfRefRelation = findSelfRefRelation(model, table, 'ancestors');\n\t\t\tif (!selfRefRelation) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'listAncestors',\n\t\t\t\t\t'Table has no self-referential belongsTo/hasOne relation for ancestor traversal',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst nodeIdCol = options.nodeId ?? 'id';\n\n\t\t\t// Hierarchy helpers historically did NOT propagate inTransaction. Preserve that behavior.\n\t\t\tconst { inTransaction: _ignored, ...hierarchyCtxBase } = queryCtx;\n\t\t\tconst hierarchyCtx: QueryBuilderContext = hierarchyCtxBase;\n\n\t\t\tconst builder = new QueryBuilderImpl<TResult>(\n\t\t\t\thierarchyCtx,\n\t\t\t\ttable,\n\t\t\t\trelationHints,\n\t\t\t);\n\n\t\t\tconst result = await builder\n\t\t\t\t.where(eq(nodeIdCol, nodeIdValue))\n\t\t\t\t.include(selfRefRelation.name, {\n\t\t\t\t\trecursive: true,\n\t\t\t\t\tdirection: 'ancestors',\n\t\t\t\t\tflat: true,\n\t\t\t\t\tomitSelf: true,\n\t\t\t\t\tmaxDepth: safeMaxDepth,\n\t\t\t\t})\n\t\t\t\t.first();\n\n\t\t\t// Result shape from include({ recursive, direction: 'ancestors' }):\n\t\t\t// { id, ..., ancestors: [...] }\n\t\t\treturn extractRecursiveField<TResult>(result, 'ancestors');\n\t\t},\n\n\t\t/**\n\t\t * List all descendants of a node as a flat array.\n\t\t * Uses the new include({ recursive: true }) API internally.\n\t\t *\n\t\t * @param table - The table name\n\t\t * @param nodeIdValue - The starting node's ID value\n\t\t * @param options - Options including parentId column name\n\t\t * @returns Promise resolving to array of descendant records\n\t\t */\n\t\tasync listDescendants<TResult = unknown>(\n\t\t\ttable: string,\n\t\t\tnodeIdValue: unknown,\n\t\t\toptions: ListHierarchyOptions,\n\t\t): Promise<TResult[]> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'listDescendants() requires an adapter. ' +\n\t\t\t\t\t\t'Pass an adapter when creating the ORM.',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// FIND-001: Validate table against known tables before use in error messages\n\t\t\tif (!model.getTable(table)) {\n\t\t\t\tthrow new InvalidOperationError('listDescendants', 'Table not found');\n\t\t\t}\n\n\t\t\t// FIND-007: Cap maxDepth to prevent infinite/excessive recursion.\n\t\t\t// Use isSafeInteger to reject fractional values (e.g. 1.5) that\n\t\t\t// Number.isFinite would accept.\n\t\t\tconst MAX_RECURSION_DEPTH = 1000;\n\t\t\tconst rawMaxDepth = options.maxDepth ?? 100;\n\t\t\tif (!Number.isSafeInteger(rawMaxDepth) || rawMaxDepth < 1) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'listDescendants',\n\t\t\t\t\t'maxDepth must be a positive safe integer',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst safeMaxDepth = Math.min(rawMaxDepth, MAX_RECURSION_DEPTH);\n\n\t\t\t// Find the self-referential relation that matches the children direction\n\t\t\tconst selfRefRelation = findSelfRefRelation(model, table, 'descendants');\n\t\t\tif (!selfRefRelation) {\n\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t'listDescendants',\n\t\t\t\t\t'Table has no self-referential hasMany relation for descendant traversal',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst nodeIdCol = options.nodeId ?? 'id';\n\n\t\t\t// Hierarchy helpers historically did NOT propagate inTransaction. Preserve that behavior.\n\t\t\tconst { inTransaction: _ignored, ...hierarchyCtxBase } = queryCtx;\n\t\t\tconst hierarchyCtx: QueryBuilderContext = hierarchyCtxBase;\n\n\t\t\tconst builder = new QueryBuilderImpl<TResult>(\n\t\t\t\thierarchyCtx,\n\t\t\t\ttable,\n\t\t\t\trelationHints,\n\t\t\t);\n\n\t\t\tconst result = await builder\n\t\t\t\t.where(eq(nodeIdCol, nodeIdValue))\n\t\t\t\t.include(selfRefRelation.name, {\n\t\t\t\t\trecursive: true,\n\t\t\t\t\tdirection: 'descendants',\n\t\t\t\t\tflat: true,\n\t\t\t\t\tomitSelf: true,\n\t\t\t\t\tmaxDepth: safeMaxDepth,\n\t\t\t\t})\n\t\t\t\t.first();\n\n\t\t\t// Result shape from include({ recursive, direction: 'descendants' }):\n\t\t\t// { id, ..., descendants: [...] }\n\t\t\treturn extractRecursiveField<TResult>(result, 'descendants');\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Typed Mutation Entry Points (DX-040-SURFACE)\n\t\t// Extract table name from TableRef metadata and delegate to string methods\n\t\t// =====================================================================\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: polymorphic constraint — TTable is inferred by callers; TableRef generics are statically erased in this implementation signature\n\t\tinto<TTable extends TableRef<any, any, any>>(\n\t\t\ttableRef: TTable,\n\t\t): InsertBuilder<InferTableRow<TTable>> {\n\t\t\tconst tableName = tableRef[TABLE_META];\n\t\t\tif (tableName === undefined) {\n\t\t\t\tthrow new Error('Invalid TableRef: missing TABLE_META symbol');\n\t\t\t}\n\t\t\treturn new InsertBuilder({\n\t\t\t\ttable: tableName as string,\n\t\t\t\t...mutationOpts,\n\t\t\t}) as InsertBuilder<InferTableRow<TTable>>;\n\t\t},\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: polymorphic constraint — TTable is inferred by callers; TableRef generics are statically erased in this implementation signature\n\t\tmodify<TTable extends TableRef<any, any, any>>(\n\t\t\ttableRef: TTable,\n\t\t): UpdateBuilder<InferTableRow<TTable>> {\n\t\t\tconst tableName = tableRef[TABLE_META];\n\t\t\tif (tableName === undefined) {\n\t\t\t\tthrow new Error('Invalid TableRef: missing TABLE_META symbol');\n\t\t\t}\n\t\t\treturn new UpdateBuilder({\n\t\t\t\ttable: tableName as string,\n\t\t\t\t...mutationOpts,\n\t\t\t}) as UpdateBuilder<InferTableRow<TTable>>;\n\t\t},\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: polymorphic constraint — TTable is inferred by callers; TableRef generics are statically erased in this implementation signature\n\t\tremoveFrom<TTable extends TableRef<any, any, any>>(\n\t\t\ttableRef: TTable,\n\t\t): DeleteBuilder<InferTableRow<TTable>> {\n\t\t\tconst tableName = tableRef[TABLE_META];\n\t\t\tif (tableName === undefined) {\n\t\t\t\tthrow new Error('Invalid TableRef: missing TABLE_META symbol');\n\t\t\t}\n\t\t\treturn new DeleteBuilder({\n\t\t\t\ttable: tableName as string,\n\t\t\t\t...mutationOpts,\n\t\t\t}) as DeleteBuilder<InferTableRow<TTable>>;\n\t\t},\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: polymorphic constraint — TTable is inferred by callers; TableRef generics are statically erased in this implementation signature\n\t\tupsertInto<TTable extends TableRef<any, any, any>>(\n\t\t\ttableRef: TTable,\n\t\t): UpsertBuilder<InferTableRow<TTable>> {\n\t\t\tconst tableName = tableRef[TABLE_META];\n\t\t\tif (tableName === undefined) {\n\t\t\t\tthrow new Error('Invalid TableRef: missing TABLE_META symbol');\n\t\t\t}\n\t\t\treturn new UpsertBuilder({\n\t\t\t\ttable: tableName as string,\n\t\t\t\t...mutationOpts,\n\t\t\t}) as UpsertBuilder<InferTableRow<TTable>>;\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Mutation Methods (DX-010)\n\t\t// =====================================================================\n\n\t\tinsert(table: string): InsertBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new InsertBuilder({ table, ...mutationOpts });\n\t\t},\n\n\t\tupdate(table: string): UpdateBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new UpdateBuilder({ table, ...mutationOpts });\n\t\t},\n\n\t\tdelete(table: string): DeleteBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new DeleteBuilder({ table, ...mutationOpts });\n\t\t},\n\n\t\tupdateAll(table: string): UpdateBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new UpdateBuilder({ table, allowAll: true, ...mutationOpts });\n\t\t},\n\n\t\tdeleteAll(table: string): DeleteBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new DeleteBuilder({ table, allowAll: true, ...mutationOpts });\n\t\t},\n\n\t\t// DX-026: Upsert support\n\t\tupsert(table: string): UpsertBuilder {\n\t\t\tvalidateIdentifier(table, 'table');\n\t\t\treturn new UpsertBuilder({ table, ...mutationOpts });\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Transaction Methods (DX-025)\n\t\t// =====================================================================\n\n\t\tasync transaction<T>(fn: (tx: OrmInstance<DB>) => Promise<T>): Promise<T> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'transaction() requires an adapter. ' +\n\t\t\t\t\t\t'Pass an adapter when creating the ORM.',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Passthrough to adapter's transaction API\n\t\t\treturn adapter.transaction(async (txAdapter) => {\n\t\t\t\t// Create a transaction-scoped ORM instance with inTransaction=true\n\t\t\t\tconst txOrm = createOrmInstance<DB>(\n\t\t\t\t\tmodel,\n\t\t\t\t\tstrictMode,\n\t\t\t\t\trelationHints,\n\t\t\t\t\ttxAdapter as Adapter<DB>,\n\t\t\t\t\tschemaName,\n\t\t\t\t\tdialectCapabilities,\n\t\t\t\t\tschemaDefinition,\n\t\t\t\t\tglobalPlanOptions,\n\t\t\t\t\tdefaultFilters,\n\t\t\t\t\thookStore,\n\t\t\t\t\tonHookError,\n\t\t\t\t\ttrue, // inTransaction\n\t\t\t\t\ttablesProxy,\n\t\t\t\t);\n\t\t\t\treturn fn(txOrm);\n\t\t\t});\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Raw SQL Execution (DX-027)\n\t\t// =====================================================================\n\n\t\t/**\n\t\t * Execute raw SQL directly - escape hatch for queries that cannot\n\t\t * be expressed via the intent system.\n\t\t *\n\t\t * @warning **SECURITY RISK: POTENTIAL SQL INJECTION**\n\t\t *\n\t\t * This method bypasses the semantic planner and all type safety.\n\t\t * Always use parameter placeholders ($1, $2, etc.) for values.\n\t\t *\n\t\t * **SAFE:**\n\t\t * ```typescript\n\t\t * orm.raw('SELECT * FROM users WHERE id = $1', [userId]);\n\t\t * ```\n\t\t *\n\t\t * **DANGEROUS - NEVER DO THIS:**\n\t\t * ```typescript\n\t\t * orm.raw(`SELECT * FROM users WHERE id = ${userId}`);\n\t\t * ```\n\t\t *\n\t\t * @param sqlString - SQL with parameter placeholders ($1, $2, etc.)\n\t\t * @param parameters - Values to bind (safely escaped by driver)\n\t\t * @returns Promise resolving to typed results\n\t\t *\n\t\t * @see {@link https://owasp.org/www-community/attacks/SQL_Injection | OWASP SQL Injection}\n\t\t */\n\t\tasync raw<T = unknown>(\n\t\t\tsqlString: string,\n\t\t\tparameters: readonly unknown[] = [],\n\t\t): Promise<T[]> {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'raw() requires an adapter. ' +\n\t\t\t\t\t\t'Pass an adapter when creating the ORM.',\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Passthrough to adapter's executeRaw API\n\t\t\treturn adapter.executeRaw<T>(sqlString, parameters);\n\t\t},\n\n\t\tbatchValues(\n\t\t\tdata: readonly unknown[][],\n\t\t\tcolumns: readonly string[],\n\t\t\ttypes: readonly string[],\n\t\t\topts?: BatchValuesOptions,\n\t\t): BatchValuesRef {\n\t\t\treturn batchValues(data, columns, types, opts);\n\t\t},\n\n\t\tselectExpression(expr: ExpressionSpec): SelectExpressionResult {\n\t\t\tif (!adapter) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'selectExpression() requires an adapter. ' +\n\t\t\t\t\t\t'Pass an adapter when creating the ORM.',\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst compiled = adapter.compileSelectExpression(expr.intent);\n\t\t\treturn {\n\t\t\t\tsql: compiled.sql,\n\t\t\t\tparameters: compiled.parameters,\n\t\t\t\texecute<T = unknown>(): Promise<T[]> {\n\t\t\t\t\treturn adapter?.executeRaw<T>(compiled.sql, compiled.parameters);\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\n\t\twithCte(name: string): CteBuilder {\n\t\t\treturn new CteBuilder(name, adapter, schemaName);\n\t\t},\n\n\t\trecursive<TResult = unknown>(\n\t\t\tname: string,\n\t\t\toptions: RecursiveOptions,\n\t\t): RawCteQueryBuilder<TResult> {\n\t\t\treturn createRawCteBuilder<TResult>(name, options, adapter, schemaName);\n\t\t},\n\n\t\t// =====================================================================\n\t\t// Global DDL Shortcuts (F-005)\n\t\t// =====================================================================\n\n\t\tddl: {\n\t\t\t/**\n\t\t\t * Drop an index by name (not table-scoped).\n\t\t\t *\n\t\t\t * @param name - Index name to drop\n\t\t\t * @param options - Optional DROP INDEX options\n\t\t\t */\n\t\t\tasync dropIndex(name: string, options?: DropIndexOptions): Promise<void> {\n\t\t\t\tif (!adapter?.executeDDL) {\n\t\t\t\t\tthrow new InvalidOperationError(\n\t\t\t\t\t\t'ddl.dropIndex',\n\t\t\t\t\t\t'executeDDL() requires an adapter that supports DDL execution.',\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// FIND-003: Validate index name and optional schema before building SQL\n\t\t\t\tvalidateIdentifier(name, 'index');\n\t\t\t\tconst sc = options?.schema ?? schemaName;\n\t\t\t\tif (sc) {\n\t\t\t\t\tvalidateIdentifier(sc, 'schema');\n\t\t\t\t}\n\t\t\t\tconst sql = adapter.generateDropIndex\n\t\t\t\t\t? adapter.generateDropIndex(name, options)\n\t\t\t\t\t: (() => {\n\t\t\t\t\t\t\tconst parts: string[] = ['DROP INDEX'];\n\t\t\t\t\t\t\tif (options?.concurrently) parts.push('CONCURRENTLY');\n\t\t\t\t\t\t\tif (options?.ifExists) parts.push('IF EXISTS');\n\t\t\t\t\t\t\tparts.push(\n\t\t\t\t\t\t\t\tsc\n\t\t\t\t\t\t\t\t\t? `\"${sc.replace(/\"/g, '\"\"')}\".\"${name.replace(/\"/g, '\"\"')}\"`\n\t\t\t\t\t\t\t\t\t: `\"${name.replace(/\"/g, '\"\"')}\"`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (options?.cascade) parts.push('CASCADE');\n\t\t\t\t\t\t\treturn parts.join(' ');\n\t\t\t\t\t\t})();\n\t\t\t\tawait adapter.executeDDL(sql);\n\t\t\t},\n\t\t},\n\t};\n}\n","import type {\n\tFeatureBehaviorConfig,\n\tUnsupportedFeatureBehavior,\n} from '@dbsp/types';\nimport type { Adapter } from '../adapter.js';\nimport type { ModelIR } from '../model-ir.js';\nimport type { PlanOptions } from '../planner.js';\nimport { NamingConventionMismatchError } from './errors.js';\nimport {\n\tgetHookStore,\n\ttype HookErrorHandler,\n\ttype HookManager,\n} from './hooks.js';\nimport { negotiateFeatures } from './negotiate-features.js';\nimport { createOrmInstance } from './orm-instance.js';\nimport type {\n\tDefaultFilters,\n\tInferDB,\n\tSchema,\n\tSchemaDefinition,\n} from './schema.js';\nimport { createTablesProxy } from './table-ref-factory.js';\nimport type { OrmInstance } from './types.js';\n\n// ============================================================================\n// ARCH-006: Simplified ORM Entry Point\n// ============================================================================\n\n/**\n * ARCH-006: Simplified ORM options.\n *\n * Uses the unified Schema API with required schema and adapter.\n * The schema must be created with `schema()` + `ref()`.\n *\n * @example Full ORM with adapter\n * ```typescript\n * const orm = createOrm({ schema: mySchema, adapter });\n * const users = await orm.select('users').all();\n * ```\n *\n * @example Tests with mock adapter\n * ```typescript\n * import { createMockAdapter } from './test-utils.js';\n * const orm = createOrm({ schema: mySchema, adapter: createMockAdapter() });\n * ```\n */\nexport interface SimplifiedOrmOptions<\n\tT extends SchemaDefinition = SchemaDefinition,\n> {\n\t/**\n\t * Schema created with schema() + ref().\n\t * Either schema or model is required.\n\t */\n\treadonly schema?: Schema<T>;\n\n\t/**\n\t * ModelIR directly (alternative to schema).\n\t * Use this when you have ModelIR from introspection or external source.\n\t * Either schema or model is required.\n\t */\n\treadonly model?: ModelIR;\n\n\t/**\n\t * Adapter for database operations.\n\t *\n\t * Required — provides dialect capabilities for planner strategy selection.\n\t * For compile-only usage (no DB), use `createMockAdapter()` from test-utils\n\t * or `createPgsqlCompileOnlyAdapter()` from adapter-pgsql.\n\t */\n\treadonly adapter: Adapter<unknown>;\n\n\t/**\n\t * Enable strict mode validation (default: false).\n\t */\n\treadonly strictMode?: boolean;\n\n\t// ============================================================\n\t// Global Limits (NQL-ALIGN Block 3)\n\t// ============================================================\n\n\t/**\n\t * Maximum depth for recursive CTE queries.\n\t * Prevents infinite recursion in tree/graph traversals.\n\t * @default 10\n\t */\n\treadonly maxDepth?: number;\n\n\t/**\n\t * Maximum number of relation hops in a single query.\n\t * Limits paths like `user.posts.comments.author.profile`.\n\t * @default 5\n\t */\n\treadonly maxTableHops?: number;\n\n\t/**\n\t * Maximum nesting depth for CASE expressions.\n\t * Prevents overly complex conditional logic.\n\t * @default 10\n\t */\n\treadonly maxNestedCase?: number;\n\n\t/**\n\t * Global plan options passed to the semantic planner for every query.\n\t * Per-query overrides via `.withPlanOptions()` take precedence.\n\t *\n\t * @example\n\t * ```typescript\n\t * const orm = createOrm({\n\t * schema,\n\t * adapter,\n\t * planOptions: {\n\t * defaultIncludeStrategy: 'subquery',\n\t * enableCTEs: true,\n\t * maxIncludeDepth: 3,\n\t * },\n\t * });\n\t * ```\n\t */\n\treadonly planOptions?: PlanOptions;\n\n\t/**\n\t * Hook manager for query/mutation interception (E17b).\n\t * Created via `createHookManager()`.\n\t * Hooks are frozen on ORM creation — no hooks can be added after.\n\t */\n\treadonly hooks?: HookManager;\n\n\t/**\n\t * Error handler for hook failures (E17b).\n\t * Called when a hook throws. Returns 'continue' to skip the failed hook,\n\t * or 'abort' to propagate the error.\n\t */\n\treadonly onHookError?: HookErrorHandler;\n\n\t/**\n\t * Behavior when schema uses features the adapter doesn't support.\n\t * Default: 'warning' (emit warning + skip).\n\t * Use 'error' for strict environments, 'ignore' to suppress.\n\t * Pass FeatureBehaviorConfig for per-feature overrides.\n\t */\n\treadonly unsupportedFeatures?:\n\t\t| UnsupportedFeatureBehavior\n\t\t| FeatureBehaviorConfig;\n}\n\n/**\n * Create an ORM instance with the specified configuration.\n *\n * @typeParam DB - Database schema type (Kysely-like).\n * Keys are table names, values are row types.\n * When provided, query() provides autocomplete and type inference.\n *\n * @param options - Configuration options including model and strictMode\n * @returns An ORM instance for building and planning queries\n *\n * @example With schema() + ref() API (recommended)\n * ```typescript\n * import { schema, ref, createOrm } from '@dbsp/core';\n *\n * const mySchema = schema({\n * users: {\n * id: 'uuid',\n * name: 'string',\n * },\n * posts: {\n * id: 'uuid',\n * title: 'string',\n * authorId: ref('users.id'),\n * },\n * });\n *\n * const orm = createOrm({ schema: mySchema, adapter });\n *\n * // Table names autocomplete, results are typed!\n * const users = await orm.select('users').all();\n *\n * // Include relations with type inference\n * const usersWithPosts = await orm.select('users').include('posts').all();\n * ```\n */\n/**\n * ARCH-006: Creates an ORM instance from a schema.\n *\n * This is the single entry point for creating ORM instances.\n * The schema must be created with `schema()` + `ref()`.\n *\n * For database introspection (when available), use the adapter's introspect method:\n * ```typescript\n * const model = await adapter.introspect({ schema: 'public' });\n * const orm = createOrm({ schema: model, adapter });\n * ```\n *\n * @param options - ORM options with required schema\n * @returns ORM instance for querying\n *\n * @example With database adapter\n * ```typescript\n * const orm = createOrm({ schema: mySchema, adapter });\n * const users = await orm.select('users').all();\n * ```\n */\nexport function createOrm<T extends SchemaDefinition>(\n\toptions: SimplifiedOrmOptions<T>,\n): OrmInstance<InferDB<T>> {\n\tconst {\n\t\tschema: schemaObj,\n\t\tmodel: modelDirect,\n\t\tadapter,\n\t\tstrictMode = false,\n\t\tplanOptions: globalPlanOptions,\n\t\thooks: hookManager,\n\t\tonHookError,\n\t\tunsupportedFeatures,\n\t} = options;\n\n\t// ARCH-006: Either schema or model is required\n\t// Schema provides full type inference; model is simpler for introspection/tests\n\tlet model: ModelIR;\n\tlet schemaDefinition: unknown;\n\tlet defaultFilters: DefaultFilters | undefined;\n\n\tif (schemaObj && 'model' in schemaObj) {\n\t\t// Full schema object provided\n\t\tmodel = schemaObj.model;\n\t\tschemaDefinition = schemaObj.definition;\n\t\tdefaultFilters = schemaObj.defaultFilters;\n\n\t\t// ARCH-006: Validate casing consistency\n\t\tif (\n\t\t\tadapter &&\n\t\t\tschemaObj.dbCasing &&\n\t\t\tadapter.dbCasing &&\n\t\t\tschemaObj.dbCasing !== adapter.dbCasing\n\t\t) {\n\t\t\tthrow new NamingConventionMismatchError({\n\t\t\t\tschemaCasing: schemaObj.dbCasing,\n\t\t\t\tadapterCasing: adapter.dbCasing,\n\t\t\t});\n\t\t}\n\t} else if (modelDirect) {\n\t\t// ModelIR provided directly (simpler API for introspection/tests)\n\t\tmodel = modelDirect;\n\t\tschemaDefinition = undefined; // NQL will work without schema validation\n\t\tdefaultFilters = undefined;\n\t} else {\n\t\tthrow new Error(\n\t\t\t'Invalid options: must provide either schema (from schema() function) ' +\n\t\t\t\t'or model (ModelIR). For database introspection, use getSchemaFromDb() ' +\n\t\t\t\t'from the adapter (e.g. adapter.introspect()).',\n\t\t);\n\t}\n\n\t// CAPS-003: Feature negotiation — cross-check ModelIR against adapter capabilities\n\tif (adapter?.dialectCapabilities) {\n\t\tconst result = negotiateFeatures(\n\t\t\tmodel,\n\t\t\tadapter.dialectCapabilities,\n\t\t\tunsupportedFeatures ?? 'warning',\n\t\t);\n\t\tfor (const w of result.warnings) {\n\t\t\tconsole.warn(`[dbsp] ${w.message}`);\n\t\t}\n\t}\n\n\t// E17b: Freeze hook manager on ORM creation — no hooks can be added after\n\tconst frozenHookStore = hookManager\n\t\t? getHookStore(hookManager.freeze())\n\t\t: undefined;\n\n\t// DX-040-SURFACE: Build tables proxy for type-safe table access\n\t// Use schema's pre-built proxy if available, otherwise build from model\n\tconst tablesProxy: object =\n\t\tschemaObj && 'tables' in schemaObj\n\t\t\t? (schemaObj.tables as object)\n\t\t\t: createTablesProxy(model, model.tables ? [...model.tables.keys()] : []);\n\n\t// Create ORM instance with ModelIR\n\t// Cast to InferDB<T> since createOrmInstance uses internal types\n\treturn createOrmInstance(\n\t\tmodel,\n\t\tstrictMode,\n\t\t{}, // relationHints removed in ARCH-006\n\t\tadapter,\n\t\tundefined, // schemaName\n\t\tadapter.dialectCapabilities,\n\t\tschemaDefinition,\n\t\tglobalPlanOptions,\n\t\tdefaultFilters,\n\t\tfrozenHookStore,\n\t\tonHookError,\n\t\tundefined, // inTransaction\n\t\ttablesProxy,\n\t) as unknown as OrmInstance<InferDB<T>>;\n}\n","/**\n * @module range\n * PostgreSQL range operator helpers — expression-level (ExpressionRef) API.\n *\n * Provides three operators for PostgreSQL range types:\n * - `rangeOverlaps` — `&&` (any points in common)\n * - `rangeContains` — `@>` (range contains range or element)\n * - `rangeContainedBy` — `<@` (range is contained by another range)\n *\n * Tuple form: `rangeOverlaps('period', ['2024-01-01', '2024-01-31'])` → ExpressionRef\n * Compiles to: `\"period\" && daterange($1, $2)`\n *\n * Object form: `rangeOverlaps('period', { lower: '2024-01-01', upper: '2024-01-31' })` → WhereRangeIntent\n * Handled by the planner's range pipeline (backward-compatible path).\n *\n * @example\n * ```typescript\n * import { rangeOverlaps, rangeContains, rangeContainedBy } from '@dbsp/core';\n *\n * orm.select('bookings').where(rangeOverlaps('period', ['2024-01-01', '2024-01-31']))\n * orm.select('events').where(rangeContains('dateRange', ['2024-06-15', '2024-06-15']))\n * orm.select('events').where(rangeContainedBy('dateRange', ['2024-01-01', '2024-12-31']))\n * ```\n */\n\nimport type { RangeOperand, RangeValue } from '@dbsp/types';\nimport type { WhereRangeIntent } from '../intent-ast.js';\nimport { type ExpressionRef, fn, op, param, ref } from './expressions.js';\n\nexport type { RangeOperand, RangeValue } from '@dbsp/types';\n\n// ============================================================================\n// RangeType\n// ============================================================================\n\n/**\n * PostgreSQL range type names.\n *\n * Used as the third argument to range helpers to control the constructor\n * function emitted in SQL (e.g. `daterange($1, $2)`, `int4range($1, $2)`).\n *\n * Defaults to `'daterange'` when omitted.\n */\nexport type RangeType =\n\t| 'int4range'\n\t| 'int8range'\n\t| 'numrange'\n\t| 'tsrange'\n\t| 'tstzrange'\n\t| 'daterange';\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\n/**\n * Build the range constructor call: `rangeType(param(lower), param(upper))`\n */\nfunction makeRangeFn(\n\trange: readonly [unknown, unknown],\n\trangeType: RangeType,\n): ExpressionRef {\n\treturn fn(rangeType, param(range[0]), param(range[1]));\n}\n\n/**\n * Assert that `arr` is a 2-element tuple.\n * Throws a clear error for 0-, 1-, or 3+-element arrays so callers get\n * actionable feedback instead of silently producing bad SQL.\n */\nfunction assertTupleLength(arr: unknown[]): void {\n\tif (arr.length !== 2) {\n\t\tthrow new Error(\n\t\t\t`range tuple must have exactly 2 elements (got ${arr.length}); use [lower, upper] or pass a RangeValue object`,\n\t\t);\n\t}\n}\n\n// ============================================================================\n// rangeOverlaps — &&\n// ============================================================================\n\n/**\n * Range OVERLAPS — tuple API: `\"column\" && rangeType($1, $2)` (ExpressionRef)\n *\n * @example rangeOverlaps('period', ['2024-01-01', '2024-01-31'])\n * → \"period\" && daterange($1, $2)\n * @example rangeOverlaps('span', [1, 100], 'int4range')\n * → \"span\" && int4range($1, $2)\n */\nexport function rangeOverlaps(\n\tcolumn: string,\n\trange: readonly [unknown, unknown],\n\trangeType?: RangeType,\n): ExpressionRef;\n\n/**\n * Range OVERLAPS — object API: delegates to WhereRangeIntent (planner path)\n *\n * @example rangeOverlaps('dates', { lower: '2025-01-15', upper: '2025-01-20' })\n */\nexport function rangeOverlaps(\n\tfield: string,\n\tvalue: RangeValue,\n): WhereRangeIntent;\n\nexport function rangeOverlaps(\n\tfieldOrColumn: string,\n\tvalueOrRange: RangeOperand | readonly [unknown, unknown],\n\trangeType: RangeType = 'daterange',\n): ExpressionRef | WhereRangeIntent {\n\tif (Array.isArray(valueOrRange)) {\n\t\tassertTupleLength(valueOrRange);\n\t\tconst tuple = valueOrRange as unknown as readonly [unknown, unknown];\n\t\treturn op('&&', ref(fieldOrColumn), makeRangeFn(tuple, rangeType));\n\t}\n\treturn {\n\t\tkind: 'range',\n\t\tfield: fieldOrColumn,\n\t\toperator: 'overlaps',\n\t\t// Cast: non-array branch is RangeOperand (tuple path already returned above)\n\t\tvalue: valueOrRange as RangeOperand,\n\t};\n}\n\n// ============================================================================\n// rangeContains — @>\n// ============================================================================\n\n/**\n * Range CONTAINS — tuple API: `\"column\" @> rangeType($1, $2)` (ExpressionRef)\n *\n * @example rangeContains('dateRange', ['2024-06-15', '2024-06-15'])\n * → \"dateRange\" @> daterange($1, $2)\n */\nexport function rangeContains(\n\tcolumn: string,\n\trange: readonly [unknown, unknown],\n\trangeType?: RangeType,\n): ExpressionRef;\n\n/**\n * Range CONTAINS — object API: delegates to WhereRangeIntent (planner path)\n *\n * @example rangeContains('date_range', { lower: '2025-01-01', upper: '2025-01-05' })\n */\nexport function rangeContains(\n\tfield: string,\n\tvalue: RangeValue,\n): WhereRangeIntent;\n\nexport function rangeContains(\n\tfieldOrColumn: string,\n\tvalueOrRange: RangeOperand | readonly [unknown, unknown],\n\trangeType: RangeType = 'daterange',\n): ExpressionRef | WhereRangeIntent {\n\tif (Array.isArray(valueOrRange)) {\n\t\tassertTupleLength(valueOrRange);\n\t\tconst tuple = valueOrRange as unknown as readonly [unknown, unknown];\n\t\treturn op('@>', ref(fieldOrColumn), makeRangeFn(tuple, rangeType));\n\t}\n\treturn {\n\t\tkind: 'range',\n\t\tfield: fieldOrColumn,\n\t\toperator: 'contains',\n\t\tvalue: valueOrRange as RangeOperand,\n\t};\n}\n\n// ============================================================================\n// rangeContainedBy — <@\n// ============================================================================\n\n/**\n * Range CONTAINED BY — tuple API: `\"column\" <@ rangeType($1, $2)` (ExpressionRef)\n *\n * @example rangeContainedBy('dateRange', ['2024-01-01', '2024-12-31'])\n * → \"dateRange\" <@ daterange($1, $2)\n */\nexport function rangeContainedBy(\n\tcolumn: string,\n\trange: readonly [unknown, unknown],\n\trangeType?: RangeType,\n): ExpressionRef;\n\n/**\n * Range CONTAINED BY — object API: delegates to WhereRangeIntent (planner path)\n *\n * @example rangeContainedBy('event_dates', { lower: '2025-01-01', upper: '2025-12-31' })\n */\nexport function rangeContainedBy(\n\tfield: string,\n\tvalue: RangeValue,\n): WhereRangeIntent;\n\nexport function rangeContainedBy(\n\tfieldOrColumn: string,\n\tvalueOrRange: RangeOperand | readonly [unknown, unknown],\n\trangeType: RangeType = 'daterange',\n): ExpressionRef | WhereRangeIntent {\n\tif (Array.isArray(valueOrRange)) {\n\t\tassertTupleLength(valueOrRange);\n\t\tconst tuple = valueOrRange as unknown as readonly [unknown, unknown];\n\t\treturn op('<@', ref(fieldOrColumn), makeRangeFn(tuple, rangeType));\n\t}\n\treturn {\n\t\tkind: 'range',\n\t\tfield: fieldOrColumn,\n\t\toperator: 'containedBy',\n\t\tvalue: valueOrRange as RangeOperand,\n\t};\n}\n","/**\n * ARCH-002 Block 6: Schema Bridge\n *\n * Converts generated schema (from dbsp generate manifest) to ModelIR.\n * This enables sync createOrm usage with codegen-first schemas.\n */\n\nimport type { Mutable } from '@dbsp/types/internal';\nimport * as v from 'valibot';\nimport { ModelIRImpl } from '../model-impl.js';\nimport {\n\ttype Cardinality,\n\ttype ColumnIR,\n\ttype ColumnType,\n\tcreatePseudoColumnMetadata,\n\ttype FilterStrategy,\n\ttype ForeignKeyIR,\n\ttype IncludeStrategy,\n\ttype IndexIR,\n\ttype JoinDefault,\n\ttype ModelIR,\n\ttype Optionality,\n\ttype PseudoColumnMetadata,\n\ttype RelationIR,\n\ttype RelationType,\n\ttype TableIR,\n} from '../model-ir.js';\nimport type { ResolvedSchema } from '../schema-dsl-types.js';\n\n// ============================================================================\n// Generated Schema Types (from dbsp generate manifest)\n// ============================================================================\n\n/**\n * Column type in generated schema.\n */\nexport type GeneratedColumnType =\n\t| 'string'\n\t| 'text'\n\t| 'number'\n\t| 'integer'\n\t| 'bigint'\n\t| 'decimal'\n\t| 'boolean'\n\t| 'date'\n\t| 'timestamp'\n\t| 'datetime'\n\t| 'time'\n\t| 'json'\n\t| 'jsonb'\n\t| 'uuid'\n\t| 'daterange'\n\t| 'tstzrange'\n\t| 'int4range'\n\t| 'tsrange'\n\t| 'int8range'\n\t| 'numrange';\n\n/**\n * Column definition in generated schema.\n */\nexport interface GeneratedColumn {\n\treadonly type: GeneratedColumnType;\n\treadonly primaryKey?: boolean;\n\treadonly nullable?: boolean;\n\treadonly unique?: boolean;\n\treadonly autoIncrement?: boolean;\n\treadonly default?: string;\n\treadonly references?: {\n\t\treadonly table: string;\n\t\treadonly column?: string;\n\t\treadonly onDelete?: 'CASCADE' | 'SET NULL' | 'RESTRICT' | 'NO ACTION';\n\t\t/** Create an index on this FK column (matches ColumnDefinitionSchema index field) */\n\t\treadonly index?: boolean;\n\t\t/** Role name for parent traversal in self-ref hierarchies (e.g., 'parent') */\n\t\treadonly parentRole?: string;\n\t\t/** Role name for child traversal in self-ref hierarchies (e.g., 'children') */\n\t\treadonly childRole?: string;\n\t};\n\t/** Create an index on this column (true for auto-name, string for custom name) */\n\treadonly index?: boolean | string;\n}\n\n/**\n * Table definition in generated schema.\n */\nexport type GeneratedTable = Record<string, GeneratedColumn>;\n\n/**\n * Relation kind in generated schema (discriminated union).\n */\nexport type GeneratedRelationKind = 'belongsTo' | 'hasMany' | 'manyToMany';\n\n/**\n * Include strategy for relations.\n */\ntype GeneratedIncludeStrategy =\n\t| 'join'\n\t| 'subquery'\n\t| 'cte'\n\t| 'lateral'\n\t| 'json_agg'\n\t| 'auto';\n\n/**\n * BelongsTo relation in generated schema.\n */\nexport interface GeneratedBelongsTo {\n\treadonly kind: 'belongsTo';\n\treadonly target: string;\n\treadonly foreignKey: string;\n\treadonly targetKey?: string;\n\treadonly includeStrategy?: GeneratedIncludeStrategy;\n}\n\n/**\n * HasMany relation in generated schema.\n */\nexport interface GeneratedHasMany {\n\treadonly kind: 'hasMany';\n\treadonly target: string;\n\treadonly foreignKey: string;\n\treadonly sourceKey?: string;\n\treadonly includeStrategy?: GeneratedIncludeStrategy;\n\treadonly cardinality?: 'one' | 'many';\n}\n\n/**\n * ManyToMany relation in generated schema.\n */\nexport interface GeneratedManyToMany {\n\treadonly kind: 'manyToMany';\n\treadonly target: string;\n\treadonly through: string;\n\treadonly sourceFk: string;\n\treadonly targetFk: string;\n\treadonly includeStrategy?: GeneratedIncludeStrategy;\n}\n\n/**\n * Relation definition in generated schema.\n */\nexport type GeneratedRelation =\n\t| GeneratedBelongsTo\n\t| GeneratedHasMany\n\t| GeneratedManyToMany;\n\n/**\n * Hint definition in generated schema.\n */\nexport interface GeneratedHint {\n\treadonly defaultStrategy?: 'exists' | 'join';\n\treadonly cardinality?: 'one' | 'many';\n}\n\n/**\n * Conventions in generated schema.\n */\nexport interface GeneratedConventions {\n\treadonly fkPattern: string;\n\treadonly pluralize: boolean;\n\treadonly timestamps: readonly string[];\n\treadonly fkAutoIndex: boolean;\n}\n\n/**\n * Complete generated schema (output of dbsp generate manifest).\n *\n * @typeParam TTables - The tables type, preserving literal table names for autocomplete.\n * When using `as const` on your schema definition, table names will be preserved.\n *\n * @example\n * ```typescript\n * const schema = {\n * tables: {\n * users: { id: { type: 'uuid', primaryKey: true }, name: { type: 'string' } },\n * posts: { id: { type: 'uuid', primaryKey: true }, title: { type: 'string' } },\n * },\n * relations: {},\n * hints: {},\n * conventions: { fkPattern: '{singular}Id', pluralize: true, timestamps: [], fkAutoIndex: true },\n * } as const satisfies GeneratedSchema;\n *\n * // TypeScript knows: keyof typeof schema.tables = 'users' | 'posts'\n * ```\n */\nexport interface GeneratedSchema<\n\tTTables extends Record<string, GeneratedTable> = Record<\n\t\tstring,\n\t\tGeneratedTable\n\t>,\n> {\n\treadonly tables: TTables;\n\treadonly relations: Record<string, GeneratedRelation>;\n\treadonly hints: Record<string, GeneratedHint>;\n\treadonly conventions: GeneratedConventions;\n}\n\n// ============================================================================\n// Type Utilities for Schema Inference\n// ============================================================================\n\n/**\n * Map a GeneratedColumnType to its TypeScript runtime type.\n */\nexport type ColumnTypeToTS<T extends GeneratedColumnType> = T extends\n\t| 'string'\n\t| 'text'\n\t| 'uuid'\n\t? string\n\t: T extends 'number' | 'integer' | 'decimal'\n\t\t? number\n\t\t: T extends 'bigint'\n\t\t\t? bigint\n\t\t\t: T extends 'boolean'\n\t\t\t\t? boolean\n\t\t\t\t: T extends 'date' | 'timestamp' | 'datetime'\n\t\t\t\t\t? Date\n\t\t\t\t\t: T extends 'time'\n\t\t\t\t\t\t? string\n\t\t\t\t\t\t: T extends 'json' | 'jsonb'\n\t\t\t\t\t\t\t? unknown\n\t\t\t\t\t\t\t: // PostgreSQL range types — no native Range<T> in TS; represented as string (e.g., \"[2020-01-01,2020-12-31)\")\n\t\t\t\t\t\t\t\tT extends\n\t\t\t\t\t\t\t\t\t\t| 'daterange'\n\t\t\t\t\t\t\t\t\t\t| 'tstzrange'\n\t\t\t\t\t\t\t\t\t\t| 'int4range'\n\t\t\t\t\t\t\t\t\t\t| 'tsrange'\n\t\t\t\t\t\t\t\t\t\t| 'int8range'\n\t\t\t\t\t\t\t\t\t\t| 'numrange'\n\t\t\t\t\t\t\t\t? string\n\t\t\t\t\t\t\t\t: never;\n\n/**\n * Infer the TypeScript row type from a GeneratedTable definition.\n */\nexport type InferRowType<T extends GeneratedTable> = {\n\t[K in keyof T]: T[K]['nullable'] extends true\n\t\t? ColumnTypeToTS<T[K]['type']> | null\n\t\t: ColumnTypeToTS<T[K]['type']>;\n};\n\n/**\n * Infer the database type from a GeneratedSchema.\n * Maps each table name to its row type.\n *\n * @example\n * ```typescript\n * const schema = { tables: { users: { id: { type: 'uuid' } } } } as const satisfies GeneratedSchema;\n * type DB = InferDBFromSchema<typeof schema>;\n * // DB = { users: { id: string } }\n * ```\n */\nexport type InferDBFromSchema<S extends GeneratedSchema> = {\n\t[TableName in keyof S['tables'] & string]: InferRowType<\n\t\tS['tables'][TableName]\n\t>;\n};\n\n// ============================================================================\n// Conversion Functions\n// ============================================================================\n\n/**\n * Map generated column type to ModelIR column type.\n */\nfunction generatedTypeToColumnType(genType: GeneratedColumnType): ColumnType {\n\tswitch (genType) {\n\t\tcase 'string':\n\t\tcase 'text':\n\t\t\treturn 'string';\n\t\tcase 'number':\n\t\tcase 'decimal':\n\t\t\treturn 'number';\n\t\tcase 'integer':\n\t\t\treturn 'integer';\n\t\tcase 'bigint':\n\t\t\treturn 'bigint';\n\t\tcase 'boolean':\n\t\t\treturn 'boolean';\n\t\tcase 'date':\n\t\t\treturn 'date';\n\t\tcase 'timestamp':\n\t\tcase 'datetime':\n\t\t\treturn 'datetime';\n\t\tcase 'json':\n\t\t\treturn 'json';\n\t\tcase 'jsonb':\n\t\t\treturn 'jsonb';\n\t\tcase 'time':\n\t\t\treturn 'time';\n\t\tcase 'uuid':\n\t\t\treturn 'uuid';\n\t\tcase 'daterange':\n\t\t\treturn 'daterange';\n\t\tcase 'tstzrange':\n\t\t\treturn 'tstzrange';\n\t\tcase 'int4range':\n\t\t\treturn 'int4range';\n\t\tcase 'tsrange':\n\t\t\treturn 'tsrange';\n\t\tcase 'int8range':\n\t\t\treturn 'int8range';\n\t\tcase 'numrange':\n\t\t\treturn 'numrange';\n\t}\n}\n\n/**\n * Map generated relation kind to ModelIR relation type.\n */\nfunction mapRelationType(kind: GeneratedRelationKind): RelationType {\n\tswitch (kind) {\n\t\tcase 'belongsTo':\n\t\t\treturn 'belongsTo';\n\t\tcase 'hasMany':\n\t\t\treturn 'hasMany';\n\t\tcase 'manyToMany':\n\t\t\treturn 'belongsToMany';\n\t}\n}\n\n/**\n * Build a TableIR from generated table definition.\n */\nfunction buildTableIRFromDefinition(\n\ttableName: string,\n\tgenTable: GeneratedTable,\n\tfkAutoIndex: boolean,\n): TableIR {\n\tconst columns: ColumnIR[] = [];\n\tconst foreignKeys: ForeignKeyIR[] = [];\n\tconst indexes: IndexIR[] = [];\n\tconst primaryKeys: string[] = [];\n\t// Track columns that already have explicit indexes\n\tconst indexedColumns = new Set<string>();\n\n\tfor (const [colName, colDef] of Object.entries(genTable)) {\n\t\t// Column (with unique support)\n\t\tconst col: Mutable<ColumnIR> = {\n\t\t\tname: colName,\n\t\t\ttype: generatedTypeToColumnType(colDef.type),\n\t\t\tnullable: colDef.nullable ?? false,\n\t\t\tdefault: colDef.default,\n\t\t};\n\t\tif (colDef.unique !== undefined) {\n\t\t\tcol.unique = colDef.unique;\n\t\t}\n\t\tif (colDef.autoIncrement !== undefined) {\n\t\t\tcol.autoIncrement = colDef.autoIncrement;\n\t\t}\n\t\tcolumns.push(col);\n\n\t\t// Primary key\n\t\tif (colDef.primaryKey) {\n\t\t\tprimaryKeys.push(colName);\n\t\t}\n\n\t\t// Foreign key (with onDelete support)\n\t\tif (colDef.references) {\n\t\t\tconst fk: Mutable<ForeignKeyIR> = {\n\t\t\t\tcolumns: [colName],\n\t\t\t\treferences: {\n\t\t\t\t\ttable: colDef.references.table,\n\t\t\t\t\tcolumns: [colDef.references.column ?? 'id'],\n\t\t\t\t},\n\t\t\t};\n\t\t\tif (colDef.references.onDelete) {\n\t\t\t\tfk.onDelete = colDef.references.onDelete;\n\t\t\t}\n\t\t\tforeignKeys.push(fk);\n\t\t}\n\n\t\t// Column-level index (explicit)\n\t\tif (colDef.index) {\n\t\t\tconst indexName =\n\t\t\t\ttypeof colDef.index === 'string'\n\t\t\t\t\t? colDef.index\n\t\t\t\t\t: `idx_${tableName}_${colName}`;\n\t\t\tindexes.push({\n\t\t\t\tname: indexName,\n\t\t\t\tcolumns: [colName],\n\t\t\t\tunique: false,\n\t\t\t});\n\t\t\tindexedColumns.add(colName);\n\t\t}\n\n\t\t// Auto-index for FK columns if fkAutoIndex is enabled and no explicit index\n\t\tif (fkAutoIndex && colDef.references && !colDef.index) {\n\t\t\tindexes.push({\n\t\t\t\tname: `idx_${tableName}_${colName}`,\n\t\t\t\tcolumns: [colName],\n\t\t\t\tunique: false,\n\t\t\t});\n\t\t\tindexedColumns.add(colName);\n\t\t}\n\t}\n\n\t// Extract pseudo-columns from self-referential FKs\n\tconst pseudoColumns: PseudoColumnMetadata[] = [];\n\tfor (const fk of foreignKeys) {\n\t\t// Check if FK points to same table (self-referential)\n\t\tconst fkColumn = fk.columns[0];\n\t\tconst targetColumn = fk.references.columns[0];\n\t\tif (\n\t\t\tfk.references.table === tableName &&\n\t\t\tfkColumn !== undefined &&\n\t\t\ttargetColumn !== undefined\n\t\t) {\n\t\t\t// Get column definition for role extraction\n\t\t\tconst colDef = genTable[fkColumn];\n\t\t\t// Infer role names from column name or explicit references\n\t\t\tconst inferredName = fkColumn.endsWith('Id')\n\t\t\t\t? fkColumn.slice(0, -2)\n\t\t\t\t: 'parent';\n\t\t\tconst parentRole = colDef?.references?.parentRole ?? inferredName;\n\t\t\tconst childRole =\n\t\t\t\tcolDef?.references?.childRole ??\n\t\t\t\t(parentRole === 'parent' ? 'children' : `${parentRole}s`);\n\n\t\t\tpseudoColumns.push(\n\t\t\t\tcreatePseudoColumnMetadata(\n\t\t\t\t\ttableName,\n\t\t\t\t\tfkColumn,\n\t\t\t\t\ttargetColumn,\n\t\t\t\t\tparentRole,\n\t\t\t\t\tchildRole,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Determine PK: explicit > composite FK > 'id' column > omit\n\tlet primaryKey: string | readonly string[] | undefined;\n\tif (primaryKeys.length > 0) {\n\t\tprimaryKey =\n\t\t\tprimaryKeys.length === 1 ? (primaryKeys[0] as string) : primaryKeys;\n\t} else {\n\t\t// No explicit PK — infer from FK columns or 'id'\n\t\tconst fkColumns = foreignKeys.flatMap((fk) => fk.columns);\n\t\tif (fkColumns.length > 0) {\n\t\t\tprimaryKey = fkColumns.length === 1 ? fkColumns[0] : fkColumns;\n\t\t} else {\n\t\t\tconst hasId = columns.some((c) => c.name === 'id');\n\t\t\tprimaryKey = hasId ? 'id' : undefined;\n\t\t}\n\t}\n\n\t// Freeze columns array for runtime immutability\n\tconst frozenColumns = Object.freeze(columns);\n\n\t// Freeze and return the table object\n\treturn Object.freeze({\n\t\tname: tableName,\n\t\tcolumns: frozenColumns,\n\t\t...(primaryKey !== undefined ? { primaryKey } : {}),\n\t\tforeignKeys: Object.freeze(foreignKeys),\n\t\tindexes: Object.freeze(indexes),\n\t\t...(pseudoColumns.length > 0 && {\n\t\t\tpseudoColumns: Object.freeze(pseudoColumns),\n\t\t}),\n\t});\n}\n\n/**\n * Build a RelationIR from generated relation definition.\n */\nfunction buildRelationIR(\n\tqualifiedName: string,\n\tgenRelation: GeneratedRelation,\n\thints: Record<string, GeneratedHint>,\n): RelationIR {\n\t// Extract source table and relation name from qualified name (e.g., \"posts.author\")\n\tconst dotIndex = qualifiedName.indexOf('.');\n\tconst sourceTable =\n\t\tdotIndex > 0 ? qualifiedName.slice(0, dotIndex) : qualifiedName;\n\tconst relationName =\n\t\tdotIndex > 0 ? qualifiedName.slice(dotIndex + 1) : qualifiedName;\n\n\t// Get hints for this relation\n\tconst hint = hints[qualifiedName];\n\t// Check cardinality from: hint > relation definition > inferred from kind\n\tconst relCardinality =\n\t\tgenRelation.kind === 'hasMany'\n\t\t\t? (genRelation as GeneratedHasMany).cardinality\n\t\t\t: undefined;\n\tconst cardinality: Cardinality =\n\t\thint?.cardinality === 'one'\n\t\t\t? 'one'\n\t\t\t: relCardinality === 'one'\n\t\t\t\t? 'one'\n\t\t\t\t: genRelation.kind === 'belongsTo'\n\t\t\t\t\t? 'one'\n\t\t\t\t\t: 'many';\n\n\t// Determine optionality from nullable FK (for belongsTo) or default to 'optional' for hasMany\n\tconst optionality: Optionality =\n\t\tgenRelation.kind === 'belongsTo' ? 'optional' : 'optional';\n\n\t// Determine relation type - hasMany with cardinality 'one' becomes 'hasOne'\n\tlet relationType = mapRelationType(genRelation.kind);\n\tif (genRelation.kind === 'hasMany' && cardinality === 'one') {\n\t\trelationType = 'hasOne';\n\t}\n\n\t// Build base relation\n\tconst baseRelation = {\n\t\tname: relationName,\n\t\tsource: sourceTable,\n\t\ttarget: genRelation.target,\n\t\ttype: relationType,\n\t\tcardinality,\n\t\toptionality,\n\t\tincludeStrategy: (genRelation.includeStrategy ?? 'auto') as IncludeStrategy,\n\t\tfilterStrategy: (hint?.defaultStrategy ?? 'auto') as FilterStrategy,\n\t\tjoinDefault: 'auto' as JoinDefault,\n\t};\n\n\t// Add relation-specific fields (including optional key overrides from generated relation).\n\t// sourceKey (hasMany): column on source table that the FK on target references (overrides PK).\n\t// targetKey (belongsTo): column on target table that the FK points to (overrides PK).\n\tswitch (genRelation.kind) {\n\t\tcase 'belongsTo':\n\t\t\treturn {\n\t\t\t\t...baseRelation,\n\t\t\t\tforeignKey: genRelation.foreignKey,\n\t\t\t\t...(genRelation.targetKey ? { targetKey: genRelation.targetKey } : {}),\n\t\t\t};\n\t\tcase 'hasMany':\n\t\t\treturn {\n\t\t\t\t...baseRelation,\n\t\t\t\tforeignKey: genRelation.foreignKey,\n\t\t\t\t...(genRelation.sourceKey ? { sourceKey: genRelation.sourceKey } : {}),\n\t\t\t};\n\t\tcase 'manyToMany':\n\t\t\treturn {\n\t\t\t\t...baseRelation,\n\t\t\t\tthrough: genRelation.through,\n\t\t\t\tforeignKey: genRelation.sourceFk,\n\t\t\t\totherKey: genRelation.targetFk,\n\t\t\t};\n\t}\n}\n\n/**\n * Build a ModelIR from a generated schema.\n *\n * This is the main entry point for the schema bridge.\n * It converts the output of `dbsp generate manifest` into a ModelIR\n * that can be used with createOrm.\n *\n * @example\n * ```typescript\n * import { schema } from './generated/dbsp/schema';\n * import { buildModelFromSchema, createOrm } from '@dbsp/core';\n *\n * const model = buildModelFromSchema(schema);\n * const orm = createOrm({ model, adapter });\n * ```\n */\nexport function buildModelFromSchema(schema: GeneratedSchema): ModelIR {\n\tconst tables = new Map<string, TableIR>();\n\tconst relations = new Map<string, RelationIR>();\n\tconst fkAutoIndex = schema.conventions.fkAutoIndex;\n\n\t// Build tables\n\tfor (const [tableName, genTable] of Object.entries(schema.tables)) {\n\t\ttables.set(\n\t\t\ttableName,\n\t\t\tbuildTableIRFromDefinition(tableName, genTable, fkAutoIndex),\n\t\t);\n\t}\n\n\t// Build relations\n\tfor (const [qualifiedName, genRelation] of Object.entries(schema.relations)) {\n\t\trelations.set(\n\t\t\tqualifiedName,\n\t\t\tbuildRelationIR(qualifiedName, genRelation, schema.hints),\n\t\t);\n\t}\n\n\treturn new ModelIRImpl(tables, relations);\n}\n\n/**\n * Build ModelIR directly from ResolvedSchema.\n *\n * Combines the conversion steps: ResolvedSchema → GeneratedSchema → ModelIR.\n * This is the canonical path for creating ModelIR from user-defined schemas.\n *\n * @example\n * ```typescript\n * import { defineSchema, buildModelFromResolvedSchema } from '@dbsp/core';\n *\n * const schema = defineSchema({ users: { ... } }, { relations: { ... } });\n * const model = buildModelFromResolvedSchema(schema);\n * ```\n */\nexport function buildModelFromResolvedSchema(schema: ResolvedSchema): ModelIR {\n\tconst generatedSchema = assertResolvedSchemaToGeneratedSchema(schema);\n\treturn buildModelFromSchema(generatedSchema);\n}\n\n/**\n * Type guard for GeneratedSchema.\n *\n * Note: Both GeneratedSchema and ResolvedSchema have the same structure,\n * so this check will return true for both. Use `isResolvedSchema()` to\n * specifically detect ResolvedSchema (from @dbsp/schema).\n */\nexport function isGeneratedSchema(value: unknown): value is GeneratedSchema {\n\tif (typeof value !== 'object' || value === null) {\n\t\treturn false;\n\t}\n\tconst obj = value as Record<string, unknown>;\n\treturn (\n\t\ttypeof obj.tables === 'object' &&\n\t\tobj.tables !== null &&\n\t\ttypeof obj.relations === 'object' &&\n\t\tobj.relations !== null &&\n\t\ttypeof obj.hints === 'object' &&\n\t\tobj.hints !== null &&\n\t\ttypeof obj.conventions === 'object' &&\n\t\tobj.conventions !== null\n\t);\n}\n\n/**\n * Column types that exist only in ResolvedSchema (from @dbsp/schema).\n * These types are PostgreSQL-specific and not present in GeneratedSchema.\n */\nconst RESOLVED_SCHEMA_ONLY_TYPES = new Set(['time', 'jsonb']);\n\n/**\n * Column types that exist only in GeneratedSchema.\n * These are dialect-agnostic types not present in ResolvedSchema.\n */\nconst GENERATED_SCHEMA_ONLY_TYPES = new Set(['number', 'datetime']);\n\n/**\n * Check if any column in the schema has a type only found in ResolvedSchema.\n */\nfunction hasResolvedSchemaOnlyTypes(\n\ttables: Record<string, Record<string, { type?: string }>>,\n): boolean {\n\tfor (const table of Object.values(tables)) {\n\t\tfor (const column of Object.values(table)) {\n\t\t\tif (column?.type && RESOLVED_SCHEMA_ONLY_TYPES.has(column.type)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Check if any column in the schema has a type only found in GeneratedSchema.\n */\nfunction hasGeneratedSchemaOnlyTypes(\n\ttables: Record<string, Record<string, { type?: string }>>,\n): boolean {\n\tfor (const table of Object.values(tables)) {\n\t\tfor (const column of Object.values(table)) {\n\t\t\tif (column?.type && GENERATED_SCHEMA_ONLY_TYPES.has(column.type)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Type guard for ResolvedSchema (from @dbsp/schema).\n *\n * Detects ResolvedSchema by checking for PostgreSQL-specific column types\n * like 'time' and 'jsonb' that only exist in ResolvedSchema.\n *\n * Note: If the schema has no such types, this may return false even for\n * a valid ResolvedSchema. In that case, the schema can be used directly\n * as a GeneratedSchema since both have the same structure.\n */\nexport function isResolvedSchema(value: unknown): boolean {\n\tif (!isGeneratedSchema(value)) {\n\t\treturn false;\n\t}\n\t// If it has ResolvedSchema-only types, it's definitely a ResolvedSchema\n\tif (\n\t\thasResolvedSchemaOnlyTypes(\n\t\t\tvalue.tables as Record<string, Record<string, { type?: string }>>,\n\t\t)\n\t) {\n\t\treturn true;\n\t}\n\t// If it has GeneratedSchema-only types, it's definitely NOT a ResolvedSchema\n\tif (\n\t\thasGeneratedSchemaOnlyTypes(\n\t\t\tvalue.tables as Record<string, Record<string, { type?: string }>>,\n\t\t)\n\t) {\n\t\treturn false;\n\t}\n\t// Ambiguous case: no distinguishing types. Assume GeneratedSchema (more common at runtime).\n\treturn false;\n}\n\n/**\n * Normalize a schema input to GeneratedSchema.\n *\n * This function accepts either a GeneratedSchema or a ResolvedSchema\n * and returns a GeneratedSchema. If the input is already a GeneratedSchema,\n * it is returned as-is. If it's a ResolvedSchema, it is converted.\n *\n * This is the recommended way to accept schemas in APIs that need to\n * support both schema formats transparently.\n *\n * @param input - Either a GeneratedSchema or ResolvedSchema\n * @returns GeneratedSchema (possibly converted from ResolvedSchema)\n * @throws Error if the input is not a valid schema\n *\n * @example\n * ```typescript\n * import { normalizeSchema } from '@dbsp/core';\n *\n * // Works with GeneratedSchema (from codegen)\n * const schema1 = normalizeSchema(generatedSchema);\n *\n * // Works with ResolvedSchema (from defineSchema())\n * const schema2 = normalizeSchema(resolvedSchema);\n * ```\n */\nexport function normalizeSchema(input: unknown): GeneratedSchema {\n\t// First check if it has the basic structure\n\tif (!isGeneratedSchema(input)) {\n\t\tthrow new Error(\n\t\t\t'Invalid schema: must have tables, relations, hints, and conventions properties',\n\t\t);\n\t}\n\n\t// Check if it looks like a ResolvedSchema (has PostgreSQL-specific types)\n\tif (isResolvedSchema(input)) {\n\t\t// Convert using the existing converter\n\t\tconst result = resolvedSchemaToGeneratedSchema(input);\n\t\tif (!result.success) {\n\t\t\tconst messages = result.errors.map((e) => e.message).join(', ');\n\t\t\tthrow new Error(`Schema conversion failed: ${messages}`);\n\t\t}\n\t\treturn result.schema;\n\t}\n\n\t// Already a GeneratedSchema (or ambiguous but structurally valid)\n\treturn input;\n}\n\n// ============================================================================\n// Valibot Validation Schemas (CORE-005)\n// ============================================================================\n\n/**\n * Schema column type from @dbsp/schema\n */\nconst SchemaColumnTypeSchema = v.picklist([\n\t'uuid',\n\t'string',\n\t'text',\n\t'integer',\n\t'bigint',\n\t'decimal',\n\t'boolean',\n\t'timestamp',\n\t'date',\n\t'time',\n\t'json',\n\t'jsonb',\n\t'daterange',\n\t'tstzrange',\n\t'int4range',\n\t'tsrange',\n\t'int8range',\n\t'numrange',\n]);\n\n/**\n * Foreign key reference schema\n */\n\n/**\n * Prototype-pollution-safe string key validator.\n *\n * Rejects keys that would mutate the Object prototype chain when used as\n * record keys. Used in all top-level record validators (tables, relations,\n * hints) to prevent `{ \"__proto__\": {...} }` from poisoning downstream objects.\n *\n * The three dangerous keys are: `__proto__`, `constructor`, `prototype`.\n */\nconst PROTO_POLLUTION_KEYS = ['__proto__', 'constructor', 'prototype'] as const;\n\n/**\n * Wraps a `v.record(v.string(), valueSchema)` with a pre-check that rejects\n * prototype-pollution keys BEFORE Valibot iterates the record entries.\n *\n * Why not `v.record(safePipedStringKey, valueSchema)`?\n * In Valibot v1, the key schema in `v.record` is only used for TS type inference;\n * it does NOT run validation on keys at parse time. The outer `v.unknown()` +\n * `v.check()` pipe runs on the raw input object before Valibot strips built-in\n * prototype properties like `constructor`, ensuring `constructor` and `__proto__`\n * (the latter only visible via JSON.parse) are caught.\n */\nfunction safeRecord<TValue extends v.GenericSchema>(valueSchema: TValue) {\n\treturn v.pipe(\n\t\tv.unknown(),\n\t\tv.check((input) => {\n\t\t\tif (typeof input !== 'object' || input === null) return true;\n\t\t\treturn !Object.keys(input).some((k) =>\n\t\t\t\t(PROTO_POLLUTION_KEYS as readonly string[]).includes(k),\n\t\t\t);\n\t\t}, 'Schema keys must not include prototype-pollution names (__proto__, constructor, prototype)'),\n\t\tv.record(v.string(), valueSchema),\n\t);\n}\n\nconst ForeignKeyReferenceSchema = v.object({\n\ttable: v.string(),\n\tcolumn: v.optional(v.string()),\n\tonDelete: v.optional(\n\t\tv.picklist(['CASCADE', 'SET NULL', 'RESTRICT', 'NO ACTION']),\n\t),\n\tindex: v.optional(v.boolean()),\n\tparentRole: v.optional(v.string()),\n\tchildRole: v.optional(v.string()),\n});\n\n/**\n * Column definition schema (from @dbsp/schema)\n */\nconst ColumnDefinitionSchema = v.object({\n\ttype: SchemaColumnTypeSchema,\n\tprimaryKey: v.optional(v.boolean()),\n\tnullable: v.optional(v.boolean()),\n\tunique: v.optional(v.boolean()),\n\tautoIncrement: v.optional(v.boolean()),\n\tdefault: v.optional(v.union([v.string(), v.number(), v.boolean()])),\n\treferences: v.optional(ForeignKeyReferenceSchema),\n\tindex: v.optional(v.union([v.boolean(), v.string()])),\n});\n\n/**\n * Table definition schema - flat format (column name -> column def).\n */\nconst FlatTableDefinitionSchema = safeRecord(ColumnDefinitionSchema);\n\n/**\n * Table definition with config - supports composite primary keys.\n * Format: { columns: { col1: ColumnDef }, primaryKey: ['col1', 'col2'] }\n */\nconst TableDefWithConfigSchema = v.object({\n\tcolumns: FlatTableDefinitionSchema,\n\tprimaryKey: v.array(v.string()),\n\tindexes: v.optional(\n\t\tv.array(\n\t\t\tv.object({\n\t\t\t\tcolumns: v.array(v.string()),\n\t\t\t\tunique: v.optional(v.boolean()),\n\t\t\t\tname: v.optional(v.string()),\n\t\t\t}),\n\t\t),\n\t),\n});\n\n/**\n * Table definition schema - accepts both flat and with-config formats.\n */\nconst TableDefinitionSchema = v.union([\n\tTableDefWithConfigSchema,\n\tFlatTableDefinitionSchema,\n]);\n\n/**\n * Tables definition schema\n */\nconst TablesDefinitionSchema = safeRecord(TableDefinitionSchema);\n\n/**\n * BelongsTo relation schema\n */\n/**\n * Include strategy schema for relations\n */\nconst IncludeStrategySchema = v.optional(\n\tv.picklist(['join', 'subquery', 'cte', 'lateral', 'json_agg', 'auto']),\n);\n\nconst BelongsToRelationSchema = v.object({\n\tkind: v.literal('belongsTo'),\n\ttarget: v.string(),\n\tforeignKey: v.string(),\n\ttargetKey: v.optional(v.string()),\n\tincludeStrategy: IncludeStrategySchema,\n});\n\n/**\n * HasMany relation schema\n */\nconst HasManyRelationSchema = v.object({\n\tkind: v.literal('hasMany'),\n\ttarget: v.string(),\n\tforeignKey: v.string(),\n\tsourceKey: v.optional(v.string()),\n\tincludeStrategy: IncludeStrategySchema,\n});\n\n/**\n * ManyToMany relation schema\n */\nconst ManyToManyRelationSchema = v.object({\n\tkind: v.literal('manyToMany'),\n\ttarget: v.string(),\n\tthrough: v.string(),\n\tsourceFk: v.string(),\n\ttargetFk: v.string(),\n\tincludeStrategy: IncludeStrategySchema,\n});\n\n/**\n * Relation definition schema (discriminated union)\n */\nconst RelationDefinitionSchema = v.variant('kind', [\n\tBelongsToRelationSchema,\n\tHasManyRelationSchema,\n\tManyToManyRelationSchema,\n]);\n\n/**\n * Relations definition schema\n */\nconst RelationsDefinitionSchema = safeRecord(RelationDefinitionSchema);\n\n/**\n * Hint definition schema\n */\nconst HintDefinitionSchema = v.object({\n\tdefaultStrategy: v.optional(v.picklist(['exists', 'join'])),\n\tcardinality: v.optional(v.picklist(['one', 'many'])),\n});\n\n/**\n * Hints definition schema\n */\nconst HintsDefinitionSchema = safeRecord(HintDefinitionSchema);\n\n/**\n * Conventions definition schema (resolved = all required)\n */\nconst ConventionsDefinitionSchema = v.object({\n\tfkPattern: v.string(),\n\tpluralize: v.boolean(),\n\ttimestamps: v.array(v.string()),\n\tfkAutoIndex: v.boolean(),\n});\n\n/**\n * Index definition schema\n */\nconst IndexDefinitionSchema = v.object({\n\tcolumns: v.array(v.string()),\n\tunique: v.optional(v.boolean()),\n\tname: v.optional(v.string()),\n});\n\n/**\n * Indexes definition schema - mapping table name to array of indexes\n */\nconst IndexesDefinitionSchema = safeRecord(v.array(IndexDefinitionSchema));\n\n/**\n * Complete ResolvedSchema validation schema\n */\nexport const ResolvedSchemaValidation = v.object({\n\ttables: TablesDefinitionSchema,\n\trelations: RelationsDefinitionSchema,\n\thints: HintsDefinitionSchema,\n\tconventions: ConventionsDefinitionSchema,\n\tindexes: v.optional(IndexesDefinitionSchema),\n});\n\n/**\n * Type inferred from ResolvedSchemaValidation\n */\nexport type ValidatedResolvedSchema = v.InferOutput<\n\ttypeof ResolvedSchemaValidation\n>;\n\n// ============================================================================\n// ResolvedSchema → GeneratedSchema Converter (CORE-005)\n// ============================================================================\n\n/**\n * Map schema column type to generated column type.\n * Handles type differences between the two systems.\n */\nfunction mapSchemaColumnType(\n\tschemaType: v.InferOutput<typeof SchemaColumnTypeSchema>,\n): GeneratedColumnType {\n\tswitch (schemaType) {\n\t\tcase 'uuid':\n\t\t\treturn 'uuid';\n\t\tcase 'string':\n\t\t\treturn 'string';\n\t\tcase 'text':\n\t\t\treturn 'text';\n\t\tcase 'integer':\n\t\t\treturn 'integer';\n\t\tcase 'bigint':\n\t\t\treturn 'bigint';\n\t\tcase 'decimal':\n\t\t\treturn 'decimal';\n\t\tcase 'boolean':\n\t\t\treturn 'boolean';\n\t\tcase 'timestamp':\n\t\t\treturn 'timestamp';\n\t\tcase 'date':\n\t\t\treturn 'date';\n\t\tcase 'time':\n\t\t\treturn 'time';\n\t\tcase 'json':\n\t\t\treturn 'json';\n\t\tcase 'jsonb':\n\t\t\treturn 'jsonb';\n\t\tcase 'daterange':\n\t\t\treturn 'daterange';\n\t\tcase 'tstzrange':\n\t\t\treturn 'tstzrange';\n\t\tcase 'int4range':\n\t\t\treturn 'int4range';\n\t\tcase 'tsrange':\n\t\t\treturn 'tsrange';\n\t\tcase 'int8range':\n\t\t\treturn 'int8range';\n\t\tcase 'numrange':\n\t\t\treturn 'numrange';\n\t}\n}\n\n/**\n * Convert a validated column definition to GeneratedColumn.\n */\nfunction convertColumn(\n\tcol: v.InferOutput<typeof ColumnDefinitionSchema>,\n): GeneratedColumn {\n\tconst result: Mutable<GeneratedColumn> = {\n\t\ttype: mapSchemaColumnType(col.type),\n\t};\n\tif (col.primaryKey !== undefined) {\n\t\tresult.primaryKey = col.primaryKey;\n\t}\n\tif (col.nullable !== undefined) {\n\t\tresult.nullable = col.nullable;\n\t}\n\tif (col.unique !== undefined) {\n\t\tresult.unique = col.unique;\n\t}\n\tif (col.autoIncrement !== undefined) {\n\t\tresult.autoIncrement = col.autoIncrement;\n\t}\n\tif (col.default !== undefined) {\n\t\tresult.default = col.default as string;\n\t}\n\tif (col.references) {\n\t\tresult.references = {\n\t\t\ttable: col.references.table,\n\t\t\t...(col.references.column !== undefined\n\t\t\t\t? { column: col.references.column }\n\t\t\t\t: {}),\n\t\t\t...(col.references.onDelete ? { onDelete: col.references.onDelete } : {}),\n\t\t\t...(col.references.index !== undefined\n\t\t\t\t? { index: col.references.index }\n\t\t\t\t: {}),\n\t\t\t...(col.references.parentRole\n\t\t\t\t? { parentRole: col.references.parentRole }\n\t\t\t\t: {}),\n\t\t\t...(col.references.childRole\n\t\t\t\t? { childRole: col.references.childRole }\n\t\t\t\t: {}),\n\t\t};\n\t}\n\treturn result as GeneratedColumn;\n}\n\n/**\n * Convert a validated relation definition to GeneratedRelation.\n */\nfunction convertRelation(\n\trel: v.InferOutput<typeof RelationDefinitionSchema>,\n): GeneratedRelation {\n\tswitch (rel.kind) {\n\t\tcase 'belongsTo': {\n\t\t\tconst result: Mutable<GeneratedBelongsTo> = {\n\t\t\t\tkind: 'belongsTo',\n\t\t\t\ttarget: rel.target,\n\t\t\t\tforeignKey: rel.foreignKey,\n\t\t\t};\n\t\t\tif (rel.targetKey !== undefined) {\n\t\t\t\tresult.targetKey = rel.targetKey;\n\t\t\t}\n\t\t\tif (rel.includeStrategy !== undefined) {\n\t\t\t\tresult.includeStrategy = rel.includeStrategy;\n\t\t\t}\n\t\t\treturn result as GeneratedBelongsTo;\n\t\t}\n\t\tcase 'hasMany': {\n\t\t\tconst result: Mutable<GeneratedHasMany> = {\n\t\t\t\tkind: 'hasMany',\n\t\t\t\ttarget: rel.target,\n\t\t\t\tforeignKey: rel.foreignKey,\n\t\t\t};\n\t\t\tif (rel.sourceKey !== undefined) {\n\t\t\t\tresult.sourceKey = rel.sourceKey;\n\t\t\t}\n\t\t\tif (rel.includeStrategy !== undefined) {\n\t\t\t\tresult.includeStrategy = rel.includeStrategy;\n\t\t\t}\n\t\t\treturn result as GeneratedHasMany;\n\t\t}\n\t\tcase 'manyToMany': {\n\t\t\tconst result: Mutable<GeneratedManyToMany> = {\n\t\t\t\tkind: 'manyToMany',\n\t\t\t\ttarget: rel.target,\n\t\t\t\tthrough: rel.through,\n\t\t\t\tsourceFk: rel.sourceFk,\n\t\t\t\ttargetFk: rel.targetFk,\n\t\t\t};\n\t\t\tif (rel.includeStrategy !== undefined) {\n\t\t\t\tresult.includeStrategy = rel.includeStrategy;\n\t\t\t}\n\t\t\treturn result as GeneratedManyToMany;\n\t\t}\n\t}\n}\n\n/**\n * Convert a validated hint definition to GeneratedHint.\n */\nfunction convertHint(\n\thint: v.InferOutput<typeof HintDefinitionSchema>,\n): GeneratedHint {\n\tconst result: Mutable<GeneratedHint> = {};\n\tif (hint.defaultStrategy !== undefined) {\n\t\tresult.defaultStrategy = hint.defaultStrategy;\n\t}\n\tif (hint.cardinality !== undefined) {\n\t\tresult.cardinality = hint.cardinality;\n\t}\n\treturn result as GeneratedHint;\n}\n\n/**\n * Result of schema conversion.\n */\nexport type SchemaConversionResult =\n\t| { success: true; schema: GeneratedSchema }\n\t| { success: false; errors: v.BaseIssue<unknown>[] };\n\n/**\n * Convert a ResolvedSchema (from @dbsp/schema) to GeneratedSchema.\n *\n * This function validates the input using Valibot and then converts the\n * schema structure to the format expected by createOrm().\n *\n * @param input - The ResolvedSchema to convert (output of defineSchema())\n * @returns Conversion result with either the converted schema or validation errors\n *\n * @example\n * ```typescript\n * import { defineSchema } from '@dbsp/schema';\n * import { resolvedSchemaToGeneratedSchema, createOrm } from '@dbsp/core';\n *\n * const resolved = defineSchema({ tables: { users: { id: { type: 'uuid' } } } });\n * const result = resolvedSchemaToGeneratedSchema(resolved);\n *\n * if (result.success) {\n * const orm = createOrm({ schema: result.schema, adapter });\n * } else {\n * console.error('Schema validation failed:', result.errors);\n * }\n * ```\n */\nexport function resolvedSchemaToGeneratedSchema(\n\tinput: unknown,\n): SchemaConversionResult {\n\t// Validate input\n\tconst parseResult = v.safeParse(ResolvedSchemaValidation, input);\n\n\tif (!parseResult.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terrors: parseResult.issues,\n\t\t};\n\t}\n\n\tconst validated = parseResult.output;\n\n\t// Convert tables (handles both flat and with-config formats)\n\t// Use Object.create(null) for accumulators to prevent prototype-chain mutation\n\t// even if a key somehow bypasses the safeStringKey Valibot check.\n\tconst tables = Object.create(null) as Record<string, GeneratedTable>;\n\tfor (const [tableName, tableDef] of Object.entries(validated.tables)) {\n\t\tconst convertedTable = Object.create(null) as Record<\n\t\t\tstring,\n\t\t\tGeneratedColumn\n\t\t>;\n\n\t\t// Discriminate with-config vs flat format by checking for a primaryKey array.\n\t\t// Using 'columns' as the discriminant is unsafe: a flat table could legitimately\n\t\t// have a column named 'columns', causing it to be misread as with-config.\n\t\t// TableDefWithConfigSchema requires `primaryKey: array(string())` which flat\n\t\t// shorthand columns never have, so this is a reliable discriminant.\n\t\tconst tableObj = tableDef as Record<string, unknown>;\n\t\tconst isWithConfig = Array.isArray(tableObj.primaryKey);\n\n\t\tconst columns = isWithConfig\n\t\t\t? (tableObj.columns as Record<string, unknown>)\n\t\t\t: tableObj;\n\n\t\tfor (const [colName, colDef] of Object.entries(columns)) {\n\t\t\tconvertedTable[colName] = convertColumn(\n\t\t\t\tcolDef as v.InferOutput<typeof ColumnDefinitionSchema>,\n\t\t\t);\n\t\t}\n\t\ttables[tableName] = convertedTable;\n\t}\n\n\t// Convert relations\n\tconst relations = Object.create(null) as Record<string, GeneratedRelation>;\n\tfor (const [relName, relDef] of Object.entries(validated.relations)) {\n\t\trelations[relName] = convertRelation(relDef);\n\t}\n\n\t// Convert hints\n\tconst hints = Object.create(null) as Record<string, GeneratedHint>;\n\tfor (const [hintName, hintDef] of Object.entries(validated.hints)) {\n\t\thints[hintName] = convertHint(hintDef);\n\t}\n\n\t// Convert conventions\n\tconst conventions: GeneratedConventions = {\n\t\tfkPattern: validated.conventions.fkPattern,\n\t\tpluralize: validated.conventions.pluralize,\n\t\ttimestamps: validated.conventions.timestamps,\n\t\tfkAutoIndex: validated.conventions.fkAutoIndex,\n\t};\n\n\treturn {\n\t\tsuccess: true,\n\t\tschema: {\n\t\t\ttables,\n\t\t\trelations,\n\t\t\thints,\n\t\t\tconventions,\n\t\t},\n\t};\n}\n\n/**\n * Assert and convert a ResolvedSchema to GeneratedSchema.\n *\n * Throws an error if validation fails. Use this when you're confident\n * the input is valid and want cleaner code without result checking.\n *\n * @param input - The ResolvedSchema to convert\n * @returns The converted GeneratedSchema\n * @throws Error if validation fails\n */\nexport function assertResolvedSchemaToGeneratedSchema(\n\tinput: unknown,\n): GeneratedSchema {\n\tconst result = resolvedSchemaToGeneratedSchema(input);\n\tif (!result.success) {\n\t\tconst messages = result.errors\n\t\t\t.map((e) => {\n\t\t\t\tconst path = e.path?.map((p) => p.key).join('.') || 'root';\n\t\t\t\treturn `[${path}] ${e.message} (expected: ${e.expected}, received: ${e.received})`;\n\t\t\t})\n\t\t\t.join('\\n');\n\t\tthrow new Error(`Schema validation failed:\\n${messages}`);\n\t}\n\treturn result.schema;\n}\n","/**\n * Dialect Capabilities Registry\n *\n * CORE-004: Centralized module for SQL dialect capabilities.\n * Avoids duplication across adapters by providing a single source of truth.\n *\n * Type definitions live in @dbsp/types. This module re-exports them\n * and provides runtime constants and functions.\n */\n\nimport type {\n\tColumnType,\n\tDDLFeature,\n\tDDLFeatureVersionRange,\n} from '@dbsp/types';\n\n// Re-export all dialect types from @dbsp/types for backward compatibility\nexport type {\n\tCommonColumnType,\n\tDDLFeatureVersionRange,\n\tDialectCapabilities,\n\tDialectName,\n\tDuckDBColumnType,\n\tIsTypeSupported,\n\tMSSQLColumnType,\n\tMySQLColumnType,\n\tPostgresColumnType,\n\tPostgresOnlyColumnType,\n\tSQLiteColumnType,\n\tSupportedColumnTypes,\n} from '@dbsp/types';\n\nimport type { DialectCapabilities } from '@dbsp/types';\n\n/**\n * PostgreSQL dialect capabilities.\n * The most feature-rich dialect, serves as the reference implementation.\n */\nexport const POSTGRESQL_CAPABILITIES: DialectCapabilities = {\n\tname: 'postgresql',\n\n\t// Features\n\tsupportsReturning: true,\n\tsupportsRecursiveCTE: true,\n\tsupportsWindowFunctions: true,\n\tsupportsArrayType: true,\n\tsupportsRangeTypes: true, // PostgreSQL has native range types (daterange, int4range, etc.)\n\tsupportsJsonType: true,\n\tsupportsJsonOperators: true, // PG: ->, ->>, @>, <@, ?, #>, #>>\n\tsupportsSchemas: true,\n\n\t// Include Strategy Capabilities (CORE-006)\n\tsupportsLateralJoin: true,\n\tsupportsJsonAgg: true,\n\n\t// DDL Feature Support (CAPS-001)\n\tsupportsDDLEnumTypes: true,\n\tsupportsDDLSequences: true,\n\tsupportsDDLExtensions: true,\n\tsupportsDDLPartitioning: true,\n\tsupportsDDLCheckConstraints: true,\n\tsupportsDDLOnUpdateFK: true,\n\tsupportsDDLDeferredFK: true,\n\tsupportsDDLIdentityColumns: true,\n\tsupportsDDLCollation: true,\n\tsupportsDDLComments: true,\n\tsupportsDDLIndexMethods: true,\n\tsupportsDDLIndexOpclass: true,\n\tsupportsDDLIndexInclude: true,\n\tsupportsDDLPartialIndexes: true,\n\tsupportsDDLExpressionIndexes: true,\n\tsupportsDDLRowLevelSecurity: true,\n\n\t// Syntax\n\trecursivePathStyle: 'array',\n\tstringConcatStyle: 'operator',\n\tidentifierQuote: '\"',\n\tparameterStyle: 'dollar',\n\tlimitStyle: 'limit-offset',\n\tbooleanStyle: 'native',\n};\n\n/**\n * MySQL dialect capabilities.\n */\nexport const MYSQL_CAPABILITIES: DialectCapabilities = {\n\tname: 'mysql',\n\n\t// Features\n\tsupportsReturning: false, // MySQL 8.0.21+ has limited support\n\tsupportsRecursiveCTE: true, // MySQL 8.0+\n\tsupportsWindowFunctions: true, // MySQL 8.0+\n\tsupportsArrayType: false,\n\tsupportsRangeTypes: false, // MySQL has no native range types\n\tsupportsJsonType: true,\n\tsupportsJsonOperators: false, // MySQL uses JSON_EXTRACT() functions, not operators\n\tsupportsSchemas: true, // MySQL uses database as schema\n\n\t// Include Strategy Capabilities (CORE-006)\n\tsupportsLateralJoin: false, // MySQL 8.0.14+ has LATERAL but limited\n\tsupportsJsonAgg: true, // JSON_ARRAYAGG() in MySQL 8.0+\n\n\t// Syntax\n\trecursivePathStyle: 'string',\n\tstringConcatStyle: 'function',\n\tidentifierQuote: '`',\n\tparameterStyle: 'question',\n\tlimitStyle: 'limit-offset',\n\tbooleanStyle: 'numeric',\n};\n\n/**\n * SQLite dialect capabilities.\n */\nexport const SQLITE_CAPABILITIES: DialectCapabilities = {\n\tname: 'sqlite',\n\n\t// Features\n\tsupportsReturning: true, // SQLite 3.35+\n\tsupportsRecursiveCTE: true,\n\tsupportsWindowFunctions: true, // SQLite 3.25+\n\tsupportsArrayType: false,\n\tsupportsRangeTypes: false, // SQLite has no native range types\n\tsupportsJsonType: true, // SQLite 3.38+ (JSON1 extension)\n\tsupportsJsonOperators: false, // SQLite uses json_extract() functions\n\tsupportsSchemas: false, // SQLite uses ATTACH for multiple databases\n\n\t// Include Strategy Capabilities (CORE-006)\n\tsupportsLateralJoin: false, // Not supported\n\tsupportsJsonAgg: false, // json_group_array exists but is limited\n\n\t// Syntax\n\trecursivePathStyle: 'string',\n\tstringConcatStyle: 'operator',\n\tidentifierQuote: '\"',\n\tparameterStyle: 'question',\n\tlimitStyle: 'limit-offset',\n\tbooleanStyle: 'numeric',\n};\n\n/**\n * DuckDB dialect capabilities.\n * Analytical database with PostgreSQL-compatible syntax.\n */\nexport const DUCKDB_CAPABILITIES: DialectCapabilities = {\n\tname: 'duckdb',\n\n\t// Features\n\tsupportsReturning: true,\n\tsupportsRecursiveCTE: true,\n\tsupportsWindowFunctions: true,\n\tsupportsArrayType: true, // DuckDB has LIST type\n\tsupportsRangeTypes: false, // DuckDB has no native range types like PostgreSQL\n\tsupportsJsonType: true,\n\tsupportsJsonOperators: false, // DuckDB uses json_extract() style\n\tsupportsSchemas: true,\n\n\t// Include Strategy Capabilities (CORE-006)\n\tsupportsLateralJoin: true, // DuckDB supports LATERAL\n\tsupportsJsonAgg: true, // list_agg / json_group_array\n\n\t// Syntax\n\trecursivePathStyle: 'array', // DuckDB uses LIST which is similar\n\tstringConcatStyle: 'operator',\n\tidentifierQuote: '\"',\n\tparameterStyle: 'dollar',\n\tlimitStyle: 'limit-offset',\n\tbooleanStyle: 'native',\n};\n\n/**\n * MSSQL dialect capabilities.\n */\nexport const MSSQL_CAPABILITIES: DialectCapabilities = {\n\tname: 'mssql',\n\n\t// Features\n\tsupportsReturning: true, // OUTPUT clause\n\tsupportsRecursiveCTE: true,\n\tsupportsWindowFunctions: true,\n\tsupportsArrayType: false,\n\tsupportsRangeTypes: false, // MSSQL has no native range types\n\tsupportsJsonType: true, // SQL Server 2016+\n\tsupportsJsonOperators: false, // MSSQL uses JSON_VALUE/JSON_QUERY functions\n\tsupportsSchemas: true,\n\n\t// Include Strategy Capabilities (CORE-006)\n\tsupportsLateralJoin: true, // CROSS APPLY / OUTER APPLY\n\tsupportsJsonAgg: false, // FOR JSON exists but different semantics\n\n\t// Syntax\n\trecursivePathStyle: 'string',\n\tstringConcatStyle: 'function', // CONCAT() or +\n\tidentifierQuote: '[',\n\tparameterStyle: 'named', // @param\n\tlimitStyle: 'top', // TOP or OFFSET FETCH\n\tbooleanStyle: 'numeric',\n};\n\n/**\n * Compare two version strings numerically (e.g., '8.0.16' vs '8.0.15').\n * Returns: -1 if a < b, 0 if equal, 1 if a > b.\n * Supports any number of segments (3.8, 8.0.16, 15.0.1.2).\n */\nfunction compareVersions(a: string, b: string): number {\n\tconst partsA = a.split('.').map(Number);\n\tconst partsB = b.split('.').map(Number);\n\tconst len = Math.max(partsA.length, partsB.length);\n\tfor (let i = 0; i < len; i++) {\n\t\tconst segA = partsA[i] ?? 0;\n\t\tconst segB = partsB[i] ?? 0;\n\t\tif (segA < segB) return -1;\n\t\tif (segA > segB) return 1;\n\t}\n\treturn 0;\n}\n\n/** Maps DDLFeature name → DialectCapabilities flag name */\nconst FEATURE_TO_FLAG: Record<DDLFeature, string> = {\n\tenum: 'supportsDDLEnumTypes',\n\tsequence: 'supportsDDLSequences',\n\textension: 'supportsDDLExtensions',\n\tpartition: 'supportsDDLPartitioning',\n\tcheckConstraint: 'supportsDDLCheckConstraints',\n\tonUpdateFK: 'supportsDDLOnUpdateFK',\n\tdeferredFK: 'supportsDDLDeferredFK',\n\tidentity: 'supportsDDLIdentityColumns',\n\tcollation: 'supportsDDLCollation',\n\tcomment: 'supportsDDLComments',\n\tindexMethod: 'supportsDDLIndexMethods',\n\tindexOpclass: 'supportsDDLIndexOpclass',\n\tindexInclude: 'supportsDDLIndexInclude',\n\tpartialIndex: 'supportsDDLPartialIndexes',\n\texpressionIndex: 'supportsDDLExpressionIndexes',\n\trowLevelSecurity: 'supportsDDLRowLevelSecurity',\n};\n\n/**\n * Factory helper for adapter authors to create DialectCapabilities.\n * All DDL flags default to false (unsupported) unless overridden.\n * Required fields (name, syntax variants) must be provided.\n *\n * @param overrides - Required syntax fields plus any capability overrides.\n * @param options - Optional version-aware resolution. When `version` and\n * `versionRequirements` are both provided, features outside their version\n * range are set to `undefined` (unsupported) in the returned capabilities.\n */\nexport function createDialectCapabilities(\n\toverrides: Partial<DialectCapabilities> &\n\t\tPick<\n\t\t\tDialectCapabilities,\n\t\t\t| 'name'\n\t\t\t| 'identifierQuote'\n\t\t\t| 'parameterStyle'\n\t\t\t| 'limitStyle'\n\t\t\t| 'booleanStyle'\n\t\t\t| 'recursivePathStyle'\n\t\t\t| 'stringConcatStyle'\n\t\t>,\n\toptions?: {\n\t\t/** Current database version (e.g., '8.0.16', '3.35.0') */\n\t\tversion?: string;\n\t\t/** Per-feature version requirements. Features outside the range are set to undefined. */\n\t\tversionRequirements?: Partial<Record<DDLFeature, DDLFeatureVersionRange>>;\n\t},\n): DialectCapabilities {\n\tconst result: Record<string, unknown> = {\n\t\t// Feature defaults (all false = unsupported)\n\t\tsupportsReturning: false,\n\t\tsupportsRecursiveCTE: false,\n\t\tsupportsWindowFunctions: false,\n\t\tsupportsArrayType: false,\n\t\tsupportsRangeTypes: false,\n\t\tsupportsJsonType: false,\n\t\tsupportsJsonOperators: false,\n\t\tsupportsSchemas: false,\n\t\tsupportsLateralJoin: false,\n\t\tsupportsJsonAgg: false,\n\t\t// DDL flags all default to undefined (unsupported per INV-02)\n\t\t...overrides,\n\t};\n\n\tif (options?.version && options?.versionRequirements) {\n\t\tconst ver = options.version;\n\t\tconst reqs = options.versionRequirements;\n\t\tfor (const [feature, range] of Object.entries(reqs) as [\n\t\t\tDDLFeature,\n\t\t\tDDLFeatureVersionRange,\n\t\t][]) {\n\t\t\tconst flagName = FEATURE_TO_FLAG[feature];\n\t\t\tif (!flagName) continue;\n\t\t\tconst meetsMin = !range.min || compareVersions(ver, range.min) >= 0;\n\t\t\tconst meetsMax = !range.max || compareVersions(ver, range.max) <= 0;\n\t\t\tif (!meetsMin || !meetsMax) {\n\t\t\t\tdelete result[flagName];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result as unknown as DialectCapabilities;\n}\n\n/**\n * Registry of all known dialect capabilities.\n * Use `registerDialect()` to add custom dialects.\n */\nconst dialectRegistry: Map<string, DialectCapabilities> = new Map([\n\t['postgresql', POSTGRESQL_CAPABILITIES],\n\t['postgres', POSTGRESQL_CAPABILITIES], // Alias\n\t['pg', POSTGRESQL_CAPABILITIES], // Alias\n\t['mysql', MYSQL_CAPABILITIES],\n\t['sqlite', SQLITE_CAPABILITIES],\n\t['duckdb', DUCKDB_CAPABILITIES],\n\t['mssql', MSSQL_CAPABILITIES],\n\t['sqlserver', MSSQL_CAPABILITIES], // Alias\n]);\n\n/**\n * Error thrown when a dialect is not found in the registry.\n */\nexport class UnknownDialectError extends Error {\n\tconstructor(\n\t\tpublic readonly dialectName: string,\n\t\tpublic readonly availableDialects: string[],\n\t) {\n\t\tconst available = availableDialects.join(', ');\n\t\tsuper(`Unknown dialect '${dialectName}'. Available dialects: ${available}`);\n\t\tthis.name = 'UnknownDialectError';\n\t}\n}\n\n/**\n * Get capabilities for a known dialect.\n *\n * @param dialectName - The dialect identifier (e.g., 'postgresql', 'mysql')\n * @returns The dialect capabilities\n * @throws UnknownDialectError if the dialect is not registered\n *\n * @example\n * ```typescript\n * const caps = getDialectCapabilities('postgresql');\n * if (caps.supportsReturning) {\n * // Add RETURNING clause\n * }\n * ```\n */\nexport function getDialectCapabilities(\n\tdialectName: string,\n): DialectCapabilities {\n\tconst normalized = dialectName.toLowerCase();\n\tconst capabilities = dialectRegistry.get(normalized);\n\n\tif (!capabilities) {\n\t\tconst available = Array.from(dialectRegistry.keys()).filter(\n\t\t\t(key) => dialectRegistry.get(key)?.name === key, // Only show primary names, not aliases\n\t\t);\n\t\tthrow new UnknownDialectError(dialectName, available);\n\t}\n\n\treturn capabilities;\n}\n\n/**\n * Check if a dialect is registered.\n *\n * @param dialectName - The dialect identifier\n * @returns true if the dialect is known\n */\nexport function isKnownDialect(dialectName: string): boolean {\n\treturn dialectRegistry.has(dialectName.toLowerCase());\n}\n\n/**\n * Get all registered dialect names (primary names only, not aliases).\n *\n * @returns Array of dialect names\n */\nexport function getAvailableDialects(): string[] {\n\tconst seen = new Set<string>();\n\tconst result: string[] = [];\n\n\tfor (const [_key, caps] of dialectRegistry) {\n\t\tif (!seen.has(caps.name)) {\n\t\t\tseen.add(caps.name);\n\t\t\tresult.push(caps.name);\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Register a custom dialect or override an existing one.\n *\n * @param dialectName - The dialect identifier\n * @param capabilities - The dialect capabilities\n *\n * @example\n * ```typescript\n * // Register a custom dialect\n * registerDialect('cockroachdb', {\n * ...POSTGRESQL_CAPABILITIES,\n * name: 'cockroachdb',\n * // Override specific capabilities\n * });\n *\n * // Add an alias\n * registerDialect('crdb', getDialectCapabilities('cockroachdb'));\n * ```\n */\nexport function registerDialect(\n\tdialectName: string,\n\tcapabilities: DialectCapabilities,\n): void {\n\tdialectRegistry.set(dialectName.toLowerCase(), capabilities);\n}\n\n/**\n * Create custom capabilities by extending a base dialect.\n *\n * @param base - The base dialect to extend\n * @param overrides - Partial capabilities to override\n * @returns New capabilities object\n *\n * @example\n * ```typescript\n * const cockroachCaps = extendDialect(POSTGRESQL_CAPABILITIES, {\n * name: 'cockroachdb',\n * supportsArrayType: false, // CockroachDB has limited array support\n * });\n * registerDialect('cockroachdb', cockroachCaps);\n * ```\n */\nexport function extendDialect(\n\tbase: DialectCapabilities,\n\toverrides: Partial<DialectCapabilities> & { name: string },\n): DialectCapabilities {\n\treturn { ...base, ...overrides };\n}\n\n// ============================================================================\n// Dialect Type Errors\n// ============================================================================\n\n/**\n * Error thrown when a column type is not supported by the target dialect.\n *\n * @example\n * ```typescript\n * // PostgreSQL range types are not supported in MySQL\n * throw new UnhandledTypeInDialect('daterange', 'mysql', 'Range types are PostgreSQL-specific');\n * ```\n */\nexport class UnhandledTypeInDialect extends Error {\n\tconstructor(\n\t\t/** The column type that is not supported */\n\t\tpublic readonly columnType: ColumnType | string,\n\t\t/** The dialect that doesn't support the type */\n\t\tpublic readonly dialectName: string,\n\t\t/** Optional hint for the user */\n\t\tpublic readonly hint?: string,\n\t) {\n\t\tconst hintSuffix = hint ? ` Hint: ${hint}` : '';\n\t\tsuper(\n\t\t\t`Type '${columnType}' is not supported by dialect '${dialectName}'.${hintSuffix}`,\n\t\t);\n\t\tthis.name = 'UnhandledTypeInDialect';\n\t}\n}\n\n/**\n * Check if a column type is supported by a dialect at runtime.\n * Returns true if supported, throws UnhandledTypeInDialect if not.\n *\n * @param type - The column type to check\n * @param dialectName - The target dialect\n * @param capabilities - The dialect capabilities\n * @throws UnhandledTypeInDialect if the type is not supported\n *\n * @example\n * ```typescript\n * assertTypeSupported('daterange', 'postgresql', pgCaps); // OK\n * assertTypeSupported('daterange', 'mysql', mysqlCaps); // throws!\n * ```\n */\nexport function assertTypeSupported(\n\ttype: ColumnType,\n\tdialectName: string,\n\tcapabilities: DialectCapabilities,\n): void {\n\t// Range types require supportsRangeTypes\n\tconst rangeTypes: ColumnType[] = [\n\t\t'daterange',\n\t\t'tsrange',\n\t\t'tstzrange',\n\t\t'int4range',\n\t\t'int8range',\n\t\t'numrange',\n\t];\n\n\tif (rangeTypes.includes(type) && !capabilities.supportsRangeTypes) {\n\t\tthrow new UnhandledTypeInDialect(\n\t\t\ttype,\n\t\t\tdialectName,\n\t\t\t'Range types are PostgreSQL-specific. Consider using separate start/end columns instead.',\n\t\t);\n\t}\n\n\t// JSONB specifically requires PostgreSQL\n\tif (type === 'jsonb' && dialectName !== 'postgresql') {\n\t\tthrow new UnhandledTypeInDialect(\n\t\t\ttype,\n\t\t\tdialectName,\n\t\t\t\"Use 'json' type instead, which is supported by most dialects.\",\n\t\t);\n\t}\n}\n","/**\n * Adapter-agnostic SQL utilities.\n *\n * Pure string helpers that work with any SQL dialect.\n * Placed in core so every package can use them without\n * pulling in a specific adapter dependency.\n */\n\n/**\n * Normalize SQL for comparison: collapse whitespace, lowercase, trim.\n * Useful for golden-file tests and assertion systems.\n */\nexport function normalizeSQL(sql: string): string {\n\treturn sql\n\t\t.toLowerCase()\n\t\t.replace(/\\s+/g, ' ')\n\t\t.replace(/\\s*,\\s*/g, ', ')\n\t\t.replace(/\\(\\s+/g, '(')\n\t\t.replace(/\\s+\\)/g, ')')\n\t\t.replace(/;\\s*$/, '')\n\t\t.trim();\n}\n","/**\n * Individual assertion evaluators for the assertion system.\n *\n * Each function takes inputs and returns an AssertionOutcome.\n * Grouped by domain: general, SQL, params, DB, intent.\n */\n\nimport { normalizeSQL } from '../sql-utils.js';\nimport type { AssertionType, TableAssertionData } from './assertion-parser.js';\nimport type {\n\tAssertionOutcome,\n\tAssertionQueryResult,\n\tIntentSummary,\n} from './types.js';\n\n// Re-export normalizeSQL from core (canonical location)\nexport { normalizeSQL };\n\n// ============================================================\n// Helpers\n// ============================================================\n\n/**\n * Convert camelCase to snake_case\n */\nfunction toSnakeCase(str: string): string {\n\treturn str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n// ============================================================\n// GENERAL ASSERTIONS\n// ============================================================\n\n/**\n * Assert that a string contains a substring\n */\nexport function assertContains(\n\tfield: string,\n\tactual: string,\n\texpected: string,\n\toriginalType?: AssertionType,\n): AssertionOutcome {\n\tconst passed = actual.includes(expected);\n\treturn {\n\t\ttype: originalType ?? (`${field}.contains` as AssertionType),\n\t\texpected,\n\t\tactual: passed ? undefined : actual, // Full value, no truncation\n\t\tpassed,\n\t\tmessage: passed ? undefined : `Expected ${field} to contain \"${expected}\"`,\n\t};\n}\n\n/**\n * Assert exact string equality\n */\nexport function assertEquals(\n\tfield: string,\n\tactual: string,\n\texpected: string,\n): AssertionOutcome {\n\tconst passed = actual.trim() === expected.trim();\n\treturn {\n\t\ttype: `${field}.equals` as AssertionType,\n\t\texpected,\n\t\tactual: passed ? undefined : actual, // Full value, no truncation\n\t\tpassed,\n\t\tmessage: passed ? undefined : `Expected ${field} to equal \"${expected}\"`,\n\t};\n}\n\n/**\n * Assert string matches regex\n */\nexport function assertMatches(\n\tfield: string,\n\tactual: string,\n\tpattern: string,\n): AssertionOutcome {\n\tconst regex = new RegExp(pattern);\n\tconst passed = regex.test(actual);\n\treturn {\n\t\ttype: `${field}.matches` as AssertionType,\n\t\texpected: pattern,\n\t\tactual: passed ? undefined : actual, // Full value, no truncation\n\t\tpassed,\n\t\tmessage: passed ? undefined : `Expected ${field} to match /${pattern}/`,\n\t};\n}\n\n/**\n * Assert query success/failure\n */\nexport function assertSuccess(\n\tactual: boolean,\n\texpected: boolean,\n): AssertionOutcome {\n\tconst passed = actual === expected;\n\treturn {\n\t\ttype: 'success',\n\t\texpected,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Expected query to ${expected ? 'succeed' : 'fail'}, but it ${actual ? 'succeeded' : 'failed'}`,\n\t};\n}\n\n// ============================================================\n// SQL ASSERTIONS\n// ============================================================\n\n/**\n * Assert SQL equality with normalization\n */\nexport function assertSQLEquals(\n\tactual: string,\n\texpected: string,\n): AssertionOutcome {\n\tconst normalizedActual = normalizeSQL(actual);\n\tconst normalizedExpected = normalizeSQL(expected);\n\tconst passed = normalizedActual === normalizedExpected;\n\n\treturn {\n\t\ttype: 'sql.equals',\n\t\texpected,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `SQL mismatch:\\n Expected: ${expected}\\n Actual: ${actual}`,\n\t};\n}\n\n/**\n * Factory for SQL identifier assertions (table/column).\n * Matches: logical name, physical snake_case, or quoted variants.\n */\nfunction createSQLIdentifierAssertion(\n\tassertionType: AssertionType,\n\tlabel: string,\n) {\n\treturn (sql: string, name: string): AssertionOutcome => {\n\t\tconst normalizedSql = sql.toLowerCase();\n\t\tconst logicalLower = name.toLowerCase();\n\t\tconst physicalSnake = toSnakeCase(name).toLowerCase();\n\n\t\tconst found =\n\t\t\tnormalizedSql.includes(logicalLower) ||\n\t\t\tnormalizedSql.includes(physicalSnake) ||\n\t\t\tnormalizedSql.includes(`\"${logicalLower}\"`) ||\n\t\t\tnormalizedSql.includes(`\"${physicalSnake}\"`);\n\n\t\treturn {\n\t\t\ttype: assertionType,\n\t\t\texpected: name,\n\t\t\tactual: found ? undefined : sql,\n\t\t\tpassed: found,\n\t\t\tmessage: found\n\t\t\t\t? undefined\n\t\t\t\t: `Expected SQL to reference ${label} \"${name}\"${physicalSnake !== logicalLower ? ` (or \"${physicalSnake}\")` : ''}`,\n\t\t};\n\t};\n}\n\nexport const assertSQLTable = createSQLIdentifierAssertion(\n\t'sql.table',\n\t'table',\n);\nexport const assertSQLColumn = createSQLIdentifierAssertion(\n\t'sql.column',\n\t'column',\n);\n\n/**\n * Assert SQL references a table via JOIN or CTE\n * Detects: LEFT/RIGHT/INNER/FULL/CROSS JOIN, WITH clause (CTE)\n * Handles schema-qualified names: \"schema\".\"table\" and plain \"table\"\n */\nexport function assertSQLJoin(\n\tsql: string,\n\ttableName: string,\n): AssertionOutcome {\n\tconst normalizedSql = sql.toLowerCase();\n\tconst tableNameLower = tableName.toLowerCase();\n\tconst tableSnake = toSnakeCase(tableName).toLowerCase();\n\n\t// Check for any type of JOIN (left, right, inner, full, cross)\n\tconst joinPattern = /\\b(left|right|inner|full|cross)?\\s*join\\b/;\n\tconst hasJoin = joinPattern.test(normalizedSql);\n\n\t// Check for CTE (WITH clause)\n\tconst ctePattern = new RegExp(\n\t\t`\\\\bwith\\\\b[^)]*\\\\b(${tableNameLower}|${tableSnake})\\\\b`,\n\t);\n\tconst hasCte = ctePattern.test(normalizedSql);\n\n\t// Check for table name (handles schema-qualified: \"schema\".\"table\")\n\t// Match: \"table\", \"schema\".\"table\", table (unquoted)\n\tconst tablePatterns = [\n\t\t`\"${tableNameLower}\"`, // quoted logical\n\t\t`\"${tableSnake}\"`, // quoted physical\n\t\t`.${tableNameLower}`, // after schema dot\n\t\t`.${tableSnake}`, // after schema dot (snake)\n\t\t` ${tableNameLower} `, // unquoted with spaces\n\t\t` ${tableSnake} `, // unquoted snake\n\t];\n\tconst hasTable = tablePatterns.some((p) => normalizedSql.includes(p));\n\n\t// Pass if: (has JOIN AND has table) OR (has CTE with table)\n\tconst found = (hasJoin && hasTable) || hasCte;\n\n\treturn {\n\t\ttype: 'sql.join',\n\t\texpected: tableName,\n\t\tactual: found ? undefined : sql,\n\t\tpassed: found,\n\t\tmessage: found\n\t\t\t? undefined\n\t\t\t: `Expected SQL to reference \"${tableName}\" via JOIN or CTE`,\n\t};\n}\n\n// ============================================================\n// PARAMS ASSERTIONS\n// ============================================================\n\n/**\n * Assert params array equality\n */\nexport function assertParamsEquals(\n\tactual: readonly unknown[],\n\texpected: unknown[],\n): AssertionOutcome {\n\tconst actualStr = JSON.stringify(actual);\n\tconst expectedStr = JSON.stringify(expected);\n\tconst passed = actualStr === expectedStr;\n\n\treturn {\n\t\ttype: 'params.equals',\n\t\texpected,\n\t\tactual: passed ? undefined : [...actual],\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Params mismatch:\\n Expected: ${expectedStr}\\n Actual: ${actualStr}`,\n\t};\n}\n\n/**\n * Assert params array length\n */\nexport function assertParamsLength(\n\tactual: readonly unknown[],\n\texpected: number,\n): AssertionOutcome {\n\tconst passed = actual.length === expected;\n\treturn {\n\t\ttype: 'params.length',\n\t\texpected,\n\t\tactual: passed ? undefined : actual.length,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Expected ${expected} params, got ${actual.length}`,\n\t};\n}\n\n/**\n * Assert parameter types (string, number, boolean, null, object)\n */\nexport function assertParamsType(\n\tparams: readonly unknown[],\n\texpectedTypes: string[],\n): AssertionOutcome {\n\tif (params.length !== expectedTypes.length) {\n\t\treturn {\n\t\t\ttype: 'params.type',\n\t\t\texpected: expectedTypes,\n\t\t\tactual: params.map((p) => typeof p),\n\t\t\tpassed: false,\n\t\t\tmessage: `Expected ${expectedTypes.length} params, got ${params.length}`,\n\t\t};\n\t}\n\n\tconst actualTypes: string[] = [];\n\tconst mismatches: string[] = [];\n\n\tfor (let i = 0; i < params.length; i++) {\n\t\tconst param = params[i];\n\t\tconst expectedType = expectedTypes[i];\n\t\tlet actualType: string;\n\n\t\tif (param === null) {\n\t\t\tactualType = 'null';\n\t\t} else if (Array.isArray(param)) {\n\t\t\tactualType = 'array';\n\t\t} else if (typeof param === 'object') {\n\t\t\tactualType = 'object';\n\t\t} else {\n\t\t\tactualType = typeof param;\n\t\t}\n\n\t\tactualTypes.push(actualType);\n\n\t\tif (actualType !== expectedType) {\n\t\t\tmismatches.push(\n\t\t\t\t`Index ${i}: expected ${expectedType}, got ${actualType}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tconst passed = mismatches.length === 0;\n\n\treturn {\n\t\ttype: 'params.type',\n\t\texpected: expectedTypes,\n\t\tactual: passed ? undefined : actualTypes,\n\t\tpassed,\n\t\tmessage: passed ? undefined : `Type mismatch: ${mismatches.join('; ')}`,\n\t};\n}\n\n/**\n * Spec format for asserting parameter value by index\n */\ninterface ParamsValueSpec {\n\tindex: number;\n\tvalue: unknown;\n}\n\n/**\n * Assert specific parameter value by index\n * Value format: { index: number, value: unknown }\n */\nexport function assertParamsValue(\n\tparams: readonly unknown[],\n\tspec: unknown,\n): AssertionOutcome {\n\tconst { index, value } =\n\t\ttypeof spec === 'object' && spec !== null\n\t\t\t? (spec as ParamsValueSpec)\n\t\t\t: { index: 0, value: spec };\n\n\tif (index >= params.length) {\n\t\treturn {\n\t\t\ttype: 'params.value',\n\t\t\texpected: value,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: `No param at index ${index} (only ${params.length} params)`,\n\t\t};\n\t}\n\n\tconst actual = params[index];\n\tconst passed = JSON.stringify(actual) === JSON.stringify(value);\n\n\treturn {\n\t\ttype: 'params.value',\n\t\texpected: value,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Param at index ${index}: expected ${JSON.stringify(value)}, got ${JSON.stringify(actual)}`,\n\t};\n}\n\n// ============================================================\n// DB ASSERTIONS (require database connection)\n// ============================================================\n\ntype RowCountComparator = (actual: number, expected: number) => boolean;\n\nfunction createRowCountAssertion(\n\tassertionType: AssertionType,\n\tcompare: RowCountComparator,\n\tmessageTemplate: (expected: number, actual: number) => string,\n) {\n\treturn (result: AssertionQueryResult, expected: number): AssertionOutcome => {\n\t\tconst rowCount = result.rowCount ?? 0;\n\t\tconst passed = compare(rowCount, expected);\n\t\treturn {\n\t\t\ttype: assertionType,\n\t\t\texpected,\n\t\t\tactual: passed ? undefined : rowCount,\n\t\t\tpassed,\n\t\t\tmessage: passed ? undefined : messageTemplate(expected, rowCount),\n\t\t};\n\t};\n}\n\nexport const assertDbRowsEquals = createRowCountAssertion(\n\t'db.rows.equals',\n\t(a, e) => a === e,\n\t(e, a) => `Expected ${e} rows, got ${a}`,\n);\n\nexport const assertDbRowsMin = createRowCountAssertion(\n\t'db.rows.min',\n\t(a, e) => a >= e,\n\t(e, a) => `Expected at least ${e} rows, got ${a}`,\n);\n\nexport const assertDbRowsMax = createRowCountAssertion(\n\t'db.rows.max',\n\t(a, e) => a <= e,\n\t(e, a) => `Expected at most ${e} rows, got ${a}`,\n);\n\n/**\n * Assert column exists in result\n */\nexport function assertDbColumnExists(\n\tresult: AssertionQueryResult,\n\tcolumnName: string,\n): AssertionOutcome {\n\tconst columns = result.columns ?? [];\n\tconst columnLower = columnName.toLowerCase();\n\tconst columnSnake = toSnakeCase(columnName).toLowerCase();\n\n\tconst found = columns.some((col) => {\n\t\tconst colLower = col.toLowerCase();\n\t\treturn colLower === columnLower || colLower === columnSnake;\n\t});\n\n\treturn {\n\t\ttype: 'db.column.exists',\n\t\texpected: columnName,\n\t\tactual: found ? undefined : columns,\n\t\tpassed: found,\n\t\tmessage: found\n\t\t\t? undefined\n\t\t\t: `Column \"${columnName}\" not found in result. Available: ${columns.join(', ')}`,\n\t};\n}\n\n/**\n * Spec format for asserting cell value in result\n */\ninterface CellValueSpec {\n\trow: number;\n\tcolumn: string;\n\tvalue: unknown;\n}\n\n/**\n * Assert specific cell value in result\n * Value format: { row: number, column: string, value: unknown }\n */\nexport function assertDbValueEquals(\n\tresult: AssertionQueryResult,\n\tspec: unknown,\n): AssertionOutcome {\n\tconst { row, column, value } =\n\t\ttypeof spec === 'object' && spec !== null\n\t\t\t? (spec as CellValueSpec)\n\t\t\t: { row: 0, column: '', value: spec };\n\n\tconst rows = result.rows ?? [];\n\tif (row >= rows.length) {\n\t\treturn {\n\t\t\ttype: 'db.value.equals',\n\t\t\texpected: value,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: `No row at index ${row} (only ${rows.length} rows)`,\n\t\t};\n\t}\n\n\tconst rowData = rows[row] as Record<string, unknown> | undefined;\n\tif (!rowData) {\n\t\treturn {\n\t\t\ttype: 'db.value.equals',\n\t\t\texpected: value,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: `Row ${row} is empty`,\n\t\t};\n\t}\n\n\t// Try both exact column name and snake_case\n\tconst actual = rowData[column] ?? rowData[toSnakeCase(column)];\n\tconst passed = JSON.stringify(actual) === JSON.stringify(value);\n\n\treturn {\n\t\ttype: 'db.value.equals',\n\t\texpected: value,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Value at [${row}][\"${column}\"]: expected ${JSON.stringify(value)}, got ${JSON.stringify(actual)}`,\n\t};\n}\n\n/**\n * Assert db.output table: compare parsed markdown table against actual DB rows.\n * - Row count must match exactly\n * - Only listed columns are checked (extra actual columns ignored)\n * - Values compared as trimmed strings\n * - \"NULL\" (case-sensitive) matches null/undefined actual values\n */\nexport function assertDbOutput(\n\tresult: AssertionQueryResult,\n\ttableData: TableAssertionData,\n): AssertionOutcome {\n\tconst { columns, rows: expectedRows } = tableData;\n\tconst actualRows = (result.rows ?? []) as Record<string, unknown>[];\n\n\t// Normalize a value for string comparison (Date → ISO, etc.)\n\tconst normalize = (val: unknown): string => {\n\t\tif (val === null || val === undefined) return 'NULL';\n\t\tif (val instanceof Date) return val.toISOString();\n\t\tif (typeof val === 'object') return JSON.stringify(val);\n\t\treturn String(val);\n\t};\n\n\t// Helper: format actual rows as markdown table for error messages\n\tconst formatActualTable = (): string => {\n\t\tif (actualRows.length === 0) return '(no rows)';\n\t\tconst actualCols =\n\t\t\tcolumns.length > 0\n\t\t\t\t? columns\n\t\t\t\t: Object.keys(actualRows[0] as Record<string, unknown>);\n\t\tconst header = `| ${actualCols.join(' | ')} |`;\n\t\tconst separator = `| ${actualCols.map(() => '---').join(' | ')} |`;\n\t\tconst rows = actualRows.map((row) => {\n\t\t\tconst cells = actualCols.map((col) => normalize(row[col]));\n\t\t\treturn `| ${cells.join(' | ')} |`;\n\t\t});\n\t\treturn [header, separator, ...rows].join('\\n');\n\t};\n\n\t// Row count check\n\tif (actualRows.length !== expectedRows.length) {\n\t\treturn {\n\t\t\ttype: 'db.output',\n\t\t\texpected: `${expectedRows.length} rows`,\n\t\t\tactual: `${actualRows.length} rows`,\n\t\t\tpassed: false,\n\t\t\tmessage: `Expected ${expectedRows.length} rows, got ${actualRows.length}\\nActual data:\\n${formatActualTable()}`,\n\t\t};\n\t}\n\n\t// Check expected columns exist in actual result (if any rows)\n\tif (actualRows.length > 0) {\n\t\tconst firstRow = actualRows[0] as Record<string, unknown>;\n\t\tfor (const col of columns) {\n\t\t\tif (!(col in firstRow)) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'db.output',\n\t\t\t\t\texpected: `column \"${col}\" in results`,\n\t\t\t\t\tactual: `columns: ${Object.keys(firstRow).join(', ')}`,\n\t\t\t\t\tpassed: false,\n\t\t\t\t\tmessage: `Expected column \"${col}\" not found in results. Available: ${Object.keys(firstRow).join(', ')}\\nActual data:\\n${formatActualTable()}`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t// Row-by-row, column-by-column comparison\n\tfor (let r = 0; r < expectedRows.length; r++) {\n\t\tconst expectedRow = expectedRows[r];\n\t\tconst actualRow = actualRows[r];\n\t\tif (!expectedRow || !actualRow) continue;\n\n\t\tfor (let c = 0; c < columns.length; c++) {\n\t\t\tconst col = columns[c];\n\t\t\tif (!col) continue;\n\t\t\tconst expectedVal = expectedRow[c] ?? '';\n\t\t\tconst actualVal = actualRow[col];\n\t\t\tconst normalizedActual = normalize(actualVal);\n\n\t\t\t// NULL handling: \"NULL\" (case-sensitive) matches null/undefined\n\t\t\tconst expectedIsNull = expectedVal === 'NULL';\n\t\t\tconst actualIsNull = actualVal === null || actualVal === undefined;\n\n\t\t\tif (expectedIsNull && actualIsNull) continue;\n\t\t\tif (expectedIsNull !== actualIsNull) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'db.output',\n\t\t\t\t\texpected: expectedVal,\n\t\t\t\t\tactual: normalizedActual,\n\t\t\t\t\tpassed: false,\n\t\t\t\t\tmessage: `Row ${r + 1}, column \"${col}\": expected ${expectedVal}, got ${normalizedActual}\\nActual data:\\n${formatActualTable()}`,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// String comparison (trimmed, with Date→ISO normalization)\n\t\t\tif (normalizedActual.trim() !== expectedVal.trim()) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'db.output',\n\t\t\t\t\texpected: expectedVal,\n\t\t\t\t\tactual: normalizedActual,\n\t\t\t\t\tpassed: false,\n\t\t\t\t\tmessage: `Row ${r + 1}, column \"${col}\": expected \"${expectedVal}\", got \"${normalizedActual}\"\\nActual data:\\n${formatActualTable()}`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\ttype: 'db.output',\n\t\texpected: `${expectedRows.length} rows matching`,\n\t\tactual: `${expectedRows.length} rows matching`,\n\t\tpassed: true,\n\t\tmessage: undefined,\n\t};\n}\n\n// ============================================================\n// INTENT AST ASSERTIONS (semantic verification)\n// ============================================================\n\n/**\n * Assert intent type (query, insert, update, delete, upsert)\n */\nexport function assertIntentType(\n\tresult: AssertionQueryResult,\n\texpected: string,\n): AssertionOutcome {\n\tconst actual = result.intent?.type;\n\n\tif (!result.intent) {\n\t\treturn {\n\t\t\ttype: 'intent.type',\n\t\t\texpected,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: 'No intent available (command or parse error)',\n\t\t};\n\t}\n\n\tconst passed = actual === expected;\n\n\treturn {\n\t\ttype: 'intent.type',\n\t\texpected,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Expected intent type \"${expected}\", got \"${actual}\"`,\n\t};\n}\n\n/**\n * Assert main table name (logical name)\n */\nexport function assertIntentTable(\n\tresult: AssertionQueryResult,\n\texpected: string,\n): AssertionOutcome {\n\tconst actual = result.intent?.table;\n\n\tif (!result.intent) {\n\t\treturn {\n\t\t\ttype: 'intent.table',\n\t\t\texpected,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: 'No intent available (command or parse error)',\n\t\t};\n\t}\n\n\t// Compare case-insensitively for flexibility\n\tconst passed = actual?.toLowerCase() === expected.toLowerCase();\n\n\treturn {\n\t\ttype: 'intent.table',\n\t\texpected,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Expected table \"${expected}\", got \"${actual}\"`,\n\t};\n}\n\n/**\n * Assert relations joined via `with` keyword\n * Value can be a single string or array of strings\n */\nexport function assertIntentWith(\n\tresult: AssertionQueryResult,\n\texpected: string | string[],\n): AssertionOutcome {\n\tconst actual = result.intent?.with ?? [];\n\tconst expectedArray = Array.isArray(expected) ? expected : [expected];\n\n\tif (!result.intent) {\n\t\treturn {\n\t\t\ttype: 'intent.with',\n\t\t\texpected: expectedArray,\n\t\t\tactual: undefined,\n\t\t\tpassed: false,\n\t\t\tmessage: 'No intent available (command or parse error)',\n\t\t};\n\t}\n\n\t// Check if all expected relations are present (case-insensitive)\n\tconst actualLower = actual.map((r: string) => r.toLowerCase());\n\tconst missing = expectedArray.filter(\n\t\t(e) => !actualLower.includes(e.toLowerCase()),\n\t);\n\n\tconst passed = missing.length === 0;\n\n\treturn {\n\t\ttype: 'intent.with',\n\t\texpected: expectedArray,\n\t\tactual: passed ? undefined : actual,\n\t\tpassed,\n\t\tmessage: passed\n\t\t\t? undefined\n\t\t\t: `Missing relations: ${missing.join(', ')}. Found: ${actual.join(', ')}`,\n\t};\n}\n\n/**\n * Factory for intent boolean flag assertions (hasWhere, hasGroupBy, hasOrderBy).\n */\nfunction createIntentBooleanAssertion(\n\tassertionType: AssertionType,\n\tfield: keyof IntentSummary,\n) {\n\treturn (\n\t\tresult: AssertionQueryResult,\n\t\texpected: boolean,\n\t): AssertionOutcome => {\n\t\tif (!result.intent) {\n\t\t\treturn {\n\t\t\t\ttype: assertionType,\n\t\t\t\texpected,\n\t\t\t\tactual: undefined,\n\t\t\t\tpassed: false,\n\t\t\t\tmessage: 'No intent available (command or parse error)',\n\t\t\t};\n\t\t}\n\n\t\tconst actual = (result.intent[field] as boolean) ?? false;\n\t\tconst passed = actual === expected;\n\n\t\treturn {\n\t\t\ttype: assertionType,\n\t\t\texpected,\n\t\t\tactual: passed ? undefined : actual,\n\t\t\tpassed,\n\t\t\tmessage: passed\n\t\t\t\t? undefined\n\t\t\t\t: `Expected ${String(field)}=${expected}, got ${actual}`,\n\t\t};\n\t};\n}\n\nexport const assertIntentHasWhere = createIntentBooleanAssertion(\n\t'intent.hasWhere',\n\t'hasWhere',\n);\nexport const assertIntentHasGroupBy = createIntentBooleanAssertion(\n\t'intent.hasGroupBy',\n\t'hasGroupBy',\n);\nexport const assertIntentHasOrderBy = createIntentBooleanAssertion(\n\t'intent.hasOrderBy',\n\t'hasOrderBy',\n);\n","/**\n * Assertion Parser for .assert.dbsp files.\n *\n * Parses YAML-like assertion files that validate query output.\n * Each assertion block starts with \"---\" followed by query reference.\n *\n * Pure string parser — zero external dependencies.\n */\n\n// Valid assertion types\nexport const ASSERTION_TYPES = [\n\t// Existing (keep for backward compat)\n\t'output.contains',\n\t'output.equals',\n\t'output.matches',\n\t'sql.equals',\n\t'sql.matches',\n\t'params.equals',\n\t'params.length',\n\t'plan.contains',\n\t'success',\n\t'error.contains',\n\n\t// NEW: Typed SQL assertions\n\t'sql.table', // Table name (logical or physical)\n\t'sql.column', // Column name in SQL\n\t'sql.join', // JOIN clause present\n\n\t// NEW: Typed params assertions\n\t'params.type', // Type validation per param\n\t'params.value', // Specific param value by index\n\n\t// NEW: DB-only assertions (skipped in dry-run)\n\t'db.success', // Success check (skipped in dry-run)\n\t'db.output.contains', // Output contains (skipped in dry-run)\n\t'db.rows.equals', // Exact row count\n\t'db.rows.min', // At least N rows\n\t'db.rows.max', // At most N rows\n\t'db.output', // Table block assertion (multiline row comparison)\n\t'db.column.exists', // Column in result\n\t'db.value.equals', // Specific cell value\n\n\t// NEW: Intent AST assertions (semantic verification)\n\t'intent.type', // Intent type (query/insert/update/delete/upsert)\n\t'intent.table', // Main table name (logical)\n\t'intent.with', // Relations joined via `with` keyword (was 'include')\n\t'intent.hasWhere', // Has WHERE clause (true/false)\n\t'intent.hasGroupBy', // Has GROUP BY (true/false)\n\t'intent.hasOrderBy', // Has ORDER BY (true/false)\n] as const;\n\nexport type AssertionType = (typeof ASSERTION_TYPES)[number];\n\n/**\n * Check if an assertion type requires database connection\n * All db.* assertions need actual query execution\n */\nexport function requiresDatabase(type: AssertionType): boolean {\n\treturn type.startsWith('db.');\n}\n\n/**\n * Parsed table data for db.output table assertions.\n * columns: header names; rows: cell values as trimmed strings.\n */\nexport interface TableAssertionData {\n\tcolumns: string[];\n\trows: string[][];\n}\n\n/**\n * A single assertion within a block\n */\nexport interface Assertion {\n\ttype: AssertionType;\n\tvalue: string | number | boolean | unknown[] | TableAssertionData;\n\tline: number;\n}\n\n/**\n * A block of assertions for a single query\n */\nexport interface AssertionBlock {\n\t/** Query index (0-based) if using \"query: N\" */\n\tqueryIndex?: number;\n\t/** Query text pattern if using \"match: text\" */\n\tqueryMatch?: string;\n\t/** Line number where the block starts */\n\tstartLine: number;\n\t/** All assertions in this block */\n\tassertions: Assertion[];\n}\n\n/**\n * Result of parsing an assertion file\n */\nexport interface ParseResult {\n\tblocks: AssertionBlock[];\n\terrors: ParseError[];\n}\n\n/**\n * A parsing error with location information\n */\nexport interface ParseError {\n\tline: number;\n\tmessage: string;\n}\n\n/**\n * Parse an assertion file content into structured blocks\n *\n * @param content - The raw content of the .assert.dbsp file\n * @returns ParseResult with blocks and any parsing errors\n */\nexport function parseAssertionFile(content: string): ParseResult {\n\tconst lines = content.split('\\n');\n\tconst blocks: AssertionBlock[] = [];\n\tconst errors: ParseError[] = [];\n\n\tlet currentBlock: AssertionBlock | null = null;\n\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst lineNum = i + 1; // 1-based line numbers for user display\n\t\tconst line = lines[i];\n\t\tif (line === undefined) continue;\n\t\tconst trimmed = line.trim();\n\n\t\t// Skip empty lines and comments\n\t\tif (!trimmed || trimmed.startsWith('#')) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check for block start: --- query: N or --- match: text\n\t\tif (trimmed.startsWith('---')) {\n\t\t\t// Save previous block if exists\n\t\t\tif (currentBlock) {\n\t\t\t\tblocks.push(currentBlock);\n\t\t\t}\n\n\t\t\tconst blockHeader = trimmed.slice(3).trim();\n\t\t\tconst parsed = parseBlockHeader(blockHeader, lineNum);\n\n\t\t\tif (parsed.error || !parsed.block) {\n\t\t\t\terrors.push({\n\t\t\t\t\tline: lineNum,\n\t\t\t\t\tmessage: parsed.error ?? 'Invalid block header',\n\t\t\t\t});\n\t\t\t\tcurrentBlock = null;\n\t\t\t} else {\n\t\t\t\tcurrentBlock = {\n\t\t\t\t\t...parsed.block,\n\t\t\t\t\tstartLine: lineNum,\n\t\t\t\t\tassertions: [],\n\t\t\t\t};\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Parse assertion line within a block\n\t\tif (currentBlock) {\n\t\t\tconst assertion = parseAssertionLine(trimmed, lineNum);\n\t\t\tif (assertion.error) {\n\t\t\t\terrors.push({ line: lineNum, message: assertion.error });\n\t\t\t} else if (assertion.assertion) {\n\t\t\t\t// db.output table block: collect pipe-delimited rows from subsequent lines\n\t\t\t\tif (\n\t\t\t\t\tassertion.assertion.type === 'db.output' &&\n\t\t\t\t\tassertion.assertion.value === ''\n\t\t\t\t) {\n\t\t\t\t\tconst tableResult = parseTableBlock(lines, i + 1);\n\t\t\t\t\tif (tableResult.error) {\n\t\t\t\t\t\terrors.push({ line: lineNum, message: tableResult.error });\n\t\t\t\t\t} else if (tableResult.data) {\n\t\t\t\t\t\tassertion.assertion.value = tableResult.data;\n\t\t\t\t\t\tcurrentBlock.assertions.push(assertion.assertion);\n\t\t\t\t\t}\n\t\t\t\t\ti += tableResult.linesConsumed; // skip past consumed table lines\n\t\t\t\t} else {\n\t\t\t\t\tcurrentBlock.assertions.push(assertion.assertion);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Assertion outside of any block\n\t\t\terrors.push({\n\t\t\t\tline: lineNum,\n\t\t\t\tmessage:\n\t\t\t\t\t'Assertion found outside of any block. Start a block with \"--- query: N\" or \"--- match: text\"',\n\t\t\t});\n\t\t}\n\t}\n\n\t// Don't forget the last block\n\tif (currentBlock) {\n\t\tblocks.push(currentBlock);\n\t}\n\n\treturn { blocks, errors };\n}\n\n/**\n * Parse a block header (after the \"---\")\n */\nfunction parseBlockHeader(\n\theader: string,\n\t_line: number,\n): { block?: Partial<AssertionBlock>; error?: string } {\n\t// Handle \"query: N\"\n\tconst queryMatch = header.match(/^query:\\s*(\\d+)$/);\n\tconst queryIndexStr = queryMatch?.[1];\n\tif (queryIndexStr !== undefined) {\n\t\tconst index = parseInt(queryIndexStr, 10);\n\t\treturn { block: { queryIndex: index } };\n\t}\n\n\t// Handle \"match: text\"\n\tconst matchMatch = header.match(/^match:\\s*(.+)$/);\n\tconst matchText = matchMatch?.[1];\n\tif (matchText !== undefined) {\n\t\tconst text = matchText.trim();\n\t\tif (!text) {\n\t\t\treturn { error: 'Empty match pattern' };\n\t\t}\n\t\treturn { block: { queryMatch: text } };\n\t}\n\n\t// Invalid header format\n\treturn {\n\t\terror: `Invalid block header: \"${header}\". Expected \"query: N\" or \"match: text\"`,\n\t};\n}\n\n/**\n * Parse a single assertion line\n */\nfunction parseAssertionLine(\n\tline: string,\n\tlineNum: number,\n): { assertion?: Assertion; error?: string } {\n\t// Find the colon separator\n\tconst colonIndex = line.indexOf(':');\n\tif (colonIndex === -1) {\n\t\treturn {\n\t\t\terror: `Invalid assertion syntax: \"${line}\". Expected \"type: value\"`,\n\t\t};\n\t}\n\n\tconst typeStr = line.slice(0, colonIndex).trim();\n\tconst valueStr = line.slice(colonIndex + 1).trim();\n\n\t// Validate assertion type\n\tif (!isValidAssertionType(typeStr)) {\n\t\treturn {\n\t\t\terror: `Unknown assertion type: \"${typeStr}\". Valid types: ${ASSERTION_TYPES.join(', ')}`,\n\t\t};\n\t}\n\n\tconst type = typeStr as AssertionType;\n\n\t// Parse value based on type\n\tconst parsedValue = parseAssertionValue(type, valueStr);\n\tif (parsedValue.error || parsedValue.value === undefined) {\n\t\treturn { error: parsedValue.error ?? 'Failed to parse assertion value' };\n\t}\n\n\treturn {\n\t\tassertion: {\n\t\t\ttype,\n\t\t\tvalue: parsedValue.value,\n\t\t\tline: lineNum,\n\t\t},\n\t};\n}\n\n/**\n * Check if a string is a valid assertion type\n */\nfunction isValidAssertionType(type: string): type is AssertionType {\n\treturn ASSERTION_TYPES.includes(type as AssertionType);\n}\n\n/**\n * Parse the value part of an assertion based on its type\n */\nfunction parseAssertionValue(\n\ttype: AssertionType,\n\tvalueStr: string,\n): { value?: string | number | boolean | unknown[]; error?: string } {\n\tswitch (type) {\n\t\t// Boolean value\n\t\tcase 'success':\n\t\tcase 'db.success':\n\t\tcase 'intent.hasWhere':\n\t\tcase 'intent.hasGroupBy':\n\t\tcase 'intent.hasOrderBy':\n\t\t\tif (valueStr === 'true') return { value: true };\n\t\t\tif (valueStr === 'false') return { value: false };\n\t\t\treturn {\n\t\t\t\terror: `Invalid boolean value for \"${type}\": \"${valueStr}\". Expected \"true\" or \"false\"`,\n\t\t\t};\n\n\t\t// Numeric value\n\t\tcase 'params.length':\n\t\tcase 'db.rows.equals':\n\t\tcase 'db.rows.min':\n\t\tcase 'db.rows.max': {\n\t\t\tconst num = parseInt(valueStr, 10);\n\t\t\tif (Number.isNaN(num) || num < 0) {\n\t\t\t\treturn {\n\t\t\t\t\terror: `Invalid number for \"${type}\": \"${valueStr}\". Expected non-negative integer`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { value: num };\n\t\t}\n\n\t\t// JSON array value\n\t\tcase 'params.equals':\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(valueStr);\n\t\t\t\tif (!Array.isArray(parsed)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\terror: `Invalid params.equals value: expected JSON array, got ${typeof parsed}`,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn { value: parsed };\n\t\t\t} catch (_e) {\n\t\t\t\treturn { error: `Invalid JSON for \"params.equals\": ${valueStr}` };\n\t\t\t}\n\n\t\t// JSON array value for params.type\n\t\tcase 'params.type':\n\t\t\ttry {\n\t\t\t\tconst parsed = JSON.parse(valueStr);\n\t\t\t\tif (!Array.isArray(parsed)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\terror: `Invalid params.type value: expected JSON array, got ${typeof parsed}`,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn { value: parsed };\n\t\t\t} catch (_e) {\n\t\t\t\treturn { error: `Invalid JSON for \"params.type\": ${valueStr}` };\n\t\t\t}\n\n\t\t// JSON value for params.value (format: \"index:value\")\n\t\tcase 'params.value':\n\t\t\t// Format: index:value or just value (for simple cases)\n\t\t\treturn { value: valueStr };\n\n\t\t// JSON/any value for db.value.equals\n\t\tcase 'db.value.equals':\n\t\t\t// Try to parse as JSON, otherwise treat as string\n\t\t\ttry {\n\t\t\t\treturn { value: JSON.parse(valueStr) };\n\t\t\t} catch {\n\t\t\t\treturn { value: valueStr };\n\t\t\t}\n\n\t\t// Table block assertion: db.output has no inline value (table follows on next lines)\n\t\tcase 'db.output':\n\t\t\treturn { value: '' }; // Marker — table data parsed separately by parseAssertionFile\n\n\t\t// String values (all others)\n\t\tcase 'output.contains':\n\t\tcase 'output.equals':\n\t\tcase 'output.matches':\n\t\tcase 'sql.equals':\n\t\tcase 'sql.matches':\n\t\tcase 'sql.table':\n\t\tcase 'sql.column':\n\t\tcase 'sql.join':\n\t\tcase 'plan.contains':\n\t\tcase 'error.contains':\n\t\tcase 'db.column.exists':\n\t\tcase 'db.output.contains':\n\t\tcase 'intent.type':\n\t\tcase 'intent.table':\n\t\tcase 'intent.with':\n\t\t\t// For regex types, validate the pattern\n\t\t\tif (type.endsWith('.matches')) {\n\t\t\t\ttry {\n\t\t\t\t\tnew RegExp(valueStr);\n\t\t\t\t} catch (_e) {\n\t\t\t\t\treturn { error: `Invalid regex pattern: \"${valueStr}\"` };\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { value: valueStr };\n\n\t\tdefault:\n\t\t\treturn { error: `Unhandled assertion type: ${type}` };\n\t}\n}\n\n// ============================================================================\n// Table block parsing helpers (for db.output)\n// ============================================================================\n\n/**\n * Check if a pipe-delimited line is a separator row (e.g. |---|---|)\n */\nfunction isSeparatorRow(line: string): boolean {\n\treturn /^\\|[\\s\\-:|]+\\|$/.test(line.trim());\n}\n\n/**\n * Parse a pipe-delimited row into an array of trimmed cell values.\n * Handles escaped pipes (\\|) within cell values.\n */\nfunction parseTableCells(line: string): string[] {\n\tlet inner = line.trim();\n\t// Strip leading/trailing pipes\n\tif (inner.startsWith('|')) inner = inner.slice(1);\n\tif (inner.endsWith('|')) inner = inner.slice(0, -1);\n\n\tconst cells: string[] = [];\n\tlet current = '';\n\tfor (let i = 0; i < inner.length; i++) {\n\t\tif (inner[i] === '\\\\' && i + 1 < inner.length && inner[i + 1] === '|') {\n\t\t\tcurrent += '|';\n\t\t\ti++; // skip escaped pipe\n\t\t} else if (inner[i] === '|') {\n\t\t\tcells.push(current.trim());\n\t\t\tcurrent = '';\n\t\t} else {\n\t\t\tcurrent += inner[i];\n\t\t}\n\t}\n\tcells.push(current.trim());\n\treturn cells;\n}\n\n/**\n * Parse a table block starting at `startIndex` in the lines array.\n * Collects pipe-delimited rows, skips blanks and separator rows.\n * Returns parsed TableAssertionData and number of lines consumed.\n */\nfunction parseTableBlock(\n\tlines: string[],\n\tstartIndex: number,\n): { data?: TableAssertionData; linesConsumed: number; error?: string } {\n\tconst tableLines: string[] = [];\n\tlet consumed = 0;\n\n\tfor (let j = startIndex; j < lines.length; j++) {\n\t\tconst raw = lines[j];\n\t\tif (raw === undefined) break;\n\t\tconst trimmed = raw.trim();\n\n\t\t// Blank lines within table are ignored (not terminators)\n\t\tif (!trimmed) {\n\t\t\tconsumed++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Pipe-delimited line → part of the table\n\t\tif (trimmed.startsWith('|')) {\n\t\t\ttableLines.push(trimmed);\n\t\t\tconsumed++;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Any other line (including --- block headers) → end of table\n\t\tbreak;\n\t}\n\n\tif (tableLines.length === 0) {\n\t\treturn {\n\t\t\tlinesConsumed: consumed,\n\t\t\terror: 'db.output: expected table rows starting with |',\n\t\t};\n\t}\n\n\t// Filter out separator rows\n\tconst dataLines = tableLines.filter((l) => !isSeparatorRow(l));\n\tif (dataLines.length === 0) {\n\t\treturn {\n\t\t\tlinesConsumed: consumed,\n\t\t\terror: 'db.output: table has only separator rows, no header or data',\n\t\t};\n\t}\n\n\tconst headerLine = dataLines[0] as string;\n\tconst columns = parseTableCells(headerLine);\n\tconst rows = dataLines.slice(1).map((l) => parseTableCells(l));\n\n\treturn { data: { columns, rows }, linesConsumed: consumed };\n}\n\n/**\n * Validate that all query references in assertion blocks are valid\n *\n * @param blocks - Parsed assertion blocks\n * @param queryCount - Number of queries in the query file\n * @param queries - The actual query strings (for match validation)\n * @returns Array of validation errors\n */\nexport function validateAssertionBlocks(\n\tblocks: AssertionBlock[],\n\tqueryCount: number,\n\tqueries: string[],\n): ParseError[] {\n\tconst errors: ParseError[] = [];\n\n\tfor (const block of blocks) {\n\t\t// Validate query index\n\t\tif (block.queryIndex !== undefined) {\n\t\t\tif (block.queryIndex < 0 || block.queryIndex >= queryCount) {\n\t\t\t\terrors.push({\n\t\t\t\t\tline: block.startLine,\n\t\t\t\t\tmessage: `Query index ${block.queryIndex} out of bounds (0-${queryCount - 1})`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Validate query match and check for ambiguity\n\t\tif (block.queryMatch !== undefined) {\n\t\t\tconst matchingIndices = queries\n\t\t\t\t.map((q, i) => (q.trim() === block.queryMatch?.trim() ? i : -1))\n\t\t\t\t.filter((i) => i !== -1);\n\n\t\t\tif (matchingIndices.length === 0) {\n\t\t\t\terrors.push({\n\t\t\t\t\tline: block.startLine,\n\t\t\t\t\tmessage: `No query matches \"${block.queryMatch}\"`,\n\t\t\t\t});\n\t\t\t} else if (matchingIndices.length > 1) {\n\t\t\t\t// ERR-06: Ambiguous match\n\t\t\t\terrors.push({\n\t\t\t\t\tline: block.startLine,\n\t\t\t\t\tmessage: `Ambiguous match: '${block.queryMatch}' matches queries ${matchingIndices.join(', ')}. Use query index instead.`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Warn if block has no assertions\n\t\tif (block.assertions.length === 0) {\n\t\t\terrors.push({\n\t\t\t\tline: block.startLine,\n\t\t\t\tmessage: 'Block has no assertions',\n\t\t\t});\n\t\t}\n\t}\n\n\treturn errors;\n}\n\n/**\n * Resolve which query index a block refers to\n *\n * @param block - The assertion block\n * @param queries - The query strings\n * @returns The resolved query index, or -1 if not found\n */\nexport function resolveQueryIndex(\n\tblock: AssertionBlock,\n\tqueries: string[],\n): number {\n\tif (block.queryIndex !== undefined) {\n\t\treturn block.queryIndex;\n\t}\n\n\tif (block.queryMatch !== undefined) {\n\t\tconst index = queries.findIndex(\n\t\t\t(q) => q.trim() === block.queryMatch?.trim(),\n\t\t);\n\t\treturn index;\n\t}\n\n\treturn -1;\n}\n","/**\n * Assertion Runner for .assert.dbsp files.\n *\n * Runs assertions against query results and collects pass/fail outcomes.\n * Shared by CLI and GUI sidecar.\n */\n\nimport {\n\tassertContains,\n\tassertDbColumnExists,\n\tassertDbOutput,\n\tassertDbRowsEquals,\n\tassertDbRowsMax,\n\tassertDbRowsMin,\n\tassertDbValueEquals,\n\tassertEquals,\n\tassertIntentHasGroupBy,\n\tassertIntentHasOrderBy,\n\tassertIntentHasWhere,\n\tassertIntentTable,\n\tassertIntentType,\n\tassertIntentWith,\n\tassertMatches,\n\tassertParamsEquals,\n\tassertParamsLength,\n\tassertParamsType,\n\tassertParamsValue,\n\tassertSQLColumn,\n\tassertSQLEquals,\n\tassertSQLJoin,\n\tassertSQLTable,\n\tassertSuccess,\n} from './assertion-functions.js';\nimport type {\n\tAssertion,\n\tAssertionBlock,\n\tTableAssertionData,\n} from './assertion-parser.js';\nimport { resolveQueryIndex } from './assertion-parser.js';\nimport type {\n\tAssertionOutcome,\n\tAssertionQueryResult,\n\tAssertionSummary,\n\tQueryAssertionResult,\n} from './types.js';\n\n/**\n * Run all assertion blocks against query results\n *\n * @param blocks - Parsed assertion blocks\n * @param results - Query execution results\n * @param queries - Original query strings (for matching)\n * @param hasDb - Whether a database connection is available (for db.* assertions)\n * @returns Summary with detailed results\n */\nexport function runAssertions(\n\tblocks: AssertionBlock[],\n\tresults: AssertionQueryResult[],\n\tqueries: string[],\n\thasDb = false,\n): AssertionSummary {\n\tconst queryResults: QueryAssertionResult[] = [];\n\tlet totalPassed = 0;\n\tlet totalFailed = 0;\n\tlet totalSkipped = 0;\n\n\tfor (const block of blocks) {\n\t\tconst queryIndex = resolveQueryIndex(block, queries);\n\n\t\t// Skip if query index couldn't be resolved (validation should catch this earlier)\n\t\tif (queryIndex === -1 || queryIndex >= results.length) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst result = results[queryIndex];\n\t\tif (!result) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst outcomes: AssertionOutcome[] = [];\n\t\tlet allPassed = true;\n\n\t\tfor (const assertion of block.assertions) {\n\t\t\tconst outcome = runSingleAssertion(assertion, result, hasDb);\n\t\t\toutcomes.push(outcome);\n\n\t\t\tif (outcome.skipped) {\n\t\t\t\ttotalSkipped++;\n\t\t\t} else if (outcome.passed) {\n\t\t\t\ttotalPassed++;\n\t\t\t} else {\n\t\t\t\ttotalFailed++;\n\t\t\t\tallPassed = false;\n\t\t\t}\n\t\t}\n\n\t\tqueryResults.push({\n\t\t\tqueryIndex,\n\t\t\tquery: result.query,\n\t\t\tquerySuccess: result.success,\n\t\t\tassertions: outcomes,\n\t\t\tpassed: allPassed,\n\t\t});\n\t}\n\n\treturn {\n\t\ttotal: totalPassed + totalFailed + totalSkipped,\n\t\tpassed: totalPassed,\n\t\tfailed: totalFailed,\n\t\tskipped: totalSkipped,\n\t\tresults: queryResults,\n\t};\n}\n\n/**\n * Run a single assertion against a query result\n */\nfunction runSingleAssertion(\n\tassertion: Assertion,\n\tresult: AssertionQueryResult,\n\thasDb: boolean,\n): AssertionOutcome {\n\tconst { type, value } = assertion;\n\n\t// Skip db.* assertions when no database connection\n\tif (type.startsWith('db.') && !hasDb) {\n\t\treturn {\n\t\t\ttype,\n\t\t\texpected: value,\n\t\t\tactual: undefined,\n\t\t\tpassed: true, // Consider skipped as not-failed\n\t\t\tmessage: undefined,\n\t\t\tskipped: true,\n\t\t\tskipReason: 'No database connection (dry-run mode)',\n\t\t};\n\t}\n\n\tswitch (type) {\n\t\t// Output assertions\n\t\tcase 'output.contains':\n\t\t\treturn assertContains('output', result.output ?? '', value as string);\n\n\t\tcase 'output.equals':\n\t\t\treturn assertEquals('output', result.output ?? '', value as string);\n\n\t\tcase 'output.matches':\n\t\t\treturn assertMatches('output', result.output ?? '', value as string);\n\n\t\t// SQL assertions\n\t\tcase 'sql.equals':\n\t\t\treturn assertSQLEquals(result.sql ?? '', value as string);\n\n\t\tcase 'sql.matches':\n\t\t\treturn assertMatches('sql', result.sql ?? '', value as string);\n\n\t\tcase 'sql.table':\n\t\t\treturn assertSQLTable(result.sql ?? '', value as string);\n\n\t\tcase 'sql.column':\n\t\t\treturn assertSQLColumn(result.sql ?? '', value as string);\n\n\t\tcase 'sql.join':\n\t\t\treturn assertSQLJoin(result.sql ?? '', value as string);\n\n\t\t// Params assertions\n\t\tcase 'params.equals':\n\t\t\treturn assertParamsEquals(result.params ?? [], value as unknown[]);\n\n\t\tcase 'params.length':\n\t\t\treturn assertParamsLength(result.params ?? [], value as number);\n\n\t\tcase 'params.type':\n\t\t\treturn assertParamsType(result.params ?? [], value as string[]);\n\n\t\tcase 'params.value':\n\t\t\treturn assertParamsValue(result.params ?? [], value as unknown);\n\n\t\t// Plan assertion (plan info is in output)\n\t\tcase 'plan.contains':\n\t\t\treturn assertContains('plan', result.output ?? '', value as string);\n\n\t\t// Success assertion\n\t\tcase 'success':\n\t\t\treturn assertSuccess(result.success, value as boolean);\n\n\t\t// Error assertion\n\t\tcase 'error.contains':\n\t\t\treturn assertContains('error', result.error ?? '', value as string);\n\n\t\t// DB assertions (require database connection)\n\t\tcase 'db.success':\n\t\t\t// Use dbSuccess if available, fall back to success for backwards compatibility\n\t\t\treturn assertSuccess(\n\t\t\t\tresult.dbSuccess ?? result.success,\n\t\t\t\tvalue as boolean,\n\t\t\t);\n\n\t\tcase 'db.output':\n\t\t\treturn assertDbOutput(result, value as TableAssertionData);\n\n\t\tcase 'db.output.contains':\n\t\t\treturn assertContains(\n\t\t\t\t'output',\n\t\t\t\tresult.output ?? '',\n\t\t\t\tvalue as string,\n\t\t\t\t'db.output.contains',\n\t\t\t);\n\n\t\tcase 'db.rows.equals':\n\t\t\treturn assertDbRowsEquals(result, value as number);\n\n\t\tcase 'db.rows.min':\n\t\t\treturn assertDbRowsMin(result, value as number);\n\n\t\tcase 'db.rows.max':\n\t\t\treturn assertDbRowsMax(result, value as number);\n\n\t\tcase 'db.column.exists':\n\t\t\treturn assertDbColumnExists(result, value as string);\n\n\t\tcase 'db.value.equals':\n\t\t\treturn assertDbValueEquals(result, value as unknown);\n\n\t\t// Intent AST assertions\n\t\tcase 'intent.type':\n\t\t\treturn assertIntentType(result, value as string);\n\n\t\tcase 'intent.table':\n\t\t\treturn assertIntentTable(result, value as string);\n\n\t\tcase 'intent.with':\n\t\t\treturn assertIntentWith(result, value as string | string[]);\n\n\t\tcase 'intent.hasWhere':\n\t\t\treturn assertIntentHasWhere(result, value as boolean);\n\n\t\tcase 'intent.hasGroupBy':\n\t\t\treturn assertIntentHasGroupBy(result, value as boolean);\n\n\t\tcase 'intent.hasOrderBy':\n\t\t\treturn assertIntentHasOrderBy(result, value as boolean);\n\n\t\tdefault:\n\t\t\treturn {\n\t\t\t\ttype,\n\t\t\t\texpected: value,\n\t\t\t\tactual: undefined,\n\t\t\t\tpassed: false,\n\t\t\t\tmessage: `Unknown assertion type: ${type}`,\n\t\t\t};\n\t}\n}\n","/**\n * Shared assertion types for .assert.dbsp evaluation.\n *\n * Used by both CLI (assertion-runner) and GUI sidecar (assertion-handler).\n */\n\nimport type { AssertionType } from './assertion-parser.js';\n\n// ── Intent summary (inline — no dependency on CLI's nql-executor) ──\n\n/**\n * Lightweight summary of a compiled query intent.\n * Populated by the NQL executor after compilation.\n */\nexport interface IntentSummary {\n\ttype: 'query' | 'insert' | 'update' | 'delete' | 'upsert' | 'setOperation';\n\ttable: string;\n\twith: string[];\n\thasWhere: boolean;\n\thasGroupBy: boolean;\n\thasOrderBy: boolean;\n\tctes: string[];\n}\n\n// ── Query result (sidecar-friendly version of CLI's BatchResult) ──\n\n/**\n * Portable query result for assertion evaluation.\n * Both CLI (via BatchResult adapter) and sidecar produce this shape.\n */\nexport interface AssertionQueryResult {\n\tquery: string;\n\tsuccess: boolean;\n\tdbSuccess?: boolean;\n\toutput?: string;\n\tsql?: string;\n\tparams?: readonly unknown[];\n\terror?: string;\n\trowCount?: number;\n\tcolumns?: string[];\n\trows?: unknown[];\n\tintent?: IntentSummary;\n}\n\n// ── Assertion outcome ──\n\n/**\n * Result of running a single assertion.\n */\nexport interface AssertionOutcome {\n\ttype: AssertionType;\n\texpected: unknown;\n\tactual: unknown;\n\tpassed: boolean;\n\tmessage: string | undefined;\n\t/** True if assertion was skipped (e.g., db.* without DB connection) */\n\tskipped?: boolean;\n\t/** Reason for skipping */\n\tskipReason?: string;\n}\n\n// ── Aggregated results ──\n\n/**\n * Result of running all assertions for a single query.\n */\nexport interface QueryAssertionResult {\n\tqueryIndex: number;\n\tquery: string;\n\tquerySuccess: boolean;\n\tassertions: AssertionOutcome[];\n\tpassed: boolean;\n}\n\n/**\n * Summary of all assertion results.\n */\nexport interface AssertionSummary {\n\ttotal: number;\n\tpassed: number;\n\tfailed: number;\n\tskipped: number;\n\tresults: QueryAssertionResult[];\n}\n\n/**\n * Determine whether a query result represents end-to-end success\n * (compile + DB execution combined).\n *\n * Truth table:\n * | success | dbSuccess | result |\n * |---------|------------|--------|\n * | false | (any) | false |\n * | true | undefined | true | (compile-only mode — no DB)\n * | true | true | true |\n * | true | false | false |\n *\n * Contract: conforming producers either omit `dbSuccess` (compile-only\n * mode — no DB execution) or set it to a real boolean reflecting DB\n * outcome.\n *\n * Stable predicate — the truth table above IS the contract; callers may\n * rely on its exact behavior. As a `@public` helper, the implementation\n * is also defensive: malformed input (`null`, `undefined`, missing\n * `success`, non-boolean `success`) returns `false` rather than throwing\n * or returning a non-boolean.\n *\n * @public\n */\nexport function isOverallSuccess(r: {\n\tsuccess: boolean;\n\tdbSuccess?: boolean;\n}): boolean {\n\treturn Boolean(r) && r.success === true && r.dbSuccess !== false;\n}\n"],"mappings":"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","names":["col","ref","col","SchemaValidationError","col","raw","col","ref","col","col","fn","ref","fn","col","distinct","intent","record","record","v","op","col","distinct","rows","col","op","v","requireAdapter","sql","schemaName","fn","ref","mapRelationType","col","schema","sql","sql","param","col","raw"]}
|