@pattern-stack/codegen 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -4
- package/dist/src/cli/index.js +136 -128
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/index.d.ts +16 -0
- package/dist/src/index.js +25 -0
- package/dist/src/index.js.map +1 -1
- package/package.json +10 -1
- package/templates/entity/new/backend/application/commands/create.ejs.t +38 -1
- package/templates/entity/new/backend/application/commands/delete.ejs.t +41 -1
- package/templates/entity/new/backend/application/commands/update.ejs.t +42 -1
- package/templates/entity/new/backend/database/repository.ejs.t +33 -3
- package/templates/entity/new/backend/domain/repository-interface.ejs.t +6 -3
- package/templates/entity/new/backend/modules/core/module.ejs.t +6 -0
- package/templates/entity/new/backend/presentation/controller.ejs.t +32 -10
- package/templates/entity/new/clean-lite-ps/controller.ejs.t +72 -11
- package/templates/entity/new/clean-lite-ps/entity.ejs.t +16 -2
- package/templates/entity/new/clean-lite-ps/index.ejs.t +1 -1
- package/templates/entity/new/clean-lite-ps/module.ejs.t +45 -2
- package/templates/entity/new/clean-lite-ps/prompt-extension.js +459 -98
- package/templates/entity/new/clean-lite-ps/repository.ejs.t +57 -4
- package/templates/entity/new/clean-lite-ps/search-controller.ejs.t +50 -0
- package/templates/entity/new/clean-lite-ps/service.ejs.t +98 -1
- package/templates/entity/new/clean-lite-ps/use-cases/create.ejs.t +150 -0
- package/templates/entity/new/clean-lite-ps/use-cases/delete.ejs.t +70 -0
- package/templates/entity/new/clean-lite-ps/use-cases/find-by-id-with-fields.ejs.t +19 -0
- package/templates/entity/new/clean-lite-ps/use-cases/find-by-id.ejs.t +7 -3
- package/templates/entity/new/clean-lite-ps/use-cases/list-with-fields.ejs.t +17 -0
- package/templates/entity/new/clean-lite-ps/use-cases/search.ejs.t +63 -0
- package/templates/entity/new/clean-lite-ps/use-cases/update.ejs.t +153 -0
- package/templates/entity/new/prompt.js +284 -41
- package/templates/relationship/new/entity.ejs.t +2 -2
- package/templates/relationship/new/prompt.js +3 -7
- package/templates/relationship/new/service.ejs.t +1 -1
- package/templates/subsystem/bridge/generated-keep.ejs.t +4 -0
- package/templates/subsystem/bridge/prompt.js +36 -0
- package/templates/subsystem/bridge-config/codegen-config-bridge-block.ejs.t +20 -0
- package/templates/subsystem/bridge-config/prompt.js +20 -0
- package/templates/subsystem/events/domain-events.schema.ejs.t +81 -0
- package/templates/subsystem/events/generated-keep.ejs.t +4 -0
- package/templates/subsystem/events/prompt.js +39 -0
- package/templates/subsystem/events-config/codegen-config-events-block.ejs.t +26 -0
- package/templates/subsystem/events-config/prompt.js +20 -0
- package/templates/subsystem/jobs/job-orchestration.schema.ejs.t +221 -0
- package/templates/subsystem/jobs/main-hook.ejs.t +11 -0
- package/templates/subsystem/jobs/prompt.js +40 -0
- package/templates/subsystem/jobs/worker.ejs.t +82 -0
- package/templates/subsystem/jobs-config/codegen-config-jobs-block.ejs.t +55 -0
- package/templates/subsystem/jobs-config/prompt.js +20 -0
- package/templates/subsystem/sync/prompt.js +43 -0
- package/templates/subsystem/sync/sync-audit.schema.ejs.t +195 -0
- package/templates/subsystem/sync-config/codegen-config-sync-block.ejs.t +29 -0
- package/templates/subsystem/sync-config/prompt.js +22 -0
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/parser/load-entities.ts","../../src/utils/yaml-loader.ts","../../src/schema/entity-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/formatters/console-formatter.ts","../../src/formatters/json-formatter.ts","../../src/formatters/markdown-formatter.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 type { EntityFamily } from '../analyzer/types.js';\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\tconst queries: ParsedQuery[] | undefined = definition.queries?.map((q) => ({\n\t\tby: q.by,\n\t\tunique: q.unique,\n\t\tselect: q.select,\n\t\torder: q.order,\n\t\tlimit: q.limit,\n\t\tvia: q.via,\n\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\tfamily: definition.entity.family as EntityFamily | undefined,\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\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\tconst queries: ParsedQuery[] | undefined = definition.queries?.map((q) => ({\n\t\tby: q.by,\n\t\tunique: q.unique,\n\t\tselect: q.select,\n\t\torder: q.order,\n\t\tlimit: q.limit,\n\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 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 * 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\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 })\n .strict();\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 // v2: Entity family classification (ADR-005)\n // Determines which base class hierarchy the entity inherits from\n family: z\n .enum([\"base\", \"synced\", \"activity\", \"knowledge\", \"metadata\"])\n .optional(),\n })\n .strict();\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// 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\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 // v2: Declarative query generation (ADR-005)\n // Generates repository + service + use case methods from declarations\n queries: z.array(QueryDeclarationSchema).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 // v2: Analytics / semantic layer configuration\n // Cube.js measure packs, custom cube name, and metric definitions\n analytics: AnalyticsBlockSchema.optional(),\n })\n .strict();\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 decimal: \"z.number()\",\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 * 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 * 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 * 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 type { AnalysisResult, OutputFormat } from './analyzer/types';\n\n/**\n * Analyze a domain from entity and relationship YAML files\n */\nexport async function analyzeDomain(\n\tentitiesDir: string,\n\trelationshipsDir?: string,\n): Promise<AnalysisResult> {\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// 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];\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"],"mappings":"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","names":["z"]}
|
|
1
|
+
{"version":3,"sources":["../../src/parser/load-entities.ts","../../src/utils/yaml-loader.ts","../../src/schema/entity-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/formatters/console-formatter.ts","../../src/formatters/json-formatter.ts","../../src/formatters/markdown-formatter.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 type { EntityFamily } from '../analyzer/types.js';\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\tconst queries: ParsedQuery[] | undefined = definition.queries?.map((q) => ({\n\t\tby: q.by,\n\t\tunique: q.unique,\n\t\tselect: q.select,\n\t\torder: q.order,\n\t\tlimit: q.limit,\n\t\tvia: q.via,\n\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\tfamily: definition.entity.family as EntityFamily | undefined,\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\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\tconst queries: ParsedQuery[] | undefined = definition.queries?.map((q) => ({\n\t\tby: q.by,\n\t\tunique: q.unique,\n\t\tselect: q.select,\n\t\torder: q.order,\n\t\tlimit: q.limit,\n\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 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 * 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\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 })\n .strict();\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 // v2: Entity family classification (ADR-005)\n // Determines which base class hierarchy the entity inherits from\n family: z\n .enum([\"base\", \"synced\", \"activity\", \"knowledge\", \"metadata\"])\n .optional(),\n })\n .strict();\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// 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\n // v2: Declarative query generation (ADR-005)\n // Generates repository + service + use case methods from declarations\n queries: z.array(QueryDeclarationSchema).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 // v2: Analytics / semantic layer configuration\n // Cube.js measure packs, custom cube name, and metric definitions\n analytics: AnalyticsBlockSchema.optional(),\n })\n .strict();\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 decimal: \"z.number()\",\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 * 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 * 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 * 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 type { AnalysisResult, OutputFormat } from './analyzer/types';\n\n/**\n * Analyze a domain from entity and relationship YAML files\n */\nexport async function analyzeDomain(\n\tentitiesDir: string,\n\trelationshipsDir?: string,\n): Promise<AnalysisResult> {\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// 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];\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"],"mappings":"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","names":["z"]}
|