From 2762d055c21213bcf7dd15c9262662c64a0c9b91 Mon Sep 17 00:00:00 2001 From: D-Sketon <2055272094@qq.com> Date: Sat, 23 Dec 2023 17:33:18 +0800 Subject: [PATCH] refactor: generic --- .gitignore | 5 +- src/database.ts | 10 ++-- src/document.ts | 20 +++---- src/model.ts | 118 ++++++++++++++++++++------------------- src/query.ts | 52 +++++++++-------- src/schema.ts | 67 ++++++++++++---------- src/types.ts | 24 ++++++++ test/scripts/document.ts | 16 +++++- test/scripts/model.ts | 87 ++++++++++++++++++----------- test/scripts/query.ts | 111 ++++++++++++++++++++---------------- test/scripts/schema.ts | 2 + 11 files changed, 299 insertions(+), 213 deletions(-) diff --git a/.gitignore b/.gitignore index 4efa43ee..1740ad6d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,7 @@ node_modules/ *.log docs/ coverage/ -dist \ No newline at end of file +dist +yarn.lock +package-lock.json +pnpm-lock.yaml \ No newline at end of file diff --git a/src/database.ts b/src/database.ts index 48aec4c0..2a301479 100644 --- a/src/database.ts +++ b/src/database.ts @@ -7,7 +7,7 @@ import Schema from './schema'; import SchemaType from './schematype'; import WarehouseError from './error'; import { logger } from 'hexo-log'; -import type { NodeJSLikeCallback } from './types'; +import type { AddSchemaTypeOptions, NodeJSLikeCallback } from './types'; const log = logger(); const pkg = require('../package.json'); @@ -80,7 +80,7 @@ interface DatabaseOptions { class Database { options: DatabaseOptions; - _models: Record; + _models: Record>; Model: typeof Model; /** @@ -104,7 +104,7 @@ class Database { this._models = {}; - class _Model extends Model {} + class _Model extends Model {} this.Model = _Model; @@ -118,7 +118,7 @@ class Database { * @param {Schema|object} [schema] * @return {Model} */ - model(name: string, schema?: Schema | object): Model { + model(name: string, schema?: Schema | Record): Model { if (this._models[name]) { return this._models[name]; } @@ -181,7 +181,7 @@ class Database { return Bluebird.resolve(exportAsync(this, path)).asCallback(callback); } - toJSON(): { meta: { version: number, warehouse: string }, models: Record } { + toJSON(): { meta: { version: number, warehouse: string }, models: Record> } { const models = Object.keys(this._models) .reduce((obj, key) => { const value = this._models[key]; diff --git a/src/document.ts b/src/document.ts index 29e800bf..fcb5bbb3 100644 --- a/src/document.ts +++ b/src/document.ts @@ -4,18 +4,18 @@ import type Schema from './schema'; import type { NodeJSLikeCallback } from './types'; const cloneDeep = rfdc(); -abstract class Document { - abstract _model: Model; +abstract class Document { + abstract _model: Model; _id!: string | number | undefined; abstract _schema: Schema; - [key: PropertyKey]: any; + [key : string]: any; /** * Document constructor. * * @param {object} data */ - constructor(data?: object) { + constructor(data?: T) { if (data) { Object.assign(this, data); } @@ -38,7 +38,7 @@ abstract class Document { * @param {function} [callback] * @return {Promise} */ - update(data: Record, callback?: NodeJSLikeCallback): Promise { + update(data: object, callback?: NodeJSLikeCallback): Promise { return this._model.updateById(this._id, data, callback); } @@ -49,7 +49,7 @@ abstract class Document { * @param {function} [callback] * @return {Promise} */ - replace(data: object | Document, callback?: NodeJSLikeCallback): Promise { + replace(data: T | Document, callback?: NodeJSLikeCallback): Promise { return this._model.replaceById(this._id, data, callback); } @@ -68,9 +68,9 @@ abstract class Document { * * @return {object} */ - toObject(): object { + toObject(): T { const keys = Object.keys(this); - const obj = {}; + const obj: Partial = {}; for (let i = 0, len = keys.length; i < len; i++) { const key = keys[i]; @@ -79,7 +79,7 @@ abstract class Document { obj[key] = isGetter(this, key) ? this[key] : cloneDeep(this[key]); } - return obj; + return obj as T; } /** @@ -97,7 +97,7 @@ abstract class Document { * @param {String|Object} expr * @return {Document} */ - populate(expr: string | any[] | { path?: string; model?: any; [key: PropertyKey]: any }): Document { + populate(expr: string | any[] | { path?: string; model?: any; [key: PropertyKey]: any }): Document { const stack = this._schema._parsePopulate(expr); return this._model._populate(this, stack); } diff --git a/src/model.ts b/src/model.ts index 034a3e60..32a6429d 100644 --- a/src/model.ts +++ b/src/model.ts @@ -11,11 +11,11 @@ import WarehouseError from './error'; import PopulationError from './error/population'; import Mutex from './mutex'; import type Database from './database'; -import type { NodeJSLikeCallback, Options } from './types'; +import type { AddSchemaTypeOptions, NodeJSLikeCallback, Options, PopulateResult } from './types'; -class Model extends EventEmitter { +class Model extends EventEmitter { _mutex = new Mutex(); - data: Record = {}; + data: Record = {}; schema: Schema; length = 0; Document; @@ -28,7 +28,7 @@ class Model extends EventEmitter { * @param {string} name Model name * @param {Schema|object} [schema_] Schema */ - constructor(public name: string, schema_: Schema | object) { + constructor(public name: string, schema_: Schema | Record) { super(); let schema: Schema; @@ -49,10 +49,10 @@ class Model extends EventEmitter { this.schema = schema; - class _Document extends Document { - _model!: Model; + class _Document extends Document { + _model!: Model; _schema!: Schema; - constructor(data: object) { + constructor(data: T) { super(data); // Apply getters @@ -65,8 +65,8 @@ class Model extends EventEmitter { _Document.prototype._model = this; _Document.prototype._schema = schema; - class _Query extends Query { - _model!: Model; + class _Query extends Query { + _model!: Model; _schema!: Schema; } @@ -88,7 +88,7 @@ class Model extends EventEmitter { * @param {object} data * @return {Document} */ - new(data?: object): Document { + new(data?: T): Document { return new this.Document(data); } @@ -100,7 +100,7 @@ class Model extends EventEmitter { * @param {boolean} [options.lean=false] Returns a plain JavaScript object * @return {Document|object} */ - findById(id: PropertyKey, options_?: Options): Document | Record { + findById(id: PropertyKey, options_?: Options): Document | T { const raw = this.data[id]; if (!raw) return; @@ -145,11 +145,11 @@ class Model extends EventEmitter { * @return {Promise} * @private */ - _insertOne(data_: Document | object): Promise { + _insertOne(data_: Document | T): Promise { const schema = this.schema; // Apply getters - const data = (data_ instanceof this.Document ? data_ : this.new(data_)) as Document; + const data = (data_ instanceof this.Document ? data_ : this.new(data_ as T)) as Document; const id = data._id; // Check ID @@ -163,7 +163,7 @@ class Model extends EventEmitter { // Apply setters const result = data.toObject(); - schema._applySetters(result); + schema._applySetters(result as object); // Pre-hooks return execHooks(schema, 'pre', 'save', data).then(data => { @@ -183,7 +183,7 @@ class Model extends EventEmitter { * @param {function} [callback] * @return {Promise} */ - insertOne(data: Document | object, callback?: NodeJSLikeCallback): Promise { + insertOne(data: Document | T, callback?: NodeJSLikeCallback): Promise { return Promise.using(this._acquireWriteLock(), () => this._insertOne(data)).asCallback(callback); } @@ -194,9 +194,9 @@ class Model extends EventEmitter { * @param {function} [callback] * @return {Promise} */ - insert(data: object | object[], callback?: NodeJSLikeCallback): Promise { + insert(data: Document | T | Document[] | T[], callback?: NodeJSLikeCallback): Promise { if (Array.isArray(data)) { - return Promise.mapSeries(data, item => this.insertOne(item)).asCallback(callback); + return Promise.mapSeries | T, any>(data, item => this.insertOne(item)).asCallback(callback); } return this.insertOne(data, callback); @@ -209,7 +209,7 @@ class Model extends EventEmitter { * @param {function} [callback] * @return {Promise} */ - save(data: Document | object, callback?: NodeJSLikeCallback): Promise { + save(data: Document | T, callback?: NodeJSLikeCallback): Promise { const id = (data as any)._id; if (!id) return this.insertOne(data, callback); @@ -231,7 +231,7 @@ class Model extends EventEmitter { * @return {Promise} * @private */ - _updateWithStack(id: string | number, stack: any[]): Promise { + _updateWithStack(id: string | number, stack: ((data: any) => void)[]): Promise { const schema = this.schema; const data = this.data[id]; @@ -253,7 +253,7 @@ class Model extends EventEmitter { // Apply setters result = doc.toObject(); - schema._applySetters(result); + schema._applySetters(result as object); // Pre-hooks return execHooks(schema, 'pre', 'save', doc).then(data => { @@ -273,9 +273,9 @@ class Model extends EventEmitter { * @param {function} [callback] * @return {Promise} */ - updateById(id: string | number, update: Record, callback?: NodeJSLikeCallback): Promise { + updateById(id: string | number, update: object, callback?: NodeJSLikeCallback): Promise { return Promise.using(this._acquireWriteLock(), () => { - const stack = this.schema._parseUpdate(update); + const stack = this.schema._parseUpdate(update as object); return this._updateWithStack(id, stack); }).asCallback(callback); } @@ -289,7 +289,7 @@ class Model extends EventEmitter { * @return {Promise} */ update(query: object, data: object, callback?: NodeJSLikeCallback): Promise { - return (this.find(query) as Query).update(data, callback); + return (this.find(query) as Query).update(data, callback); } /** @@ -300,7 +300,7 @@ class Model extends EventEmitter { * @return {Promise} * @private */ - _replaceById(id: string | number, data_: Document | object): Promise { + _replaceById(id: string | number, data_: Document | T): Promise { const schema = this.schema; if (!this.has(id)) { @@ -310,11 +310,11 @@ class Model extends EventEmitter { (data_ as any)._id = id; // Apply getters - const data = (data_ instanceof this.Document ? data_ : this.new(data_)) as Document; + const data = (data_ instanceof this.Document ? data_ : this.new(data_ as T)) as Document; // Apply setters const result = data.toObject(); - schema._applySetters(result); + schema._applySetters(result as object); // Pre-hooks return execHooks(schema, 'pre', 'save', data).then(data => { @@ -334,7 +334,7 @@ class Model extends EventEmitter { * @param {function} [callback] * @return {Promise} */ - replaceById(id: string | number, data: Document | object, callback?: NodeJSLikeCallback): Promise { + replaceById(id: string | number, data: Document | T, callback?: NodeJSLikeCallback): Promise { return Promise.using(this._acquireWriteLock(), () => this._replaceById(id, data)).asCallback(callback); } @@ -347,7 +347,7 @@ class Model extends EventEmitter { * @return {Promise} */ replace(query: object, data, callback?: NodeJSLikeCallback): Promise { - return (this.find(query) as Query).replace(data, callback); + return (this.find(query) as Query).replace(data, callback); } /** @@ -396,7 +396,7 @@ class Model extends EventEmitter { * @return {Promise} */ remove(query: object, callback?: NodeJSLikeCallback): Promise { - return (this.find(query) as Query).remove(callback); + return (this.find(query) as Query).remove(callback); } /** @@ -421,7 +421,7 @@ class Model extends EventEmitter { * @param {function} iterator * @param {object} [options] See {@link Model#findById}. */ - forEach(iterator: (value: any, index: number) => any, options?: Options): void { + forEach(iterator: (value: any, index: number) => void, options?: Options): void { const keys = Object.keys(this.data); let num = 0; @@ -457,14 +457,16 @@ class Model extends EventEmitter { * @param {Boolean} [options.lean=false] Returns a plain JavaScript object. * @return {Query|Array} */ - find(query: object, options: Options = {}): Query | any[] { + find(query: object): Query; + find(query: object, options: Options): Query | T[]; + find(query: object, options: Options = {}): Query | T[] { const filter = this.schema._execQuery(query); const keys = Object.keys(this.data); const len = keys.length; let limit = options.limit || this.length; let skip = options.skip; const data = this.data; - const arr = []; + const arr: (T | Document)[] = []; for (let i = 0; limit && i < len; i++) { const key = keys[i]; @@ -492,11 +494,13 @@ class Model extends EventEmitter { * @param {Boolean} [options.lean=false] Returns a plain JavaScript object. * @return {Document|Object} */ - findOne(query: object, options_ : Options = {}): Document | Record { + findOne(query: object): Document; + findOne(query: object, options_ : Options): Document | T; + findOne(query: object, options_ : Options = {}): Document | T { const options = Object.assign(options_, { limit: 1 }); const result = this.find(query, options); - return options.lean ? (result as any[])[0] : (result as Query).toArray()[0]; + return options.lean ? (result as any[])[0] : (result as Query).toArray()[0]; } /** @@ -506,7 +510,7 @@ class Model extends EventEmitter { * @param {String|Number} [order] * @return {Query} */ - sort(orderby: string | object, order?: string | number): Query { + sort(orderby: string | object, order?: string | number): Query { const sort = parseArgs(orderby, order); const fn = this.schema._execSort(sort); @@ -521,7 +525,7 @@ class Model extends EventEmitter { * @param {Object} [options] See {@link Model#findById}. * @return {Document|Object} */ - eq(i_: number, options?: Options): Document | Record { + eq(i_: number, options?: Options): Document | Record { let index = i_ < 0 ? this.length + i_ : i_; const data = this.data; const keys = Object.keys(data); @@ -546,7 +550,7 @@ class Model extends EventEmitter { * @param {Object} [options] See {@link Model#findById}. * @return {Document|Object} */ - first(options?: Options): Document | Record { + first(options?: Options): Document | Record { return this.eq(0, options); } @@ -556,7 +560,7 @@ class Model extends EventEmitter { * @param {Object} [options] See {@link Model#findById}. * @return {Document|Object} */ - last(options?: Options): Document | Record { + last(options?: Options): Document | Record { return this.eq(-1, options); } @@ -567,7 +571,7 @@ class Model extends EventEmitter { * @param {Number} [end] * @return {Query} */ - slice(start_?: number, end_?: number): Query { + slice(start_?: number, end_?: number): Query { const total = this.length; let start = start_ | 0; @@ -606,7 +610,7 @@ class Model extends EventEmitter { * @param {Number} i * @return {Query} */ - limit(i: number): Query { + limit(i: number): Query { return this.slice(0, i); } @@ -616,7 +620,7 @@ class Model extends EventEmitter { * @param {Number} i * @return {Query} */ - skip(i: number): Query { + skip(i: number): Query { return this.slice(i); } @@ -625,7 +629,7 @@ class Model extends EventEmitter { * * @return {Query} */ - reverse(): Query { + reverse(): Query { return new this.Query(this.toArray().reverse()); } @@ -634,7 +638,7 @@ class Model extends EventEmitter { * * @return {Query} */ - shuffle(): Query { + shuffle(): Query { return new this.Query(shuffle(this.toArray())); } @@ -725,7 +729,7 @@ class Model extends EventEmitter { * @param {Object} [options] * @return {Query} */ - filter(iterator: (value: any, index: number) => any, options?: Options): Query { + filter(iterator: (value: any, index: number) => any, options?: Options): Query { const arr = []; this.forEach((item: any, i: number) => { @@ -794,9 +798,9 @@ class Model extends EventEmitter { * @return {Function} * @private */ - _populateGetter(data: string | number, model: Model, options: unknown) { + _populateGetter(data: string | number, model: Model, options: unknown) { let hasCache = false; - let cache: Record | Document; + let cache: Record | Document; return () => { if (!hasCache) { @@ -817,10 +821,10 @@ class Model extends EventEmitter { * @return {Function} * @private */ - _populateGetterArray(data: any[], model: Model, options: Options): () => any[] | Query { + _populateGetterArray(data: any[], model: Model, options: Options): () => any[] | Query { const Query = model.Query; let hasCache = false; - let cache: any[] | Query; + let cache: any[] | Query; return () => { if (!hasCache) { @@ -831,7 +835,7 @@ class Model extends EventEmitter { } if (options.match) { - cache = (new Query(arr) as Query).find(options.match, options); + cache = (new Query(arr) as Query).find(options.match, options); } else if (options.skip) { if (options.limit) { arr = arr.slice(options.skip, options.skip + options.limit); @@ -865,7 +869,7 @@ class Model extends EventEmitter { * @return {Object} * @private */ - _populate(data: Document, stack: any[]): Document { + _populate(data: Document, stack: PopulateResult[]): Document { const models = this._database._models; for (let i = 0, len = stack.length; i < len; i++) { @@ -895,7 +899,7 @@ class Model extends EventEmitter { * @param {String|Object} path * @return {Query} */ - populate(path: string | any[] | { path?: string; model?: any; [key: PropertyKey]: any }): Query { + populate(path: string | any[] | { path?: string; model?: any; [key: PropertyKey]: any }): Query { if (!path) throw new TypeError('path is required'); const stack = this.schema._parsePopulate(path); @@ -921,7 +925,7 @@ class Model extends EventEmitter { for (let i = 0; i < len; i++) { const item = arr[i]; - data[item._id] = schema._parseDatabase(item); + data[item._id] = schema._parseDatabase(item) as T; } this.length = len; @@ -946,15 +950,15 @@ class Model extends EventEmitter { for (let i = 0, num = 0; i < length; i++) { const raw = data[keys[i]]; if (raw) { - result[num++] = schema._exportDatabase(cloneDeep(raw)); + result[num++] = schema._exportDatabase(cloneDeep(raw) as object); } } return result; } - get: Model['findById']; - size: Model['count']; - each: Model['forEach']; - random: Model['shuffle']; + get: Model['findById']; + size: Model['count']; + each: Model['forEach']; + random: Model['shuffle']; } Model.prototype.get = Model.prototype.findById; diff --git a/src/query.ts b/src/query.ts index f2493fe5..d9445909 100644 --- a/src/query.ts +++ b/src/query.ts @@ -5,10 +5,10 @@ import type Schema from './schema'; import type Document from './document'; import type { NodeJSLikeCallback, Options } from './types'; -abstract class Query { - data: any[]; +abstract class Query { + data: Document[]; length: number; - abstract _model: Model; + abstract _model: Model; abstract _schema: Schema; /** @@ -16,7 +16,7 @@ abstract class Query { * * @param {Array} data */ - constructor(data: any[]) { + constructor(data: Document[]) { this.data = data; this.length = data.length; } @@ -48,7 +48,7 @@ abstract class Query { * * @return {Array} */ - toArray(): any[] { + toArray(): Document[] { return this.data; } @@ -59,7 +59,7 @@ abstract class Query { * @param {Number} i * @return {Document|Object} */ - eq(i: number): Document | Record { + eq(i: number): Document { const index = i < 0 ? this.length + i : i; return this.data[index]; } @@ -69,7 +69,7 @@ abstract class Query { * * @return {Document|Object} */ - first(): Document | Record { + first(): Document { return this.eq(0); } @@ -78,7 +78,7 @@ abstract class Query { * * @return {Document|Object} */ - last(): Document | Record { + last(): Document { return this.eq(-1); } @@ -89,7 +89,7 @@ abstract class Query { * @param {Number} [end] * @return {Query} */ - slice(start: number, end?: number): Query { + slice(start: number, end?: number): Query { return Reflect.construct(this.constructor, [this.data.slice(start, end)]); } @@ -99,7 +99,7 @@ abstract class Query { * @param {Number} i * @return {Query} */ - limit(i: number): Query { + limit(i: number): Query { return this.slice(0, i); } @@ -109,7 +109,7 @@ abstract class Query { * @param {Number} i * @return {Query} */ - skip(i: number): Query { + skip(i: number): Query { return this.slice(i); } @@ -118,7 +118,7 @@ abstract class Query { * * @return {Query} */ - reverse(): Query { + reverse(): Query { return Reflect.construct(this.constructor, [this.data.slice().reverse()]); } @@ -127,7 +127,7 @@ abstract class Query { * * @return {Query} */ - shuffle(): Query { + shuffle(): Query { return Reflect.construct(this.constructor, [shuffle(this.data)]); } @@ -141,7 +141,9 @@ abstract class Query { * @param {Boolean} [options.lean=false] Returns a plain JavaScript object. * @return {Query|Array} */ - find(query: object, options: Options = {}): any[] | Query { + find(query: object): Query; + find(query: object, options: Options): T[] | Query; + find(query: object, options: Options = {}): T[] | Query { const filter = this._schema._execQuery(query); const { data, length } = this; const { lean = false } = options; @@ -173,7 +175,9 @@ abstract class Query { * @param {Boolean} [options.lean=false] Returns a plain JavaScript object. * @return {Document|Object} */ - findOne(query: object, options: Options = {}): Document | Record { + findOne(query: object): Document; + findOne(query: object, options): Document | T; + findOne(query: object, options: Options = {}): Document | T { const _options = Object.assign(options, { limit: 1 }); const result = this.find(query, _options); @@ -198,7 +202,7 @@ abstract class Query { * @param {String|Number} [order] * @return {Query} */ - sort(orderby: string | object, order?: string | number | object): Query { + sort(orderby: string | object, order?: string | number | object): Query { const sort = parseArgs(orderby, order); const fn = this._schema._execSort(sort); @@ -230,9 +234,9 @@ abstract class Query { * @param {*} [initial] By default, the initial value is the first document. * @return {*} */ - reduce(iterator: (pre: any, cur: any, index: number) => T, initial?: T): T { + reduce(iterator: (pre: any, cur: any, index: number) => R, initial?: R): R { const { data, length } = this; - let result: T, i: number; + let result, i: number; if (initial === undefined) { i = 1; @@ -257,7 +261,7 @@ abstract class Query { * @param {*} [initial] By default, the initial value is the last document. * @return {*} */ - reduceRight(iterator: (pre: any, cur: any, index: number) => T, initial?: T): T { + reduceRight(iterator: (pre: any, cur: any, index: number) => R, initial?: R): R { const { data, length } = this; let result, i; @@ -283,7 +287,7 @@ abstract class Query { * @param {Function} iterator * @return {Query} */ - filter(iterator: (item: any, index: number) => boolean): Query { + filter(iterator: (item: any, index: number) => boolean): Query { const { data, length } = this; const arr = []; @@ -374,7 +378,7 @@ abstract class Query { * @param {String|Object} expr * @return {Query} */ - populate(expr: string | any[] | { path?: string; model?: any; [key: PropertyKey]: any }): Query { + populate(expr: string | any[] | { path?: string; model?: any; [key: PropertyKey]: any }): Query { const stack = this._schema._parsePopulate(expr); const { data, length } = this; const model = this._model; @@ -386,9 +390,9 @@ abstract class Query { return this; } - size: Query['count']; - each: Query['forEach']; - random: Query['shuffle']; + size: Query['count']; + each: Query['forEach']; + random: Query['shuffle']; } Query.prototype.size = Query.prototype.count; diff --git a/src/schema.ts b/src/schema.ts index 8e783e3a..933a3598 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -5,7 +5,7 @@ import { getProp, setProp, delProp } from './util'; import PopulationError from './error/population'; import SchemaTypeVirtual from './types/virtual'; import { isPlainObject } from 'is-plain-object'; -import type { NodeJSLikeCallback } from './types'; +import type { AddSchemaTypeLoopOptions, AddSchemaTypeOptions, PopulateResult, SchemaTypeOptions } from './types'; /** * @callback queryFilterCallback @@ -29,21 +29,11 @@ type queryCallback = (data: unknown) => void; */ type queryParseCallback = (a: unknown, b: unknown) => number; -/** - * @typedef PopulateResult - * @property {string} path - * @property {*} model - */ -type PopulateResult = { - path: string; - model: any; -}; - const builtinTypes = new Set(['String', 'Number', 'Boolean', 'Array', 'Object', 'Date', 'Buffer']); -const getSchemaType = (name: string, options: Record | { type: any; }) => { - const Type = options.type || options; - const typeName = Type.name; +const getSchemaType = (name: string, options: { type: SchemaTypeOptions; [key: string]: any } | SchemaTypeOptions) => { + const Type = (options as any).type || options; + const typeName: string = Type.name; if (builtinTypes.has(typeName)) { return new Types[typeName](name, options); @@ -388,19 +378,34 @@ class QueryParser { } } + class Schema { paths: Record> = {}; - statics: Record = {}; - methods: Record = {}; - hooks; - stacks; + statics: Record any> = {}; + methods: Record any> = {}; + hooks: { + pre: { + save: ((...args: any[]) => Promise)[] + remove: ((...args: any[]) => Promise)[] + }; + post: { + save: ((...args: any[]) => Promise)[] + remove: ((...args: any[]) => Promise)[] + }; + }; + stacks: { + getter: ((data: object) => void)[]; + setter: ((data: object) => void)[]; + import: ((data: object) => void)[]; + export: ((data: object) => void)[]; + }; /** * Schema constructor. * * @param {Object} [schema] */ - constructor(schema?: object) { + constructor(schema?: Record) { this.hooks = { pre: { save: [], @@ -430,7 +435,7 @@ class Schema { * @param {Object} schema * @param {String} prefix */ - add(schema: Record, prefix = ''): void { + add(schema: Record, prefix = ''): void { const keys = Object.keys(schema); const len = keys.length; @@ -452,8 +457,8 @@ class Schema { * @return {SchemaType | undefined} */ path(name: string): SchemaType; - path(name: string, obj: SchemaType | ((...args: any[]) => any) | { type: any; } | Record | any[]): void; - path(name: string, obj?: SchemaType | ((...args: any[]) => any) | { type: any; } | Record | any[]): SchemaType | void { + path(name: string, obj: AddSchemaTypeOptions): void; + path(name: string, obj?: AddSchemaTypeOptions): SchemaType | void { if (obj == null) { return this.paths[name]; } @@ -475,7 +480,7 @@ class Schema { child: obj.length ? getSchemaType(name, obj[0]) : new SchemaType(name) }); } else if (obj.type) { - type = getSchemaType(name, obj); + type = getSchemaType(name, obj as { type: SchemaTypeOptions; }); } else { type = new Types.Object(); nested = Object.keys(obj).length > 0; @@ -491,7 +496,7 @@ class Schema { this.paths[name] = type; this._updateStack(name, type); - if (nested) this.add(obj, `${name}.`); + if (nested) this.add(obj as AddSchemaTypeLoopOptions, `${name}.`); } /** @@ -567,7 +572,7 @@ class Schema { * @param {String} type Hook type. One of `save` or `remove`. * @param {Function} fn */ - pre(type: string, fn: (...args: any[]) => void): void { + pre(type: 'save' | 'remove', fn: (...args: any[]) => void): void { checkHookType(type); if (typeof fn !== 'function') throw new TypeError('Hook must be a function!'); @@ -580,7 +585,7 @@ class Schema { * @param {String} type Hook type. One of `save` or `remove`. * @param {Function} fn */ - post(type: string, fn: (...args: any[]) => void): void { + post(type: 'save' | 'remove', fn: (...args: any[]) => void): void { checkHookType(type); if (typeof fn !== 'function') throw new TypeError('Hook must be a function!'); @@ -593,7 +598,7 @@ class Schema { * @param {String} name * @param {Function} fn */ - method(name: string | number, fn: (...args: any[]) => any) { + method(name: string, fn: (...args: any[]) => any) { if (!name) throw new TypeError('Method name is required!'); if (typeof fn !== 'function') { @@ -656,7 +661,7 @@ class Schema { * @return {Object} * @private */ - _parseDatabase(data) { + _parseDatabase(data: object): object { const stack = this.stacks.import; for (let i = 0, len = stack.length; i < len; i++) { @@ -673,7 +678,7 @@ class Schema { * @return {Object} * @private */ - _exportDatabase(data) { + _exportDatabase(data: object): object { const stack = this.stacks.export; for (let i = 0, len = stack.length; i < len; i++) { @@ -690,7 +695,7 @@ class Schema { * @return {queryCallback[]} * @private */ - _parseUpdate(updates): queryCallback[] { + _parseUpdate(updates: object): queryCallback[] { return new UpdateParser(this.paths).parseUpdate(updates); } @@ -701,7 +706,7 @@ class Schema { * @return {queryFilterCallback} * @private */ - _execQuery(query): queryFilterCallback { + _execQuery(query: object): queryFilterCallback { return new QueryParser(this.paths).execQuery(query); } diff --git a/src/types.ts b/src/types.ts index 4e1a2468..161ca0a7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,3 +1,5 @@ +import type SchemaType from "./schematype"; + export type NodeJSLikeCallback = (err: E, result?: R) => void export interface Options { @@ -6,3 +8,25 @@ export interface Options { limit?: number; [key: PropertyKey]: any; } + +export type SchemaTypeOptions = typeof SchemaType | SchemaType | ((...args: any[]) => any) + +export type AddSchemaTypeSimpleOptions = SchemaTypeOptions | { type: SchemaTypeOptions; [key: string]: any }; + +export type AddSchemaTypeMixedOptions = AddSchemaTypeSimpleOptions | AddSchemaTypeSimpleOptions[]; + +export interface AddSchemaTypeLoopOptions { + [key: string]: AddSchemaTypeMixedOptions | AddSchemaTypeLoopOptions; +} + +export type AddSchemaTypeOptions = AddSchemaTypeMixedOptions | AddSchemaTypeLoopOptions; + +/** + * @typedef PopulateResult + * @property {string} path + * @property {*} model + */ +export type PopulateResult = { + path: string; + model: any; +}; \ No newline at end of file diff --git a/test/scripts/document.ts b/test/scripts/document.ts index 3d92fd35..565215ff 100644 --- a/test/scripts/document.ts +++ b/test/scripts/document.ts @@ -2,18 +2,30 @@ import chai from 'chai'; const should = chai.should(); // eslint-disable-line import Database from '../../dist/database'; import Document from '../../dist/document'; +import type Model from '../../dist/model'; + +interface UserType { + name?: string; + age?: number; + comments?: string; +} + +interface CommentType { + content?: string; + author?: string; +} describe('Document', () => { const db = new Database(); const Schema = Database.Schema; - const User = db.model('User', { + const User: Model = db.model('User', { name: String, age: Number, comments: [{type: Schema.Types.CUID, ref: 'Comment'}] }); - const Comment = db.model('Comment', { + const Comment: Model = db.model('Comment', { content: String, author: {type: Schema.Types.CUID, ref: 'User'} }); diff --git a/test/scripts/model.ts b/test/scripts/model.ts index 4830768c..bc4b5532 100644 --- a/test/scripts/model.ts +++ b/test/scripts/model.ts @@ -11,6 +11,24 @@ import cuid from 'cuid'; import Database from '../../dist/database'; import type Query from '../../dist/query'; import type Document from '../../dist/document'; +import type Model from '../../dist/model'; + +interface UserType { + name?: { + first: string; + last: string; + } + email?: string; + age?: number; + posts?: string[]; +} + +interface PostType { + title?: string; + content?: string; + user_id?: string; + created?: Date; +} describe('Model', () => { @@ -40,10 +58,10 @@ describe('Model', () => { created: Date }); - const User = db.model('User', userSchema); - const Post = db.model('Post', postSchema); + const User: Model = db.model('User', userSchema); + const Post: Model = db.model('Post', postSchema); - it('new()', () => { + it('new()', () => {`` const user = User.new({ name: {first: 'John', last: 'Doe'}, email: 'abc@example.com', @@ -106,6 +124,7 @@ describe('Model', () => { it('insert() - already existed', () => { let user; + // @ts-ignore return (User.insert({}).then(data => { user = data; return User.insert(data); @@ -506,7 +525,7 @@ describe('Model', () => { {age: 30}, {age: 40} ]).then(data => { - const query = User.find({age: 20}) as Query; + const query = User.find({age: 20}) as Query; query.data.should.eql(data.slice(1, 3)); return data; }).map(item => User.removeById(item._id))); @@ -518,7 +537,7 @@ describe('Model', () => { {age: 30}, {age: 40} ]).then(data => { - const query = User.find({}) as Query; + const query = User.find({}) as Query; query.data.should.eql(data); return data; }).map(item => User.removeById(item._id))); @@ -529,7 +548,7 @@ describe('Model', () => { {age: 30}, {age: 40} ]).then(data => { - const query = User.find({age: {$gt: 20}}) as Query; + const query = User.find({age: {$gt: 20}}) as Query; query.data.should.eql(data.slice(2)); return data; }).map(item => User.removeById(item._id))); @@ -540,7 +559,7 @@ describe('Model', () => { {age: 30}, {age: 40} ]).then(data => { - const query = User.find({age: {$gte: 20}}, {limit: 2}) as Query; + const query = User.find({age: {$gte: 20}}, {limit: 2}) as Query; query.data.should.eql(data.slice(1, 3)); return data; }).map(item => User.removeById(item._id))); @@ -551,11 +570,11 @@ describe('Model', () => { {age: 30}, {age: 40} ]).then(data => { - let query = User.find({age: {$gte: 20}}, {skip: 1}) as Query; + let query = User.find({age: {$gte: 20}}, {skip: 1}) as Query; query.data.should.eql(data.slice(2)); // with limit - query = User.find({age: {$gte: 20}}, {limit: 1, skip: 1}) as Query; + query = User.find({age: {$gte: 20}}, {limit: 1, skip: 1}) as Query; query.data.should.eql(data.slice(2, 3)); return data; @@ -584,7 +603,7 @@ describe('Model', () => { ] }); - (query as Query).toArray().should.eql([data[1]]); + (query as Query).toArray().should.eql([data[1]]); return data; }).map(item => User.removeById(item._id))); @@ -601,7 +620,7 @@ describe('Model', () => { ] }); - (query as Query).toArray().should.eql(data.slice(1)); + (query as Query).toArray().should.eql(data.slice(1)); return data; }).map(item => User.removeById(item._id))); @@ -618,7 +637,7 @@ describe('Model', () => { ] }); - (query as Query).toArray().should.eql([data[0]]); + (query as Query).toArray().should.eql([data[0]]); return data; }).map(item => User.removeById(item._id))); @@ -632,7 +651,7 @@ describe('Model', () => { $not: {'name.last': 'Doe'} }); - (query as Query).toArray().should.eql(data.slice(2)); + (query as Query).toArray().should.eql(data.slice(2)); return data; }).map(item => User.removeById(item._id))); @@ -648,7 +667,7 @@ describe('Model', () => { } }); - (query as Query).toArray().should.eql(data.slice(0, 2)); + (query as Query).toArray().should.eql(data.slice(0, 2)); return data; }).map(item => User.removeById(item._id))); @@ -669,7 +688,7 @@ describe('Model', () => { {age: 30}, {age: 40} ]).then(data => { - (User.findOne({age: {$gt: 20}}, {lean: true}) as Document)._id!.should.eql(data[2]._id); + (User.findOne({age: {$gt: 20}}, {lean: true}) as Document)._id!.should.eql(data[2]._id); return data; }).map(item => User.removeById(item._id))); @@ -830,32 +849,32 @@ describe('Model', () => { }).map(item => Post.removeById(item._id))); it('reduce()', () => Post.insert([ - {email: 'A'}, - {email: 'B'}, - {email: 'C'} + {title: 'A'}, + {title: 'B'}, + {title: 'C'} ]).then(data => { let num = 1; const sum = Post.reduce((sum, item, i) => { i.should.eql(num++); - return {email: sum.email + item.email}; + return {title: sum.title + item.title}; }); - sum.email.should.eql('ABC'); + sum.title.should.eql('ABC'); return data; }).map(item => Post.removeById(item._id))); it('reduce() - with initial', () => Post.insert([ - {email: 'A'}, - {email: 'B'}, - {email: 'C'} + {title: 'A'}, + {title: 'B'}, + {title: 'C'} ]).then(data => { let num = 0; const sum = Post.reduce((sum, item, i) => { i.should.eql(num++); - return sum + item.email; + return sum + item.title; }, '_'); sum.should.eql('_ABC'); @@ -864,32 +883,32 @@ describe('Model', () => { }).map(item => Post.removeById(item._id))); it('reduceRight()', () => Post.insert([ - {email: 'A'}, - {email: 'B'}, - {email: 'C'} + {title: 'A'}, + {title: 'B'}, + {title: 'C'} ]).then(data => { let num = 1; const sum = Post.reduceRight((sum, item, i) => { i.should.eql(num--); - return {email: sum.email + item.email}; + return {title: sum.title + item.title}; }); - sum.email.should.eql('CBA'); + sum.title.should.eql('CBA'); return data; }).map(item => Post.removeById(item._id))); it('reduceRight() - with initial', () => Post.insert([ - {email: 'A'}, - {email: 'B'}, - {email: 'C'} + {title: 'A'}, + {title: 'B'}, + {title: 'C'} ]).then(data => { let num = 2; const sum = Post.reduceRight((sum, item, i) => { i.should.eql(num--); - return sum + item.email; + return sum + item.title; }, '_'); sum.should.eql('_CBA'); @@ -1302,7 +1321,7 @@ describe('Model', () => { it('_export() - should not save undefined value', () => { // @ts-ignore - class CacheType extends SchemaType { + class CacheType extends SchemaType { value() {} } diff --git a/test/scripts/query.ts b/test/scripts/query.ts index eca942e7..1d2e0317 100644 --- a/test/scripts/query.ts +++ b/test/scripts/query.ts @@ -6,19 +6,32 @@ import Promise from 'bluebird'; import Document from '../../dist/document'; import Database from '../../dist/database'; import type Query from '../../dist/query'; +import type Model from '../../dist/model'; + +interface UserType { + name?: string; + age?: number; + comments?: string; +} + +interface LoopType { + age: { + age: number; + } +} describe('Query', () => { const db = new Database(); const Schema = Database.Schema; - const User = db.model('User', { + const User: Model = db.model('User', { name: String, age: Number, comments: [{type: Schema.Types.CUID, ref: 'Comment'}] }); - const Loop = db.model('Loop', { + const Loop: Model = db.model('Loop', { age: { age: Number } @@ -30,7 +43,7 @@ describe('Query', () => { }); it('count()', () => User.insert(Array(5).fill({})).then(data => { - (User.find({}) as Query).count().should.eql(data.length); + User.find({}).count().should.eql(data.length); return data; }).map(item => User.removeById(item._id))); @@ -46,7 +59,7 @@ describe('Query', () => { }).map(item => User.removeById(item._id))); it('toArray()', () => User.insert(Array(5).fill({})).then(data => { - (User.find({}) as Query).toArray().should.eql(data); + User.find({}).toArray().should.eql(data); return data; }).map(item => User.removeById(item._id))); @@ -54,7 +67,7 @@ describe('Query', () => { const query = User.find({}); for (let i = 0, len = data.length; i < len; i++) { - (query as Query).eq(i).should.eql(data[i]); + query.eq(i).should.eql(data[i]); } return data; @@ -64,44 +77,44 @@ describe('Query', () => { const query = User.find({}); for (let i = 1, len = data.length; i <= len; i++) { - (query as Query).eq(-i).should.eql(data[len - i]); + query.eq(-i).should.eql(data[len - i]); } return data; }).map(item => User.removeById(item._id))); it('first()', () => User.insert(Array(5).fill({})).then(data => { - (User.find({}) as Query).first().should.eql(data[0]); + User.find({}).first().should.eql(data[0]); return data; }).map(item => User.removeById(item._id))); it('last()', () => User.insert(Array(5).fill({})).then(data => { - (User.find({}) as Query).last().should.eql(data[data.length - 1]); + User.find({}).last().should.eql(data[data.length - 1]); return data; }).map(item => User.removeById(item._id))); it('slice()', () => User.insert(Array(5).fill({})).then(data => { - (User.find({}) as Query).slice(2, 4).data.should.eql(data.slice(2, 4)); + User.find({}).slice(2, 4).data.should.eql(data.slice(2, 4)); return data; }).map(item => User.removeById(item._id))); it('limit()', () => User.insert(Array(5).fill({})).then(data => { - (User.find({}) as Query).limit(2).data.should.eql(data.slice(0, 2)); + User.find({}).limit(2).data.should.eql(data.slice(0, 2)); return data; }).map(item => User.removeById(item._id))); it('skip()', () => User.insert(Array(5).fill({})).then(data => { - (User.find({}) as Query).skip(2).data.should.eql(data.slice(2)); + User.find({}).skip(2).data.should.eql(data.slice(2)); return data; }).map(item => User.removeById(item._id))); it('reverse()', () => User.insert(Array(5).fill({})).then(data => { - (User.find({}) as Query).reverse().data.should.eql(data.reverse()); + User.find({}).reverse().data.should.eql(data.reverse()); return data; }).map(item => User.removeById(item._id))); it('shuffle()', () => User.insert(Array(5).fill({})).then(data => { - sortBy((User.find({}) as Query).shuffle().data, '_id').should.eql(sortBy(data, '_id')); + sortBy(User.find({}).shuffle().data, '_id').should.eql(sortBy(data, '_id')); return data; }).map(item => User.removeById(item._id))); @@ -112,7 +125,7 @@ describe('Query', () => { {age: 30}, {age: 40} ]).then(data => { - const query = (User.find({}) as Query).find({age: 20}) as Query; + const query = User.find({}).find({age: 20}); query.data.should.eql(data.slice(1, 3)); const { length } = query; @@ -130,7 +143,7 @@ describe('Query', () => { {age: 30}, {age: 40} ]).then(data => { - const query = (User.find({}) as Query).find({}) as Query; + const query = User.find({}).find({}); query.data.should.eql(data); return data; }).map(item => User.removeById(item._id))); @@ -141,7 +154,7 @@ describe('Query', () => { {age: 30}, {age: 40} ]).then(data => { - const query = (User.find({}) as Query).find({age: {$gt: 20}}) as Query; + const query = User.find({}).find({age: {$gt: 20}}); query.data.should.eql(data.slice(2)); return data; }).map(item => User.removeById(item._id))); @@ -152,7 +165,7 @@ describe('Query', () => { {age: 30}, {age: 40} ]).then(data => { - const query = (User.find({}) as Query).find({age: {$gte: 20}}, {limit: 2}) as Query; + const query = User.find({}).find({age: {$gte: 20}}, {limit: 2}) as Query; query.data.should.eql(data.slice(1, 3)); return data; }).map(item => User.removeById(item._id))); @@ -163,11 +176,11 @@ describe('Query', () => { {age: 30}, {age: 40} ]).then(data => { - let query = (User.find({}) as Query).find({age: {$gte: 20}}, {skip: 1}) as Query; + let query = User.find({}).find({age: {$gte: 20}}, {skip: 1}) as Query; query.data.should.eql(data.slice(2)); // with limit - query = (User.find({}) as Query).find({age: {$gte: 20}}, {limit: 1, skip: 1}) as Query; + query = User.find({}).find({age: {$gte: 20}}, {limit: 1, skip: 1}) as Query; query.data.should.eql(data.slice(2, 3)); return data; @@ -179,7 +192,7 @@ describe('Query', () => { {age: 30}, {age: 40} ]).then(data => { - const query = (User.find({}) as Query).find({age: {$gt: 20}}, {lean: true}) as Query; + const query = User.find({}).find({age: {$gt: 20}}, {lean: true}) as Query; query.should.be.a('array'); const { length } = query; for (let i = 0; i < length; i++) { @@ -193,12 +206,12 @@ describe('Query', () => { {name: 'John', age: 25}, {name: 'Jack', age: 30} ]).then(data => { - const query = (User.find({}) as Query).find({ + const query = User.find({}).find({ $and: [ {name: 'John'}, {age: {$gt: 20}} ] - }) as Query; + }); query.toArray().should.eql([data[1]]); @@ -210,12 +223,12 @@ describe('Query', () => { {name: 'John', age: 25}, {name: 'Jack', age: 30} ]).then(data => { - const query = (User.find({}) as Query).find({ + const query = User.find({}).find({ $or: [ {name: 'Jack'}, {age: {$gt: 20}} ] - }) as Query; + }); query.toArray().should.eql(data.slice(1)); @@ -227,12 +240,12 @@ describe('Query', () => { {name: 'John', age: 25}, {name: 'Jack', age: 30} ]).then(data => { - const query = (User.find({}) as Query).find({ + const query = User.find({}).find({ $nor: [ {name: 'Jack'}, {age: {$gt: 20}} ] - }) as Query; + }); query.toArray().should.eql([data[0]]); @@ -244,9 +257,9 @@ describe('Query', () => { {name: 'John', age: 25}, {name: 'Jack', age: 30} ]).then(data => { - const query = (User.find({}) as Query).find({ + const query = User.find({}).find({ $not: {name: 'John'} - }) as Query; + }); query.toArray().should.eql([data[2]]); @@ -258,11 +271,11 @@ describe('Query', () => { {name: 'John', age: 25}, {name: 'Jack', age: 30} ]).then(data => { - const query = (User.find({}) as Query).find({ + const query = User.find({}).find({ $where() { return this.name === 'John'; } - }) as Query; + }); query.toArray().should.eql(data.slice(0, 2)); @@ -274,12 +287,12 @@ describe('Query', () => { {name: 'John', age: 25}, {name: 'Jack', age: 30} ]).then(data => { - const query = (User.find({}) as Query).find({ + const query = User.find({}).find({ $and: [ {name: 'Jack'}, {age: {gt: 20}} ] - }) as Query; + }); query.toArray().length.should.eql(0); return data; @@ -290,12 +303,12 @@ describe('Query', () => { {name: 'John', age: 25}, {name: 'Jack', age: 30} ]).then(data => { - const query = (User.find({}) as Query).find({ + const query = User.find({}).find({ $and: [ {name: 'Jack'}, {age: {gt: {}}} ] - }) as Query; + }); query.toArray().should.eql([data[2]]); return data; @@ -307,7 +320,7 @@ describe('Query', () => { {age: 30}, {age: 40} ]).then(data => { - const result = (User.find({}) as Query).findOne({age: {$gt: 20}}); + const result = (User.find({})).findOne({age: {$gt: 20}}); result.should.eql(data[2]); result.should.to.be.an.instanceof(Document); return data; @@ -319,8 +332,8 @@ describe('Query', () => { {age: 30}, {age: 40} ]).then(data => { - const result = (User.find({}) as Query).findOne({age: {$gt: 20}}, {lean: true}); - result._id.should.eql(data[2]._id); + const result = User.find({}).findOne({age: {$gt: 20}}, {lean: true}) as Document; + result._id!.should.eql(data[2]._id); result.should.to.not.be.an.instanceof(Document); return data; }).map(item => User.removeById(item._id))); @@ -330,7 +343,7 @@ describe('Query', () => { {age: 35}, {age: 10} ]).then(data => { - const query = (User.find({}) as Query).sort('age'); + const query = User.find({}).sort('age'); query.data[0].should.eql(data[2]); query.data[1].should.eql(data[0]); query.data[2].should.eql(data[1]); @@ -342,7 +355,7 @@ describe('Query', () => { {age: {age: 35}}, {age: {age: 10}} ]).then(data => { - const query = (Loop.find({}) as Query).sort('age', { age: 1 }); + const query = Loop.find({}).sort('age', { age: 1 }); query.data[0].should.eql(data[2]); query.data[1].should.eql(data[0]); query.data[2].should.eql(data[1]); @@ -354,7 +367,7 @@ describe('Query', () => { {age: 35}, {age: 10} ]).then(data => { - const query = (User.find({}) as Query).sort('age', -1); + const query = User.find({}).sort('age', -1); query.data[0].should.eql(data[1]); query.data[1].should.eql(data[0]); query.data[2].should.eql(data[2]); @@ -367,7 +380,7 @@ describe('Query', () => { {age: 20, name: 'C'}, {age: 20, name: 'D'} ]).then(data => { - const query = (User.find({}) as Query).sort('age name'); + const query = User.find({}).sort('age name'); query.data[0].should.eql(data[0]); query.data[1].should.eql(data[2]); query.data[2].should.eql(data[3]); @@ -469,7 +482,7 @@ describe('Query', () => { const query = User.find({}).filter((data, i) => { i.should.eql(num++); return data.age > 20; - }) as Query; + }); query.data.should.eql(data.slice(2)); @@ -518,7 +531,7 @@ describe('Query', () => { {age: 30}, {age: 20}, {age: 40} - ]).then(data => (User.find({age: 20}) as Query).update({name: 'A'}).then(updated => { + ]).then(data => User.find({age: 20}).update({name: 'A'}).then(updated => { updated[0]._id.should.eql(data[1]._id); updated[1]._id.should.eql(data[3]._id); updated[0].name.should.eql('A'); @@ -532,7 +545,7 @@ describe('Query', () => { {age: 30}, {age: 20}, {age: 40} - ]).then(data => (User.find({age: 20}) as Query).replace({name: 'A'}).then(updated => { + ]).then(data => User.find({age: 20}).replace({name: 'A'}).then(updated => { updated[0]._id.should.eql(data[1]._id); updated[1]._id.should.eql(data[3]._id); updated[0].name.should.eql('A'); @@ -546,7 +559,7 @@ describe('Query', () => { {age: 30}, {age: 20}, {age: 40} - ]).then(data => (User.find({age: 20}) as Query).remove().then(removed => { + ]).then(data => User.find({age: 20}).remove().then(removed => { should.not.exist(User.findById(data[1]._id)); should.not.exist(User.findById(data[3]._id)); return [data[0], data[2], data[4]]; @@ -563,7 +576,7 @@ describe('Query', () => { }); }).then(comment_ => { comment = comment_; - return (Comment.find({}) as Query).populate('author'); + return Comment.find({}).populate('author'); }).then(result => { result.first().author.should.eql(user); @@ -615,7 +628,7 @@ describe('Query', () => { }); }).then(comment_ => { comment = comment_; - return (Comment.find({}) as Query).populate(['author']); + return Comment.find({}).populate(['author']); }).then(result => { result.first().author.should.eql(user); @@ -637,7 +650,7 @@ describe('Query', () => { }); }).then(comment_ => { comment = comment_; - return (Comment.find({}) as Query).populate([{ path: 'author' }]); + return Comment.find({}).populate([{ path: 'author' }]); }).then(result => { result.first().author.should.eql(user); @@ -650,7 +663,7 @@ describe('Query', () => { it('populate() - path is required', () => { try { - (Comment.find({}) as Query).populate({}); + Comment.find({}).populate({}); } catch (err) { err.message.should.eql('path is required'); } diff --git a/test/scripts/schema.ts b/test/scripts/schema.ts index f14cd92d..dbe04a8f 100644 --- a/test/scripts/schema.ts +++ b/test/scripts/schema.ts @@ -100,6 +100,7 @@ describe('Schema', () => { schema.hooks.pre.remove.should.have.length(1); // incompatible type + // @ts-ignore (() => schema.pre('wtf', () => {})).should.to.throw(TypeError, 'Hook type must be `save` or `remove`!'); // hook is not a function @@ -121,6 +122,7 @@ describe('Schema', () => { schema.hooks.post.remove.should.have.length(1); // incompatible type + // @ts-ignore (() => schema.post('wtf', () => {})).should.throw(TypeError, 'Hook type must be `save` or `remove`!'); // hook is not a function