import { Reflect } from "./utils/reflect.ts";import { metadata } from "./constants.ts";import { getDataType } from "./utils/models.ts";
export function Model(tableName?: string) { return (target: Function) => { Reflect.defineMetadata( metadata.tableName, tableName || target.name.toLowerCase(), target, ); };}
export enum DataType { String = "string", Date = "date", Number = "number", Boolean = "boolean",}
export interface ColumnOptions { type: DataType;
name: string;
default?: any;}
export type ColumnDescription = ColumnOptions & { propertyKey: string; isPrimaryKey: boolean;};
export function Column(options?: Partial<ColumnOptions>) { return (target: Object, propertyKey: string) => { let columns: ColumnDescription[] = []; if (Reflect.hasMetadata(metadata.columns, target)) { columns = Reflect.getMetadata(metadata.columns, target); }
const typeMetadata = Reflect.getMetadata( "design:type", target, propertyKey, ); const type = getDataType(typeMetadata); if (!type && !options?.type) { throw new Error(`Column '${propertyKey}' must have a type!`); }
const description: ColumnDescription = Object.assign({}, { propertyKey: propertyKey, name: propertyKey, type: type, isPrimaryKey: false, }, options);
columns.push(description);
Reflect.defineMetadata(metadata.columns, columns, target); };}
export interface PrimaryFieldOptions { name: string;}
export function Primary(options?: PrimaryFieldOptions) { return (target: Object, propertyKey: string) => { let columns: ColumnDescription[] = []; if (Reflect.hasMetadata(metadata.columns, target)) { columns = Reflect.getMetadata(metadata.columns, target); }
columns.push({ propertyKey, name: options?.name || "id", type: DataType.Number, isPrimaryKey: true, });
Reflect.defineMetadata(metadata.columns, columns, target); };}
export enum RelationType { HasMany = 1, BelongsTo = 2,}
export interface RelationDescription { propertyKey: string; type: RelationType; getModel: () => { new (): any }; targetColumn: string;}
export function BelongsTo( getModel: () => { new (): any }, column: string,) { return (target: Object, propertyKey: string) => { addRelation(target, RelationType.BelongsTo, propertyKey, getModel, column); };}
export function HasMany( getModel: () => { new (): any }, column: string,) { return (target: Object, propertyKey: string) => { addRelation(target, RelationType.HasMany, propertyKey, getModel, column); };}
function addRelation( target: Object, type: RelationType, propertyKey: string, getModel: () => any, targetColumn: string,) { let relations: RelationDescription[] = []; if (Reflect.hasMetadata(metadata.relations, target)) { relations = Reflect.getMetadata(metadata.relations, target); }
relations.push({ propertyKey, type, getModel, targetColumn });
Reflect.defineMetadata(metadata.relations, relations, target);}