import { Reflect } from "./utils/reflect.ts" ; import { metadata } from "./constants.ts" ; import { getDataType } from "./utils/models.ts" ; param tableName export function Model ( tableName ? ) { return ( target ) => { Reflect . defineMetadata ( metadata . tableName , tableName || target . name . toLowerCase ( ) , target ) ; } ; } /**
 * Transform database value to JavaScript types
 */ export enum DataType { String = "string" , Date = "date" , Number = "number" , Boolean = "boolean" } /**
 * Information about table the table column
 */ export interface ColumnOptions { /** JavaScript type which will be converted from the database */ type : DataType ; /** The column name on the database */ name : string ; /** The default value */ default ? : any ; } export type ColumnDescription = ColumnOptions & { propertyKey : string ; isPrimaryKey : boolean ; } ; param options export function Column ( options ? ) { return ( target , propertyKey ) => { let columns = [ ] ; 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 = Object . assign ( { } , { propertyKey : propertyKey , name : propertyKey , type : type , isPrimaryKey : false } , options ) ; columns . push ( description ) ; Reflect . defineMetadata ( metadata . columns , columns , target ) ; } ; } /** Options for model's primary field */ export interface PrimaryFieldOptions { name : string ; } param options export function Primary ( options ? ) { return ( target , propertyKey ) => { let columns = [ ] ; 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 ; } param getModel param column export function BelongsTo ( getModel , column ) { return ( target , propertyKey ) => { addRelation ( target , RelationType . BelongsTo , propertyKey , getModel , column ) ; } ; } param getModel param column export function HasMany ( getModel , column ) { return ( target , propertyKey ) => { addRelation ( target , RelationType . HasMany , propertyKey , getModel , column ) ; } ; } /**
 * Add relation metadata to a targetted model.
 */ function addRelation ( target , type , propertyKey , getModel , targetColumn ) { let relations = [ ] ; if ( Reflect . hasMetadata ( metadata . relations , target ) ) { relations = Reflect . getMetadata ( metadata . relations , target ) ; } relations . push ( { propertyKey , type , getModel , targetColumn } ) ; Reflect . defineMetadata ( metadata . relations , relations , target ) ; }