import "reflect-metadata"; import { CollectionCreateOptions } from "mongodb"; import { MongoCollection } from "./MongoCollection"; import { MongoSchema, MongoSchemaField, IDocumentOptions, ERelationType, IFieldOptions, IFieldIndex } from "./MongoSchema"; import { MongoSchemaRegistry } from "./MongoSchemaRegistry"; import { ObjectType } from "./Types"; function resolveParentInheritors(target: any): any[] { let parent = Object.getPrototypeOf(target); if(!parent || !parent.name) { return []; } let inheritors = resolveParentInheritors(parent); inheritors.unshift(parent); return inheritors; } export function Model(name: string, options?: IDocumentOptions, createOptions?: CollectionCreateOptions) { return function(target: any) { if(!target.SchemaDefinition) { target.SchemaDefinition = new MongoSchema(target); } let parents = resolveParentInheritors(target); let schema:MongoSchema = MongoSchemaRegistry.getSchema(target.name); if(!schema) { schema = new MongoSchema(target); MongoSchemaRegistry.register(target.name, schema); } schema.name = name; schema.createOptions = createOptions; schema.inherits = parents; if(!options) return; if(options.indexes) { for(let index of options.indexes) { schema.addIndex(index); } } if(options.inherits) { schema.inherits.push.prototype.apply(options.inherits); //schema.inherits = options.inherits.concat(parents); } } }; export function Schema(inherits?:any[]) { return function(target: any) { if(!target.SchemaDefinition) { target.SchemaDefinition = new MongoSchema(target); } let parents = resolveParentInheritors(target); let schema:MongoSchema = MongoSchemaRegistry.getSchema(target.name); if(!schema) { schema = new MongoSchema(target); MongoSchemaRegistry.register(target.name, schema); } if(inherits) { schema.inherits.push.prototype.apply(inherits); //schema.inherits = options.inherits.concat(parents); } } }; // field tells export function Field(fieldOptions: IFieldOptions={}) { return function(target: any, key: string) { let schema:MongoSchema = MongoSchemaRegistry.getSchema(target.constructor.name); if(!schema) { schema = new MongoSchema(target.constructor); MongoSchemaRegistry.register(target.constructor.name, schema); } fieldOptions.relationType = ERelationType.None; schema.addField(key, (type) => { return fieldOptions.type || Reflect.getMetadata("design:type", target, key).name; }, fieldOptions); } }; // Single field representing a singl object export function FieldReference(typeFunction: (type?: any) => ObjectType, fieldOptions: IFieldOptions={}): Function { return function(target: any, key: string) { let fieldType = Reflect.getMetadata("design:type", target, key); let schema:MongoSchema = MongoSchemaRegistry.getSchema(target.constructor.name); if(!schema) { schema = new MongoSchema(target.constructor); MongoSchemaRegistry.register(target.constructor.name, schema); } if(!typeFunction) { typeFunction = type => { return fieldOptions.type || Reflect.getMetadata("design:type", target, key).name; }; } fieldOptions.foreignField = fieldOptions.foreignField || "_id"; if(!fieldType || fieldType.name != "Array") { fieldOptions.relationType = ERelationType.SingleObjectId; } if(fieldType && fieldType.name == "Array") { fieldOptions.relationType = ERelationType.ArrayObjectId; } schema.addField(key, typeFunction, fieldOptions); } } export function Hook(hookName: string) { return function(target: any, key: string) { if(!target.SchemaDefinition) { target.SchemaDefinition = new MongoSchema(target); } let schema:MongoSchema = target.SchemaDefinition; schema.registerHook(hookName, target[key]); } };