Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: refactor types #249

Merged
merged 4 commits into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class Database {
* @param {Schema|object} [schema]
* @return {Model}
*/
model(name: string, schema?: Schema | Record<string, AddSchemaTypeOptions>): Model<any> {
model<T>(name: string, schema?: Schema<T> | Record<string, AddSchemaTypeOptions>): Model<any> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
model<T>(name: string, schema?: Schema<T> | Record<string, AddSchemaTypeOptions>): Model<any> {
model<T = any>(name: string, schema?: Schema<T> | Record<string, AddSchemaTypeOptions>): Model<any> {

We can assign a default value to any to prevent breaking change (where model previously doesn't require a type argument).

if (this._models[name]) {
return this._models[name];
}
Expand Down
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;
abstract _schema: Schema;
abstract _schema: Schema<T>;
[key : string]: any;

/**
Expand Down
12 changes: 6 additions & 6 deletions src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type { AddSchemaTypeOptions, NodeJSLikeCallback, Options, PopulateResult
class Model<T> extends EventEmitter {
_mutex = new Mutex();
data: Record<PropertyKey, T> = {};
schema: Schema;
schema: Schema<T>;
length = 0;
Document;
Query;
Expand All @@ -28,10 +28,10 @@ class Model<T> extends EventEmitter {
* @param {string} name Model name
* @param {Schema|object} [schema_] Schema
*/
constructor(public name: string, schema_: Schema | Record<string, AddSchemaTypeOptions>) {
constructor(public name: string, schema_: Schema<T> | Record<string, AddSchemaTypeOptions>) {
super();

let schema: Schema;
let schema: Schema<T>;

// Define schema
if (schema_ instanceof Schema) {
Expand All @@ -51,7 +51,7 @@ class Model<T> extends EventEmitter {

class _Document<T> extends Document<T> {
_model!: Model<T>;
_schema!: Schema;
_schema!: Schema<T>;
constructor(data: T) {
super(data);

Expand All @@ -67,7 +67,7 @@ class Model<T> extends EventEmitter {

class _Query<T> extends Query<T> {
_model!: Model<T>;
_schema!: Schema;
_schema!: Schema<T>;
}

this.Query = _Query;
Expand Down Expand Up @@ -963,7 +963,7 @@ class Model<T> extends EventEmitter {

Model.prototype.get = Model.prototype.findById;

function execHooks(schema: Schema, type: string, event: string, data: any): Promise<any> {
function execHooks(schema: Schema<any>, type: string, event: string, data: any): Promise<any> {
const hooks = schema.hooks[type][event] as ((data: any) => Promise<void> | void)[];
if (!hooks.length) return Promise.resolve(data);

Expand Down
2 changes: 1 addition & 1 deletion src/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ abstract class Query<T> {
data: Document<T>[];
length: number;
abstract _model: Model<T>;
abstract _schema: Schema;
abstract _schema: Schema<T>;

/**
* Query constructor.
Expand Down
7 changes: 4 additions & 3 deletions src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import PopulationError from './error/population';
import SchemaTypeVirtual from './types/virtual';
import { isPlainObject } from 'is-plain-object';
import type { AddSchemaTypeLoopOptions, AddSchemaTypeOptions, PopulateResult, SchemaTypeOptions } from './types';
import type Model from './model';

/**
* @callback queryFilterCallback
Expand Down Expand Up @@ -379,7 +380,7 @@ class QueryParser {
}


class Schema {
class Schema<T> {
paths: Record<string, SchemaType<any>> = {};
statics: Record<string, (...args: any[]) => any> = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
statics: Record<string, (...args: any[]) => any> = {};
statics: Record<string, (this: T, ...args: any[]) => any> = {};

Is it possible to improve the types here as well? This could achieve stricter type checking.

methods: Record<string, (...args: any[]) => any> = {};
Expand Down Expand Up @@ -557,7 +558,7 @@ class Schema {
* @param {Function} [getter]
* @return {SchemaType.Virtual}
*/
virtual(name: string, getter?: () => any): SchemaTypeVirtual {
virtual(name: string, getter?: (this: T) => any): SchemaTypeVirtual<T> {
const virtual = new Types.Virtual(name, {});
if (getter) virtual.get(getter);

Expand Down Expand Up @@ -614,7 +615,7 @@ class Schema {
* @param {String} name
* @param {Function} fn
*/
static(name: string, fn: (...args: any[]) => any) {
static(name: string, fn: (this: Model<T>, ...args: any[]) => any) {
if (!name) throw new TypeError('Method name is required!');

if (typeof fn !== 'function') {
Expand Down
8 changes: 4 additions & 4 deletions src/types/virtual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { setGetter } from '../util';
/**
* Virtual schema type.
*/
class SchemaTypeVirtual extends SchemaType<any> {
getter: (() => any) | undefined;
class SchemaTypeVirtual<T> extends SchemaType<any> {
getter: ((this: T) => any) | undefined;
setter: ((value: any) => void) | undefined;

/**
Expand All @@ -14,7 +14,7 @@ class SchemaTypeVirtual extends SchemaType<any> {
* @param {Function} fn
* @chainable
*/
get(fn: () => any): SchemaTypeVirtual {
get(fn: (this: T) => any): SchemaTypeVirtual<T> {
if (typeof fn !== 'function') {
throw new TypeError('Getter must be a function!');
}
Expand All @@ -30,7 +30,7 @@ class SchemaTypeVirtual extends SchemaType<any> {
* @param {Function} fn
* @chainable
*/
set(fn: (value: any) => void): SchemaTypeVirtual {
set(fn: (this: T, value: any) => void): SchemaTypeVirtual<T> {
if (typeof fn !== 'function') {
throw new TypeError('Setter must be a function!');
}
Expand Down
10 changes: 9 additions & 1 deletion test/scripts/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@

const db = new Database();

const userSchema = new Schema({
const userSchema = new Schema<{
name: {
first: string;
last: string;
}
email: string;
age: number;
posts: string[];
}>({
name: {
first: String,
last: String
Expand Down Expand Up @@ -68,7 +76,7 @@
age: 20
});

user._id!.should.exist;

Check warning on line 79 in test/scripts/model.ts

View workflow job for this annotation

GitHub Actions / linter

Forbidden non-null assertion
user.name.first.should.eql('John');
user.name.last.should.eql('Doe');
user.name.full.should.eql('John Doe');
Expand Down Expand Up @@ -688,7 +696,7 @@
{age: 30},
{age: 40}
]).then(data => {
(User.findOne({age: {$gt: 20}}, {lean: true}) as Document<UserType>)._id!.should.eql(data[2]._id);

Check warning on line 699 in test/scripts/model.ts

View workflow job for this annotation

GitHub Actions / linter

Forbidden non-null assertion
return data;
}).map<unknown, any>(item => User.removeById(item._id)));

Expand Down
2 changes: 1 addition & 1 deletion test/scripts/types/virtual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const should = chai.should(); // eslint-disable-line
import SchemaTypeVirtual from '../../../dist/types/virtual';

describe('SchemaTypeVirtual', () => {
const type = new SchemaTypeVirtual('test');
const type = new SchemaTypeVirtual<any>('test');

it('get()', () => {
const getter = () => 'foo';
Expand Down
Loading