@pattern-stack/codegen 0.4.3 → 0.4.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/parser/load-entities.ts","../../src/utils/yaml-loader.ts","../../src/schema/entity-definition.schema.ts","../../src/schema/event-definition.schema.ts","../../src/schema/relationship-definition.schema.ts","../../src/analyzer/graph-builder.ts","../../src/behaviors/external-id-tracking.ts","../../src/behaviors/soft-delete.ts","../../src/behaviors/timestamps.ts","../../src/behaviors/user-tracking.ts","../../src/behaviors/index.ts","../../src/analyzer/consistency-checker.ts","../../src/analyzer/statistics.ts","../../src/patterns/registry.ts","../../src/patterns/pattern-definition.ts","../../src/patterns/validate-composition.ts","../../src/formatters/console-formatter.ts","../../src/formatters/json-formatter.ts","../../src/formatters/markdown-formatter.ts","../../src/patterns/library/activity.pattern.ts","../../src/patterns/library/base.pattern.ts","../../src/patterns/library/knowledge.pattern.ts","../../src/patterns/library/metadata.pattern.ts","../../src/patterns/library/synced.pattern.ts","../../src/patterns/library/index.ts","../../src/index.ts"],"sourcesContent":["/**\n * Entity Loader\n *\n * Loads and parses all YAML entity files from a directory.\n * Reuses existing yaml-loader and entity-definition schema from codegen.\n */\n\nimport { readdirSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport {\n\tloadEntityFromYaml,\n\tloadRelationshipFromYaml,\n\ttype LoadResult,\n\ttype LoadError,\n\ttype RelationshipLoadResult,\n\ttype RelationshipLoadError,\n} from '../utils/yaml-loader';\nimport type {\n\tParsedEntity,\n\tParsedEvent,\n\tParsedField,\n\tParsedProviderSync,\n\tParsedQuery,\n\tParsedRelationship,\n\tParsedRelationshipDefinition,\n\tParsedSync,\n\tParsedTypeDirection,\n\tAnalysisIssue,\n} from '../analyzer/types';\nimport {\n\tderiveRelationshipFKColumns,\n\tderiveTableName,\n\tderiveUniqueConstraint,\n\tcollectTypeNames,\n\ttype RelationshipDefinition,\n\ttype RelationshipTypes,\n} from '../schema/relationship-definition.schema';\n\nexport interface LoadEntitiesResult {\n\tentities: ParsedEntity[];\n\tissues: AnalysisIssue[];\n}\n\n/**\n * Transform a loaded entity definition into a ParsedEntity\n */\nfunction transformToEntity(result: LoadResult): ParsedEntity {\n\tconst { definition, filePath } = result;\n\n\t// Search queries use a different shape (name/filters/search/paginate) and\n\t// are consumed directly by the codegen templates, not by the analyzer.\n\t// Narrow to the by-column variant here for ParsedQuery mapping.\n\tconst queries: ParsedQuery[] | undefined = definition.queries\n\t\t?.filter((q): q is Extract<typeof q, { by: unknown }> => 'by' in q)\n\t\t.map((q) => ({\n\t\t\tby: q.by,\n\t\t\tunique: q.unique,\n\t\t\tselect: q.select,\n\t\t\torder: q.order,\n\t\t\tlimit: q.limit,\n\t\t\tvia: q.via,\n\t\t}));\n\n\tconst entity: ParsedEntity = {\n\t\tname: definition.entity.name,\n\t\tplural: definition.entity.plural,\n\t\ttable: definition.entity.table,\n\t\tpattern: definition.entity.pattern,\n\t\tpatterns: definition.entity.patterns,\n\t\tpatternConfig: definition.entity.config,\n\t\tscopeable: definition.entity.scopeable ?? false,\n\t\tfolderStructure: definition.entity.folder_structure ?? 'nested',\n\t\tfields: new Map(),\n\t\trelationships: new Map(),\n\t\tbehaviors: definition.behaviors.map((b) => (typeof b === 'string' ? b : b.name)),\n\t\tqueries,\n\t\tsourcePath: filePath,\n\t};\n\n\t// Parse fields\n\tfor (const [name, fieldDef] of Object.entries(definition.fields)) {\n\t\tconst field: ParsedField = {\n\t\t\tname,\n\t\t\ttype: fieldDef.type,\n\t\t\trequired: fieldDef.required ?? false,\n\t\t\tnullable: fieldDef.nullable ?? false,\n\t\t\tunique: fieldDef.unique ?? false,\n\t\t\tindex: fieldDef.index ?? false,\n\t\t\tforeignKey: fieldDef.foreign_key ? parseForeignKey(fieldDef.foreign_key) : undefined,\n\t\t\tchoices: fieldDef.choices,\n\t\t\tconstraints: {\n\t\t\t\tminLength: fieldDef.min_length,\n\t\t\t\tmaxLength: fieldDef.max_length,\n\t\t\t\tmin: fieldDef.min,\n\t\t\t\tmax: fieldDef.max,\n\t\t\t},\n\t\t\tui: {\n\t\t\t\tlabel: fieldDef.ui_label,\n\t\t\t\ttype: fieldDef.ui_type,\n\t\t\t\timportance: fieldDef.ui_importance,\n\t\t\t\tgroup: fieldDef.ui_group,\n\t\t\t\tsortable: fieldDef.ui_sortable,\n\t\t\t\tfilterable: fieldDef.ui_filterable,\n\t\t\t\tvisible: fieldDef.ui_visible,\n\t\t\t},\n\t\t};\n\t\tentity.fields.set(name, field);\n\t}\n\n\t// Parse relationships\n\tif (definition.relationships) {\n\t\tfor (const [name, relDef] of Object.entries(definition.relationships)) {\n\t\t\tconst relationship: ParsedRelationship = {\n\t\t\t\tname,\n\t\t\t\ttype: relDef.type,\n\t\t\t\ttarget: relDef.target,\n\t\t\t\tforeignKey: relDef.foreign_key,\n\t\t\t\tinverse: relDef.inverse,\n\t\t\t\tthrough: relDef.through,\n\t\t\t\tresolved: false,\n\t\t\t};\n\t\t\tentity.relationships.set(name, relationship);\n\t\t}\n\t}\n\n\t// Parse sync configuration\n\tif (definition.sync) {\n\t\tconst syncDef = definition.sync;\n\t\tconst parsedSync: ParsedSync = {\n\t\t\telectric: syncDef.electric ?? false,\n\t\t};\n\n\t\tif (syncDef.providers) {\n\t\t\tparsedSync.providers = {};\n\t\t\tfor (const [providerName, providerDef] of Object.entries(syncDef.providers)) {\n\t\t\t\tconst parsedProvider: ParsedProviderSync = {\n\t\t\t\t\tremoteEntity: providerDef.remote_entity,\n\t\t\t\t\tdirection: providerDef.direction,\n\t\t\t\t\tcdc: providerDef.cdc ?? false,\n\t\t\t\t};\n\t\t\t\tif (providerDef.field_mapping) {\n\t\t\t\t\tparsedProvider.fieldMapping = providerDef.field_mapping;\n\t\t\t\t}\n\t\t\t\tif (providerDef.read_only_fields) {\n\t\t\t\t\tparsedProvider.readOnlyFields = providerDef.read_only_fields;\n\t\t\t\t}\n\t\t\t\tparsedSync.providers[providerName] = parsedProvider;\n\t\t\t}\n\t\t}\n\n\t\tentity.sync = parsedSync;\n\t}\n\n\t// Parse events\n\tif (definition.events) {\n\t\tentity.events = definition.events.map((ev): ParsedEvent => ({\n\t\t\tname: ev.name,\n\t\t\tqueue: ev.queue,\n\t\t\tbody: ev.body,\n\t\t\tgenerateHandler: ev.generate_handler,\n\t\t}));\n\t}\n\n\t// Parse emits (EVT-7). Preserve `undefined` vs `[]` distinction — the\n\t// validator treats absence as a warning and explicit empty as opt-out.\n\tif (definition.emits !== undefined) {\n\t\tentity.emits = definition.emits;\n\t}\n\n\treturn entity;\n}\n\n/**\n * Parse a foreign key string (e.g., \"accounts.id\") into table and column\n */\nfunction parseForeignKey(fk: string): { table: string; column: string } {\n\tconst [table, column] = fk.split('.');\n\treturn { table, column: column ?? 'id' };\n}\n\n/**\n * Convert a load error to an analysis issue\n */\nfunction loadErrorToIssue(error: LoadError): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tissues.push({\n\t\tseverity: 'error',\n\t\ttype: 'parse_error',\n\t\tmessage: error.error,\n\t\tpath: error.filePath,\n\t});\n\n\tif (error.details) {\n\t\tfor (const detail of error.details) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'schema_error',\n\t\t\t\tmessage: detail,\n\t\t\t\tpath: error.filePath,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Load all entity YAML files from a directory\n */\nexport function loadEntities(entitiesDir: string): LoadEntitiesResult {\n\tconst entities: ParsedEntity[] = [];\n\tconst issues: AnalysisIssue[] = [];\n\n\tconst resolvedDir = resolve(entitiesDir);\n\n\t// Get all YAML files\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(resolvedDir)\n\t\t\t.filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'))\n\t\t\t.map((f) => join(resolvedDir, f));\n\t} catch (err) {\n\t\tissues.push({\n\t\t\tseverity: 'error',\n\t\t\ttype: 'parse_error',\n\t\t\tmessage: `Failed to read directory: ${resolvedDir}`,\n\t\t\tpath: resolvedDir,\n\t\t});\n\t\treturn { entities, issues };\n\t}\n\n\tif (files.length === 0) {\n\t\tissues.push({\n\t\t\tseverity: 'warning',\n\t\t\ttype: 'no_files',\n\t\t\tmessage: `No YAML files found in directory: ${resolvedDir}`,\n\t\t\tpath: resolvedDir,\n\t\t});\n\t\treturn { entities, issues };\n\t}\n\n\t// Load each file\n\tfor (const filePath of files) {\n\t\tconst result = loadEntityFromYaml(filePath);\n\n\t\tif (result.success) {\n\t\t\tentities.push(transformToEntity(result));\n\t\t} else {\n\t\t\tissues.push(...loadErrorToIssue(result));\n\t\t}\n\t}\n\n\treturn { entities, issues };\n}\n\n/**\n * Resolve cross-entity references\n */\nexport function resolveReferences(entities: ParsedEntity[]): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst entityMap = new Map<string, ParsedEntity>();\n\n\t// Build entity map by name\n\tfor (const entity of entities) {\n\t\tif (entityMap.has(entity.name)) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'duplicate_entity',\n\t\t\t\tentity: entity.name,\n\t\t\t\tmessage: `Duplicate entity name: ${entity.name}`,\n\t\t\t\tpath: entity.sourcePath,\n\t\t\t});\n\t\t}\n\t\tentityMap.set(entity.name, entity);\n\t}\n\n\t// Resolve relationships\n\tfor (const entity of entities) {\n\t\tfor (const [relName, rel] of entity.relationships) {\n\t\t\tconst targetEntity = entityMap.get(rel.target);\n\t\t\tif (targetEntity) {\n\t\t\t\trel.resolved = true;\n\t\t\t} else {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'missing_target',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: relName,\n\t\t\t\t\tmessage: `Relationship '${relName}' references unknown entity '${rel.target}'`,\n\t\t\t\t\tpath: entity.sourcePath,\n\t\t\t\t\tsuggestion: `Define entity '${rel.target}' or fix the target name`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Check foreign key references\n\t\tfor (const [fieldName, field] of entity.fields) {\n\t\t\tif (field.foreignKey) {\n\t\t\t\tconst targetTable = field.foreignKey.table;\n\t\t\t\tconst targetEntity = Array.from(entityMap.values()).find(\n\t\t\t\t\t(e) => e.table === targetTable\n\t\t\t\t);\n\t\t\t\tif (!targetEntity) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\t\ttype: 'missing_fk_target',\n\t\t\t\t\t\tentity: entity.name,\n\t\t\t\t\t\tfield: fieldName,\n\t\t\t\t\t\tmessage: `Foreign key references unknown table '${targetTable}'`,\n\t\t\t\t\t\tpath: entity.sourcePath,\n\t\t\t\t\t\tsuggestion: `Define entity with table '${targetTable}' or fix the foreign_key reference`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n// ============================================================================\n// Relationship Loading\n// ============================================================================\n\nexport interface LoadRelationshipsResult {\n\trelationships: ParsedRelationshipDefinition[];\n\tissues: AnalysisIssue[];\n}\n\n/**\n * Transform a loaded relationship definition into a ParsedRelationshipDefinition.\n *\n * This resolves all auto-generated fields: FK columns, type directions,\n * temporal/sourced fields, unique constraints.\n */\nfunction transformToRelationshipDefinition(\n\tresult: RelationshipLoadResult,\n): ParsedRelationshipDefinition {\n\tconst { definition, filePath } = result;\n\tconst config = definition.relationship;\n\n\tconst { fromColumn, toColumn } = deriveRelationshipFKColumns(config);\n\tconst table = deriveTableName(config);\n\tconst uniqueOn = deriveUniqueConstraint(config);\n\n\t// Resolve type directions\n\tconst types = resolveTypeDirections(config.types);\n\n\t// Parse custom fields\n\tconst fields = new Map<string, ParsedField>();\n\tif (definition.fields) {\n\t\tfor (const [name, fieldDef] of Object.entries(definition.fields)) {\n\t\t\tconst field: ParsedField = {\n\t\t\t\tname,\n\t\t\t\ttype: fieldDef.type,\n\t\t\t\trequired: fieldDef.required ?? false,\n\t\t\t\tnullable: fieldDef.nullable ?? false,\n\t\t\t\tunique: fieldDef.unique ?? false,\n\t\t\t\tindex: fieldDef.index ?? false,\n\t\t\t\tforeignKey: fieldDef.foreign_key\n\t\t\t\t\t? parseForeignKey(fieldDef.foreign_key)\n\t\t\t\t\t: undefined,\n\t\t\t\tchoices: fieldDef.choices,\n\t\t\t\tconstraints: {\n\t\t\t\t\tminLength: fieldDef.min_length,\n\t\t\t\t\tmaxLength: fieldDef.max_length,\n\t\t\t\t\tmin: fieldDef.min,\n\t\t\t\t\tmax: fieldDef.max,\n\t\t\t\t},\n\t\t\t\tui: {\n\t\t\t\t\tlabel: fieldDef.ui_label,\n\t\t\t\t\ttype: fieldDef.ui_type,\n\t\t\t\t\timportance: fieldDef.ui_importance,\n\t\t\t\t\tgroup: fieldDef.ui_group,\n\t\t\t\t\tsortable: fieldDef.ui_sortable,\n\t\t\t\t\tfilterable: fieldDef.ui_filterable,\n\t\t\t\t\tvisible: fieldDef.ui_visible,\n\t\t\t\t},\n\t\t\t};\n\t\t\tfields.set(name, field);\n\t\t}\n\t}\n\n\t// Parse queries\n\t// Relationship queries here: same filtering rationale as entity queries.\n\tconst queries: ParsedQuery[] | undefined = definition.queries\n\t\t?.filter((q): q is Extract<typeof q, { by: unknown }> => 'by' in q)\n\t\t.map((q) => ({\n\t\t\tby: q.by,\n\t\t\tunique: q.unique,\n\t\t\tselect: q.select,\n\t\t\torder: q.order,\n\t\t\tlimit: q.limit,\n\t\t}));\n\n\treturn {\n\t\tname: config.name,\n\t\ttable,\n\t\tfrom: config.from,\n\t\tto: config.to,\n\t\tselfReferential: config.from === config.to,\n\t\tfromColumn,\n\t\ttoColumn,\n\t\ttypes,\n\t\thasTypes: types.length > 0,\n\t\ttemporal: config.temporal,\n\t\tsourced: config.sourced,\n\t\tonDeleteFrom: config.on_delete_from ?? 'restrict',\n\t\tonDeleteTo: config.on_delete_to ?? 'restrict',\n\t\tuniqueOn,\n\t\tfields,\n\t\tqueries,\n\t\tsourcePath: filePath,\n\t};\n}\n\n/**\n * Resolve type directions from the YAML types: block.\n *\n * Simple list → all directed, no inverses.\n * Object map → each type has explicit direction metadata.\n */\nfunction resolveTypeDirections(\n\ttypes: RelationshipTypes | undefined,\n): ParsedTypeDirection[] {\n\tif (!types) return [];\n\n\tif (Array.isArray(types)) {\n\t\t// Simple list: all directed from→to\n\t\treturn types.map((name) => ({\n\t\t\tname,\n\t\t\tbidirectional: false,\n\t\t\tdirected: true,\n\t\t}));\n\t}\n\n\t// Object map: resolve each type's direction\n\treturn Object.entries(types).map(([name, dir]) => {\n\t\tconst direction = dir as { inverse?: string; bidirectional?: boolean; directed?: boolean };\n\t\treturn {\n\t\t\tname,\n\t\t\tinverse: direction.inverse,\n\t\t\tbidirectional: direction.bidirectional ?? false,\n\t\t\tdirected: direction.directed ?? (!direction.bidirectional && !direction.inverse),\n\t\t};\n\t});\n}\n\n/**\n * Load all relationship YAML files from a directory\n */\nexport function loadRelationships(\n\trelationshipsDir: string,\n): LoadRelationshipsResult {\n\tconst relationships: ParsedRelationshipDefinition[] = [];\n\tconst issues: AnalysisIssue[] = [];\n\n\tconst resolvedDir = resolve(relationshipsDir);\n\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(resolvedDir)\n\t\t\t.filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'))\n\t\t\t.map((f) => join(resolvedDir, f));\n\t} catch {\n\t\t// Directory doesn't exist — not an error, relationships are optional\n\t\treturn { relationships, issues };\n\t}\n\n\tif (files.length === 0) {\n\t\treturn { relationships, issues };\n\t}\n\n\tfor (const filePath of files) {\n\t\tconst result = loadRelationshipFromYaml(filePath);\n\n\t\tif (result.success) {\n\t\t\trelationships.push(transformToRelationshipDefinition(result));\n\t\t} else {\n\t\t\tissues.push(...loadErrorToIssue(result as unknown as LoadError));\n\t\t}\n\t}\n\n\treturn { relationships, issues };\n}\n\n/**\n * Resolve cross-references between relationship definitions and entities.\n * Validates that from/to entities exist.\n */\nexport function resolveRelationshipReferences(\n\trelationshipDefs: ParsedRelationshipDefinition[],\n\tentities: ParsedEntity[],\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst entityNames = new Set(entities.map((e) => e.name));\n\n\tfor (const relDef of relationshipDefs) {\n\t\tif (!entityNames.has(relDef.from)) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'missing_relationship_endpoint',\n\t\t\t\tentity: relDef.name,\n\t\t\t\tmessage: `Relationship '${relDef.name}' references unknown 'from' entity '${relDef.from}'`,\n\t\t\t\tpath: relDef.sourcePath,\n\t\t\t\tsuggestion: `Define entity '${relDef.from}' or fix the 'from' value`,\n\t\t\t});\n\t\t}\n\n\t\tif (!entityNames.has(relDef.to)) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'missing_relationship_endpoint',\n\t\t\t\tentity: relDef.name,\n\t\t\t\tmessage: `Relationship '${relDef.name}' references unknown 'to' entity '${relDef.to}'`,\n\t\t\t\tpath: relDef.sourcePath,\n\t\t\t\tsuggestion: `Define entity '${relDef.to}' or fix the 'to' value`,\n\t\t\t});\n\t\t}\n\n\t\t// Check for duplicate relationship names\n\t\tconst dupes = relationshipDefs.filter((r) => r.name === relDef.name);\n\t\tif (dupes.length > 1) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'duplicate_relationship',\n\t\t\t\tentity: relDef.name,\n\t\t\t\tmessage: `Duplicate relationship name: ${relDef.name}`,\n\t\t\t\tpath: relDef.sourcePath,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\nexport { loadEntityFromYaml } from '../utils/yaml-loader';\nexport { loadRelationshipFromYaml } from '../utils/yaml-loader';\n","import { readFileSync, existsSync } from 'node:fs';\nimport { parse as parseYaml } from 'yaml';\nimport { ZodError } from 'zod';\nimport {\n\ttype EntityDefinition,\n\tEntityDefinitionSchema,\n} from '../schema/entity-definition.schema';\nimport {\n\ttype EventDefinition,\n\tEventDefinitionSchema,\n} from '../schema/event-definition.schema';\nimport {\n\ttype RelationshipDefinition,\n\tRelationshipDefinitionSchema,\n} from '../schema/relationship-definition.schema';\n\nexport interface LoadResult {\n\tsuccess: true;\n\tdefinition: EntityDefinition;\n\tfilePath: string;\n}\n\nexport interface LoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadEntityResult = LoadResult | LoadError;\n\n/**\n * Load and validate an entity definition from a YAML file\n */\nexport function loadEntityFromYaml(filePath: string): LoadEntityResult {\n\t// Check file exists\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\t// Read file\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\t// Parse YAML\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\t// Validate against schema\n\tconst result = EntityDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n/**\n * Format Zod errors into human-readable messages\n */\nfunction formatZodErrors(error: ZodError): string[] {\n\treturn error.errors.map((err) => {\n\t\tconst path = err.path.join('.');\n\t\tconst location = path ? `at '${path}'` : 'at root';\n\t\treturn `${err.message} ${location}`;\n\t});\n}\n\n/**\n * Pretty-print a load error for CLI output\n */\nexport function formatLoadError(result: LoadError): string {\n\tconst lines = [`❌ ${result.error}`];\n\tif (result.details && result.details.length > 0) {\n\t\tlines.push('');\n\t\tfor (const detail of result.details) {\n\t\t\tlines.push(` • ${detail}`);\n\t\t}\n\t}\n\treturn lines.join('\\n');\n}\n\n/**\n * Load multiple entity files\n */\nexport function loadEntitiesFromYaml(filePaths: string[]): {\n\tsuccesses: LoadResult[];\n\tfailures: LoadError[];\n} {\n\tconst successes: LoadResult[] = [];\n\tconst failures: LoadError[] = [];\n\n\tfor (const filePath of filePaths) {\n\t\tconst result = loadEntityFromYaml(filePath);\n\t\tif (result.success) {\n\t\t\tsuccesses.push(result);\n\t\t} else {\n\t\t\tfailures.push(result);\n\t\t}\n\t}\n\n\treturn { successes, failures };\n}\n\n// ============================================================================\n// Relationship YAML Loading\n// ============================================================================\n\nexport interface RelationshipLoadResult {\n\tsuccess: true;\n\tdefinition: RelationshipDefinition;\n\tfilePath: string;\n}\n\nexport interface RelationshipLoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadRelationshipResult =\n\t| RelationshipLoadResult\n\t| RelationshipLoadError;\n\n/**\n * Load and validate a relationship definition from a YAML file\n */\nexport function loadRelationshipFromYaml(\n\tfilePath: string,\n): LoadRelationshipResult {\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tconst result = RelationshipDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n/**\n * Load multiple relationship files\n */\nexport function loadRelationshipsFromYaml(filePaths: string[]): {\n\tsuccesses: RelationshipLoadResult[];\n\tfailures: RelationshipLoadError[];\n} {\n\tconst successes: RelationshipLoadResult[] = [];\n\tconst failures: RelationshipLoadError[] = [];\n\n\tfor (const filePath of filePaths) {\n\t\tconst result = loadRelationshipFromYaml(filePath);\n\t\tif (result.success) {\n\t\t\tsuccesses.push(result);\n\t\t} else {\n\t\t\tfailures.push(result);\n\t\t}\n\t}\n\n\treturn { successes, failures };\n}\n\n// ============================================================================\n// Event YAML Loading\n// ============================================================================\n\nexport interface EventLoadResult {\n\tsuccess: true;\n\tdefinition: EventDefinition;\n\tfilePath: string;\n}\n\nexport interface EventLoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadEventResult = EventLoadResult | EventLoadError;\n\n/**\n * Load and validate a single event definition from a YAML file.\n *\n * Mirrors {@link loadEntityFromYaml}: existence check → readFileSync →\n * parseYaml → `EventDefinitionSchema.safeParse`. Returns a discriminated\n * result; callers are expected to aggregate into `AnalysisIssue`s rather\n * than throw.\n */\nexport function loadEventFromYaml(filePath: string): LoadEventResult {\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tconst result = EventDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n/**\n * Detect whether a YAML file is an entity or relationship definition.\n * Checks for the top-level discriminator key.\n */\nexport function detectYamlType(\n\tfilePath: string,\n): 'entity' | 'relationship' | 'unknown' {\n\tif (!existsSync(filePath)) return 'unknown';\n\n\ttry {\n\t\tconst content = readFileSync(filePath, 'utf-8');\n\t\tconst parsed = parseYaml(content) as Record<string, unknown>;\n\t\tif (parsed && typeof parsed === 'object') {\n\t\t\tif ('entity' in parsed) return 'entity';\n\t\t\tif ('relationship' in parsed) return 'relationship';\n\t\t}\n\t} catch {\n\t\t// Fall through\n\t}\n\treturn 'unknown';\n}\n","import { z } from \"zod\";\n\n/**\n * Entity Definition Schema\n *\n * Generates backend code:\n * - Domain entity + repository interface\n * - Application DTOs, use-cases, queries\n * - Infrastructure Drizzle schema + repository\n * - Presentation controller\n * - NestJS module wiring\n * - Shared Zod schema in packages/db\n *\n * Generates frontend code:\n * - Entity metadata for automatic admin panels\n * - UI type, importance, grouping for fields\n */\n\n// ============================================================================\n// Field Types\n// ============================================================================\n\nconst FieldTypeSchema = z.enum([\n \"string\",\n \"integer\",\n \"decimal\",\n \"boolean\",\n \"uuid\",\n \"date\",\n \"datetime\",\n \"json\",\n \"entity_ref\", // Polymorphic reference: generates {field}EntityType + {field}EntityId columns\n \"string_array\", // Array of strings: generates text[] column\n \"enum\", // Enum type with choices or choices_from\n]);\n\nexport type FieldType = z.infer<typeof FieldTypeSchema>;\n\n// ============================================================================\n// UI Metadata Types\n// ============================================================================\n\nconst UiTypeSchema = z.enum([\n \"text\",\n \"textarea\",\n \"number\",\n \"money\",\n \"percentage\",\n \"email\",\n \"url\",\n \"date\",\n \"datetime\",\n \"boolean\",\n \"enum\",\n \"reference\",\n \"json\",\n \"badge\",\n \"password\",\n]);\n\nexport type UiType = z.infer<typeof UiTypeSchema>;\n\nconst UiImportanceSchema = z.enum([\"primary\", \"secondary\", \"tertiary\"]);\n\nexport type UiImportance = z.infer<typeof UiImportanceSchema>;\n\n/**\n * UI Metadata Schema - Optional field-level UI properties\n *\n * All properties are optional and will be inferred at generation time\n * if not explicitly specified in the YAML definition.\n */\n// ============================================================================\n// Semantic / Analytics Metadata Types\n// ============================================================================\n\nconst AnalyticsAggregationSchema = z.enum([\n 'sum',\n 'min',\n 'max',\n 'count',\n 'count_distinct',\n 'average',\n 'median',\n 'percentile',\n 'sum_boolean',\n]);\n\nconst AnalyticsDimensionTypeSchema = z.enum(['categorical', 'time']);\n\nconst AnalyticsEntityTypeSchema = z.enum(['primary', 'unique', 'foreign', 'natural']);\n\nconst AnalyticsTimeGranularitySchema = z.enum(['day', 'week', 'month', 'quarter', 'year']);\n\nconst AnalyticsVisibilitySchema = z.enum(['internal', 'agent', 'public']);\n\nconst NonAdditiveDimensionSchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n window_choice: z.string().optional(),\n window_groupings: z.array(z.string()).optional(),\n }),\n]);\n\n/**\n * Semantic Metadata Schema - Optional field-level analytics properties\n *\n * Controls how a field is exposed to the cube.js semantic layer:\n * measures, dimensions, entities, and their configuration.\n */\nconst SemanticMetadataSchema = z.object({\n measure: z.boolean().optional(),\n analytics_aggregation: AnalyticsAggregationSchema.optional(),\n agg_time_dimension: z.string().optional(),\n non_additive_dimension: NonAdditiveDimensionSchema.optional(),\n dimension: z.boolean().optional(),\n dimension_type: AnalyticsDimensionTypeSchema.optional(),\n time_granularity: AnalyticsTimeGranularitySchema.optional(),\n is_partition: z.boolean().optional(),\n entity: z.boolean().optional(),\n entity_type: AnalyticsEntityTypeSchema.optional(),\n entity_role: z.string().optional(),\n analytics_visibility: AnalyticsVisibilitySchema.optional(),\n semantic_expr: z.string().optional(),\n semantic_label: z.string().optional(),\n});\n\nconst UiMetadataSchema = z.object({\n ui_label: z.string().optional(),\n ui_type: UiTypeSchema.optional(),\n ui_importance: UiImportanceSchema.optional(),\n ui_group: z.string().optional(),\n ui_sortable: z.boolean().optional(),\n ui_filterable: z.boolean().optional(),\n ui_visible: z.boolean().optional(),\n ui_placeholder: z.string().optional(),\n ui_help: z.string().optional(),\n ui_format: z.record(z.unknown()).optional(),\n});\n\n// ============================================================================\n// Field Definition\n// ============================================================================\n\n/**\n * Field Definition Schema\n *\n * Semantics:\n * - `required: true` → Field must be provided on CREATE (DTO validation)\n * - `required: false` → Field is optional on CREATE (DTO validation)\n * - `nullable: true` → Database column allows NULL\n * - `nullable: false` (default) → Database column is NOT NULL\n *\n * Common patterns:\n * - `required: true` (nullable defaults to false) → Must provide, cannot be null\n * - `required: false, nullable: true` → Optional field, can be null\n * - `required: true, nullable: true` → INVALID (rejected by validator)\n * - `required: false, nullable: false` → Has default value in DB\n */\n/**\n * Base Field Schema - Core database/type properties\n */\nconst BaseFieldSchema = z.object({\n type: FieldTypeSchema,\n required: z.boolean().optional().default(false),\n nullable: z.boolean().optional().default(false),\n\n // String constraints\n max_length: z.number().int().positive().optional(),\n min_length: z.number().int().nonnegative().optional(),\n\n // Numeric constraints\n min: z.number().optional(),\n max: z.number().optional(),\n\n // Enum/choices (inline definition)\n choices: z.array(z.string()).optional(),\n\n // Enum/choices from external file (e.g., \"relationship_types.yaml\")\n // Mutually exclusive with choices - parser loads file and extracts keys\n choices_from: z.string().optional(),\n\n // Entity reference: allowed entity types for polymorphic refs\n // Required when type is 'entity_ref'\n allowed_types: z.array(z.string()).optional(),\n\n // Default value\n default: z.unknown().optional(),\n\n // Indexing\n index: z.boolean().optional(),\n unique: z.boolean().optional(),\n\n // Foreign key reference (e.g., \"accounts.id\")\n foreign_key: z.string().optional(),\n});\n\n/**\n * Field Definition Schema - Combines base fields with optional UI metadata\n */\nconst FieldDefinitionSchema = BaseFieldSchema.merge(UiMetadataSchema).merge(SemanticMetadataSchema)\n .refine((data) => !(data.required === true && data.nullable === true), {\n message:\n \"'required: true' and 'nullable: true' cannot both be set. A required field cannot be null.\",\n path: [\"required\"],\n })\n .refine(\n (data) => {\n if (data.min_length !== undefined && data.type !== \"string\") {\n return false;\n }\n return true;\n },\n {\n message: \"'min_length' can only be used with type 'string'\",\n path: [\"min_length\"],\n },\n )\n .refine(\n (data) => {\n if (data.max_length !== undefined && data.type !== \"string\") {\n return false;\n }\n return true;\n },\n {\n message: \"'max_length' can only be used with type 'string'\",\n path: [\"max_length\"],\n },\n )\n .refine(\n (data) => {\n if (\n data.min !== undefined &&\n ![\"integer\", \"decimal\"].includes(data.type)\n ) {\n return false;\n }\n return true;\n },\n {\n message: \"'min' can only be used with numeric types\",\n path: [\"min\"],\n },\n )\n .refine(\n (data) => {\n if (\n data.max !== undefined &&\n ![\"integer\", \"decimal\"].includes(data.type)\n ) {\n return false;\n }\n return true;\n },\n {\n message: \"'max' can only be used with numeric types\",\n path: [\"max\"],\n },\n )\n .refine(\n (data) => {\n // entity_ref requires allowed_types\n if (data.type === \"entity_ref\" && !data.allowed_types?.length) {\n return false;\n }\n return true;\n },\n {\n message: \"'entity_ref' type requires 'allowed_types' to be specified\",\n path: [\"allowed_types\"],\n },\n )\n .refine(\n (data) => {\n // allowed_types only valid for entity_ref\n if (data.allowed_types !== undefined && data.type !== \"entity_ref\") {\n return false;\n }\n return true;\n },\n {\n message: \"'allowed_types' can only be used with type 'entity_ref'\",\n path: [\"allowed_types\"],\n },\n )\n .refine(\n (data) => {\n // choices and choices_from are mutually exclusive\n if (data.choices !== undefined && data.choices_from !== undefined) {\n return false;\n }\n return true;\n },\n {\n message: \"'choices' and 'choices_from' cannot both be specified\",\n path: [\"choices_from\"],\n },\n )\n .refine(\n (data) => {\n // enum type requires either choices or choices_from\n if (data.type === \"enum\" && !data.choices?.length && !data.choices_from) {\n return false;\n }\n return true;\n },\n {\n message: \"'enum' type requires either 'choices' or 'choices_from'\",\n path: [\"choices\"],\n },\n )\n .refine(\n (data) => {\n // If measure is true, analytics_aggregation must be present\n if (data.measure === true && !data.analytics_aggregation) {\n return false;\n }\n return true;\n },\n {\n message:\n \"When 'measure' is true, 'analytics_aggregation' must be specified\",\n path: [\"analytics_aggregation\"],\n },\n );\n\nexport type FieldDefinition = z.infer<typeof FieldDefinitionSchema>;\n\n// ============================================================================\n// Relationship Definition\n// ============================================================================\n\nconst RelationshipTypeSchema = z.enum([\"belongs_to\", \"has_many\", \"has_one\"]);\n\n/**\n * on_delete — governs database-level FK cascade behaviour for hard-deletes.\n *\n * Applies only to belongs_to relations; ignored on has_many / has_one.\n * Per ADR-021, this has NO effect under soft-delete: BaseService.delete()\n * issues an UPDATE (sets deleted_at), never a DELETE, so Postgres cascade\n * rules never fire for a soft-deleted parent.\n *\n * | Value | Emitted Drizzle | Postgres behaviour |\n * |-------------|------------------------------|---------------------------------------|\n * | restrict | { onDelete: 'restrict' } | Parent DELETE fails if children exist. DEFAULT. |\n * | cascade | { onDelete: 'cascade' } | Parent DELETE removes children. |\n * | set_null | { onDelete: 'set null' } | Parent DELETE nulls FK on children. Requires nullable: true. |\n * | no_action | { onDelete: 'no action' } | Deferred check (equivalent to restrict in single-statement txns). |\n *\n * See docs/adrs/ADR-021-on-delete-semantics.md for the full decision.\n */\nexport const OnDeleteSchema = z.enum([\"restrict\", \"cascade\", \"set_null\", \"no_action\"]);\n\nexport type OnDelete = z.infer<typeof OnDeleteSchema>;\n\nconst RelationshipSchema = z\n .object({\n type: RelationshipTypeSchema,\n target: z.string(), // Target entity name (e.g., \"account\")\n foreign_key: z.string(), // FK field name (e.g., \"account_id\")\n through: z.string().optional(), // For transitive: \"owned_opportunities.updates\"\n inverse: z.string().optional(), // Name of inverse relationship on target entity\n nullable: z.boolean().optional(), // Whether the FK column allows NULL\n on_delete: OnDeleteSchema.optional().default(\"restrict\"), // FK cascade action (belongs_to only; hard-delete only)\n })\n .strict()\n .refine(\n (data) => {\n // set_null requires nullable: true — Postgres cannot null a NOT NULL column\n if (data.on_delete === \"set_null\" && data.nullable !== true) {\n return false;\n }\n return true;\n },\n {\n message:\n \"'on_delete: set_null' requires 'nullable: true' — Postgres cannot null a NOT NULL FK column.\",\n path: [\"on_delete\"],\n },\n );\n\nexport type Relationship = z.infer<typeof RelationshipSchema>;\n\n// ============================================================================\n// Behavior Configuration\n// ============================================================================\n\n/**\n * Behavior configuration can be:\n * - A simple string: \"timestamps\"\n * - An object with options: { name: \"sluggable\", options: { source: \"title\" } }\n *\n * Built-in behaviors:\n * - timestamps: Adds created_at, updated_at fields\n * - soft_delete: Adds deleted_at field, filters deleted records\n * - user_tracking: Adds created_by, updated_by fields\n * - temporal_validity: Adds valid_from, valid_to, is_active fields\n * with deactivate() method and validity-aware query filtering\n */\nconst BehaviorConfigSchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n options: z.record(z.unknown()).optional(),\n }),\n]);\n\nexport type BehaviorConfig = z.infer<typeof BehaviorConfigSchema>;\n\n/**\n * Behavior strategy for repository code generation\n * - base_class: Extend BaseRepository (DRY, recommended)\n * - inline: Generate all code directly (WET, full transparency)\n */\nconst BehaviorStrategySchema = z.enum([\"base_class\", \"inline\"]);\n\nexport type BehaviorStrategy = z.infer<typeof BehaviorStrategySchema>;\n\n// ============================================================================\n// Entity Configuration\n// ============================================================================\n\n/**\n * Layout: Folder structure - controls directory nesting\n * - nested: domain/opportunity/opportunity.entity.ts\n * - flat: domain/opportunity.entity.ts\n */\nconst FolderStructureSchema = z.enum([\"nested\", \"flat\"]).default(\"nested\");\n\n/**\n * Layout: File grouping - controls how related code is organized\n * - separate: Each concern in its own file (entity.ts, repository.interface.ts)\n * - grouped: Related concerns combined into index.ts\n *\n * This is orthogonal to folder_structure:\n * | folder_structure | file_grouping | Result |\n * |-----------------|---------------|--------|\n * | nested | separate | domain/opportunity/opportunity.entity.ts |\n * | nested | grouped | domain/opportunity/index.ts (combined) |\n * | flat | separate | domain/opportunity.entity.ts |\n * | flat | grouped | domain/opportunity.ts (combined) |\n */\nconst FileGroupingSchema = z.enum([\"separate\", \"grouped\"]).default(\"separate\");\n\n/**\n * Expose configuration - which layers to generate for this entity\n * - repository: Always generated (domain entity, repository interface/impl)\n * - rest: Generate REST controller\n * - trpc: Generate tRPC module\n * - electric: Generate Electric SQL migration (REPLICA IDENTITY + publication)\n *\n * Default: ['repository', 'rest', 'trpc'] (all layers)\n */\nconst ExposeLayerSchema = z.enum([\"repository\", \"rest\", \"trpc\", \"electric\"]);\nexport type ExposeLayer = z.infer<typeof ExposeLayerSchema>;\n\nconst EntityConfigSchema = z\n .object({\n name: z\n .string()\n .regex(\n /^[a-z][a-z0-9_]*$/,\n \"Entity name must be lowercase with underscores (e.g., 'opportunity')\",\n ),\n plural: z.string().regex(/^[a-z][a-z0-9_]*$/, \"Plural must be lowercase\"),\n table: z.string().regex(/^[a-z][a-z0-9_]*$/, \"Table must be lowercase\"),\n\n // Layout options (orthogonal concerns)\n // folder_structure: controls directory nesting\n // file_grouping: controls file organization\n folder_structure: FolderStructureSchema.optional(),\n file_grouping: FileGroupingSchema.optional(),\n\n // Per-entity behavior strategy override (overrides codegen.config.yaml)\n behavior_strategy: BehaviorStrategySchema.optional(),\n // Which layers to generate (default: all)\n expose: z\n .array(ExposeLayerSchema)\n .optional()\n .default([\"repository\", \"rest\", \"trpc\"]),\n\n // App-defined patterns (ADR-031, supersedes ADR-005 family:).\n // `pattern:` and `patterns:` are mutually exclusive — use `pattern:`\n // for a single pattern and `patterns:` for multi-pattern composition.\n // Pattern names resolve against the registry at codegen time.\n pattern: z.string().optional(),\n patterns: z.array(z.string()).optional(),\n // Per-pattern config, keyed by pattern name. Each value is validated\n // against the pattern's `configSchema` in composition validation\n // (src/patterns/validate-composition.ts — PATTERN-4).\n config: z.record(z.string(), z.unknown()).optional(),\n\n // JOB-7: marks this entity as a valid scope target for job scoping.\n // Drives the generated ScopeEntityType union in\n // runtime/subsystems/jobs/generated/scope-entity-type.ts.\n scopeable: z.boolean().optional(),\n })\n .strict()\n .refine((d) => !(d.pattern && d.patterns), {\n message: \"'pattern' and 'patterns' are mutually exclusive\",\n });\n\nexport type EntityConfig = z.infer<typeof EntityConfigSchema>;\n\n// ============================================================================\n// Query Declaration\n// ============================================================================\n\n/**\n * Query Declaration Schema - Declarative query generation (ADR-005)\n *\n * Each declaration generates repository + service + use case methods.\n *\n * Examples:\n * { by: [\"user_id\"] }\n * { by: [\"email\"], unique: true }\n * { by: [\"account_id\"], order: \"created_at desc\", limit: true }\n * { by: [\"opportunity_id\"], select: [\"email\"], via: \"opportunity_contact_link\" }\n */\nconst QueryDeclarationSchema = z.object({\n by: z.array(z.string()).min(1),\n unique: z.boolean().optional(),\n select: z.array(z.string()).optional(),\n order: z.string().optional(),\n limit: z.boolean().optional(),\n via: z.string().optional(),\n});\n\nexport type QueryDeclaration = z.infer<typeof QueryDeclarationSchema>;\n\n/**\n * Search Query Declaration — filtered search with pagination.\n *\n * Emits:\n * - `searchXs(input): Promise<Page<Entity>>` on the service\n * - `GET /xs/search` controller route with Zod filter schema\n * - `SearchXsUseCase` with filter-AND + count-for-total semantics\n *\n * Example:\n * - name: search\n * filters: [user_id, provider, is_visible, canonical_state, is_closed]\n * search: name # optional ilike on a single text column\n * paginate: true # defaults to limit 50, max 200, offset 0\n *\n * Consumer contract: `@shared/http/pagination` must export\n * `PaginationSchema` (z.object with limit+offset defaults) and a\n * `Page<T>` interface with `{ items, total, limit, offset }`.\n */\nconst SearchQueryDeclarationSchema = z.object({\n name: z.literal('search'),\n filters: z.array(z.string()).min(1),\n search: z.string().optional(),\n paginate: z.boolean().optional().default(true),\n order: z.string().optional(),\n});\n\nexport type SearchQueryDeclaration = z.infer<typeof SearchQueryDeclarationSchema>;\n\n/**\n * Discriminated union: query declarations can be either the legacy\n * by-column findByX form or the named-search form. The two shapes are\n * disjoint (no `name` vs required `name: 'search'`), so consumers can\n * mix them in the same `queries:` block.\n */\nconst AnyQueryDeclarationSchema = z.union([\n SearchQueryDeclarationSchema,\n QueryDeclarationSchema,\n]);\n\n// ============================================================================\n// Sync Configuration\n// ============================================================================\n\n/**\n * Direction of sync with an external provider\n */\nexport const SyncDirectionSchema = z.enum([\n 'inbound',\n 'outbound',\n 'bidirectional',\n]);\n\nexport type SyncDirection = z.infer<typeof SyncDirectionSchema>;\n\n/**\n * Per-provider sync configuration\n */\nexport const ProviderSyncSchema = z.object({\n remote_entity: z.string(),\n direction: SyncDirectionSchema,\n cdc: z.boolean().optional().default(false),\n field_mapping: z.record(z.string(), z.string()).optional(),\n read_only_fields: z.array(z.string()).optional(),\n});\n\nexport type ProviderSync = z.infer<typeof ProviderSyncSchema>;\n\n/**\n * Top-level sync block: Electric SQL + named provider configs\n */\nexport const SyncConfigSchema = z.object({\n electric: z.boolean().optional().default(false),\n providers: z.record(z.string(), ProviderSyncSchema).optional(),\n});\n\nexport type SyncConfig = z.infer<typeof SyncConfigSchema>;\n\n// ============================================================================\n// Event Declaration\n// ============================================================================\n\n/**\n * Event Declaration Schema - Domain event declarations (CODEGEN-EVOLUTION-PLAN Phase 2)\n *\n * Each declaration generates typed event classes, handlers, and queue registration.\n *\n * Example:\n * name: opportunity_stage_changed\n * queue: domain-events\n * body:\n * opportunity_id: uuid\n * old_stage: string\n * generate_handler: true\n */\nconst EventDeclarationSchema = z.object({\n name: z\n .string()\n .regex(/^[a-z][a-z0-9_]*$/, \"Event name must be snake_case\"),\n queue: z.string(),\n body: z.record(z.string(), z.string()),\n generate_handler: z.boolean().optional().default(false),\n});\n\nexport type EventDeclaration = z.infer<typeof EventDeclarationSchema>;\n\n// ============================================================================\n// Analytics Block (entity-level)\n// ============================================================================\n\n/**\n * Simple metric in a YAML metric definition\n */\nconst SimpleMetricSchema = z.object({\n type: z.literal('simple'),\n measure: z.string(),\n agg: AnalyticsAggregationSchema.optional(),\n filter: z.string().optional(),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Derived metric — expression combining other metrics\n */\nconst DerivedMetricSchema = z.object({\n type: z.literal('derived'),\n expr: z.string(),\n metrics: z.array(z.string()),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Ratio metric — numerator / denominator\n */\nconst RatioMetricSchema = z.object({\n type: z.literal('ratio'),\n numerator: z.union([z.string(), SimpleMetricSchema]),\n denominator: z.union([z.string(), SimpleMetricSchema]),\n filter: z.string().optional(),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Cumulative metric — time-series accumulation\n */\nconst CumulativeMetricSchema = z.object({\n type: z.literal('cumulative'),\n measure: z.string(),\n window: z.string().optional(),\n grain_to_date: AnalyticsTimeGranularitySchema.optional(),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Discriminated union of all four metric types\n */\nconst MetricDefinitionSchema = z.discriminatedUnion('type', [\n SimpleMetricSchema,\n DerivedMetricSchema,\n RatioMetricSchema,\n CumulativeMetricSchema,\n]);\n\nexport type MetricDefinition = z.infer<typeof MetricDefinitionSchema>;\n\n/**\n * Entity-level analytics block\n *\n * Declared in the YAML under `analytics:` alongside fields and relationships.\n */\nconst AnalyticsBlockSchema = z.object({\n measure_packs: z.array(z.string()).optional(),\n cube_name: z.string().optional(),\n metrics: z.record(z.string(), MetricDefinitionSchema).optional(),\n});\n\nexport type AnalyticsBlock = z.infer<typeof AnalyticsBlockSchema>;\n\n// ============================================================================\n// Full Entity Definition\n// ============================================================================\n\n// ============================================================================\n// Generation Toggles\n// ============================================================================\n\n/**\n * Per-entity opt-outs for code generation.\n *\n * - `writes`: when `false`, suppresses create/update/delete use cases,\n * matching controller routes, and module providers. Defaults to `true`.\n */\nconst GenerateConfigSchema = z\n .object({\n writes: z.boolean().optional().default(true),\n })\n .strict();\n\nexport type GenerateConfig = z.infer<typeof GenerateConfigSchema>;\n\nexport const EntityDefinitionSchema = z\n .object({\n entity: EntityConfigSchema,\n fields: z.record(z.string(), FieldDefinitionSchema),\n relationships: z.record(z.string(), RelationshipSchema).optional(),\n // Behaviors add cross-cutting concerns (timestamps, soft_delete, user_tracking, etc.)\n behaviors: z.array(BehaviorConfigSchema).optional().default([]),\n\n // Per-entity generation toggles (e.g. disable write-side emission)\n generate: GenerateConfigSchema.optional(),\n\n // EAV (entity-attribute-value) dual-write + paired reads (ADR-13).\n // When `true`, codegen emits:\n // - FindXWithFieldsUseCase + ListXWithFieldsUseCase (paired reads)\n // - CreateX / UpdateX use cases in transactional compound-write shape\n // (composes entity service + FieldValueService in one db.transaction,\n // splits `{ fields, ...core }` from the DTO)\n // - GET /:id/with-fields + GET /with-fields controller routes\n // - Service with injected FieldValueRepository + findByIdWithFields /\n // listWithFields paired read methods\n //\n // Consumer contract (must be in place before regen):\n // - BaseService.create/update/delete accept optional `tx` parameter\n // - `@shared/eav-helpers` exports `toEavRows(entityId, entityType, fields)`\n // and `mergeEavRows(rows)`\n // - FieldValueService exposes `upsertMany(rows, tx?)` (inherited from\n // MetadataEntityService)\n // - DRIZZLE_DB injection token available via `@shared/constants/tokens`\n //\n // Defaults to `false` — opt in per entity that needs dynamic/custom fields.\n eav: z.boolean().optional().default(false),\n\n // Declare this entity IS an EAV value table. When `true`, codegen emits\n // the compound EAV methods (upsertFieldsTransactional, findMergedByEntity)\n // on the service and the upsertCurrentValues method on the repository —\n // no hand extension required. Companion flag `eav_definition_table`\n // identifies the sibling entity that stores the field-key ↔ id lookup.\n //\n // Mutually exclusive with `eav: true` in practice — a value table holds\n // OTHER entities' dynamic fields, it isn't itself an EAV-opt-in entity.\n //\n // Assumption (v1): value tables have a `user_id` column. Future\n // `eav_user_scoped: false` flag will relax this for audit/system EAV.\n eav_value_table: z.boolean().optional().default(false),\n\n // Singular entity name of the field-definitions entity that pairs with\n // this value table (matches the `target:` convention in relationship\n // YAMLs). Required when `eav_value_table: true`; ignored otherwise.\n eav_definition_table: z.string().optional(),\n\n\n // v2: Declarative query generation (ADR-005)\n // Generates repository + service + use case methods from declarations\n queries: z.array(AnyQueryDeclarationSchema).optional(),\n\n // v2: Integration sync configuration (CODEGEN-EVOLUTION-PLAN Phase 2)\n // Electric SQL + provider sync (Salesforce, HubSpot, etc.)\n sync: SyncConfigSchema.optional(),\n\n // v2: Domain event declarations (CODEGEN-EVOLUTION-PLAN Phase 2)\n // Generates typed event classes, handlers, and queue registration\n events: z.array(EventDeclarationSchema).optional(),\n\n // EVT-7: Opt-in typed event emission. Each entry names an `EventDefinition`\n // (top-level `events/<type>.yaml` or an inline `events:` block entry) that\n // the generated use-cases should publish via `TypedEventBus.publish(...)`\n // inside a Drizzle transaction.\n //\n // emits: [contact_created, contact_updated]\n //\n // Cross-validated in `validateEntityEmits()` against the merged event\n // registry. `undefined` ⇒ fallback to untyped lifecycle-events + warning;\n // `[]` ⇒ explicit opt-out, no warning, no typed emission.\n emits: z\n .array(\n z\n .string()\n .regex(/^[a-z][a-z0-9_]*$/, 'emits entries must be snake_case event type names'),\n )\n .optional(),\n\n // v2: Analytics / semantic layer configuration\n // Cube.js measure packs, custom cube name, and metric definitions\n analytics: AnalyticsBlockSchema.optional(),\n })\n .strict()\n .refine(\n (data) => !data.eav_value_table || typeof data.eav_definition_table === 'string',\n {\n message:\n \"`eav_definition_table` is required when `eav_value_table: true` — \" +\n \"declare the singular entity name of the paired field-definitions entity \" +\n \"(e.g. `eav_definition_table: 'field_definition'`).\",\n path: ['eav_definition_table'],\n },\n );\n\nexport type EntityDefinition = z.infer<typeof EntityDefinitionSchema>;\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nexport function validateEntityDefinition(data: unknown): EntityDefinition {\n return EntityDefinitionSchema.parse(data);\n}\n\nexport function safeValidateEntityDefinition(data: unknown): {\n success: boolean;\n data?: EntityDefinition;\n error?: z.ZodError;\n} {\n const result = EntityDefinitionSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return { success: false, error: result.error };\n}\n\n// ============================================================================\n// Type Mapping Utilities (for code generation)\n// ============================================================================\n\n/**\n * Maps YAML field types to TypeScript types\n *\n * Note: 'entity_ref' is handled specially in templates as it generates\n * two fields: {field}EntityType (EntityType enum) and {field}EntityId (string)\n */\nexport const fieldTypeToTypeScript: Record<FieldType, string> = {\n string: \"string\",\n integer: \"number\",\n decimal: \"number\",\n boolean: \"boolean\",\n uuid: \"string\",\n date: \"Date\",\n datetime: \"Date\",\n json: \"unknown\",\n entity_ref: \"EntityRef\", // Placeholder - templates handle specially\n string_array: \"string[]\",\n enum: \"string\", // Actual enum type generated from choices\n};\n\n/**\n * Maps YAML field types to Drizzle column types\n *\n * Note: 'entity_ref' generates two columns: pgEnum + uuid\n * Note: 'enum' uses pgEnum with choices\n */\nexport const fieldTypeToDrizzle: Record<FieldType, string> = {\n string: \"varchar\",\n integer: \"integer\",\n decimal: \"decimal\",\n boolean: \"boolean\",\n uuid: \"uuid\",\n date: \"date\",\n datetime: \"timestamp\",\n json: \"jsonb\",\n entity_ref: \"entity_ref\", // Placeholder - templates handle specially (enum + uuid)\n string_array: \"text().array()\",\n enum: \"enum\", // Placeholder - templates generate pgEnum\n};\n\n/**\n * Maps YAML field types to Zod schema methods\n *\n * Note: 'entity_ref' generates two fields in Zod schema\n * Note: 'enum' uses z.enum() with choices\n */\nexport const fieldTypeToZod: Record<FieldType, string> = {\n string: \"z.string()\",\n integer: \"z.number().int()\",\n // Drizzle maps PG `numeric` to a JS string to preserve precision.\n // Using z.coerce.string() — not z.coerce.number() — prevents silent\n // precision loss on large decimal values. Matches clean-lite-ps (PR #42).\n decimal: \"z.coerce.string()\",\n boolean: \"z.boolean()\",\n uuid: \"z.string().uuid()\",\n date: \"z.date()\",\n datetime: \"z.date()\",\n json: \"z.unknown()\",\n entity_ref: \"entity_ref\", // Placeholder - templates handle specially\n string_array: \"z.array(z.string())\",\n enum: \"z.enum()\", // Placeholder - templates add choices\n};\n","import { z } from \"zod\";\n\n/**\n * Event Definition Schema\n *\n * Describes a single `events/*.yaml` file. This is the codegen-side contract\n * for first-class event declarations (ADR-024 Phase 1, EVT-2). One file per\n * event; filename matches `type` (snake_case). Consumed by EVT-3 to emit\n * `runtime/subsystems/events/generated/` artifacts.\n *\n * Payload field types intentionally narrower than entity field types:\n * events are a wire format, not a database schema. `decimal`, `entity_ref`,\n * `string_array`, `enum` make no sense in an event payload.\n */\n\n// ============================================================================\n// Enums and constants\n// ============================================================================\n\nexport const EVENT_DIRECTIONS = [\"inbound\", \"change\", \"outbound\"] as const;\nexport type EventDirection = (typeof EVENT_DIRECTIONS)[number];\n\nexport const EVENT_FIELD_TYPES = [\n\t\"uuid\",\n\t\"string\",\n\t\"number\",\n\t\"boolean\",\n\t\"date\",\n\t\"json\",\n] as const;\nexport type EventFieldType = (typeof EVENT_FIELD_TYPES)[number];\n\nexport const RESERVED_EVENT_POOLS = [\n\t\"events_inbound\",\n\t\"events_change\",\n\t\"events_outbound\",\n] as const;\nexport type EventPool = (typeof RESERVED_EVENT_POOLS)[number];\n\nexport const EVENT_BACKOFF_STRATEGIES = [\"linear\", \"exponential\"] as const;\nexport type EventBackoffStrategy = (typeof EVENT_BACKOFF_STRATEGIES)[number];\n\n/**\n * Direction → default pool derivation. Each `direction` maps to exactly one\n * reserved pool; overrides must stay within the same category.\n */\nexport const DIRECTION_TO_POOL: Record<EventDirection, EventPool> = {\n\tinbound: \"events_inbound\",\n\tchange: \"events_change\",\n\toutbound: \"events_outbound\",\n};\n\n// ============================================================================\n// Sub-schemas\n// ============================================================================\n\nconst EventDirectionSchema = z.enum(EVENT_DIRECTIONS);\nconst EventFieldTypeSchema = z.enum(EVENT_FIELD_TYPES);\nconst EventPoolSchema = z.enum(RESERVED_EVENT_POOLS);\n\n/**\n * Per-payload-field metadata. `nullable: true` means the field may be `null`\n * on the wire; `description` is surfaced into the generated interface/Zod\n * schema as a JSDoc.\n */\nconst EventPayloadFieldSchema = z\n\t.object({\n\t\ttype: EventFieldTypeSchema,\n\t\tnullable: z.boolean().optional().default(false),\n\t\tdescription: z.string().optional(),\n\t})\n\t.strict();\n\nexport type EventPayloadField = z.infer<typeof EventPayloadFieldSchema>;\n\n/**\n * Retry metadata hints surfaced to the drain loop. Default applied at parent\n * level (see `EventDefinitionSchemaCore`).\n */\nconst RetrySchema = z\n\t.object({\n\t\tattempts: z.number().int().min(0).max(20),\n\t\tbackoff: z.enum(EVENT_BACKOFF_STRATEGIES),\n\t})\n\t.strict();\n\nexport type EventRetry = z.infer<typeof RetrySchema>;\n\n// ============================================================================\n// Top-level schema\n// ============================================================================\n\nconst SNAKE_CASE_RE = /^[a-z][a-z0-9_]*$/;\n\nconst EventDefinitionSchemaCore = z\n\t.object({\n\t\ttype: z\n\t\t\t.string()\n\t\t\t.regex(\n\t\t\t\tSNAKE_CASE_RE,\n\t\t\t\t\"Event type must be snake_case starting with a letter\",\n\t\t\t),\n\t\tdirection: EventDirectionSchema,\n\t\tpool: EventPoolSchema.optional(),\n\t\taggregate: z.string().regex(SNAKE_CASE_RE).optional(),\n\t\tsource: z.string().min(1).optional(),\n\t\tdestination: z.string().min(1).optional(),\n\t\tpayload: z\n\t\t\t.record(\n\t\t\t\tz\n\t\t\t\t\t.string()\n\t\t\t\t\t.regex(SNAKE_CASE_RE, \"Payload keys must be snake_case\"),\n\t\t\t\tEventPayloadFieldSchema,\n\t\t\t)\n\t\t\t.default({}),\n\t\tretry: RetrySchema.optional().default({\n\t\t\tattempts: 3,\n\t\t\tbackoff: \"exponential\",\n\t\t}),\n\t\tversion: z.number().int().min(1).optional().default(1),\n\t\tdescription: z.string().optional(),\n\t})\n\t.strict();\n\n/**\n * Cross-field refinements (in order):\n *\n * 1. `direction: change` ⇒ `aggregate` is required.\n * 2. `source` is only valid when `direction: inbound` (strict direction gating).\n * 3. `destination` is only valid when `direction: outbound` (strict direction gating).\n * 4. An explicit `pool` must match `DIRECTION_TO_POOL[direction]`.\n *\n * Strict gating on #2/#3 is a deliberate choice: silent acceptance breeds\n * drift. The ADR defines `source` as inbound-only and `destination` as\n * outbound-only.\n */\nconst EventDefinitionSchemaRefined = EventDefinitionSchemaCore.superRefine(\n\t(data, ctx) => {\n\t\tif (data.direction === \"change\" && !data.aggregate) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: \"'aggregate' is required when direction is 'change'\",\n\t\t\t\tpath: [\"aggregate\"],\n\t\t\t});\n\t\t}\n\n\t\tif (data.source !== undefined && data.direction !== \"inbound\") {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: `'source' is only valid when direction is 'inbound' (got '${data.direction}')`,\n\t\t\t\tpath: [\"source\"],\n\t\t\t});\n\t\t}\n\n\t\tif (data.destination !== undefined && data.direction !== \"outbound\") {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: `'destination' is only valid when direction is 'outbound' (got '${data.direction}')`,\n\t\t\t\tpath: [\"destination\"],\n\t\t\t});\n\t\t}\n\n\t\tif (data.pool !== undefined) {\n\t\t\tconst expected = DIRECTION_TO_POOL[data.direction];\n\t\t\tif (data.pool !== expected) {\n\t\t\t\tctx.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tmessage: `pool '${data.pool}' is inconsistent with direction '${data.direction}' (expected '${expected}')`,\n\t\t\t\t\tpath: [\"pool\"],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n);\n\n/**\n * Final schema: derive `pool` from `direction` when not explicitly set. After\n * `parse()`, every `EventDefinition` has `pool` populated.\n */\nexport const EventDefinitionSchema = EventDefinitionSchemaRefined.transform(\n\t(parsed) => ({\n\t\t...parsed,\n\t\tpool: parsed.pool ?? DIRECTION_TO_POOL[parsed.direction],\n\t}),\n);\n\nexport type EventDefinition = z.infer<typeof EventDefinitionSchema>;\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nexport function validateEventDefinition(data: unknown): EventDefinition {\n\treturn EventDefinitionSchema.parse(data);\n}\n\nexport function safeValidateEventDefinition(data: unknown): {\n\tsuccess: boolean;\n\tdata?: EventDefinition;\n\terror?: z.ZodError;\n} {\n\tconst result = EventDefinitionSchema.safeParse(data);\n\tif (result.success) {\n\t\treturn { success: true, data: result.data };\n\t}\n\treturn { success: false, error: result.error };\n}\n","import { z } from 'zod';\n\n/**\n * Relationship Definition Schema\n *\n * Defines the YAML contract for first-class relationship entities — typed,\n * temporal, sourced junction tables between core entities.\n *\n * A relationship definition generates the same artifacts as an entity\n * (Drizzle schema, repository, DTOs, NestJS module, controller) but with\n * auto-generated FK columns, type enum, temporal fields, and source tracking.\n *\n * The relationship: block replaces entity: as the top-level discriminator.\n * The fields:, queries:, and behaviors: blocks reuse entity-definition schemas.\n *\n * See: docs/codegen-evolution-data-model/03-relationship-taxonomy.md\n * See: test/fixtures/relationships/ for examples\n */\n\n// Re-use field and query schemas from entity-definition\n// These are imported to avoid duplication — fields on a relationship\n// work identically to fields on an entity.\nimport type { FieldDefinition, QueryDeclaration } from './entity-definition.schema.js';\n\n// ============================================================================\n// Relationship Type Definitions\n// ============================================================================\n\n/**\n * Direction metadata for a single relationship type.\n *\n * Required for self-referential relationships (person↔person, org↔org)\n * where direction can't be inferred from entity-type asymmetry.\n *\n * Three mutually exclusive modes:\n * - inverse: \"from→to is called X, to→from is called Y\"\n * - bidirectional: true — direction doesn't matter, query both sides\n * - directed: true — one-way, no inverse name (default if none specified)\n */\nconst TypeDirectionSchema = z\n\t.object({\n\t\t/** Name of the inverse type when viewed from the other direction */\n\t\tinverse: z.string().optional(),\n\t\t/** Both directions are equivalent — queries should check both FK columns */\n\t\tbidirectional: z.boolean().optional(),\n\t\t/** Explicitly directed, no named inverse (default behavior) */\n\t\tdirected: z.boolean().optional(),\n\t})\n\t.refine(\n\t\t(data) => {\n\t\t\tconst set = [data.inverse, data.bidirectional, data.directed].filter(\n\t\t\t\t(v) => v !== undefined,\n\t\t\t);\n\t\t\treturn set.length === 1;\n\t\t},\n\t\t{\n\t\t\tmessage:\n\t\t\t\t'Exactly one of inverse, bidirectional, or directed must be specified',\n\t\t},\n\t);\n\nexport type TypeDirection = z.infer<typeof TypeDirectionSchema>;\n\n/**\n * Relationship types can be declared in two forms:\n *\n * 1. Simple list — for cross-type relationships where direction is\n * unambiguous from entity asymmetry:\n * types: [employed_by, advises, board_member]\n *\n * 2. Object map — for self-referential or when types need direction metadata:\n * types:\n * reporting:\n * inverse: management\n * network:\n * bidirectional: true\n *\n * The simple list is sugar for \"all directed from→to, no inverses.\"\n */\nconst RelationshipTypesSchema = z.union([\n\t// Simple list: all types are directed from→to\n\tz.array(z.string().regex(/^[a-z][a-z0-9_]*$/, 'Type must be snake_case')),\n\t// Object map: each type has direction metadata\n\tz.record(\n\t\tz.string().regex(/^[a-z][a-z0-9_]*$/, 'Type key must be snake_case'),\n\t\tTypeDirectionSchema,\n\t),\n]);\n\nexport type RelationshipTypes = z.infer<typeof RelationshipTypesSchema>;\n\n// ============================================================================\n// On-Delete Semantics (ADR-021)\n// ============================================================================\n\nconst OnDeleteActionSchema = z\n\t.enum(['restrict', 'cascade', 'set_null', 'no_action'])\n\t.default('restrict');\n\nexport type OnDeleteAction = z.infer<typeof OnDeleteActionSchema>;\n\n// ============================================================================\n// Relationship Configuration Block\n// ============================================================================\n\n/**\n * The relationship: block — top-level config for a relationship definition.\n *\n * Establishes the two endpoints, type taxonomy, and behavioral flags.\n * Auto-generates FK columns, type enum, temporal fields, source tracking,\n * and timestamps based on configuration.\n */\nconst RelationshipConfigSchema = z\n\t.object({\n\t\t/** Relationship name (snake_case). Used for class/file naming. */\n\t\tname: z.string().regex(\n\t\t\t/^[a-z][a-z0-9_]*$/,\n\t\t\t'Relationship name must be snake_case',\n\t\t),\n\n\t\t/** Database table name. Defaults to {name}s if not specified. */\n\t\ttable: z\n\t\t\t.string()\n\t\t\t.regex(/^[a-z][a-z0-9_]*$/, 'Table must be snake_case')\n\t\t\t.optional(),\n\n\t\t/** The \"from\" entity — generates {entity}_id FK column (subject). */\n\t\tfrom: z.string().regex(/^[a-z][a-z0-9_]*$/, 'Entity name must be snake_case'),\n\n\t\t/** The \"to\" entity — generates {entity}_id FK column (object). */\n\t\tto: z.string().regex(/^[a-z][a-z0-9_]*$/, 'Entity name must be snake_case'),\n\n\t\t/**\n\t\t * Relationship subtypes. Optional — omit for untyped junctions.\n\t\t * When present, generates a `type` enum column on the junction table.\n\t\t *\n\t\t * Simple list: all types are directed (from→to). Use for cross-type\n\t\t * relationships where entity asymmetry makes direction obvious.\n\t\t *\n\t\t * Object map: each type declares its own direction metadata.\n\t\t * Required for self-referential relationships (from === to).\n\t\t */\n\t\ttypes: RelationshipTypesSchema.optional(),\n\n\t\t/**\n\t\t * Generate temporal validity fields: valid_from (date), valid_to (date?),\n\t\t * is_current (boolean, denormalized for query performance).\n\t\t * Default: true\n\t\t */\n\t\ttemporal: z.boolean().default(true),\n\n\t\t/**\n\t\t * Generate source tracking fields: source (enum), confidence (decimal 0-1).\n\t\t * Default: true\n\t\t */\n\t\tsourced: z.boolean().default(true),\n\n\t\t/** on_delete action for the \"from\" endpoint FK. Default: restrict */\n\t\ton_delete_from: OnDeleteActionSchema.optional(),\n\n\t\t/** on_delete action for the \"to\" endpoint FK. Default: restrict */\n\t\ton_delete_to: OnDeleteActionSchema.optional(),\n\n\t\t/**\n\t\t * Override the default unique constraint columns.\n\t\t *\n\t\t * Defaults:\n\t\t * - Typed: [from_id, to_id, type]\n\t\t * - Typed + temporal: [from_id, to_id, type, valid_from]\n\t\t * - Untyped: [from_id, to_id]\n\t\t *\n\t\t * Use this when the default doesn't fit — e.g., allowing multiple\n\t\t * relationships of the same type between the same entities at different times.\n\t\t */\n\t\tunique_on: z.array(z.string()).optional(),\n\t})\n\t.strict();\n\nexport type RelationshipConfig = z.infer<typeof RelationshipConfigSchema>;\n\n// ============================================================================\n// Query Declaration (reuse from entity-definition)\n// ============================================================================\n\n/**\n * Same query declaration syntax as entities.\n * FK field names in `by:` use the auto-generated names:\n * - Cross-type: {entity}_id (e.g., person_id, organization_id)\n * - Self-referential: from_{entity}_id, to_{entity}_id\n */\nconst RelationshipQuerySchema = z.object({\n\tby: z.array(z.string()).min(1),\n\tunique: z.boolean().optional(),\n\tselect: z.array(z.string()).optional(),\n\torder: z.string().optional(),\n\tlimit: z.boolean().optional(),\n});\n\n// ============================================================================\n// Field Definition (reuse from entity-definition)\n// ============================================================================\n\n// We import the type but need to re-reference the schema inline for Zod parsing.\n// The actual FieldDefinitionSchema is defined in entity-definition.schema.ts.\n// For now, we use z.record(z.string(), z.any()) and validate fields\n// through the shared FieldDefinitionSchema at parse time.\n//\n// TODO: Extract FieldDefinitionSchema to a shared module so both\n// entity-definition and relationship-definition can import it directly.\n\n// ============================================================================\n// Full Relationship Definition\n// ============================================================================\n\n/**\n * Complete relationship definition — the top-level shape of a relationship YAML file.\n *\n * Example (minimal):\n * relationship:\n * name: engagement_opportunity\n * from: engagement\n * to: opportunity\n *\n * Example (full):\n * relationship:\n * name: person_organization\n * table: person_organizations\n * from: person\n * to: organization\n * types: [employed_by, advises, board_member]\n * temporal: true\n * sourced: true\n * fields:\n * role_title:\n * type: string\n * nullable: true\n * queries:\n * - by: [person_id]\n */\nexport const RelationshipDefinitionSchema = z\n\t.object({\n\t\t/** Relationship configuration block */\n\t\trelationship: RelationshipConfigSchema,\n\n\t\t/**\n\t\t * Additional fields beyond auto-generated ones.\n\t\t * These describe the relationship, not either endpoint entity.\n\t\t * Uses the same field definition schema as entity fields.\n\t\t */\n\t\tfields: z.record(z.string(), z.any()).optional(),\n\n\t\t/** Declarative queries — same syntax as entity queries. */\n\t\tqueries: z.array(RelationshipQuerySchema).optional(),\n\t})\n\t.strict()\n\t.refine(\n\t\t(data) => {\n\t\t\t// Self-referential relationships with types MUST use the object map form\n\t\t\t// so that direction metadata (inverse/bidirectional/directed) is explicit.\n\t\t\tif (data.relationship.from === data.relationship.to && data.relationship.types) {\n\t\t\t\treturn !Array.isArray(data.relationship.types);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\t{\n\t\t\tmessage:\n\t\t\t\t'Self-referential relationships must use the object map form for types ' +\n\t\t\t\t'(with inverse/bidirectional/directed metadata), not a simple list',\n\t\t\tpath: ['relationship', 'types'],\n\t\t},\n\t)\n\t.refine(\n\t\t(data) => {\n\t\t\t// Reject fields: keys that collide with auto-generated column names.\n\t\t\t// The reserved set is dynamic — depends on the relationship config.\n\t\t\tif (!data.fields) return true;\n\n\t\t\tconst reserved = getReservedColumnNames(data.relationship);\n\t\t\tconst collisions = Object.keys(data.fields).filter((key) =>\n\t\t\t\treserved.has(key),\n\t\t\t);\n\t\t\treturn collisions.length === 0;\n\t\t},\n\t\t{\n\t\t\tmessage:\n\t\t\t\t'fields: contains keys that collide with auto-generated columns. ' +\n\t\t\t\t'Reserved names depend on config (type, valid_from, valid_to, ' +\n\t\t\t\t'is_current, source, confidence, id, created_at, updated_at, and FK columns).',\n\t\t\tpath: ['fields'],\n\t\t},\n\t);\n\nexport type RelationshipDefinition = z.infer<\n\ttypeof RelationshipDefinitionSchema\n>;\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nexport function validateRelationshipDefinition(\n\tdata: unknown,\n): RelationshipDefinition {\n\treturn RelationshipDefinitionSchema.parse(data);\n}\n\nexport function safeValidateRelationshipDefinition(data: unknown): {\n\tsuccess: boolean;\n\tdata?: RelationshipDefinition;\n\terror?: z.ZodError;\n} {\n\tconst result = RelationshipDefinitionSchema.safeParse(data);\n\tif (result.success) {\n\t\treturn { success: true, data: result.data };\n\t}\n\treturn { success: false, error: result.error };\n}\n\n// ============================================================================\n// Reserved Column Names\n// ============================================================================\n\n/**\n * Returns the set of column names that are auto-generated for a relationship\n * and therefore cannot be used as custom field names.\n *\n * The set is dynamic — it depends on the relationship config:\n * - Always: id, created_at, updated_at, and both FK columns\n * - If types: present → type\n * - If temporal: true → valid_from, valid_to, is_current\n * - If sourced: true → source, confidence\n */\nexport function getReservedColumnNames(config: RelationshipConfig): Set<string> {\n\tconst { fromColumn, toColumn } = deriveRelationshipFKColumns(config);\n\tconst reserved = new Set([\n\t\t'id',\n\t\t'created_at',\n\t\t'updated_at',\n\t\tfromColumn,\n\t\ttoColumn,\n\t]);\n\n\tif (config.types) {\n\t\treserved.add('type');\n\t}\n\tif (config.temporal) {\n\t\treserved.add('valid_from');\n\t\treserved.add('valid_to');\n\t\treserved.add('is_current');\n\t}\n\tif (config.sourced) {\n\t\treserved.add('source');\n\t\treserved.add('confidence');\n\t}\n\n\treturn reserved;\n}\n\n// ============================================================================\n// Auto-Generated Field Helpers\n// ============================================================================\n\n/**\n * Derives the FK column names for a relationship.\n *\n * Cross-type (from !== to):\n * from: person, to: organization → person_id, organization_id\n *\n * Self-referential (from === to):\n * from: person, to: person → from_person_id, to_person_id\n */\nexport function deriveRelationshipFKColumns(config: RelationshipConfig): {\n\tfromColumn: string;\n\ttoColumn: string;\n} {\n\tif (config.from === config.to) {\n\t\treturn {\n\t\t\tfromColumn: `from_${config.from}_id`,\n\t\t\ttoColumn: `to_${config.to}_id`,\n\t\t};\n\t}\n\treturn {\n\t\tfromColumn: `${config.from}_id`,\n\t\ttoColumn: `${config.to}_id`,\n\t};\n}\n\n/**\n * Derives the default table name if not explicitly specified.\n * Uses the relationship name + 's' suffix.\n */\nexport function deriveTableName(config: RelationshipConfig): string {\n\treturn config.table ?? `${config.name}s`;\n}\n\n/**\n * Collects all type names from a types declaration.\n * Handles both simple list and object map forms.\n */\nexport function collectTypeNames(\n\ttypes: RelationshipTypes | undefined,\n): string[] {\n\tif (!types) return [];\n\tif (Array.isArray(types)) return types;\n\treturn Object.keys(types);\n}\n\n/**\n * Collects all inverse type names from a types declaration.\n * Only applicable for object map form with inverse metadata.\n */\nexport function collectInverseNames(\n\ttypes: RelationshipTypes | undefined,\n): string[] {\n\tif (!types || Array.isArray(types)) return [];\n\treturn Object.values(types)\n\t\t.map((dir) => (dir as TypeDirection & { inverse?: string }).inverse)\n\t\t.filter((v): v is string => v !== undefined);\n}\n\n/**\n * Determines the default unique constraint columns.\n *\n * Logic:\n * - Typed + temporal: [from_id, to_id, type, valid_from]\n * - Typed: [from_id, to_id, type]\n * - Untyped: [from_id, to_id]\n */\nexport function deriveUniqueConstraint(config: RelationshipConfig): string[] {\n\tif (config.unique_on) return config.unique_on;\n\n\tconst { fromColumn, toColumn } = deriveRelationshipFKColumns(config);\n\tconst columns = [fromColumn, toColumn];\n\n\tif (config.types) {\n\t\tcolumns.push('type');\n\t}\n\tif (config.temporal && config.types) {\n\t\tcolumns.push('valid_from');\n\t}\n\n\treturn columns;\n}\n","/**\n * Graph Builder\n *\n * Builds a domain graph from parsed entities, including nodes and edges.\n * Tracks bidirectional connections between entities.\n */\n\nimport type {\n\tParsedEntity,\n\tParsedRelationship,\n\tParsedRelationshipDefinition,\n\tDomainGraph,\n\tRelationshipEdge,\n\tEntityNode,\n} from './types';\n\n/**\n * Infer cardinality from relationship type\n */\nfunction inferCardinality(type: string): '1:1' | '1:N' | 'N:1' | 'N:M' {\n\tswitch (type) {\n\t\tcase 'belongs_to':\n\t\t\treturn 'N:1';\n\t\tcase 'has_many':\n\t\t\treturn '1:N';\n\t\tcase 'has_one':\n\t\t\treturn '1:1';\n\t\tdefault:\n\t\t\treturn '1:N';\n\t}\n}\n\n/**\n * Check if an edge already exists in the opposite direction\n */\nfunction hasReverseEdge(\n\tedges: RelationshipEdge[],\n\tfrom: string,\n\tto: string\n): RelationshipEdge | undefined {\n\treturn edges.find((e) => e.from === to && e.to === from);\n}\n\n/**\n * Build a domain graph from parsed entities\n */\nexport function buildDomainGraph(\n\tentities: ParsedEntity[],\n\trelationshipDefinitions: ParsedRelationshipDefinition[] = [],\n): DomainGraph {\n\tconst entityMap = new Map<string, ParsedEntity>();\n\tconst relDefMap = new Map<string, ParsedRelationshipDefinition>();\n\tconst edges: RelationshipEdge[] = [];\n\n\t// Build entity map\n\tfor (const entity of entities) {\n\t\tentityMap.set(entity.name, entity);\n\t}\n\n\t// Build relationship definition map\n\tfor (const relDef of relationshipDefinitions) {\n\t\trelDefMap.set(relDef.name, relDef);\n\t}\n\n\t// Build edges from inline entity relationships (belongs_to, has_many, has_one)\n\tfor (const entity of entities) {\n\t\tfor (const [relName, rel] of entity.relationships) {\n\t\t\tif (!rel.resolved) continue;\n\n\t\t\t// Check if reverse edge already exists\n\t\t\tconst reverseEdge = hasReverseEdge(edges, entity.name, rel.target);\n\n\t\t\tconst edge: RelationshipEdge = {\n\t\t\t\tfrom: entity.name,\n\t\t\t\tto: rel.target,\n\t\t\t\trelationship: rel,\n\t\t\t\tcardinality: inferCardinality(rel.type),\n\t\t\t\tbidirectional: reverseEdge !== undefined,\n\t\t\t};\n\n\t\t\t// Mark reverse edge as bidirectional too\n\t\t\tif (reverseEdge) {\n\t\t\t\treverseEdge.bidirectional = true;\n\t\t\t}\n\n\t\t\tedges.push(edge);\n\t\t}\n\t}\n\n\t// Build edges from first-class relationship definitions (junction entities)\n\tfor (const relDef of relationshipDefinitions) {\n\t\tconst fromExists = entityMap.has(relDef.from);\n\t\tconst toExists = entityMap.has(relDef.to);\n\n\t\tif (fromExists && toExists) {\n\t\t\t// Create an N:M edge — junction tables are always many-to-many\n\t\t\tconst edge: RelationshipEdge = {\n\t\t\t\tfrom: relDef.from,\n\t\t\t\tto: relDef.to,\n\t\t\t\trelationship: {\n\t\t\t\t\tname: relDef.name,\n\t\t\t\t\ttype: 'has_many',\n\t\t\t\t\ttarget: relDef.to,\n\t\t\t\t\tforeignKey: relDef.fromColumn,\n\t\t\t\t\tresolved: true,\n\t\t\t\t},\n\t\t\t\tcardinality: 'N:M',\n\t\t\t\tbidirectional: relDef.types.some((t) => t.bidirectional),\n\t\t\t};\n\n\t\t\tedges.push(edge);\n\t\t}\n\t}\n\n\treturn { entities: entityMap, relationshipDefinitions: relDefMap, edges };\n}\n\n/**\n * Get all entities related to a given entity within a specified depth\n */\nexport function getRelatedEntities(\n\tgraph: DomainGraph,\n\tentityName: string,\n\tdepth = 1\n): Set<string> {\n\tconst related = new Set<string>();\n\tconst visited = new Set<string>();\n\tconst queue: Array<{ name: string; currentDepth: number }> = [\n\t\t{ name: entityName, currentDepth: 0 },\n\t];\n\n\twhile (queue.length > 0) {\n\t\tconst item = queue.shift();\n\t\tif (!item) continue;\n\n\t\tconst { name, currentDepth } = item;\n\t\tif (visited.has(name) || currentDepth > depth) continue;\n\t\tvisited.add(name);\n\n\t\tfor (const edge of graph.edges) {\n\t\t\tif (edge.from === name && !visited.has(edge.to)) {\n\t\t\t\trelated.add(edge.to);\n\t\t\t\tqueue.push({ name: edge.to, currentDepth: currentDepth + 1 });\n\t\t\t}\n\t\t\tif (edge.to === name && !visited.has(edge.from)) {\n\t\t\t\trelated.add(edge.from);\n\t\t\t\tqueue.push({ name: edge.from, currentDepth: currentDepth + 1 });\n\t\t\t}\n\t\t}\n\t}\n\n\treturn related;\n}\n\n/**\n * Find entities with no relationships (orphans)\n */\nexport function findOrphanEntities(graph: DomainGraph): string[] {\n\tconst orphans: string[] = [];\n\tfor (const [name] of graph.entities) {\n\t\tconst hasRelationship = graph.edges.some((e) => e.from === name || e.to === name);\n\t\tif (!hasRelationship) {\n\t\t\torphans.push(name);\n\t\t}\n\t}\n\treturn orphans;\n}\n\n/**\n * Find circular dependencies in the graph\n */\nexport function findCircularDependencies(graph: DomainGraph): string[][] {\n\tconst cycles: string[][] = [];\n\tconst visited = new Set<string>();\n\tconst recursionStack = new Set<string>();\n\n\tfunction dfs(node: string, path: string[]): void {\n\t\tvisited.add(node);\n\t\trecursionStack.add(node);\n\n\t\tconst outgoingEdges = graph.edges.filter((e) => e.from === node);\n\t\tfor (const edge of outgoingEdges) {\n\t\t\tif (!visited.has(edge.to)) {\n\t\t\t\tdfs(edge.to, [...path, edge.to]);\n\t\t\t} else if (recursionStack.has(edge.to)) {\n\t\t\t\t// Found cycle\n\t\t\t\tconst cycleStart = path.indexOf(edge.to);\n\t\t\t\tif (cycleStart !== -1) {\n\t\t\t\t\tcycles.push([...path.slice(cycleStart), edge.to]);\n\t\t\t\t} else {\n\t\t\t\t\t// The cycle starts at edge.to which is in the recursion stack\n\t\t\t\t\tcycles.push([...path, edge.to]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trecursionStack.delete(node);\n\t}\n\n\tfor (const [name] of graph.entities) {\n\t\tif (!visited.has(name)) {\n\t\t\tdfs(name, [name]);\n\t\t}\n\t}\n\n\t// Deduplicate cycles (same cycle can be detected from different starting points)\n\tconst uniqueCycles: string[][] = [];\n\tconst seen = new Set<string>();\n\n\tfor (const cycle of cycles) {\n\t\t// Normalize cycle by rotating to start with smallest element\n\t\tconst minIndex = cycle.indexOf(\n\t\t\tcycle.reduce((min, val) => (val < min ? val : min), cycle[0])\n\t\t);\n\t\tconst normalized = [...cycle.slice(minIndex), ...cycle.slice(0, minIndex)];\n\t\tconst key = normalized.join('->');\n\n\t\tif (!seen.has(key)) {\n\t\t\tseen.add(key);\n\t\t\tuniqueCycles.push(cycle);\n\t\t}\n\t}\n\n\treturn uniqueCycles;\n}\n\n/**\n * Build entity nodes for visualization\n */\nexport function buildEntityNodes(graph: DomainGraph): EntityNode[] {\n\tconst nodes: EntityNode[] = [];\n\tfor (const [name, entity] of graph.entities) {\n\t\tnodes.push({\n\t\t\tid: name,\n\t\t\tname: entity.name,\n\t\t\tentity,\n\t\t});\n\t}\n\treturn nodes;\n}\n","/**\n * External ID Tracking Behavior\n *\n * Adds external_id, provider, and provider_metadata fields to track\n * records that are synced from external systems (e.g., Salesforce, HubSpot).\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const externalIdTrackingBehavior: BehaviorDefinition = {\n\tname: 'external_id_tracking',\n\tdescription: 'Adds external_id, provider, and provider_metadata fields for external system sync tracking',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'external_id',\n\t\t\tcamelName: 'externalId',\n\t\t\ttype: 'string',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'varchar',\n\t\t\tdrizzleImports: ['varchar', 'index'],\n\t\t\tzodType: 'z.string().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'External ID',\n\t\t\t\ttype: 'text',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'provider',\n\t\t\tcamelName: 'provider',\n\t\t\ttype: 'string',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'varchar',\n\t\t\tdrizzleImports: ['varchar'],\n\t\t\tzodType: 'z.string().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'Provider',\n\t\t\t\ttype: 'text',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'provider_metadata',\n\t\t\tcamelName: 'providerMetadata',\n\t\t\ttype: 'json',\n\t\t\ttsType: 'unknown | null',\n\t\t\tdrizzleType: 'jsonb',\n\t\t\tdrizzleImports: ['jsonb'],\n\t\t\tzodType: 'z.unknown().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'Provider Metadata',\n\t\t\t\ttype: 'json',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['varchar', 'jsonb', 'index'],\n\n\tconfigKey: 'externalIdTracking',\n};\n","/**\n * Soft Delete Behavior\n *\n * Adds deleted_at field for soft delete functionality.\n * Records are marked as deleted instead of being removed from the database.\n * BaseRepository automatically filters soft-deleted records in queries.\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const softDeleteBehavior: BehaviorDefinition = {\n\tname: 'soft_delete',\n\tdescription: 'Adds deleted_at field for soft delete functionality',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'deleted_at',\n\t\t\tcamelName: 'deletedAt',\n\t\t\ttype: 'datetime',\n\t\t\ttsType: 'Date | null',\n\t\t\tdrizzleType: 'timestamp',\n\t\t\tdrizzleImports: ['timestamp'],\n\t\t\tzodType: 'z.coerce.date().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'Deleted At',\n\t\t\t\ttype: 'datetime',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['timestamp'],\n\n\tmethods: [\n\t\t'softDelete',\n\t\t'restore',\n\t\t'findWithDeleted',\n\t\t'findOnlyDeleted',\n\t\t'baseQuery', // Modified to filter deleted records\n\t],\n\n\tconfigKey: 'softDelete',\n};\n","/**\n * Timestamps Behavior\n *\n * Adds created_at and updated_at fields to track entity lifecycle.\n * These fields are automatically managed by BaseRepository.\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const timestampsBehavior: BehaviorDefinition = {\n\tname: 'timestamps',\n\tdescription: 'Adds created_at and updated_at timestamp fields',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'created_at',\n\t\t\tcamelName: 'createdAt',\n\t\t\ttype: 'datetime',\n\t\t\ttsType: 'Date',\n\t\t\tdrizzleType: 'timestamp',\n\t\t\tdrizzleImports: ['timestamp'],\n\t\t\tzodType: 'z.coerce.date()',\n\t\t\tnullable: false,\n\t\t\tdefault: 'now()',\n\t\t\tui: {\n\t\t\t\tlabel: 'Created At',\n\t\t\t\ttype: 'datetime',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'updated_at',\n\t\t\tcamelName: 'updatedAt',\n\t\t\ttype: 'datetime',\n\t\t\ttsType: 'Date',\n\t\t\tdrizzleType: 'timestamp',\n\t\t\tdrizzleImports: ['timestamp'],\n\t\t\tzodType: 'z.coerce.date()',\n\t\t\tnullable: false,\n\t\t\tdefault: 'now()',\n\t\t\tui: {\n\t\t\t\tlabel: 'Updated At',\n\t\t\t\ttype: 'datetime',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['timestamp'],\n\n\tmethods: ['applyTimestampsOnCreate', 'applyTimestampsOnUpdate'],\n\n\tconfigKey: 'timestamps',\n};\n","/**\n * User Tracking Behavior\n *\n * Adds created_by and updated_by fields to track which user\n * created and last modified an entity.\n * These fields are automatically managed by BaseRepository when\n * a RepositoryContext with userId is provided.\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const userTrackingBehavior: BehaviorDefinition = {\n\tname: 'user_tracking',\n\tdescription: 'Adds created_by and updated_by user reference fields',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'created_by',\n\t\t\tcamelName: 'createdBy',\n\t\t\ttype: 'uuid',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'uuid',\n\t\t\tdrizzleImports: ['uuid'],\n\t\t\tzodType: 'z.string().uuid().nullable()',\n\t\t\tnullable: true,\n\t\t\tforeignKey: 'users.id',\n\t\t\tui: {\n\t\t\t\tlabel: 'Created By',\n\t\t\t\ttype: 'reference',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'updated_by',\n\t\t\tcamelName: 'updatedBy',\n\t\t\ttype: 'uuid',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'uuid',\n\t\t\tdrizzleImports: ['uuid'],\n\t\t\tzodType: 'z.string().uuid().nullable()',\n\t\t\tnullable: true,\n\t\t\tforeignKey: 'users.id',\n\t\t\tui: {\n\t\t\t\tlabel: 'Updated By',\n\t\t\t\ttype: 'reference',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['uuid'],\n\n\tmethods: ['applyUserTrackingOnCreate', 'applyUserTrackingOnUpdate'],\n\n\tconfigKey: 'userTracking',\n};\n","/**\n * Behavior Registry - Central registry for all entity behaviors\n *\n * Provides functions to:\n * - Get behavior definitions by name\n * - Validate behavior configurations\n * - Resolve fields added by behaviors\n */\n\nimport { externalIdTrackingBehavior } from './external-id-tracking';\nimport { softDeleteBehavior } from './soft-delete';\nimport { timestampsBehavior } from './timestamps';\nimport type {\n\tBehaviorConfig,\n\tBehaviorDefinition,\n\tBehaviorField,\n\tNormalizedBehaviorConfig,\n\tResolvedBehaviors,\n\tValidationResult,\n} from './types';\nimport { userTrackingBehavior } from './user-tracking';\n\n// ============================================================================\n// Behavior Registry\n// ============================================================================\n\nconst behaviorRegistry = new Map<string, BehaviorDefinition>([\n\t['timestamps', timestampsBehavior],\n\t['soft_delete', softDeleteBehavior],\n\t['user_tracking', userTrackingBehavior],\n\t['external_id_tracking', externalIdTrackingBehavior],\n]);\n\n/**\n * Get a behavior definition by name\n */\nexport function getBehavior(name: string): BehaviorDefinition | undefined {\n\treturn behaviorRegistry.get(name);\n}\n\n/**\n * Get all registered behavior names\n */\nexport function getAllBehaviorNames(): string[] {\n\treturn Array.from(behaviorRegistry.keys());\n}\n\n// ============================================================================\n// Config Normalization\n// ============================================================================\n\n/**\n * Normalize a behavior config to always have name and options\n */\nexport function normalizeBehaviorConfig(\n\tconfig: BehaviorConfig,\n): NormalizedBehaviorConfig {\n\tif (typeof config === 'string') {\n\t\treturn { name: config, options: {} };\n\t}\n\treturn { name: config.name, options: config.options ?? {} };\n}\n\n/**\n * Normalize an array of behavior configs\n */\nexport function normalizeBehaviorConfigs(\n\tconfigs: BehaviorConfig[],\n): NormalizedBehaviorConfig[] {\n\treturn configs.map(normalizeBehaviorConfig);\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\n/**\n * Validate a set of behavior configurations\n * Checks for unknown behaviors, missing dependencies, and conflicts\n */\nexport function validateBehaviors(configs: BehaviorConfig[]): ValidationResult {\n\tconst errors: string[] = [];\n\tconst warnings: string[] = [];\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst enabledNames = new Set(normalized.map((c) => c.name));\n\n\tfor (const config of normalized) {\n\t\tconst behavior = getBehavior(config.name);\n\n\t\t// Check behavior exists\n\t\tif (!behavior) {\n\t\t\terrors.push(`Unknown behavior: '${config.name}'`);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check dependencies\n\t\tif (behavior.requires) {\n\t\t\tfor (const req of behavior.requires) {\n\t\t\t\tif (!enabledNames.has(req)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Behavior '${config.name}' requires '${req}' which is not enabled`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check conflicts\n\t\tif (behavior.conflicts) {\n\t\t\tfor (const conflict of behavior.conflicts) {\n\t\t\t\tif (enabledNames.has(conflict)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Behavior '${config.name}' conflicts with '${conflict}'`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t\twarnings,\n\t};\n}\n\n// ============================================================================\n// Field Resolution\n// ============================================================================\n\n/**\n * Get all fields added by a set of behaviors\n */\nexport function resolveBehaviorFields(\n\tconfigs: BehaviorConfig[],\n): BehaviorField[] {\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst fields: BehaviorField[] = [];\n\tconst addedFieldNames = new Set<string>();\n\n\tfor (const config of normalized) {\n\t\tconst behavior = getBehavior(config.name);\n\t\tif (!behavior) continue;\n\n\t\tfor (const field of behavior.fields) {\n\t\t\t// Avoid duplicate fields if multiple behaviors add the same field\n\t\t\tif (!addedFieldNames.has(field.name)) {\n\t\t\t\tfields.push(field);\n\t\t\t\taddedFieldNames.add(field.name);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fields;\n}\n\n/**\n * Get all Drizzle imports needed by a set of behaviors\n */\nexport function resolveBehaviorDrizzleImports(\n\tconfigs: BehaviorConfig[],\n): string[] {\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst imports = new Set<string>();\n\n\tfor (const config of normalized) {\n\t\tconst behavior = getBehavior(config.name);\n\t\tif (!behavior) continue;\n\n\t\tfor (const imp of behavior.drizzleImports) {\n\t\t\timports.add(imp);\n\t\t}\n\t}\n\n\treturn Array.from(imports).sort();\n}\n\n// ============================================================================\n// Full Resolution\n// ============================================================================\n\n/**\n * Resolve all behavior data for templates\n */\nexport function resolveBehaviors(configs: BehaviorConfig[]): ResolvedBehaviors {\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst fields = resolveBehaviorFields(configs);\n\tconst drizzleImports = resolveBehaviorDrizzleImports(configs);\n\n\tconst enabledNames = new Set(normalized.map((c) => c.name));\n\n\tconst hasTimestamps = enabledNames.has('timestamps');\n\tconst hasSoftDelete = enabledNames.has('soft_delete');\n\tconst hasUserTracking = enabledNames.has('user_tracking');\n\tconst hasExternalIdTracking = enabledNames.has('external_id_tracking');\n\n\treturn {\n\t\tconfigs: normalized,\n\t\tfields,\n\t\tdrizzleImports,\n\t\trepositoryConfig: {\n\t\t\ttimestamps: hasTimestamps,\n\t\t\tsoftDelete: hasSoftDelete,\n\t\t\tuserTracking: hasUserTracking,\n\t\t\tversionable: false, // Future behavior\n\t\t},\n\t\thasBehaviors: normalized.length > 0,\n\t\thasTimestamps,\n\t\thasSoftDelete,\n\t\thasUserTracking,\n\t\thasExternalIdTracking,\n\t};\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport type {\n\tBehaviorConfig,\n\tBehaviorDefinition,\n\tBehaviorField,\n\tNormalizedBehaviorConfig,\n\tResolvedBehaviors,\n\tValidationResult,\n} from './types';\n\nexport { timestampsBehavior } from './timestamps';\nexport { softDeleteBehavior } from './soft-delete';\nexport { userTrackingBehavior } from './user-tracking';\nexport { externalIdTrackingBehavior } from './external-id-tracking';\n","/**\n * Consistency Checker\n *\n * Performs various consistency checks on the domain model:\n * - Missing relationship targets\n * - Missing inverse relationships\n * - Missing indexes on filterable fields\n * - Orphan entities (no relationships)\n * - Circular dependencies\n * - Naming conventions\n * - Missing UI metadata\n */\n\nimport type { ParsedEntity, DomainGraph, AnalysisIssue } from './types';\nimport { findOrphanEntities, findCircularDependencies } from './graph-builder';\nimport { resolveBehaviorFields } from '../behaviors/index';\n\n/**\n * Run all consistency checks on the domain graph\n */\nexport function checkConsistency(graph: DomainGraph): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Check each entity\n\tfor (const [name, entity] of graph.entities) {\n\t\tissues.push(...checkEntityConsistency(entity));\n\t\tissues.push(...checkRelationshipConsistency(entity, graph));\n\t\tissues.push(...checkNamingConventions(entity));\n\t\tissues.push(...checkMissingIndexes(entity));\n\t\tissues.push(...checkUiMetadata(entity));\n\t\tif (entity.queries !== undefined) {\n\t\t\tissues.push(...checkQueryFieldReferences(entity));\n\t\t}\n\t\tif (entity.sync !== undefined) {\n\t\t\tissues.push(...checkSyncFieldMappingReferences(entity));\n\t\t\tissues.push(...checkExternalIdTrackingCollision(entity));\n\t\t}\n\t}\n\n\t// Check graph-level issues\n\tissues.push(...checkOrphanEntities(graph));\n\tissues.push(...checkCircularReferences(graph));\n\tissues.push(...checkMissingInverses(graph));\n\n\treturn issues;\n}\n\n/**\n * Check entity-level consistency\n */\nfunction checkEntityConsistency(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Check for missing primary key\n\tif (!entity.fields.has('id')) {\n\t\tissues.push({\n\t\t\tseverity: 'info',\n\t\t\ttype: 'missing_id',\n\t\t\tentity: entity.name,\n\t\t\tmessage: 'Entity missing standard \"id\" field',\n\t\t\tsuggestion: 'Add an \"id\" field with type \"uuid\"',\n\t\t});\n\t}\n\n\t// Check for missing timestamps\n\tconst hasCreatedAt = entity.fields.has('created_at');\n\tconst hasTimestampsBehavior = entity.behaviors.includes('timestamps');\n\n\tif (!hasCreatedAt && !hasTimestampsBehavior) {\n\t\tissues.push({\n\t\t\tseverity: 'info',\n\t\t\ttype: 'missing_timestamps',\n\t\t\tentity: entity.name,\n\t\t\tmessage: 'Entity missing \"created_at\" field and \"timestamps\" behavior',\n\t\t\tsuggestion: 'Add \"timestamps\" to behaviors or add created_at/updated_at fields',\n\t\t});\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check relationship consistency\n */\nfunction checkRelationshipConsistency(\n\tentity: ParsedEntity,\n\tgraph: DomainGraph\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tfor (const [relName, rel] of entity.relationships) {\n\t\t// Check for belongs_to without matching foreign key field\n\t\tif (rel.type === 'belongs_to') {\n\t\t\tconst fkField = entity.fields.get(rel.foreignKey);\n\t\t\tif (!fkField) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'missing_fk_field',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: relName,\n\t\t\t\t\tmessage: `Relationship \"${relName}\" references foreign key \"${rel.foreignKey}\" but field doesn't exist`,\n\t\t\t\t\tsuggestion: `Add field \"${rel.foreignKey}\" with foreign_key reference`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Check for has_many relationships - target should have the FK field\n\t\tif (rel.type === 'has_many' || rel.type === 'has_one') {\n\t\t\tconst targetEntity = graph.entities.get(rel.target);\n\t\t\tif (targetEntity) {\n\t\t\t\tconst targetFkField = targetEntity.fields.get(rel.foreignKey);\n\t\t\t\tif (!targetFkField) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\t\ttype: 'missing_target_fk',\n\t\t\t\t\t\tentity: entity.name,\n\t\t\t\t\t\tfield: relName,\n\t\t\t\t\t\tmessage: `Relationship \"${relName}\" expects foreign key \"${rel.foreignKey}\" on \"${rel.target}\" but field doesn't exist`,\n\t\t\t\t\t\tsuggestion: `Add field \"${rel.foreignKey}\" to \"${rel.target}\" entity`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check naming conventions\n */\nfunction checkNamingConventions(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Entity name should be lowercase snake_case\n\tif (entity.name !== entity.name.toLowerCase()) {\n\t\tissues.push({\n\t\t\tseverity: 'warning',\n\t\t\ttype: 'naming_convention',\n\t\t\tentity: entity.name,\n\t\t\tmessage: 'Entity name should be lowercase',\n\t\t\tsuggestion: `Use \"${entity.name.toLowerCase()}\"`,\n\t\t});\n\t}\n\n\t// Check field naming\n\tfor (const [fieldName] of entity.fields) {\n\t\tif (fieldName !== fieldName.toLowerCase()) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'naming_convention',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: 'Field name should be snake_case',\n\t\t\t\tsuggestion: `Use \"${toSnakeCase(fieldName)}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Check relationship naming\n\tfor (const [relName] of entity.relationships) {\n\t\tif (relName !== relName.toLowerCase()) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'naming_convention',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: relName,\n\t\t\t\tmessage: 'Relationship name should be snake_case',\n\t\t\t\tsuggestion: `Use \"${toSnakeCase(relName)}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for missing indexes on filterable fields\n */\nfunction checkMissingIndexes(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tfor (const [fieldName, field] of entity.fields) {\n\t\t// Check if field is marked as filterable but has no index\n\t\tif (field.ui.filterable && !field.index && !field.unique) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'missing_index',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: `Field \"${fieldName}\" is filterable but has no index`,\n\t\t\t\tsuggestion: 'Add \"index: true\" to improve query performance',\n\t\t\t});\n\t\t}\n\n\t\t// Foreign key fields should typically have an index\n\t\tif (field.foreignKey && !field.index && !field.unique) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'info',\n\t\t\t\ttype: 'missing_fk_index',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: `Foreign key field \"${fieldName}\" has no index`,\n\t\t\t\tsuggestion: 'Add \"index: true\" for better join performance',\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for missing UI metadata\n */\nfunction checkUiMetadata(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// System fields that don't need UI metadata\n\tconst systemFields = new Set(['id', 'created_at', 'updated_at', 'deleted_at', 'tenant_id']);\n\n\tfor (const [fieldName, field] of entity.fields) {\n\t\tif (systemFields.has(fieldName)) continue;\n\n\t\tconst hasAnyUiMeta =\n\t\t\tfield.ui.label !== undefined ||\n\t\t\tfield.ui.type !== undefined ||\n\t\t\tfield.ui.group !== undefined;\n\n\t\tif (!hasAnyUiMeta) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'info',\n\t\t\t\ttype: 'missing_ui_metadata',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: `Field \"${fieldName}\" has no UI metadata`,\n\t\t\t\tsuggestion: 'Add ui_label, ui_type, ui_group for better admin panel display',\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for orphan entities\n */\nfunction checkOrphanEntities(graph: DomainGraph): AnalysisIssue[] {\n\tconst orphans = findOrphanEntities(graph);\n\treturn orphans.map((name) => ({\n\t\tseverity: 'info' as const,\n\t\ttype: 'orphan_entity',\n\t\tentity: name,\n\t\tmessage: `Entity \"${name}\" has no relationships to other entities`,\n\t\tsuggestion: 'Consider if this entity should be related to others',\n\t}));\n}\n\n/**\n * Check for circular references\n */\nfunction checkCircularReferences(graph: DomainGraph): AnalysisIssue[] {\n\tconst cycles = findCircularDependencies(graph);\n\treturn cycles.map((cycle) => ({\n\t\tseverity: 'info' as const,\n\t\ttype: 'circular_dependency',\n\t\tentity: cycle[0],\n\t\tmessage: `Circular reference detected: ${cycle.join(' -> ')}`,\n\t\tsuggestion: 'Verify this is intentional (e.g., self-referential hierarchy)',\n\t}));\n}\n\n/**\n * Check for missing inverse relationships\n */\nfunction checkMissingInverses(graph: DomainGraph): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tfor (const edge of graph.edges) {\n\t\tconst { from, to, relationship } = edge;\n\t\tconst targetEntity = graph.entities.get(to);\n\t\tif (!targetEntity) continue;\n\n\t\t// Check if target has an inverse relationship back to source\n\t\tconst hasInverse = Array.from(targetEntity.relationships.values()).some(\n\t\t\t(rel) => rel.target === from\n\t\t);\n\n\t\t// belongs_to relationships typically don't need explicit inverses\n\t\t// (the has_many on the other side serves as the inverse)\n\t\tif (!hasInverse && relationship.type !== 'belongs_to') {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'info',\n\t\t\t\ttype: 'missing_inverse',\n\t\t\t\tentity: from,\n\t\t\t\tfield: relationship.name,\n\t\t\t\tmessage: `Relationship \"${relationship.name}\" to \"${to}\" has no inverse defined on target`,\n\t\t\t\tsuggestion: `Add inverse relationship on \"${to}\" pointing back to \"${from}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Get the set of all valid field names for an entity, including behavior-added fields\n * and belongs_to foreign key fields (which the template emits as columns even when\n * not explicitly declared under `fields:`).\n */\nfunction getAvailableFieldNames(entity: ParsedEntity): string[] {\n\tconst entityFieldNames = Array.from(entity.fields.keys());\n\tconst behaviorFields = resolveBehaviorFields(entity.behaviors);\n\tconst behaviorFieldNames = behaviorFields.map((f) => f.name);\n\tconst belongsToFkNames: string[] = [];\n\tfor (const rel of entity.relationships.values()) {\n\t\tif (rel.type === 'belongs_to' && rel.foreignKey) {\n\t\t\tbelongsToFkNames.push(rel.foreignKey);\n\t\t}\n\t}\n\treturn [...new Set([...entityFieldNames, ...behaviorFieldNames, ...belongsToFkNames])];\n}\n\n/**\n * Check that query.by and query.select fields reference existing entity fields\n */\nfunction checkQueryFieldReferences(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst availableFields = getAvailableFieldNames(entity);\n\tconst availableSet = new Set(availableFields);\n\n\tfor (const query of entity.queries ?? []) {\n\t\t// Skip by-field validation when via is specified — those fields come from the junction table\n\t\tif (!query.via) {\n\t\t\tfor (const fieldName of query.by) {\n\t\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'error',\n\t\t\t\t\t\ttype: 'unknown_query_field',\n\t\t\t\t\t\tentity: entity.name,\n\t\t\t\t\t\tfield: fieldName,\n\t\t\t\t\t\tmessage: `Query references unknown field \"${fieldName}\" in entity \"${entity.name}\". Available fields: ${availableFields.join(', ')}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const fieldName of query.select ?? []) {\n\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'unknown_query_field',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t\tmessage: `Query references unknown field \"${fieldName}\" in entity \"${entity.name}\". Available fields: ${availableFields.join(', ')}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check that sync field_mapping keys and read_only_fields reference existing entity fields\n */\nfunction checkSyncFieldMappingReferences(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst availableFields = getAvailableFieldNames(entity);\n\tconst availableSet = new Set(availableFields);\n\n\tfor (const [providerName, provider] of Object.entries(entity.sync?.providers ?? {})) {\n\t\tfor (const fieldName of Object.keys(provider.fieldMapping ?? {})) {\n\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'unknown_sync_field_mapping',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t\tmessage: `Sync field mapping references unknown field \"${fieldName}\" for provider \"${providerName}\" in entity \"${entity.name}\"`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfor (const fieldName of provider.readOnlyFields ?? []) {\n\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'unknown_sync_field_mapping',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t\tmessage: `Sync field mapping references unknown field \"${fieldName}\" for provider \"${providerName}\" in entity \"${entity.name}\"`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for potential collision between external_id_tracking behavior and sync field_mapping\n */\nfunction checkExternalIdTrackingCollision(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tconst hasExternalIdTracking = entity.behaviors.includes('external_id_tracking');\n\tif (!hasExternalIdTracking) return issues;\n\n\tfor (const [providerName, provider] of Object.entries(entity.sync?.providers ?? {})) {\n\t\tif (provider.fieldMapping && 'external_id' in provider.fieldMapping) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'external_id_tracking_collision',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: 'external_id',\n\t\t\t\tmessage: `Entity \"${entity.name}\" has external_id_tracking behavior and also maps \"external_id\" in sync field_mapping for provider \"${providerName}\". The behavior-added field may collide with the mapped field.`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Convert string to snake_case\n */\nfunction toSnakeCase(str: string): string {\n\treturn str\n\t\t.replace(/([A-Z])/g, '_$1')\n\t\t.toLowerCase()\n\t\t.replace(/^_/, '');\n}\n","/**\n * Statistics\n *\n * Computes statistics about the domain model:\n * - Entity counts\n * - Field counts and type distribution\n * - Relationship counts and type distribution\n */\n\nimport type { ParsedEntity, DomainGraph, DomainStatistics } from './types';\n\n/**\n * Compute domain statistics from the graph\n */\nexport function computeStatistics(graph: DomainGraph): DomainStatistics {\n\tconst entities = Array.from(graph.entities.values());\n\n\tconst fieldsByType: Record<string, number> = {};\n\tconst relationshipsByType: Record<string, number> = {};\n\tlet totalFields = 0;\n\tlet totalRelationships = 0;\n\tlet entitiesWithBehaviors = 0;\n\n\tfor (const entity of entities) {\n\t\ttotalFields += entity.fields.size;\n\t\ttotalRelationships += entity.relationships.size;\n\n\t\tif (entity.behaviors.length > 0) {\n\t\t\tentitiesWithBehaviors++;\n\t\t}\n\n\t\t// Count fields by type\n\t\tfor (const field of entity.fields.values()) {\n\t\t\tfieldsByType[field.type] = (fieldsByType[field.type] ?? 0) + 1;\n\t\t}\n\n\t\t// Count relationships by type\n\t\tfor (const rel of entity.relationships.values()) {\n\t\t\trelationshipsByType[rel.type] = (relationshipsByType[rel.type] ?? 0) + 1;\n\t\t}\n\t}\n\n\treturn {\n\t\ttotalEntities: entities.length,\n\t\ttotalFields,\n\t\ttotalRelationships,\n\t\tfieldsByType,\n\t\trelationshipsByType,\n\t\tentitiesWithBehaviors,\n\t\taverageFieldsPerEntity: entities.length > 0 ? totalFields / entities.length : 0,\n\t};\n}\n\n/**\n * Get a breakdown of field properties\n */\nexport function getFieldBreakdown(graph: DomainGraph): {\n\trequired: number;\n\tnullable: number;\n\tindexed: number;\n\tunique: number;\n\twithForeignKey: number;\n\twithConstraints: number;\n} {\n\tlet required = 0;\n\tlet nullable = 0;\n\tlet indexed = 0;\n\tlet unique = 0;\n\tlet withForeignKey = 0;\n\tlet withConstraints = 0;\n\n\tfor (const entity of graph.entities.values()) {\n\t\tfor (const field of entity.fields.values()) {\n\t\t\tif (field.required) required++;\n\t\t\tif (field.nullable) nullable++;\n\t\t\tif (field.index) indexed++;\n\t\t\tif (field.unique) unique++;\n\t\t\tif (field.foreignKey) withForeignKey++;\n\n\t\t\tconst hasConstraints =\n\t\t\t\tfield.constraints.minLength !== undefined ||\n\t\t\t\tfield.constraints.maxLength !== undefined ||\n\t\t\t\tfield.constraints.min !== undefined ||\n\t\t\t\tfield.constraints.max !== undefined;\n\t\t\tif (hasConstraints) withConstraints++;\n\t\t}\n\t}\n\n\treturn { required, nullable, indexed, unique, withForeignKey, withConstraints };\n}\n\n/**\n * Get UI metadata coverage statistics\n */\nexport function getUiMetadataCoverage(graph: DomainGraph): {\n\twithLabel: number;\n\twithType: number;\n\twithGroup: number;\n\twithImportance: number;\n\ttotal: number;\n} {\n\tlet withLabel = 0;\n\tlet withType = 0;\n\tlet withGroup = 0;\n\tlet withImportance = 0;\n\tlet total = 0;\n\n\tfor (const entity of graph.entities.values()) {\n\t\tfor (const field of entity.fields.values()) {\n\t\t\ttotal++;\n\t\t\tif (field.ui.label) withLabel++;\n\t\t\tif (field.ui.type) withType++;\n\t\t\tif (field.ui.group) withGroup++;\n\t\t\tif (field.ui.importance) withImportance++;\n\t\t}\n\t}\n\n\treturn { withLabel, withType, withGroup, withImportance, total };\n}\n","/**\n * Pattern Registry — library + app pattern storage and discovery.\n *\n * Two stores keyed by pattern name:\n * - `LIBRARY_PATTERNS` — seeded by the codegen package itself when the\n * `src/patterns/library/*` barrel imports execute. Consumers never\n * list these in `codegen.config.yaml patterns:`.\n * - `APP_PATTERNS` — populated by `loadAppPatterns()` from a\n * consumer-supplied glob set (default `src/patterns/*.pattern.ts`).\n *\n * `getPattern()` checks app patterns first so a consumer could, in\n * principle, shadow a library pattern by using the same `name`. That's\n * not a documented feature, but nothing in the API prevents it.\n *\n * The Hygen subprocess (`src/cli/shared/hygen.ts:64`) reloads this module\n * independently — it has no shared memory with the CLI process. Both\n * loads are deterministic, side-effect-free reads of the same files, so\n * the registry contents are identical across processes. The registry\n * test suite asserts this determinism explicitly.\n *\n * See `docs/adrs/ADR-031-app-defined-patterns.md` §\"Decision 5\" and\n * `docs/specs/app-defined-patterns-implementation.md` §3.\n */\n\nimport { glob } from 'glob';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport {\n\tisPatternDefinition,\n\ttype PatternDefinition,\n} from './pattern-definition.js';\n\n// ============================================================================\n// Stores\n// ============================================================================\n\nconst LIBRARY_PATTERNS: Map<string, PatternDefinition> = new Map();\nconst APP_PATTERNS: Map<string, PatternDefinition> = new Map();\n\n/**\n * Every pattern must contribute *something* — either at least one column\n * or at least one of the two class references. A pattern that contributes\n * nothing would generate no useful output and almost certainly indicates\n * a typo or an unfinished definition.\n */\nfunction assertHasContribution(def: PatternDefinition): void {\n\tconst hasColumns = Array.isArray(def.columns) && def.columns.length > 0;\n\tconst hasRepo =\n\t\ttypeof def.repositoryClass === 'string' && def.repositoryClass.length > 0;\n\tconst hasService =\n\t\ttypeof def.serviceClass === 'string' && def.serviceClass.length > 0;\n\n\tif (!hasColumns && !hasRepo && !hasService) {\n\t\tthrow new Error(\n\t\t\t`Pattern '${def.name}' contributes nothing — at least one of ` +\n\t\t\t\t'`columns`, `repositoryClass`, or `serviceClass` is required.',\n\t\t);\n\t}\n}\n\n// ============================================================================\n// Library pattern registration\n// ============================================================================\n\n/**\n * Insert a library pattern into the registry. Called once by each\n * `src/patterns/library/*.pattern.ts` file via the barrel. Re-registering\n * the same name overwrites the previous value silently; this is\n * intentional for hot-reload scenarios but should not happen in normal\n * use.\n */\nexport function registerLibraryPattern(def: PatternDefinition): void {\n\tassertHasContribution(def);\n\tLIBRARY_PATTERNS.set(def.name, def);\n}\n\n// ============================================================================\n// Lookup\n// ============================================================================\n\n/**\n * Resolve a pattern by name. App patterns shadow library patterns with\n * the same name — useful in principle but not a documented feature.\n */\nexport function getPattern(name: string): PatternDefinition | undefined {\n\treturn APP_PATTERNS.get(name) ?? LIBRARY_PATTERNS.get(name);\n}\n\n/**\n * Return every registered pattern name (library + app), sorted for\n * deterministic output. The two-process determinism test relies on this\n * ordering being stable across processes.\n */\nexport function getAllPatternNames(): string[] {\n\tconst set = new Set<string>([\n\t\t...LIBRARY_PATTERNS.keys(),\n\t\t...APP_PATTERNS.keys(),\n\t]);\n\treturn [...set].sort();\n}\n\n/** Library-only view — mainly for debugging and tests. */\nexport function getLibraryPatternNames(): string[] {\n\treturn [...LIBRARY_PATTERNS.keys()].sort();\n}\n\n/** App-only view — mainly for debugging and tests. */\nexport function getAppPatternNames(): string[] {\n\treturn [...APP_PATTERNS.keys()].sort();\n}\n\n// ============================================================================\n// App pattern discovery\n// ============================================================================\n\nexport interface LoadAppPatternsResult {\n\t/** Pattern names that were successfully registered, sorted */\n\tloaded: string[];\n\t/** One human-readable error per failed file import */\n\terrors: string[];\n}\n\n/**\n * Expand every glob in `manifestPaths` relative to `cwd`, dynamic-import\n * each matching file, and register every exported value that passes\n * `isPatternDefinition()`. Exports whose name ends in `Pattern` and\n * pass the shape check are registered; other exports are ignored so\n * that files can export helper values alongside their pattern.\n *\n * Import failures are non-fatal — the error is collected and returned\n * so the CLI can surface it without breaking generation of unrelated\n * entities. A pattern that fails the \"at-least-one-contribution\" check\n * surfaces here as an error too.\n *\n * Idempotent: calling twice with the same arguments leaves `APP_PATTERNS`\n * in the same state as calling once.\n */\nexport async function loadAppPatterns(\n\tmanifestPaths: string[],\n\tcwd: string,\n): Promise<LoadAppPatternsResult> {\n\tconst loaded = new Set<string>();\n\tconst errors: string[] = [];\n\n\t// Collect + dedupe absolute file paths across every glob pattern so\n\t// a file matched by two globs is imported once.\n\tconst files = new Set<string>();\n\tfor (const raw of manifestPaths) {\n\t\ttry {\n\t\t\tconst expanded = await glob(raw, { cwd, absolute: true, nodir: true });\n\t\t\tfor (const filePath of expanded) {\n\t\t\t\tfiles.add(filePath);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\terrors.push(\n\t\t\t\t`Failed to expand pattern glob '${raw}': ${stringifyError(err)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Sort so dynamic-import order is deterministic across processes —\n\t// the Hygen subprocess relies on this to produce the same registry\n\t// as the CLI.\n\tconst sortedFiles = [...files].sort();\n\n\tfor (const filePath of sortedFiles) {\n\t\ttry {\n\t\t\t// `pathToFileURL` is required for absolute-path dynamic imports on\n\t\t\t// Windows and makes the behavior identical on macOS/Linux.\n\t\t\tconst mod = (await import(pathToFileURL(filePath).href)) as Record<\n\t\t\t\tstring,\n\t\t\t\tunknown\n\t\t\t>;\n\t\t\tfor (const [key, val] of Object.entries(mod)) {\n\t\t\t\tif (!key.endsWith('Pattern')) continue;\n\t\t\t\tif (!isPatternDefinition(val)) continue;\n\t\t\t\ttry {\n\t\t\t\t\tassertHasContribution(val);\n\t\t\t\t\tAPP_PATTERNS.set(val.name, val);\n\t\t\t\t\tloaded.add(val.name);\n\t\t\t\t} catch (assertErr) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Pattern '${val.name}' in ${relPath(filePath, cwd)} is invalid: ${stringifyError(assertErr)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\terrors.push(\n\t\t\t\t`Failed to load pattern file '${relPath(filePath, cwd)}': ${stringifyError(err)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn {\n\t\tloaded: [...loaded].sort(),\n\t\terrors,\n\t};\n}\n\n// ============================================================================\n// Test-only reset\n// ============================================================================\n\n/**\n * Clear every registered app pattern and, optionally, library patterns too.\n *\n * Intended for unit tests that build isolated scenarios on top of a clean\n * registry. Not exported from the barrel — tests import it directly from\n * `./registry.js`.\n */\nexport function _resetRegistryForTests(\n\topts: { includeLibrary?: boolean } = {},\n): void {\n\tAPP_PATTERNS.clear();\n\tif (opts.includeLibrary) {\n\t\tLIBRARY_PATTERNS.clear();\n\t}\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction stringifyError(err: unknown): string {\n\tif (err instanceof Error) return err.message;\n\treturn String(err);\n}\n\nfunction relPath(abs: string, cwd: string): string {\n\ttry {\n\t\treturn path.relative(cwd, abs) || abs;\n\t} catch {\n\t\treturn abs;\n\t}\n}\n","/**\n * Pattern Definition — pure metadata record returned by an identity function.\n *\n * `definePattern()` is the registration artifact for both library-shipped and\n * app-defined patterns. It carries only names + import paths for the classes\n * a generated entity should extend — never the class constructors themselves.\n * This keeps the codegen pipeline free of TS class-evaluation cost and avoids\n * `reflect-metadata`, which lets the Hygen subprocess cheaply rebuild the\n * registry (see `src/cli/shared/hygen.ts` — the registry loads twice per\n * `entity new` invocation).\n *\n * See `docs/adrs/ADR-031-app-defined-patterns.md` §\"Decision 1\" for the\n * binding surface and `docs/specs/app-defined-patterns-implementation.md` §1\n * for the file-by-file rationale.\n */\n\nimport type { ZodSchema } from 'zod';\n\n/**\n * A column a pattern contributes to every entity that declares it.\n *\n * Column-level conflicts between patterns, between a pattern and an\n * entity-declared field, or between a pattern and a behavior-contributed\n * field are codegen-time hard errors; see\n * `src/patterns/validate-composition.ts`.\n */\nexport interface PatternColumnContribution {\n\t/** snake_case column name — matches the database column */\n\tname: string;\n\t/** Drizzle column type string, e.g. \"varchar(255)\" or \"text\" */\n\ttype: string;\n}\n\n/**\n * The full pattern metadata record. Every `definePattern({...})` call\n * returns a value of this shape; the library and consumer registries\n * store these and look them up by `name`.\n */\nexport interface PatternDefinition<TConfig = unknown> {\n\t/** Unique name used in YAML — e.g. `pattern: Synced` */\n\tname: string;\n\n\t/**\n\t * Built-in patterns this extends, by name. Phase 1 supports single-depth\n\t * chains only — a pattern may `extends: ['Synced']` but the transitive\n\t * chain is not yet resolved. Multi-depth inheritance is deferred until\n\t * a real consumer asks.\n\t */\n\textends?: string[];\n\n\t/** Constructor name codegen emits in the generated repo's `extends` clause */\n\trepositoryClass?: string;\n\t/** Constructor name codegen emits in the generated service's `extends` clause */\n\tserviceClass?: string;\n\n\t/**\n\t * Fully-qualified TypeScript path alias the consumer's tsconfig resolves.\n\t * Library patterns use the consumer-installed runtime base class path\n\t * (e.g. `@shared/base-classes/synced-entity-repository`); app patterns\n\t * use whatever alias the consumer has configured (e.g. `@/patterns/...`).\n\t */\n\trepositoryImport?: string;\n\t/** Same as `repositoryImport` but for the service base class */\n\tserviceImport?: string;\n\n\t/**\n\t * Documentation-only method-signature strings emitted as comments in the\n\t * generated repo. Exist purely so app authors reading the generated file\n\t * see what their concrete class inherits without jumping to the base.\n\t */\n\trepositoryInheritedMethods?: string[];\n\t/** Same as `repositoryInheritedMethods` but for the service base class */\n\tserviceInheritedMethods?: string[];\n\n\t/**\n\t * Columns this pattern adds to every entity that declares it. Used by\n\t * the composition validator to detect column-name collisions.\n\t */\n\tcolumns?: PatternColumnContribution[];\n\n\t/**\n\t * Behaviors this pattern implicitly enables. Entity YAML need not\n\t * re-declare them; duplicates across patterns are silent-deduped.\n\t */\n\timpliedBehaviors?: string[];\n\n\t/**\n\t * Zod schema that validates the per-entity `config:` block for this\n\t * pattern at parse time. When absent, entities may not supply a `config:`\n\t * entry for this pattern and codegen emits no `patternConfig` property.\n\t */\n\tconfigSchema?: ZodSchema<TConfig>;\n\n\t/** One-line description for codegen help output and error messages */\n\tdescription?: string;\n}\n\n/**\n * Identity function that returns its argument unchanged. The body is trivial\n * on purpose — the whole point is to give TypeScript a hook for generic\n * inference on `TConfig` while leaving the runtime value a plain object\n * registered by the codegen loader.\n */\nexport function definePattern<TConfig = unknown>(\n\tdef: PatternDefinition<TConfig>,\n): PatternDefinition<TConfig> {\n\treturn def;\n}\n\n/**\n * Shape check for values produced by `import()`ing an app pattern file.\n * The registry loader runs this on every exported value it finds; only\n * values that pass are registered.\n *\n * We keep this deliberately loose — a `name` string is the whole\n * requirement — because a pattern that contributes neither columns nor\n * class references is still a *valid* identity pattern (e.g. `BasePattern`\n * exists to anchor the `extends` chain without contributing anything).\n * Stricter shape rules belong in the registry's \"at-least-one-contribution\"\n * check, not here.\n */\nexport function isPatternDefinition(val: unknown): val is PatternDefinition {\n\treturn (\n\t\ttypeof val === 'object' &&\n\t\tval !== null &&\n\t\t'name' in val &&\n\t\ttypeof (val as { name: unknown }).name === 'string'\n\t);\n}\n","/**\n * Pattern Composition Validator\n *\n * Enforces the ADR-031 composition rules against parsed entities:\n *\n * | Case | Result |\n * |------------------------------------------------------------|------------------------|\n * | Column conflict between two patterns | error |\n * | Column conflict with entity field | error |\n * | Column conflict with a behavior field | error |\n * | Method-name conflict between patterns | (TS compile error) |\n * | Same implied behavior across patterns | silent dedup |\n * | Pattern referenced in YAML but not in the registry | error |\n * | `config:` key for a pattern the entity is not using | warning |\n * | Pattern config fails its Zod schema | error |\n *\n * Method-name conflicts are explicitly **not** checked here — they surface as\n * TypeScript compile errors at the consumer when the generated concrete\n * class extends the base. Adding a codegen check would duplicate work\n * the type system already does, so we stay silent on that row per ADR-031.\n *\n * Project-level validation (`validatePatternProject`) covers plan Risk 4:\n * entities declaring `pattern:` while `generate.architecture: clean` is\n * selected get a warning since the `clean` pipeline does not yet consume\n * patterns. Additive Phase 3+ work per ADR.\n *\n * The shape mirrors `src/behaviors/index.ts:81–124` (`validateBehaviors`):\n * a single pass that returns structured issues for `analyzeDomain()` to\n * aggregate.\n */\n\nimport type { AnalysisIssue, ParsedEntity } from '../analyzer/types.js';\nimport { resolveBehaviorFields } from '../behaviors/index.js';\nimport { getPattern } from './registry.js';\n\n// ============================================================================\n// Per-entity validation\n// ============================================================================\n\n/**\n * Validate pattern composition for a single entity. Returns an array of\n * `AnalysisIssue` values suitable for concatenation into `analyzeDomain`'s\n * aggregated issue list.\n *\n * Entities with no `pattern:` or `patterns:` declared return an empty\n * array — pattern-free entities are a valid use case (plain `BaseRepository`\n * fallback) and nothing below applies to them.\n */\nexport function validatePatternComposition(\n\tentity: ParsedEntity,\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Normalise `pattern:` (single) and `patterns:` (multi) into one list,\n\t// preserving declaration order. `pattern` + `patterns` mutual exclusion\n\t// is a schema-level check — by the time we get here, at most one shape\n\t// is set.\n\tconst patternNames: string[] = entity.patterns ?? (entity.pattern ? [entity.pattern] : []);\n\tif (patternNames.length === 0) return issues;\n\n\t// Column-source tracker: maps column name → human-readable origin.\n\t// Populated in priority order (entity fields > behavior fields >\n\t// pattern contributions) so conflict messages name the *existing*\n\t// contributor correctly.\n\tconst columnSources = new Map<string, string>();\n\n\tfor (const [name] of entity.fields) {\n\t\tcolumnSources.set(name, `entity field '${name}'`);\n\t}\n\n\t// Behavior fields participate in conflict detection. Behaviors the\n\t// entity has NOT already declared but that a pattern implies will be\n\t// added below (silent dedup); conflicts against those show up when\n\t// the pattern's columns are checked.\n\tconst behaviorFields = resolveBehaviorFields(entity.behaviors);\n\tfor (const bf of behaviorFields) {\n\t\tconst existing = columnSources.get(bf.name);\n\t\tif (existing) {\n\t\t\t// A behavior field colliding with an entity-declared field\n\t\t\t// was already a codegen problem before patterns existed. We\n\t\t\t// surface it here too so the composition check is the single\n\t\t\t// authoritative pass for \"column conflicts on this entity.\"\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'pattern_column_conflict',\n\t\t\t\tentity: entity.name,\n\t\t\t\tmessage:\n\t\t\t\t\t`Behavior-contributed field '${bf.name}' conflicts with ${existing}.`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tcolumnSources.set(bf.name, `behavior field '${bf.name}'`);\n\t}\n\n\t// Track implied behaviors across all declared patterns so we can\n\t// assert silent dedup rather than repeat issues — this also lets us\n\t// return the deduped list for callers that want to thread it into\n\t// template-locals later without re-walking.\n\tconst impliedBehaviors = new Set<string>(entity.behaviors);\n\n\tfor (const patternName of patternNames) {\n\t\tconst def = getPattern(patternName);\n\n\t\t// Rule: pattern referenced in YAML but not in the registry\n\t\tif (!def) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'pattern_unknown',\n\t\t\t\tentity: entity.name,\n\t\t\t\tmessage:\n\t\t\t\t\t`Unknown pattern '${patternName}'. ` +\n\t\t\t\t\t`Library patterns are pre-registered; app patterns are loaded from ` +\n\t\t\t\t\t`globs in codegen.config.yaml 'patterns:' (default 'src/patterns/*.pattern.ts').`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Rule: pattern config must match the pattern's Zod schema\n\t\tif (def.configSchema) {\n\t\t\tconst rawConfig = entity.patternConfig?.[patternName];\n\t\t\tconst result = def.configSchema.safeParse(rawConfig ?? {});\n\t\t\tif (!result.success) {\n\t\t\t\tconst detail = result.error.issues\n\t\t\t\t\t.map((i) => `${i.path.join('.') || '<root>'}: ${i.message}`)\n\t\t\t\t\t.join(', ');\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'pattern_config_invalid',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Pattern '${patternName}' config failed validation: ${detail}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Rule: column contributions conflict with anything already in the\n\t\t// column-sources table. The first column to claim a name wins; the\n\t\t// second one reports the conflict naming both contributors.\n\t\tfor (const col of def.columns ?? []) {\n\t\t\tconst existing = columnSources.get(col.name);\n\t\t\tif (existing) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'pattern_column_conflict',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Pattern '${patternName}' contributes column '${col.name}' ` +\n\t\t\t\t\t\t`which conflicts with ${existing}.`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcolumnSources.set(col.name, `pattern '${patternName}'`);\n\t\t}\n\n\t\t// Silent dedup on implied behaviors — a pattern declaring a\n\t\t// behavior the entity already has (or another pattern already\n\t\t// contributed) is a no-op, not an error.\n\t\tfor (const b of def.impliedBehaviors ?? []) {\n\t\t\timpliedBehaviors.add(b);\n\t\t}\n\t}\n\n\t// Rule: `config:` key for a pattern not in the declared list → warning.\n\tif (entity.patternConfig) {\n\t\tconst declared = new Set(patternNames);\n\t\tfor (const key of Object.keys(entity.patternConfig)) {\n\t\t\tif (!declared.has(key)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'pattern_config_unused',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Config block has key '${key}' but pattern '${key}' is not ` +\n\t\t\t\t\t\t`declared in 'pattern:' or 'patterns:'. Remove the entry or ` +\n\t\t\t\t\t\t`add the pattern.`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n// ============================================================================\n// Project-level validation — plan Risk 4\n// ============================================================================\n\nexport interface PatternProjectContext {\n\tentities: ReadonlyArray<ParsedEntity>;\n\t/**\n\t * Selected backend architecture from `codegen.config.yaml\n\t * generate.architecture`. `undefined` when the consumer is using the\n\t * library purely as an analyzer (no generation config loaded).\n\t */\n\tarchitecture?: string;\n}\n\n/**\n * Validate project-level invariants for patterns. Runs after\n * `validatePatternComposition` has visited every entity, so we can\n * assume per-entity errors have been surfaced.\n *\n * Today this only covers plan Risk 4: warn when patterns are declared\n * but the selected architecture is `clean`, which does not yet consume\n * them. A `clean` consumer with `pattern: Synced` is not broken — the\n * `clean` pipeline ignores the key — but they see no effect, which is\n * confusing without the warning.\n */\nexport function validatePatternProject(\n\tctx: PatternProjectContext,\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tif (ctx.architecture === 'clean') {\n\t\tconst withPatterns = ctx.entities.filter(\n\t\t\t(e) => (e.patterns && e.patterns.length > 0) || !!e.pattern,\n\t\t);\n\t\tfor (const e of withPatterns) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'pattern_clean_pipeline_noop',\n\t\t\t\tentity: e.name,\n\t\t\t\tmessage:\n\t\t\t\t\t`'pattern:' is declared but 'generate.architecture: clean' does not ` +\n\t\t\t\t\t`yet consume patterns. This declaration is a no-op. Patterns are ` +\n\t\t\t\t\t`consumed by 'clean-lite-ps' today; 'clean' integration is Phase 3+ ` +\n\t\t\t\t\t`additive work (ADR-031).`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n","/**\n * Console Formatter\n *\n * Pretty terminal output with colors for the domain analysis results.\n */\n\nimport type { AnalysisResult, AnalysisIssue, Severity } from '../analyzer/types';\n\n// ANSI color codes\nconst colors = {\n\treset: '\\x1b[0m',\n\tbold: '\\x1b[1m',\n\tdim: '\\x1b[2m',\n\n\tred: '\\x1b[31m',\n\tgreen: '\\x1b[32m',\n\tyellow: '\\x1b[33m',\n\tblue: '\\x1b[34m',\n\tmagenta: '\\x1b[35m',\n\tcyan: '\\x1b[36m',\n\twhite: '\\x1b[37m',\n\n\tbgRed: '\\x1b[41m',\n\tbgGreen: '\\x1b[42m',\n\tbgYellow: '\\x1b[43m',\n};\n\nfunction color(text: string, ...styles: string[]): string {\n\treturn `${styles.join('')}${text}${colors.reset}`;\n}\n\nfunction severityColor(severity: Severity): string {\n\tswitch (severity) {\n\t\tcase 'error':\n\t\t\treturn colors.red;\n\t\tcase 'warning':\n\t\t\treturn colors.yellow;\n\t\tcase 'info':\n\t\t\treturn colors.cyan;\n\t}\n}\n\nfunction severityIcon(severity: Severity): string {\n\tswitch (severity) {\n\t\tcase 'error':\n\t\t\treturn 'X';\n\t\tcase 'warning':\n\t\t\treturn '!';\n\t\tcase 'info':\n\t\t\treturn 'i';\n\t}\n}\n\n/**\n * Format analysis result for console output\n */\nexport function formatConsole(result: AnalysisResult): string {\n\tconst lines: string[] = [];\n\n\t// Header\n\tlines.push('');\n\tlines.push(color('='.repeat(60), colors.dim));\n\tlines.push(color(' Domain Analysis Report', colors.bold, colors.cyan));\n\tlines.push(color('='.repeat(60), colors.dim));\n\tlines.push('');\n\n\t// Statistics\n\tlines.push(...formatStatistics(result));\n\n\t// Entity summary\n\tlines.push(...formatEntities(result));\n\n\t// Relationships\n\tlines.push(...formatRelationships(result));\n\n\t// Issues\n\tif (result.issues.length > 0) {\n\t\tlines.push(...formatIssues(result.issues));\n\t}\n\n\t// Final status\n\tlines.push('');\n\tlines.push(color('-'.repeat(60), colors.dim));\n\n\tconst errors = result.issues.filter((i) => i.severity === 'error');\n\tconst warnings = result.issues.filter((i) => i.severity === 'warning');\n\tconst infos = result.issues.filter((i) => i.severity === 'info');\n\n\tif (result.isValid) {\n\t\tlines.push(\n\t\t\tcolor(\n\t\t\t\t`[OK] Domain is valid (${warnings.length} warnings, ${infos.length} info)`,\n\t\t\t\tcolors.green\n\t\t\t)\n\t\t);\n\t} else {\n\t\tlines.push(color(`[FAIL] Domain has ${errors.length} errors`, colors.red));\n\t}\n\n\tlines.push(color('-'.repeat(60), colors.dim));\n\tlines.push('');\n\n\treturn lines.join('\\n');\n}\n\nfunction formatStatistics(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\tconst stats = result.statistics;\n\n\tlines.push(color('Statistics:', colors.bold));\n\tlines.push('');\n\tlines.push(` Entities: ${stats.totalEntities}`);\n\tlines.push(\n\t\t` Fields: ${stats.totalFields} (avg ${stats.averageFieldsPerEntity.toFixed(1)}/entity)`\n\t);\n\tlines.push(` Relationships: ${stats.totalRelationships}`);\n\tlines.push(` With behaviors: ${stats.entitiesWithBehaviors}`);\n\tlines.push('');\n\n\t// Field types breakdown\n\tlines.push(' Field types:');\n\tconst sortedTypes = Object.entries(stats.fieldsByType).sort((a, b) => b[1] - a[1]);\n\tfor (const [type, count] of sortedTypes) {\n\t\tconst bar = color('|'.repeat(Math.min(count, 20)), colors.blue);\n\t\tlines.push(` ${type.padEnd(12)} ${bar} ${count}`);\n\t}\n\tlines.push('');\n\n\t// Relationship types breakdown\n\tif (stats.totalRelationships > 0) {\n\t\tlines.push(' Relationship types:');\n\t\tconst sortedRels = Object.entries(stats.relationshipsByType).sort((a, b) => b[1] - a[1]);\n\t\tfor (const [type, count] of sortedRels) {\n\t\t\tconst bar = color('|'.repeat(Math.min(count, 20)), colors.magenta);\n\t\t\tlines.push(` ${type.padEnd(12)} ${bar} ${count}`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\treturn lines;\n}\n\nfunction formatEntities(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\n\tlines.push(color('Entities:', colors.bold));\n\tlines.push('');\n\n\tfor (const entity of result.entities) {\n\t\tconst fieldCount = entity.fields.size;\n\t\tconst relCount = entity.relationships.size;\n\t\tlines.push(\n\t\t\t` ${color(entity.name, colors.cyan)} (${fieldCount} fields, ${relCount} relationships)`\n\t\t);\n\t\tif (entity.behaviors.length > 0) {\n\t\t\tlines.push(color(` behaviors: ${entity.behaviors.join(', ')}`, colors.dim));\n\t\t}\n\t}\n\tlines.push('');\n\n\treturn lines;\n}\n\nfunction formatRelationships(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\n\tif (result.graph.edges.length === 0) {\n\t\treturn lines;\n\t}\n\n\tlines.push(color('Relationships:', colors.bold));\n\tlines.push('');\n\n\tfor (const edge of result.graph.edges) {\n\t\tconst arrow = getCardinalityArrow(edge.cardinality);\n\t\tconst bidir = edge.bidirectional ? color(' (bidirectional)', colors.dim) : '';\n\t\tlines.push(\n\t\t\t` ${edge.from.padEnd(20)} ${arrow} ${edge.to} ${color(`(${edge.relationship.type})`, colors.dim)}${bidir}`\n\t\t);\n\t}\n\tlines.push('');\n\n\treturn lines;\n}\n\nfunction getCardinalityArrow(cardinality: string): string {\n\tswitch (cardinality) {\n\t\tcase '1:N':\n\t\t\treturn color('--<', colors.magenta);\n\t\tcase 'N:1':\n\t\t\treturn color('>--', colors.magenta);\n\t\tcase '1:1':\n\t\t\treturn color('---', colors.magenta);\n\t\tcase 'N:M':\n\t\t\treturn color('>-<', colors.magenta);\n\t\tdefault:\n\t\t\treturn color('-->', colors.magenta);\n\t}\n}\n\nfunction formatIssues(issues: AnalysisIssue[]): string[] {\n\tconst lines: string[] = [];\n\n\t// Group by severity\n\tconst errors = issues.filter((i) => i.severity === 'error');\n\tconst warnings = issues.filter((i) => i.severity === 'warning');\n\tconst infos = issues.filter((i) => i.severity === 'info');\n\n\tif (errors.length > 0) {\n\t\tlines.push(color(`Errors (${errors.length}):`, colors.bold, colors.red));\n\t\tlines.push('');\n\t\tlines.push(...formatIssueList(errors, 'error'));\n\t\tlines.push('');\n\t}\n\n\tif (warnings.length > 0) {\n\t\tlines.push(color(`Warnings (${warnings.length}):`, colors.bold, colors.yellow));\n\t\tlines.push('');\n\t\tlines.push(...formatIssueList(warnings, 'warning'));\n\t\tlines.push('');\n\t}\n\n\tif (infos.length > 0) {\n\t\tlines.push(color(`Info (${infos.length}):`, colors.bold, colors.cyan));\n\t\tlines.push('');\n\t\tlines.push(...formatIssueList(infos, 'info', 5)); // Only show first 5 info messages\n\t\tlines.push('');\n\t}\n\n\treturn lines;\n}\n\nfunction formatIssueList(\n\tissues: AnalysisIssue[],\n\tseverity: Severity,\n\tlimit?: number\n): string[] {\n\tconst lines: string[] = [];\n\tconst displayIssues = limit ? issues.slice(0, limit) : issues;\n\n\t// Group by type\n\tconst byType = new Map<string, AnalysisIssue[]>();\n\tfor (const issue of displayIssues) {\n\t\tconst list = byType.get(issue.type) ?? [];\n\t\tlist.push(issue);\n\t\tbyType.set(issue.type, list);\n\t}\n\n\tfor (const [type, typeIssues] of byType) {\n\t\tlines.push(color(` ${type} (${typeIssues.length}):`, colors.dim));\n\n\t\tfor (const issue of typeIssues.slice(0, 5)) {\n\t\t\tconst location = issue.entity\n\t\t\t\t? `${issue.entity}${issue.field ? '.' + issue.field : ''}`\n\t\t\t\t: issue.path ?? 'unknown';\n\n\t\t\tconst icon = color(`[${severityIcon(severity)}]`, severityColor(severity));\n\t\t\tlines.push(` ${icon} ${color(location, colors.bold)}: ${issue.message}`);\n\n\t\t\tif (issue.suggestion) {\n\t\t\t\tlines.push(color(` -> ${issue.suggestion}`, colors.dim));\n\t\t\t}\n\t\t}\n\n\t\tif (typeIssues.length > 5) {\n\t\t\tlines.push(color(` ... and ${typeIssues.length - 5} more`, colors.dim));\n\t\t}\n\t}\n\n\tif (limit && issues.length > limit) {\n\t\tlines.push(color(` ... and ${issues.length - limit} more info messages`, colors.dim));\n\t}\n\n\treturn lines;\n}\n","/**\n * JSON Formatter\n *\n * Machine-readable JSON output for the domain analysis results.\n */\n\nimport type { AnalysisResult, ParsedEntity, DomainGraph } from '../analyzer/types';\n\n/**\n * Helper to convert Maps to plain objects for JSON serialization\n */\nfunction mapToObject<K extends string, V>(map: Map<K, V>): Record<K, V> {\n\tconst obj = {} as Record<K, V>;\n\tfor (const [key, value] of map) {\n\t\tobj[key] = value;\n\t}\n\treturn obj;\n}\n\n/**\n * Convert ParsedEntity to a JSON-serializable format\n */\nfunction serializeEntity(entity: ParsedEntity): Record<string, unknown> {\n\treturn {\n\t\tname: entity.name,\n\t\tplural: entity.plural,\n\t\ttable: entity.table,\n\t\tfolderStructure: entity.folderStructure,\n\t\tfields: mapToObject(entity.fields),\n\t\trelationships: mapToObject(entity.relationships),\n\t\tbehaviors: entity.behaviors,\n\t\tsourcePath: entity.sourcePath,\n\t};\n}\n\n/**\n * Convert DomainGraph to a JSON-serializable format\n */\nfunction serializeGraph(graph: DomainGraph): Record<string, unknown> {\n\tconst entities: Record<string, unknown> = {};\n\tfor (const [name, entity] of graph.entities) {\n\t\tentities[name] = serializeEntity(entity);\n\t}\n\n\treturn {\n\t\tentities,\n\t\tedges: graph.edges,\n\t};\n}\n\n/**\n * Format analysis result as JSON string\n */\nexport function formatJson(result: AnalysisResult, pretty = true): string {\n\tconst output = {\n\t\tisValid: result.isValid,\n\t\tsummary: {\n\t\t\tentities: result.statistics.totalEntities,\n\t\t\tfields: result.statistics.totalFields,\n\t\t\trelationships: result.statistics.totalRelationships,\n\t\t\terrors: result.issues.filter((i) => i.severity === 'error').length,\n\t\t\twarnings: result.issues.filter((i) => i.severity === 'warning').length,\n\t\t\tinfo: result.issues.filter((i) => i.severity === 'info').length,\n\t\t},\n\t\tentities: result.entities.map(serializeEntity),\n\t\tgraph: serializeGraph(result.graph),\n\t\tissues: result.issues,\n\t\tstatistics: result.statistics,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n\n\treturn pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output);\n}\n\n/**\n * Format only statistics as JSON\n */\nexport function formatStatsJson(result: AnalysisResult, pretty = true): string {\n\tconst output = {\n\t\tstatistics: result.statistics,\n\t\tisValid: result.isValid,\n\t\tissueCount: {\n\t\t\terrors: result.issues.filter((i) => i.severity === 'error').length,\n\t\t\twarnings: result.issues.filter((i) => i.severity === 'warning').length,\n\t\t\tinfo: result.issues.filter((i) => i.severity === 'info').length,\n\t\t},\n\t\ttimestamp: new Date().toISOString(),\n\t};\n\n\treturn pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output);\n}\n\n/**\n * Format only issues as JSON\n */\nexport function formatIssuesJson(result: AnalysisResult, pretty = true): string {\n\tconst output = {\n\t\tisValid: result.isValid,\n\t\tissues: result.issues,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n\n\treturn pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output);\n}\n","/**\n * Markdown Formatter\n *\n * Documentation output with Mermaid diagrams for the domain analysis results.\n */\n\nimport type { AnalysisResult, ParsedEntity, RelationshipEdge } from '../analyzer/types';\n\n/**\n * Format analysis result as Markdown documentation\n */\nexport function formatMarkdown(result: AnalysisResult): string {\n\tconst lines: string[] = [];\n\n\t// Title\n\tlines.push('# Domain Model Documentation');\n\tlines.push('');\n\tlines.push(`Generated: ${new Date().toISOString()}`);\n\tlines.push('');\n\n\t// Overview statistics\n\tlines.push('## Overview');\n\tlines.push('');\n\tlines.push('| Metric | Value |');\n\tlines.push('|--------|-------|');\n\tlines.push(`| Entities | ${result.statistics.totalEntities} |`);\n\tlines.push(`| Total Fields | ${result.statistics.totalFields} |`);\n\tlines.push(`| Total Relationships | ${result.statistics.totalRelationships} |`);\n\tlines.push(\n\t\t`| Avg Fields/Entity | ${result.statistics.averageFieldsPerEntity.toFixed(1)} |`\n\t);\n\tlines.push('');\n\n\t// Field type distribution\n\tlines.push('### Field Type Distribution');\n\tlines.push('');\n\tlines.push('| Type | Count |');\n\tlines.push('|------|-------|');\n\tconst sortedTypes = Object.entries(result.statistics.fieldsByType).sort(\n\t\t(a, b) => b[1] - a[1]\n\t);\n\tfor (const [type, count] of sortedTypes) {\n\t\tlines.push(`| ${type} | ${count} |`);\n\t}\n\tlines.push('');\n\n\t// Relationship type distribution\n\tif (result.statistics.totalRelationships > 0) {\n\t\tlines.push('### Relationship Type Distribution');\n\t\tlines.push('');\n\t\tlines.push('| Type | Count |');\n\t\tlines.push('|------|-------|');\n\t\tconst sortedRels = Object.entries(result.statistics.relationshipsByType).sort(\n\t\t\t(a, b) => b[1] - a[1]\n\t\t);\n\t\tfor (const [type, count] of sortedRels) {\n\t\t\tlines.push(`| ${type} | ${count} |`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\t// Entity Relationship Diagram\n\tlines.push('## Entity Relationship Diagram');\n\tlines.push('');\n\tlines.push('```mermaid');\n\tlines.push(...generateMermaidErDiagram(result));\n\tlines.push('```');\n\tlines.push('');\n\n\t// Entities\n\tlines.push('## Entities');\n\tlines.push('');\n\n\tfor (const entity of result.entities) {\n\t\tlines.push(...formatEntitySection(entity));\n\t}\n\n\t// Issues\n\tconst errors = result.issues.filter((i) => i.severity === 'error');\n\tconst warnings = result.issues.filter((i) => i.severity === 'warning');\n\tconst infos = result.issues.filter((i) => i.severity === 'info');\n\n\tif (result.issues.length > 0) {\n\t\tlines.push('## Analysis Issues');\n\t\tlines.push('');\n\n\t\tif (errors.length > 0) {\n\t\t\tlines.push('### Errors');\n\t\t\tlines.push('');\n\t\t\tfor (const issue of errors) {\n\t\t\t\tconst location = issue.entity\n\t\t\t\t\t? `**${issue.entity}${issue.field ? '.' + issue.field : ''}**`\n\t\t\t\t\t: issue.path ?? 'unknown';\n\t\t\t\tlines.push(`- [${issue.type}] ${location}: ${issue.message}`);\n\t\t\t\tif (issue.suggestion) {\n\t\t\t\t\tlines.push(` - Suggestion: ${issue.suggestion}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlines.push('');\n\t\t}\n\n\t\tif (warnings.length > 0) {\n\t\t\tlines.push('### Warnings');\n\t\t\tlines.push('');\n\t\t\tfor (const issue of warnings) {\n\t\t\t\tconst location = issue.entity\n\t\t\t\t\t? `**${issue.entity}${issue.field ? '.' + issue.field : ''}**`\n\t\t\t\t\t: issue.path ?? 'unknown';\n\t\t\t\tlines.push(`- [${issue.type}] ${location}: ${issue.message}`);\n\t\t\t\tif (issue.suggestion) {\n\t\t\t\t\tlines.push(` - Suggestion: ${issue.suggestion}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlines.push('');\n\t\t}\n\n\t\tif (infos.length > 0) {\n\t\t\tlines.push('### Info');\n\t\t\tlines.push('');\n\t\t\tlines.push('<details>');\n\t\t\tlines.push('<summary>Show info messages</summary>');\n\t\t\tlines.push('');\n\t\t\tfor (const issue of infos) {\n\t\t\t\tconst location = issue.entity\n\t\t\t\t\t? `**${issue.entity}${issue.field ? '.' + issue.field : ''}**`\n\t\t\t\t\t: issue.path ?? 'unknown';\n\t\t\t\tlines.push(`- [${issue.type}] ${location}: ${issue.message}`);\n\t\t\t}\n\t\t\tlines.push('');\n\t\t\tlines.push('</details>');\n\t\t\tlines.push('');\n\t\t}\n\t}\n\n\treturn lines.join('\\n');\n}\n\n/**\n * Format a single entity section\n */\nfunction formatEntitySection(entity: ParsedEntity): string[] {\n\tconst lines: string[] = [];\n\n\tlines.push(`### ${entity.name}`);\n\tlines.push('');\n\tlines.push(`**Table:** \\`${entity.table}\\``);\n\tlines.push(`**Plural:** ${entity.plural}`);\n\tif (entity.behaviors.length > 0) {\n\t\tlines.push(`**Behaviors:** ${entity.behaviors.join(', ')}`);\n\t}\n\tlines.push('');\n\n\t// Fields table\n\tlines.push('#### Fields');\n\tlines.push('');\n\tlines.push('| Name | Type | Required | Nullable | Index | Foreign Key |');\n\tlines.push('|------|------|----------|----------|-------|-------------|');\n\n\tfor (const [name, field] of entity.fields) {\n\t\tconst required = field.required ? 'Yes' : '';\n\t\tconst nullable = field.nullable ? 'Yes' : '';\n\t\tconst index = field.index ? 'Yes' : field.unique ? 'Unique' : '';\n\t\tconst fk = field.foreignKey ? `${field.foreignKey.table}.${field.foreignKey.column}` : '';\n\t\tlines.push(`| ${name} | ${field.type} | ${required} | ${nullable} | ${index} | ${fk} |`);\n\t}\n\tlines.push('');\n\n\t// Relationships\n\tif (entity.relationships.size > 0) {\n\t\tlines.push('#### Relationships');\n\t\tlines.push('');\n\t\tlines.push('| Name | Type | Target | Foreign Key |');\n\t\tlines.push('|------|------|--------|-------------|');\n\n\t\tfor (const [name, rel] of entity.relationships) {\n\t\t\tlines.push(`| ${name} | ${rel.type} | ${rel.target} | ${rel.foreignKey} |`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\treturn lines;\n}\n\n/**\n * Generate Mermaid ER diagram\n */\nfunction generateMermaidErDiagram(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\n\tlines.push('erDiagram');\n\n\t// Define entities with their fields\n\tfor (const entity of result.entities) {\n\t\tconst entityName = entity.name.toUpperCase();\n\t\tlines.push(` ${entityName} {`);\n\n\t\t// Show key fields only (to keep diagram readable)\n\t\tconst keyFields = Array.from(entity.fields.entries())\n\t\t\t.filter(\n\t\t\t\t([name, field]) =>\n\t\t\t\t\tfield.foreignKey || field.unique || field.index || name === 'id' || name === 'name'\n\t\t\t)\n\t\t\t.slice(0, 6); // Limit to 6 fields\n\n\t\tfor (const [name, field] of keyFields) {\n\t\t\tconst typeStr = field.type;\n\t\t\tconst pk = name === 'id' ? 'PK' : '';\n\t\t\tconst fk = field.foreignKey ? 'FK' : '';\n\t\t\tconst marker = pk || fk ? ` \"${pk}${fk}\"` : '';\n\t\t\tlines.push(` ${typeStr} ${name}${marker}`);\n\t\t}\n\n\t\tif (entity.fields.size > keyFields.length) {\n\t\t\tlines.push(` string _more_fields`);\n\t\t}\n\n\t\tlines.push(' }');\n\t}\n\n\t// Add relationships\n\tfor (const edge of result.graph.edges) {\n\t\tconst from = edge.from.toUpperCase();\n\t\tconst to = edge.to.toUpperCase();\n\t\tconst cardinalitySymbol = getCardinalitySymbol(edge.cardinality);\n\t\tconst label = edge.relationship.name;\n\n\t\tlines.push(` ${from} ${cardinalitySymbol} ${to} : \"${label}\"`);\n\t}\n\n\treturn lines;\n}\n\n/**\n * Get Mermaid cardinality symbol\n */\nfunction getCardinalitySymbol(cardinality: string): string {\n\tswitch (cardinality) {\n\t\tcase '1:N':\n\t\t\treturn '||--o{';\n\t\tcase 'N:1':\n\t\t\treturn '}o--||';\n\t\tcase '1:1':\n\t\t\treturn '||--||';\n\t\tcase 'N:M':\n\t\t\treturn '}o--o{';\n\t\tdefault:\n\t\t\treturn '||--o{';\n\t}\n}\n\n/**\n * Generate a simple relationship graph in Mermaid\n */\nexport function formatMermaidGraph(result: AnalysisResult): string {\n\tconst lines: string[] = [];\n\n\tlines.push('```mermaid');\n\tlines.push('graph LR');\n\n\t// Style definitions\n\tlines.push(' classDef entity fill:#e1f5fe,stroke:#01579b');\n\n\t// Add entities as nodes\n\tfor (const entity of result.entities) {\n\t\tlines.push(` ${entity.name}[\"${entity.name}\\\\n(${entity.fields.size} fields)\"]`);\n\t}\n\n\t// Add relationships as edges\n\tfor (const edge of result.graph.edges) {\n\t\tconst style = edge.bidirectional ? '<-->' : '-->';\n\t\tlines.push(` ${edge.from} ${style}|${edge.relationship.type}| ${edge.to}`);\n\t}\n\n\t// Apply styles\n\tconst entityList = result.entities.map((e) => e.name).join(',');\n\tif (entityList) {\n\t\tlines.push(` class ${entityList} entity`);\n\t}\n\n\tlines.push('```');\n\n\treturn lines.join('\\n');\n}\n","/**\n * ActivityPattern — replaces `family: activity`.\n *\n * Activity entities represent time-bounded interactions (calls, meetings,\n * emails). The base repository/service expose date-range + opportunity +\n * user-scoped lookups on top of the standard CRUD methods.\n *\n * Class names, import paths, and inherited-method strings match the\n * legacy `FAMILY_MAP` entry verbatim so PATTERN-5's template swap produces\n * byte-identical output.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const ActivityPattern = definePattern({\n\tname: 'Activity',\n\textends: ['Base'],\n\trepositoryClass: 'ActivityEntityRepository',\n\tserviceClass: 'ActivityEntityService',\n\trepositoryImport: '@shared/base-classes/activity-entity-repository',\n\tserviceImport: '@shared/base-classes/activity-entity-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'findByDateRange, findByUserId, findByOpportunityId, findRecentByOpportunityId',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'findByDateRange, findByUserId, findByOpportunityId, findRecentByOpportunityId',\n\t],\n\tdescription:\n\t\t'Time-bounded interaction entities — date-range + opportunity scoped lookups',\n});\n","/**\n * BasePattern — identity pattern for the `extends` chain.\n *\n * Contributes no columns, no implied behaviors, and no config. Its only\n * purpose is to anchor the inheritance hierarchy so every other pattern\n * can declare `extends: ['Base']` and codegen can resolve that to a\n * concrete `BaseRepository` / `BaseService` reference.\n *\n * Matches the existing `family: base` entry in\n * `templates/entity/new/clean-lite-ps/prompt-extension.js` verbatim.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const BasePattern = definePattern({\n\tname: 'Base',\n\trepositoryClass: 'BaseRepository',\n\tserviceClass: 'BaseService',\n\trepositoryImport: '@shared/base-classes/base-repository',\n\tserviceImport: '@shared/base-classes/base-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t],\n\tdescription: 'Identity pattern — base CRUD, no extra columns or methods',\n});\n","/**\n * KnowledgePattern — replaces `family: knowledge`.\n *\n * Knowledge entities hold long-form content with a workflow status and\n * semantic-search support (vectors, pending/approved states). The base\n * classes expose `semanticSearch`, pending-by-opportunity lookups, and\n * batch status updates.\n *\n * Class names, import paths, and inherited-method strings match the\n * legacy `FAMILY_MAP` entry verbatim.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const KnowledgePattern = definePattern({\n\tname: 'Knowledge',\n\textends: ['Base'],\n\trepositoryClass: 'KnowledgeEntityRepository',\n\tserviceClass: 'KnowledgeEntityService',\n\trepositoryImport: '@shared/base-classes/knowledge-entity-repository',\n\tserviceImport: '@shared/base-classes/knowledge-entity-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'semanticSearch, findPendingByOpportunityId, updateStatus, updateStatusBatch',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'semanticSearch, findPendingByOpportunityId, updateStatus, updateStatusBatch',\n\t],\n\tdescription: 'Knowledge entities — semantic search + workflow status',\n});\n","/**\n * MetadataPattern — replaces `family: metadata`.\n *\n * Metadata entities represent history-tracked auxiliary rows attached to a\n * parent entity (audit trails, custom-field values, change logs). The base\n * classes expose entity-id + type scoped lookups and history listing.\n *\n * Class names, import paths, and inherited-method strings match the\n * legacy `FAMILY_MAP` entry verbatim.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const MetadataPattern = definePattern({\n\tname: 'Metadata',\n\textends: ['Base'],\n\trepositoryClass: 'MetadataEntityRepository',\n\tserviceClass: 'MetadataEntityService',\n\trepositoryImport: '@shared/base-classes/metadata-entity-repository',\n\tserviceImport: '@shared/base-classes/metadata-entity-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'findByEntityIdAndType, listByEntityId, listHistoryByEntityId',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'findByEntityIdAndType, listByEntityId, listHistoryByEntityId',\n\t],\n\tdescription:\n\t\t'History-tracked metadata rows — entity-id + type scoped lookups',\n});\n","/**\n * SyncedPattern — adds external-system sync columns and methods.\n *\n * Replaces the legacy `family: synced` entry in\n * `templates/entity/new/clean-lite-ps/prompt-extension.js`. Class names,\n * import paths, and inherited-method comment lines are preserved verbatim\n * so PATTERN-5's template swap produces byte-identical output for\n * pre-existing `family: synced` fixtures.\n *\n * Implies `external_id_tracking` — the behavior that contributes the\n * `external_id`, `provider`, and `provider_metadata` columns to the table.\n * An entity declaring `pattern: Synced` need not re-declare the behavior.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const SyncedPattern = definePattern({\n\tname: 'Synced',\n\textends: ['Base'],\n\trepositoryClass: 'SyncedEntityRepository',\n\tserviceClass: 'SyncedEntityService',\n\trepositoryImport: '@shared/base-classes/synced-entity-repository',\n\tserviceImport: '@shared/base-classes/synced-entity-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'findByExternalId, findAllByUserId, findVisibleByUserId, syncUpsert',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'findByExternalId, findAllByUserId, findVisibleByUserId',\n\t],\n\timpliedBehaviors: ['external_id_tracking'],\n\tdescription: 'External CRM/system sync columns and syncUpsert methods',\n});\n","/**\n * Library pattern bootstrap — imports every shipped pattern and registers\n * it with the shared library registry. Side-effect-only module: importing\n * this barrel is what pre-registers `Base`, `Synced`, `Activity`,\n * `Knowledge`, and `Metadata`.\n *\n * Adding a new library pattern is two edits: create the `*.pattern.ts`\n * file and add the import+register pair below.\n */\n\nimport { registerLibraryPattern } from '../registry.js';\nimport { ActivityPattern } from './activity.pattern.js';\nimport { BasePattern } from './base.pattern.js';\nimport { KnowledgePattern } from './knowledge.pattern.js';\nimport { MetadataPattern } from './metadata.pattern.js';\nimport { SyncedPattern } from './synced.pattern.js';\n\nregisterLibraryPattern(BasePattern);\nregisterLibraryPattern(SyncedPattern);\nregisterLibraryPattern(ActivityPattern);\nregisterLibraryPattern(KnowledgePattern);\nregisterLibraryPattern(MetadataPattern);\n\nexport {\n\tActivityPattern,\n\tBasePattern,\n\tKnowledgePattern,\n\tMetadataPattern,\n\tSyncedPattern,\n};\n","/**\n * Entity Codegen & Domain Analyzer\n *\n * A validation and analysis tool for entity YAML definitions.\n * Parses entities, builds a relationship graph, and detects issues.\n */\n\nimport { loadEntities, loadRelationships, resolveReferences, resolveRelationshipReferences } from './parser';\nimport { buildDomainGraph, checkConsistency, computeStatistics } from './analyzer';\nimport {\n\tvalidatePatternComposition,\n\tvalidatePatternProject,\n} from './patterns/validate-composition.js';\nimport type { AnalysisResult, OutputFormat } from './analyzer/types';\n\n/**\n * Options for `analyzeDomain`. All fields are optional and additive — omitting\n * them keeps the analyzer's behavior identical to pre-PATTERN-4 callers.\n */\nexport interface AnalyzeDomainOptions {\n\t/**\n\t * Path to the relationships directory. Equivalent to the legacy second\n\t * positional argument — preserved for call-site compatibility.\n\t */\n\trelationshipsDir?: string;\n\t/**\n\t * Selected backend architecture from `codegen.config.yaml\n\t * generate.architecture`. When provided, enables the PATTERN-4 project-level\n\t * check (plan Risk 4) that warns when `pattern:` is declared but the\n\t * selected architecture does not yet consume patterns (e.g. `clean`).\n\t */\n\tarchitecture?: string;\n}\n\n/**\n * Analyze a domain from entity and relationship YAML files.\n *\n * The signature accepts either the legacy `(entitiesDir, relationshipsDir)`\n * shape or the newer `(entitiesDir, options)` object form. Existing callers\n * keep working unchanged; pattern-aware callers pass\n * `{ architecture, relationshipsDir }` to opt into the Risk-4 project-level\n * warning surface.\n */\nexport async function analyzeDomain(\n\tentitiesDir: string,\n\trelationshipsOrOptions?: string | AnalyzeDomainOptions,\n): Promise<AnalysisResult> {\n\tconst opts: AnalyzeDomainOptions =\n\t\ttypeof relationshipsOrOptions === 'string'\n\t\t\t? { relationshipsDir: relationshipsOrOptions }\n\t\t\t: relationshipsOrOptions ?? {};\n\tconst relationshipsDir = opts.relationshipsDir;\n\n\t// Load and parse all entity files\n\tconst { entities, issues: loadIssues } = loadEntities(entitiesDir);\n\n\t// Load relationship definitions (optional — directory may not exist)\n\tconst { relationships: relationshipDefinitions, issues: relLoadIssues } =\n\t\trelationshipsDir\n\t\t\t? loadRelationships(relationshipsDir)\n\t\t\t: { relationships: [], issues: [] };\n\n\t// Resolve cross-entity references\n\tconst resolveIssues = resolveReferences(entities);\n\n\t// Resolve relationship endpoint references\n\tconst relResolveIssues = resolveRelationshipReferences(\n\t\trelationshipDefinitions,\n\t\tentities,\n\t);\n\n\t// Build relationship graph (includes both inline and first-class relationships)\n\tconst graph = buildDomainGraph(entities, relationshipDefinitions);\n\n\t// Check consistency\n\tconst consistencyIssues = checkConsistency(graph);\n\n\t// PATTERN-4 — pattern composition check. Runs AFTER resolveReferences()\n\t// (per ADR-031 §3) so entity fields + behaviors are known; the\n\t// per-entity validator detects column conflicts, unknown patterns, and\n\t// config-schema failures, and the project-level validator covers plan\n\t// Risk 4 (warn when `pattern:` is declared under an architecture that\n\t// does not yet consume patterns).\n\tconst patternIssues = entities.flatMap((e) => validatePatternComposition(e));\n\tconst patternProjectIssues = validatePatternProject({\n\t\tentities,\n\t\tarchitecture: opts.architecture,\n\t});\n\n\t// Compute statistics\n\tconst statistics = computeStatistics(graph);\n\n\t// Combine all issues\n\tconst allIssues = [\n\t\t...loadIssues,\n\t\t...relLoadIssues,\n\t\t...resolveIssues,\n\t\t...relResolveIssues,\n\t\t...consistencyIssues,\n\t\t...patternIssues,\n\t\t...patternProjectIssues,\n\t];\n\n\t// Determine validity (only errors make it invalid)\n\tconst hasErrors = allIssues.some((i) => i.severity === 'error');\n\n\treturn {\n\t\tisValid: !hasErrors,\n\t\tentities,\n\t\trelationshipDefinitions,\n\t\tgraph,\n\t\tissues: allIssues,\n\t\tstatistics,\n\t};\n}\n\n/**\n * Validate entity files without full analysis\n * Returns true if all files parse successfully\n */\nexport function validateEntities(entitiesDir: string): {\n\tvalid: boolean;\n\terrors: string[];\n} {\n\tconst { entities, issues } = loadEntities(entitiesDir);\n\tconst errors = issues\n\t\t.filter((i) => i.severity === 'error')\n\t\t.map((i) => i.message);\n\n\treturn {\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t};\n}\n\n// Re-export types\nexport * from './analyzer/types';\n\n// Re-export parser utilities\nexport { loadEntities, loadRelationships, loadEntityFromYaml, loadRelationshipFromYaml } from './parser';\n\n// Re-export analyzer utilities\nexport {\n\tbuildDomainGraph,\n\tgetRelatedEntities,\n\tfindOrphanEntities,\n\tfindCircularDependencies,\n\tcheckConsistency,\n\tcomputeStatistics,\n} from './analyzer';\n\n// Re-export formatters\nexport {\n\tformatConsole,\n\tformatJson,\n\tformatMarkdown,\n\tformatMermaidGraph,\n} from './formatters';\n\n\n// Re-export patterns surface (definePattern + library patterns + registry).\n// Importing this barrel has the side effect of pre-registering the five\n// library-shipped patterns (Base / Synced / Activity / Knowledge / Metadata).\nexport * from './patterns';\n"],"mappings":";AAOA,SAAS,mBAAmB;AAC5B,SAAS,MAAM,eAAe;;;ACR9B,SAAS,cAAc,kBAAkB;AACzC,SAAS,SAAS,iBAAiB;;;ACDnC,SAAS,SAAS;AAsBlB,IAAM,kBAAkB,EAAE,KAAK;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF,CAAC;AAQD,IAAM,eAAe,EAAE,KAAK;AAAA,EAC1B;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;AACF,CAAC;AAID,IAAM,qBAAqB,EAAE,KAAK,CAAC,WAAW,aAAa,UAAU,CAAC;AActE,IAAM,6BAA6B,EAAE,KAAK;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,+BAA+B,EAAE,KAAK,CAAC,eAAe,MAAM,CAAC;AAEnE,IAAM,4BAA4B,EAAE,KAAK,CAAC,WAAW,UAAU,WAAW,SAAS,CAAC;AAEpF,IAAM,iCAAiC,EAAE,KAAK,CAAC,OAAO,QAAQ,SAAS,WAAW,MAAM,CAAC;AAEzF,IAAM,4BAA4B,EAAE,KAAK,CAAC,YAAY,SAAS,QAAQ,CAAC;AAExE,IAAM,6BAA6B,EAAE,MAAM;AAAA,EACzC,EAAE,OAAO;AAAA,EACT,EAAE,OAAO;AAAA,IACP,MAAM,EAAE,OAAO;AAAA,IACf,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,IACnC,kBAAkB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACjD,CAAC;AACH,CAAC;AAQD,IAAM,yBAAyB,EAAE,OAAO;AAAA,EACtC,SAAS,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC9B,uBAAuB,2BAA2B,SAAS;AAAA,EAC3D,oBAAoB,EAAE,OAAO,EAAE,SAAS;AAAA,EACxC,wBAAwB,2BAA2B,SAAS;AAAA,EAC5D,WAAW,EAAE,QAAQ,EAAE,SAAS;AAAA,EAChC,gBAAgB,6BAA6B,SAAS;AAAA,EACtD,kBAAkB,+BAA+B,SAAS;AAAA,EAC1D,cAAc,EAAE,QAAQ,EAAE,SAAS;AAAA,EACnC,QAAQ,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC7B,aAAa,0BAA0B,SAAS;AAAA,EAChD,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,sBAAsB,0BAA0B,SAAS;AAAA,EACzD,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,EACnC,gBAAgB,EAAE,OAAO,EAAE,SAAS;AACtC,CAAC;AAED,IAAM,mBAAmB,EAAE,OAAO;AAAA,EAChC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,SAAS,aAAa,SAAS;AAAA,EAC/B,eAAe,mBAAmB,SAAS;AAAA,EAC3C,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,aAAa,EAAE,QAAQ,EAAE,SAAS;AAAA,EAClC,eAAe,EAAE,QAAQ,EAAE,SAAS;AAAA,EACpC,YAAY,EAAE,QAAQ,EAAE,SAAS;AAAA,EACjC,gBAAgB,EAAE,OAAO,EAAE,SAAS;AAAA,EACpC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,WAAW,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS;AAC5C,CAAC;AAwBD,IAAM,kBAAkB,EAAE,OAAO;AAAA,EAC/B,MAAM;AAAA,EACN,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK;AAAA,EAC9C,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK;AAAA;AAAA,EAG9C,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,EACjD,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS;AAAA;AAAA,EAGpD,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA,EACzB,KAAK,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAGzB,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA,EAItC,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA,EAIlC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA;AAAA,EAG5C,SAAS,EAAE,QAAQ,EAAE,SAAS;AAAA;AAAA,EAG9B,OAAO,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC5B,QAAQ,EAAE,QAAQ,EAAE,SAAS;AAAA;AAAA,EAG7B,aAAa,EAAE,OAAO,EAAE,SAAS;AACnC,CAAC;AAKD,IAAM,wBAAwB,gBAAgB,MAAM,gBAAgB,EAAE,MAAM,sBAAsB,EAC/F,OAAO,CAAC,SAAS,EAAE,KAAK,aAAa,QAAQ,KAAK,aAAa,OAAO;AAAA,EACrE,SACE;AAAA,EACF,MAAM,CAAC,UAAU;AACnB,CAAC,EACA;AAAA,EACC,CAAC,SAAS;AACR,QAAI,KAAK,eAAe,UAAa,KAAK,SAAS,UAAU;AAC3D,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,MAAM,CAAC,YAAY;AAAA,EACrB;AACF,EACC;AAAA,EACC,CAAC,SAAS;AACR,QAAI,KAAK,eAAe,UAAa,KAAK,SAAS,UAAU;AAC3D,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,MAAM,CAAC,YAAY;AAAA,EACrB;AACF,EACC;AAAA,EACC,CAAC,SAAS;AACR,QACE,KAAK,QAAQ,UACb,CAAC,CAAC,WAAW,SAAS,EAAE,SAAS,KAAK,IAAI,GAC1C;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,MAAM,CAAC,KAAK;AAAA,EACd;AACF,EACC;AAAA,EACC,CAAC,SAAS;AACR,QACE,KAAK,QAAQ,UACb,CAAC,CAAC,WAAW,SAAS,EAAE,SAAS,KAAK,IAAI,GAC1C;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,MAAM,CAAC,KAAK;AAAA,EACd;AACF,EACC;AAAA,EACC,CAAC,SAAS;AAER,QAAI,KAAK,SAAS,gBAAgB,CAAC,KAAK,eAAe,QAAQ;AAC7D,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,MAAM,CAAC,eAAe;AAAA,EACxB;AACF,EACC;AAAA,EACC,CAAC,SAAS;AAER,QAAI,KAAK,kBAAkB,UAAa,KAAK,SAAS,cAAc;AAClE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,MAAM,CAAC,eAAe;AAAA,EACxB;AACF,EACC;AAAA,EACC,CAAC,SAAS;AAER,QAAI,KAAK,YAAY,UAAa,KAAK,iBAAiB,QAAW;AACjE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,MAAM,CAAC,cAAc;AAAA,EACvB;AACF,EACC;AAAA,EACC,CAAC,SAAS;AAER,QAAI,KAAK,SAAS,UAAU,CAAC,KAAK,SAAS,UAAU,CAAC,KAAK,cAAc;AACvE,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,MAAM,CAAC,SAAS;AAAA,EAClB;AACF,EACC;AAAA,EACC,CAAC,SAAS;AAER,QAAI,KAAK,YAAY,QAAQ,CAAC,KAAK,uBAAuB;AACxD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,SACE;AAAA,IACF,MAAM,CAAC,uBAAuB;AAAA,EAChC;AACF;AAQF,IAAM,yBAAyB,EAAE,KAAK,CAAC,cAAc,YAAY,SAAS,CAAC;AAmBpE,IAAM,iBAAiB,EAAE,KAAK,CAAC,YAAY,WAAW,YAAY,WAAW,CAAC;AAIrF,IAAM,qBAAqB,EACxB,OAAO;AAAA,EACN,MAAM;AAAA,EACN,QAAQ,EAAE,OAAO;AAAA;AAAA,EACjB,aAAa,EAAE,OAAO;AAAA;AAAA,EACtB,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAC7B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAC7B,UAAU,EAAE,QAAQ,EAAE,SAAS;AAAA;AAAA,EAC/B,WAAW,eAAe,SAAS,EAAE,QAAQ,UAAU;AAAA;AACzD,CAAC,EACA,OAAO,EACP;AAAA,EACC,CAAC,SAAS;AAER,QAAI,KAAK,cAAc,cAAc,KAAK,aAAa,MAAM;AAC3D,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,SACE;AAAA,IACF,MAAM,CAAC,WAAW;AAAA,EACpB;AACF;AAoBF,IAAM,uBAAuB,EAAE,MAAM;AAAA,EACnC,EAAE,OAAO;AAAA,EACT,EAAE,OAAO;AAAA,IACP,MAAM,EAAE,OAAO;AAAA,IACf,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EAC1C,CAAC;AACH,CAAC;AASD,IAAM,yBAAyB,EAAE,KAAK,CAAC,cAAc,QAAQ,CAAC;AAa9D,IAAM,wBAAwB,EAAE,KAAK,CAAC,UAAU,MAAM,CAAC,EAAE,QAAQ,QAAQ;AAezE,IAAM,qBAAqB,EAAE,KAAK,CAAC,YAAY,SAAS,CAAC,EAAE,QAAQ,UAAU;AAW7E,IAAM,oBAAoB,EAAE,KAAK,CAAC,cAAc,QAAQ,QAAQ,UAAU,CAAC;AAG3E,IAAM,qBAAqB,EACxB,OAAO;AAAA,EACN,MAAM,EACH,OAAO,EACP;AAAA,IACC;AAAA,IACA;AAAA,EACF;AAAA,EACF,QAAQ,EAAE,OAAO,EAAE,MAAM,qBAAqB,0BAA0B;AAAA,EACxE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,yBAAyB;AAAA;AAAA;AAAA;AAAA,EAKtE,kBAAkB,sBAAsB,SAAS;AAAA,EACjD,eAAe,mBAAmB,SAAS;AAAA;AAAA,EAG3C,mBAAmB,uBAAuB,SAAS;AAAA;AAAA,EAEnD,QAAQ,EACL,MAAM,iBAAiB,EACvB,SAAS,EACT,QAAQ,CAAC,cAAc,QAAQ,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMzC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA,EAIvC,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA,EAKnD,WAAW,EAAE,QAAQ,EAAE,SAAS;AAClC,CAAC,EACA,OAAO,EACP,OAAO,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,WAAW;AAAA,EACzC,SAAS;AACX,CAAC;AAmBH,IAAM,yBAAyB,EAAE,OAAO;AAAA,EACtC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC;AAAA,EAC7B,QAAQ,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC7B,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACrC,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,OAAO,EAAE,QAAQ,EAAE,SAAS;AAAA,EAC5B,KAAK,EAAE,OAAO,EAAE,SAAS;AAC3B,CAAC;AAsBD,IAAM,+BAA+B,EAAE,OAAO;AAAA,EAC5C,MAAM,EAAE,QAAQ,QAAQ;AAAA,EACxB,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC;AAAA,EAClC,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EAC7C,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAUD,IAAM,4BAA4B,EAAE,MAAM;AAAA,EACxC;AAAA,EACA;AACF,CAAC;AASM,IAAM,sBAAsB,EAAE,KAAK;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAOM,IAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,eAAe,EAAE,OAAO;AAAA,EACxB,WAAW;AAAA,EACX,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK;AAAA,EACzC,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACzD,kBAAkB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AACjD,CAAC;AAOM,IAAM,mBAAmB,EAAE,OAAO;AAAA,EACvC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK;AAAA,EAC9C,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,EAAE,SAAS;AAC/D,CAAC;AAqBD,IAAM,yBAAyB,EAAE,OAAO;AAAA,EACtC,MAAM,EACH,OAAO,EACP,MAAM,qBAAqB,+BAA+B;AAAA,EAC7D,OAAO,EAAE,OAAO;AAAA,EAChB,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC;AAAA,EACrC,kBAAkB,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK;AACxD,CAAC;AAWD,IAAM,qBAAqB,EAAE,OAAO;AAAA,EAClC,MAAM,EAAE,QAAQ,QAAQ;AAAA,EACxB,SAAS,EAAE,OAAO;AAAA,EAClB,KAAK,2BAA2B,SAAS;AAAA,EACzC,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAKD,IAAM,sBAAsB,EAAE,OAAO;AAAA,EACnC,MAAM,EAAE,QAAQ,SAAS;AAAA,EACzB,MAAM,EAAE,OAAO;AAAA,EACf,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAC3B,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAKD,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACjC,MAAM,EAAE,QAAQ,OAAO;AAAA,EACvB,WAAW,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,kBAAkB,CAAC;AAAA,EACnD,aAAa,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,kBAAkB,CAAC;AAAA,EACrD,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAKD,IAAM,yBAAyB,EAAE,OAAO;AAAA,EACtC,MAAM,EAAE,QAAQ,YAAY;AAAA,EAC5B,SAAS,EAAE,OAAO;AAAA,EAClB,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,eAAe,+BAA+B,SAAS;AAAA,EACvD,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,OAAO,EAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAKD,IAAM,yBAAyB,EAAE,mBAAmB,QAAQ;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AASD,IAAM,uBAAuB,EAAE,OAAO;AAAA,EACpC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EAC5C,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,sBAAsB,EAAE,SAAS;AACjE,CAAC;AAkBD,IAAM,uBAAuB,EAC1B,OAAO;AAAA,EACN,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,IAAI;AAC7C,CAAC,EACA,OAAO;AAIH,IAAM,yBAAyB,EACnC,OAAO;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,qBAAqB;AAAA,EAClD,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,kBAAkB,EAAE,SAAS;AAAA;AAAA,EAEjE,WAAW,EAAE,MAAM,oBAAoB,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAAA;AAAA,EAG9D,UAAU,qBAAqB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBxC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAazC,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK;AAAA;AAAA;AAAA;AAAA,EAKrD,sBAAsB,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA,EAK1C,SAAS,EAAE,MAAM,yBAAyB,EAAE,SAAS;AAAA;AAAA;AAAA,EAIrD,MAAM,iBAAiB,SAAS;AAAA;AAAA;AAAA,EAIhC,QAAQ,EAAE,MAAM,sBAAsB,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYjD,OAAO,EACJ;AAAA,IACC,EACG,OAAO,EACP,MAAM,qBAAqB,mDAAmD;AAAA,EACnF,EACC,SAAS;AAAA;AAAA;AAAA,EAIZ,WAAW,qBAAqB,SAAS;AAC3C,CAAC,EACA,OAAO,EACP;AAAA,EACC,CAAC,SAAS,CAAC,KAAK,mBAAmB,OAAO,KAAK,yBAAyB;AAAA,EACxE;AAAA,IACE,SACE;AAAA,IAGF,MAAM,CAAC,sBAAsB;AAAA,EAC/B;AACF;;;AC9zBF,SAAS,KAAAA,UAAS;AAmBX,IAAM,mBAAmB,CAAC,WAAW,UAAU,UAAU;AAGzD,IAAM,oBAAoB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAGO,IAAM,uBAAuB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACD;AAGO,IAAM,2BAA2B,CAAC,UAAU,aAAa;AAOzD,IAAM,oBAAuD;AAAA,EACnE,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,UAAU;AACX;AAMA,IAAM,uBAAuBA,GAAE,KAAK,gBAAgB;AACpD,IAAM,uBAAuBA,GAAE,KAAK,iBAAiB;AACrD,IAAM,kBAAkBA,GAAE,KAAK,oBAAoB;AAOnD,IAAM,0BAA0BA,GAC9B,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAUA,GAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK;AAAA,EAC9C,aAAaA,GAAE,OAAO,EAAE,SAAS;AAClC,CAAC,EACA,OAAO;AAQT,IAAM,cAAcA,GAClB,OAAO;AAAA,EACP,UAAUA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,EACxC,SAASA,GAAE,KAAK,wBAAwB;AACzC,CAAC,EACA,OAAO;AAQT,IAAM,gBAAgB;AAEtB,IAAM,4BAA4BA,GAChC,OAAO;AAAA,EACP,MAAMA,GACJ,OAAO,EACP;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAAA,EACD,WAAW;AAAA,EACX,MAAM,gBAAgB,SAAS;AAAA,EAC/B,WAAWA,GAAE,OAAO,EAAE,MAAM,aAAa,EAAE,SAAS;AAAA,EACpD,QAAQA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACnC,aAAaA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACxC,SAASA,GACP;AAAA,IACAA,GACE,OAAO,EACP,MAAM,eAAe,iCAAiC;AAAA,IACxD;AAAA,EACD,EACC,QAAQ,CAAC,CAAC;AAAA,EACZ,OAAO,YAAY,SAAS,EAAE,QAAQ;AAAA,IACrC,UAAU;AAAA,IACV,SAAS;AAAA,EACV,CAAC;AAAA,EACD,SAASA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC;AAAA,EACrD,aAAaA,GAAE,OAAO,EAAE,SAAS;AAClC,CAAC,EACA,OAAO;AAcT,IAAM,+BAA+B,0BAA0B;AAAA,EAC9D,CAAC,MAAM,QAAQ;AACd,QAAI,KAAK,cAAc,YAAY,CAAC,KAAK,WAAW;AACnD,UAAI,SAAS;AAAA,QACZ,MAAMA,GAAE,aAAa;AAAA,QACrB,SAAS;AAAA,QACT,MAAM,CAAC,WAAW;AAAA,MACnB,CAAC;AAAA,IACF;AAEA,QAAI,KAAK,WAAW,UAAa,KAAK,cAAc,WAAW;AAC9D,UAAI,SAAS;AAAA,QACZ,MAAMA,GAAE,aAAa;AAAA,QACrB,SAAS,4DAA4D,KAAK,SAAS;AAAA,QACnF,MAAM,CAAC,QAAQ;AAAA,MAChB,CAAC;AAAA,IACF;AAEA,QAAI,KAAK,gBAAgB,UAAa,KAAK,cAAc,YAAY;AACpE,UAAI,SAAS;AAAA,QACZ,MAAMA,GAAE,aAAa;AAAA,QACrB,SAAS,kEAAkE,KAAK,SAAS;AAAA,QACzF,MAAM,CAAC,aAAa;AAAA,MACrB,CAAC;AAAA,IACF;AAEA,QAAI,KAAK,SAAS,QAAW;AAC5B,YAAM,WAAW,kBAAkB,KAAK,SAAS;AACjD,UAAI,KAAK,SAAS,UAAU;AAC3B,YAAI,SAAS;AAAA,UACZ,MAAMA,GAAE,aAAa;AAAA,UACrB,SAAS,SAAS,KAAK,IAAI,qCAAqC,KAAK,SAAS,gBAAgB,QAAQ;AAAA,UACtG,MAAM,CAAC,MAAM;AAAA,QACd,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AACD;AAMO,IAAM,wBAAwB,6BAA6B;AAAA,EACjE,CAAC,YAAY;AAAA,IACZ,GAAG;AAAA,IACH,MAAM,OAAO,QAAQ,kBAAkB,OAAO,SAAS;AAAA,EACxD;AACD;;;ACxLA,SAAS,KAAAC,UAAS;AAuClB,IAAM,sBAAsBA,GAC1B,OAAO;AAAA;AAAA,EAEP,SAASA,GAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE7B,eAAeA,GAAE,QAAQ,EAAE,SAAS;AAAA;AAAA,EAEpC,UAAUA,GAAE,QAAQ,EAAE,SAAS;AAChC,CAAC,EACA;AAAA,EACA,CAAC,SAAS;AACT,UAAM,MAAM,CAAC,KAAK,SAAS,KAAK,eAAe,KAAK,QAAQ,EAAE;AAAA,MAC7D,CAAC,MAAM,MAAM;AAAA,IACd;AACA,WAAO,IAAI,WAAW;AAAA,EACvB;AAAA,EACA;AAAA,IACC,SACC;AAAA,EACF;AACD;AAoBD,IAAM,0BAA0BA,GAAE,MAAM;AAAA;AAAA,EAEvCA,GAAE,MAAMA,GAAE,OAAO,EAAE,MAAM,qBAAqB,yBAAyB,CAAC;AAAA;AAAA,EAExEA,GAAE;AAAA,IACDA,GAAE,OAAO,EAAE,MAAM,qBAAqB,6BAA6B;AAAA,IACnE;AAAA,EACD;AACD,CAAC;AAQD,IAAM,uBAAuBA,GAC3B,KAAK,CAAC,YAAY,WAAW,YAAY,WAAW,CAAC,EACrD,QAAQ,UAAU;AAepB,IAAM,2BAA2BA,GAC/B,OAAO;AAAA;AAAA,EAEP,MAAMA,GAAE,OAAO,EAAE;AAAA,IAChB;AAAA,IACA;AAAA,EACD;AAAA;AAAA,EAGA,OAAOA,GACL,OAAO,EACP,MAAM,qBAAqB,0BAA0B,EACrD,SAAS;AAAA;AAAA,EAGX,MAAMA,GAAE,OAAO,EAAE,MAAM,qBAAqB,gCAAgC;AAAA;AAAA,EAG5E,IAAIA,GAAE,OAAO,EAAE,MAAM,qBAAqB,gCAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAY1E,OAAO,wBAAwB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxC,UAAUA,GAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlC,SAASA,GAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA;AAAA,EAGjC,gBAAgB,qBAAqB,SAAS;AAAA;AAAA,EAG9C,cAAc,qBAAqB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAa5C,WAAWA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,SAAS;AACzC,CAAC,EACA,OAAO;AAcT,IAAM,0BAA0BA,GAAE,OAAO;AAAA,EACxC,IAAIA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,IAAI,CAAC;AAAA,EAC7B,QAAQA,GAAE,QAAQ,EAAE,SAAS;AAAA,EAC7B,QAAQA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACrC,OAAOA,GAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,OAAOA,GAAE,QAAQ,EAAE,SAAS;AAC7B,CAAC;AA2CM,IAAM,+BAA+BA,GAC1C,OAAO;AAAA;AAAA,EAEP,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOd,QAAQA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA,EAG/C,SAASA,GAAE,MAAM,uBAAuB,EAAE,SAAS;AACpD,CAAC,EACA,OAAO,EACP;AAAA,EACA,CAAC,SAAS;AAGT,QAAI,KAAK,aAAa,SAAS,KAAK,aAAa,MAAM,KAAK,aAAa,OAAO;AAC/E,aAAO,CAAC,MAAM,QAAQ,KAAK,aAAa,KAAK;AAAA,IAC9C;AACA,WAAO;AAAA,EACR;AAAA,EACA;AAAA,IACC,SACC;AAAA,IAED,MAAM,CAAC,gBAAgB,OAAO;AAAA,EAC/B;AACD,EACC;AAAA,EACA,CAAC,SAAS;AAGT,QAAI,CAAC,KAAK,OAAQ,QAAO;AAEzB,UAAM,WAAW,uBAAuB,KAAK,YAAY;AACzD,UAAM,aAAa,OAAO,KAAK,KAAK,MAAM,EAAE;AAAA,MAAO,CAAC,QACnD,SAAS,IAAI,GAAG;AAAA,IACjB;AACA,WAAO,WAAW,WAAW;AAAA,EAC9B;AAAA,EACA;AAAA,IACC,SACC;AAAA,IAGD,MAAM,CAAC,QAAQ;AAAA,EAChB;AACD;AA0CM,SAAS,uBAAuB,QAAyC;AAC/E,QAAM,EAAE,YAAY,SAAS,IAAI,4BAA4B,MAAM;AACnE,QAAM,WAAW,oBAAI,IAAI;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AAED,MAAI,OAAO,OAAO;AACjB,aAAS,IAAI,MAAM;AAAA,EACpB;AACA,MAAI,OAAO,UAAU;AACpB,aAAS,IAAI,YAAY;AACzB,aAAS,IAAI,UAAU;AACvB,aAAS,IAAI,YAAY;AAAA,EAC1B;AACA,MAAI,OAAO,SAAS;AACnB,aAAS,IAAI,QAAQ;AACrB,aAAS,IAAI,YAAY;AAAA,EAC1B;AAEA,SAAO;AACR;AAeO,SAAS,4BAA4B,QAG1C;AACD,MAAI,OAAO,SAAS,OAAO,IAAI;AAC9B,WAAO;AAAA,MACN,YAAY,QAAQ,OAAO,IAAI;AAAA,MAC/B,UAAU,MAAM,OAAO,EAAE;AAAA,IAC1B;AAAA,EACD;AACA,SAAO;AAAA,IACN,YAAY,GAAG,OAAO,IAAI;AAAA,IAC1B,UAAU,GAAG,OAAO,EAAE;AAAA,EACvB;AACD;AAMO,SAAS,gBAAgB,QAAoC;AACnE,SAAO,OAAO,SAAS,GAAG,OAAO,IAAI;AACtC;AAmCO,SAAS,uBAAuB,QAAsC;AAC5E,MAAI,OAAO,UAAW,QAAO,OAAO;AAEpC,QAAM,EAAE,YAAY,SAAS,IAAI,4BAA4B,MAAM;AACnE,QAAM,UAAU,CAAC,YAAY,QAAQ;AAErC,MAAI,OAAO,OAAO;AACjB,YAAQ,KAAK,MAAM;AAAA,EACpB;AACA,MAAI,OAAO,YAAY,OAAO,OAAO;AACpC,YAAQ,KAAK,YAAY;AAAA,EAC1B;AAEA,SAAO;AACR;;;AHxZO,SAAS,mBAAmB,UAAoC;AAEtE,MAAI,CAAC,WAAW,QAAQ,GAAG;AAC1B,WAAO;AAAA,MACN,SAAS;AAAA,MACT,OAAO,mBAAmB,QAAQ;AAAA,MAClC;AAAA,IACD;AAAA,EACD;AAGA,MAAI;AACJ,MAAI;AACH,cAAU,aAAa,UAAU,OAAO;AAAA,EACzC,SAAS,KAAK;AACb,WAAO;AAAA,MACN,SAAS;AAAA,MACT,OAAO,wBAAwB,QAAQ;AAAA,MACvC,SAAS,CAAC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC1D;AAAA,IACD;AAAA,EACD;AAGA,MAAI;AACJ,MAAI;AACH,aAAS,UAAU,OAAO;AAAA,EAC3B,SAAS,KAAK;AACb,WAAO;AAAA,MACN,SAAS;AAAA,MACT,OAAO,0BAA0B,QAAQ;AAAA,MACzC,SAAS,CAAC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC1D;AAAA,IACD;AAAA,EACD;AAGA,QAAM,SAAS,uBAAuB,UAAU,MAAM;AACtD,MAAI,CAAC,OAAO,SAAS;AACpB,WAAO;AAAA,MACN,SAAS;AAAA,MACT,OAAO,yBAAyB,QAAQ;AAAA,MACxC,SAAS,gBAAgB,OAAO,KAAK;AAAA,MACrC;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN,SAAS;AAAA,IACT,YAAY,OAAO;AAAA,IACnB;AAAA,EACD;AACD;AAKA,SAAS,gBAAgB,OAA2B;AACnD,SAAO,MAAM,OAAO,IAAI,CAAC,QAAQ;AAChC,UAAMC,QAAO,IAAI,KAAK,KAAK,GAAG;AAC9B,UAAM,WAAWA,QAAO,OAAOA,KAAI,MAAM;AACzC,WAAO,GAAG,IAAI,OAAO,IAAI,QAAQ;AAAA,EAClC,CAAC;AACF;AA8DO,SAAS,yBACf,UACyB;AACzB,MAAI,CAAC,WAAW,QAAQ,GAAG;AAC1B,WAAO;AAAA,MACN,SAAS;AAAA,MACT,OAAO,mBAAmB,QAAQ;AAAA,MAClC;AAAA,IACD;AAAA,EACD;AAEA,MAAI;AACJ,MAAI;AACH,cAAU,aAAa,UAAU,OAAO;AAAA,EACzC,SAAS,KAAK;AACb,WAAO;AAAA,MACN,SAAS;AAAA,MACT,OAAO,wBAAwB,QAAQ;AAAA,MACvC,SAAS,CAAC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC1D;AAAA,IACD;AAAA,EACD;AAEA,MAAI;AACJ,MAAI;AACH,aAAS,UAAU,OAAO;AAAA,EAC3B,SAAS,KAAK;AACb,WAAO;AAAA,MACN,SAAS;AAAA,MACT,OAAO,0BAA0B,QAAQ;AAAA,MACzC,SAAS,CAAC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC1D;AAAA,IACD;AAAA,EACD;AAEA,QAAM,SAAS,6BAA6B,UAAU,MAAM;AAC5D,MAAI,CAAC,OAAO,SAAS;AACpB,WAAO;AAAA,MACN,SAAS;AAAA,MACT,OAAO,yBAAyB,QAAQ;AAAA,MACxC,SAAS,gBAAgB,OAAO,KAAK;AAAA,MACrC;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN,SAAS;AAAA,IACT,YAAY,OAAO;AAAA,IACnB;AAAA,EACD;AACD;;;ADnKA,SAAS,kBAAkB,QAAkC;AAC5D,QAAM,EAAE,YAAY,SAAS,IAAI;AAKjC,QAAM,UAAqC,WAAW,SACnD,OAAO,CAAC,MAA+C,QAAQ,CAAC,EACjE,IAAI,CAAC,OAAO;AAAA,IACZ,IAAI,EAAE;AAAA,IACN,QAAQ,EAAE;AAAA,IACV,QAAQ,EAAE;AAAA,IACV,OAAO,EAAE;AAAA,IACT,OAAO,EAAE;AAAA,IACT,KAAK,EAAE;AAAA,EACR,EAAE;AAEH,QAAM,SAAuB;AAAA,IAC5B,MAAM,WAAW,OAAO;AAAA,IACxB,QAAQ,WAAW,OAAO;AAAA,IAC1B,OAAO,WAAW,OAAO;AAAA,IACzB,SAAS,WAAW,OAAO;AAAA,IAC3B,UAAU,WAAW,OAAO;AAAA,IAC5B,eAAe,WAAW,OAAO;AAAA,IACjC,WAAW,WAAW,OAAO,aAAa;AAAA,IAC1C,iBAAiB,WAAW,OAAO,oBAAoB;AAAA,IACvD,QAAQ,oBAAI,IAAI;AAAA,IAChB,eAAe,oBAAI,IAAI;AAAA,IACvB,WAAW,WAAW,UAAU,IAAI,CAAC,MAAO,OAAO,MAAM,WAAW,IAAI,EAAE,IAAK;AAAA,IAC/E;AAAA,IACA,YAAY;AAAA,EACb;AAGA,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,WAAW,MAAM,GAAG;AACjE,UAAM,QAAqB;AAAA,MAC1B;AAAA,MACA,MAAM,SAAS;AAAA,MACf,UAAU,SAAS,YAAY;AAAA,MAC/B,UAAU,SAAS,YAAY;AAAA,MAC/B,QAAQ,SAAS,UAAU;AAAA,MAC3B,OAAO,SAAS,SAAS;AAAA,MACzB,YAAY,SAAS,cAAc,gBAAgB,SAAS,WAAW,IAAI;AAAA,MAC3E,SAAS,SAAS;AAAA,MAClB,aAAa;AAAA,QACZ,WAAW,SAAS;AAAA,QACpB,WAAW,SAAS;AAAA,QACpB,KAAK,SAAS;AAAA,QACd,KAAK,SAAS;AAAA,MACf;AAAA,MACA,IAAI;AAAA,QACH,OAAO,SAAS;AAAA,QAChB,MAAM,SAAS;AAAA,QACf,YAAY,SAAS;AAAA,QACrB,OAAO,SAAS;AAAA,QAChB,UAAU,SAAS;AAAA,QACnB,YAAY,SAAS;AAAA,QACrB,SAAS,SAAS;AAAA,MACnB;AAAA,IACD;AACA,WAAO,OAAO,IAAI,MAAM,KAAK;AAAA,EAC9B;AAGA,MAAI,WAAW,eAAe;AAC7B,eAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,WAAW,aAAa,GAAG;AACtE,YAAM,eAAmC;AAAA,QACxC;AAAA,QACA,MAAM,OAAO;AAAA,QACb,QAAQ,OAAO;AAAA,QACf,YAAY,OAAO;AAAA,QACnB,SAAS,OAAO;AAAA,QAChB,SAAS,OAAO;AAAA,QAChB,UAAU;AAAA,MACX;AACA,aAAO,cAAc,IAAI,MAAM,YAAY;AAAA,IAC5C;AAAA,EACD;AAGA,MAAI,WAAW,MAAM;AACpB,UAAM,UAAU,WAAW;AAC3B,UAAM,aAAyB;AAAA,MAC9B,UAAU,QAAQ,YAAY;AAAA,IAC/B;AAEA,QAAI,QAAQ,WAAW;AACtB,iBAAW,YAAY,CAAC;AACxB,iBAAW,CAAC,cAAc,WAAW,KAAK,OAAO,QAAQ,QAAQ,SAAS,GAAG;AAC5E,cAAM,iBAAqC;AAAA,UAC1C,cAAc,YAAY;AAAA,UAC1B,WAAW,YAAY;AAAA,UACvB,KAAK,YAAY,OAAO;AAAA,QACzB;AACA,YAAI,YAAY,eAAe;AAC9B,yBAAe,eAAe,YAAY;AAAA,QAC3C;AACA,YAAI,YAAY,kBAAkB;AACjC,yBAAe,iBAAiB,YAAY;AAAA,QAC7C;AACA,mBAAW,UAAU,YAAY,IAAI;AAAA,MACtC;AAAA,IACD;AAEA,WAAO,OAAO;AAAA,EACf;AAGA,MAAI,WAAW,QAAQ;AACtB,WAAO,SAAS,WAAW,OAAO,IAAI,CAAC,QAAqB;AAAA,MAC3D,MAAM,GAAG;AAAA,MACT,OAAO,GAAG;AAAA,MACV,MAAM,GAAG;AAAA,MACT,iBAAiB,GAAG;AAAA,IACrB,EAAE;AAAA,EACH;AAIA,MAAI,WAAW,UAAU,QAAW;AACnC,WAAO,QAAQ,WAAW;AAAA,EAC3B;AAEA,SAAO;AACR;AAKA,SAAS,gBAAgB,IAA+C;AACvE,QAAM,CAAC,OAAO,MAAM,IAAI,GAAG,MAAM,GAAG;AACpC,SAAO,EAAE,OAAO,QAAQ,UAAU,KAAK;AACxC;AAKA,SAAS,iBAAiB,OAAmC;AAC5D,QAAM,SAA0B,CAAC;AAEjC,SAAO,KAAK;AAAA,IACX,UAAU;AAAA,IACV,MAAM;AAAA,IACN,SAAS,MAAM;AAAA,IACf,MAAM,MAAM;AAAA,EACb,CAAC;AAED,MAAI,MAAM,SAAS;AAClB,eAAW,UAAU,MAAM,SAAS;AACnC,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM,MAAM;AAAA,MACb,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO;AACR;AAKO,SAAS,aAAa,aAAyC;AACrE,QAAM,WAA2B,CAAC;AAClC,QAAM,SAA0B,CAAC;AAEjC,QAAM,cAAc,QAAQ,WAAW;AAGvC,MAAI;AACJ,MAAI;AACH,YAAQ,YAAY,WAAW,EAC7B,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,KAAK,EAAE,SAAS,MAAM,CAAC,EACvD,IAAI,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC;AAAA,EAClC,SAAS,KAAK;AACb,WAAO,KAAK;AAAA,MACX,UAAU;AAAA,MACV,MAAM;AAAA,MACN,SAAS,6BAA6B,WAAW;AAAA,MACjD,MAAM;AAAA,IACP,CAAC;AACD,WAAO,EAAE,UAAU,OAAO;AAAA,EAC3B;AAEA,MAAI,MAAM,WAAW,GAAG;AACvB,WAAO,KAAK;AAAA,MACX,UAAU;AAAA,MACV,MAAM;AAAA,MACN,SAAS,qCAAqC,WAAW;AAAA,MACzD,MAAM;AAAA,IACP,CAAC;AACD,WAAO,EAAE,UAAU,OAAO;AAAA,EAC3B;AAGA,aAAW,YAAY,OAAO;AAC7B,UAAM,SAAS,mBAAmB,QAAQ;AAE1C,QAAI,OAAO,SAAS;AACnB,eAAS,KAAK,kBAAkB,MAAM,CAAC;AAAA,IACxC,OAAO;AACN,aAAO,KAAK,GAAG,iBAAiB,MAAM,CAAC;AAAA,IACxC;AAAA,EACD;AAEA,SAAO,EAAE,UAAU,OAAO;AAC3B;AAKO,SAAS,kBAAkB,UAA2C;AAC5E,QAAM,SAA0B,CAAC;AACjC,QAAM,YAAY,oBAAI,IAA0B;AAGhD,aAAW,UAAU,UAAU;AAC9B,QAAI,UAAU,IAAI,OAAO,IAAI,GAAG;AAC/B,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,SAAS,0BAA0B,OAAO,IAAI;AAAA,QAC9C,MAAM,OAAO;AAAA,MACd,CAAC;AAAA,IACF;AACA,cAAU,IAAI,OAAO,MAAM,MAAM;AAAA,EAClC;AAGA,aAAW,UAAU,UAAU;AAC9B,eAAW,CAAC,SAAS,GAAG,KAAK,OAAO,eAAe;AAClD,YAAM,eAAe,UAAU,IAAI,IAAI,MAAM;AAC7C,UAAI,cAAc;AACjB,YAAI,WAAW;AAAA,MAChB,OAAO;AACN,eAAO,KAAK;AAAA,UACX,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,OAAO;AAAA,UACf,OAAO;AAAA,UACP,SAAS,iBAAiB,OAAO,gCAAgC,IAAI,MAAM;AAAA,UAC3E,MAAM,OAAO;AAAA,UACb,YAAY,kBAAkB,IAAI,MAAM;AAAA,QACzC,CAAC;AAAA,MACF;AAAA,IACD;AAGA,eAAW,CAAC,WAAW,KAAK,KAAK,OAAO,QAAQ;AAC/C,UAAI,MAAM,YAAY;AACrB,cAAM,cAAc,MAAM,WAAW;AACrC,cAAM,eAAe,MAAM,KAAK,UAAU,OAAO,CAAC,EAAE;AAAA,UACnD,CAAC,MAAM,EAAE,UAAU;AAAA,QACpB;AACA,YAAI,CAAC,cAAc;AAClB,iBAAO,KAAK;AAAA,YACX,UAAU;AAAA,YACV,MAAM;AAAA,YACN,QAAQ,OAAO;AAAA,YACf,OAAO;AAAA,YACP,SAAS,yCAAyC,WAAW;AAAA,YAC7D,MAAM,OAAO;AAAA,YACb,YAAY,6BAA6B,WAAW;AAAA,UACrD,CAAC;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAiBA,SAAS,kCACR,QAC+B;AAC/B,QAAM,EAAE,YAAY,SAAS,IAAI;AACjC,QAAM,SAAS,WAAW;AAE1B,QAAM,EAAE,YAAY,SAAS,IAAI,4BAA4B,MAAM;AACnE,QAAM,QAAQ,gBAAgB,MAAM;AACpC,QAAM,WAAW,uBAAuB,MAAM;AAG9C,QAAM,QAAQ,sBAAsB,OAAO,KAAK;AAGhD,QAAM,SAAS,oBAAI,IAAyB;AAC5C,MAAI,WAAW,QAAQ;AACtB,eAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,WAAW,MAAM,GAAG;AACjE,YAAM,QAAqB;AAAA,QAC1B;AAAA,QACA,MAAM,SAAS;AAAA,QACf,UAAU,SAAS,YAAY;AAAA,QAC/B,UAAU,SAAS,YAAY;AAAA,QAC/B,QAAQ,SAAS,UAAU;AAAA,QAC3B,OAAO,SAAS,SAAS;AAAA,QACzB,YAAY,SAAS,cAClB,gBAAgB,SAAS,WAAW,IACpC;AAAA,QACH,SAAS,SAAS;AAAA,QAClB,aAAa;AAAA,UACZ,WAAW,SAAS;AAAA,UACpB,WAAW,SAAS;AAAA,UACpB,KAAK,SAAS;AAAA,UACd,KAAK,SAAS;AAAA,QACf;AAAA,QACA,IAAI;AAAA,UACH,OAAO,SAAS;AAAA,UAChB,MAAM,SAAS;AAAA,UACf,YAAY,SAAS;AAAA,UACrB,OAAO,SAAS;AAAA,UAChB,UAAU,SAAS;AAAA,UACnB,YAAY,SAAS;AAAA,UACrB,SAAS,SAAS;AAAA,QACnB;AAAA,MACD;AACA,aAAO,IAAI,MAAM,KAAK;AAAA,IACvB;AAAA,EACD;AAIA,QAAM,UAAqC,WAAW,SACnD,OAAO,CAAC,MAA+C,QAAQ,CAAC,EACjE,IAAI,CAAC,OAAO;AAAA,IACZ,IAAI,EAAE;AAAA,IACN,QAAQ,EAAE;AAAA,IACV,QAAQ,EAAE;AAAA,IACV,OAAO,EAAE;AAAA,IACT,OAAO,EAAE;AAAA,EACV,EAAE;AAEH,SAAO;AAAA,IACN,MAAM,OAAO;AAAA,IACb;AAAA,IACA,MAAM,OAAO;AAAA,IACb,IAAI,OAAO;AAAA,IACX,iBAAiB,OAAO,SAAS,OAAO;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,MAAM,SAAS;AAAA,IACzB,UAAU,OAAO;AAAA,IACjB,SAAS,OAAO;AAAA,IAChB,cAAc,OAAO,kBAAkB;AAAA,IACvC,YAAY,OAAO,gBAAgB;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,EACb;AACD;AAQA,SAAS,sBACR,OACwB;AACxB,MAAI,CAAC,MAAO,QAAO,CAAC;AAEpB,MAAI,MAAM,QAAQ,KAAK,GAAG;AAEzB,WAAO,MAAM,IAAI,CAAC,UAAU;AAAA,MAC3B;AAAA,MACA,eAAe;AAAA,MACf,UAAU;AAAA,IACX,EAAE;AAAA,EACH;AAGA,SAAO,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM;AACjD,UAAM,YAAY;AAClB,WAAO;AAAA,MACN;AAAA,MACA,SAAS,UAAU;AAAA,MACnB,eAAe,UAAU,iBAAiB;AAAA,MAC1C,UAAU,UAAU,aAAa,CAAC,UAAU,iBAAiB,CAAC,UAAU;AAAA,IACzE;AAAA,EACD,CAAC;AACF;AAKO,SAAS,kBACf,kBAC0B;AAC1B,QAAM,gBAAgD,CAAC;AACvD,QAAM,SAA0B,CAAC;AAEjC,QAAM,cAAc,QAAQ,gBAAgB;AAE5C,MAAI;AACJ,MAAI;AACH,YAAQ,YAAY,WAAW,EAC7B,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,KAAK,EAAE,SAAS,MAAM,CAAC,EACvD,IAAI,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC;AAAA,EAClC,QAAQ;AAEP,WAAO,EAAE,eAAe,OAAO;AAAA,EAChC;AAEA,MAAI,MAAM,WAAW,GAAG;AACvB,WAAO,EAAE,eAAe,OAAO;AAAA,EAChC;AAEA,aAAW,YAAY,OAAO;AAC7B,UAAM,SAAS,yBAAyB,QAAQ;AAEhD,QAAI,OAAO,SAAS;AACnB,oBAAc,KAAK,kCAAkC,MAAM,CAAC;AAAA,IAC7D,OAAO;AACN,aAAO,KAAK,GAAG,iBAAiB,MAA8B,CAAC;AAAA,IAChE;AAAA,EACD;AAEA,SAAO,EAAE,eAAe,OAAO;AAChC;AAMO,SAAS,8BACf,kBACA,UACkB;AAClB,QAAM,SAA0B,CAAC;AACjC,QAAM,cAAc,IAAI,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAEvD,aAAW,UAAU,kBAAkB;AACtC,QAAI,CAAC,YAAY,IAAI,OAAO,IAAI,GAAG;AAClC,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,SAAS,iBAAiB,OAAO,IAAI,uCAAuC,OAAO,IAAI;AAAA,QACvF,MAAM,OAAO;AAAA,QACb,YAAY,kBAAkB,OAAO,IAAI;AAAA,MAC1C,CAAC;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,IAAI,OAAO,EAAE,GAAG;AAChC,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,SAAS,iBAAiB,OAAO,IAAI,qCAAqC,OAAO,EAAE;AAAA,QACnF,MAAM,OAAO;AAAA,QACb,YAAY,kBAAkB,OAAO,EAAE;AAAA,MACxC,CAAC;AAAA,IACF;AAGA,UAAM,QAAQ,iBAAiB,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,IAAI;AACnE,QAAI,MAAM,SAAS,GAAG;AACrB,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,SAAS,gCAAgC,OAAO,IAAI;AAAA,QACpD,MAAM,OAAO;AAAA,MACd,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO;AACR;;;AKpgBA,SAAS,iBAAiB,MAA6C;AACtE,UAAQ,MAAM;AAAA,IACb,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR;AACC,aAAO;AAAA,EACT;AACD;AAKA,SAAS,eACR,OACA,MACA,IAC+B;AAC/B,SAAO,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,OAAO,IAAI;AACxD;AAKO,SAAS,iBACf,UACA,0BAA0D,CAAC,GAC7C;AACd,QAAM,YAAY,oBAAI,IAA0B;AAChD,QAAM,YAAY,oBAAI,IAA0C;AAChE,QAAM,QAA4B,CAAC;AAGnC,aAAW,UAAU,UAAU;AAC9B,cAAU,IAAI,OAAO,MAAM,MAAM;AAAA,EAClC;AAGA,aAAW,UAAU,yBAAyB;AAC7C,cAAU,IAAI,OAAO,MAAM,MAAM;AAAA,EAClC;AAGA,aAAW,UAAU,UAAU;AAC9B,eAAW,CAAC,SAAS,GAAG,KAAK,OAAO,eAAe;AAClD,UAAI,CAAC,IAAI,SAAU;AAGnB,YAAM,cAAc,eAAe,OAAO,OAAO,MAAM,IAAI,MAAM;AAEjE,YAAM,OAAyB;AAAA,QAC9B,MAAM,OAAO;AAAA,QACb,IAAI,IAAI;AAAA,QACR,cAAc;AAAA,QACd,aAAa,iBAAiB,IAAI,IAAI;AAAA,QACtC,eAAe,gBAAgB;AAAA,MAChC;AAGA,UAAI,aAAa;AAChB,oBAAY,gBAAgB;AAAA,MAC7B;AAEA,YAAM,KAAK,IAAI;AAAA,IAChB;AAAA,EACD;AAGA,aAAW,UAAU,yBAAyB;AAC7C,UAAM,aAAa,UAAU,IAAI,OAAO,IAAI;AAC5C,UAAM,WAAW,UAAU,IAAI,OAAO,EAAE;AAExC,QAAI,cAAc,UAAU;AAE3B,YAAM,OAAyB;AAAA,QAC9B,MAAM,OAAO;AAAA,QACb,IAAI,OAAO;AAAA,QACX,cAAc;AAAA,UACb,MAAM,OAAO;AAAA,UACb,MAAM;AAAA,UACN,QAAQ,OAAO;AAAA,UACf,YAAY,OAAO;AAAA,UACnB,UAAU;AAAA,QACX;AAAA,QACA,aAAa;AAAA,QACb,eAAe,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa;AAAA,MACxD;AAEA,YAAM,KAAK,IAAI;AAAA,IAChB;AAAA,EACD;AAEA,SAAO,EAAE,UAAU,WAAW,yBAAyB,WAAW,MAAM;AACzE;AAKO,SAAS,mBACf,OACA,YACA,QAAQ,GACM;AACd,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,QAAuD;AAAA,IAC5D,EAAE,MAAM,YAAY,cAAc,EAAE;AAAA,EACrC;AAEA,SAAO,MAAM,SAAS,GAAG;AACxB,UAAM,OAAO,MAAM,MAAM;AACzB,QAAI,CAAC,KAAM;AAEX,UAAM,EAAE,MAAM,aAAa,IAAI;AAC/B,QAAI,QAAQ,IAAI,IAAI,KAAK,eAAe,MAAO;AAC/C,YAAQ,IAAI,IAAI;AAEhB,eAAW,QAAQ,MAAM,OAAO;AAC/B,UAAI,KAAK,SAAS,QAAQ,CAAC,QAAQ,IAAI,KAAK,EAAE,GAAG;AAChD,gBAAQ,IAAI,KAAK,EAAE;AACnB,cAAM,KAAK,EAAE,MAAM,KAAK,IAAI,cAAc,eAAe,EAAE,CAAC;AAAA,MAC7D;AACA,UAAI,KAAK,OAAO,QAAQ,CAAC,QAAQ,IAAI,KAAK,IAAI,GAAG;AAChD,gBAAQ,IAAI,KAAK,IAAI;AACrB,cAAM,KAAK,EAAE,MAAM,KAAK,MAAM,cAAc,eAAe,EAAE,CAAC;AAAA,MAC/D;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAKO,SAAS,mBAAmB,OAA8B;AAChE,QAAM,UAAoB,CAAC;AAC3B,aAAW,CAAC,IAAI,KAAK,MAAM,UAAU;AACpC,UAAM,kBAAkB,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,OAAO,IAAI;AAChF,QAAI,CAAC,iBAAiB;AACrB,cAAQ,KAAK,IAAI;AAAA,IAClB;AAAA,EACD;AACA,SAAO;AACR;AAKO,SAAS,yBAAyB,OAAgC;AACxE,QAAM,SAAqB,CAAC;AAC5B,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,iBAAiB,oBAAI,IAAY;AAEvC,WAAS,IAAI,MAAcC,OAAsB;AAChD,YAAQ,IAAI,IAAI;AAChB,mBAAe,IAAI,IAAI;AAEvB,UAAM,gBAAgB,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AAC/D,eAAW,QAAQ,eAAe;AACjC,UAAI,CAAC,QAAQ,IAAI,KAAK,EAAE,GAAG;AAC1B,YAAI,KAAK,IAAI,CAAC,GAAGA,OAAM,KAAK,EAAE,CAAC;AAAA,MAChC,WAAW,eAAe,IAAI,KAAK,EAAE,GAAG;AAEvC,cAAM,aAAaA,MAAK,QAAQ,KAAK,EAAE;AACvC,YAAI,eAAe,IAAI;AACtB,iBAAO,KAAK,CAAC,GAAGA,MAAK,MAAM,UAAU,GAAG,KAAK,EAAE,CAAC;AAAA,QACjD,OAAO;AAEN,iBAAO,KAAK,CAAC,GAAGA,OAAM,KAAK,EAAE,CAAC;AAAA,QAC/B;AAAA,MACD;AAAA,IACD;AAEA,mBAAe,OAAO,IAAI;AAAA,EAC3B;AAEA,aAAW,CAAC,IAAI,KAAK,MAAM,UAAU;AACpC,QAAI,CAAC,QAAQ,IAAI,IAAI,GAAG;AACvB,UAAI,MAAM,CAAC,IAAI,CAAC;AAAA,IACjB;AAAA,EACD;AAGA,QAAM,eAA2B,CAAC;AAClC,QAAM,OAAO,oBAAI,IAAY;AAE7B,aAAW,SAAS,QAAQ;AAE3B,UAAM,WAAW,MAAM;AAAA,MACtB,MAAM,OAAO,CAAC,KAAK,QAAS,MAAM,MAAM,MAAM,KAAM,MAAM,CAAC,CAAC;AAAA,IAC7D;AACA,UAAM,aAAa,CAAC,GAAG,MAAM,MAAM,QAAQ,GAAG,GAAG,MAAM,MAAM,GAAG,QAAQ,CAAC;AACzE,UAAM,MAAM,WAAW,KAAK,IAAI;AAEhC,QAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AACnB,WAAK,IAAI,GAAG;AACZ,mBAAa,KAAK,KAAK;AAAA,IACxB;AAAA,EACD;AAEA,SAAO;AACR;;;ACvNO,IAAM,6BAAiD;AAAA,EAC7D,MAAM;AAAA,EACN,aAAa;AAAA,EAEb,QAAQ;AAAA,IACP;AAAA,MACC,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,gBAAgB,CAAC,WAAW,OAAO;AAAA,MACnC,SAAS;AAAA,MACT,UAAU;AAAA,MACV,IAAI;AAAA,QACH,OAAO;AAAA,QACP,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,SAAS;AAAA,MACV;AAAA,IACD;AAAA,IACA;AAAA,MACC,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,gBAAgB,CAAC,SAAS;AAAA,MAC1B,SAAS;AAAA,MACT,UAAU;AAAA,MACV,IAAI;AAAA,QACH,OAAO;AAAA,QACP,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,SAAS;AAAA,MACV;AAAA,IACD;AAAA,IACA;AAAA,MACC,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,gBAAgB,CAAC,OAAO;AAAA,MACxB,SAAS;AAAA,MACT,UAAU;AAAA,MACV,IAAI;AAAA,QACH,OAAO;AAAA,QACP,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,SAAS;AAAA,MACV;AAAA,IACD;AAAA,EACD;AAAA,EAEA,gBAAgB,CAAC,WAAW,SAAS,OAAO;AAAA,EAE5C,WAAW;AACZ;;;AC5DO,IAAM,qBAAyC;AAAA,EACrD,MAAM;AAAA,EACN,aAAa;AAAA,EAEb,QAAQ;AAAA,IACP;AAAA,MACC,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,gBAAgB,CAAC,WAAW;AAAA,MAC5B,SAAS;AAAA,MACT,UAAU;AAAA,MACV,IAAI;AAAA,QACH,OAAO;AAAA,QACP,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,SAAS;AAAA,MACV;AAAA,IACD;AAAA,EACD;AAAA,EAEA,gBAAgB,CAAC,WAAW;AAAA,EAE5B,SAAS;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,EACD;AAAA,EAEA,WAAW;AACZ;;;ACpCO,IAAM,qBAAyC;AAAA,EACrD,MAAM;AAAA,EACN,aAAa;AAAA,EAEb,QAAQ;AAAA,IACP;AAAA,MACC,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,gBAAgB,CAAC,WAAW;AAAA,MAC5B,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS;AAAA,MACT,IAAI;AAAA,QACH,OAAO;AAAA,QACP,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,SAAS;AAAA,MACV;AAAA,IACD;AAAA,IACA;AAAA,MACC,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,gBAAgB,CAAC,WAAW;AAAA,MAC5B,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS;AAAA,MACT,IAAI;AAAA,QACH,OAAO;AAAA,QACP,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,SAAS;AAAA,MACV;AAAA,IACD;AAAA,EACD;AAAA,EAEA,gBAAgB,CAAC,WAAW;AAAA,EAE5B,SAAS,CAAC,2BAA2B,yBAAyB;AAAA,EAE9D,WAAW;AACZ;;;AC9CO,IAAM,uBAA2C;AAAA,EACvD,MAAM;AAAA,EACN,aAAa;AAAA,EAEb,QAAQ;AAAA,IACP;AAAA,MACC,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,gBAAgB,CAAC,MAAM;AAAA,MACvB,SAAS;AAAA,MACT,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,IAAI;AAAA,QACH,OAAO;AAAA,QACP,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,SAAS;AAAA,MACV;AAAA,IACD;AAAA,IACA;AAAA,MACC,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,gBAAgB,CAAC,MAAM;AAAA,MACvB,SAAS;AAAA,MACT,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,IAAI;AAAA,QACH,OAAO;AAAA,QACP,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,OAAO;AAAA,QACP,SAAS;AAAA,MACV;AAAA,IACD;AAAA,EACD;AAAA,EAEA,gBAAgB,CAAC,MAAM;AAAA,EAEvB,SAAS,CAAC,6BAA6B,2BAA2B;AAAA,EAElE,WAAW;AACZ;;;ACjCA,IAAM,mBAAmB,oBAAI,IAAgC;AAAA,EAC5D,CAAC,cAAc,kBAAkB;AAAA,EACjC,CAAC,eAAe,kBAAkB;AAAA,EAClC,CAAC,iBAAiB,oBAAoB;AAAA,EACtC,CAAC,wBAAwB,0BAA0B;AACpD,CAAC;AAKM,SAAS,YAAY,MAA8C;AACzE,SAAO,iBAAiB,IAAI,IAAI;AACjC;AAgBO,SAAS,wBACf,QAC2B;AAC3B,MAAI,OAAO,WAAW,UAAU;AAC/B,WAAO,EAAE,MAAM,QAAQ,SAAS,CAAC,EAAE;AAAA,EACpC;AACA,SAAO,EAAE,MAAM,OAAO,MAAM,SAAS,OAAO,WAAW,CAAC,EAAE;AAC3D;AAKO,SAAS,yBACf,SAC6B;AAC7B,SAAO,QAAQ,IAAI,uBAAuB;AAC3C;AA8DO,SAAS,sBACf,SACkB;AAClB,QAAM,aAAa,yBAAyB,OAAO;AACnD,QAAM,SAA0B,CAAC;AACjC,QAAM,kBAAkB,oBAAI,IAAY;AAExC,aAAW,UAAU,YAAY;AAChC,UAAM,WAAW,YAAY,OAAO,IAAI;AACxC,QAAI,CAAC,SAAU;AAEf,eAAW,SAAS,SAAS,QAAQ;AAEpC,UAAI,CAAC,gBAAgB,IAAI,MAAM,IAAI,GAAG;AACrC,eAAO,KAAK,KAAK;AACjB,wBAAgB,IAAI,MAAM,IAAI;AAAA,MAC/B;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;;;ACrIO,SAAS,iBAAiB,OAAqC;AACrE,QAAM,SAA0B,CAAC;AAGjC,aAAW,CAAC,MAAM,MAAM,KAAK,MAAM,UAAU;AAC5C,WAAO,KAAK,GAAG,uBAAuB,MAAM,CAAC;AAC7C,WAAO,KAAK,GAAG,6BAA6B,QAAQ,KAAK,CAAC;AAC1D,WAAO,KAAK,GAAG,uBAAuB,MAAM,CAAC;AAC7C,WAAO,KAAK,GAAG,oBAAoB,MAAM,CAAC;AAC1C,WAAO,KAAK,GAAG,gBAAgB,MAAM,CAAC;AACtC,QAAI,OAAO,YAAY,QAAW;AACjC,aAAO,KAAK,GAAG,0BAA0B,MAAM,CAAC;AAAA,IACjD;AACA,QAAI,OAAO,SAAS,QAAW;AAC9B,aAAO,KAAK,GAAG,gCAAgC,MAAM,CAAC;AACtD,aAAO,KAAK,GAAG,iCAAiC,MAAM,CAAC;AAAA,IACxD;AAAA,EACD;AAGA,SAAO,KAAK,GAAG,oBAAoB,KAAK,CAAC;AACzC,SAAO,KAAK,GAAG,wBAAwB,KAAK,CAAC;AAC7C,SAAO,KAAK,GAAG,qBAAqB,KAAK,CAAC;AAE1C,SAAO;AACR;AAKA,SAAS,uBAAuB,QAAuC;AACtE,QAAM,SAA0B,CAAC;AAGjC,MAAI,CAAC,OAAO,OAAO,IAAI,IAAI,GAAG;AAC7B,WAAO,KAAK;AAAA,MACX,UAAU;AAAA,MACV,MAAM;AAAA,MACN,QAAQ,OAAO;AAAA,MACf,SAAS;AAAA,MACT,YAAY;AAAA,IACb,CAAC;AAAA,EACF;AAGA,QAAM,eAAe,OAAO,OAAO,IAAI,YAAY;AACnD,QAAM,wBAAwB,OAAO,UAAU,SAAS,YAAY;AAEpE,MAAI,CAAC,gBAAgB,CAAC,uBAAuB;AAC5C,WAAO,KAAK;AAAA,MACX,UAAU;AAAA,MACV,MAAM;AAAA,MACN,QAAQ,OAAO;AAAA,MACf,SAAS;AAAA,MACT,YAAY;AAAA,IACb,CAAC;AAAA,EACF;AAEA,SAAO;AACR;AAKA,SAAS,6BACR,QACA,OACkB;AAClB,QAAM,SAA0B,CAAC;AAEjC,aAAW,CAAC,SAAS,GAAG,KAAK,OAAO,eAAe;AAElD,QAAI,IAAI,SAAS,cAAc;AAC9B,YAAM,UAAU,OAAO,OAAO,IAAI,IAAI,UAAU;AAChD,UAAI,CAAC,SAAS;AACb,eAAO,KAAK;AAAA,UACX,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,OAAO;AAAA,UACf,OAAO;AAAA,UACP,SAAS,iBAAiB,OAAO,6BAA6B,IAAI,UAAU;AAAA,UAC5E,YAAY,cAAc,IAAI,UAAU;AAAA,QACzC,CAAC;AAAA,MACF;AAAA,IACD;AAGA,QAAI,IAAI,SAAS,cAAc,IAAI,SAAS,WAAW;AACtD,YAAM,eAAe,MAAM,SAAS,IAAI,IAAI,MAAM;AAClD,UAAI,cAAc;AACjB,cAAM,gBAAgB,aAAa,OAAO,IAAI,IAAI,UAAU;AAC5D,YAAI,CAAC,eAAe;AACnB,iBAAO,KAAK;AAAA,YACX,UAAU;AAAA,YACV,MAAM;AAAA,YACN,QAAQ,OAAO;AAAA,YACf,OAAO;AAAA,YACP,SAAS,iBAAiB,OAAO,0BAA0B,IAAI,UAAU,SAAS,IAAI,MAAM;AAAA,YAC5F,YAAY,cAAc,IAAI,UAAU,SAAS,IAAI,MAAM;AAAA,UAC5D,CAAC;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAKA,SAAS,uBAAuB,QAAuC;AACtE,QAAM,SAA0B,CAAC;AAGjC,MAAI,OAAO,SAAS,OAAO,KAAK,YAAY,GAAG;AAC9C,WAAO,KAAK;AAAA,MACX,UAAU;AAAA,MACV,MAAM;AAAA,MACN,QAAQ,OAAO;AAAA,MACf,SAAS;AAAA,MACT,YAAY,QAAQ,OAAO,KAAK,YAAY,CAAC;AAAA,IAC9C,CAAC;AAAA,EACF;AAGA,aAAW,CAAC,SAAS,KAAK,OAAO,QAAQ;AACxC,QAAI,cAAc,UAAU,YAAY,GAAG;AAC1C,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,OAAO;AAAA,QACP,SAAS;AAAA,QACT,YAAY,QAAQ,YAAY,SAAS,CAAC;AAAA,MAC3C,CAAC;AAAA,IACF;AAAA,EACD;AAGA,aAAW,CAAC,OAAO,KAAK,OAAO,eAAe;AAC7C,QAAI,YAAY,QAAQ,YAAY,GAAG;AACtC,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,OAAO;AAAA,QACP,SAAS;AAAA,QACT,YAAY,QAAQ,YAAY,OAAO,CAAC;AAAA,MACzC,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO;AACR;AAKA,SAAS,oBAAoB,QAAuC;AACnE,QAAM,SAA0B,CAAC;AAEjC,aAAW,CAAC,WAAW,KAAK,KAAK,OAAO,QAAQ;AAE/C,QAAI,MAAM,GAAG,cAAc,CAAC,MAAM,SAAS,CAAC,MAAM,QAAQ;AACzD,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,OAAO;AAAA,QACP,SAAS,UAAU,SAAS;AAAA,QAC5B,YAAY;AAAA,MACb,CAAC;AAAA,IACF;AAGA,QAAI,MAAM,cAAc,CAAC,MAAM,SAAS,CAAC,MAAM,QAAQ;AACtD,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,OAAO;AAAA,QACP,SAAS,sBAAsB,SAAS;AAAA,QACxC,YAAY;AAAA,MACb,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO;AACR;AAKA,SAAS,gBAAgB,QAAuC;AAC/D,QAAM,SAA0B,CAAC;AAGjC,QAAM,eAAe,oBAAI,IAAI,CAAC,MAAM,cAAc,cAAc,cAAc,WAAW,CAAC;AAE1F,aAAW,CAAC,WAAW,KAAK,KAAK,OAAO,QAAQ;AAC/C,QAAI,aAAa,IAAI,SAAS,EAAG;AAEjC,UAAM,eACL,MAAM,GAAG,UAAU,UACnB,MAAM,GAAG,SAAS,UAClB,MAAM,GAAG,UAAU;AAEpB,QAAI,CAAC,cAAc;AAClB,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,OAAO;AAAA,QACP,SAAS,UAAU,SAAS;AAAA,QAC5B,YAAY;AAAA,MACb,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO;AACR;AAKA,SAAS,oBAAoB,OAAqC;AACjE,QAAM,UAAU,mBAAmB,KAAK;AACxC,SAAO,QAAQ,IAAI,CAAC,UAAU;AAAA,IAC7B,UAAU;AAAA,IACV,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS,WAAW,IAAI;AAAA,IACxB,YAAY;AAAA,EACb,EAAE;AACH;AAKA,SAAS,wBAAwB,OAAqC;AACrE,QAAM,SAAS,yBAAyB,KAAK;AAC7C,SAAO,OAAO,IAAI,CAAC,WAAW;AAAA,IAC7B,UAAU;AAAA,IACV,MAAM;AAAA,IACN,QAAQ,MAAM,CAAC;AAAA,IACf,SAAS,gCAAgC,MAAM,KAAK,MAAM,CAAC;AAAA,IAC3D,YAAY;AAAA,EACb,EAAE;AACH;AAKA,SAAS,qBAAqB,OAAqC;AAClE,QAAM,SAA0B,CAAC;AAEjC,aAAW,QAAQ,MAAM,OAAO;AAC/B,UAAM,EAAE,MAAM,IAAI,aAAa,IAAI;AACnC,UAAM,eAAe,MAAM,SAAS,IAAI,EAAE;AAC1C,QAAI,CAAC,aAAc;AAGnB,UAAM,aAAa,MAAM,KAAK,aAAa,cAAc,OAAO,CAAC,EAAE;AAAA,MAClE,CAAC,QAAQ,IAAI,WAAW;AAAA,IACzB;AAIA,QAAI,CAAC,cAAc,aAAa,SAAS,cAAc;AACtD,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,OAAO,aAAa;AAAA,QACpB,SAAS,iBAAiB,aAAa,IAAI,SAAS,EAAE;AAAA,QACtD,YAAY,gCAAgC,EAAE,uBAAuB,IAAI;AAAA,MAC1E,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO;AACR;AAOA,SAAS,uBAAuB,QAAgC;AAC/D,QAAM,mBAAmB,MAAM,KAAK,OAAO,OAAO,KAAK,CAAC;AACxD,QAAM,iBAAiB,sBAAsB,OAAO,SAAS;AAC7D,QAAM,qBAAqB,eAAe,IAAI,CAAC,MAAM,EAAE,IAAI;AAC3D,QAAM,mBAA6B,CAAC;AACpC,aAAW,OAAO,OAAO,cAAc,OAAO,GAAG;AAChD,QAAI,IAAI,SAAS,gBAAgB,IAAI,YAAY;AAChD,uBAAiB,KAAK,IAAI,UAAU;AAAA,IACrC;AAAA,EACD;AACA,SAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,kBAAkB,GAAG,oBAAoB,GAAG,gBAAgB,CAAC,CAAC;AACtF;AAKA,SAAS,0BAA0B,QAAuC;AACzE,QAAM,SAA0B,CAAC;AACjC,QAAM,kBAAkB,uBAAuB,MAAM;AACrD,QAAM,eAAe,IAAI,IAAI,eAAe;AAE5C,aAAW,SAAS,OAAO,WAAW,CAAC,GAAG;AAEzC,QAAI,CAAC,MAAM,KAAK;AACf,iBAAW,aAAa,MAAM,IAAI;AACjC,YAAI,CAAC,aAAa,IAAI,SAAS,GAAG;AACjC,iBAAO,KAAK;AAAA,YACX,UAAU;AAAA,YACV,MAAM;AAAA,YACN,QAAQ,OAAO;AAAA,YACf,OAAO;AAAA,YACP,SAAS,mCAAmC,SAAS,gBAAgB,OAAO,IAAI,wBAAwB,gBAAgB,KAAK,IAAI,CAAC;AAAA,UACnI,CAAC;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAEA,eAAW,aAAa,MAAM,UAAU,CAAC,GAAG;AAC3C,UAAI,CAAC,aAAa,IAAI,SAAS,GAAG;AACjC,eAAO,KAAK;AAAA,UACX,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,OAAO;AAAA,UACf,OAAO;AAAA,UACP,SAAS,mCAAmC,SAAS,gBAAgB,OAAO,IAAI,wBAAwB,gBAAgB,KAAK,IAAI,CAAC;AAAA,QACnI,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAKA,SAAS,gCAAgC,QAAuC;AAC/E,QAAM,SAA0B,CAAC;AACjC,QAAM,kBAAkB,uBAAuB,MAAM;AACrD,QAAM,eAAe,IAAI,IAAI,eAAe;AAE5C,aAAW,CAAC,cAAc,QAAQ,KAAK,OAAO,QAAQ,OAAO,MAAM,aAAa,CAAC,CAAC,GAAG;AACpF,eAAW,aAAa,OAAO,KAAK,SAAS,gBAAgB,CAAC,CAAC,GAAG;AACjE,UAAI,CAAC,aAAa,IAAI,SAAS,GAAG;AACjC,eAAO,KAAK;AAAA,UACX,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,OAAO;AAAA,UACf,OAAO;AAAA,UACP,SAAS,gDAAgD,SAAS,mBAAmB,YAAY,gBAAgB,OAAO,IAAI;AAAA,QAC7H,CAAC;AAAA,MACF;AAAA,IACD;AAEA,eAAW,aAAa,SAAS,kBAAkB,CAAC,GAAG;AACtD,UAAI,CAAC,aAAa,IAAI,SAAS,GAAG;AACjC,eAAO,KAAK;AAAA,UACX,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,OAAO;AAAA,UACf,OAAO;AAAA,UACP,SAAS,gDAAgD,SAAS,mBAAmB,YAAY,gBAAgB,OAAO,IAAI;AAAA,QAC7H,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAKA,SAAS,iCAAiC,QAAuC;AAChF,QAAM,SAA0B,CAAC;AAEjC,QAAM,wBAAwB,OAAO,UAAU,SAAS,sBAAsB;AAC9E,MAAI,CAAC,sBAAuB,QAAO;AAEnC,aAAW,CAAC,cAAc,QAAQ,KAAK,OAAO,QAAQ,OAAO,MAAM,aAAa,CAAC,CAAC,GAAG;AACpF,QAAI,SAAS,gBAAgB,iBAAiB,SAAS,cAAc;AACpE,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,OAAO;AAAA,QACP,SAAS,WAAW,OAAO,IAAI,uGAAuG,YAAY;AAAA,MACnJ,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO;AACR;AAKA,SAAS,YAAY,KAAqB;AACzC,SAAO,IACL,QAAQ,YAAY,KAAK,EACzB,YAAY,EACZ,QAAQ,MAAM,EAAE;AACnB;;;ACjaO,SAAS,kBAAkB,OAAsC;AACvE,QAAM,WAAW,MAAM,KAAK,MAAM,SAAS,OAAO,CAAC;AAEnD,QAAM,eAAuC,CAAC;AAC9C,QAAM,sBAA8C,CAAC;AACrD,MAAI,cAAc;AAClB,MAAI,qBAAqB;AACzB,MAAI,wBAAwB;AAE5B,aAAW,UAAU,UAAU;AAC9B,mBAAe,OAAO,OAAO;AAC7B,0BAAsB,OAAO,cAAc;AAE3C,QAAI,OAAO,UAAU,SAAS,GAAG;AAChC;AAAA,IACD;AAGA,eAAW,SAAS,OAAO,OAAO,OAAO,GAAG;AAC3C,mBAAa,MAAM,IAAI,KAAK,aAAa,MAAM,IAAI,KAAK,KAAK;AAAA,IAC9D;AAGA,eAAW,OAAO,OAAO,cAAc,OAAO,GAAG;AAChD,0BAAoB,IAAI,IAAI,KAAK,oBAAoB,IAAI,IAAI,KAAK,KAAK;AAAA,IACxE;AAAA,EACD;AAEA,SAAO;AAAA,IACN,eAAe,SAAS;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,wBAAwB,SAAS,SAAS,IAAI,cAAc,SAAS,SAAS;AAAA,EAC/E;AACD;;;AC3BA,SAAS,YAAY;AACrB,OAAO,UAAU;AACjB,SAAS,qBAAqB;;;AC6EvB,SAAS,cACf,KAC6B;AAC7B,SAAO;AACR;AAcO,SAAS,oBAAoB,KAAwC;AAC3E,SACC,OAAO,QAAQ,YACf,QAAQ,QACR,UAAU,OACV,OAAQ,IAA0B,SAAS;AAE7C;;;AD5FA,IAAM,mBAAmD,oBAAI,IAAI;AACjE,IAAM,eAA+C,oBAAI,IAAI;AAQ7D,SAAS,sBAAsB,KAA8B;AAC5D,QAAM,aAAa,MAAM,QAAQ,IAAI,OAAO,KAAK,IAAI,QAAQ,SAAS;AACtE,QAAM,UACL,OAAO,IAAI,oBAAoB,YAAY,IAAI,gBAAgB,SAAS;AACzE,QAAM,aACL,OAAO,IAAI,iBAAiB,YAAY,IAAI,aAAa,SAAS;AAEnE,MAAI,CAAC,cAAc,CAAC,WAAW,CAAC,YAAY;AAC3C,UAAM,IAAI;AAAA,MACT,YAAY,IAAI,IAAI;AAAA,IAErB;AAAA,EACD;AACD;AAaO,SAAS,uBAAuB,KAA8B;AACpE,wBAAsB,GAAG;AACzB,mBAAiB,IAAI,IAAI,MAAM,GAAG;AACnC;AAUO,SAAS,WAAW,MAA6C;AACvE,SAAO,aAAa,IAAI,IAAI,KAAK,iBAAiB,IAAI,IAAI;AAC3D;AAOO,SAAS,qBAA+B;AAC9C,QAAM,MAAM,oBAAI,IAAY;AAAA,IAC3B,GAAG,iBAAiB,KAAK;AAAA,IACzB,GAAG,aAAa,KAAK;AAAA,EACtB,CAAC;AACD,SAAO,CAAC,GAAG,GAAG,EAAE,KAAK;AACtB;AAGO,SAAS,yBAAmC;AAClD,SAAO,CAAC,GAAG,iBAAiB,KAAK,CAAC,EAAE,KAAK;AAC1C;AAGO,SAAS,qBAA+B;AAC9C,SAAO,CAAC,GAAG,aAAa,KAAK,CAAC,EAAE,KAAK;AACtC;AA4BA,eAAsB,gBACrB,eACA,KACiC;AACjC,QAAM,SAAS,oBAAI,IAAY;AAC/B,QAAM,SAAmB,CAAC;AAI1B,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,OAAO,eAAe;AAChC,QAAI;AACH,YAAM,WAAW,MAAM,KAAK,KAAK,EAAE,KAAK,UAAU,MAAM,OAAO,KAAK,CAAC;AACrE,iBAAW,YAAY,UAAU;AAChC,cAAM,IAAI,QAAQ;AAAA,MACnB;AAAA,IACD,SAAS,KAAK;AACb,aAAO;AAAA,QACN,kCAAkC,GAAG,MAAM,eAAe,GAAG,CAAC;AAAA,MAC/D;AAAA,IACD;AAAA,EACD;AAKA,QAAM,cAAc,CAAC,GAAG,KAAK,EAAE,KAAK;AAEpC,aAAW,YAAY,aAAa;AACnC,QAAI;AAGH,YAAM,MAAO,MAAM,OAAO,cAAc,QAAQ,EAAE;AAIlD,iBAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC7C,YAAI,CAAC,IAAI,SAAS,SAAS,EAAG;AAC9B,YAAI,CAAC,oBAAoB,GAAG,EAAG;AAC/B,YAAI;AACH,gCAAsB,GAAG;AACzB,uBAAa,IAAI,IAAI,MAAM,GAAG;AAC9B,iBAAO,IAAI,IAAI,IAAI;AAAA,QACpB,SAAS,WAAW;AACnB,iBAAO;AAAA,YACN,YAAY,IAAI,IAAI,QAAQ,QAAQ,UAAU,GAAG,CAAC,gBAAgB,eAAe,SAAS,CAAC;AAAA,UAC5F;AAAA,QACD;AAAA,MACD;AAAA,IACD,SAAS,KAAK;AACb,aAAO;AAAA,QACN,gCAAgC,QAAQ,UAAU,GAAG,CAAC,MAAM,eAAe,GAAG,CAAC;AAAA,MAChF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AAAA,IACN,QAAQ,CAAC,GAAG,MAAM,EAAE,KAAK;AAAA,IACzB;AAAA,EACD;AACD;AA0BA,SAAS,eAAe,KAAsB;AAC7C,MAAI,eAAe,MAAO,QAAO,IAAI;AACrC,SAAO,OAAO,GAAG;AAClB;AAEA,SAAS,QAAQ,KAAa,KAAqB;AAClD,MAAI;AACH,WAAO,KAAK,SAAS,KAAK,GAAG,KAAK;AAAA,EACnC,QAAQ;AACP,WAAO;AAAA,EACR;AACD;;;AE1LO,SAAS,2BACf,QACkB;AAClB,QAAM,SAA0B,CAAC;AAMjC,QAAM,eAAyB,OAAO,aAAa,OAAO,UAAU,CAAC,OAAO,OAAO,IAAI,CAAC;AACxF,MAAI,aAAa,WAAW,EAAG,QAAO;AAMtC,QAAM,gBAAgB,oBAAI,IAAoB;AAE9C,aAAW,CAAC,IAAI,KAAK,OAAO,QAAQ;AACnC,kBAAc,IAAI,MAAM,iBAAiB,IAAI,GAAG;AAAA,EACjD;AAMA,QAAM,iBAAiB,sBAAsB,OAAO,SAAS;AAC7D,aAAW,MAAM,gBAAgB;AAChC,UAAM,WAAW,cAAc,IAAI,GAAG,IAAI;AAC1C,QAAI,UAAU;AAKb,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,SACC,+BAA+B,GAAG,IAAI,oBAAoB,QAAQ;AAAA,MACpE,CAAC;AACD;AAAA,IACD;AACA,kBAAc,IAAI,GAAG,MAAM,mBAAmB,GAAG,IAAI,GAAG;AAAA,EACzD;AAMA,QAAM,mBAAmB,IAAI,IAAY,OAAO,SAAS;AAEzD,aAAW,eAAe,cAAc;AACvC,UAAM,MAAM,WAAW,WAAW;AAGlC,QAAI,CAAC,KAAK;AACT,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,OAAO;AAAA,QACf,SACC,oBAAoB,WAAW;AAAA,MAGjC,CAAC;AACD;AAAA,IACD;AAGA,QAAI,IAAI,cAAc;AACrB,YAAM,YAAY,OAAO,gBAAgB,WAAW;AACpD,YAAM,SAAS,IAAI,aAAa,UAAU,aAAa,CAAC,CAAC;AACzD,UAAI,CAAC,OAAO,SAAS;AACpB,cAAM,SAAS,OAAO,MAAM,OAC1B,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,KAAK,GAAG,KAAK,QAAQ,KAAK,EAAE,OAAO,EAAE,EAC1D,KAAK,IAAI;AACX,eAAO,KAAK;AAAA,UACX,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,OAAO;AAAA,UACf,SACC,YAAY,WAAW,+BAA+B,MAAM;AAAA,QAC9D,CAAC;AAAA,MACF;AAAA,IACD;AAKA,eAAW,OAAO,IAAI,WAAW,CAAC,GAAG;AACpC,YAAM,WAAW,cAAc,IAAI,IAAI,IAAI;AAC3C,UAAI,UAAU;AACb,eAAO,KAAK;AAAA,UACX,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,OAAO;AAAA,UACf,SACC,YAAY,WAAW,yBAAyB,IAAI,IAAI,0BAChC,QAAQ;AAAA,QAClC,CAAC;AACD;AAAA,MACD;AACA,oBAAc,IAAI,IAAI,MAAM,YAAY,WAAW,GAAG;AAAA,IACvD;AAKA,eAAW,KAAK,IAAI,oBAAoB,CAAC,GAAG;AAC3C,uBAAiB,IAAI,CAAC;AAAA,IACvB;AAAA,EACD;AAGA,MAAI,OAAO,eAAe;AACzB,UAAM,WAAW,IAAI,IAAI,YAAY;AACrC,eAAW,OAAO,OAAO,KAAK,OAAO,aAAa,GAAG;AACpD,UAAI,CAAC,SAAS,IAAI,GAAG,GAAG;AACvB,eAAO,KAAK;AAAA,UACX,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,OAAO;AAAA,UACf,SACC,yBAAyB,GAAG,kBAAkB,GAAG;AAAA,QAGnD,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AA2BO,SAAS,uBACf,KACkB;AAClB,QAAM,SAA0B,CAAC;AAEjC,MAAI,IAAI,iBAAiB,SAAS;AACjC,UAAM,eAAe,IAAI,SAAS;AAAA,MACjC,CAAC,MAAO,EAAE,YAAY,EAAE,SAAS,SAAS,KAAM,CAAC,CAAC,EAAE;AAAA,IACrD;AACA,eAAW,KAAK,cAAc;AAC7B,aAAO,KAAK;AAAA,QACX,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,EAAE;AAAA,QACV,SACC;AAAA,MAIF,CAAC;AAAA,IACF;AAAA,EACD;AAEA,SAAO;AACR;;;AC/NA,IAAM,SAAS;AAAA,EACd,OAAO;AAAA,EACP,MAAM;AAAA,EACN,KAAK;AAAA,EAEL,KAAK;AAAA,EACL,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,SAAS;AAAA,EACT,MAAM;AAAA,EACN,OAAO;AAAA,EAEP,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AACX;AAEA,SAAS,MAAM,SAAiB,QAA0B;AACzD,SAAO,GAAG,OAAO,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,OAAO,KAAK;AAChD;AAEA,SAAS,cAAc,UAA4B;AAClD,UAAQ,UAAU;AAAA,IACjB,KAAK;AACJ,aAAO,OAAO;AAAA,IACf,KAAK;AACJ,aAAO,OAAO;AAAA,IACf,KAAK;AACJ,aAAO,OAAO;AAAA,EAChB;AACD;AAEA,SAAS,aAAa,UAA4B;AACjD,UAAQ,UAAU;AAAA,IACjB,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,EACT;AACD;AAKO,SAAS,cAAc,QAAgC;AAC7D,QAAM,QAAkB,CAAC;AAGzB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,MAAM,IAAI,OAAO,EAAE,GAAG,OAAO,GAAG,CAAC;AAC5C,QAAM,KAAK,MAAM,4BAA4B,OAAO,MAAM,OAAO,IAAI,CAAC;AACtE,QAAM,KAAK,MAAM,IAAI,OAAO,EAAE,GAAG,OAAO,GAAG,CAAC;AAC5C,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,GAAG,iBAAiB,MAAM,CAAC;AAGtC,QAAM,KAAK,GAAG,eAAe,MAAM,CAAC;AAGpC,QAAM,KAAK,GAAG,oBAAoB,MAAM,CAAC;AAGzC,MAAI,OAAO,OAAO,SAAS,GAAG;AAC7B,UAAM,KAAK,GAAG,aAAa,OAAO,MAAM,CAAC;AAAA,EAC1C;AAGA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,MAAM,IAAI,OAAO,EAAE,GAAG,OAAO,GAAG,CAAC;AAE5C,QAAM,SAAS,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO;AACjE,QAAM,WAAW,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS;AACrE,QAAM,QAAQ,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,MAAM;AAE/D,MAAI,OAAO,SAAS;AACnB,UAAM;AAAA,MACL;AAAA,QACC,yBAAyB,SAAS,MAAM,cAAc,MAAM,MAAM;AAAA,QAClE,OAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD,OAAO;AACN,UAAM,KAAK,MAAM,qBAAqB,OAAO,MAAM,WAAW,OAAO,GAAG,CAAC;AAAA,EAC1E;AAEA,QAAM,KAAK,MAAM,IAAI,OAAO,EAAE,GAAG,OAAO,GAAG,CAAC;AAC5C,QAAM,KAAK,EAAE;AAEb,SAAO,MAAM,KAAK,IAAI;AACvB;AAEA,SAAS,iBAAiB,QAAkC;AAC3D,QAAM,QAAkB,CAAC;AACzB,QAAM,QAAQ,OAAO;AAErB,QAAM,KAAK,MAAM,eAAe,OAAO,IAAI,CAAC;AAC5C,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,uBAAuB,MAAM,aAAa,EAAE;AACvD,QAAM;AAAA,IACL,uBAAuB,MAAM,WAAW,SAAS,MAAM,uBAAuB,QAAQ,CAAC,CAAC;AAAA,EACzF;AACA,QAAM,KAAK,uBAAuB,MAAM,kBAAkB,EAAE;AAC5D,QAAM,KAAK,uBAAuB,MAAM,qBAAqB,EAAE;AAC/D,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,iBAAiB;AAC5B,QAAM,cAAc,OAAO,QAAQ,MAAM,YAAY,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AACjF,aAAW,CAAC,MAAM,KAAK,KAAK,aAAa;AACxC,UAAM,MAAM,MAAM,IAAI,OAAO,KAAK,IAAI,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI;AAC9D,UAAM,KAAK,QAAQ,KAAK,OAAO,EAAE,CAAC,IAAI,GAAG,IAAI,KAAK,EAAE;AAAA,EACrD;AACA,QAAM,KAAK,EAAE;AAGb,MAAI,MAAM,qBAAqB,GAAG;AACjC,UAAM,KAAK,wBAAwB;AACnC,UAAM,aAAa,OAAO,QAAQ,MAAM,mBAAmB,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AACvF,eAAW,CAAC,MAAM,KAAK,KAAK,YAAY;AACvC,YAAM,MAAM,MAAM,IAAI,OAAO,KAAK,IAAI,OAAO,EAAE,CAAC,GAAG,OAAO,OAAO;AACjE,YAAM,KAAK,QAAQ,KAAK,OAAO,EAAE,CAAC,IAAI,GAAG,IAAI,KAAK,EAAE;AAAA,IACrD;AACA,UAAM,KAAK,EAAE;AAAA,EACd;AAEA,SAAO;AACR;AAEA,SAAS,eAAe,QAAkC;AACzD,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,MAAM,aAAa,OAAO,IAAI,CAAC;AAC1C,QAAM,KAAK,EAAE;AAEb,aAAW,UAAU,OAAO,UAAU;AACrC,UAAM,aAAa,OAAO,OAAO;AACjC,UAAM,WAAW,OAAO,cAAc;AACtC,UAAM;AAAA,MACL,MAAM,MAAM,OAAO,MAAM,OAAO,IAAI,CAAC,KAAK,UAAU,YAAY,QAAQ;AAAA,IACzE;AACA,QAAI,OAAO,UAAU,SAAS,GAAG;AAChC,YAAM,KAAK,MAAM,oBAAoB,OAAO,UAAU,KAAK,IAAI,CAAC,IAAI,OAAO,GAAG,CAAC;AAAA,IAChF;AAAA,EACD;AACA,QAAM,KAAK,EAAE;AAEb,SAAO;AACR;AAEA,SAAS,oBAAoB,QAAkC;AAC9D,QAAM,QAAkB,CAAC;AAEzB,MAAI,OAAO,MAAM,MAAM,WAAW,GAAG;AACpC,WAAO;AAAA,EACR;AAEA,QAAM,KAAK,MAAM,kBAAkB,OAAO,IAAI,CAAC;AAC/C,QAAM,KAAK,EAAE;AAEb,aAAW,QAAQ,OAAO,MAAM,OAAO;AACtC,UAAM,QAAQ,oBAAoB,KAAK,WAAW;AAClD,UAAM,QAAQ,KAAK,gBAAgB,MAAM,oBAAoB,OAAO,GAAG,IAAI;AAC3E,UAAM;AAAA,MACL,MAAM,KAAK,KAAK,OAAO,EAAE,CAAC,IAAI,KAAK,IAAI,KAAK,EAAE,IAAI,MAAM,IAAI,KAAK,aAAa,IAAI,KAAK,OAAO,GAAG,CAAC,GAAG,KAAK;AAAA,IAC3G;AAAA,EACD;AACA,QAAM,KAAK,EAAE;AAEb,SAAO;AACR;AAEA,SAAS,oBAAoB,aAA6B;AACzD,UAAQ,aAAa;AAAA,IACpB,KAAK;AACJ,aAAO,MAAM,OAAO,OAAO,OAAO;AAAA,IACnC,KAAK;AACJ,aAAO,MAAM,OAAO,OAAO,OAAO;AAAA,IACnC,KAAK;AACJ,aAAO,MAAM,OAAO,OAAO,OAAO;AAAA,IACnC,KAAK;AACJ,aAAO,MAAM,OAAO,OAAO,OAAO;AAAA,IACnC;AACC,aAAO,MAAM,OAAO,OAAO,OAAO;AAAA,EACpC;AACD;AAEA,SAAS,aAAa,QAAmC;AACxD,QAAM,QAAkB,CAAC;AAGzB,QAAM,SAAS,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO;AAC1D,QAAM,WAAW,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS;AAC9D,QAAM,QAAQ,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,MAAM;AAExD,MAAI,OAAO,SAAS,GAAG;AACtB,UAAM,KAAK,MAAM,WAAW,OAAO,MAAM,MAAM,OAAO,MAAM,OAAO,GAAG,CAAC;AACvE,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,GAAG,gBAAgB,QAAQ,OAAO,CAAC;AAC9C,UAAM,KAAK,EAAE;AAAA,EACd;AAEA,MAAI,SAAS,SAAS,GAAG;AACxB,UAAM,KAAK,MAAM,aAAa,SAAS,MAAM,MAAM,OAAO,MAAM,OAAO,MAAM,CAAC;AAC9E,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,GAAG,gBAAgB,UAAU,SAAS,CAAC;AAClD,UAAM,KAAK,EAAE;AAAA,EACd;AAEA,MAAI,MAAM,SAAS,GAAG;AACrB,UAAM,KAAK,MAAM,SAAS,MAAM,MAAM,MAAM,OAAO,MAAM,OAAO,IAAI,CAAC;AACrE,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,GAAG,gBAAgB,OAAO,QAAQ,CAAC,CAAC;AAC/C,UAAM,KAAK,EAAE;AAAA,EACd;AAEA,SAAO;AACR;AAEA,SAAS,gBACR,QACA,UACA,OACW;AACX,QAAM,QAAkB,CAAC;AACzB,QAAM,gBAAgB,QAAQ,OAAO,MAAM,GAAG,KAAK,IAAI;AAGvD,QAAM,SAAS,oBAAI,IAA6B;AAChD,aAAW,SAAS,eAAe;AAClC,UAAM,OAAO,OAAO,IAAI,MAAM,IAAI,KAAK,CAAC;AACxC,SAAK,KAAK,KAAK;AACf,WAAO,IAAI,MAAM,MAAM,IAAI;AAAA,EAC5B;AAEA,aAAW,CAAC,MAAM,UAAU,KAAK,QAAQ;AACxC,UAAM,KAAK,MAAM,MAAM,IAAI,KAAK,WAAW,MAAM,MAAM,OAAO,GAAG,CAAC;AAElE,eAAW,SAAS,WAAW,MAAM,GAAG,CAAC,GAAG;AAC3C,YAAM,WAAW,MAAM,SACpB,GAAG,MAAM,MAAM,GAAG,MAAM,QAAQ,MAAM,MAAM,QAAQ,EAAE,KACtD,MAAM,QAAQ;AAEjB,YAAM,OAAO,MAAM,IAAI,aAAa,QAAQ,CAAC,KAAK,cAAc,QAAQ,CAAC;AACzE,YAAM,KAAK,QAAQ,IAAI,IAAI,MAAM,UAAU,OAAO,IAAI,CAAC,KAAK,MAAM,OAAO,EAAE;AAE3E,UAAI,MAAM,YAAY;AACrB,cAAM,KAAK,MAAM,cAAc,MAAM,UAAU,IAAI,OAAO,GAAG,CAAC;AAAA,MAC/D;AAAA,IACD;AAEA,QAAI,WAAW,SAAS,GAAG;AAC1B,YAAM,KAAK,MAAM,gBAAgB,WAAW,SAAS,CAAC,SAAS,OAAO,GAAG,CAAC;AAAA,IAC3E;AAAA,EACD;AAEA,MAAI,SAAS,OAAO,SAAS,OAAO;AACnC,UAAM,KAAK,MAAM,cAAc,OAAO,SAAS,KAAK,uBAAuB,OAAO,GAAG,CAAC;AAAA,EACvF;AAEA,SAAO;AACR;;;ACvQA,SAAS,YAAiC,KAA8B;AACvE,QAAM,MAAM,CAAC;AACb,aAAW,CAAC,KAAK,KAAK,KAAK,KAAK;AAC/B,QAAI,GAAG,IAAI;AAAA,EACZ;AACA,SAAO;AACR;AAKA,SAAS,gBAAgB,QAA+C;AACvE,SAAO;AAAA,IACN,MAAM,OAAO;AAAA,IACb,QAAQ,OAAO;AAAA,IACf,OAAO,OAAO;AAAA,IACd,iBAAiB,OAAO;AAAA,IACxB,QAAQ,YAAY,OAAO,MAAM;AAAA,IACjC,eAAe,YAAY,OAAO,aAAa;AAAA,IAC/C,WAAW,OAAO;AAAA,IAClB,YAAY,OAAO;AAAA,EACpB;AACD;AAKA,SAAS,eAAe,OAA6C;AACpE,QAAM,WAAoC,CAAC;AAC3C,aAAW,CAAC,MAAM,MAAM,KAAK,MAAM,UAAU;AAC5C,aAAS,IAAI,IAAI,gBAAgB,MAAM;AAAA,EACxC;AAEA,SAAO;AAAA,IACN;AAAA,IACA,OAAO,MAAM;AAAA,EACd;AACD;AAKO,SAAS,WAAW,QAAwB,SAAS,MAAc;AACzE,QAAM,SAAS;AAAA,IACd,SAAS,OAAO;AAAA,IAChB,SAAS;AAAA,MACR,UAAU,OAAO,WAAW;AAAA,MAC5B,QAAQ,OAAO,WAAW;AAAA,MAC1B,eAAe,OAAO,WAAW;AAAA,MACjC,QAAQ,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO,EAAE;AAAA,MAC5D,UAAU,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS,EAAE;AAAA,MAChE,MAAM,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,MAAM,EAAE;AAAA,IAC1D;AAAA,IACA,UAAU,OAAO,SAAS,IAAI,eAAe;AAAA,IAC7C,OAAO,eAAe,OAAO,KAAK;AAAA,IAClC,QAAQ,OAAO;AAAA,IACf,YAAY,OAAO;AAAA,IACnB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,EACnC;AAEA,SAAO,SAAS,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,KAAK,UAAU,MAAM;AACxE;;;AC7DO,SAAS,eAAe,QAAgC;AAC9D,QAAM,QAAkB,CAAC;AAGzB,QAAM,KAAK,8BAA8B;AACzC,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,eAAc,oBAAI,KAAK,GAAE,YAAY,CAAC,EAAE;AACnD,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,aAAa;AACxB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,oBAAoB;AAC/B,QAAM,KAAK,oBAAoB;AAC/B,QAAM,KAAK,gBAAgB,OAAO,WAAW,aAAa,IAAI;AAC9D,QAAM,KAAK,oBAAoB,OAAO,WAAW,WAAW,IAAI;AAChE,QAAM,KAAK,2BAA2B,OAAO,WAAW,kBAAkB,IAAI;AAC9E,QAAM;AAAA,IACL,yBAAyB,OAAO,WAAW,uBAAuB,QAAQ,CAAC,CAAC;AAAA,EAC7E;AACA,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,6BAA6B;AACxC,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,kBAAkB;AAC7B,QAAM,KAAK,kBAAkB;AAC7B,QAAM,cAAc,OAAO,QAAQ,OAAO,WAAW,YAAY,EAAE;AAAA,IAClE,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,EACrB;AACA,aAAW,CAAC,MAAM,KAAK,KAAK,aAAa;AACxC,UAAM,KAAK,KAAK,IAAI,MAAM,KAAK,IAAI;AAAA,EACpC;AACA,QAAM,KAAK,EAAE;AAGb,MAAI,OAAO,WAAW,qBAAqB,GAAG;AAC7C,UAAM,KAAK,oCAAoC;AAC/C,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,kBAAkB;AAC7B,UAAM,KAAK,kBAAkB;AAC7B,UAAM,aAAa,OAAO,QAAQ,OAAO,WAAW,mBAAmB,EAAE;AAAA,MACxE,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC;AAAA,IACrB;AACA,eAAW,CAAC,MAAM,KAAK,KAAK,YAAY;AACvC,YAAM,KAAK,KAAK,IAAI,MAAM,KAAK,IAAI;AAAA,IACpC;AACA,UAAM,KAAK,EAAE;AAAA,EACd;AAGA,QAAM,KAAK,gCAAgC;AAC3C,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,YAAY;AACvB,QAAM,KAAK,GAAG,yBAAyB,MAAM,CAAC;AAC9C,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,aAAa;AACxB,QAAM,KAAK,EAAE;AAEb,aAAW,UAAU,OAAO,UAAU;AACrC,UAAM,KAAK,GAAG,oBAAoB,MAAM,CAAC;AAAA,EAC1C;AAGA,QAAM,SAAS,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO;AACjE,QAAM,WAAW,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS;AACrE,QAAM,QAAQ,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,MAAM;AAE/D,MAAI,OAAO,OAAO,SAAS,GAAG;AAC7B,UAAM,KAAK,oBAAoB;AAC/B,UAAM,KAAK,EAAE;AAEb,QAAI,OAAO,SAAS,GAAG;AACtB,YAAM,KAAK,YAAY;AACvB,YAAM,KAAK,EAAE;AACb,iBAAW,SAAS,QAAQ;AAC3B,cAAM,WAAW,MAAM,SACpB,KAAK,MAAM,MAAM,GAAG,MAAM,QAAQ,MAAM,MAAM,QAAQ,EAAE,OACxD,MAAM,QAAQ;AACjB,cAAM,KAAK,MAAM,MAAM,IAAI,KAAK,QAAQ,KAAK,MAAM,OAAO,EAAE;AAC5D,YAAI,MAAM,YAAY;AACrB,gBAAM,KAAK,mBAAmB,MAAM,UAAU,EAAE;AAAA,QACjD;AAAA,MACD;AACA,YAAM,KAAK,EAAE;AAAA,IACd;AAEA,QAAI,SAAS,SAAS,GAAG;AACxB,YAAM,KAAK,cAAc;AACzB,YAAM,KAAK,EAAE;AACb,iBAAW,SAAS,UAAU;AAC7B,cAAM,WAAW,MAAM,SACpB,KAAK,MAAM,MAAM,GAAG,MAAM,QAAQ,MAAM,MAAM,QAAQ,EAAE,OACxD,MAAM,QAAQ;AACjB,cAAM,KAAK,MAAM,MAAM,IAAI,KAAK,QAAQ,KAAK,MAAM,OAAO,EAAE;AAC5D,YAAI,MAAM,YAAY;AACrB,gBAAM,KAAK,mBAAmB,MAAM,UAAU,EAAE;AAAA,QACjD;AAAA,MACD;AACA,YAAM,KAAK,EAAE;AAAA,IACd;AAEA,QAAI,MAAM,SAAS,GAAG;AACrB,YAAM,KAAK,UAAU;AACrB,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,WAAW;AACtB,YAAM,KAAK,uCAAuC;AAClD,YAAM,KAAK,EAAE;AACb,iBAAW,SAAS,OAAO;AAC1B,cAAM,WAAW,MAAM,SACpB,KAAK,MAAM,MAAM,GAAG,MAAM,QAAQ,MAAM,MAAM,QAAQ,EAAE,OACxD,MAAM,QAAQ;AACjB,cAAM,KAAK,MAAM,MAAM,IAAI,KAAK,QAAQ,KAAK,MAAM,OAAO,EAAE;AAAA,MAC7D;AACA,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,YAAY;AACvB,YAAM,KAAK,EAAE;AAAA,IACd;AAAA,EACD;AAEA,SAAO,MAAM,KAAK,IAAI;AACvB;AAKA,SAAS,oBAAoB,QAAgC;AAC5D,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,OAAO,OAAO,IAAI,EAAE;AAC/B,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,gBAAgB,OAAO,KAAK,IAAI;AAC3C,QAAM,KAAK,eAAe,OAAO,MAAM,EAAE;AACzC,MAAI,OAAO,UAAU,SAAS,GAAG;AAChC,UAAM,KAAK,kBAAkB,OAAO,UAAU,KAAK,IAAI,CAAC,EAAE;AAAA,EAC3D;AACA,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,aAAa;AACxB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,6DAA6D;AACxE,QAAM,KAAK,6DAA6D;AAExE,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ;AAC1C,UAAM,WAAW,MAAM,WAAW,QAAQ;AAC1C,UAAM,WAAW,MAAM,WAAW,QAAQ;AAC1C,UAAM,QAAQ,MAAM,QAAQ,QAAQ,MAAM,SAAS,WAAW;AAC9D,UAAM,KAAK,MAAM,aAAa,GAAG,MAAM,WAAW,KAAK,IAAI,MAAM,WAAW,MAAM,KAAK;AACvF,UAAM,KAAK,KAAK,IAAI,MAAM,MAAM,IAAI,MAAM,QAAQ,MAAM,QAAQ,MAAM,KAAK,MAAM,EAAE,IAAI;AAAA,EACxF;AACA,QAAM,KAAK,EAAE;AAGb,MAAI,OAAO,cAAc,OAAO,GAAG;AAClC,UAAM,KAAK,oBAAoB;AAC/B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,wCAAwC;AACnD,UAAM,KAAK,wCAAwC;AAEnD,eAAW,CAAC,MAAM,GAAG,KAAK,OAAO,eAAe;AAC/C,YAAM,KAAK,KAAK,IAAI,MAAM,IAAI,IAAI,MAAM,IAAI,MAAM,MAAM,IAAI,UAAU,IAAI;AAAA,IAC3E;AACA,UAAM,KAAK,EAAE;AAAA,EACd;AAEA,SAAO;AACR;AAKA,SAAS,yBAAyB,QAAkC;AACnE,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,WAAW;AAGtB,aAAW,UAAU,OAAO,UAAU;AACrC,UAAM,aAAa,OAAO,KAAK,YAAY;AAC3C,UAAM,KAAK,OAAO,UAAU,IAAI;AAGhC,UAAM,YAAY,MAAM,KAAK,OAAO,OAAO,QAAQ,CAAC,EAClD;AAAA,MACA,CAAC,CAAC,MAAM,KAAK,MACZ,MAAM,cAAc,MAAM,UAAU,MAAM,SAAS,SAAS,QAAQ,SAAS;AAAA,IAC/E,EACC,MAAM,GAAG,CAAC;AAEZ,eAAW,CAAC,MAAM,KAAK,KAAK,WAAW;AACtC,YAAM,UAAU,MAAM;AACtB,YAAM,KAAK,SAAS,OAAO,OAAO;AAClC,YAAM,KAAK,MAAM,aAAa,OAAO;AACrC,YAAM,SAAS,MAAM,KAAK,KAAK,EAAE,GAAG,EAAE,MAAM;AAC5C,YAAM,KAAK,WAAW,OAAO,IAAI,IAAI,GAAG,MAAM,EAAE;AAAA,IACjD;AAEA,QAAI,OAAO,OAAO,OAAO,UAAU,QAAQ;AAC1C,YAAM,KAAK,6BAA6B;AAAA,IACzC;AAEA,UAAM,KAAK,OAAO;AAAA,EACnB;AAGA,aAAW,QAAQ,OAAO,MAAM,OAAO;AACtC,UAAM,OAAO,KAAK,KAAK,YAAY;AACnC,UAAM,KAAK,KAAK,GAAG,YAAY;AAC/B,UAAM,oBAAoB,qBAAqB,KAAK,WAAW;AAC/D,UAAM,QAAQ,KAAK,aAAa;AAEhC,UAAM,KAAK,OAAO,IAAI,IAAI,iBAAiB,IAAI,EAAE,OAAO,KAAK,GAAG;AAAA,EACjE;AAEA,SAAO;AACR;AAKA,SAAS,qBAAqB,aAA6B;AAC1D,UAAQ,aAAa;AAAA,IACpB,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO;AAAA,IACR;AACC,aAAO;AAAA,EACT;AACD;AAKO,SAAS,mBAAmB,QAAgC;AAClE,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,YAAY;AACvB,QAAM,KAAK,UAAU;AAGrB,QAAM,KAAK,iDAAiD;AAG5D,aAAW,UAAU,OAAO,UAAU;AACrC,UAAM,KAAK,OAAO,OAAO,IAAI,KAAK,OAAO,IAAI,OAAO,OAAO,OAAO,IAAI,YAAY;AAAA,EACnF;AAGA,aAAW,QAAQ,OAAO,MAAM,OAAO;AACtC,UAAM,QAAQ,KAAK,gBAAgB,SAAS;AAC5C,UAAM,KAAK,OAAO,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,aAAa,IAAI,KAAK,KAAK,EAAE,EAAE;AAAA,EAC7E;AAGA,QAAM,aAAa,OAAO,SAAS,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG;AAC9D,MAAI,YAAY;AACf,UAAM,KAAK,aAAa,UAAU,SAAS;AAAA,EAC5C;AAEA,QAAM,KAAK,KAAK;AAEhB,SAAO,MAAM,KAAK,IAAI;AACvB;;;AC5QO,IAAM,kBAAkB,cAAc;AAAA,EAC5C,MAAM;AAAA,EACN,SAAS,CAAC,MAAM;AAAA,EAChB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,4BAA4B;AAAA,IAC3B;AAAA,IACA;AAAA,EACD;AAAA,EACA,yBAAyB;AAAA,IACxB;AAAA,IACA;AAAA,EACD;AAAA,EACA,aACC;AACF,CAAC;;;ACjBM,IAAM,cAAc,cAAc;AAAA,EACxC,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,4BAA4B;AAAA,IAC3B;AAAA,EACD;AAAA,EACA,yBAAyB;AAAA,IACxB;AAAA,EACD;AAAA,EACA,aAAa;AACd,CAAC;;;ACbM,IAAM,mBAAmB,cAAc;AAAA,EAC7C,MAAM;AAAA,EACN,SAAS,CAAC,MAAM;AAAA,EAChB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,4BAA4B;AAAA,IAC3B;AAAA,IACA;AAAA,EACD;AAAA,EACA,yBAAyB;AAAA,IACxB;AAAA,IACA;AAAA,EACD;AAAA,EACA,aAAa;AACd,CAAC;;;ACjBM,IAAM,kBAAkB,cAAc;AAAA,EAC5C,MAAM;AAAA,EACN,SAAS,CAAC,MAAM;AAAA,EAChB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,4BAA4B;AAAA,IAC3B;AAAA,IACA;AAAA,EACD;AAAA,EACA,yBAAyB;AAAA,IACxB;AAAA,IACA;AAAA,EACD;AAAA,EACA,aACC;AACF,CAAC;;;ACdM,IAAM,gBAAgB,cAAc;AAAA,EAC1C,MAAM;AAAA,EACN,SAAS,CAAC,MAAM;AAAA,EAChB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,4BAA4B;AAAA,IAC3B;AAAA,IACA;AAAA,EACD;AAAA,EACA,yBAAyB;AAAA,IACxB;AAAA,IACA;AAAA,EACD;AAAA,EACA,kBAAkB,CAAC,sBAAsB;AAAA,EACzC,aAAa;AACd,CAAC;;;AChBD,uBAAuB,WAAW;AAClC,uBAAuB,aAAa;AACpC,uBAAuB,eAAe;AACtC,uBAAuB,gBAAgB;AACvC,uBAAuB,eAAe;;;ACsBtC,eAAsB,cACrB,aACA,wBAC0B;AAC1B,QAAM,OACL,OAAO,2BAA2B,WAC/B,EAAE,kBAAkB,uBAAuB,IAC3C,0BAA0B,CAAC;AAC/B,QAAM,mBAAmB,KAAK;AAG9B,QAAM,EAAE,UAAU,QAAQ,WAAW,IAAI,aAAa,WAAW;AAGjE,QAAM,EAAE,eAAe,yBAAyB,QAAQ,cAAc,IACrE,mBACG,kBAAkB,gBAAgB,IAClC,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,EAAE;AAGpC,QAAM,gBAAgB,kBAAkB,QAAQ;AAGhD,QAAM,mBAAmB;AAAA,IACxB;AAAA,IACA;AAAA,EACD;AAGA,QAAM,QAAQ,iBAAiB,UAAU,uBAAuB;AAGhE,QAAM,oBAAoB,iBAAiB,KAAK;AAQhD,QAAM,gBAAgB,SAAS,QAAQ,CAAC,MAAM,2BAA2B,CAAC,CAAC;AAC3E,QAAM,uBAAuB,uBAAuB;AAAA,IACnD;AAAA,IACA,cAAc,KAAK;AAAA,EACpB,CAAC;AAGD,QAAM,aAAa,kBAAkB,KAAK;AAG1C,QAAM,YAAY;AAAA,IACjB,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACJ;AAGA,QAAM,YAAY,UAAU,KAAK,CAAC,MAAM,EAAE,aAAa,OAAO;AAE9D,SAAO;AAAA,IACN,SAAS,CAAC;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,EACD;AACD;AAMO,SAAS,iBAAiB,aAG/B;AACD,QAAM,EAAE,UAAU,OAAO,IAAI,aAAa,WAAW;AACrD,QAAM,SAAS,OACb,OAAO,CAAC,MAAM,EAAE,aAAa,OAAO,EACpC,IAAI,CAAC,MAAM,EAAE,OAAO;AAEtB,SAAO;AAAA,IACN,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,EACD;AACD;","names":["z","z","path","path"]}
1
+ {"version":3,"sources":["../../src/parser/load-entities.ts","../../src/utils/yaml-loader.ts","../../src/schema/entity-definition.schema.ts","../../src/schema/event-definition.schema.ts","../../src/schema/relationship-definition.schema.ts","../../src/analyzer/graph-builder.ts","../../src/behaviors/external-id-tracking.ts","../../src/behaviors/soft-delete.ts","../../src/behaviors/timestamps.ts","../../src/behaviors/user-tracking.ts","../../src/behaviors/index.ts","../../src/analyzer/consistency-checker.ts","../../src/analyzer/statistics.ts","../../src/patterns/registry.ts","../../src/patterns/pattern-definition.ts","../../src/patterns/validate-composition.ts","../../src/formatters/console-formatter.ts","../../src/formatters/json-formatter.ts","../../src/formatters/markdown-formatter.ts","../../src/patterns/library/activity.pattern.ts","../../src/patterns/library/base.pattern.ts","../../src/patterns/library/knowledge.pattern.ts","../../src/patterns/library/metadata.pattern.ts","../../src/patterns/library/synced.pattern.ts","../../src/patterns/library/index.ts","../../src/index.ts"],"sourcesContent":["/**\n * Entity Loader\n *\n * Loads and parses all YAML entity files from a directory.\n * Reuses existing yaml-loader and entity-definition schema from codegen.\n */\n\nimport { readdirSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport {\n\tloadEntityFromYaml,\n\tloadRelationshipFromYaml,\n\ttype LoadResult,\n\ttype LoadError,\n\ttype RelationshipLoadResult,\n\ttype RelationshipLoadError,\n} from '../utils/yaml-loader';\nimport type {\n\tParsedEntity,\n\tParsedEvent,\n\tParsedField,\n\tParsedProviderSync,\n\tParsedQuery,\n\tParsedRelationship,\n\tParsedRelationshipDefinition,\n\tParsedSync,\n\tParsedTypeDirection,\n\tAnalysisIssue,\n} from '../analyzer/types';\nimport {\n\tderiveRelationshipFKColumns,\n\tderiveTableName,\n\tderiveUniqueConstraint,\n\tcollectTypeNames,\n\ttype RelationshipDefinition,\n\ttype RelationshipTypes,\n} from '../schema/relationship-definition.schema';\n\nexport interface LoadEntitiesResult {\n\tentities: ParsedEntity[];\n\tissues: AnalysisIssue[];\n}\n\n/**\n * Transform a loaded entity definition into a ParsedEntity\n */\nfunction transformToEntity(result: LoadResult): ParsedEntity {\n\tconst { definition, filePath } = result;\n\n\t// Search queries use a different shape (name/filters/search/paginate) and\n\t// are consumed directly by the codegen templates, not by the analyzer.\n\t// Narrow to the by-column variant here for ParsedQuery mapping.\n\tconst queries: ParsedQuery[] | undefined = definition.queries\n\t\t?.filter((q): q is Extract<typeof q, { by: unknown }> => 'by' in q)\n\t\t.map((q) => ({\n\t\t\tby: q.by,\n\t\t\tunique: q.unique,\n\t\t\tselect: q.select,\n\t\t\torder: q.order,\n\t\t\tlimit: q.limit,\n\t\t\tvia: q.via,\n\t\t}));\n\n\tconst entity: ParsedEntity = {\n\t\tname: definition.entity.name,\n\t\tplural: definition.entity.plural,\n\t\ttable: definition.entity.table,\n\t\tpattern: definition.entity.pattern,\n\t\tpatterns: definition.entity.patterns,\n\t\tpatternConfig: definition.entity.config,\n\t\tscopeable: definition.entity.scopeable ?? false,\n\t\tfolderStructure: definition.entity.folder_structure ?? 'nested',\n\t\tfields: new Map(),\n\t\trelationships: new Map(),\n\t\tbehaviors: definition.behaviors.map((b) => (typeof b === 'string' ? b : b.name)),\n\t\tqueries,\n\t\tsourcePath: filePath,\n\t};\n\n\t// Parse fields\n\tfor (const [name, fieldDef] of Object.entries(definition.fields)) {\n\t\tconst field: ParsedField = {\n\t\t\tname,\n\t\t\ttype: fieldDef.type,\n\t\t\trequired: fieldDef.required ?? false,\n\t\t\tnullable: fieldDef.nullable ?? false,\n\t\t\tunique: fieldDef.unique ?? false,\n\t\t\tindex: fieldDef.index ?? false,\n\t\t\tforeignKey: fieldDef.foreign_key ? parseForeignKey(fieldDef.foreign_key) : undefined,\n\t\t\tchoices: fieldDef.choices,\n\t\t\tconstraints: {\n\t\t\t\tminLength: fieldDef.min_length,\n\t\t\t\tmaxLength: fieldDef.max_length,\n\t\t\t\tmin: fieldDef.min,\n\t\t\t\tmax: fieldDef.max,\n\t\t\t},\n\t\t\tui: {\n\t\t\t\tlabel: fieldDef.ui_label,\n\t\t\t\ttype: fieldDef.ui_type,\n\t\t\t\timportance: fieldDef.ui_importance,\n\t\t\t\tgroup: fieldDef.ui_group,\n\t\t\t\tsortable: fieldDef.ui_sortable,\n\t\t\t\tfilterable: fieldDef.ui_filterable,\n\t\t\t\tvisible: fieldDef.ui_visible,\n\t\t\t},\n\t\t};\n\t\tentity.fields.set(name, field);\n\t}\n\n\t// Parse relationships\n\tif (definition.relationships) {\n\t\tfor (const [name, relDef] of Object.entries(definition.relationships)) {\n\t\t\tconst relationship: ParsedRelationship = {\n\t\t\t\tname,\n\t\t\t\ttype: relDef.type,\n\t\t\t\ttarget: relDef.target,\n\t\t\t\tforeignKey: relDef.foreign_key,\n\t\t\t\tinverse: relDef.inverse,\n\t\t\t\tthrough: relDef.through,\n\t\t\t\tresolved: false,\n\t\t\t};\n\t\t\tentity.relationships.set(name, relationship);\n\t\t}\n\t}\n\n\t// Parse sync configuration\n\tif (definition.sync) {\n\t\tconst syncDef = definition.sync;\n\t\tconst parsedSync: ParsedSync = {\n\t\t\telectric: syncDef.electric ?? false,\n\t\t};\n\n\t\tif (syncDef.providers) {\n\t\t\tparsedSync.providers = {};\n\t\t\tfor (const [providerName, providerDef] of Object.entries(syncDef.providers)) {\n\t\t\t\tconst parsedProvider: ParsedProviderSync = {\n\t\t\t\t\tremoteEntity: providerDef.remote_entity,\n\t\t\t\t\tdirection: providerDef.direction,\n\t\t\t\t\tcdc: providerDef.cdc ?? false,\n\t\t\t\t};\n\t\t\t\tif (providerDef.field_mapping) {\n\t\t\t\t\tparsedProvider.fieldMapping = providerDef.field_mapping;\n\t\t\t\t}\n\t\t\t\tif (providerDef.read_only_fields) {\n\t\t\t\t\tparsedProvider.readOnlyFields = providerDef.read_only_fields;\n\t\t\t\t}\n\t\t\t\tparsedSync.providers[providerName] = parsedProvider;\n\t\t\t}\n\t\t}\n\n\t\tentity.sync = parsedSync;\n\t}\n\n\t// Parse events\n\tif (definition.events) {\n\t\tentity.events = definition.events.map((ev): ParsedEvent => ({\n\t\t\tname: ev.name,\n\t\t\tqueue: ev.queue,\n\t\t\tbody: ev.body,\n\t\t\tgenerateHandler: ev.generate_handler,\n\t\t}));\n\t}\n\n\t// Parse emits (EVT-7). Preserve `undefined` vs `[]` distinction — the\n\t// validator treats absence as a warning and explicit empty as opt-out.\n\tif (definition.emits !== undefined) {\n\t\tentity.emits = definition.emits;\n\t}\n\n\treturn entity;\n}\n\n/**\n * Parse a foreign key string (e.g., \"accounts.id\") into table and column\n */\nfunction parseForeignKey(fk: string): { table: string; column: string } {\n\tconst [table, column] = fk.split('.');\n\treturn { table, column: column ?? 'id' };\n}\n\n/**\n * Convert a load error to an analysis issue\n */\nfunction loadErrorToIssue(error: LoadError): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tissues.push({\n\t\tseverity: 'error',\n\t\ttype: 'parse_error',\n\t\tmessage: error.error,\n\t\tpath: error.filePath,\n\t});\n\n\tif (error.details) {\n\t\tfor (const detail of error.details) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'schema_error',\n\t\t\t\tmessage: detail,\n\t\t\t\tpath: error.filePath,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Load all entity YAML files from a directory\n */\nexport function loadEntities(entitiesDir: string): LoadEntitiesResult {\n\tconst entities: ParsedEntity[] = [];\n\tconst issues: AnalysisIssue[] = [];\n\n\tconst resolvedDir = resolve(entitiesDir);\n\n\t// Get all YAML files\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(resolvedDir)\n\t\t\t.filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'))\n\t\t\t.map((f) => join(resolvedDir, f));\n\t} catch (err) {\n\t\tissues.push({\n\t\t\tseverity: 'error',\n\t\t\ttype: 'parse_error',\n\t\t\tmessage: `Failed to read directory: ${resolvedDir}`,\n\t\t\tpath: resolvedDir,\n\t\t});\n\t\treturn { entities, issues };\n\t}\n\n\tif (files.length === 0) {\n\t\tissues.push({\n\t\t\tseverity: 'warning',\n\t\t\ttype: 'no_files',\n\t\t\tmessage: `No YAML files found in directory: ${resolvedDir}`,\n\t\t\tpath: resolvedDir,\n\t\t});\n\t\treturn { entities, issues };\n\t}\n\n\t// Load each file\n\tfor (const filePath of files) {\n\t\tconst result = loadEntityFromYaml(filePath);\n\n\t\tif (result.success) {\n\t\t\tentities.push(transformToEntity(result));\n\t\t} else {\n\t\t\tissues.push(...loadErrorToIssue(result));\n\t\t}\n\t}\n\n\treturn { entities, issues };\n}\n\n/**\n * Resolve cross-entity references\n */\nexport function resolveReferences(entities: ParsedEntity[]): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst entityMap = new Map<string, ParsedEntity>();\n\n\t// Build entity map by name\n\tfor (const entity of entities) {\n\t\tif (entityMap.has(entity.name)) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'duplicate_entity',\n\t\t\t\tentity: entity.name,\n\t\t\t\tmessage: `Duplicate entity name: ${entity.name}`,\n\t\t\t\tpath: entity.sourcePath,\n\t\t\t});\n\t\t}\n\t\tentityMap.set(entity.name, entity);\n\t}\n\n\t// Resolve relationships\n\tfor (const entity of entities) {\n\t\tfor (const [relName, rel] of entity.relationships) {\n\t\t\tconst targetEntity = entityMap.get(rel.target);\n\t\t\tif (targetEntity) {\n\t\t\t\trel.resolved = true;\n\t\t\t} else {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'missing_target',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: relName,\n\t\t\t\t\tmessage: `Relationship '${relName}' references unknown entity '${rel.target}'`,\n\t\t\t\t\tpath: entity.sourcePath,\n\t\t\t\t\tsuggestion: `Define entity '${rel.target}' or fix the target name`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Check foreign key references\n\t\tfor (const [fieldName, field] of entity.fields) {\n\t\t\tif (field.foreignKey) {\n\t\t\t\tconst targetTable = field.foreignKey.table;\n\t\t\t\tconst targetEntity = Array.from(entityMap.values()).find(\n\t\t\t\t\t(e) => e.table === targetTable\n\t\t\t\t);\n\t\t\t\tif (!targetEntity) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\t\ttype: 'missing_fk_target',\n\t\t\t\t\t\tentity: entity.name,\n\t\t\t\t\t\tfield: fieldName,\n\t\t\t\t\t\tmessage: `Foreign key references unknown table '${targetTable}'`,\n\t\t\t\t\t\tpath: entity.sourcePath,\n\t\t\t\t\t\tsuggestion: `Define entity with table '${targetTable}' or fix the foreign_key reference`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n// ============================================================================\n// Relationship Loading\n// ============================================================================\n\nexport interface LoadRelationshipsResult {\n\trelationships: ParsedRelationshipDefinition[];\n\tissues: AnalysisIssue[];\n}\n\n/**\n * Transform a loaded relationship definition into a ParsedRelationshipDefinition.\n *\n * This resolves all auto-generated fields: FK columns, type directions,\n * temporal/sourced fields, unique constraints.\n */\nfunction transformToRelationshipDefinition(\n\tresult: RelationshipLoadResult,\n): ParsedRelationshipDefinition {\n\tconst { definition, filePath } = result;\n\tconst config = definition.relationship;\n\n\tconst { fromColumn, toColumn } = deriveRelationshipFKColumns(config);\n\tconst table = deriveTableName(config);\n\tconst uniqueOn = deriveUniqueConstraint(config);\n\n\t// Resolve type directions\n\tconst types = resolveTypeDirections(config.types);\n\n\t// Parse custom fields\n\tconst fields = new Map<string, ParsedField>();\n\tif (definition.fields) {\n\t\tfor (const [name, fieldDef] of Object.entries(definition.fields)) {\n\t\t\tconst field: ParsedField = {\n\t\t\t\tname,\n\t\t\t\ttype: fieldDef.type,\n\t\t\t\trequired: fieldDef.required ?? false,\n\t\t\t\tnullable: fieldDef.nullable ?? false,\n\t\t\t\tunique: fieldDef.unique ?? false,\n\t\t\t\tindex: fieldDef.index ?? false,\n\t\t\t\tforeignKey: fieldDef.foreign_key\n\t\t\t\t\t? parseForeignKey(fieldDef.foreign_key)\n\t\t\t\t\t: undefined,\n\t\t\t\tchoices: fieldDef.choices,\n\t\t\t\tconstraints: {\n\t\t\t\t\tminLength: fieldDef.min_length,\n\t\t\t\t\tmaxLength: fieldDef.max_length,\n\t\t\t\t\tmin: fieldDef.min,\n\t\t\t\t\tmax: fieldDef.max,\n\t\t\t\t},\n\t\t\t\tui: {\n\t\t\t\t\tlabel: fieldDef.ui_label,\n\t\t\t\t\ttype: fieldDef.ui_type,\n\t\t\t\t\timportance: fieldDef.ui_importance,\n\t\t\t\t\tgroup: fieldDef.ui_group,\n\t\t\t\t\tsortable: fieldDef.ui_sortable,\n\t\t\t\t\tfilterable: fieldDef.ui_filterable,\n\t\t\t\t\tvisible: fieldDef.ui_visible,\n\t\t\t\t},\n\t\t\t};\n\t\t\tfields.set(name, field);\n\t\t}\n\t}\n\n\t// Parse queries\n\t// Relationship queries here: same filtering rationale as entity queries.\n\tconst queries: ParsedQuery[] | undefined = definition.queries\n\t\t?.filter((q): q is Extract<typeof q, { by: unknown }> => 'by' in q)\n\t\t.map((q) => ({\n\t\t\tby: q.by,\n\t\t\tunique: q.unique,\n\t\t\tselect: q.select,\n\t\t\torder: q.order,\n\t\t\tlimit: q.limit,\n\t\t}));\n\n\treturn {\n\t\tname: config.name,\n\t\ttable,\n\t\tfrom: config.from,\n\t\tto: config.to,\n\t\tselfReferential: config.from === config.to,\n\t\tfromColumn,\n\t\ttoColumn,\n\t\ttypes,\n\t\thasTypes: types.length > 0,\n\t\ttemporal: config.temporal,\n\t\tsourced: config.sourced,\n\t\tonDeleteFrom: config.on_delete_from ?? 'restrict',\n\t\tonDeleteTo: config.on_delete_to ?? 'restrict',\n\t\tuniqueOn,\n\t\tfields,\n\t\tqueries,\n\t\tsourcePath: filePath,\n\t};\n}\n\n/**\n * Resolve type directions from the YAML types: block.\n *\n * Simple list → all directed, no inverses.\n * Object map → each type has explicit direction metadata.\n */\nfunction resolveTypeDirections(\n\ttypes: RelationshipTypes | undefined,\n): ParsedTypeDirection[] {\n\tif (!types) return [];\n\n\tif (Array.isArray(types)) {\n\t\t// Simple list: all directed from→to\n\t\treturn types.map((name) => ({\n\t\t\tname,\n\t\t\tbidirectional: false,\n\t\t\tdirected: true,\n\t\t}));\n\t}\n\n\t// Object map: resolve each type's direction\n\treturn Object.entries(types).map(([name, dir]) => {\n\t\tconst direction = dir as { inverse?: string; bidirectional?: boolean; directed?: boolean };\n\t\treturn {\n\t\t\tname,\n\t\t\tinverse: direction.inverse,\n\t\t\tbidirectional: direction.bidirectional ?? false,\n\t\t\tdirected: direction.directed ?? (!direction.bidirectional && !direction.inverse),\n\t\t};\n\t});\n}\n\n/**\n * Load all relationship YAML files from a directory\n */\nexport function loadRelationships(\n\trelationshipsDir: string,\n): LoadRelationshipsResult {\n\tconst relationships: ParsedRelationshipDefinition[] = [];\n\tconst issues: AnalysisIssue[] = [];\n\n\tconst resolvedDir = resolve(relationshipsDir);\n\n\tlet files: string[];\n\ttry {\n\t\tfiles = readdirSync(resolvedDir)\n\t\t\t.filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'))\n\t\t\t.map((f) => join(resolvedDir, f));\n\t} catch {\n\t\t// Directory doesn't exist — not an error, relationships are optional\n\t\treturn { relationships, issues };\n\t}\n\n\tif (files.length === 0) {\n\t\treturn { relationships, issues };\n\t}\n\n\tfor (const filePath of files) {\n\t\tconst result = loadRelationshipFromYaml(filePath);\n\n\t\tif (result.success) {\n\t\t\trelationships.push(transformToRelationshipDefinition(result));\n\t\t} else {\n\t\t\tissues.push(...loadErrorToIssue(result as unknown as LoadError));\n\t\t}\n\t}\n\n\treturn { relationships, issues };\n}\n\n/**\n * Resolve cross-references between relationship definitions and entities.\n * Validates that from/to entities exist.\n */\nexport function resolveRelationshipReferences(\n\trelationshipDefs: ParsedRelationshipDefinition[],\n\tentities: ParsedEntity[],\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst entityNames = new Set(entities.map((e) => e.name));\n\n\tfor (const relDef of relationshipDefs) {\n\t\tif (!entityNames.has(relDef.from)) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'missing_relationship_endpoint',\n\t\t\t\tentity: relDef.name,\n\t\t\t\tmessage: `Relationship '${relDef.name}' references unknown 'from' entity '${relDef.from}'`,\n\t\t\t\tpath: relDef.sourcePath,\n\t\t\t\tsuggestion: `Define entity '${relDef.from}' or fix the 'from' value`,\n\t\t\t});\n\t\t}\n\n\t\tif (!entityNames.has(relDef.to)) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'missing_relationship_endpoint',\n\t\t\t\tentity: relDef.name,\n\t\t\t\tmessage: `Relationship '${relDef.name}' references unknown 'to' entity '${relDef.to}'`,\n\t\t\t\tpath: relDef.sourcePath,\n\t\t\t\tsuggestion: `Define entity '${relDef.to}' or fix the 'to' value`,\n\t\t\t});\n\t\t}\n\n\t\t// Check for duplicate relationship names\n\t\tconst dupes = relationshipDefs.filter((r) => r.name === relDef.name);\n\t\tif (dupes.length > 1) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'duplicate_relationship',\n\t\t\t\tentity: relDef.name,\n\t\t\t\tmessage: `Duplicate relationship name: ${relDef.name}`,\n\t\t\t\tpath: relDef.sourcePath,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\nexport { loadEntityFromYaml } from '../utils/yaml-loader';\nexport { loadRelationshipFromYaml } from '../utils/yaml-loader';\n","import { readFileSync, existsSync } from 'node:fs';\nimport { parse as parseYaml } from 'yaml';\nimport { ZodError } from 'zod';\nimport {\n\ttype EntityDefinition,\n\tEntityDefinitionSchema,\n} from '../schema/entity-definition.schema';\nimport {\n\ttype EventDefinition,\n\tEventDefinitionSchema,\n} from '../schema/event-definition.schema';\nimport {\n\ttype RelationshipDefinition,\n\tRelationshipDefinitionSchema,\n} from '../schema/relationship-definition.schema';\n\nexport interface LoadResult {\n\tsuccess: true;\n\tdefinition: EntityDefinition;\n\tfilePath: string;\n}\n\nexport interface LoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadEntityResult = LoadResult | LoadError;\n\n/**\n * Load and validate an entity definition from a YAML file\n */\nexport function loadEntityFromYaml(filePath: string): LoadEntityResult {\n\t// Check file exists\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\t// Read file\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\t// Parse YAML\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\t// Validate against schema\n\tconst result = EntityDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n/**\n * Format Zod errors into human-readable messages\n */\nfunction formatZodErrors(error: ZodError): string[] {\n\treturn error.errors.map((err) => {\n\t\tconst path = err.path.join('.');\n\t\tconst location = path ? `at '${path}'` : 'at root';\n\t\treturn `${err.message} ${location}`;\n\t});\n}\n\n/**\n * Pretty-print a load error for CLI output\n */\nexport function formatLoadError(result: LoadError): string {\n\tconst lines = [`❌ ${result.error}`];\n\tif (result.details && result.details.length > 0) {\n\t\tlines.push('');\n\t\tfor (const detail of result.details) {\n\t\t\tlines.push(` • ${detail}`);\n\t\t}\n\t}\n\treturn lines.join('\\n');\n}\n\n/**\n * Load multiple entity files\n */\nexport function loadEntitiesFromYaml(filePaths: string[]): {\n\tsuccesses: LoadResult[];\n\tfailures: LoadError[];\n} {\n\tconst successes: LoadResult[] = [];\n\tconst failures: LoadError[] = [];\n\n\tfor (const filePath of filePaths) {\n\t\tconst result = loadEntityFromYaml(filePath);\n\t\tif (result.success) {\n\t\t\tsuccesses.push(result);\n\t\t} else {\n\t\t\tfailures.push(result);\n\t\t}\n\t}\n\n\treturn { successes, failures };\n}\n\n// ============================================================================\n// Relationship YAML Loading\n// ============================================================================\n\nexport interface RelationshipLoadResult {\n\tsuccess: true;\n\tdefinition: RelationshipDefinition;\n\tfilePath: string;\n}\n\nexport interface RelationshipLoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadRelationshipResult =\n\t| RelationshipLoadResult\n\t| RelationshipLoadError;\n\n/**\n * Load and validate a relationship definition from a YAML file\n */\nexport function loadRelationshipFromYaml(\n\tfilePath: string,\n): LoadRelationshipResult {\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tconst result = RelationshipDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n/**\n * Load multiple relationship files\n */\nexport function loadRelationshipsFromYaml(filePaths: string[]): {\n\tsuccesses: RelationshipLoadResult[];\n\tfailures: RelationshipLoadError[];\n} {\n\tconst successes: RelationshipLoadResult[] = [];\n\tconst failures: RelationshipLoadError[] = [];\n\n\tfor (const filePath of filePaths) {\n\t\tconst result = loadRelationshipFromYaml(filePath);\n\t\tif (result.success) {\n\t\t\tsuccesses.push(result);\n\t\t} else {\n\t\t\tfailures.push(result);\n\t\t}\n\t}\n\n\treturn { successes, failures };\n}\n\n// ============================================================================\n// Event YAML Loading\n// ============================================================================\n\nexport interface EventLoadResult {\n\tsuccess: true;\n\tdefinition: EventDefinition;\n\tfilePath: string;\n}\n\nexport interface EventLoadError {\n\tsuccess: false;\n\terror: string;\n\tdetails?: string[];\n\tfilePath: string;\n}\n\nexport type LoadEventResult = EventLoadResult | EventLoadError;\n\n/**\n * Load and validate a single event definition from a YAML file.\n *\n * Mirrors {@link loadEntityFromYaml}: existence check → readFileSync →\n * parseYaml → `EventDefinitionSchema.safeParse`. Returns a discriminated\n * result; callers are expected to aggregate into `AnalysisIssue`s rather\n * than throw.\n */\nexport function loadEventFromYaml(filePath: string): LoadEventResult {\n\tif (!existsSync(filePath)) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `File not found: ${filePath}`,\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(filePath, 'utf-8');\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Failed to read file: ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = parseYaml(content);\n\t} catch (err) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Invalid YAML syntax in ${filePath}`,\n\t\t\tdetails: [err instanceof Error ? err.message : String(err)],\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\tconst result = EventDefinitionSchema.safeParse(parsed);\n\tif (!result.success) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: `Validation failed for ${filePath}`,\n\t\t\tdetails: formatZodErrors(result.error),\n\t\t\tfilePath,\n\t\t};\n\t}\n\n\treturn {\n\t\tsuccess: true,\n\t\tdefinition: result.data,\n\t\tfilePath,\n\t};\n}\n\n/**\n * Detect whether a YAML file is an entity or relationship definition.\n * Checks for the top-level discriminator key.\n */\nexport function detectYamlType(\n\tfilePath: string,\n): 'entity' | 'relationship' | 'unknown' {\n\tif (!existsSync(filePath)) return 'unknown';\n\n\ttry {\n\t\tconst content = readFileSync(filePath, 'utf-8');\n\t\tconst parsed = parseYaml(content) as Record<string, unknown>;\n\t\tif (parsed && typeof parsed === 'object') {\n\t\t\tif ('entity' in parsed) return 'entity';\n\t\t\tif ('relationship' in parsed) return 'relationship';\n\t\t}\n\t} catch {\n\t\t// Fall through\n\t}\n\treturn 'unknown';\n}\n","import { z } from \"zod\";\n\n/**\n * Entity Definition Schema\n *\n * Generates backend code:\n * - Domain entity + repository interface\n * - Application DTOs, use-cases, queries\n * - Infrastructure Drizzle schema + repository\n * - Presentation controller\n * - NestJS module wiring\n * - Shared Zod schema in packages/db\n *\n * Generates frontend code:\n * - Entity metadata for automatic admin panels\n * - UI type, importance, grouping for fields\n */\n\n// ============================================================================\n// Field Types\n// ============================================================================\n\nconst FieldTypeSchema = z.enum([\n \"string\",\n \"integer\",\n \"decimal\",\n \"boolean\",\n \"uuid\",\n \"date\",\n \"datetime\",\n \"json\",\n \"entity_ref\", // Polymorphic reference: generates {field}EntityType + {field}EntityId columns\n \"string_array\", // Array of strings: generates text[] column\n \"enum\", // Enum type with choices or choices_from\n]);\n\nexport type FieldType = z.infer<typeof FieldTypeSchema>;\n\n// ============================================================================\n// UI Metadata Types\n// ============================================================================\n\nconst UiTypeSchema = z.enum([\n \"text\",\n \"textarea\",\n \"number\",\n \"money\",\n \"percentage\",\n \"email\",\n \"url\",\n \"date\",\n \"datetime\",\n \"boolean\",\n \"enum\",\n \"reference\",\n \"json\",\n \"badge\",\n \"password\",\n]);\n\nexport type UiType = z.infer<typeof UiTypeSchema>;\n\nconst UiImportanceSchema = z.enum([\"primary\", \"secondary\", \"tertiary\"]);\n\nexport type UiImportance = z.infer<typeof UiImportanceSchema>;\n\n/**\n * UI Metadata Schema - Optional field-level UI properties\n *\n * All properties are optional and will be inferred at generation time\n * if not explicitly specified in the YAML definition.\n */\n// ============================================================================\n// Semantic / Analytics Metadata Types\n// ============================================================================\n\nconst AnalyticsAggregationSchema = z.enum([\n 'sum',\n 'min',\n 'max',\n 'count',\n 'count_distinct',\n 'average',\n 'median',\n 'percentile',\n 'sum_boolean',\n]);\n\nconst AnalyticsDimensionTypeSchema = z.enum(['categorical', 'time']);\n\nconst AnalyticsEntityTypeSchema = z.enum(['primary', 'unique', 'foreign', 'natural']);\n\nconst AnalyticsTimeGranularitySchema = z.enum(['day', 'week', 'month', 'quarter', 'year']);\n\nconst AnalyticsVisibilitySchema = z.enum(['internal', 'agent', 'public']);\n\nconst NonAdditiveDimensionSchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n window_choice: z.string().optional(),\n window_groupings: z.array(z.string()).optional(),\n }),\n]);\n\n/**\n * Semantic Metadata Schema - Optional field-level analytics properties\n *\n * Controls how a field is exposed to the cube.js semantic layer:\n * measures, dimensions, entities, and their configuration.\n */\nconst SemanticMetadataSchema = z.object({\n measure: z.boolean().optional(),\n analytics_aggregation: AnalyticsAggregationSchema.optional(),\n agg_time_dimension: z.string().optional(),\n non_additive_dimension: NonAdditiveDimensionSchema.optional(),\n dimension: z.boolean().optional(),\n dimension_type: AnalyticsDimensionTypeSchema.optional(),\n time_granularity: AnalyticsTimeGranularitySchema.optional(),\n is_partition: z.boolean().optional(),\n entity: z.boolean().optional(),\n entity_type: AnalyticsEntityTypeSchema.optional(),\n entity_role: z.string().optional(),\n analytics_visibility: AnalyticsVisibilitySchema.optional(),\n semantic_expr: z.string().optional(),\n semantic_label: z.string().optional(),\n});\n\nconst UiMetadataSchema = z.object({\n ui_label: z.string().optional(),\n ui_type: UiTypeSchema.optional(),\n ui_importance: UiImportanceSchema.optional(),\n ui_group: z.string().optional(),\n ui_sortable: z.boolean().optional(),\n ui_filterable: z.boolean().optional(),\n ui_visible: z.boolean().optional(),\n ui_placeholder: z.string().optional(),\n ui_help: z.string().optional(),\n ui_format: z.record(z.unknown()).optional(),\n});\n\n// ============================================================================\n// Field Definition\n// ============================================================================\n\n/**\n * Field Definition Schema\n *\n * Semantics:\n * - `required: true` → Field must be provided on CREATE (DTO validation)\n * - `required: false` → Field is optional on CREATE (DTO validation)\n * - `nullable: true` → Database column allows NULL\n * - `nullable: false` (default) → Database column is NOT NULL\n *\n * Common patterns:\n * - `required: true` (nullable defaults to false) → Must provide, cannot be null\n * - `required: false, nullable: true` → Optional field, can be null\n * - `required: true, nullable: true` → INVALID (rejected by validator)\n * - `required: false, nullable: false` → Has default value in DB\n */\n/**\n * Base Field Schema - Core database/type properties\n */\nconst BaseFieldSchema = z.object({\n type: FieldTypeSchema,\n required: z.boolean().optional().default(false),\n nullable: z.boolean().optional().default(false),\n\n // String constraints\n max_length: z.number().int().positive().optional(),\n min_length: z.number().int().nonnegative().optional(),\n\n // Numeric constraints\n min: z.number().optional(),\n max: z.number().optional(),\n\n // Enum/choices (inline definition)\n choices: z.array(z.string()).optional(),\n\n // Enum/choices from external file (e.g., \"relationship_types.yaml\")\n // Mutually exclusive with choices - parser loads file and extracts keys\n choices_from: z.string().optional(),\n\n // Entity reference: allowed entity types for polymorphic refs\n // Required when type is 'entity_ref'\n allowed_types: z.array(z.string()).optional(),\n\n // Default value\n default: z.unknown().optional(),\n\n // Indexing\n index: z.boolean().optional(),\n unique: z.boolean().optional(),\n\n // Foreign key reference (e.g., \"accounts.id\")\n foreign_key: z.string().optional(),\n});\n\n/**\n * Field Definition Schema - Combines base fields with optional UI metadata\n */\nconst FieldDefinitionSchema = BaseFieldSchema.merge(UiMetadataSchema).merge(SemanticMetadataSchema)\n .refine((data) => !(data.required === true && data.nullable === true), {\n message:\n \"'required: true' and 'nullable: true' cannot both be set. A required field cannot be null.\",\n path: [\"required\"],\n })\n .refine(\n (data) => {\n if (data.min_length !== undefined && data.type !== \"string\") {\n return false;\n }\n return true;\n },\n {\n message: \"'min_length' can only be used with type 'string'\",\n path: [\"min_length\"],\n },\n )\n .refine(\n (data) => {\n if (data.max_length !== undefined && data.type !== \"string\") {\n return false;\n }\n return true;\n },\n {\n message: \"'max_length' can only be used with type 'string'\",\n path: [\"max_length\"],\n },\n )\n .refine(\n (data) => {\n if (\n data.min !== undefined &&\n ![\"integer\", \"decimal\"].includes(data.type)\n ) {\n return false;\n }\n return true;\n },\n {\n message: \"'min' can only be used with numeric types\",\n path: [\"min\"],\n },\n )\n .refine(\n (data) => {\n if (\n data.max !== undefined &&\n ![\"integer\", \"decimal\"].includes(data.type)\n ) {\n return false;\n }\n return true;\n },\n {\n message: \"'max' can only be used with numeric types\",\n path: [\"max\"],\n },\n )\n .refine(\n (data) => {\n // entity_ref requires allowed_types\n if (data.type === \"entity_ref\" && !data.allowed_types?.length) {\n return false;\n }\n return true;\n },\n {\n message: \"'entity_ref' type requires 'allowed_types' to be specified\",\n path: [\"allowed_types\"],\n },\n )\n .refine(\n (data) => {\n // allowed_types only valid for entity_ref\n if (data.allowed_types !== undefined && data.type !== \"entity_ref\") {\n return false;\n }\n return true;\n },\n {\n message: \"'allowed_types' can only be used with type 'entity_ref'\",\n path: [\"allowed_types\"],\n },\n )\n .refine(\n (data) => {\n // choices and choices_from are mutually exclusive\n if (data.choices !== undefined && data.choices_from !== undefined) {\n return false;\n }\n return true;\n },\n {\n message: \"'choices' and 'choices_from' cannot both be specified\",\n path: [\"choices_from\"],\n },\n )\n .refine(\n (data) => {\n // enum type requires either choices or choices_from\n if (data.type === \"enum\" && !data.choices?.length && !data.choices_from) {\n return false;\n }\n return true;\n },\n {\n message: \"'enum' type requires either 'choices' or 'choices_from'\",\n path: [\"choices\"],\n },\n )\n .refine(\n (data) => {\n // If measure is true, analytics_aggregation must be present\n if (data.measure === true && !data.analytics_aggregation) {\n return false;\n }\n return true;\n },\n {\n message:\n \"When 'measure' is true, 'analytics_aggregation' must be specified\",\n path: [\"analytics_aggregation\"],\n },\n );\n\nexport type FieldDefinition = z.infer<typeof FieldDefinitionSchema>;\n\n// ============================================================================\n// Relationship Definition\n// ============================================================================\n\nconst RelationshipTypeSchema = z.enum([\"belongs_to\", \"has_many\", \"has_one\"]);\n\n/**\n * on_delete — governs database-level FK cascade behaviour for hard-deletes.\n *\n * Applies only to belongs_to relations; ignored on has_many / has_one.\n * Per ADR-021, this has NO effect under soft-delete: BaseService.delete()\n * issues an UPDATE (sets deleted_at), never a DELETE, so Postgres cascade\n * rules never fire for a soft-deleted parent.\n *\n * | Value | Emitted Drizzle | Postgres behaviour |\n * |-------------|------------------------------|---------------------------------------|\n * | restrict | { onDelete: 'restrict' } | Parent DELETE fails if children exist. DEFAULT. |\n * | cascade | { onDelete: 'cascade' } | Parent DELETE removes children. |\n * | set_null | { onDelete: 'set null' } | Parent DELETE nulls FK on children. Requires nullable: true. |\n * | no_action | { onDelete: 'no action' } | Deferred check (equivalent to restrict in single-statement txns). |\n *\n * See docs/adrs/ADR-021-on-delete-semantics.md for the full decision.\n */\nexport const OnDeleteSchema = z.enum([\"restrict\", \"cascade\", \"set_null\", \"no_action\"]);\n\nexport type OnDelete = z.infer<typeof OnDeleteSchema>;\n\nconst RelationshipSchema = z\n .object({\n type: RelationshipTypeSchema,\n target: z.string(), // Target entity name (e.g., \"account\")\n foreign_key: z.string(), // FK field name (e.g., \"account_id\")\n through: z.string().optional(), // For transitive: \"owned_opportunities.updates\"\n inverse: z.string().optional(), // Name of inverse relationship on target entity\n nullable: z.boolean().optional(), // Whether the FK column allows NULL\n on_delete: OnDeleteSchema.optional().default(\"restrict\"), // FK cascade action (belongs_to only; hard-delete only)\n })\n .strict()\n .refine(\n (data) => {\n // set_null requires nullable: true — Postgres cannot null a NOT NULL column\n if (data.on_delete === \"set_null\" && data.nullable !== true) {\n return false;\n }\n return true;\n },\n {\n message:\n \"'on_delete: set_null' requires 'nullable: true' — Postgres cannot null a NOT NULL FK column.\",\n path: [\"on_delete\"],\n },\n );\n\nexport type Relationship = z.infer<typeof RelationshipSchema>;\n\n// ============================================================================\n// Behavior Configuration\n// ============================================================================\n\n/**\n * Behavior configuration can be:\n * - A simple string: \"timestamps\"\n * - An object with options: { name: \"sluggable\", options: { source: \"title\" } }\n *\n * Built-in behaviors:\n * - timestamps: Adds created_at, updated_at fields\n * - soft_delete: Adds deleted_at field, filters deleted records\n * - user_tracking: Adds created_by, updated_by fields\n * - temporal_validity: Adds valid_from, valid_to, is_active fields\n * with deactivate() method and validity-aware query filtering\n */\nconst BehaviorConfigSchema = z.union([\n z.string(),\n z.object({\n name: z.string(),\n options: z.record(z.unknown()).optional(),\n }),\n]);\n\nexport type BehaviorConfig = z.infer<typeof BehaviorConfigSchema>;\n\n/**\n * Behavior strategy for repository code generation\n * - base_class: Extend BaseRepository (DRY, recommended)\n * - inline: Generate all code directly (WET, full transparency)\n */\nconst BehaviorStrategySchema = z.enum([\"base_class\", \"inline\"]);\n\nexport type BehaviorStrategy = z.infer<typeof BehaviorStrategySchema>;\n\n// ============================================================================\n// Entity Configuration\n// ============================================================================\n\n/**\n * Layout: Folder structure - controls directory nesting\n * - nested: domain/opportunity/opportunity.entity.ts\n * - flat: domain/opportunity.entity.ts\n */\nconst FolderStructureSchema = z.enum([\"nested\", \"flat\"]).default(\"nested\");\n\n/**\n * Layout: File grouping - controls how related code is organized\n * - separate: Each concern in its own file (entity.ts, repository.interface.ts)\n * - grouped: Related concerns combined into index.ts\n *\n * This is orthogonal to folder_structure:\n * | folder_structure | file_grouping | Result |\n * |-----------------|---------------|--------|\n * | nested | separate | domain/opportunity/opportunity.entity.ts |\n * | nested | grouped | domain/opportunity/index.ts (combined) |\n * | flat | separate | domain/opportunity.entity.ts |\n * | flat | grouped | domain/opportunity.ts (combined) |\n */\nconst FileGroupingSchema = z.enum([\"separate\", \"grouped\"]).default(\"separate\");\n\n/**\n * Expose configuration - which layers to generate for this entity\n * - repository: Always generated (domain entity, repository interface/impl)\n * - rest: Generate REST controller\n * - trpc: Generate tRPC module\n * - electric: Generate Electric SQL migration (REPLICA IDENTITY + publication)\n *\n * Default: ['repository', 'rest', 'trpc'] (all layers)\n */\nconst ExposeLayerSchema = z.enum([\"repository\", \"rest\", \"trpc\", \"electric\"]);\nexport type ExposeLayer = z.infer<typeof ExposeLayerSchema>;\n\nconst EntityConfigSchema = z\n .object({\n name: z\n .string()\n .regex(\n /^[a-z][a-z0-9_]*$/,\n \"Entity name must be lowercase with underscores (e.g., 'opportunity')\",\n ),\n plural: z.string().regex(/^[a-z][a-z0-9_]*$/, \"Plural must be lowercase\"),\n table: z.string().regex(/^[a-z][a-z0-9_]*$/, \"Table must be lowercase\"),\n\n // Layout options (orthogonal concerns)\n // folder_structure: controls directory nesting\n // file_grouping: controls file organization\n folder_structure: FolderStructureSchema.optional(),\n file_grouping: FileGroupingSchema.optional(),\n\n // Per-entity behavior strategy override (overrides codegen.config.yaml)\n behavior_strategy: BehaviorStrategySchema.optional(),\n // Which layers to generate (default: all)\n expose: z\n .array(ExposeLayerSchema)\n .optional()\n .default([\"repository\", \"rest\", \"trpc\"]),\n\n // App-defined patterns (ADR-031, supersedes ADR-005 family:).\n // `pattern:` and `patterns:` are mutually exclusive — use `pattern:`\n // for a single pattern and `patterns:` for multi-pattern composition.\n // Pattern names resolve against the registry at codegen time.\n pattern: z.string().optional(),\n patterns: z.array(z.string()).optional(),\n // Per-pattern config, keyed by pattern name. Each value is validated\n // against the pattern's `configSchema` in composition validation\n // (src/patterns/validate-composition.ts — PATTERN-4).\n config: z.record(z.string(), z.unknown()).optional(),\n\n // JOB-7: marks this entity as a valid scope target for job scoping.\n // Drives the generated ScopeEntityType union in\n // runtime/subsystems/jobs/generated/scope-entity-type.ts.\n scopeable: z.boolean().optional(),\n })\n .strict()\n .refine((d) => !(d.pattern && d.patterns), {\n message: \"'pattern' and 'patterns' are mutually exclusive\",\n });\n\nexport type EntityConfig = z.infer<typeof EntityConfigSchema>;\n\n// ============================================================================\n// Query Declaration\n// ============================================================================\n\n/**\n * Query Declaration Schema - Declarative query generation (ADR-005)\n *\n * Each declaration generates repository + service + use case methods.\n *\n * Examples:\n * { by: [\"user_id\"] }\n * { by: [\"email\"], unique: true }\n * { by: [\"account_id\"], order: \"created_at desc\", limit: true }\n * { by: [\"opportunity_id\"], select: [\"email\"], via: \"opportunity_contact_link\" }\n */\nconst QueryDeclarationSchema = z.object({\n by: z.array(z.string()).min(1),\n unique: z.boolean().optional(),\n select: z.array(z.string()).optional(),\n order: z.string().optional(),\n limit: z.boolean().optional(),\n via: z.string().optional(),\n});\n\nexport type QueryDeclaration = z.infer<typeof QueryDeclarationSchema>;\n\n/**\n * Search Query Declaration — filtered search with pagination.\n *\n * Emits:\n * - `searchXs(input): Promise<Page<Entity>>` on the service\n * - `GET /xs/search` controller route with Zod filter schema\n * - `SearchXsUseCase` with filter-AND + count-for-total semantics\n *\n * Example:\n * - name: search\n * filters: [user_id, provider, is_visible, canonical_state, is_closed]\n * search: name # optional ilike on a single text column\n * paginate: true # defaults to limit 50, max 200, offset 0\n *\n * Consumer contract: `@shared/http/pagination` must export\n * `PaginationSchema` (z.object with limit+offset defaults) and a\n * `Page<T>` interface with `{ items, total, limit, offset }`.\n */\nconst SearchQueryDeclarationSchema = z.object({\n name: z.literal('search'),\n filters: z.array(z.string()).min(1),\n search: z.string().optional(),\n paginate: z.boolean().optional().default(true),\n order: z.string().optional(),\n});\n\nexport type SearchQueryDeclaration = z.infer<typeof SearchQueryDeclarationSchema>;\n\n/**\n * Discriminated union: query declarations can be either the legacy\n * by-column findByX form or the named-search form. The two shapes are\n * disjoint (no `name` vs required `name: 'search'`), so consumers can\n * mix them in the same `queries:` block.\n */\nconst AnyQueryDeclarationSchema = z.union([\n SearchQueryDeclarationSchema,\n QueryDeclarationSchema,\n]);\n\n// ============================================================================\n// Sync Configuration\n// ============================================================================\n\n/**\n * Direction of sync with an external provider\n */\nexport const SyncDirectionSchema = z.enum([\n 'inbound',\n 'outbound',\n 'bidirectional',\n]);\n\nexport type SyncDirection = z.infer<typeof SyncDirectionSchema>;\n\n/**\n * Per-provider sync configuration\n */\nexport const ProviderSyncSchema = z.object({\n remote_entity: z.string(),\n direction: SyncDirectionSchema,\n cdc: z.boolean().optional().default(false),\n field_mapping: z.record(z.string(), z.string()).optional(),\n read_only_fields: z.array(z.string()).optional(),\n});\n\nexport type ProviderSync = z.infer<typeof ProviderSyncSchema>;\n\n/**\n * Top-level sync block: Electric SQL + named provider configs\n */\nexport const SyncConfigSchema = z.object({\n electric: z.boolean().optional().default(false),\n providers: z.record(z.string(), ProviderSyncSchema).optional(),\n});\n\nexport type SyncConfig = z.infer<typeof SyncConfigSchema>;\n\n// ============================================================================\n// Event Declaration\n// ============================================================================\n\n/**\n * Event Declaration Schema - Domain event declarations (CODEGEN-EVOLUTION-PLAN Phase 2)\n *\n * Each declaration generates typed event classes, handlers, and queue registration.\n *\n * Example:\n * name: opportunity_stage_changed\n * queue: domain-events\n * body:\n * opportunity_id: uuid\n * old_stage: string\n * generate_handler: true\n */\nconst EventDeclarationSchema = z.object({\n name: z\n .string()\n .regex(/^[a-z][a-z0-9_]*$/, \"Event name must be snake_case\"),\n queue: z.string(),\n body: z.record(z.string(), z.string()),\n generate_handler: z.boolean().optional().default(false),\n});\n\nexport type EventDeclaration = z.infer<typeof EventDeclarationSchema>;\n\n// ============================================================================\n// Analytics Block (entity-level)\n// ============================================================================\n\n/**\n * Simple metric in a YAML metric definition\n */\nconst SimpleMetricSchema = z.object({\n type: z.literal('simple'),\n measure: z.string(),\n agg: AnalyticsAggregationSchema.optional(),\n filter: z.string().optional(),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Derived metric — expression combining other metrics\n */\nconst DerivedMetricSchema = z.object({\n type: z.literal('derived'),\n expr: z.string(),\n metrics: z.array(z.string()),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Ratio metric — numerator / denominator\n */\nconst RatioMetricSchema = z.object({\n type: z.literal('ratio'),\n numerator: z.union([z.string(), SimpleMetricSchema]),\n denominator: z.union([z.string(), SimpleMetricSchema]),\n filter: z.string().optional(),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Cumulative metric — time-series accumulation\n */\nconst CumulativeMetricSchema = z.object({\n type: z.literal('cumulative'),\n measure: z.string(),\n window: z.string().optional(),\n grain_to_date: AnalyticsTimeGranularitySchema.optional(),\n description: z.string().optional(),\n label: z.string().optional(),\n});\n\n/**\n * Discriminated union of all four metric types\n */\nconst MetricDefinitionSchema = z.discriminatedUnion('type', [\n SimpleMetricSchema,\n DerivedMetricSchema,\n RatioMetricSchema,\n CumulativeMetricSchema,\n]);\n\nexport type MetricDefinition = z.infer<typeof MetricDefinitionSchema>;\n\n/**\n * Entity-level analytics block\n *\n * Declared in the YAML under `analytics:` alongside fields and relationships.\n */\nconst AnalyticsBlockSchema = z.object({\n measure_packs: z.array(z.string()).optional(),\n cube_name: z.string().optional(),\n metrics: z.record(z.string(), MetricDefinitionSchema).optional(),\n});\n\nexport type AnalyticsBlock = z.infer<typeof AnalyticsBlockSchema>;\n\n// ============================================================================\n// Full Entity Definition\n// ============================================================================\n\n// ============================================================================\n// Generation Toggles\n// ============================================================================\n\n/**\n * Per-entity opt-outs for code generation.\n *\n * - `writes`: when `false`, suppresses create/update/delete use cases,\n * matching controller routes, and module providers. Defaults to `true`.\n */\nconst GenerateConfigSchema = z\n .object({\n writes: z.boolean().optional().default(true),\n })\n .strict();\n\nexport type GenerateConfig = z.infer<typeof GenerateConfigSchema>;\n\nexport const EntityDefinitionSchema = z\n .object({\n entity: EntityConfigSchema,\n fields: z.record(z.string(), FieldDefinitionSchema),\n relationships: z.record(z.string(), RelationshipSchema).optional(),\n // Behaviors add cross-cutting concerns (timestamps, soft_delete, user_tracking, etc.)\n behaviors: z.array(BehaviorConfigSchema).optional().default([]),\n\n // Per-entity generation toggles (e.g. disable write-side emission)\n generate: GenerateConfigSchema.optional(),\n\n // EAV (entity-attribute-value) dual-write + paired reads (ADR-13).\n // When `true`, codegen emits:\n // - FindXWithFieldsUseCase + ListXWithFieldsUseCase (paired reads)\n // - CreateX / UpdateX use cases in transactional compound-write shape\n // (composes entity service + FieldValueService in one db.transaction,\n // splits `{ fields, ...core }` from the DTO)\n // - GET /:id/with-fields + GET /with-fields controller routes\n // - Service with injected FieldValueRepository + findByIdWithFields /\n // listWithFields paired read methods\n //\n // Consumer contract (must be in place before regen):\n // - BaseService.create/update/delete accept optional `tx` parameter\n // - `@shared/eav-helpers` exports `toEavRows(entityId, entityType, fields)`\n // and `mergeEavRows(rows)`\n // - FieldValueService exposes `upsertMany(rows, tx?)` (inherited from\n // MetadataEntityService)\n // - DRIZZLE_DB injection token available via `@shared/constants/tokens`\n //\n // Defaults to `false` — opt in per entity that needs dynamic/custom fields.\n eav: z.boolean().optional().default(false),\n\n // Declare this entity IS an EAV value table. When `true`, codegen emits\n // the compound EAV methods (upsertFieldsTransactional, findMergedByEntity)\n // on the service and the upsertCurrentValues method on the repository —\n // no hand extension required. Companion flag `eav_definition_table`\n // identifies the sibling entity that stores the field-key ↔ id lookup.\n //\n // Mutually exclusive with `eav: true` in practice — a value table holds\n // OTHER entities' dynamic fields, it isn't itself an EAV-opt-in entity.\n //\n // Assumption (v1): value tables have a `user_id` column. Future\n // `eav_user_scoped: false` flag will relax this for audit/system EAV.\n eav_value_table: z.boolean().optional().default(false),\n\n // Singular entity name of the field-definitions entity that pairs with\n // this value table (matches the `target:` convention in relationship\n // YAMLs). Required when `eav_value_table: true`; ignored otherwise.\n eav_definition_table: z.string().optional(),\n\n\n // v2: Declarative query generation (ADR-005)\n // Generates repository + service + use case methods from declarations\n queries: z.array(AnyQueryDeclarationSchema).optional(),\n\n // v2: Integration sync configuration (CODEGEN-EVOLUTION-PLAN Phase 2)\n // Electric SQL + provider sync (Salesforce, HubSpot, etc.)\n sync: SyncConfigSchema.optional(),\n\n // v2: Domain event declarations (CODEGEN-EVOLUTION-PLAN Phase 2)\n // Generates typed event classes, handlers, and queue registration\n events: z.array(EventDeclarationSchema).optional(),\n\n // EVT-7: Opt-in typed event emission. Each entry names an `EventDefinition`\n // (top-level `events/<type>.yaml` or an inline `events:` block entry) that\n // the generated use-cases should publish via `TypedEventBus.publish(...)`\n // inside a Drizzle transaction.\n //\n // emits: [contact_created, contact_updated]\n //\n // Cross-validated in `validateEntityEmits()` against the merged event\n // registry. `undefined` ⇒ fallback to untyped lifecycle-events + warning;\n // `[]` ⇒ explicit opt-out, no warning, no typed emission.\n emits: z\n .array(\n z\n .string()\n .regex(/^[a-z][a-z0-9_]*$/, 'emits entries must be snake_case event type names'),\n )\n .optional(),\n\n // v2: Analytics / semantic layer configuration\n // Cube.js measure packs, custom cube name, and metric definitions\n analytics: AnalyticsBlockSchema.optional(),\n })\n .strict()\n .refine(\n (data) => !data.eav_value_table || typeof data.eav_definition_table === 'string',\n {\n message:\n \"`eav_definition_table` is required when `eav_value_table: true` — \" +\n \"declare the singular entity name of the paired field-definitions entity \" +\n \"(e.g. `eav_definition_table: 'field_definition'`).\",\n path: ['eav_definition_table'],\n },\n );\n\nexport type EntityDefinition = z.infer<typeof EntityDefinitionSchema>;\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nexport function validateEntityDefinition(data: unknown): EntityDefinition {\n return EntityDefinitionSchema.parse(data);\n}\n\nexport function safeValidateEntityDefinition(data: unknown): {\n success: boolean;\n data?: EntityDefinition;\n error?: z.ZodError;\n} {\n const result = EntityDefinitionSchema.safeParse(data);\n if (result.success) {\n return { success: true, data: result.data };\n }\n return { success: false, error: result.error };\n}\n\n// ============================================================================\n// Type Mapping Utilities (for code generation)\n// ============================================================================\n\n/**\n * Maps YAML field types to TypeScript types\n *\n * Note: 'entity_ref' is handled specially in templates as it generates\n * two fields: {field}EntityType (EntityType enum) and {field}EntityId (string)\n */\nexport const fieldTypeToTypeScript: Record<FieldType, string> = {\n string: \"string\",\n integer: \"number\",\n decimal: \"number\",\n boolean: \"boolean\",\n uuid: \"string\",\n date: \"Date\",\n datetime: \"Date\",\n json: \"unknown\",\n entity_ref: \"EntityRef\", // Placeholder - templates handle specially\n string_array: \"string[]\",\n enum: \"string\", // Actual enum type generated from choices\n};\n\n/**\n * Maps YAML field types to Drizzle column types\n *\n * Note: 'entity_ref' generates two columns: pgEnum + uuid\n * Note: 'enum' uses pgEnum with choices\n */\nexport const fieldTypeToDrizzle: Record<FieldType, string> = {\n string: \"varchar\",\n integer: \"integer\",\n decimal: \"decimal\",\n boolean: \"boolean\",\n uuid: \"uuid\",\n date: \"date\",\n datetime: \"timestamp\",\n json: \"jsonb\",\n entity_ref: \"entity_ref\", // Placeholder - templates handle specially (enum + uuid)\n string_array: \"text().array()\",\n enum: \"enum\", // Placeholder - templates generate pgEnum\n};\n\n/**\n * Maps YAML field types to Zod schema methods\n *\n * Note: 'entity_ref' generates two fields in Zod schema\n * Note: 'enum' uses z.enum() with choices\n */\nexport const fieldTypeToZod: Record<FieldType, string> = {\n string: \"z.string()\",\n integer: \"z.number().int()\",\n // Drizzle maps PG `numeric` to a JS string to preserve precision.\n // Using z.coerce.string() — not z.coerce.number() — prevents silent\n // precision loss on large decimal values. Matches clean-lite-ps (PR #42).\n decimal: \"z.coerce.string()\",\n boolean: \"z.boolean()\",\n uuid: \"z.string().uuid()\",\n date: \"z.date()\",\n datetime: \"z.date()\",\n json: \"z.unknown()\",\n entity_ref: \"entity_ref\", // Placeholder - templates handle specially\n string_array: \"z.array(z.string())\",\n enum: \"z.enum()\", // Placeholder - templates add choices\n};\n","import { z } from \"zod\";\n\n/**\n * Event Definition Schema\n *\n * Describes a single `events/*.yaml` file. This is the codegen-side contract\n * for first-class event declarations (ADR-024 Phase 1, EVT-2). One file per\n * event; filename matches `type` (snake_case). Consumed by EVT-3 to emit\n * `runtime/subsystems/events/generated/` artifacts.\n *\n * Payload field types intentionally narrower than entity field types:\n * events are a wire format, not a database schema. `decimal`, `entity_ref`,\n * `string_array`, `enum` make no sense in an event payload.\n */\n\n// ============================================================================\n// Enums and constants\n// ============================================================================\n\nexport const EVENT_DIRECTIONS = [\"inbound\", \"change\", \"outbound\"] as const;\nexport type EventDirection = (typeof EVENT_DIRECTIONS)[number];\n\nexport const EVENT_FIELD_TYPES = [\n\t\"uuid\",\n\t\"string\",\n\t\"number\",\n\t\"boolean\",\n\t\"date\",\n\t\"json\",\n\t\"array\",\n] as const;\nexport type EventFieldType = (typeof EVENT_FIELD_TYPES)[number];\n\n/**\n * Scalar types permitted as `items` of an `array` field. Intentionally narrower\n * than the full field-type set: nested arrays and nested objects inside a\n * payload array cross the line from \"wire format\" into \"embedded schema\" and\n * should be modelled either as a separate event or as a `json` blob.\n */\nexport const EVENT_ARRAY_ITEM_TYPES = [\n\t\"uuid\",\n\t\"string\",\n\t\"number\",\n\t\"boolean\",\n\t\"date\",\n] as const;\nexport type EventArrayItemType = (typeof EVENT_ARRAY_ITEM_TYPES)[number];\n\nexport const RESERVED_EVENT_POOLS = [\n\t\"events_inbound\",\n\t\"events_change\",\n\t\"events_outbound\",\n] as const;\nexport type EventPool = (typeof RESERVED_EVENT_POOLS)[number];\n\nexport const EVENT_BACKOFF_STRATEGIES = [\"linear\", \"exponential\"] as const;\nexport type EventBackoffStrategy = (typeof EVENT_BACKOFF_STRATEGIES)[number];\n\n/**\n * Direction → default pool derivation. Each `direction` maps to exactly one\n * reserved pool; overrides must stay within the same category.\n */\nexport const DIRECTION_TO_POOL: Record<EventDirection, EventPool> = {\n\tinbound: \"events_inbound\",\n\tchange: \"events_change\",\n\toutbound: \"events_outbound\",\n};\n\n// ============================================================================\n// Sub-schemas\n// ============================================================================\n\nconst EventDirectionSchema = z.enum(EVENT_DIRECTIONS);\nconst EventFieldTypeSchema = z.enum(EVENT_FIELD_TYPES);\nconst EventArrayItemTypeSchema = z.enum(EVENT_ARRAY_ITEM_TYPES);\nconst EventPoolSchema = z.enum(RESERVED_EVENT_POOLS);\n\n/**\n * Per-payload-field metadata. `nullable: true` means the field may be `null`\n * on the wire; `description` is surfaced into the generated interface/Zod\n * schema as a JSDoc. `items` is required when `type: 'array'` and rejected\n * otherwise — enforces \"array-ness is declared, item shape is declared\"\n * without opening the door to arbitrary nesting.\n */\nconst EventPayloadFieldSchema = z\n\t.object({\n\t\ttype: EventFieldTypeSchema,\n\t\titems: EventArrayItemTypeSchema.optional(),\n\t\tnullable: z.boolean().optional().default(false),\n\t\tdescription: z.string().optional(),\n\t})\n\t.strict()\n\t.superRefine((data, ctx) => {\n\t\tif (data.type === \"array\" && data.items === undefined) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: \"'items' is required when type is 'array'\",\n\t\t\t\tpath: [\"items\"],\n\t\t\t});\n\t\t}\n\t\tif (data.type !== \"array\" && data.items !== undefined) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: `'items' is only valid when type is 'array' (got '${data.type}')`,\n\t\t\t\tpath: [\"items\"],\n\t\t\t});\n\t\t}\n\t});\n\nexport type EventPayloadField = z.infer<typeof EventPayloadFieldSchema>;\n\n/**\n * Retry metadata hints surfaced to the drain loop. Default applied at parent\n * level (see `EventDefinitionSchemaCore`).\n */\nconst RetrySchema = z\n\t.object({\n\t\tattempts: z.number().int().min(0).max(20),\n\t\tbackoff: z.enum(EVENT_BACKOFF_STRATEGIES),\n\t})\n\t.strict();\n\nexport type EventRetry = z.infer<typeof RetrySchema>;\n\n// ============================================================================\n// Top-level schema\n// ============================================================================\n\nconst SNAKE_CASE_RE = /^[a-z][a-z0-9_]*$/;\n\nconst EventDefinitionSchemaCore = z\n\t.object({\n\t\ttype: z\n\t\t\t.string()\n\t\t\t.regex(\n\t\t\t\tSNAKE_CASE_RE,\n\t\t\t\t\"Event type must be snake_case starting with a letter\",\n\t\t\t),\n\t\tdirection: EventDirectionSchema,\n\t\tpool: EventPoolSchema.optional(),\n\t\taggregate: z.string().regex(SNAKE_CASE_RE).optional(),\n\t\tsource: z.string().min(1).optional(),\n\t\tdestination: z.string().min(1).optional(),\n\t\tpayload: z\n\t\t\t.record(\n\t\t\t\tz\n\t\t\t\t\t.string()\n\t\t\t\t\t.regex(SNAKE_CASE_RE, \"Payload keys must be snake_case\"),\n\t\t\t\tEventPayloadFieldSchema,\n\t\t\t)\n\t\t\t.default({}),\n\t\tretry: RetrySchema.optional().default({\n\t\t\tattempts: 3,\n\t\t\tbackoff: \"exponential\",\n\t\t}),\n\t\tversion: z.number().int().min(1).optional().default(1),\n\t\tdescription: z.string().optional(),\n\t})\n\t.strict();\n\n/**\n * Cross-field refinements (in order):\n *\n * 1. `direction: change` ⇒ `aggregate` is required.\n * 2. `source` is only valid when `direction: inbound` (strict direction gating).\n * 3. `destination` is only valid when `direction: outbound` (strict direction gating).\n * 4. An explicit `pool` must match `DIRECTION_TO_POOL[direction]`.\n *\n * Strict gating on #2/#3 is a deliberate choice: silent acceptance breeds\n * drift. The ADR defines `source` as inbound-only and `destination` as\n * outbound-only.\n */\nconst EventDefinitionSchemaRefined = EventDefinitionSchemaCore.superRefine(\n\t(data, ctx) => {\n\t\tif (data.direction === \"change\" && !data.aggregate) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: \"'aggregate' is required when direction is 'change'\",\n\t\t\t\tpath: [\"aggregate\"],\n\t\t\t});\n\t\t}\n\n\t\tif (data.source !== undefined && data.direction !== \"inbound\") {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: `'source' is only valid when direction is 'inbound' (got '${data.direction}')`,\n\t\t\t\tpath: [\"source\"],\n\t\t\t});\n\t\t}\n\n\t\tif (data.destination !== undefined && data.direction !== \"outbound\") {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\tmessage: `'destination' is only valid when direction is 'outbound' (got '${data.direction}')`,\n\t\t\t\tpath: [\"destination\"],\n\t\t\t});\n\t\t}\n\n\t\tif (data.pool !== undefined) {\n\t\t\tconst expected = DIRECTION_TO_POOL[data.direction];\n\t\t\tif (data.pool !== expected) {\n\t\t\t\tctx.addIssue({\n\t\t\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\t\t\tmessage: `pool '${data.pool}' is inconsistent with direction '${data.direction}' (expected '${expected}')`,\n\t\t\t\t\tpath: [\"pool\"],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t},\n);\n\n/**\n * Final schema: derive `pool` from `direction` when not explicitly set. After\n * `parse()`, every `EventDefinition` has `pool` populated.\n */\nexport const EventDefinitionSchema = EventDefinitionSchemaRefined.transform(\n\t(parsed) => ({\n\t\t...parsed,\n\t\tpool: parsed.pool ?? DIRECTION_TO_POOL[parsed.direction],\n\t}),\n);\n\nexport type EventDefinition = z.infer<typeof EventDefinitionSchema>;\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nexport function validateEventDefinition(data: unknown): EventDefinition {\n\treturn EventDefinitionSchema.parse(data);\n}\n\nexport function safeValidateEventDefinition(data: unknown): {\n\tsuccess: boolean;\n\tdata?: EventDefinition;\n\terror?: z.ZodError;\n} {\n\tconst result = EventDefinitionSchema.safeParse(data);\n\tif (result.success) {\n\t\treturn { success: true, data: result.data };\n\t}\n\treturn { success: false, error: result.error };\n}\n","import { z } from 'zod';\n\n/**\n * Relationship Definition Schema\n *\n * Defines the YAML contract for first-class relationship entities — typed,\n * temporal, sourced junction tables between core entities.\n *\n * A relationship definition generates the same artifacts as an entity\n * (Drizzle schema, repository, DTOs, NestJS module, controller) but with\n * auto-generated FK columns, type enum, temporal fields, and source tracking.\n *\n * The relationship: block replaces entity: as the top-level discriminator.\n * The fields:, queries:, and behaviors: blocks reuse entity-definition schemas.\n *\n * See: docs/codegen-evolution-data-model/03-relationship-taxonomy.md\n * See: test/fixtures/relationships/ for examples\n */\n\n// Re-use field and query schemas from entity-definition\n// These are imported to avoid duplication — fields on a relationship\n// work identically to fields on an entity.\nimport type { FieldDefinition, QueryDeclaration } from './entity-definition.schema.js';\n\n// ============================================================================\n// Relationship Type Definitions\n// ============================================================================\n\n/**\n * Direction metadata for a single relationship type.\n *\n * Required for self-referential relationships (person↔person, org↔org)\n * where direction can't be inferred from entity-type asymmetry.\n *\n * Three mutually exclusive modes:\n * - inverse: \"from→to is called X, to→from is called Y\"\n * - bidirectional: true — direction doesn't matter, query both sides\n * - directed: true — one-way, no inverse name (default if none specified)\n */\nconst TypeDirectionSchema = z\n\t.object({\n\t\t/** Name of the inverse type when viewed from the other direction */\n\t\tinverse: z.string().optional(),\n\t\t/** Both directions are equivalent — queries should check both FK columns */\n\t\tbidirectional: z.boolean().optional(),\n\t\t/** Explicitly directed, no named inverse (default behavior) */\n\t\tdirected: z.boolean().optional(),\n\t})\n\t.refine(\n\t\t(data) => {\n\t\t\tconst set = [data.inverse, data.bidirectional, data.directed].filter(\n\t\t\t\t(v) => v !== undefined,\n\t\t\t);\n\t\t\treturn set.length === 1;\n\t\t},\n\t\t{\n\t\t\tmessage:\n\t\t\t\t'Exactly one of inverse, bidirectional, or directed must be specified',\n\t\t},\n\t);\n\nexport type TypeDirection = z.infer<typeof TypeDirectionSchema>;\n\n/**\n * Relationship types can be declared in two forms:\n *\n * 1. Simple list — for cross-type relationships where direction is\n * unambiguous from entity asymmetry:\n * types: [employed_by, advises, board_member]\n *\n * 2. Object map — for self-referential or when types need direction metadata:\n * types:\n * reporting:\n * inverse: management\n * network:\n * bidirectional: true\n *\n * The simple list is sugar for \"all directed from→to, no inverses.\"\n */\nconst RelationshipTypesSchema = z.union([\n\t// Simple list: all types are directed from→to\n\tz.array(z.string().regex(/^[a-z][a-z0-9_]*$/, 'Type must be snake_case')),\n\t// Object map: each type has direction metadata\n\tz.record(\n\t\tz.string().regex(/^[a-z][a-z0-9_]*$/, 'Type key must be snake_case'),\n\t\tTypeDirectionSchema,\n\t),\n]);\n\nexport type RelationshipTypes = z.infer<typeof RelationshipTypesSchema>;\n\n// ============================================================================\n// On-Delete Semantics (ADR-021)\n// ============================================================================\n\nconst OnDeleteActionSchema = z\n\t.enum(['restrict', 'cascade', 'set_null', 'no_action'])\n\t.default('restrict');\n\nexport type OnDeleteAction = z.infer<typeof OnDeleteActionSchema>;\n\n// ============================================================================\n// Relationship Configuration Block\n// ============================================================================\n\n/**\n * The relationship: block — top-level config for a relationship definition.\n *\n * Establishes the two endpoints, type taxonomy, and behavioral flags.\n * Auto-generates FK columns, type enum, temporal fields, source tracking,\n * and timestamps based on configuration.\n */\nconst RelationshipConfigSchema = z\n\t.object({\n\t\t/** Relationship name (snake_case). Used for class/file naming. */\n\t\tname: z.string().regex(\n\t\t\t/^[a-z][a-z0-9_]*$/,\n\t\t\t'Relationship name must be snake_case',\n\t\t),\n\n\t\t/** Database table name. Defaults to {name}s if not specified. */\n\t\ttable: z\n\t\t\t.string()\n\t\t\t.regex(/^[a-z][a-z0-9_]*$/, 'Table must be snake_case')\n\t\t\t.optional(),\n\n\t\t/** The \"from\" entity — generates {entity}_id FK column (subject). */\n\t\tfrom: z.string().regex(/^[a-z][a-z0-9_]*$/, 'Entity name must be snake_case'),\n\n\t\t/** The \"to\" entity — generates {entity}_id FK column (object). */\n\t\tto: z.string().regex(/^[a-z][a-z0-9_]*$/, 'Entity name must be snake_case'),\n\n\t\t/**\n\t\t * Relationship subtypes. Optional — omit for untyped junctions.\n\t\t * When present, generates a `type` enum column on the junction table.\n\t\t *\n\t\t * Simple list: all types are directed (from→to). Use for cross-type\n\t\t * relationships where entity asymmetry makes direction obvious.\n\t\t *\n\t\t * Object map: each type declares its own direction metadata.\n\t\t * Required for self-referential relationships (from === to).\n\t\t */\n\t\ttypes: RelationshipTypesSchema.optional(),\n\n\t\t/**\n\t\t * Generate temporal validity fields: valid_from (date), valid_to (date?),\n\t\t * is_current (boolean, denormalized for query performance).\n\t\t * Default: true\n\t\t */\n\t\ttemporal: z.boolean().default(true),\n\n\t\t/**\n\t\t * Generate source tracking fields: source (enum), confidence (decimal 0-1).\n\t\t * Default: true\n\t\t */\n\t\tsourced: z.boolean().default(true),\n\n\t\t/** on_delete action for the \"from\" endpoint FK. Default: restrict */\n\t\ton_delete_from: OnDeleteActionSchema.optional(),\n\n\t\t/** on_delete action for the \"to\" endpoint FK. Default: restrict */\n\t\ton_delete_to: OnDeleteActionSchema.optional(),\n\n\t\t/**\n\t\t * Override the default unique constraint columns.\n\t\t *\n\t\t * Defaults:\n\t\t * - Typed: [from_id, to_id, type]\n\t\t * - Typed + temporal: [from_id, to_id, type, valid_from]\n\t\t * - Untyped: [from_id, to_id]\n\t\t *\n\t\t * Use this when the default doesn't fit — e.g., allowing multiple\n\t\t * relationships of the same type between the same entities at different times.\n\t\t */\n\t\tunique_on: z.array(z.string()).optional(),\n\t})\n\t.strict();\n\nexport type RelationshipConfig = z.infer<typeof RelationshipConfigSchema>;\n\n// ============================================================================\n// Query Declaration (reuse from entity-definition)\n// ============================================================================\n\n/**\n * Same query declaration syntax as entities.\n * FK field names in `by:` use the auto-generated names:\n * - Cross-type: {entity}_id (e.g., person_id, organization_id)\n * - Self-referential: from_{entity}_id, to_{entity}_id\n */\nconst RelationshipQuerySchema = z.object({\n\tby: z.array(z.string()).min(1),\n\tunique: z.boolean().optional(),\n\tselect: z.array(z.string()).optional(),\n\torder: z.string().optional(),\n\tlimit: z.boolean().optional(),\n});\n\n// ============================================================================\n// Field Definition (reuse from entity-definition)\n// ============================================================================\n\n// We import the type but need to re-reference the schema inline for Zod parsing.\n// The actual FieldDefinitionSchema is defined in entity-definition.schema.ts.\n// For now, we use z.record(z.string(), z.any()) and validate fields\n// through the shared FieldDefinitionSchema at parse time.\n//\n// TODO: Extract FieldDefinitionSchema to a shared module so both\n// entity-definition and relationship-definition can import it directly.\n\n// ============================================================================\n// Full Relationship Definition\n// ============================================================================\n\n/**\n * Complete relationship definition — the top-level shape of a relationship YAML file.\n *\n * Example (minimal):\n * relationship:\n * name: engagement_opportunity\n * from: engagement\n * to: opportunity\n *\n * Example (full):\n * relationship:\n * name: person_organization\n * table: person_organizations\n * from: person\n * to: organization\n * types: [employed_by, advises, board_member]\n * temporal: true\n * sourced: true\n * fields:\n * role_title:\n * type: string\n * nullable: true\n * queries:\n * - by: [person_id]\n */\nexport const RelationshipDefinitionSchema = z\n\t.object({\n\t\t/** Relationship configuration block */\n\t\trelationship: RelationshipConfigSchema,\n\n\t\t/**\n\t\t * Additional fields beyond auto-generated ones.\n\t\t * These describe the relationship, not either endpoint entity.\n\t\t * Uses the same field definition schema as entity fields.\n\t\t */\n\t\tfields: z.record(z.string(), z.any()).optional(),\n\n\t\t/** Declarative queries — same syntax as entity queries. */\n\t\tqueries: z.array(RelationshipQuerySchema).optional(),\n\t})\n\t.strict()\n\t.refine(\n\t\t(data) => {\n\t\t\t// Self-referential relationships with types MUST use the object map form\n\t\t\t// so that direction metadata (inverse/bidirectional/directed) is explicit.\n\t\t\tif (data.relationship.from === data.relationship.to && data.relationship.types) {\n\t\t\t\treturn !Array.isArray(data.relationship.types);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\t{\n\t\t\tmessage:\n\t\t\t\t'Self-referential relationships must use the object map form for types ' +\n\t\t\t\t'(with inverse/bidirectional/directed metadata), not a simple list',\n\t\t\tpath: ['relationship', 'types'],\n\t\t},\n\t)\n\t.refine(\n\t\t(data) => {\n\t\t\t// Reject fields: keys that collide with auto-generated column names.\n\t\t\t// The reserved set is dynamic — depends on the relationship config.\n\t\t\tif (!data.fields) return true;\n\n\t\t\tconst reserved = getReservedColumnNames(data.relationship);\n\t\t\tconst collisions = Object.keys(data.fields).filter((key) =>\n\t\t\t\treserved.has(key),\n\t\t\t);\n\t\t\treturn collisions.length === 0;\n\t\t},\n\t\t{\n\t\t\tmessage:\n\t\t\t\t'fields: contains keys that collide with auto-generated columns. ' +\n\t\t\t\t'Reserved names depend on config (type, valid_from, valid_to, ' +\n\t\t\t\t'is_current, source, confidence, id, created_at, updated_at, and FK columns).',\n\t\t\tpath: ['fields'],\n\t\t},\n\t);\n\nexport type RelationshipDefinition = z.infer<\n\ttypeof RelationshipDefinitionSchema\n>;\n\n// ============================================================================\n// Validation Helpers\n// ============================================================================\n\nexport function validateRelationshipDefinition(\n\tdata: unknown,\n): RelationshipDefinition {\n\treturn RelationshipDefinitionSchema.parse(data);\n}\n\nexport function safeValidateRelationshipDefinition(data: unknown): {\n\tsuccess: boolean;\n\tdata?: RelationshipDefinition;\n\terror?: z.ZodError;\n} {\n\tconst result = RelationshipDefinitionSchema.safeParse(data);\n\tif (result.success) {\n\t\treturn { success: true, data: result.data };\n\t}\n\treturn { success: false, error: result.error };\n}\n\n// ============================================================================\n// Reserved Column Names\n// ============================================================================\n\n/**\n * Returns the set of column names that are auto-generated for a relationship\n * and therefore cannot be used as custom field names.\n *\n * The set is dynamic — it depends on the relationship config:\n * - Always: id, created_at, updated_at, and both FK columns\n * - If types: present → type\n * - If temporal: true → valid_from, valid_to, is_current\n * - If sourced: true → source, confidence\n */\nexport function getReservedColumnNames(config: RelationshipConfig): Set<string> {\n\tconst { fromColumn, toColumn } = deriveRelationshipFKColumns(config);\n\tconst reserved = new Set([\n\t\t'id',\n\t\t'created_at',\n\t\t'updated_at',\n\t\tfromColumn,\n\t\ttoColumn,\n\t]);\n\n\tif (config.types) {\n\t\treserved.add('type');\n\t}\n\tif (config.temporal) {\n\t\treserved.add('valid_from');\n\t\treserved.add('valid_to');\n\t\treserved.add('is_current');\n\t}\n\tif (config.sourced) {\n\t\treserved.add('source');\n\t\treserved.add('confidence');\n\t}\n\n\treturn reserved;\n}\n\n// ============================================================================\n// Auto-Generated Field Helpers\n// ============================================================================\n\n/**\n * Derives the FK column names for a relationship.\n *\n * Cross-type (from !== to):\n * from: person, to: organization → person_id, organization_id\n *\n * Self-referential (from === to):\n * from: person, to: person → from_person_id, to_person_id\n */\nexport function deriveRelationshipFKColumns(config: RelationshipConfig): {\n\tfromColumn: string;\n\ttoColumn: string;\n} {\n\tif (config.from === config.to) {\n\t\treturn {\n\t\t\tfromColumn: `from_${config.from}_id`,\n\t\t\ttoColumn: `to_${config.to}_id`,\n\t\t};\n\t}\n\treturn {\n\t\tfromColumn: `${config.from}_id`,\n\t\ttoColumn: `${config.to}_id`,\n\t};\n}\n\n/**\n * Derives the default table name if not explicitly specified.\n * Uses the relationship name + 's' suffix.\n */\nexport function deriveTableName(config: RelationshipConfig): string {\n\treturn config.table ?? `${config.name}s`;\n}\n\n/**\n * Collects all type names from a types declaration.\n * Handles both simple list and object map forms.\n */\nexport function collectTypeNames(\n\ttypes: RelationshipTypes | undefined,\n): string[] {\n\tif (!types) return [];\n\tif (Array.isArray(types)) return types;\n\treturn Object.keys(types);\n}\n\n/**\n * Collects all inverse type names from a types declaration.\n * Only applicable for object map form with inverse metadata.\n */\nexport function collectInverseNames(\n\ttypes: RelationshipTypes | undefined,\n): string[] {\n\tif (!types || Array.isArray(types)) return [];\n\treturn Object.values(types)\n\t\t.map((dir) => (dir as TypeDirection & { inverse?: string }).inverse)\n\t\t.filter((v): v is string => v !== undefined);\n}\n\n/**\n * Determines the default unique constraint columns.\n *\n * Logic:\n * - Typed + temporal: [from_id, to_id, type, valid_from]\n * - Typed: [from_id, to_id, type]\n * - Untyped: [from_id, to_id]\n */\nexport function deriveUniqueConstraint(config: RelationshipConfig): string[] {\n\tif (config.unique_on) return config.unique_on;\n\n\tconst { fromColumn, toColumn } = deriveRelationshipFKColumns(config);\n\tconst columns = [fromColumn, toColumn];\n\n\tif (config.types) {\n\t\tcolumns.push('type');\n\t}\n\tif (config.temporal && config.types) {\n\t\tcolumns.push('valid_from');\n\t}\n\n\treturn columns;\n}\n","/**\n * Graph Builder\n *\n * Builds a domain graph from parsed entities, including nodes and edges.\n * Tracks bidirectional connections between entities.\n */\n\nimport type {\n\tParsedEntity,\n\tParsedRelationship,\n\tParsedRelationshipDefinition,\n\tDomainGraph,\n\tRelationshipEdge,\n\tEntityNode,\n} from './types';\n\n/**\n * Infer cardinality from relationship type\n */\nfunction inferCardinality(type: string): '1:1' | '1:N' | 'N:1' | 'N:M' {\n\tswitch (type) {\n\t\tcase 'belongs_to':\n\t\t\treturn 'N:1';\n\t\tcase 'has_many':\n\t\t\treturn '1:N';\n\t\tcase 'has_one':\n\t\t\treturn '1:1';\n\t\tdefault:\n\t\t\treturn '1:N';\n\t}\n}\n\n/**\n * Check if an edge already exists in the opposite direction\n */\nfunction hasReverseEdge(\n\tedges: RelationshipEdge[],\n\tfrom: string,\n\tto: string\n): RelationshipEdge | undefined {\n\treturn edges.find((e) => e.from === to && e.to === from);\n}\n\n/**\n * Build a domain graph from parsed entities\n */\nexport function buildDomainGraph(\n\tentities: ParsedEntity[],\n\trelationshipDefinitions: ParsedRelationshipDefinition[] = [],\n): DomainGraph {\n\tconst entityMap = new Map<string, ParsedEntity>();\n\tconst relDefMap = new Map<string, ParsedRelationshipDefinition>();\n\tconst edges: RelationshipEdge[] = [];\n\n\t// Build entity map\n\tfor (const entity of entities) {\n\t\tentityMap.set(entity.name, entity);\n\t}\n\n\t// Build relationship definition map\n\tfor (const relDef of relationshipDefinitions) {\n\t\trelDefMap.set(relDef.name, relDef);\n\t}\n\n\t// Build edges from inline entity relationships (belongs_to, has_many, has_one)\n\tfor (const entity of entities) {\n\t\tfor (const [relName, rel] of entity.relationships) {\n\t\t\tif (!rel.resolved) continue;\n\n\t\t\t// Check if reverse edge already exists\n\t\t\tconst reverseEdge = hasReverseEdge(edges, entity.name, rel.target);\n\n\t\t\tconst edge: RelationshipEdge = {\n\t\t\t\tfrom: entity.name,\n\t\t\t\tto: rel.target,\n\t\t\t\trelationship: rel,\n\t\t\t\tcardinality: inferCardinality(rel.type),\n\t\t\t\tbidirectional: reverseEdge !== undefined,\n\t\t\t};\n\n\t\t\t// Mark reverse edge as bidirectional too\n\t\t\tif (reverseEdge) {\n\t\t\t\treverseEdge.bidirectional = true;\n\t\t\t}\n\n\t\t\tedges.push(edge);\n\t\t}\n\t}\n\n\t// Build edges from first-class relationship definitions (junction entities)\n\tfor (const relDef of relationshipDefinitions) {\n\t\tconst fromExists = entityMap.has(relDef.from);\n\t\tconst toExists = entityMap.has(relDef.to);\n\n\t\tif (fromExists && toExists) {\n\t\t\t// Create an N:M edge — junction tables are always many-to-many\n\t\t\tconst edge: RelationshipEdge = {\n\t\t\t\tfrom: relDef.from,\n\t\t\t\tto: relDef.to,\n\t\t\t\trelationship: {\n\t\t\t\t\tname: relDef.name,\n\t\t\t\t\ttype: 'has_many',\n\t\t\t\t\ttarget: relDef.to,\n\t\t\t\t\tforeignKey: relDef.fromColumn,\n\t\t\t\t\tresolved: true,\n\t\t\t\t},\n\t\t\t\tcardinality: 'N:M',\n\t\t\t\tbidirectional: relDef.types.some((t) => t.bidirectional),\n\t\t\t};\n\n\t\t\tedges.push(edge);\n\t\t}\n\t}\n\n\treturn { entities: entityMap, relationshipDefinitions: relDefMap, edges };\n}\n\n/**\n * Get all entities related to a given entity within a specified depth\n */\nexport function getRelatedEntities(\n\tgraph: DomainGraph,\n\tentityName: string,\n\tdepth = 1\n): Set<string> {\n\tconst related = new Set<string>();\n\tconst visited = new Set<string>();\n\tconst queue: Array<{ name: string; currentDepth: number }> = [\n\t\t{ name: entityName, currentDepth: 0 },\n\t];\n\n\twhile (queue.length > 0) {\n\t\tconst item = queue.shift();\n\t\tif (!item) continue;\n\n\t\tconst { name, currentDepth } = item;\n\t\tif (visited.has(name) || currentDepth > depth) continue;\n\t\tvisited.add(name);\n\n\t\tfor (const edge of graph.edges) {\n\t\t\tif (edge.from === name && !visited.has(edge.to)) {\n\t\t\t\trelated.add(edge.to);\n\t\t\t\tqueue.push({ name: edge.to, currentDepth: currentDepth + 1 });\n\t\t\t}\n\t\t\tif (edge.to === name && !visited.has(edge.from)) {\n\t\t\t\trelated.add(edge.from);\n\t\t\t\tqueue.push({ name: edge.from, currentDepth: currentDepth + 1 });\n\t\t\t}\n\t\t}\n\t}\n\n\treturn related;\n}\n\n/**\n * Find entities with no relationships (orphans)\n */\nexport function findOrphanEntities(graph: DomainGraph): string[] {\n\tconst orphans: string[] = [];\n\tfor (const [name] of graph.entities) {\n\t\tconst hasRelationship = graph.edges.some((e) => e.from === name || e.to === name);\n\t\tif (!hasRelationship) {\n\t\t\torphans.push(name);\n\t\t}\n\t}\n\treturn orphans;\n}\n\n/**\n * Find circular dependencies in the graph\n */\nexport function findCircularDependencies(graph: DomainGraph): string[][] {\n\tconst cycles: string[][] = [];\n\tconst visited = new Set<string>();\n\tconst recursionStack = new Set<string>();\n\n\tfunction dfs(node: string, path: string[]): void {\n\t\tvisited.add(node);\n\t\trecursionStack.add(node);\n\n\t\tconst outgoingEdges = graph.edges.filter((e) => e.from === node);\n\t\tfor (const edge of outgoingEdges) {\n\t\t\tif (!visited.has(edge.to)) {\n\t\t\t\tdfs(edge.to, [...path, edge.to]);\n\t\t\t} else if (recursionStack.has(edge.to)) {\n\t\t\t\t// Found cycle\n\t\t\t\tconst cycleStart = path.indexOf(edge.to);\n\t\t\t\tif (cycleStart !== -1) {\n\t\t\t\t\tcycles.push([...path.slice(cycleStart), edge.to]);\n\t\t\t\t} else {\n\t\t\t\t\t// The cycle starts at edge.to which is in the recursion stack\n\t\t\t\t\tcycles.push([...path, edge.to]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trecursionStack.delete(node);\n\t}\n\n\tfor (const [name] of graph.entities) {\n\t\tif (!visited.has(name)) {\n\t\t\tdfs(name, [name]);\n\t\t}\n\t}\n\n\t// Deduplicate cycles (same cycle can be detected from different starting points)\n\tconst uniqueCycles: string[][] = [];\n\tconst seen = new Set<string>();\n\n\tfor (const cycle of cycles) {\n\t\t// Normalize cycle by rotating to start with smallest element\n\t\tconst minIndex = cycle.indexOf(\n\t\t\tcycle.reduce((min, val) => (val < min ? val : min), cycle[0])\n\t\t);\n\t\tconst normalized = [...cycle.slice(minIndex), ...cycle.slice(0, minIndex)];\n\t\tconst key = normalized.join('->');\n\n\t\tif (!seen.has(key)) {\n\t\t\tseen.add(key);\n\t\t\tuniqueCycles.push(cycle);\n\t\t}\n\t}\n\n\treturn uniqueCycles;\n}\n\n/**\n * Build entity nodes for visualization\n */\nexport function buildEntityNodes(graph: DomainGraph): EntityNode[] {\n\tconst nodes: EntityNode[] = [];\n\tfor (const [name, entity] of graph.entities) {\n\t\tnodes.push({\n\t\t\tid: name,\n\t\t\tname: entity.name,\n\t\t\tentity,\n\t\t});\n\t}\n\treturn nodes;\n}\n","/**\n * External ID Tracking Behavior\n *\n * Adds external_id, provider, and provider_metadata fields to track\n * records that are synced from external systems (e.g., Salesforce, HubSpot).\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const externalIdTrackingBehavior: BehaviorDefinition = {\n\tname: 'external_id_tracking',\n\tdescription: 'Adds external_id, provider, and provider_metadata fields for external system sync tracking',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'external_id',\n\t\t\tcamelName: 'externalId',\n\t\t\ttype: 'string',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'varchar',\n\t\t\tdrizzleImports: ['varchar', 'index'],\n\t\t\tzodType: 'z.string().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'External ID',\n\t\t\t\ttype: 'text',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'provider',\n\t\t\tcamelName: 'provider',\n\t\t\ttype: 'string',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'varchar',\n\t\t\tdrizzleImports: ['varchar'],\n\t\t\tzodType: 'z.string().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'Provider',\n\t\t\t\ttype: 'text',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'provider_metadata',\n\t\t\tcamelName: 'providerMetadata',\n\t\t\ttype: 'json',\n\t\t\ttsType: 'unknown | null',\n\t\t\tdrizzleType: 'jsonb',\n\t\t\tdrizzleImports: ['jsonb'],\n\t\t\tzodType: 'z.unknown().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'Provider Metadata',\n\t\t\t\ttype: 'json',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['varchar', 'jsonb', 'index'],\n\n\tconfigKey: 'externalIdTracking',\n};\n","/**\n * Soft Delete Behavior\n *\n * Adds deleted_at field for soft delete functionality.\n * Records are marked as deleted instead of being removed from the database.\n * BaseRepository automatically filters soft-deleted records in queries.\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const softDeleteBehavior: BehaviorDefinition = {\n\tname: 'soft_delete',\n\tdescription: 'Adds deleted_at field for soft delete functionality',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'deleted_at',\n\t\t\tcamelName: 'deletedAt',\n\t\t\ttype: 'datetime',\n\t\t\ttsType: 'Date | null',\n\t\t\tdrizzleType: 'timestamp',\n\t\t\tdrizzleImports: ['timestamp'],\n\t\t\tzodType: 'z.coerce.date().nullable()',\n\t\t\tnullable: true,\n\t\t\tui: {\n\t\t\t\tlabel: 'Deleted At',\n\t\t\t\ttype: 'datetime',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['timestamp'],\n\n\tmethods: [\n\t\t'softDelete',\n\t\t'restore',\n\t\t'findWithDeleted',\n\t\t'findOnlyDeleted',\n\t\t'baseQuery', // Modified to filter deleted records\n\t],\n\n\tconfigKey: 'softDelete',\n};\n","/**\n * Timestamps Behavior\n *\n * Adds created_at and updated_at fields to track entity lifecycle.\n * These fields are automatically managed by BaseRepository.\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const timestampsBehavior: BehaviorDefinition = {\n\tname: 'timestamps',\n\tdescription: 'Adds created_at and updated_at timestamp fields',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'created_at',\n\t\t\tcamelName: 'createdAt',\n\t\t\ttype: 'datetime',\n\t\t\ttsType: 'Date',\n\t\t\tdrizzleType: 'timestamp',\n\t\t\tdrizzleImports: ['timestamp'],\n\t\t\tzodType: 'z.coerce.date()',\n\t\t\tnullable: false,\n\t\t\tdefault: 'now()',\n\t\t\tui: {\n\t\t\t\tlabel: 'Created At',\n\t\t\t\ttype: 'datetime',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'updated_at',\n\t\t\tcamelName: 'updatedAt',\n\t\t\ttype: 'datetime',\n\t\t\ttsType: 'Date',\n\t\t\tdrizzleType: 'timestamp',\n\t\t\tdrizzleImports: ['timestamp'],\n\t\t\tzodType: 'z.coerce.date()',\n\t\t\tnullable: false,\n\t\t\tdefault: 'now()',\n\t\t\tui: {\n\t\t\t\tlabel: 'Updated At',\n\t\t\t\ttype: 'datetime',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['timestamp'],\n\n\tmethods: ['applyTimestampsOnCreate', 'applyTimestampsOnUpdate'],\n\n\tconfigKey: 'timestamps',\n};\n","/**\n * User Tracking Behavior\n *\n * Adds created_by and updated_by fields to track which user\n * created and last modified an entity.\n * These fields are automatically managed by BaseRepository when\n * a RepositoryContext with userId is provided.\n */\n\nimport type { BehaviorDefinition } from './types';\n\nexport const userTrackingBehavior: BehaviorDefinition = {\n\tname: 'user_tracking',\n\tdescription: 'Adds created_by and updated_by user reference fields',\n\n\tfields: [\n\t\t{\n\t\t\tname: 'created_by',\n\t\t\tcamelName: 'createdBy',\n\t\t\ttype: 'uuid',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'uuid',\n\t\t\tdrizzleImports: ['uuid'],\n\t\t\tzodType: 'z.string().uuid().nullable()',\n\t\t\tnullable: true,\n\t\t\tforeignKey: 'users.id',\n\t\t\tui: {\n\t\t\t\tlabel: 'Created By',\n\t\t\t\ttype: 'reference',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: 'updated_by',\n\t\t\tcamelName: 'updatedBy',\n\t\t\ttype: 'uuid',\n\t\t\ttsType: 'string | null',\n\t\t\tdrizzleType: 'uuid',\n\t\t\tdrizzleImports: ['uuid'],\n\t\t\tzodType: 'z.string().uuid().nullable()',\n\t\t\tnullable: true,\n\t\t\tforeignKey: 'users.id',\n\t\t\tui: {\n\t\t\t\tlabel: 'Updated By',\n\t\t\t\ttype: 'reference',\n\t\t\t\timportance: 'tertiary',\n\t\t\t\tgroup: 'metadata',\n\t\t\t\tvisible: false,\n\t\t\t},\n\t\t},\n\t],\n\n\tdrizzleImports: ['uuid'],\n\n\tmethods: ['applyUserTrackingOnCreate', 'applyUserTrackingOnUpdate'],\n\n\tconfigKey: 'userTracking',\n};\n","/**\n * Behavior Registry - Central registry for all entity behaviors\n *\n * Provides functions to:\n * - Get behavior definitions by name\n * - Validate behavior configurations\n * - Resolve fields added by behaviors\n */\n\nimport { externalIdTrackingBehavior } from './external-id-tracking';\nimport { softDeleteBehavior } from './soft-delete';\nimport { timestampsBehavior } from './timestamps';\nimport type {\n\tBehaviorConfig,\n\tBehaviorDefinition,\n\tBehaviorField,\n\tNormalizedBehaviorConfig,\n\tResolvedBehaviors,\n\tValidationResult,\n} from './types';\nimport { userTrackingBehavior } from './user-tracking';\n\n// ============================================================================\n// Behavior Registry\n// ============================================================================\n\nconst behaviorRegistry = new Map<string, BehaviorDefinition>([\n\t['timestamps', timestampsBehavior],\n\t['soft_delete', softDeleteBehavior],\n\t['user_tracking', userTrackingBehavior],\n\t['external_id_tracking', externalIdTrackingBehavior],\n]);\n\n/**\n * Get a behavior definition by name\n */\nexport function getBehavior(name: string): BehaviorDefinition | undefined {\n\treturn behaviorRegistry.get(name);\n}\n\n/**\n * Get all registered behavior names\n */\nexport function getAllBehaviorNames(): string[] {\n\treturn Array.from(behaviorRegistry.keys());\n}\n\n// ============================================================================\n// Config Normalization\n// ============================================================================\n\n/**\n * Normalize a behavior config to always have name and options\n */\nexport function normalizeBehaviorConfig(\n\tconfig: BehaviorConfig,\n): NormalizedBehaviorConfig {\n\tif (typeof config === 'string') {\n\t\treturn { name: config, options: {} };\n\t}\n\treturn { name: config.name, options: config.options ?? {} };\n}\n\n/**\n * Normalize an array of behavior configs\n */\nexport function normalizeBehaviorConfigs(\n\tconfigs: BehaviorConfig[],\n): NormalizedBehaviorConfig[] {\n\treturn configs.map(normalizeBehaviorConfig);\n}\n\n// ============================================================================\n// Validation\n// ============================================================================\n\n/**\n * Validate a set of behavior configurations\n * Checks for unknown behaviors, missing dependencies, and conflicts\n */\nexport function validateBehaviors(configs: BehaviorConfig[]): ValidationResult {\n\tconst errors: string[] = [];\n\tconst warnings: string[] = [];\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst enabledNames = new Set(normalized.map((c) => c.name));\n\n\tfor (const config of normalized) {\n\t\tconst behavior = getBehavior(config.name);\n\n\t\t// Check behavior exists\n\t\tif (!behavior) {\n\t\t\terrors.push(`Unknown behavior: '${config.name}'`);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Check dependencies\n\t\tif (behavior.requires) {\n\t\t\tfor (const req of behavior.requires) {\n\t\t\t\tif (!enabledNames.has(req)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Behavior '${config.name}' requires '${req}' which is not enabled`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check conflicts\n\t\tif (behavior.conflicts) {\n\t\t\tfor (const conflict of behavior.conflicts) {\n\t\t\t\tif (enabledNames.has(conflict)) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Behavior '${config.name}' conflicts with '${conflict}'`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t\twarnings,\n\t};\n}\n\n// ============================================================================\n// Field Resolution\n// ============================================================================\n\n/**\n * Get all fields added by a set of behaviors\n */\nexport function resolveBehaviorFields(\n\tconfigs: BehaviorConfig[],\n): BehaviorField[] {\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst fields: BehaviorField[] = [];\n\tconst addedFieldNames = new Set<string>();\n\n\tfor (const config of normalized) {\n\t\tconst behavior = getBehavior(config.name);\n\t\tif (!behavior) continue;\n\n\t\tfor (const field of behavior.fields) {\n\t\t\t// Avoid duplicate fields if multiple behaviors add the same field\n\t\t\tif (!addedFieldNames.has(field.name)) {\n\t\t\t\tfields.push(field);\n\t\t\t\taddedFieldNames.add(field.name);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fields;\n}\n\n/**\n * Get all Drizzle imports needed by a set of behaviors\n */\nexport function resolveBehaviorDrizzleImports(\n\tconfigs: BehaviorConfig[],\n): string[] {\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst imports = new Set<string>();\n\n\tfor (const config of normalized) {\n\t\tconst behavior = getBehavior(config.name);\n\t\tif (!behavior) continue;\n\n\t\tfor (const imp of behavior.drizzleImports) {\n\t\t\timports.add(imp);\n\t\t}\n\t}\n\n\treturn Array.from(imports).sort();\n}\n\n// ============================================================================\n// Full Resolution\n// ============================================================================\n\n/**\n * Resolve all behavior data for templates\n */\nexport function resolveBehaviors(configs: BehaviorConfig[]): ResolvedBehaviors {\n\tconst normalized = normalizeBehaviorConfigs(configs);\n\tconst fields = resolveBehaviorFields(configs);\n\tconst drizzleImports = resolveBehaviorDrizzleImports(configs);\n\n\tconst enabledNames = new Set(normalized.map((c) => c.name));\n\n\tconst hasTimestamps = enabledNames.has('timestamps');\n\tconst hasSoftDelete = enabledNames.has('soft_delete');\n\tconst hasUserTracking = enabledNames.has('user_tracking');\n\tconst hasExternalIdTracking = enabledNames.has('external_id_tracking');\n\n\treturn {\n\t\tconfigs: normalized,\n\t\tfields,\n\t\tdrizzleImports,\n\t\trepositoryConfig: {\n\t\t\ttimestamps: hasTimestamps,\n\t\t\tsoftDelete: hasSoftDelete,\n\t\t\tuserTracking: hasUserTracking,\n\t\t\tversionable: false, // Future behavior\n\t\t},\n\t\thasBehaviors: normalized.length > 0,\n\t\thasTimestamps,\n\t\thasSoftDelete,\n\t\thasUserTracking,\n\t\thasExternalIdTracking,\n\t};\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport type {\n\tBehaviorConfig,\n\tBehaviorDefinition,\n\tBehaviorField,\n\tNormalizedBehaviorConfig,\n\tResolvedBehaviors,\n\tValidationResult,\n} from './types';\n\nexport { timestampsBehavior } from './timestamps';\nexport { softDeleteBehavior } from './soft-delete';\nexport { userTrackingBehavior } from './user-tracking';\nexport { externalIdTrackingBehavior } from './external-id-tracking';\n","/**\n * Consistency Checker\n *\n * Performs various consistency checks on the domain model:\n * - Missing relationship targets\n * - Missing inverse relationships\n * - Missing indexes on filterable fields\n * - Orphan entities (no relationships)\n * - Circular dependencies\n * - Naming conventions\n * - Missing UI metadata\n */\n\nimport type { ParsedEntity, DomainGraph, AnalysisIssue } from './types';\nimport { findOrphanEntities, findCircularDependencies } from './graph-builder';\nimport { resolveBehaviorFields } from '../behaviors/index';\n\n/**\n * Run all consistency checks on the domain graph\n */\nexport function checkConsistency(graph: DomainGraph): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Check each entity\n\tfor (const [name, entity] of graph.entities) {\n\t\tissues.push(...checkEntityConsistency(entity));\n\t\tissues.push(...checkRelationshipConsistency(entity, graph));\n\t\tissues.push(...checkNamingConventions(entity));\n\t\tissues.push(...checkMissingIndexes(entity));\n\t\tissues.push(...checkUiMetadata(entity));\n\t\tif (entity.queries !== undefined) {\n\t\t\tissues.push(...checkQueryFieldReferences(entity));\n\t\t}\n\t\tif (entity.sync !== undefined) {\n\t\t\tissues.push(...checkSyncFieldMappingReferences(entity));\n\t\t\tissues.push(...checkExternalIdTrackingCollision(entity));\n\t\t}\n\t}\n\n\t// Check graph-level issues\n\tissues.push(...checkOrphanEntities(graph));\n\tissues.push(...checkCircularReferences(graph));\n\tissues.push(...checkMissingInverses(graph));\n\n\treturn issues;\n}\n\n/**\n * Check entity-level consistency\n */\nfunction checkEntityConsistency(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Check for missing primary key\n\tif (!entity.fields.has('id')) {\n\t\tissues.push({\n\t\t\tseverity: 'info',\n\t\t\ttype: 'missing_id',\n\t\t\tentity: entity.name,\n\t\t\tmessage: 'Entity missing standard \"id\" field',\n\t\t\tsuggestion: 'Add an \"id\" field with type \"uuid\"',\n\t\t});\n\t}\n\n\t// Check for missing timestamps\n\tconst hasCreatedAt = entity.fields.has('created_at');\n\tconst hasTimestampsBehavior = entity.behaviors.includes('timestamps');\n\n\tif (!hasCreatedAt && !hasTimestampsBehavior) {\n\t\tissues.push({\n\t\t\tseverity: 'info',\n\t\t\ttype: 'missing_timestamps',\n\t\t\tentity: entity.name,\n\t\t\tmessage: 'Entity missing \"created_at\" field and \"timestamps\" behavior',\n\t\t\tsuggestion: 'Add \"timestamps\" to behaviors or add created_at/updated_at fields',\n\t\t});\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check relationship consistency\n */\nfunction checkRelationshipConsistency(\n\tentity: ParsedEntity,\n\tgraph: DomainGraph\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tfor (const [relName, rel] of entity.relationships) {\n\t\t// Check for belongs_to without matching foreign key field\n\t\tif (rel.type === 'belongs_to') {\n\t\t\tconst fkField = entity.fields.get(rel.foreignKey);\n\t\t\tif (!fkField) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'missing_fk_field',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: relName,\n\t\t\t\t\tmessage: `Relationship \"${relName}\" references foreign key \"${rel.foreignKey}\" but field doesn't exist`,\n\t\t\t\t\tsuggestion: `Add field \"${rel.foreignKey}\" with foreign_key reference`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Check for has_many relationships - target should have the FK field\n\t\tif (rel.type === 'has_many' || rel.type === 'has_one') {\n\t\t\tconst targetEntity = graph.entities.get(rel.target);\n\t\t\tif (targetEntity) {\n\t\t\t\tconst targetFkField = targetEntity.fields.get(rel.foreignKey);\n\t\t\t\tif (!targetFkField) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\t\ttype: 'missing_target_fk',\n\t\t\t\t\t\tentity: entity.name,\n\t\t\t\t\t\tfield: relName,\n\t\t\t\t\t\tmessage: `Relationship \"${relName}\" expects foreign key \"${rel.foreignKey}\" on \"${rel.target}\" but field doesn't exist`,\n\t\t\t\t\t\tsuggestion: `Add field \"${rel.foreignKey}\" to \"${rel.target}\" entity`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check naming conventions\n */\nfunction checkNamingConventions(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Entity name should be lowercase snake_case\n\tif (entity.name !== entity.name.toLowerCase()) {\n\t\tissues.push({\n\t\t\tseverity: 'warning',\n\t\t\ttype: 'naming_convention',\n\t\t\tentity: entity.name,\n\t\t\tmessage: 'Entity name should be lowercase',\n\t\t\tsuggestion: `Use \"${entity.name.toLowerCase()}\"`,\n\t\t});\n\t}\n\n\t// Check field naming\n\tfor (const [fieldName] of entity.fields) {\n\t\tif (fieldName !== fieldName.toLowerCase()) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'naming_convention',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: 'Field name should be snake_case',\n\t\t\t\tsuggestion: `Use \"${toSnakeCase(fieldName)}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Check relationship naming\n\tfor (const [relName] of entity.relationships) {\n\t\tif (relName !== relName.toLowerCase()) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'naming_convention',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: relName,\n\t\t\t\tmessage: 'Relationship name should be snake_case',\n\t\t\t\tsuggestion: `Use \"${toSnakeCase(relName)}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for missing indexes on filterable fields\n */\nfunction checkMissingIndexes(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tfor (const [fieldName, field] of entity.fields) {\n\t\t// Check if field is marked as filterable but has no index\n\t\tif (field.ui.filterable && !field.index && !field.unique) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'missing_index',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: `Field \"${fieldName}\" is filterable but has no index`,\n\t\t\t\tsuggestion: 'Add \"index: true\" to improve query performance',\n\t\t\t});\n\t\t}\n\n\t\t// Foreign key fields should typically have an index\n\t\tif (field.foreignKey && !field.index && !field.unique) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'info',\n\t\t\t\ttype: 'missing_fk_index',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: `Foreign key field \"${fieldName}\" has no index`,\n\t\t\t\tsuggestion: 'Add \"index: true\" for better join performance',\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for missing UI metadata\n */\nfunction checkUiMetadata(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// System fields that don't need UI metadata\n\tconst systemFields = new Set(['id', 'created_at', 'updated_at', 'deleted_at', 'tenant_id']);\n\n\tfor (const [fieldName, field] of entity.fields) {\n\t\tif (systemFields.has(fieldName)) continue;\n\n\t\tconst hasAnyUiMeta =\n\t\t\tfield.ui.label !== undefined ||\n\t\t\tfield.ui.type !== undefined ||\n\t\t\tfield.ui.group !== undefined;\n\n\t\tif (!hasAnyUiMeta) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'info',\n\t\t\t\ttype: 'missing_ui_metadata',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: fieldName,\n\t\t\t\tmessage: `Field \"${fieldName}\" has no UI metadata`,\n\t\t\t\tsuggestion: 'Add ui_label, ui_type, ui_group for better admin panel display',\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for orphan entities\n */\nfunction checkOrphanEntities(graph: DomainGraph): AnalysisIssue[] {\n\tconst orphans = findOrphanEntities(graph);\n\treturn orphans.map((name) => ({\n\t\tseverity: 'info' as const,\n\t\ttype: 'orphan_entity',\n\t\tentity: name,\n\t\tmessage: `Entity \"${name}\" has no relationships to other entities`,\n\t\tsuggestion: 'Consider if this entity should be related to others',\n\t}));\n}\n\n/**\n * Check for circular references\n */\nfunction checkCircularReferences(graph: DomainGraph): AnalysisIssue[] {\n\tconst cycles = findCircularDependencies(graph);\n\treturn cycles.map((cycle) => ({\n\t\tseverity: 'info' as const,\n\t\ttype: 'circular_dependency',\n\t\tentity: cycle[0],\n\t\tmessage: `Circular reference detected: ${cycle.join(' -> ')}`,\n\t\tsuggestion: 'Verify this is intentional (e.g., self-referential hierarchy)',\n\t}));\n}\n\n/**\n * Check for missing inverse relationships\n */\nfunction checkMissingInverses(graph: DomainGraph): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tfor (const edge of graph.edges) {\n\t\tconst { from, to, relationship } = edge;\n\t\tconst targetEntity = graph.entities.get(to);\n\t\tif (!targetEntity) continue;\n\n\t\t// Check if target has an inverse relationship back to source\n\t\tconst hasInverse = Array.from(targetEntity.relationships.values()).some(\n\t\t\t(rel) => rel.target === from\n\t\t);\n\n\t\t// belongs_to relationships typically don't need explicit inverses\n\t\t// (the has_many on the other side serves as the inverse)\n\t\tif (!hasInverse && relationship.type !== 'belongs_to') {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'info',\n\t\t\t\ttype: 'missing_inverse',\n\t\t\t\tentity: from,\n\t\t\t\tfield: relationship.name,\n\t\t\t\tmessage: `Relationship \"${relationship.name}\" to \"${to}\" has no inverse defined on target`,\n\t\t\t\tsuggestion: `Add inverse relationship on \"${to}\" pointing back to \"${from}\"`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Get the set of all valid field names for an entity, including behavior-added fields\n * and belongs_to foreign key fields (which the template emits as columns even when\n * not explicitly declared under `fields:`).\n */\nfunction getAvailableFieldNames(entity: ParsedEntity): string[] {\n\tconst entityFieldNames = Array.from(entity.fields.keys());\n\tconst behaviorFields = resolveBehaviorFields(entity.behaviors);\n\tconst behaviorFieldNames = behaviorFields.map((f) => f.name);\n\tconst belongsToFkNames: string[] = [];\n\tfor (const rel of entity.relationships.values()) {\n\t\tif (rel.type === 'belongs_to' && rel.foreignKey) {\n\t\t\tbelongsToFkNames.push(rel.foreignKey);\n\t\t}\n\t}\n\treturn [...new Set([...entityFieldNames, ...behaviorFieldNames, ...belongsToFkNames])];\n}\n\n/**\n * Check that query.by and query.select fields reference existing entity fields\n */\nfunction checkQueryFieldReferences(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst availableFields = getAvailableFieldNames(entity);\n\tconst availableSet = new Set(availableFields);\n\n\tfor (const query of entity.queries ?? []) {\n\t\t// Skip by-field validation when via is specified — those fields come from the junction table\n\t\tif (!query.via) {\n\t\t\tfor (const fieldName of query.by) {\n\t\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tseverity: 'error',\n\t\t\t\t\t\ttype: 'unknown_query_field',\n\t\t\t\t\t\tentity: entity.name,\n\t\t\t\t\t\tfield: fieldName,\n\t\t\t\t\t\tmessage: `Query references unknown field \"${fieldName}\" in entity \"${entity.name}\". Available fields: ${availableFields.join(', ')}`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const fieldName of query.select ?? []) {\n\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'unknown_query_field',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t\tmessage: `Query references unknown field \"${fieldName}\" in entity \"${entity.name}\". Available fields: ${availableFields.join(', ')}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check that sync field_mapping keys and read_only_fields reference existing entity fields\n */\nfunction checkSyncFieldMappingReferences(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\tconst availableFields = getAvailableFieldNames(entity);\n\tconst availableSet = new Set(availableFields);\n\n\tfor (const [providerName, provider] of Object.entries(entity.sync?.providers ?? {})) {\n\t\tfor (const fieldName of Object.keys(provider.fieldMapping ?? {})) {\n\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'unknown_sync_field_mapping',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t\tmessage: `Sync field mapping references unknown field \"${fieldName}\" for provider \"${providerName}\" in entity \"${entity.name}\"`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tfor (const fieldName of provider.readOnlyFields ?? []) {\n\t\t\tif (!availableSet.has(fieldName)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'unknown_sync_field_mapping',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tfield: fieldName,\n\t\t\t\t\tmessage: `Sync field mapping references unknown field \"${fieldName}\" for provider \"${providerName}\" in entity \"${entity.name}\"`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Check for potential collision between external_id_tracking behavior and sync field_mapping\n */\nfunction checkExternalIdTrackingCollision(entity: ParsedEntity): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tconst hasExternalIdTracking = entity.behaviors.includes('external_id_tracking');\n\tif (!hasExternalIdTracking) return issues;\n\n\tfor (const [providerName, provider] of Object.entries(entity.sync?.providers ?? {})) {\n\t\tif (provider.fieldMapping && 'external_id' in provider.fieldMapping) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'external_id_tracking_collision',\n\t\t\t\tentity: entity.name,\n\t\t\t\tfield: 'external_id',\n\t\t\t\tmessage: `Entity \"${entity.name}\" has external_id_tracking behavior and also maps \"external_id\" in sync field_mapping for provider \"${providerName}\". The behavior-added field may collide with the mapped field.`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n/**\n * Convert string to snake_case\n */\nfunction toSnakeCase(str: string): string {\n\treturn str\n\t\t.replace(/([A-Z])/g, '_$1')\n\t\t.toLowerCase()\n\t\t.replace(/^_/, '');\n}\n","/**\n * Statistics\n *\n * Computes statistics about the domain model:\n * - Entity counts\n * - Field counts and type distribution\n * - Relationship counts and type distribution\n */\n\nimport type { ParsedEntity, DomainGraph, DomainStatistics } from './types';\n\n/**\n * Compute domain statistics from the graph\n */\nexport function computeStatistics(graph: DomainGraph): DomainStatistics {\n\tconst entities = Array.from(graph.entities.values());\n\n\tconst fieldsByType: Record<string, number> = {};\n\tconst relationshipsByType: Record<string, number> = {};\n\tlet totalFields = 0;\n\tlet totalRelationships = 0;\n\tlet entitiesWithBehaviors = 0;\n\n\tfor (const entity of entities) {\n\t\ttotalFields += entity.fields.size;\n\t\ttotalRelationships += entity.relationships.size;\n\n\t\tif (entity.behaviors.length > 0) {\n\t\t\tentitiesWithBehaviors++;\n\t\t}\n\n\t\t// Count fields by type\n\t\tfor (const field of entity.fields.values()) {\n\t\t\tfieldsByType[field.type] = (fieldsByType[field.type] ?? 0) + 1;\n\t\t}\n\n\t\t// Count relationships by type\n\t\tfor (const rel of entity.relationships.values()) {\n\t\t\trelationshipsByType[rel.type] = (relationshipsByType[rel.type] ?? 0) + 1;\n\t\t}\n\t}\n\n\treturn {\n\t\ttotalEntities: entities.length,\n\t\ttotalFields,\n\t\ttotalRelationships,\n\t\tfieldsByType,\n\t\trelationshipsByType,\n\t\tentitiesWithBehaviors,\n\t\taverageFieldsPerEntity: entities.length > 0 ? totalFields / entities.length : 0,\n\t};\n}\n\n/**\n * Get a breakdown of field properties\n */\nexport function getFieldBreakdown(graph: DomainGraph): {\n\trequired: number;\n\tnullable: number;\n\tindexed: number;\n\tunique: number;\n\twithForeignKey: number;\n\twithConstraints: number;\n} {\n\tlet required = 0;\n\tlet nullable = 0;\n\tlet indexed = 0;\n\tlet unique = 0;\n\tlet withForeignKey = 0;\n\tlet withConstraints = 0;\n\n\tfor (const entity of graph.entities.values()) {\n\t\tfor (const field of entity.fields.values()) {\n\t\t\tif (field.required) required++;\n\t\t\tif (field.nullable) nullable++;\n\t\t\tif (field.index) indexed++;\n\t\t\tif (field.unique) unique++;\n\t\t\tif (field.foreignKey) withForeignKey++;\n\n\t\t\tconst hasConstraints =\n\t\t\t\tfield.constraints.minLength !== undefined ||\n\t\t\t\tfield.constraints.maxLength !== undefined ||\n\t\t\t\tfield.constraints.min !== undefined ||\n\t\t\t\tfield.constraints.max !== undefined;\n\t\t\tif (hasConstraints) withConstraints++;\n\t\t}\n\t}\n\n\treturn { required, nullable, indexed, unique, withForeignKey, withConstraints };\n}\n\n/**\n * Get UI metadata coverage statistics\n */\nexport function getUiMetadataCoverage(graph: DomainGraph): {\n\twithLabel: number;\n\twithType: number;\n\twithGroup: number;\n\twithImportance: number;\n\ttotal: number;\n} {\n\tlet withLabel = 0;\n\tlet withType = 0;\n\tlet withGroup = 0;\n\tlet withImportance = 0;\n\tlet total = 0;\n\n\tfor (const entity of graph.entities.values()) {\n\t\tfor (const field of entity.fields.values()) {\n\t\t\ttotal++;\n\t\t\tif (field.ui.label) withLabel++;\n\t\t\tif (field.ui.type) withType++;\n\t\t\tif (field.ui.group) withGroup++;\n\t\t\tif (field.ui.importance) withImportance++;\n\t\t}\n\t}\n\n\treturn { withLabel, withType, withGroup, withImportance, total };\n}\n","/**\n * Pattern Registry — library + app pattern storage and discovery.\n *\n * Two stores keyed by pattern name:\n * - `LIBRARY_PATTERNS` — seeded by the codegen package itself when the\n * `src/patterns/library/*` barrel imports execute. Consumers never\n * list these in `codegen.config.yaml patterns:`.\n * - `APP_PATTERNS` — populated by `loadAppPatterns()` from a\n * consumer-supplied glob set (default `src/patterns/*.pattern.ts`).\n *\n * `getPattern()` checks app patterns first so a consumer could, in\n * principle, shadow a library pattern by using the same `name`. That's\n * not a documented feature, but nothing in the API prevents it.\n *\n * The Hygen subprocess (`src/cli/shared/hygen.ts:64`) reloads this module\n * independently — it has no shared memory with the CLI process. Both\n * loads are deterministic, side-effect-free reads of the same files, so\n * the registry contents are identical across processes. The registry\n * test suite asserts this determinism explicitly.\n *\n * See `docs/adrs/ADR-031-app-defined-patterns.md` §\"Decision 5\" and\n * `docs/specs/app-defined-patterns-implementation.md` §3.\n */\n\nimport { glob } from 'glob';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport {\n\tisPatternDefinition,\n\ttype PatternDefinition,\n} from './pattern-definition.js';\n\n// ============================================================================\n// Stores\n// ============================================================================\n\nconst LIBRARY_PATTERNS: Map<string, PatternDefinition> = new Map();\nconst APP_PATTERNS: Map<string, PatternDefinition> = new Map();\n\n/**\n * Every pattern must contribute *something* — either at least one column\n * or at least one of the two class references. A pattern that contributes\n * nothing would generate no useful output and almost certainly indicates\n * a typo or an unfinished definition.\n */\nfunction assertHasContribution(def: PatternDefinition): void {\n\tconst hasColumns = Array.isArray(def.columns) && def.columns.length > 0;\n\tconst hasRepo =\n\t\ttypeof def.repositoryClass === 'string' && def.repositoryClass.length > 0;\n\tconst hasService =\n\t\ttypeof def.serviceClass === 'string' && def.serviceClass.length > 0;\n\n\tif (!hasColumns && !hasRepo && !hasService) {\n\t\tthrow new Error(\n\t\t\t`Pattern '${def.name}' contributes nothing — at least one of ` +\n\t\t\t\t'`columns`, `repositoryClass`, or `serviceClass` is required.',\n\t\t);\n\t}\n}\n\n// ============================================================================\n// Library pattern registration\n// ============================================================================\n\n/**\n * Insert a library pattern into the registry. Called once by each\n * `src/patterns/library/*.pattern.ts` file via the barrel. Re-registering\n * the same name overwrites the previous value silently; this is\n * intentional for hot-reload scenarios but should not happen in normal\n * use.\n */\nexport function registerLibraryPattern(def: PatternDefinition): void {\n\tassertHasContribution(def);\n\tLIBRARY_PATTERNS.set(def.name, def);\n}\n\n// ============================================================================\n// Lookup\n// ============================================================================\n\n/**\n * Resolve a pattern by name. App patterns shadow library patterns with\n * the same name — useful in principle but not a documented feature.\n */\nexport function getPattern(name: string): PatternDefinition | undefined {\n\treturn APP_PATTERNS.get(name) ?? LIBRARY_PATTERNS.get(name);\n}\n\n/**\n * Return every registered pattern name (library + app), sorted for\n * deterministic output. The two-process determinism test relies on this\n * ordering being stable across processes.\n */\nexport function getAllPatternNames(): string[] {\n\tconst set = new Set<string>([\n\t\t...LIBRARY_PATTERNS.keys(),\n\t\t...APP_PATTERNS.keys(),\n\t]);\n\treturn [...set].sort();\n}\n\n/** Library-only view — mainly for debugging and tests. */\nexport function getLibraryPatternNames(): string[] {\n\treturn [...LIBRARY_PATTERNS.keys()].sort();\n}\n\n/** App-only view — mainly for debugging and tests. */\nexport function getAppPatternNames(): string[] {\n\treturn [...APP_PATTERNS.keys()].sort();\n}\n\n// ============================================================================\n// App pattern discovery\n// ============================================================================\n\nexport interface LoadAppPatternsResult {\n\t/** Pattern names that were successfully registered, sorted */\n\tloaded: string[];\n\t/** One human-readable error per failed file import */\n\terrors: string[];\n}\n\n/**\n * Expand every glob in `manifestPaths` relative to `cwd`, dynamic-import\n * each matching file, and register every exported value that passes\n * `isPatternDefinition()`. Exports whose name ends in `Pattern` and\n * pass the shape check are registered; other exports are ignored so\n * that files can export helper values alongside their pattern.\n *\n * Import failures are non-fatal — the error is collected and returned\n * so the CLI can surface it without breaking generation of unrelated\n * entities. A pattern that fails the \"at-least-one-contribution\" check\n * surfaces here as an error too.\n *\n * Idempotent: calling twice with the same arguments leaves `APP_PATTERNS`\n * in the same state as calling once.\n */\nexport async function loadAppPatterns(\n\tmanifestPaths: string[],\n\tcwd: string,\n): Promise<LoadAppPatternsResult> {\n\tconst loaded = new Set<string>();\n\tconst errors: string[] = [];\n\n\t// Collect + dedupe absolute file paths across every glob pattern so\n\t// a file matched by two globs is imported once.\n\tconst files = new Set<string>();\n\tfor (const raw of manifestPaths) {\n\t\ttry {\n\t\t\tconst expanded = await glob(raw, { cwd, absolute: true, nodir: true });\n\t\t\tfor (const filePath of expanded) {\n\t\t\t\tfiles.add(filePath);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\terrors.push(\n\t\t\t\t`Failed to expand pattern glob '${raw}': ${stringifyError(err)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// Sort so dynamic-import order is deterministic across processes —\n\t// the Hygen subprocess relies on this to produce the same registry\n\t// as the CLI.\n\tconst sortedFiles = [...files].sort();\n\n\tfor (const filePath of sortedFiles) {\n\t\ttry {\n\t\t\t// `pathToFileURL` is required for absolute-path dynamic imports on\n\t\t\t// Windows and makes the behavior identical on macOS/Linux.\n\t\t\tconst mod = (await import(pathToFileURL(filePath).href)) as Record<\n\t\t\t\tstring,\n\t\t\t\tunknown\n\t\t\t>;\n\t\t\tfor (const [key, val] of Object.entries(mod)) {\n\t\t\t\tif (!key.endsWith('Pattern')) continue;\n\t\t\t\tif (!isPatternDefinition(val)) continue;\n\t\t\t\ttry {\n\t\t\t\t\tassertHasContribution(val);\n\t\t\t\t\tAPP_PATTERNS.set(val.name, val);\n\t\t\t\t\tloaded.add(val.name);\n\t\t\t\t} catch (assertErr) {\n\t\t\t\t\terrors.push(\n\t\t\t\t\t\t`Pattern '${val.name}' in ${relPath(filePath, cwd)} is invalid: ${stringifyError(assertErr)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (err) {\n\t\t\terrors.push(\n\t\t\t\t`Failed to load pattern file '${relPath(filePath, cwd)}': ${stringifyError(err)}`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn {\n\t\tloaded: [...loaded].sort(),\n\t\terrors,\n\t};\n}\n\n// ============================================================================\n// Test-only reset\n// ============================================================================\n\n/**\n * Clear every registered app pattern and, optionally, library patterns too.\n *\n * Intended for unit tests that build isolated scenarios on top of a clean\n * registry. Not exported from the barrel — tests import it directly from\n * `./registry.js`.\n */\nexport function _resetRegistryForTests(\n\topts: { includeLibrary?: boolean } = {},\n): void {\n\tAPP_PATTERNS.clear();\n\tif (opts.includeLibrary) {\n\t\tLIBRARY_PATTERNS.clear();\n\t}\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction stringifyError(err: unknown): string {\n\tif (err instanceof Error) return err.message;\n\treturn String(err);\n}\n\nfunction relPath(abs: string, cwd: string): string {\n\ttry {\n\t\treturn path.relative(cwd, abs) || abs;\n\t} catch {\n\t\treturn abs;\n\t}\n}\n","/**\n * Pattern Definition — pure metadata record returned by an identity function.\n *\n * `definePattern()` is the registration artifact for both library-shipped and\n * app-defined patterns. It carries only names + import paths for the classes\n * a generated entity should extend — never the class constructors themselves.\n * This keeps the codegen pipeline free of TS class-evaluation cost and avoids\n * `reflect-metadata`, which lets the Hygen subprocess cheaply rebuild the\n * registry (see `src/cli/shared/hygen.ts` — the registry loads twice per\n * `entity new` invocation).\n *\n * See `docs/adrs/ADR-031-app-defined-patterns.md` §\"Decision 1\" for the\n * binding surface and `docs/specs/app-defined-patterns-implementation.md` §1\n * for the file-by-file rationale.\n */\n\nimport type { ZodSchema } from 'zod';\n\n/**\n * A column a pattern contributes to every entity that declares it.\n *\n * Column-level conflicts between patterns, between a pattern and an\n * entity-declared field, or between a pattern and a behavior-contributed\n * field are codegen-time hard errors; see\n * `src/patterns/validate-composition.ts`.\n */\nexport interface PatternColumnContribution {\n\t/** snake_case column name — matches the database column */\n\tname: string;\n\t/** Drizzle column type string, e.g. \"varchar(255)\" or \"text\" */\n\ttype: string;\n}\n\n/**\n * The full pattern metadata record. Every `definePattern({...})` call\n * returns a value of this shape; the library and consumer registries\n * store these and look them up by `name`.\n */\nexport interface PatternDefinition<TConfig = unknown> {\n\t/** Unique name used in YAML — e.g. `pattern: Synced` */\n\tname: string;\n\n\t/**\n\t * Built-in patterns this extends, by name. Phase 1 supports single-depth\n\t * chains only — a pattern may `extends: ['Synced']` but the transitive\n\t * chain is not yet resolved. Multi-depth inheritance is deferred until\n\t * a real consumer asks.\n\t */\n\textends?: string[];\n\n\t/** Constructor name codegen emits in the generated repo's `extends` clause */\n\trepositoryClass?: string;\n\t/** Constructor name codegen emits in the generated service's `extends` clause */\n\tserviceClass?: string;\n\n\t/**\n\t * Fully-qualified TypeScript path alias the consumer's tsconfig resolves.\n\t * Library patterns use the consumer-installed runtime base class path\n\t * (e.g. `@shared/base-classes/synced-entity-repository`); app patterns\n\t * use whatever alias the consumer has configured (e.g. `@/patterns/...`).\n\t */\n\trepositoryImport?: string;\n\t/** Same as `repositoryImport` but for the service base class */\n\tserviceImport?: string;\n\n\t/**\n\t * Documentation-only method-signature strings emitted as comments in the\n\t * generated repo. Exist purely so app authors reading the generated file\n\t * see what their concrete class inherits without jumping to the base.\n\t */\n\trepositoryInheritedMethods?: string[];\n\t/** Same as `repositoryInheritedMethods` but for the service base class */\n\tserviceInheritedMethods?: string[];\n\n\t/**\n\t * Columns this pattern adds to every entity that declares it. Used by\n\t * the composition validator to detect column-name collisions.\n\t */\n\tcolumns?: PatternColumnContribution[];\n\n\t/**\n\t * Behaviors this pattern implicitly enables. Entity YAML need not\n\t * re-declare them; duplicates across patterns are silent-deduped.\n\t */\n\timpliedBehaviors?: string[];\n\n\t/**\n\t * Zod schema that validates the per-entity `config:` block for this\n\t * pattern at parse time. When absent, entities may not supply a `config:`\n\t * entry for this pattern and codegen emits no `patternConfig` property.\n\t */\n\tconfigSchema?: ZodSchema<TConfig>;\n\n\t/** One-line description for codegen help output and error messages */\n\tdescription?: string;\n}\n\n/**\n * Identity function that returns its argument unchanged. The body is trivial\n * on purpose — the whole point is to give TypeScript a hook for generic\n * inference on `TConfig` while leaving the runtime value a plain object\n * registered by the codegen loader.\n */\nexport function definePattern<TConfig = unknown>(\n\tdef: PatternDefinition<TConfig>,\n): PatternDefinition<TConfig> {\n\treturn def;\n}\n\n/**\n * Shape check for values produced by `import()`ing an app pattern file.\n * The registry loader runs this on every exported value it finds; only\n * values that pass are registered.\n *\n * We keep this deliberately loose — a `name` string is the whole\n * requirement — because a pattern that contributes neither columns nor\n * class references is still a *valid* identity pattern (e.g. `BasePattern`\n * exists to anchor the `extends` chain without contributing anything).\n * Stricter shape rules belong in the registry's \"at-least-one-contribution\"\n * check, not here.\n */\nexport function isPatternDefinition(val: unknown): val is PatternDefinition {\n\treturn (\n\t\ttypeof val === 'object' &&\n\t\tval !== null &&\n\t\t'name' in val &&\n\t\ttypeof (val as { name: unknown }).name === 'string'\n\t);\n}\n","/**\n * Pattern Composition Validator\n *\n * Enforces the ADR-031 composition rules against parsed entities:\n *\n * | Case | Result |\n * |------------------------------------------------------------|------------------------|\n * | Column conflict between two patterns | error |\n * | Column conflict with entity field | error |\n * | Column conflict with a behavior field | error |\n * | Method-name conflict between patterns | (TS compile error) |\n * | Same implied behavior across patterns | silent dedup |\n * | Pattern referenced in YAML but not in the registry | error |\n * | `config:` key for a pattern the entity is not using | warning |\n * | Pattern config fails its Zod schema | error |\n *\n * Method-name conflicts are explicitly **not** checked here — they surface as\n * TypeScript compile errors at the consumer when the generated concrete\n * class extends the base. Adding a codegen check would duplicate work\n * the type system already does, so we stay silent on that row per ADR-031.\n *\n * Project-level validation (`validatePatternProject`) covers plan Risk 4:\n * entities declaring `pattern:` while `generate.architecture: clean` is\n * selected get a warning since the `clean` pipeline does not yet consume\n * patterns. Additive Phase 3+ work per ADR.\n *\n * The shape mirrors `src/behaviors/index.ts:81–124` (`validateBehaviors`):\n * a single pass that returns structured issues for `analyzeDomain()` to\n * aggregate.\n */\n\nimport type { AnalysisIssue, ParsedEntity } from '../analyzer/types.js';\nimport { resolveBehaviorFields } from '../behaviors/index.js';\nimport { getPattern } from './registry.js';\n\n// ============================================================================\n// Per-entity validation\n// ============================================================================\n\n/**\n * Validate pattern composition for a single entity. Returns an array of\n * `AnalysisIssue` values suitable for concatenation into `analyzeDomain`'s\n * aggregated issue list.\n *\n * Entities with no `pattern:` or `patterns:` declared return an empty\n * array — pattern-free entities are a valid use case (plain `BaseRepository`\n * fallback) and nothing below applies to them.\n */\nexport function validatePatternComposition(\n\tentity: ParsedEntity,\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\t// Normalise `pattern:` (single) and `patterns:` (multi) into one list,\n\t// preserving declaration order. `pattern` + `patterns` mutual exclusion\n\t// is a schema-level check — by the time we get here, at most one shape\n\t// is set.\n\tconst patternNames: string[] = entity.patterns ?? (entity.pattern ? [entity.pattern] : []);\n\tif (patternNames.length === 0) return issues;\n\n\t// Column-source tracker: maps column name → human-readable origin.\n\t// Populated in priority order (entity fields > behavior fields >\n\t// pattern contributions) so conflict messages name the *existing*\n\t// contributor correctly.\n\tconst columnSources = new Map<string, string>();\n\n\tfor (const [name] of entity.fields) {\n\t\tcolumnSources.set(name, `entity field '${name}'`);\n\t}\n\n\t// Behavior fields participate in conflict detection. Behaviors the\n\t// entity has NOT already declared but that a pattern implies will be\n\t// added below (silent dedup); conflicts against those show up when\n\t// the pattern's columns are checked.\n\tconst behaviorFields = resolveBehaviorFields(entity.behaviors);\n\tfor (const bf of behaviorFields) {\n\t\tconst existing = columnSources.get(bf.name);\n\t\tif (existing) {\n\t\t\t// A behavior field colliding with an entity-declared field\n\t\t\t// was already a codegen problem before patterns existed. We\n\t\t\t// surface it here too so the composition check is the single\n\t\t\t// authoritative pass for \"column conflicts on this entity.\"\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'pattern_column_conflict',\n\t\t\t\tentity: entity.name,\n\t\t\t\tmessage:\n\t\t\t\t\t`Behavior-contributed field '${bf.name}' conflicts with ${existing}.`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tcolumnSources.set(bf.name, `behavior field '${bf.name}'`);\n\t}\n\n\t// Track implied behaviors across all declared patterns so we can\n\t// assert silent dedup rather than repeat issues — this also lets us\n\t// return the deduped list for callers that want to thread it into\n\t// template-locals later without re-walking.\n\tconst impliedBehaviors = new Set<string>(entity.behaviors);\n\n\tfor (const patternName of patternNames) {\n\t\tconst def = getPattern(patternName);\n\n\t\t// Rule: pattern referenced in YAML but not in the registry\n\t\tif (!def) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'error',\n\t\t\t\ttype: 'pattern_unknown',\n\t\t\t\tentity: entity.name,\n\t\t\t\tmessage:\n\t\t\t\t\t`Unknown pattern '${patternName}'. ` +\n\t\t\t\t\t`Library patterns are pre-registered; app patterns are loaded from ` +\n\t\t\t\t\t`globs in codegen.config.yaml 'patterns:' (default 'src/patterns/*.pattern.ts').`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Rule: pattern config must match the pattern's Zod schema\n\t\tif (def.configSchema) {\n\t\t\tconst rawConfig = entity.patternConfig?.[patternName];\n\t\t\tconst result = def.configSchema.safeParse(rawConfig ?? {});\n\t\t\tif (!result.success) {\n\t\t\t\tconst detail = result.error.issues\n\t\t\t\t\t.map((i) => `${i.path.join('.') || '<root>'}: ${i.message}`)\n\t\t\t\t\t.join(', ');\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'pattern_config_invalid',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Pattern '${patternName}' config failed validation: ${detail}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Rule: column contributions conflict with anything already in the\n\t\t// column-sources table. The first column to claim a name wins; the\n\t\t// second one reports the conflict naming both contributors.\n\t\tfor (const col of def.columns ?? []) {\n\t\t\tconst existing = columnSources.get(col.name);\n\t\t\tif (existing) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t\ttype: 'pattern_column_conflict',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Pattern '${patternName}' contributes column '${col.name}' ` +\n\t\t\t\t\t\t`which conflicts with ${existing}.`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcolumnSources.set(col.name, `pattern '${patternName}'`);\n\t\t}\n\n\t\t// Silent dedup on implied behaviors — a pattern declaring a\n\t\t// behavior the entity already has (or another pattern already\n\t\t// contributed) is a no-op, not an error.\n\t\tfor (const b of def.impliedBehaviors ?? []) {\n\t\t\timpliedBehaviors.add(b);\n\t\t}\n\t}\n\n\t// Rule: `config:` key for a pattern not in the declared list → warning.\n\tif (entity.patternConfig) {\n\t\tconst declared = new Set(patternNames);\n\t\tfor (const key of Object.keys(entity.patternConfig)) {\n\t\t\tif (!declared.has(key)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tseverity: 'warning',\n\t\t\t\t\ttype: 'pattern_config_unused',\n\t\t\t\t\tentity: entity.name,\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t`Config block has key '${key}' but pattern '${key}' is not ` +\n\t\t\t\t\t\t`declared in 'pattern:' or 'patterns:'. Remove the entry or ` +\n\t\t\t\t\t\t`add the pattern.`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn issues;\n}\n\n// ============================================================================\n// Project-level validation — plan Risk 4\n// ============================================================================\n\nexport interface PatternProjectContext {\n\tentities: ReadonlyArray<ParsedEntity>;\n\t/**\n\t * Selected backend architecture from `codegen.config.yaml\n\t * generate.architecture`. `undefined` when the consumer is using the\n\t * library purely as an analyzer (no generation config loaded).\n\t */\n\tarchitecture?: string;\n}\n\n/**\n * Validate project-level invariants for patterns. Runs after\n * `validatePatternComposition` has visited every entity, so we can\n * assume per-entity errors have been surfaced.\n *\n * Today this only covers plan Risk 4: warn when patterns are declared\n * but the selected architecture is `clean`, which does not yet consume\n * them. A `clean` consumer with `pattern: Synced` is not broken — the\n * `clean` pipeline ignores the key — but they see no effect, which is\n * confusing without the warning.\n */\nexport function validatePatternProject(\n\tctx: PatternProjectContext,\n): AnalysisIssue[] {\n\tconst issues: AnalysisIssue[] = [];\n\n\tif (ctx.architecture === 'clean') {\n\t\tconst withPatterns = ctx.entities.filter(\n\t\t\t(e) => (e.patterns && e.patterns.length > 0) || !!e.pattern,\n\t\t);\n\t\tfor (const e of withPatterns) {\n\t\t\tissues.push({\n\t\t\t\tseverity: 'warning',\n\t\t\t\ttype: 'pattern_clean_pipeline_noop',\n\t\t\t\tentity: e.name,\n\t\t\t\tmessage:\n\t\t\t\t\t`'pattern:' is declared but 'generate.architecture: clean' does not ` +\n\t\t\t\t\t`yet consume patterns. This declaration is a no-op. Patterns are ` +\n\t\t\t\t\t`consumed by 'clean-lite-ps' today; 'clean' integration is Phase 3+ ` +\n\t\t\t\t\t`additive work (ADR-031).`,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn issues;\n}\n","/**\n * Console Formatter\n *\n * Pretty terminal output with colors for the domain analysis results.\n */\n\nimport type { AnalysisResult, AnalysisIssue, Severity } from '../analyzer/types';\n\n// ANSI color codes\nconst colors = {\n\treset: '\\x1b[0m',\n\tbold: '\\x1b[1m',\n\tdim: '\\x1b[2m',\n\n\tred: '\\x1b[31m',\n\tgreen: '\\x1b[32m',\n\tyellow: '\\x1b[33m',\n\tblue: '\\x1b[34m',\n\tmagenta: '\\x1b[35m',\n\tcyan: '\\x1b[36m',\n\twhite: '\\x1b[37m',\n\n\tbgRed: '\\x1b[41m',\n\tbgGreen: '\\x1b[42m',\n\tbgYellow: '\\x1b[43m',\n};\n\nfunction color(text: string, ...styles: string[]): string {\n\treturn `${styles.join('')}${text}${colors.reset}`;\n}\n\nfunction severityColor(severity: Severity): string {\n\tswitch (severity) {\n\t\tcase 'error':\n\t\t\treturn colors.red;\n\t\tcase 'warning':\n\t\t\treturn colors.yellow;\n\t\tcase 'info':\n\t\t\treturn colors.cyan;\n\t}\n}\n\nfunction severityIcon(severity: Severity): string {\n\tswitch (severity) {\n\t\tcase 'error':\n\t\t\treturn 'X';\n\t\tcase 'warning':\n\t\t\treturn '!';\n\t\tcase 'info':\n\t\t\treturn 'i';\n\t}\n}\n\n/**\n * Format analysis result for console output\n */\nexport function formatConsole(result: AnalysisResult): string {\n\tconst lines: string[] = [];\n\n\t// Header\n\tlines.push('');\n\tlines.push(color('='.repeat(60), colors.dim));\n\tlines.push(color(' Domain Analysis Report', colors.bold, colors.cyan));\n\tlines.push(color('='.repeat(60), colors.dim));\n\tlines.push('');\n\n\t// Statistics\n\tlines.push(...formatStatistics(result));\n\n\t// Entity summary\n\tlines.push(...formatEntities(result));\n\n\t// Relationships\n\tlines.push(...formatRelationships(result));\n\n\t// Issues\n\tif (result.issues.length > 0) {\n\t\tlines.push(...formatIssues(result.issues));\n\t}\n\n\t// Final status\n\tlines.push('');\n\tlines.push(color('-'.repeat(60), colors.dim));\n\n\tconst errors = result.issues.filter((i) => i.severity === 'error');\n\tconst warnings = result.issues.filter((i) => i.severity === 'warning');\n\tconst infos = result.issues.filter((i) => i.severity === 'info');\n\n\tif (result.isValid) {\n\t\tlines.push(\n\t\t\tcolor(\n\t\t\t\t`[OK] Domain is valid (${warnings.length} warnings, ${infos.length} info)`,\n\t\t\t\tcolors.green\n\t\t\t)\n\t\t);\n\t} else {\n\t\tlines.push(color(`[FAIL] Domain has ${errors.length} errors`, colors.red));\n\t}\n\n\tlines.push(color('-'.repeat(60), colors.dim));\n\tlines.push('');\n\n\treturn lines.join('\\n');\n}\n\nfunction formatStatistics(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\tconst stats = result.statistics;\n\n\tlines.push(color('Statistics:', colors.bold));\n\tlines.push('');\n\tlines.push(` Entities: ${stats.totalEntities}`);\n\tlines.push(\n\t\t` Fields: ${stats.totalFields} (avg ${stats.averageFieldsPerEntity.toFixed(1)}/entity)`\n\t);\n\tlines.push(` Relationships: ${stats.totalRelationships}`);\n\tlines.push(` With behaviors: ${stats.entitiesWithBehaviors}`);\n\tlines.push('');\n\n\t// Field types breakdown\n\tlines.push(' Field types:');\n\tconst sortedTypes = Object.entries(stats.fieldsByType).sort((a, b) => b[1] - a[1]);\n\tfor (const [type, count] of sortedTypes) {\n\t\tconst bar = color('|'.repeat(Math.min(count, 20)), colors.blue);\n\t\tlines.push(` ${type.padEnd(12)} ${bar} ${count}`);\n\t}\n\tlines.push('');\n\n\t// Relationship types breakdown\n\tif (stats.totalRelationships > 0) {\n\t\tlines.push(' Relationship types:');\n\t\tconst sortedRels = Object.entries(stats.relationshipsByType).sort((a, b) => b[1] - a[1]);\n\t\tfor (const [type, count] of sortedRels) {\n\t\t\tconst bar = color('|'.repeat(Math.min(count, 20)), colors.magenta);\n\t\t\tlines.push(` ${type.padEnd(12)} ${bar} ${count}`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\treturn lines;\n}\n\nfunction formatEntities(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\n\tlines.push(color('Entities:', colors.bold));\n\tlines.push('');\n\n\tfor (const entity of result.entities) {\n\t\tconst fieldCount = entity.fields.size;\n\t\tconst relCount = entity.relationships.size;\n\t\tlines.push(\n\t\t\t` ${color(entity.name, colors.cyan)} (${fieldCount} fields, ${relCount} relationships)`\n\t\t);\n\t\tif (entity.behaviors.length > 0) {\n\t\t\tlines.push(color(` behaviors: ${entity.behaviors.join(', ')}`, colors.dim));\n\t\t}\n\t}\n\tlines.push('');\n\n\treturn lines;\n}\n\nfunction formatRelationships(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\n\tif (result.graph.edges.length === 0) {\n\t\treturn lines;\n\t}\n\n\tlines.push(color('Relationships:', colors.bold));\n\tlines.push('');\n\n\tfor (const edge of result.graph.edges) {\n\t\tconst arrow = getCardinalityArrow(edge.cardinality);\n\t\tconst bidir = edge.bidirectional ? color(' (bidirectional)', colors.dim) : '';\n\t\tlines.push(\n\t\t\t` ${edge.from.padEnd(20)} ${arrow} ${edge.to} ${color(`(${edge.relationship.type})`, colors.dim)}${bidir}`\n\t\t);\n\t}\n\tlines.push('');\n\n\treturn lines;\n}\n\nfunction getCardinalityArrow(cardinality: string): string {\n\tswitch (cardinality) {\n\t\tcase '1:N':\n\t\t\treturn color('--<', colors.magenta);\n\t\tcase 'N:1':\n\t\t\treturn color('>--', colors.magenta);\n\t\tcase '1:1':\n\t\t\treturn color('---', colors.magenta);\n\t\tcase 'N:M':\n\t\t\treturn color('>-<', colors.magenta);\n\t\tdefault:\n\t\t\treturn color('-->', colors.magenta);\n\t}\n}\n\nfunction formatIssues(issues: AnalysisIssue[]): string[] {\n\tconst lines: string[] = [];\n\n\t// Group by severity\n\tconst errors = issues.filter((i) => i.severity === 'error');\n\tconst warnings = issues.filter((i) => i.severity === 'warning');\n\tconst infos = issues.filter((i) => i.severity === 'info');\n\n\tif (errors.length > 0) {\n\t\tlines.push(color(`Errors (${errors.length}):`, colors.bold, colors.red));\n\t\tlines.push('');\n\t\tlines.push(...formatIssueList(errors, 'error'));\n\t\tlines.push('');\n\t}\n\n\tif (warnings.length > 0) {\n\t\tlines.push(color(`Warnings (${warnings.length}):`, colors.bold, colors.yellow));\n\t\tlines.push('');\n\t\tlines.push(...formatIssueList(warnings, 'warning'));\n\t\tlines.push('');\n\t}\n\n\tif (infos.length > 0) {\n\t\tlines.push(color(`Info (${infos.length}):`, colors.bold, colors.cyan));\n\t\tlines.push('');\n\t\tlines.push(...formatIssueList(infos, 'info', 5)); // Only show first 5 info messages\n\t\tlines.push('');\n\t}\n\n\treturn lines;\n}\n\nfunction formatIssueList(\n\tissues: AnalysisIssue[],\n\tseverity: Severity,\n\tlimit?: number\n): string[] {\n\tconst lines: string[] = [];\n\tconst displayIssues = limit ? issues.slice(0, limit) : issues;\n\n\t// Group by type\n\tconst byType = new Map<string, AnalysisIssue[]>();\n\tfor (const issue of displayIssues) {\n\t\tconst list = byType.get(issue.type) ?? [];\n\t\tlist.push(issue);\n\t\tbyType.set(issue.type, list);\n\t}\n\n\tfor (const [type, typeIssues] of byType) {\n\t\tlines.push(color(` ${type} (${typeIssues.length}):`, colors.dim));\n\n\t\tfor (const issue of typeIssues.slice(0, 5)) {\n\t\t\tconst location = issue.entity\n\t\t\t\t? `${issue.entity}${issue.field ? '.' + issue.field : ''}`\n\t\t\t\t: issue.path ?? 'unknown';\n\n\t\t\tconst icon = color(`[${severityIcon(severity)}]`, severityColor(severity));\n\t\t\tlines.push(` ${icon} ${color(location, colors.bold)}: ${issue.message}`);\n\n\t\t\tif (issue.suggestion) {\n\t\t\t\tlines.push(color(` -> ${issue.suggestion}`, colors.dim));\n\t\t\t}\n\t\t}\n\n\t\tif (typeIssues.length > 5) {\n\t\t\tlines.push(color(` ... and ${typeIssues.length - 5} more`, colors.dim));\n\t\t}\n\t}\n\n\tif (limit && issues.length > limit) {\n\t\tlines.push(color(` ... and ${issues.length - limit} more info messages`, colors.dim));\n\t}\n\n\treturn lines;\n}\n","/**\n * JSON Formatter\n *\n * Machine-readable JSON output for the domain analysis results.\n */\n\nimport type { AnalysisResult, ParsedEntity, DomainGraph } from '../analyzer/types';\n\n/**\n * Helper to convert Maps to plain objects for JSON serialization\n */\nfunction mapToObject<K extends string, V>(map: Map<K, V>): Record<K, V> {\n\tconst obj = {} as Record<K, V>;\n\tfor (const [key, value] of map) {\n\t\tobj[key] = value;\n\t}\n\treturn obj;\n}\n\n/**\n * Convert ParsedEntity to a JSON-serializable format\n */\nfunction serializeEntity(entity: ParsedEntity): Record<string, unknown> {\n\treturn {\n\t\tname: entity.name,\n\t\tplural: entity.plural,\n\t\ttable: entity.table,\n\t\tfolderStructure: entity.folderStructure,\n\t\tfields: mapToObject(entity.fields),\n\t\trelationships: mapToObject(entity.relationships),\n\t\tbehaviors: entity.behaviors,\n\t\tsourcePath: entity.sourcePath,\n\t};\n}\n\n/**\n * Convert DomainGraph to a JSON-serializable format\n */\nfunction serializeGraph(graph: DomainGraph): Record<string, unknown> {\n\tconst entities: Record<string, unknown> = {};\n\tfor (const [name, entity] of graph.entities) {\n\t\tentities[name] = serializeEntity(entity);\n\t}\n\n\treturn {\n\t\tentities,\n\t\tedges: graph.edges,\n\t};\n}\n\n/**\n * Format analysis result as JSON string\n */\nexport function formatJson(result: AnalysisResult, pretty = true): string {\n\tconst output = {\n\t\tisValid: result.isValid,\n\t\tsummary: {\n\t\t\tentities: result.statistics.totalEntities,\n\t\t\tfields: result.statistics.totalFields,\n\t\t\trelationships: result.statistics.totalRelationships,\n\t\t\terrors: result.issues.filter((i) => i.severity === 'error').length,\n\t\t\twarnings: result.issues.filter((i) => i.severity === 'warning').length,\n\t\t\tinfo: result.issues.filter((i) => i.severity === 'info').length,\n\t\t},\n\t\tentities: result.entities.map(serializeEntity),\n\t\tgraph: serializeGraph(result.graph),\n\t\tissues: result.issues,\n\t\tstatistics: result.statistics,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n\n\treturn pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output);\n}\n\n/**\n * Format only statistics as JSON\n */\nexport function formatStatsJson(result: AnalysisResult, pretty = true): string {\n\tconst output = {\n\t\tstatistics: result.statistics,\n\t\tisValid: result.isValid,\n\t\tissueCount: {\n\t\t\terrors: result.issues.filter((i) => i.severity === 'error').length,\n\t\t\twarnings: result.issues.filter((i) => i.severity === 'warning').length,\n\t\t\tinfo: result.issues.filter((i) => i.severity === 'info').length,\n\t\t},\n\t\ttimestamp: new Date().toISOString(),\n\t};\n\n\treturn pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output);\n}\n\n/**\n * Format only issues as JSON\n */\nexport function formatIssuesJson(result: AnalysisResult, pretty = true): string {\n\tconst output = {\n\t\tisValid: result.isValid,\n\t\tissues: result.issues,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n\n\treturn pretty ? JSON.stringify(output, null, 2) : JSON.stringify(output);\n}\n","/**\n * Markdown Formatter\n *\n * Documentation output with Mermaid diagrams for the domain analysis results.\n */\n\nimport type { AnalysisResult, ParsedEntity, RelationshipEdge } from '../analyzer/types';\n\n/**\n * Format analysis result as Markdown documentation\n */\nexport function formatMarkdown(result: AnalysisResult): string {\n\tconst lines: string[] = [];\n\n\t// Title\n\tlines.push('# Domain Model Documentation');\n\tlines.push('');\n\tlines.push(`Generated: ${new Date().toISOString()}`);\n\tlines.push('');\n\n\t// Overview statistics\n\tlines.push('## Overview');\n\tlines.push('');\n\tlines.push('| Metric | Value |');\n\tlines.push('|--------|-------|');\n\tlines.push(`| Entities | ${result.statistics.totalEntities} |`);\n\tlines.push(`| Total Fields | ${result.statistics.totalFields} |`);\n\tlines.push(`| Total Relationships | ${result.statistics.totalRelationships} |`);\n\tlines.push(\n\t\t`| Avg Fields/Entity | ${result.statistics.averageFieldsPerEntity.toFixed(1)} |`\n\t);\n\tlines.push('');\n\n\t// Field type distribution\n\tlines.push('### Field Type Distribution');\n\tlines.push('');\n\tlines.push('| Type | Count |');\n\tlines.push('|------|-------|');\n\tconst sortedTypes = Object.entries(result.statistics.fieldsByType).sort(\n\t\t(a, b) => b[1] - a[1]\n\t);\n\tfor (const [type, count] of sortedTypes) {\n\t\tlines.push(`| ${type} | ${count} |`);\n\t}\n\tlines.push('');\n\n\t// Relationship type distribution\n\tif (result.statistics.totalRelationships > 0) {\n\t\tlines.push('### Relationship Type Distribution');\n\t\tlines.push('');\n\t\tlines.push('| Type | Count |');\n\t\tlines.push('|------|-------|');\n\t\tconst sortedRels = Object.entries(result.statistics.relationshipsByType).sort(\n\t\t\t(a, b) => b[1] - a[1]\n\t\t);\n\t\tfor (const [type, count] of sortedRels) {\n\t\t\tlines.push(`| ${type} | ${count} |`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\t// Entity Relationship Diagram\n\tlines.push('## Entity Relationship Diagram');\n\tlines.push('');\n\tlines.push('```mermaid');\n\tlines.push(...generateMermaidErDiagram(result));\n\tlines.push('```');\n\tlines.push('');\n\n\t// Entities\n\tlines.push('## Entities');\n\tlines.push('');\n\n\tfor (const entity of result.entities) {\n\t\tlines.push(...formatEntitySection(entity));\n\t}\n\n\t// Issues\n\tconst errors = result.issues.filter((i) => i.severity === 'error');\n\tconst warnings = result.issues.filter((i) => i.severity === 'warning');\n\tconst infos = result.issues.filter((i) => i.severity === 'info');\n\n\tif (result.issues.length > 0) {\n\t\tlines.push('## Analysis Issues');\n\t\tlines.push('');\n\n\t\tif (errors.length > 0) {\n\t\t\tlines.push('### Errors');\n\t\t\tlines.push('');\n\t\t\tfor (const issue of errors) {\n\t\t\t\tconst location = issue.entity\n\t\t\t\t\t? `**${issue.entity}${issue.field ? '.' + issue.field : ''}**`\n\t\t\t\t\t: issue.path ?? 'unknown';\n\t\t\t\tlines.push(`- [${issue.type}] ${location}: ${issue.message}`);\n\t\t\t\tif (issue.suggestion) {\n\t\t\t\t\tlines.push(` - Suggestion: ${issue.suggestion}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlines.push('');\n\t\t}\n\n\t\tif (warnings.length > 0) {\n\t\t\tlines.push('### Warnings');\n\t\t\tlines.push('');\n\t\t\tfor (const issue of warnings) {\n\t\t\t\tconst location = issue.entity\n\t\t\t\t\t? `**${issue.entity}${issue.field ? '.' + issue.field : ''}**`\n\t\t\t\t\t: issue.path ?? 'unknown';\n\t\t\t\tlines.push(`- [${issue.type}] ${location}: ${issue.message}`);\n\t\t\t\tif (issue.suggestion) {\n\t\t\t\t\tlines.push(` - Suggestion: ${issue.suggestion}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlines.push('');\n\t\t}\n\n\t\tif (infos.length > 0) {\n\t\t\tlines.push('### Info');\n\t\t\tlines.push('');\n\t\t\tlines.push('<details>');\n\t\t\tlines.push('<summary>Show info messages</summary>');\n\t\t\tlines.push('');\n\t\t\tfor (const issue of infos) {\n\t\t\t\tconst location = issue.entity\n\t\t\t\t\t? `**${issue.entity}${issue.field ? '.' + issue.field : ''}**`\n\t\t\t\t\t: issue.path ?? 'unknown';\n\t\t\t\tlines.push(`- [${issue.type}] ${location}: ${issue.message}`);\n\t\t\t}\n\t\t\tlines.push('');\n\t\t\tlines.push('</details>');\n\t\t\tlines.push('');\n\t\t}\n\t}\n\n\treturn lines.join('\\n');\n}\n\n/**\n * Format a single entity section\n */\nfunction formatEntitySection(entity: ParsedEntity): string[] {\n\tconst lines: string[] = [];\n\n\tlines.push(`### ${entity.name}`);\n\tlines.push('');\n\tlines.push(`**Table:** \\`${entity.table}\\``);\n\tlines.push(`**Plural:** ${entity.plural}`);\n\tif (entity.behaviors.length > 0) {\n\t\tlines.push(`**Behaviors:** ${entity.behaviors.join(', ')}`);\n\t}\n\tlines.push('');\n\n\t// Fields table\n\tlines.push('#### Fields');\n\tlines.push('');\n\tlines.push('| Name | Type | Required | Nullable | Index | Foreign Key |');\n\tlines.push('|------|------|----------|----------|-------|-------------|');\n\n\tfor (const [name, field] of entity.fields) {\n\t\tconst required = field.required ? 'Yes' : '';\n\t\tconst nullable = field.nullable ? 'Yes' : '';\n\t\tconst index = field.index ? 'Yes' : field.unique ? 'Unique' : '';\n\t\tconst fk = field.foreignKey ? `${field.foreignKey.table}.${field.foreignKey.column}` : '';\n\t\tlines.push(`| ${name} | ${field.type} | ${required} | ${nullable} | ${index} | ${fk} |`);\n\t}\n\tlines.push('');\n\n\t// Relationships\n\tif (entity.relationships.size > 0) {\n\t\tlines.push('#### Relationships');\n\t\tlines.push('');\n\t\tlines.push('| Name | Type | Target | Foreign Key |');\n\t\tlines.push('|------|------|--------|-------------|');\n\n\t\tfor (const [name, rel] of entity.relationships) {\n\t\t\tlines.push(`| ${name} | ${rel.type} | ${rel.target} | ${rel.foreignKey} |`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\treturn lines;\n}\n\n/**\n * Generate Mermaid ER diagram\n */\nfunction generateMermaidErDiagram(result: AnalysisResult): string[] {\n\tconst lines: string[] = [];\n\n\tlines.push('erDiagram');\n\n\t// Define entities with their fields\n\tfor (const entity of result.entities) {\n\t\tconst entityName = entity.name.toUpperCase();\n\t\tlines.push(` ${entityName} {`);\n\n\t\t// Show key fields only (to keep diagram readable)\n\t\tconst keyFields = Array.from(entity.fields.entries())\n\t\t\t.filter(\n\t\t\t\t([name, field]) =>\n\t\t\t\t\tfield.foreignKey || field.unique || field.index || name === 'id' || name === 'name'\n\t\t\t)\n\t\t\t.slice(0, 6); // Limit to 6 fields\n\n\t\tfor (const [name, field] of keyFields) {\n\t\t\tconst typeStr = field.type;\n\t\t\tconst pk = name === 'id' ? 'PK' : '';\n\t\t\tconst fk = field.foreignKey ? 'FK' : '';\n\t\t\tconst marker = pk || fk ? ` \"${pk}${fk}\"` : '';\n\t\t\tlines.push(` ${typeStr} ${name}${marker}`);\n\t\t}\n\n\t\tif (entity.fields.size > keyFields.length) {\n\t\t\tlines.push(` string _more_fields`);\n\t\t}\n\n\t\tlines.push(' }');\n\t}\n\n\t// Add relationships\n\tfor (const edge of result.graph.edges) {\n\t\tconst from = edge.from.toUpperCase();\n\t\tconst to = edge.to.toUpperCase();\n\t\tconst cardinalitySymbol = getCardinalitySymbol(edge.cardinality);\n\t\tconst label = edge.relationship.name;\n\n\t\tlines.push(` ${from} ${cardinalitySymbol} ${to} : \"${label}\"`);\n\t}\n\n\treturn lines;\n}\n\n/**\n * Get Mermaid cardinality symbol\n */\nfunction getCardinalitySymbol(cardinality: string): string {\n\tswitch (cardinality) {\n\t\tcase '1:N':\n\t\t\treturn '||--o{';\n\t\tcase 'N:1':\n\t\t\treturn '}o--||';\n\t\tcase '1:1':\n\t\t\treturn '||--||';\n\t\tcase 'N:M':\n\t\t\treturn '}o--o{';\n\t\tdefault:\n\t\t\treturn '||--o{';\n\t}\n}\n\n/**\n * Generate a simple relationship graph in Mermaid\n */\nexport function formatMermaidGraph(result: AnalysisResult): string {\n\tconst lines: string[] = [];\n\n\tlines.push('```mermaid');\n\tlines.push('graph LR');\n\n\t// Style definitions\n\tlines.push(' classDef entity fill:#e1f5fe,stroke:#01579b');\n\n\t// Add entities as nodes\n\tfor (const entity of result.entities) {\n\t\tlines.push(` ${entity.name}[\"${entity.name}\\\\n(${entity.fields.size} fields)\"]`);\n\t}\n\n\t// Add relationships as edges\n\tfor (const edge of result.graph.edges) {\n\t\tconst style = edge.bidirectional ? '<-->' : '-->';\n\t\tlines.push(` ${edge.from} ${style}|${edge.relationship.type}| ${edge.to}`);\n\t}\n\n\t// Apply styles\n\tconst entityList = result.entities.map((e) => e.name).join(',');\n\tif (entityList) {\n\t\tlines.push(` class ${entityList} entity`);\n\t}\n\n\tlines.push('```');\n\n\treturn lines.join('\\n');\n}\n","/**\n * ActivityPattern — replaces `family: activity`.\n *\n * Activity entities represent time-bounded interactions (calls, meetings,\n * emails). The base repository/service expose date-range + opportunity +\n * user-scoped lookups on top of the standard CRUD methods.\n *\n * Class names, import paths, and inherited-method strings match the\n * legacy `FAMILY_MAP` entry verbatim so PATTERN-5's template swap produces\n * byte-identical output.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const ActivityPattern = definePattern({\n\tname: 'Activity',\n\textends: ['Base'],\n\trepositoryClass: 'ActivityEntityRepository',\n\tserviceClass: 'ActivityEntityService',\n\trepositoryImport: '@shared/base-classes/activity-entity-repository',\n\tserviceImport: '@shared/base-classes/activity-entity-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'findByDateRange, findByUserId, findByOpportunityId, findRecentByOpportunityId',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'findByDateRange, findByUserId, findByOpportunityId, findRecentByOpportunityId',\n\t],\n\tdescription:\n\t\t'Time-bounded interaction entities — date-range + opportunity scoped lookups',\n});\n","/**\n * BasePattern — identity pattern for the `extends` chain.\n *\n * Contributes no columns, no implied behaviors, and no config. Its only\n * purpose is to anchor the inheritance hierarchy so every other pattern\n * can declare `extends: ['Base']` and codegen can resolve that to a\n * concrete `BaseRepository` / `BaseService` reference.\n *\n * Matches the existing `family: base` entry in\n * `templates/entity/new/clean-lite-ps/prompt-extension.js` verbatim.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const BasePattern = definePattern({\n\tname: 'Base',\n\trepositoryClass: 'BaseRepository',\n\tserviceClass: 'BaseService',\n\trepositoryImport: '@shared/base-classes/base-repository',\n\tserviceImport: '@shared/base-classes/base-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t],\n\tdescription: 'Identity pattern — base CRUD, no extra columns or methods',\n});\n","/**\n * KnowledgePattern — replaces `family: knowledge`.\n *\n * Knowledge entities hold long-form content with a workflow status and\n * semantic-search support (vectors, pending/approved states). The base\n * classes expose `semanticSearch`, pending-by-opportunity lookups, and\n * batch status updates.\n *\n * Class names, import paths, and inherited-method strings match the\n * legacy `FAMILY_MAP` entry verbatim.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const KnowledgePattern = definePattern({\n\tname: 'Knowledge',\n\textends: ['Base'],\n\trepositoryClass: 'KnowledgeEntityRepository',\n\tserviceClass: 'KnowledgeEntityService',\n\trepositoryImport: '@shared/base-classes/knowledge-entity-repository',\n\tserviceImport: '@shared/base-classes/knowledge-entity-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'semanticSearch, findPendingByOpportunityId, updateStatus, updateStatusBatch',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'semanticSearch, findPendingByOpportunityId, updateStatus, updateStatusBatch',\n\t],\n\tdescription: 'Knowledge entities — semantic search + workflow status',\n});\n","/**\n * MetadataPattern — replaces `family: metadata`.\n *\n * Metadata entities represent history-tracked auxiliary rows attached to a\n * parent entity (audit trails, custom-field values, change logs). The base\n * classes expose entity-id + type scoped lookups and history listing.\n *\n * Class names, import paths, and inherited-method strings match the\n * legacy `FAMILY_MAP` entry verbatim.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const MetadataPattern = definePattern({\n\tname: 'Metadata',\n\textends: ['Base'],\n\trepositoryClass: 'MetadataEntityRepository',\n\tserviceClass: 'MetadataEntityService',\n\trepositoryImport: '@shared/base-classes/metadata-entity-repository',\n\tserviceImport: '@shared/base-classes/metadata-entity-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'findByEntityIdAndType, listByEntityId, listHistoryByEntityId',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'findByEntityIdAndType, listByEntityId, listHistoryByEntityId',\n\t],\n\tdescription:\n\t\t'History-tracked metadata rows — entity-id + type scoped lookups',\n});\n","/**\n * SyncedPattern — adds external-system sync columns and methods.\n *\n * Replaces the legacy `family: synced` entry in\n * `templates/entity/new/clean-lite-ps/prompt-extension.js`. Class names,\n * import paths, and inherited-method comment lines are preserved verbatim\n * so PATTERN-5's template swap produces byte-identical output for\n * pre-existing `family: synced` fixtures.\n *\n * Implies `external_id_tracking` — the behavior that contributes the\n * `external_id`, `provider`, and `provider_metadata` columns to the table.\n * An entity declaring `pattern: Synced` need not re-declare the behavior.\n */\n\nimport { definePattern } from '../pattern-definition.js';\n\nexport const SyncedPattern = definePattern({\n\tname: 'Synced',\n\textends: ['Base'],\n\trepositoryClass: 'SyncedEntityRepository',\n\tserviceClass: 'SyncedEntityService',\n\trepositoryImport: '@shared/base-classes/synced-entity-repository',\n\tserviceImport: '@shared/base-classes/synced-entity-service',\n\trepositoryInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete, upsertMany',\n\t\t'findByExternalId, findAllByUserId, findVisibleByUserId, syncUpsert',\n\t],\n\tserviceInheritedMethods: [\n\t\t'findById, findByIds, list, count, exists, create, update, delete',\n\t\t'findByExternalId, findAllByUserId, findVisibleByUserId',\n\t],\n\timpliedBehaviors: ['external_id_tracking'],\n\tdescription: 'External CRM/system sync columns and syncUpsert methods',\n});\n","/**\n * Library pattern bootstrap — imports every shipped pattern and registers\n * it with the shared library registry. Side-effect-only module: importing\n * this barrel is what pre-registers `Base`, `Synced`, `Activity`,\n * `Knowledge`, and `Metadata`.\n *\n * Adding a new library pattern is two edits: create the `*.pattern.ts`\n * file and add the import+register pair below.\n */\n\nimport { registerLibraryPattern } from '../registry.js';\nimport { ActivityPattern } from './activity.pattern.js';\nimport { BasePattern } from './base.pattern.js';\nimport { KnowledgePattern } from './knowledge.pattern.js';\nimport { MetadataPattern } from './metadata.pattern.js';\nimport { SyncedPattern } from './synced.pattern.js';\n\nregisterLibraryPattern(BasePattern);\nregisterLibraryPattern(SyncedPattern);\nregisterLibraryPattern(ActivityPattern);\nregisterLibraryPattern(KnowledgePattern);\nregisterLibraryPattern(MetadataPattern);\n\nexport {\n\tActivityPattern,\n\tBasePattern,\n\tKnowledgePattern,\n\tMetadataPattern,\n\tSyncedPattern,\n};\n","/**\n * Entity Codegen & Domain Analyzer\n *\n * A validation and analysis tool for entity YAML definitions.\n * Parses entities, builds a relationship graph, and detects issues.\n */\n\nimport { loadEntities, loadRelationships, resolveReferences, resolveRelationshipReferences } from './parser';\nimport { buildDomainGraph, checkConsistency, computeStatistics } from './analyzer';\nimport {\n\tvalidatePatternComposition,\n\tvalidatePatternProject,\n} from './patterns/validate-composition.js';\nimport type { AnalysisResult, OutputFormat } from './analyzer/types';\n\n/**\n * Options for `analyzeDomain`. All fields are optional and additive — omitting\n * them keeps the analyzer's behavior identical to pre-PATTERN-4 callers.\n */\nexport interface AnalyzeDomainOptions {\n\t/**\n\t * Path to the relationships directory. Equivalent to the legacy second\n\t * positional argument — preserved for call-site compatibility.\n\t */\n\trelationshipsDir?: string;\n\t/**\n\t * Selected backend architecture from `codegen.config.yaml\n\t * generate.architecture`. When provided, enables the PATTERN-4 project-level\n\t * check (plan Risk 4) that warns when `pattern:` is declared but the\n\t * selected architecture does not yet consume patterns (e.g. `clean`).\n\t */\n\tarchitecture?: string;\n}\n\n/**\n * Analyze a domain from entity and relationship YAML files.\n *\n * The signature accepts either the legacy `(entitiesDir, relationshipsDir)`\n * shape or the newer `(entitiesDir, options)` object form. Existing callers\n * keep working unchanged; pattern-aware callers pass\n * `{ architecture, relationshipsDir }` to opt into the Risk-4 project-level\n * warning surface.\n */\nexport async function analyzeDomain(\n\tentitiesDir: string,\n\trelationshipsOrOptions?: string | AnalyzeDomainOptions,\n): Promise<AnalysisResult> {\n\tconst opts: AnalyzeDomainOptions =\n\t\ttypeof relationshipsOrOptions === 'string'\n\t\t\t? { relationshipsDir: relationshipsOrOptions }\n\t\t\t: relationshipsOrOptions ?? {};\n\tconst relationshipsDir = opts.relationshipsDir;\n\n\t// Load and parse all entity files\n\tconst { entities, issues: loadIssues } = loadEntities(entitiesDir);\n\n\t// Load relationship definitions (optional — directory may not exist)\n\tconst { relationships: relationshipDefinitions, issues: relLoadIssues } =\n\t\trelationshipsDir\n\t\t\t? loadRelationships(relationshipsDir)\n\t\t\t: { relationships: [], issues: [] };\n\n\t// Resolve cross-entity references\n\tconst resolveIssues = resolveReferences(entities);\n\n\t// Resolve relationship endpoint references\n\tconst relResolveIssues = resolveRelationshipReferences(\n\t\trelationshipDefinitions,\n\t\tentities,\n\t);\n\n\t// Build relationship graph (includes both inline and first-class relationships)\n\tconst graph = buildDomainGraph(entities, relationshipDefinitions);\n\n\t// Check consistency\n\tconst consistencyIssues = checkConsistency(graph);\n\n\t// PATTERN-4 — pattern composition check. Runs AFTER resolveReferences()\n\t// (per ADR-031 §3) so entity fields + behaviors are known; the\n\t// per-entity validator detects column conflicts, unknown patterns, and\n\t// config-schema failures, and the project-level validator covers plan\n\t// Risk 4 (warn when `pattern:` is declared under an architecture that\n\t// does not yet consume patterns).\n\tconst patternIssues = entities.flatMap((e) => validatePatternComposition(e));\n\tconst patternProjectIssues = validatePatternProject({\n\t\tentities,\n\t\tarchitecture: opts.architecture,\n\t});\n\n\t// Compute statistics\n\tconst statistics = computeStatistics(graph);\n\n\t// Combine all issues\n\tconst allIssues = [\n\t\t...loadIssues,\n\t\t...relLoadIssues,\n\t\t...resolveIssues,\n\t\t...relResolveIssues,\n\t\t...consistencyIssues,\n\t\t...patternIssues,\n\t\t...patternProjectIssues,\n\t];\n\n\t// Determine validity (only errors make it invalid)\n\tconst hasErrors = allIssues.some((i) => i.severity === 'error');\n\n\treturn {\n\t\tisValid: !hasErrors,\n\t\tentities,\n\t\trelationshipDefinitions,\n\t\tgraph,\n\t\tissues: allIssues,\n\t\tstatistics,\n\t};\n}\n\n/**\n * Validate entity files without full analysis\n * Returns true if all files parse successfully\n */\nexport function validateEntities(entitiesDir: string): {\n\tvalid: boolean;\n\terrors: string[];\n} {\n\tconst { entities, issues } = loadEntities(entitiesDir);\n\tconst errors = issues\n\t\t.filter((i) => i.severity === 'error')\n\t\t.map((i) => i.message);\n\n\treturn {\n\t\tvalid: errors.length === 0,\n\t\terrors,\n\t};\n}\n\n// Re-export types\nexport * from './analyzer/types';\n\n// Re-export parser utilities\nexport { loadEntities, loadRelationships, loadEntityFromYaml, loadRelationshipFromYaml } from './parser';\n\n// Re-export analyzer utilities\nexport {\n\tbuildDomainGraph,\n\tgetRelatedEntities,\n\tfindOrphanEntities,\n\tfindCircularDependencies,\n\tcheckConsistency,\n\tcomputeStatistics,\n} from './analyzer';\n\n// Re-export formatters\nexport {\n\tformatConsole,\n\tformatJson,\n\tformatMarkdown,\n\tformatMermaidGraph,\n} from './formatters';\n\n\n// Re-export patterns surface (definePattern + library patterns + registry).\n// Importing this barrel has the side effect of pre-registering the five\n// library-shipped patterns (Base / Synced / Activity / Knowledge / Metadata).\nexport * from './patterns';\n"],"mappings":"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","names":["z","z","path","path"]}