@mateusseiboth/ember-orm 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema/index.ts","../src/errors/index.ts","../src/schema/lexer.ts","../src/schema/parser.ts","../src/ast/index.ts","../src/schema/validator.ts","../src/schema/printer.ts","../src/utils/index.ts","../src/schema/relations-complete.ts"],"sourcesContent":["import { readFileSync, existsSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport type { SchemaDocument } from \"@ember/ast\";\nimport { Parser } from \"./parser\";\nimport { validateSchema } from \"./validator\";\nimport { printSchema } from \"./printer\";\nimport { completeRelations } from \"./relations-complete\";\n\nexport { Parser } from \"./parser\";\nexport { Lexer } from \"./lexer\";\nexport { validateSchema, printSchema, completeRelations };\n\n/**\n * Canonical formatter: parse, auto-complete missing relation sides (like\n * Prisma's formatter), validate, and re-print with aligned formatting.\n */\nexport function formatSchema(source: string, file?: string): string {\n const doc = completeRelations(parseSchema(source, file));\n validateSchema(doc);\n return printSchema(doc);\n}\n\n/** Parse schema source text into an AST (no validation). */\nexport function parseSchema(source: string, file?: string): SchemaDocument {\n return new Parser(source, file).parse();\n}\n\n/** Parse and validate schema source text. */\nexport function parseAndValidate(source: string, file?: string): SchemaDocument {\n const doc = parseSchema(source, file);\n validateSchema(doc);\n return doc;\n}\n\nexport interface LoadedSchema {\n document: SchemaDocument;\n path: string;\n /** Resolved connection URL (env() expanded). */\n databaseUrl?: string;\n}\n\nconst DEFAULT_SCHEMA_PATHS = [\n \"ember/schema.ember\",\n \"schema.ember\",\n \"prisma/schema.ember\",\n];\n\n/** Locate the schema file relative to a base directory. */\nexport function findSchemaPath(\n base = process.cwd(),\n explicit?: string,\n): string | undefined {\n if (explicit) {\n const p = resolve(base, explicit);\n return existsSync(p) ? p : undefined;\n }\n for (const candidate of DEFAULT_SCHEMA_PATHS) {\n const p = resolve(base, candidate);\n if (existsSync(p)) return p;\n }\n return undefined;\n}\n\n/** Load, parse, validate a schema file and resolve its datasource URL. */\nexport function loadSchema(path: string): LoadedSchema {\n const source = readFileSync(path, \"utf8\");\n const document = parseAndValidate(source, path);\n return {\n document,\n path,\n databaseUrl: resolveDatasourceUrl(document, dirname(path)),\n };\n}\n\nexport function resolveDatasourceUrl(\n doc: SchemaDocument,\n _base: string,\n): string | undefined {\n const ds = doc.datasource;\n if (!ds) return undefined;\n if (ds.url.kind === \"literal\") return ds.url.value;\n return process.env[ds.url.value];\n}\n","/** Base class for every error thrown by EmberORM. */\nexport class EmberError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised while lexing/parsing a `.ember` schema file. */\nexport class SchemaParseError extends EmberError {\n constructor(\n message: string,\n public readonly line: number,\n public readonly column: number,\n public readonly file?: string,\n ) {\n super(\n `${message} (at ${file ? `${file}:` : \"\"}${line}:${column})`,\n );\n }\n}\n\n/** Raised when a parsed schema is structurally invalid. */\nexport class SchemaValidationError extends EmberError {\n constructor(\n message: string,\n public readonly details: string[] = [],\n ) {\n super(\n details.length > 0 ? `${message}\\n - ${details.join(\"\\n - \")}` : message,\n );\n }\n}\n\n/** Raised when a query is malformed before it reaches the database. */\nexport class QueryValidationError extends EmberError {}\n\n/** Wraps a low-level driver/database failure with EmberORM context. */\nexport class DatabaseError extends EmberError {\n constructor(\n message: string,\n public override readonly cause?: unknown,\n public readonly sql?: string,\n ) {\n super(message);\n }\n}\n\n/** Thrown by `*OrThrow` operations when no record matches. */\nexport class RecordNotFoundError extends EmberError {\n constructor(model: string) {\n super(`No '${model}' record found matching the given criteria.`);\n }\n}\n\n/** Thrown on unique constraint violations (mapped from Firebird errors). */\nexport class UniqueConstraintError extends EmberError {\n constructor(\n public readonly target: string,\n cause?: unknown,\n ) {\n super(`Unique constraint failed on: ${target}`);\n if (cause !== undefined) this.cause = cause;\n }\n}\n","import { SchemaParseError } from \"@ember/errors\";\n\nexport type TokenType =\n | \"identifier\"\n | \"string\"\n | \"number\"\n | \"lbrace\"\n | \"rbrace\"\n | \"lparen\"\n | \"rparen\"\n | \"lbracket\"\n | \"rbracket\"\n | \"equals\"\n | \"comma\"\n | \"colon\"\n | \"at\"\n | \"double_at\"\n | \"question\"\n | \"dot\"\n | \"doc_comment\"\n | \"eof\";\n\nexport interface Token {\n type: TokenType;\n value: string;\n line: number;\n column: number;\n}\n\nconst SINGLE_CHAR_TOKENS: Record<string, TokenType> = {\n \"{\": \"lbrace\",\n \"}\": \"rbrace\",\n \"(\": \"lparen\",\n \")\": \"rparen\",\n \"[\": \"lbracket\",\n \"]\": \"rbracket\",\n \"=\": \"equals\",\n \",\": \"comma\",\n \":\": \"colon\",\n \"?\": \"question\",\n \".\": \"dot\",\n};\n\nconst IDENT_START = /[A-Za-z_]/;\nconst IDENT_PART = /[A-Za-z0-9_]/;\n\n/**\n * Converts schema source text into a flat token stream.\n * Regular `//` comments are discarded; `///` doc comments are preserved as\n * `doc_comment` tokens so the parser can attach documentation to nodes.\n */\nexport class Lexer {\n private pos = 0;\n private line = 1;\n private column = 1;\n\n constructor(\n private readonly source: string,\n private readonly file?: string,\n ) {}\n\n tokenize(): Token[] {\n const tokens: Token[] = [];\n let token = this.next();\n while (token.type !== \"eof\") {\n tokens.push(token);\n token = this.next();\n }\n tokens.push(token); // eof\n return tokens;\n }\n\n private next(): Token {\n this.skipWhitespaceAndComments();\n if (this.pos >= this.source.length) {\n return this.make(\"eof\", \"\");\n }\n\n const startLine = this.line;\n const startColumn = this.column;\n const ch = this.source[this.pos]!;\n\n // Doc comment (/// ...) — re-check here because skip kept them.\n if (ch === \"/\" && this.peek(1) === \"/\" && this.peek(2) === \"/\") {\n return this.readDocComment(startLine, startColumn);\n }\n\n if (ch === '\"') {\n return this.readString(startLine, startColumn);\n }\n\n if (ch === \"@\") {\n this.advance();\n if (this.source[this.pos] === \"@\") {\n this.advance();\n return { type: \"double_at\", value: \"@@\", line: startLine, column: startColumn };\n }\n return { type: \"at\", value: \"@\", line: startLine, column: startColumn };\n }\n\n const single = SINGLE_CHAR_TOKENS[ch];\n if (single) {\n this.advance();\n return { type: single, value: ch, line: startLine, column: startColumn };\n }\n\n if (ch === \"-\" || /[0-9]/.test(ch)) {\n return this.readNumber(startLine, startColumn);\n }\n\n if (IDENT_START.test(ch)) {\n return this.readIdentifier(startLine, startColumn);\n }\n\n throw new SchemaParseError(\n `Unexpected character '${ch}'`,\n startLine,\n startColumn,\n this.file,\n );\n }\n\n private readDocComment(line: number, column: number): Token {\n this.advance(); // /\n this.advance(); // /\n this.advance(); // /\n let value = \"\";\n while (this.pos < this.source.length && this.source[this.pos] !== \"\\n\") {\n value += this.source[this.pos];\n this.advance();\n }\n return { type: \"doc_comment\", value: value.trim(), line, column };\n }\n\n private readString(line: number, column: number): Token {\n this.advance(); // opening quote\n let value = \"\";\n while (this.pos < this.source.length && this.source[this.pos] !== '\"') {\n const c = this.source[this.pos]!;\n if (c === \"\\\\\") {\n this.advance();\n const escaped = this.source[this.pos];\n if (escaped === undefined) break;\n value += escapeChar(escaped);\n this.advance();\n continue;\n }\n if (c === \"\\n\") {\n throw new SchemaParseError(\n \"Unterminated string literal\",\n line,\n column,\n this.file,\n );\n }\n value += c;\n this.advance();\n }\n if (this.source[this.pos] !== '\"') {\n throw new SchemaParseError(\n \"Unterminated string literal\",\n line,\n column,\n this.file,\n );\n }\n this.advance(); // closing quote\n return { type: \"string\", value, line, column };\n }\n\n private readNumber(line: number, column: number): Token {\n let value = \"\";\n if (this.source[this.pos] === \"-\") {\n value += \"-\";\n this.advance();\n }\n while (\n this.pos < this.source.length &&\n /[0-9.]/.test(this.source[this.pos]!)\n ) {\n value += this.source[this.pos];\n this.advance();\n }\n return { type: \"number\", value, line, column };\n }\n\n private readIdentifier(line: number, column: number): Token {\n let value = \"\";\n while (\n this.pos < this.source.length &&\n IDENT_PART.test(this.source[this.pos]!)\n ) {\n value += this.source[this.pos];\n this.advance();\n }\n return { type: \"identifier\", value, line, column };\n }\n\n private skipWhitespaceAndComments(): void {\n while (this.pos < this.source.length) {\n const ch = this.source[this.pos]!;\n if (ch === \" \" || ch === \"\\t\" || ch === \"\\r\" || ch === \"\\n\") {\n this.advance();\n continue;\n }\n // Keep doc comments (///) — only skip plain // comments.\n if (ch === \"/\" && this.peek(1) === \"/\" && this.peek(2) !== \"/\") {\n while (this.pos < this.source.length && this.source[this.pos] !== \"\\n\") {\n this.advance();\n }\n continue;\n }\n if (ch === \"/\" && this.peek(1) === \"*\") {\n this.advance();\n this.advance();\n while (\n this.pos < this.source.length &&\n !(this.source[this.pos] === \"*\" && this.peek(1) === \"/\")\n ) {\n this.advance();\n }\n this.advance();\n this.advance();\n continue;\n }\n break;\n }\n }\n\n private peek(offset: number): string | undefined {\n return this.source[this.pos + offset];\n }\n\n private advance(): void {\n if (this.source[this.pos] === \"\\n\") {\n this.line++;\n this.column = 1;\n } else {\n this.column++;\n }\n this.pos++;\n }\n\n private make(type: TokenType, value: string): Token {\n return { type, value, line: this.line, column: this.column };\n }\n}\n\nfunction escapeChar(c: string): string {\n switch (c) {\n case \"n\":\n return \"\\n\";\n case \"t\":\n return \"\\t\";\n case \"r\":\n return \"\\r\";\n case '\"':\n return '\"';\n case \"\\\\\":\n return \"\\\\\";\n default:\n return c;\n }\n}\n","import { SchemaParseError } from \"@ember/errors\";\nimport {\n type AttributeArgValue,\n type DatasourceNode,\n type DefaultValue,\n type EnumNode,\n type FieldNode,\n type GeneratorNode,\n type ModelNode,\n type NativeType,\n type ReferentialAction,\n type RelationInfo,\n type SchemaDocument,\n} from \"@ember/ast\";\nimport { Lexer, type Token, type TokenType } from \"./lexer\";\n\ninterface RawAttribute {\n name: string; // e.g. \"id\", \"default\", \"relation\", \"db.VarChar\"\n args: AttributeArgValue[];\n line: number;\n column: number;\n}\n\n/**\n * Recursive-descent parser that turns a token stream into a SchemaDocument.\n * Field `kind` (scalar/enum/object) is resolved in a second pass once all\n * model and enum names are known (see `resolveKinds`).\n */\nexport class Parser {\n private tokens: Token[];\n private pos = 0;\n\n constructor(\n source: string,\n private readonly file?: string,\n ) {\n this.tokens = new Lexer(source, file).tokenize();\n }\n\n parse(): SchemaDocument {\n const doc: SchemaDocument = { generators: [], models: [], enums: [] };\n let pendingDoc: string[] = [];\n\n while (!this.isEof()) {\n const tok = this.peek();\n if (tok.type === \"doc_comment\") {\n pendingDoc.push(tok.value);\n this.advance();\n continue;\n }\n if (tok.type !== \"identifier\") {\n throw this.error(`Unexpected token '${tok.value}'`, tok);\n }\n const documentation = pendingDoc.length\n ? pendingDoc.join(\"\\n\")\n : undefined;\n pendingDoc = [];\n\n switch (tok.value) {\n case \"datasource\":\n doc.datasource = this.parseDatasource();\n break;\n case \"generator\":\n doc.generators.push(this.parseGenerator());\n break;\n case \"model\":\n doc.models.push(this.parseModel(documentation));\n break;\n case \"enum\":\n doc.enums.push(this.parseEnum(documentation));\n break;\n default:\n throw this.error(`Unknown top-level keyword '${tok.value}'`, tok);\n }\n }\n\n resolveKinds(doc);\n return doc;\n }\n\n // ---- Top-level blocks -------------------------------------------------\n\n private parseDatasource(): DatasourceNode {\n this.expectKeyword(\"datasource\");\n const name = this.expect(\"identifier\").value;\n this.expect(\"lbrace\");\n const assignments = this.parseAssignments();\n this.expect(\"rbrace\");\n\n const provider = literalString(assignments[\"provider\"]);\n const urlAssign = assignments[\"url\"];\n let url: DatasourceNode[\"url\"] = { kind: \"literal\", value: \"\" };\n if (urlAssign) {\n if (urlAssign.kind === \"function\" && urlAssign.name === \"env\") {\n url = { kind: \"env\", value: literalString(urlAssign.args[0]) };\n } else if (urlAssign.kind === \"string\") {\n url = { kind: \"literal\", value: urlAssign.value };\n }\n }\n return { name, provider: provider ?? \"firebird\", url };\n }\n\n private parseGenerator(): GeneratorNode {\n this.expectKeyword(\"generator\");\n const name = this.expect(\"identifier\").value;\n this.expect(\"lbrace\");\n const assignments = this.parseAssignments();\n this.expect(\"rbrace\");\n\n const config: Record<string, string> = {};\n for (const [key, value] of Object.entries(assignments)) {\n if (value.kind === \"string\") config[key] = value.value;\n }\n return {\n name,\n provider: literalString(assignments[\"provider\"]) ?? \"ember-client-js\",\n output: assignments[\"output\"]\n ? literalString(assignments[\"output\"])\n : undefined,\n config,\n };\n }\n\n private parseAssignments(): Record<string, AttributeArgValue> {\n const out: Record<string, AttributeArgValue> = {};\n while (!this.check(\"rbrace\") && !this.isEof()) {\n if (this.check(\"doc_comment\")) {\n this.advance();\n continue;\n }\n const key = this.expect(\"identifier\").value;\n this.expect(\"equals\");\n out[key] = this.parseValue();\n }\n return out;\n }\n\n private parseModel(documentation?: string): ModelNode {\n this.expectKeyword(\"model\");\n const name = this.expect(\"identifier\").value;\n this.expect(\"lbrace\");\n\n const model: ModelNode = {\n name,\n fields: [],\n primaryKey: [],\n uniqueIndexes: [],\n indexes: [],\n documentation,\n };\n\n let pendingDoc: string[] = [];\n while (!this.check(\"rbrace\") && !this.isEof()) {\n const tok = this.peek();\n if (tok.type === \"doc_comment\") {\n pendingDoc.push(tok.value);\n this.advance();\n continue;\n }\n if (tok.type === \"double_at\") {\n this.parseBlockAttribute(model);\n pendingDoc = [];\n continue;\n }\n const field = this.parseField(\n pendingDoc.length ? pendingDoc.join(\"\\n\") : undefined,\n );\n pendingDoc = [];\n model.fields.push(field);\n // Promote inline @id / @unique to model metadata.\n if (field.isId && !model.primaryKey.includes(field.name)) {\n model.primaryKey.push(field.name);\n }\n }\n this.expect(\"rbrace\");\n return model;\n }\n\n private parseField(documentation?: string): FieldNode {\n const name = this.expect(\"identifier\").value;\n const typeName = this.expect(\"identifier\").value;\n\n let isList = false;\n let isRequired = true;\n // Order-independent handling of `[]` and `?`.\n while (this.check(\"lbracket\") || this.check(\"question\")) {\n if (this.check(\"lbracket\")) {\n this.advance();\n this.expect(\"rbracket\");\n isList = true;\n } else {\n this.advance();\n isRequired = false;\n }\n }\n\n const field: FieldNode = {\n name,\n type: typeName,\n kind: \"scalar\", // resolved later\n isList,\n isRequired,\n isId: false,\n isUnique: false,\n isUpdatedAt: false,\n documentation,\n };\n\n while (this.check(\"at\")) {\n const attr = this.parseAttribute();\n this.applyFieldAttribute(field, attr);\n }\n return field;\n }\n\n private applyFieldAttribute(field: FieldNode, attr: RawAttribute): void {\n if (attr.name.startsWith(\"db.\")) {\n field.nativeType = toNativeType(attr);\n return;\n }\n switch (attr.name) {\n case \"id\":\n field.isId = true;\n break;\n case \"unique\":\n field.isUnique = true;\n break;\n case \"updatedAt\":\n field.isUpdatedAt = true;\n break;\n case \"default\":\n field.default = toDefaultValue(attr.args[0]);\n break;\n case \"map\":\n field.dbName = literalString(attr.args[0]);\n break;\n case \"relation\":\n field.relation = toRelationInfo(attr.args);\n break;\n default:\n throw this.error(`Unknown field attribute '@${attr.name}'`, attr);\n }\n }\n\n private parseBlockAttribute(model: ModelNode): void {\n const start = this.expect(\"double_at\");\n const name = this.expect(\"identifier\").value;\n const args = this.check(\"lparen\") ? this.parseArgList() : [];\n\n switch (name) {\n case \"id\":\n model.primaryKey = fieldNameList(args);\n break;\n case \"unique\":\n model.uniqueIndexes.push({\n fields: fieldNameList(args),\n name: namedArg(args, \"map\"),\n });\n break;\n case \"index\":\n model.indexes.push({\n fields: fieldNameList(args),\n name: namedArg(args, \"map\"),\n unique: false,\n });\n break;\n case \"map\":\n model.dbName = literalString(args[0]);\n break;\n default:\n throw this.error(`Unknown block attribute '@@${name}'`, start);\n }\n }\n\n private parseEnum(documentation?: string): EnumNode {\n this.expectKeyword(\"enum\");\n const name = this.expect(\"identifier\").value;\n this.expect(\"lbrace\");\n const node: EnumNode = { name, values: [], documentation };\n\n while (!this.check(\"rbrace\") && !this.isEof()) {\n if (this.check(\"doc_comment\")) {\n this.advance();\n continue;\n }\n if (this.check(\"double_at\")) {\n this.advance();\n const attrName = this.expect(\"identifier\").value;\n const args = this.check(\"lparen\") ? this.parseArgList() : [];\n if (attrName === \"map\") node.dbName = literalString(args[0]);\n continue;\n }\n const valueName = this.expect(\"identifier\").value;\n let dbName: string | undefined;\n while (this.check(\"at\")) {\n const attr = this.parseAttribute();\n if (attr.name === \"map\") dbName = literalString(attr.args[0]);\n }\n node.values.push({ name: valueName, dbName });\n }\n this.expect(\"rbrace\");\n return node;\n }\n\n // ---- Attributes & values ---------------------------------------------\n\n private parseAttribute(): RawAttribute {\n const at = this.expect(\"at\");\n let name = this.expect(\"identifier\").value;\n // Native type attributes look like @db.VarChar(255).\n if (this.check(\"dot\")) {\n this.advance();\n name += \".\" + this.expect(\"identifier\").value;\n }\n const args = this.check(\"lparen\") ? this.parseArgList() : [];\n return { name, args, line: at.line, column: at.column };\n }\n\n private parseArgList(): AttributeArgValue[] {\n this.expect(\"lparen\");\n const args: AttributeArgValue[] = [];\n while (!this.check(\"rparen\") && !this.isEof()) {\n args.push(this.parseArg());\n if (this.check(\"comma\")) this.advance();\n }\n this.expect(\"rparen\");\n return args;\n }\n\n /** Handles both positional values and `name: value` named arguments. */\n private parseArg(): AttributeArgValue {\n if (this.check(\"identifier\") && this.peek(1)?.type === \"colon\") {\n const key = this.expect(\"identifier\").value;\n this.expect(\"colon\");\n const value = this.parseValue();\n return { kind: \"function\", name: `__named:${key}`, args: [value] };\n }\n return this.parseValue();\n }\n\n private parseValue(): AttributeArgValue {\n const tok = this.peek();\n switch (tok.type) {\n case \"string\":\n this.advance();\n return { kind: \"string\", value: tok.value };\n case \"number\":\n this.advance();\n return { kind: \"number\", value: Number(tok.value) };\n case \"lbracket\": {\n this.advance();\n const items: AttributeArgValue[] = [];\n while (!this.check(\"rbracket\") && !this.isEof()) {\n items.push(this.parseValue());\n if (this.check(\"comma\")) this.advance();\n }\n this.expect(\"rbracket\");\n return { kind: \"array\", items };\n }\n case \"identifier\": {\n this.advance();\n if (tok.value === \"true\" || tok.value === \"false\") {\n return { kind: \"boolean\", value: tok.value === \"true\" };\n }\n if (this.check(\"lparen\")) {\n const args = this.parseArgList();\n return { kind: \"function\", name: tok.value, args };\n }\n return { kind: \"ref\", value: tok.value };\n }\n default:\n throw this.error(`Unexpected value token '${tok.value}'`, tok);\n }\n }\n\n // ---- Token helpers ----------------------------------------------------\n\n private peek(offset = 0): Token {\n return this.tokens[this.pos + offset] ?? this.tokens[this.tokens.length - 1]!;\n }\n\n private advance(): Token {\n const tok = this.tokens[this.pos]!;\n if (this.pos < this.tokens.length - 1) this.pos++;\n return tok;\n }\n\n private check(type: TokenType): boolean {\n return this.peek().type === type;\n }\n\n private isEof(): boolean {\n return this.peek().type === \"eof\";\n }\n\n private expect(type: TokenType): Token {\n const tok = this.peek();\n if (tok.type !== type) {\n throw this.error(`Expected ${type} but found '${tok.value}' (${tok.type})`, tok);\n }\n return this.advance();\n }\n\n private expectKeyword(keyword: string): Token {\n const tok = this.peek();\n if (tok.type !== \"identifier\" || tok.value !== keyword) {\n throw this.error(`Expected keyword '${keyword}'`, tok);\n }\n return this.advance();\n }\n\n private error(message: string, at: { line: number; column: number }) {\n return new SchemaParseError(message, at.line, at.column, this.file);\n }\n}\n\n// ---- Value coercion helpers --------------------------------------------\n\nfunction literalString(v: AttributeArgValue | undefined): string {\n if (!v) return \"\";\n if (v.kind === \"string\") return v.value;\n if (v.kind === \"ref\") return v.value;\n return String(\"value\" in v ? v.value : \"\");\n}\n\nfunction toNativeType(attr: RawAttribute): NativeType {\n const name = attr.name.slice(\"db.\".length);\n const args = attr.args\n .filter((a) => a.kind === \"number\")\n .map((a) => (a as { value: number }).value);\n return { name, args };\n}\n\nfunction toDefaultValue(v: AttributeArgValue | undefined): DefaultValue {\n if (!v) return {};\n switch (v.kind) {\n case \"function\":\n return { function: { name: v.name, args: v.args } };\n case \"string\":\n return { literal: v.value };\n case \"number\":\n return { literal: v.value };\n case \"boolean\":\n return { literal: v.value };\n case \"ref\":\n // enum value default such as @default(USER)\n return { literal: v.value };\n default:\n return {};\n }\n}\n\nfunction toRelationInfo(args: AttributeArgValue[]): RelationInfo {\n const info: RelationInfo = {};\n for (const arg of args) {\n if (arg.kind === \"string\") {\n info.name = arg.value;\n continue;\n }\n const named = asNamed(arg);\n if (!named) continue;\n const [key, value] = named;\n if (key === \"name\" && value.kind === \"string\") info.name = value.value;\n if (key === \"fields\") info.fields = refArray(value);\n if (key === \"references\") info.references = refArray(value);\n if (key === \"onDelete\") info.onDelete = refName(value) as ReferentialAction;\n if (key === \"onUpdate\") info.onUpdate = refName(value) as ReferentialAction;\n }\n return info;\n}\n\nfunction asNamed(\n arg: AttributeArgValue,\n): [string, AttributeArgValue] | undefined {\n if (arg.kind === \"function\" && arg.name.startsWith(\"__named:\")) {\n return [arg.name.slice(\"__named:\".length), arg.args[0]!];\n }\n return undefined;\n}\n\nfunction namedArg(args: AttributeArgValue[], key: string): string | undefined {\n for (const arg of args) {\n const named = asNamed(arg);\n if (named && named[0] === key && named[1].kind === \"string\") {\n return named[1].value;\n }\n }\n return undefined;\n}\n\nfunction refArray(v: AttributeArgValue): string[] {\n if (v.kind === \"array\") {\n return v.items.map((i) => refName(i)).filter((s): s is string => !!s);\n }\n const single = refName(v);\n return single ? [single] : [];\n}\n\nfunction refName(v: AttributeArgValue): string | undefined {\n if (v.kind === \"ref\") return v.value;\n if (v.kind === \"string\") return v.value;\n return undefined;\n}\n\n/** A list of bare field references, used by @@id/@@unique/@@index. */\nfunction fieldNameList(args: AttributeArgValue[]): string[] {\n for (const arg of args) {\n if (arg.kind === \"array\") return refArray(arg);\n const named = asNamed(arg);\n if (named && named[0] === \"fields\") return refArray(named[1]);\n }\n // single bare ref form: @@id(field)\n return args.map((a) => refName(a)).filter((s): s is string => !!s);\n}\n\n/**\n * Second pass: now that all model and enum names are known, classify each\n * field as scalar, enum, or object (relation).\n */\nfunction resolveKinds(doc: SchemaDocument): void {\n const modelNames = new Set(doc.models.map((m) => m.name));\n const enumNames = new Set(doc.enums.map((e) => e.name));\n for (const model of doc.models) {\n for (const field of model.fields) {\n if (modelNames.has(field.type)) field.kind = \"object\";\n else if (enumNames.has(field.type)) field.kind = \"enum\";\n else field.kind = \"scalar\";\n }\n }\n}\n","/**\n * EmberORM schema AST (DMMF-like).\n *\n * This is the single in-memory source of truth that every other layer\n * (parser, validator, query engine, generator, introspection) depends on.\n * It is intentionally decoupled from Firebird specifics so it can be reused\n * for other dialects in the future.\n */\n\nexport type ScalarType =\n | \"String\"\n | \"Boolean\"\n | \"Int\"\n | \"BigInt\"\n | \"Float\"\n | \"Decimal\"\n | \"DateTime\"\n | \"Bytes\"\n | \"Json\";\n\nexport const SCALAR_TYPES: readonly ScalarType[] = [\n \"String\",\n \"Boolean\",\n \"Int\",\n \"BigInt\",\n \"Float\",\n \"Decimal\",\n \"DateTime\",\n \"Bytes\",\n \"Json\",\n] as const;\n\nexport type FieldKind = \"scalar\" | \"enum\" | \"object\";\n\n/** Value of an attribute argument, e.g. `@default(now())` or `@map(\"USER_ID\")`. */\nexport type AttributeArgValue =\n | { kind: \"string\"; value: string }\n | { kind: \"number\"; value: number }\n | { kind: \"boolean\"; value: boolean }\n | { kind: \"ref\"; value: string } // bare identifier, e.g. an enum value or field name\n | { kind: \"function\"; name: string; args: AttributeArgValue[] } // e.g. now(), autoincrement()\n | { kind: \"array\"; items: AttributeArgValue[] };\n\nexport interface DefaultValue {\n /** A scalar literal default. */\n literal?: string | number | boolean;\n /** A function default such as now(), uuid(), cuid(), autoincrement(). */\n function?: { name: string; args: AttributeArgValue[] };\n}\n\nexport interface RelationInfo {\n /** Relation name (@relation(\"name\")). */\n name?: string;\n /** Local fields participating in the FK (`fields: [...]`). */\n fields?: string[];\n /** Referenced fields on the other model (`references: [...]`). */\n references?: string[];\n onDelete?: ReferentialAction;\n onUpdate?: ReferentialAction;\n}\n\nexport type ReferentialAction =\n | \"Cascade\"\n | \"Restrict\"\n | \"NoAction\"\n | \"SetNull\"\n | \"SetDefault\";\n\nexport interface NativeType {\n /** e.g. \"VarChar\", \"Decimal\". */\n name: string;\n /** e.g. [255] or [18, 4]. */\n args: number[];\n}\n\nexport interface FieldNode {\n name: string;\n /** Resolved type name: a ScalarType, an enum name, or a model name. */\n type: string;\n kind: FieldKind;\n isList: boolean;\n isRequired: boolean;\n isId: boolean;\n isUnique: boolean;\n isUpdatedAt: boolean;\n /** Column name in the database (@map). Defaults to `name`. */\n dbName?: string;\n default?: DefaultValue;\n relation?: RelationInfo;\n nativeType?: NativeType;\n /** documentation/comment attached above the field (///). */\n documentation?: string;\n}\n\nexport interface UniqueIndex {\n name?: string;\n fields: string[];\n}\n\nexport interface IndexNode {\n name?: string;\n fields: string[];\n unique: boolean;\n}\n\nexport interface ModelNode {\n name: string;\n /** Table name in the database (@@map). Defaults to `name`. */\n dbName?: string;\n fields: FieldNode[];\n /** Names of fields forming the primary key (composite supported via @@id). */\n primaryKey: string[];\n uniqueIndexes: UniqueIndex[];\n indexes: IndexNode[];\n documentation?: string;\n}\n\nexport interface EnumNode {\n name: string;\n dbName?: string;\n values: { name: string; dbName?: string }[];\n documentation?: string;\n}\n\nexport interface DatasourceNode {\n name: string;\n provider: string;\n /** Raw url expression; env(\"X\") resolved at runtime. */\n url: { kind: \"literal\" | \"env\"; value: string };\n}\n\nexport interface GeneratorNode {\n name: string;\n provider: string;\n output?: string;\n config: Record<string, string>;\n}\n\nexport interface SchemaDocument {\n datasource?: DatasourceNode;\n generators: GeneratorNode[];\n models: ModelNode[];\n enums: EnumNode[];\n}\n\nexport function emptySchema(): SchemaDocument {\n return { generators: [], models: [], enums: [] };\n}\n\nexport function findModel(\n schema: SchemaDocument,\n name: string,\n): ModelNode | undefined {\n return schema.models.find((m) => m.name === name);\n}\n\nexport function findEnum(\n schema: SchemaDocument,\n name: string,\n): EnumNode | undefined {\n return schema.enums.find((e) => e.name === name);\n}\n\n/**\n * Physical column name. Firebird folds unquoted identifiers to UPPER CASE, and\n * EmberORM always quotes identifiers, so a field without an explicit `@map`\n * resolves to its UPPER-CASED name to match the stored column. Use `@map` to\n * target a column created with case-sensitive (quoted) lower/mixed case.\n */\nexport function fieldColumn(field: FieldNode): string {\n return field.dbName ?? field.name.toUpperCase();\n}\n\n/** Physical table name; same UPPER-CASE folding rule as {@link fieldColumn}. */\nexport function modelTable(model: ModelNode): string {\n return model.dbName ?? model.name.toUpperCase();\n}\n\n/** Returns scalar fields only (excludes relation/object fields). */\nexport function scalarFields(model: ModelNode): FieldNode[] {\n return model.fields.filter((f) => f.kind !== \"object\");\n}\n\n/** Returns relation (object) fields only. */\nexport function relationFields(model: ModelNode): FieldNode[] {\n return model.fields.filter((f) => f.kind === \"object\");\n}\n\nexport function idFields(model: ModelNode): FieldNode[] {\n if (model.primaryKey.length > 0) {\n return model.primaryKey\n .map((n) => model.fields.find((f) => f.name === n))\n .filter((f): f is FieldNode => !!f);\n }\n return model.fields.filter((f) => f.isId);\n}\n","import { SchemaValidationError } from \"@ember/errors\";\nimport {\n SCALAR_TYPES,\n type SchemaDocument,\n findModel,\n} from \"@ember/ast\";\n\n/**\n * Structural validation of a parsed schema. Throws SchemaValidationError with\n * all detected problems at once so the user can fix them in a single pass.\n */\nexport function validateSchema(doc: SchemaDocument): void {\n const errors: string[] = [];\n const scalar = new Set<string>(SCALAR_TYPES);\n const enumNames = new Set(doc.enums.map((e) => e.name));\n const modelNames = new Set(doc.models.map((m) => m.name));\n\n const duplicateModels = findDuplicates(doc.models.map((m) => m.name));\n for (const name of duplicateModels) {\n errors.push(`Duplicate model '${name}'.`);\n }\n\n for (const model of doc.models) {\n const fieldNames = new Set<string>();\n for (const field of model.fields) {\n if (fieldNames.has(field.name)) {\n errors.push(`Duplicate field '${model.name}.${field.name}'.`);\n }\n fieldNames.add(field.name);\n\n const known =\n scalar.has(field.type) ||\n enumNames.has(field.type) ||\n modelNames.has(field.type);\n if (!known) {\n errors.push(\n `Field '${model.name}.${field.name}' has unknown type '${field.type}'.`,\n );\n }\n\n if (field.kind === \"object\" && field.relation) {\n validateRelation(doc, model.name, field.name, field.relation, errors);\n }\n }\n\n for (const pk of model.primaryKey) {\n if (!fieldNames.has(pk)) {\n errors.push(\n `Primary key field '${pk}' does not exist on model '${model.name}'.`,\n );\n }\n }\n\n const hasId =\n model.primaryKey.length > 0 || model.fields.some((f) => f.isId);\n if (!hasId) {\n errors.push(\n `Model '${model.name}' has no @id / @@id. Every model needs a primary key.`,\n );\n }\n }\n\n for (const enumNode of doc.enums) {\n if (enumNode.values.length === 0) {\n errors.push(`Enum '${enumNode.name}' has no values.`);\n }\n }\n\n if (errors.length > 0) {\n throw new SchemaValidationError(\"Schema validation failed\", errors);\n }\n}\n\nfunction validateRelation(\n doc: SchemaDocument,\n modelName: string,\n fieldName: string,\n relation: { fields?: string[]; references?: string[] },\n errors: string[],\n): void {\n const model = findModel(doc, modelName);\n if (!model) return;\n for (const f of relation.fields ?? []) {\n if (!model.fields.some((mf) => mf.name === f)) {\n errors.push(\n `Relation '${modelName}.${fieldName}' references local field '${f}' which does not exist.`,\n );\n }\n }\n}\n\nfunction findDuplicates(values: string[]): string[] {\n const seen = new Set<string>();\n const dups = new Set<string>();\n for (const v of values) {\n if (seen.has(v)) dups.add(v);\n seen.add(v);\n }\n return [...dups];\n}\n","import {\n type AttributeArgValue,\n type DefaultValue,\n type EnumNode,\n type FieldNode,\n type ModelNode,\n type SchemaDocument,\n} from \"@ember/ast\";\n\n/**\n * Serializes a SchemaDocument back into `.ember` source text.\n * Used by `ember db pull` (introspection output) and `ember format`.\n * Field columns are aligned for readability, mirroring Prisma's formatter.\n */\nexport function printSchema(doc: SchemaDocument): string {\n const blocks: string[] = [];\n\n if (doc.datasource) {\n const ds = doc.datasource;\n const url =\n ds.url.kind === \"env\"\n ? `env(\"${ds.url.value}\")`\n : `\"${ds.url.value}\"`;\n blocks.push(\n `datasource ${ds.name} {\\n provider = \"${ds.provider}\"\\n url = ${url}\\n}`,\n );\n }\n\n for (const gen of doc.generators) {\n const lines = [` provider = \"${gen.provider}\"`];\n if (gen.output) lines.push(` output = \"${gen.output}\"`);\n for (const [k, v] of Object.entries(gen.config)) {\n if (k === \"provider\" || k === \"output\") continue;\n lines.push(` ${k} = \"${v}\"`);\n }\n blocks.push(`generator ${gen.name} {\\n${lines.join(\"\\n\")}\\n}`);\n }\n\n for (const enumNode of doc.enums) {\n blocks.push(printEnum(enumNode));\n }\n\n for (const model of doc.models) {\n blocks.push(printModel(model));\n }\n\n return blocks.join(\"\\n\\n\") + \"\\n\";\n}\n\nfunction printEnum(node: EnumNode): string {\n const lines: string[] = [];\n if (node.documentation) lines.push(...docLines(node.documentation));\n lines.push(`enum ${node.name} {`);\n for (const v of node.values) {\n lines.push(` ${v.name}${v.dbName ? ` @map(\"${v.dbName}\")` : \"\"}`);\n }\n if (node.dbName) lines.push(`\\n @@map(\"${node.dbName}\")`);\n lines.push(`}`);\n return lines.join(\"\\n\");\n}\n\nfunction printModel(model: ModelNode): string {\n const lines: string[] = [];\n if (model.documentation) lines.push(...docLines(model.documentation));\n lines.push(`model ${model.name} {`);\n\n const nameWidth = Math.max(...model.fields.map((f) => f.name.length), 0);\n const typeWidth = Math.max(...model.fields.map((f) => fieldType(f).length), 0);\n\n for (const field of model.fields) {\n if (field.documentation) {\n lines.push(...docLines(field.documentation).map((l) => ` ${l}`));\n }\n const attrs = fieldAttributes(field);\n const name = field.name.padEnd(nameWidth);\n const type = fieldType(field).padEnd(typeWidth);\n lines.push(` ${name} ${type}${attrs ? ` ${attrs}` : \"\"}`.trimEnd());\n }\n\n const blockAttrs = modelBlockAttributes(model);\n if (blockAttrs.length > 0) {\n lines.push(\"\");\n for (const a of blockAttrs) lines.push(` ${a}`);\n }\n\n lines.push(`}`);\n return lines.join(\"\\n\");\n}\n\nfunction fieldType(field: FieldNode): string {\n let t = field.type;\n if (field.isList) t += \"[]\";\n else if (!field.isRequired) t += \"?\";\n return t;\n}\n\nfunction fieldAttributes(field: FieldNode): string {\n const parts: string[] = [];\n if (field.isId) parts.push(\"@id\");\n if (field.isUnique) parts.push(\"@unique\");\n if (field.default) parts.push(`@default(${printDefault(field.default)})`);\n if (field.isUpdatedAt) parts.push(\"@updatedAt\");\n if (field.relation) {\n const rel = field.relation;\n const args: string[] = [];\n if (rel.name) args.push(`\"${rel.name}\"`);\n if (rel.fields?.length) args.push(`fields: [${rel.fields.join(\", \")}]`);\n if (rel.references?.length)\n args.push(`references: [${rel.references.join(\", \")}]`);\n if (rel.onDelete) args.push(`onDelete: ${rel.onDelete}`);\n if (rel.onUpdate) args.push(`onUpdate: ${rel.onUpdate}`);\n parts.push(args.length ? `@relation(${args.join(\", \")})` : \"@relation\");\n }\n if (field.nativeType) {\n const a = field.nativeType.args.length\n ? `(${field.nativeType.args.join(\", \")})`\n : \"\";\n parts.push(`@db.${field.nativeType.name}${a}`);\n }\n if (field.dbName) parts.push(`@map(\"${field.dbName}\")`);\n return parts.join(\" \");\n}\n\nfunction printDefault(def: DefaultValue): string {\n if (def.function) {\n return `${def.function.name}(${def.function.args\n .map(printArgValue)\n .join(\", \")})`;\n }\n if (typeof def.literal === \"string\") {\n // enum/ref defaults are unquoted identifiers\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(def.literal)\n ? def.literal\n : `\"${def.literal}\"`;\n }\n return String(def.literal);\n}\n\nfunction printArgValue(v: AttributeArgValue): string {\n switch (v.kind) {\n case \"string\":\n return `\"${v.value}\"`;\n case \"number\":\n return String(v.value);\n case \"boolean\":\n return String(v.value);\n case \"ref\":\n return v.value;\n case \"array\":\n return `[${v.items.map(printArgValue).join(\", \")}]`;\n case \"function\":\n return `${v.name}(${v.args.map(printArgValue).join(\", \")})`;\n }\n}\n\nfunction modelBlockAttributes(model: ModelNode): string[] {\n const out: string[] = [];\n const inlineId =\n model.primaryKey.length === 1 &&\n model.fields.find((f) => f.name === model.primaryKey[0])?.isId;\n if (model.primaryKey.length > 0 && !inlineId) {\n out.push(`@@id([${model.primaryKey.join(\", \")}])`);\n }\n for (const u of model.uniqueIndexes) {\n out.push(\n `@@unique([${u.fields.join(\", \")}]${u.name ? `, map: \"${u.name}\"` : \"\"})`,\n );\n }\n for (const i of model.indexes) {\n out.push(\n `@@index([${i.fields.join(\", \")}]${i.name ? `, map: \"${i.name}\"` : \"\"})`,\n );\n }\n if (model.dbName) out.push(`@@map(\"${model.dbName}\")`);\n return out;\n}\n\nfunction docLines(documentation: string): string[] {\n return documentation.split(\"\\n\").map((l) => `/// ${l}`);\n}\n","/** Small, dependency-free helpers shared across layers. */\n\nexport function isPlainObject(v: unknown): v is Record<string, unknown> {\n return (\n typeof v === \"object\" &&\n v !== null &&\n !Array.isArray(v) &&\n !(v instanceof Date) &&\n !Buffer.isBuffer(v)\n );\n}\n\nexport function isEmptyObject(v: unknown): boolean {\n return isPlainObject(v) && Object.keys(v).length === 0;\n}\n\nexport function uniq<T>(items: T[]): T[] {\n return [...new Set(items)];\n}\n\nexport function pascalCase(input: string): string {\n return input\n .toLowerCase()\n .replace(/[^a-zA-Z0-9]+(.)?/g, (_, c: string | undefined) =>\n c ? c.toUpperCase() : \"\",\n )\n .replace(/^(.)/, (_, c: string) => c.toUpperCase());\n}\n\nexport function camelCase(input: string): string {\n const pascal = pascalCase(input);\n return pascal.charAt(0).toLowerCase() + pascal.slice(1);\n}\n\nexport function pluralize(word: string): string {\n if (/[^aeiou]y$/i.test(word)) return word.replace(/y$/i, \"ies\");\n if (/(s|x|z|ch|sh)$/i.test(word)) return `${word}es`;\n return `${word}s`;\n}\n\n/** First char lowercased — used to derive delegate names from model names. */\nexport function lowerFirst(input: string): string {\n return input.charAt(0).toLowerCase() + input.slice(1);\n}\n\nexport function indent(text: string, level = 1, unit = \" \"): string {\n const pad = unit.repeat(level);\n return text\n .split(\"\\n\")\n .map((l) => (l.length > 0 ? pad + l : l))\n .join(\"\\n\");\n}\n\nexport function assertNever(value: never, message = \"Unexpected value\"): never {\n throw new Error(`${message}: ${JSON.stringify(value)}`);\n}\n","import {\n type FieldNode,\n type ModelNode,\n type SchemaDocument,\n findModel,\n idFields,\n} from \"@ember/ast\";\nimport { camelCase, pascalCase, pluralize } from \"@ember/utils\";\n\n/**\n * Auto-complete missing relation sides, mirroring Prisma's formatter:\n *\n * - If a model declares the **owning** side (`field Type @relation(fields,\n * references)`), the referenced model gets the opposite **back-relation**\n * (a list, or a to-one for 1:1) if it is missing.\n * - If a model declares a **list** (`items Type[]`), the element model gets the\n * owning to-one field plus its scalar foreign key, if missing.\n * - A bare to-one (`field Type` with no `@relation` and no partner) is upgraded\n * to the owning side (scalar FK + `@relation`) and the other model gets the\n * back-relation list.\n *\n * Mutates and returns `doc`. Safe to run repeatedly (idempotent): a relation\n * whose partner already exists is left untouched.\n */\nexport function completeRelations(doc: SchemaDocument): SchemaDocument {\n // Snapshot the original relation fields so newly-added fields aren't\n // re-processed within the same pass.\n const original: { model: ModelNode; field: FieldNode }[] = [];\n for (const model of doc.models) {\n for (const field of model.fields) {\n if (field.kind === \"object\") original.push({ model, field });\n }\n }\n\n for (const { model, field } of original) {\n const related = findModel(doc, field.type);\n if (!related) continue;\n if (hasPartner(related, model, field)) continue;\n\n if (field.isList) {\n addOwningSide(related, model, field);\n } else if (field.relation?.fields?.length) {\n addBackRelation(related, model, field);\n } else {\n upgradeBareToOne(doc, model, field);\n }\n }\n\n return doc;\n}\n\nfunction hasPartner(\n related: ModelNode,\n model: ModelNode,\n field: FieldNode,\n): boolean {\n return related.fields.some(\n (f) =>\n f !== field &&\n f.kind === \"object\" &&\n f.type === model.name &&\n relationNamesMatch(f, field),\n );\n}\n\nfunction relationNamesMatch(a: FieldNode, b: FieldNode): boolean {\n const an = a.relation?.name;\n const bn = b.relation?.name;\n if (an && bn) return an === bn; // both named: must match\n if (!an && !bn) return true; // both unnamed: the single relation between them\n return false; // one named, one not: different relations\n}\n\n/** Add the opposite back-relation (list, or to-one for 1:1) on `related`. */\nfunction addBackRelation(\n related: ModelNode,\n owner: ModelNode,\n owning: FieldNode,\n): void {\n // A unique foreign key (the scalar field(s) the relation maps to) implies a\n // 1:1, so the back side is a to-one rather than a list.\n const fkFields = (owning.relation?.fields ?? [])\n .map((n) => owner.fields.find((f) => f.name === n))\n .filter((f): f is FieldNode => !!f);\n const isOneToOne = fkFields.length > 0 && fkFields.every((f) => f.isUnique);\n const baseName = isOneToOne\n ? camelCase(owner.name)\n : camelCase(pluralize(owner.name));\n const name = uniqueFieldName(related, baseName);\n\n related.fields.push({\n name,\n type: owner.name,\n kind: \"object\",\n isList: !isOneToOne,\n isRequired: false,\n isId: false,\n isUnique: false,\n isUpdatedAt: false,\n // Only emit @relation when the relation is named; an unnamed back-relation\n // carries no attribute (matches Prisma's formatter output).\n ...(owning.relation?.name ? { relation: { name: owning.relation.name } } : {}),\n });\n}\n\n/** Add the owning to-one field + scalar FK on `related` (which holds the FK). */\nfunction addOwningSide(\n related: ModelNode,\n parent: ModelNode,\n listField: FieldNode,\n): void {\n const ref = idFields(parent)[0];\n if (!ref) return;\n\n const relationField = uniqueFieldName(related, camelCase(parent.name));\n const fkName = uniqueFieldName(\n related,\n `${camelCase(parent.name)}${pascalCase(ref.name)}`,\n );\n\n related.fields.push({\n name: fkName,\n type: ref.type,\n kind: \"scalar\",\n isList: false,\n isRequired: true,\n isId: false,\n isUnique: false,\n isUpdatedAt: false,\n ...(ref.nativeType ? { nativeType: ref.nativeType } : {}),\n });\n\n related.fields.push({\n name: relationField,\n type: parent.name,\n kind: \"object\",\n isList: false,\n isRequired: true,\n isId: false,\n isUnique: false,\n isUpdatedAt: false,\n relation: {\n ...(listField.relation?.name ? { name: listField.relation.name } : {}),\n fields: [fkName],\n references: [ref.name],\n },\n });\n}\n\n/** Upgrade `field Type` (bare to-one) to the owning side and add the back list. */\nfunction upgradeBareToOne(\n doc: SchemaDocument,\n model: ModelNode,\n field: FieldNode,\n): void {\n const related = findModel(doc, field.type);\n if (!related) return;\n const ref = idFields(related)[0];\n if (!ref) return;\n\n const fkName = uniqueFieldName(model, `${field.name}${pascalCase(ref.name)}`);\n // Insert the scalar FK just before the relation field for readability.\n const idx = model.fields.indexOf(field);\n model.fields.splice(idx, 0, {\n name: fkName,\n type: ref.type,\n kind: \"scalar\",\n isList: false,\n isRequired: field.isRequired,\n isId: false,\n isUnique: false,\n isUpdatedAt: false,\n ...(ref.nativeType ? { nativeType: ref.nativeType } : {}),\n });\n field.relation = {\n ...(field.relation ?? {}),\n fields: [fkName],\n references: [ref.name],\n };\n\n addBackRelation(related, model, field);\n}\n\nfunction uniqueFieldName(model: ModelNode, base: string): string {\n let name = base || \"relation\";\n let i = 1;\n while (model.fields.some((f) => f.name === name)) name = `${base}_${++i}`;\n return name;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,72 @@
1
+ import { S as SchemaDocument } from './index-D0xIdtCl.js';
2
+
3
+ /**
4
+ * Structural validation of a parsed schema. Throws SchemaValidationError with
5
+ * all detected problems at once so the user can fix them in a single pass.
6
+ */
7
+ declare function validateSchema(doc: SchemaDocument): void;
8
+
9
+ /**
10
+ * Serializes a SchemaDocument back into `.ember` source text.
11
+ * Used by `ember db pull` (introspection output) and `ember format`.
12
+ * Field columns are aligned for readability, mirroring Prisma's formatter.
13
+ */
14
+ declare function printSchema(doc: SchemaDocument): string;
15
+
16
+ /**
17
+ * Canonical formatter: parse, auto-complete missing relation sides (like
18
+ * Prisma's formatter), validate, and re-print with aligned formatting.
19
+ */
20
+ declare function formatSchema(source: string, file?: string): string;
21
+ /** Parse schema source text into an AST (no validation). */
22
+ declare function parseSchema(source: string, file?: string): SchemaDocument;
23
+ /** Parse and validate schema source text. */
24
+ declare function parseAndValidate(source: string, file?: string): SchemaDocument;
25
+ interface LoadedSchema {
26
+ document: SchemaDocument;
27
+ path: string;
28
+ /** Resolved connection URL (env() expanded). */
29
+ databaseUrl?: string;
30
+ }
31
+ /** Locate the schema file relative to a base directory. */
32
+ declare function findSchemaPath(base?: string, explicit?: string): string | undefined;
33
+ /** Load, parse, validate a schema file and resolve its datasource URL. */
34
+ declare function loadSchema(path: string): LoadedSchema;
35
+ declare function resolveDatasourceUrl(doc: SchemaDocument, _base: string): string | undefined;
36
+
37
+ /** Base class for every error thrown by EmberORM. */
38
+ declare class EmberError extends Error {
39
+ constructor(message: string);
40
+ }
41
+ /** Raised while lexing/parsing a `.ember` schema file. */
42
+ declare class SchemaParseError extends EmberError {
43
+ readonly line: number;
44
+ readonly column: number;
45
+ readonly file?: string | undefined;
46
+ constructor(message: string, line: number, column: number, file?: string | undefined);
47
+ }
48
+ /** Raised when a parsed schema is structurally invalid. */
49
+ declare class SchemaValidationError extends EmberError {
50
+ readonly details: string[];
51
+ constructor(message: string, details?: string[]);
52
+ }
53
+ /** Raised when a query is malformed before it reaches the database. */
54
+ declare class QueryValidationError extends EmberError {
55
+ }
56
+ /** Wraps a low-level driver/database failure with EmberORM context. */
57
+ declare class DatabaseError extends EmberError {
58
+ readonly cause?: unknown | undefined;
59
+ readonly sql?: string | undefined;
60
+ constructor(message: string, cause?: unknown | undefined, sql?: string | undefined);
61
+ }
62
+ /** Thrown by `*OrThrow` operations when no record matches. */
63
+ declare class RecordNotFoundError extends EmberError {
64
+ constructor(model: string);
65
+ }
66
+ /** Thrown on unique constraint violations (mapped from Firebird errors). */
67
+ declare class UniqueConstraintError extends EmberError {
68
+ readonly target: string;
69
+ constructor(target: string, cause?: unknown);
70
+ }
71
+
72
+ export { DatabaseError as D, EmberError as E, type LoadedSchema as L, QueryValidationError as Q, RecordNotFoundError as R, SchemaParseError as S, UniqueConstraintError as U, SchemaValidationError as a, parseSchema as b, printSchema as c, findSchemaPath as d, formatSchema as f, loadSchema as l, parseAndValidate as p, resolveDatasourceUrl as r, validateSchema as v };