upd: routing dev
This commit is contained in:
104
src/lib/schema-parser.ts
Normal file
104
src/lib/schema-parser.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
export interface SchemaField {
|
||||
name: string
|
||||
type: string
|
||||
isId: boolean
|
||||
isUnique: boolean
|
||||
isOptional: boolean
|
||||
isList: boolean
|
||||
isRelation: boolean
|
||||
default?: string
|
||||
}
|
||||
|
||||
export interface SchemaRelation {
|
||||
from: string
|
||||
fromField: string
|
||||
to: string
|
||||
toField: string
|
||||
onDelete?: string
|
||||
}
|
||||
|
||||
export interface SchemaModel {
|
||||
name: string
|
||||
tableName: string
|
||||
fields: SchemaField[]
|
||||
}
|
||||
|
||||
export interface SchemaEnum {
|
||||
name: string
|
||||
values: string[]
|
||||
}
|
||||
|
||||
export interface ParsedSchema {
|
||||
models: SchemaModel[]
|
||||
enums: SchemaEnum[]
|
||||
relations: SchemaRelation[]
|
||||
}
|
||||
|
||||
export function parseSchema(raw: string): ParsedSchema {
|
||||
const models: SchemaModel[] = []
|
||||
const enums: SchemaEnum[] = []
|
||||
const relations: SchemaRelation[] = []
|
||||
|
||||
const blocks = raw.match(/(model|enum)\s+(\w+)\s*\{([^}]*)}/gs) ?? []
|
||||
|
||||
for (const block of blocks) {
|
||||
const match = block.match(/(model|enum)\s+(\w+)\s*\{([^}]*)}/s)
|
||||
if (!match) continue
|
||||
const [, type, name, body] = match
|
||||
const lines = body
|
||||
.split('\n')
|
||||
.map((l) => l.trim())
|
||||
.filter((l) => l && !l.startsWith('//'))
|
||||
|
||||
if (type === 'enum') {
|
||||
enums.push({ name, values: lines })
|
||||
continue
|
||||
}
|
||||
|
||||
let tableName = name
|
||||
const fields: SchemaField[] = []
|
||||
|
||||
for (const line of lines) {
|
||||
const mapMatch = line.match(/@@map\("(\w+)"\)/)
|
||||
if (mapMatch) { tableName = mapMatch[1]; continue }
|
||||
if (line.startsWith('@@')) continue
|
||||
|
||||
const fieldMatch = line.match(/^(\w+)\s+(\w+)(\?)?(\[\])?\s*(.*)$/)
|
||||
if (!fieldMatch) continue
|
||||
const [, fName, fType, optional, list, attrs] = fieldMatch
|
||||
|
||||
const isId = attrs.includes('@id')
|
||||
const isUnique = attrs.includes('@unique')
|
||||
const isRelation = attrs.includes('@relation')
|
||||
const defaultMatch = attrs.match(/@default\(([^)]+)\)/)
|
||||
|
||||
const isModelRef =
|
||||
/^[A-Z]/.test(fType) &&
|
||||
!enums.some((e) => e.name === fType) &&
|
||||
!['String', 'Int', 'Float', 'Boolean', 'DateTime', 'BigInt', 'Decimal', 'Bytes', 'Json'].includes(fType)
|
||||
|
||||
if (isRelation) {
|
||||
const relMatch = attrs.match(
|
||||
/@relation\(fields:\s*\[(\w+)],\s*references:\s*\[(\w+)](?:,\s*onDelete:\s*(\w+))?\)/,
|
||||
)
|
||||
if (relMatch) {
|
||||
relations.push({ from: name, fromField: relMatch[1], to: fType, toField: relMatch[2], onDelete: relMatch[3] })
|
||||
}
|
||||
}
|
||||
|
||||
fields.push({
|
||||
name: fName,
|
||||
type: fType + (list ? '[]' : ''),
|
||||
isId, isUnique,
|
||||
isOptional: !!optional,
|
||||
isList: !!list,
|
||||
isRelation: isModelRef,
|
||||
default: defaultMatch?.[1],
|
||||
})
|
||||
}
|
||||
|
||||
models.push({ name, tableName, fields })
|
||||
}
|
||||
|
||||
return { models, enums, relations }
|
||||
}
|
||||
Reference in New Issue
Block a user