Skip to content

Commit

Permalink
refactor: refactor types
Browse files Browse the repository at this point in the history
  • Loading branch information
D-Sketon committed Jul 6, 2024
1 parent 2484daf commit 707c4f9
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 70 deletions.
2 changes: 1 addition & 1 deletion src/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const cloneDeep = rfdc();

abstract class Document<T> {
abstract _model: Model<T>;
_id!: string | number | undefined;
_id!: string;
abstract _schema: Schema<T>;
[key : string]: any;

Expand Down
19 changes: 11 additions & 8 deletions src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import WarehouseError from './error';
import PopulationError from './error/population';
import Mutex from './mutex';
import type Database from './database';
import type { AddSchemaTypeOptions, NodeJSLikeCallback, Options } from './types';
import type { AddSchemaTypeOptions, NodeJSLikeCallback, Options, queryCallback } from './types';

class Model<T> extends EventEmitter {
_mutex = new Mutex();
Expand Down Expand Up @@ -236,7 +236,7 @@ class Model<T> extends EventEmitter {
* @return {BluebirdPromise}
* @private
*/
_updateWithStack(id: string | number, stack: ((data: T) => void)[]): BluebirdPromise<any> {
_updateWithStack(id: string, stack: queryCallback<T>[]): BluebirdPromise<any> {
const schema = this.schema;

const data = this.data[id];
Expand Down Expand Up @@ -278,7 +278,7 @@ class Model<T> extends EventEmitter {
* @param {function} [callback]
* @return {BluebirdPromise}
*/
updateById(id: string | number, update: object, callback?: NodeJSLikeCallback<any>): BluebirdPromise<any> {
updateById(id: string, update: object, callback?: NodeJSLikeCallback<any>): BluebirdPromise<any> {
return BluebirdPromise.using(this._acquireWriteLock(), () => {
const stack = this.schema._parseUpdate(update);
return this._updateWithStack(id, stack);
Expand All @@ -305,7 +305,7 @@ class Model<T> extends EventEmitter {
* @return {BluebirdPromise}
* @private
*/
_replaceById(id: string | number, data_: Document<T> | T): BluebirdPromise<any> {
_replaceById(id: string, data_: Document<T> | T): BluebirdPromise<any> {
const schema = this.schema;

if (!this.has(id)) {
Expand Down Expand Up @@ -339,7 +339,7 @@ class Model<T> extends EventEmitter {
* @param {function} [callback]
* @return {BluebirdPromise}
*/
replaceById(id: string | number, data: Document<T> | T, callback?: NodeJSLikeCallback<any>): BluebirdPromise<any> {
replaceById(id: string, data: Document<T> | T, callback?: NodeJSLikeCallback<any>): BluebirdPromise<any> {
return BluebirdPromise.using(this._acquireWriteLock(), () => this._replaceById(id, data)).asCallback(callback);
}

Expand All @@ -362,7 +362,7 @@ class Model<T> extends EventEmitter {
* @return {BluebirdPromise}
* @private
*/
_removeById(id: string | number): BluebirdPromise<any> {
_removeById(id: string): BluebirdPromise<any> {
const schema = this.schema;

const data = this.data[id];
Expand All @@ -389,7 +389,7 @@ class Model<T> extends EventEmitter {
* @param {function} [callback]
* @return {BluebirdPromise}
*/
removeById(id: string | number, callback?: NodeJSLikeCallback<any>): BluebirdPromise<any> {
removeById(id: string, callback?: NodeJSLikeCallback<any>): BluebirdPromise<any> {
return BluebirdPromise.using(this._acquireWriteLock(), () => this._removeById(id)).asCallback(callback);
}

Expand Down Expand Up @@ -531,7 +531,10 @@ class Model<T> extends EventEmitter {
* @param {String|Number} [order]
* @return {Query}
*/
sort(orderby: string | object, order?: string | number | object): Query<T> {
sort(orderby: string, order: 'desc' | number | Record<string, any>): Query<T>;
sort(orderby: string): Query<T>;
sort(orderby: Record<string, number | Record<string, any>>): Query<T>;
sort(orderby: string | Record<string, number | Record<string, any>>, order?: 'desc' | number | Record<string, any>): Query<T> {
const sort = parseArgs(orderby, order);
const fn = this.schema._execSort(sort);

Expand Down
7 changes: 5 additions & 2 deletions src/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,17 @@ abstract class Query<T> {
* query.sort('-date title');
* ```
*
* If the `order` equals to `-1`, `desc` or `descending`, the data will be
* If the `order` equals to `-1` or `desc`, the data will be
* returned in reversed order.
*
* @param {String|Object} orderby
* @param {String|Number} [order]
* @return {Query}
*/
sort(orderby: string | object, order?: string | number | object): Query<T> {
sort(orderby: string, order: 'desc' | number | Record<string, any>): Query<T>;
sort(orderby: string): Query<T>;
sort(orderby: Record<string, number | Record<string, any>>): Query<T>;
sort(orderby: string | Record<string, number | Record<string, any>>, order?: 'desc' | number | Record<string, any>): Query<T> {
const sort = parseArgs(orderby, order);
const fn = this._schema._execSort(sort);

Expand Down
78 changes: 27 additions & 51 deletions src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,24 @@ import { getProp, setProp, delProp } from './util';
import PopulationError from './error/population';
import SchemaTypeVirtual from './types/virtual';
import { isPlainObject } from 'is-plain-object';
import type { AddSchemaTypeLoopOptions, AddSchemaTypeOptions, Options, SchemaTypeOptions } from './types';
import type { AddSchemaTypeLoopOptions, AddSchemaTypeOptions, AddSchemaTypeSimpleOptions, Options, queryCallback, queryFilterCallback, queryParseCallback, SchemaTypeOptions } from './types';
import type Model from './model';

/**
* @callback queryFilterCallback
* @param {*} data
* @return {boolean}
*/
type queryFilterCallback = (data: unknown) => boolean;

/**
* @callback queryCallback
* @param {*} data
* @return {void}
*/
type queryCallback = (data: unknown) => void;

/**
* @callback queryParseCallback
* @param {*} a
* @param {*} b
* @returns {*}
*/
type queryParseCallback = (a: unknown, b: unknown) => number;
import type Document from './document';

const builtinTypes = new Set(['String', 'Number', 'Boolean', 'Array', 'Object', 'Date', 'Buffer']);

const getSchemaType = (name: string, options: { type: SchemaTypeOptions; [key: string]: any } | SchemaTypeOptions) => {
const Type = (options as any).type || options;
const typeName: string = Type.name;
const getSchemaType = (name: string, options: AddSchemaTypeSimpleOptions): SchemaType<any> => {
const Type: SchemaTypeOptions = (options as any).type || options;
const typeName = Type.name;

if (builtinTypes.has(typeName)) {
return new Types[typeName](name, options);
}

return new Type(name, options);
return new Type(name, options as Exclude<AddSchemaTypeSimpleOptions, SchemaTypeOptions>);
};

const checkHookType = (type: string) => {
const checkHookType = (type: string): void => {
if (type !== 'save' && type !== 'remove') {
throw new TypeError('Hook type must be `save` or `remove`!');
}
Expand All @@ -57,13 +36,10 @@ const hookWrapper = (fn: (...args: any[]) => void): (...args: any[]) => Bluebird
return BluebirdPromise.method(fn);
};

/**
* @param {Function[]} stack
*/
const execSortStack = (stack: ((a: unknown, b: unknown) => number)[]) => {
const execSortStack = <T = any>(stack: queryParseCallback<Document<T>>[]): queryParseCallback<Document<T>> => {
const len = stack.length;

return (a: any, b: any) => {
return (a: Document<T>, b: Document<T>) => {
let result: number;

for (let i = 0; i < len; i++) {
Expand All @@ -75,11 +51,11 @@ const execSortStack = (stack: ((a: unknown, b: unknown) => number)[]) => {
};
};

const sortStack = (path_: SchemaType<any>, key: string, sort: string | number) => {
const sortStack = <T = any>(path_: SchemaType<any>, key: string, sort: string | number): queryParseCallback<Document<T>> => {
const path = path_ || new SchemaType(key);
const descending = sort === 'desc' || sort === -1;

return (a: any, b: any) => {
return (a: Document<T>, b: Document<T>) => {
const result = path.compare(getProp(a, key), getProp(b, key));
return descending && result ? result * -1 : result;
};
Expand All @@ -90,7 +66,7 @@ class UpdateParser {
return (data: any) => { setProp(data, key, update); };
}

static updateStackOperator(path_: SchemaType<unknown>, ukey: string | number, key: string, update: any) {
static updateStackOperator(path_: SchemaType<unknown>, ukey: string, key: string, update: any) {
const path = path_ || new SchemaType(key);

return (data: any) => {
Expand All @@ -109,7 +85,7 @@ class UpdateParser {
* @param {queryCallback[]} [stack]
* @private
*/
parseUpdate(updates: object, prefix = '', stack: queryCallback[] = []): queryCallback[] {
parseUpdate<T>(updates: object, prefix = '', stack: queryCallback<T>[] = []): queryCallback<T>[] {
const { paths } = this;
const { updateStackOperator } = UpdateParser;
const keys = Object.keys(updates);
Expand Down Expand Up @@ -181,7 +157,7 @@ class QueryParser {
queryStackOperator(qkey: string, name: string, query: any): queryFilterCallback {
const path = this.paths[name] || new SchemaType(name);

return data => path[qkey](getProp(data, name), query, data);
return (data: unknown) => path[qkey](getProp(data, name), query, data);
}

/**
Expand All @@ -190,7 +166,7 @@ class QueryParser {
* @return {void}
* @private
*/
$and(arr: any[], stack: queryFilterCallback[]): void {
$and(arr: object[], stack: queryFilterCallback[]): void {
for (let i = 0, len = arr.length; i < len; i++) {
stack.push(this.execQuery(arr[i]));
}
Expand All @@ -201,7 +177,7 @@ class QueryParser {
* @return {queryFilterCallback}
* @private
*/
$or(query: any[]): queryFilterCallback {
$or(query: object[]): queryFilterCallback {
const stack = this.parseQueryArray(query);
const len = stack.length;

Expand All @@ -219,7 +195,7 @@ class QueryParser {
* @return {queryFilterCallback}
* @private
*/
$nor(query: any[]): queryFilterCallback {
$nor(query: object[]): queryFilterCallback {
const stack = this.parseQueryArray(query);
const len = stack.length;

Expand All @@ -237,7 +213,7 @@ class QueryParser {
* @return {queryFilterCallback}
* @private
*/
$not(query: any): queryFilterCallback {
$not(query: object): queryFilterCallback {
const stack = this.parseQuery(query);
const len = stack.length;

Expand All @@ -261,7 +237,7 @@ class QueryParser {
* @return {queryFilterCallback}
* @private
*/
$where(fn: (...args: any[]) => boolean): queryFilterCallback {
$where(fn: () => boolean): queryFilterCallback {
return data => Reflect.apply(fn, data, []);
}

Expand All @@ -272,8 +248,8 @@ class QueryParser {
* @return {queryFilterCallback[]}
* @private
*/
parseQueryArray(arr: any[]): queryFilterCallback[] {
const stack = [];
parseQueryArray(arr: object[]): queryFilterCallback[] {
const stack: queryFilterCallback[] = [];
this.$and(arr, stack);
return stack;
}
Expand Down Expand Up @@ -315,7 +291,7 @@ class QueryParser {
* @return {queryFilterCallback[]}
* @private
*/
parseQuery(queries: any): queryFilterCallback[] {
parseQuery(queries: object): queryFilterCallback[] {

/** @type {queryFilterCallback[]} */
const stack: queryFilterCallback[] = [];
Expand Down Expand Up @@ -573,7 +549,7 @@ class Schema<T = any> {
* @param {String} type Hook type. One of `save` or `remove`.
* @param {Function} fn
*/
pre(type: 'save' | 'remove', fn: (...args: any[]) => void): void {
pre(type: keyof Schema['hooks']['pre'], fn: (...args: any[]) => void): void {
checkHookType(type);
if (typeof fn !== 'function') throw new TypeError('Hook must be a function!');

Expand All @@ -586,7 +562,7 @@ class Schema<T = any> {
* @param {String} type Hook type. One of `save` or `remove`.
* @param {Function} fn
*/
post(type: 'save' | 'remove', fn: (...args: any[]) => void): void {
post(type: keyof Schema['hooks']['post'], fn: (...args: any[]) => void): void {
checkHookType(type);
if (typeof fn !== 'function') throw new TypeError('Hook must be a function!');

Expand Down Expand Up @@ -696,7 +672,7 @@ class Schema<T = any> {
* @return {queryCallback[]}
* @private
*/
_parseUpdate(updates: object): queryCallback[] {
_parseUpdate(updates: object): queryCallback<T>[] {
return new UpdateParser(this.paths).parseUpdate(updates);
}

Expand All @@ -721,7 +697,7 @@ class Schema<T = any> {
* @return {queryParseCallback[]}
* @private
*/
_parseSort(sorts: object, prefix = '', stack: queryParseCallback[] = []): queryParseCallback[] {
_parseSort(sorts: Record<string, number | string | Record<string, any>>, prefix = '', stack: queryParseCallback<Document<T>>[] = []): queryParseCallback<Document<T>>[] {
const { paths } = this;
const keys = Object.keys(sorts);

Expand All @@ -747,7 +723,7 @@ class Schema<T = any> {
* @return {queryParseCallback}
* @private
*/
_execSort(sorts: object): queryParseCallback {
_execSort(sorts: Record<string, number | string | Record<string, any>>): queryParseCallback<Document<T>> {
const stack = this._parseSort(sorts);
return execSortStack(stack);
}
Expand Down
33 changes: 28 additions & 5 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import type SchemaType from './schematype';

export type NodeJSLikeCallback<R, E = any> = (err: E, result?: R) => void
interface Constructor {
new (...args: any[]): any;
}

export type NodeJSLikeCallback<R, E = any> = (err: E, result?: R) => void;

export interface Options {
lean: boolean;
Expand All @@ -12,14 +16,33 @@ export interface Options {
model: string;
}

export type SchemaTypeOptions = typeof SchemaType<unknown> | SchemaType<unknown> | ((...args: any[]) => any)
export type SchemaTypeOptions = typeof SchemaType<unknown> | Constructor;

export type AddSchemaTypeSimpleOptions = SchemaTypeOptions | { type: SchemaTypeOptions; [key: string]: any };
export type AddSchemaTypeSimpleOptions =
| SchemaTypeOptions
| {
type: SchemaTypeOptions;
required?: boolean;
default?: (() => any) | any;
[key: string]: any;
};

export type AddSchemaTypeMixedOptions = AddSchemaTypeSimpleOptions | AddSchemaTypeSimpleOptions[];
export type AddSchemaTypeMixedOptions =
| AddSchemaTypeSimpleOptions
| []
| [AddSchemaTypeSimpleOptions];

export interface AddSchemaTypeLoopOptions {
[key: string]: AddSchemaTypeMixedOptions | AddSchemaTypeLoopOptions;
}

export type AddSchemaTypeOptions = AddSchemaTypeMixedOptions | AddSchemaTypeLoopOptions;
export type AddSchemaTypeOptions =
| AddSchemaTypeMixedOptions
| AddSchemaTypeLoopOptions
| SchemaType<unknown>;

export type queryFilterCallback = (data: unknown) => boolean;

export type queryCallback<T> = (data: T) => void;

export type queryParseCallback<T> = (a: T, b: T) => number;
10 changes: 7 additions & 3 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function _parseArgs(args: string): Record<string, number> {
if (typeof args !== 'string') return args;

const arr = args.split(' ');
const result = {};
const result: Record<string, number> = {};

for (let i = 0, len = arr.length; i < len; i++) {
const key = arr[i];
Expand Down Expand Up @@ -173,8 +173,12 @@ export function reverse<T>(arr: T[]): T[] {
return arr;
}

export function parseArgs(orderby: string | object, order?: string | number | object): Record<string, number> {
let result;
export function parseArgs<B extends string, O extends number | string | Record<string, any>>(orderby: B, order: O): { [key in typeof orderby]: typeof order };
export function parseArgs<B extends string, O>(orderby: B): Record<string, number>;
export function parseArgs<B extends Record<string, number>, O>(orderby: B): B;
export function parseArgs<B extends string | Record<string, number | Record<string, any>>, O extends number | string | Record<string, any>>(orderby: B, order?: O): Record<string, number | string | object>;
export function parseArgs<B extends string | Record<string, number | Record<string, any>>, O extends number | string | Record<string, any>>(orderby: B, order?: O) {
let result: Record<string, number | string | Record<string, any>>;

if (order) {
result = {};
Expand Down

0 comments on commit 707c4f9

Please sign in to comment.