|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|