You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lib/src/orm/model/Field.ts

81 lines
2.3 KiB

import {Collection} from '../../util'
import {FieldType} from '../types'
/** The reflection metadata key containing information about the model's fields. */
export const EXTOLLO_ORM_MODEL_FIELDS_METADATA_KEY = 'extollo:orm:Field.ts'
/**
* Abstract representation of a field on a model.
*/
export interface ModelField {
databaseKey: string,
modelKey: string | symbol,
type: any,
}
/**
* Retrieve a collection of ModelField metadata from the given model.
* @param model
*/
export function getFieldsMeta(model: unknown): Collection<ModelField> {
const fields = Reflect.getMetadata(EXTOLLO_ORM_MODEL_FIELDS_METADATA_KEY, (model as any).constructor)
if ( !(fields instanceof Collection) ) {
return new Collection<ModelField>()
}
return fields as Collection<ModelField>
}
/**
* Set the collection of ModelField metadata as the field data for the given model.
* @param model
* @param fields
*/
export function setFieldsMeta(model: unknown, fields: Collection<ModelField>): void {
Reflect.defineMetadata(EXTOLLO_ORM_MODEL_FIELDS_METADATA_KEY, fields, (model as any).constructor)
}
/**
* Decorator that maps the given property to a database column of the specified FieldType.
*
* @example
* ```typescript
* class MyModel extends Model<MyModel> {
* // Maps the 'name' VARCHAR column in the database to this property
* @Field(FieldType.Varchar)
* public name!: string
*
* // Maps the 'first_name' VARCHAR column in the database to this property
* @Field(FieldType.Varchar, 'first_name')
* public firstName!: string
* }
* ```
*
* @param type
* @param databaseKey
* @constructor
*/
export function Field(type: FieldType, databaseKey?: string): PropertyDecorator {
return (target, modelKey) => {
if ( !databaseKey ) {
databaseKey = String(modelKey)
}
const fields = getFieldsMeta(target)
const existingField = fields.firstWhere('modelKey', '=', modelKey)
if ( existingField ) {
existingField.databaseKey = databaseKey
existingField.type = type
return setFieldsMeta(target, fields)
}
fields.push({
databaseKey,
modelKey,
type,
})
setFieldsMeta(target, fields)
}
}