import { Model, SchemaDefinition, } from 'mongoose'; import { BaseDocument, TypedDocument } from './base.type'; import { STATUS_CODE_BASE } from '@gongt/ts-stl-library/request/protocol'; import { debugPromise, debugStart } from './debug'; import { RequestError } from '@gongt/ts-stl-library/request/request-error'; import { createLoggerBundle, IDebuggerBundle } from '@gongt/ts-stl-library/debug/create-logger'; import { databaseInitComplete, registerModel, testDatabaseMuted } from './connect'; export type DataDocument = DocType&TypedDocument; export abstract class DataModelAbstractMethods { protected abstract readonly collectionName: string; protected abstract readonly connectionName: string; public readonly log: Readonly = createLoggerBundle('db:' + this.modelName.replace(/Model$/, '')); protected model: Model>; protected abstract readonly schema: SchemaDefinition; // singleton constructor() { } /** @deprecated */ private wrapDbMethodWithExec(method: string, methodDisplayName: string = method): any { let original: Function; if (!testDatabaseMuted) { if (databaseInitComplete) { if (!testDatabaseMuted) { original = this.model[method]; } } else { registerModel(this.modelName + '::' + method, () => { if (!testDatabaseMuted) { original = this.model[method]; } return false; }); } } if (this.log.data.enabled) { let wrappedDatabaseMethod = (...args) => { debugStart(methodDisplayName, this.log.silly, args); const p = original.call(this.model, ...args).exec(); debugPromise(methodDisplayName, this.log.data, this.log.error, p); return p; }; wrappedDatabaseMethod['displayName'] = `${this.modelName}::${methodDisplayName}`; if (methodDisplayName !== method) { wrappedDatabaseMethod['displayName'] += `(model::${method})`; } return wrappedDatabaseMethod; } else { return (...args) => { return original.call(this.model, ...args).exec(); }; } } protected wrapDebug(method: string) { const original = this[method]; this[method] = (...args) => { debugStart(method, this.log.silly, args); const p = original.apply(this, args); debugPromise(method, this.log.data, this.log.error, p); return p; }; } /** @deprecated */ protected wrapMethodAsFind(methodName: string) { this[methodName] = this.wrapDbMethodWithExec(methodName); } /** @deprecated */ protected wrapMethodAsGet(methodName: string, findMethodName: string) { const find = this.wrapDbMethodWithExec(findMethodName, methodName); this[methodName] = (...args: any[]) => { return find(...args).then((object) => { if (!object) { this.log.debug('data not found: ' + JSON.stringify(args[0])); throw new RequestError(STATUS_CODE_BASE.DATA_NOT_EXISTS, `在数据库 "${this.name}" 中进行查询 ${JSON.stringify(args[0])},没有找到数据`); } return object; }); }; } get modelName() { return this.constructor['name']; } get name() { return this.collectionName; } }