'cannot access mongoose schema static method - typescript
the issue i am having is the following - have a method called "findByToken()" which is defined in the model and also implemented as a static method in the userSchema.
In another part of my app i cannot access the method using: User.findByToken(token) - can you help me with this? can`t seem to find an answere anywhere.
import mongoose = require('mongoose');
import validator = require('validator');
import jwt = require('jsonwebtoken');
interface IUser {
email: string,
password: string,
token: any[],
generateAuthToken(): () => any
}
interface IUserModel extends IUser, mongoose.Document{
findByToken: (token: any) => any;
findByCredentials: (email: string, password: string) => any
}
let userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
minlength: 1,
trim: true,
unique: true,
validate: {
validator: validator.isEmail,
message: '{VALUE} is not a valid email'
}
},
password: {
type: String,
required: true,
minlength: 6
},
tokens: [{
access: {
type: String,
required: true
},
token: {
type: String,
required: true
}
}]
});
userSchema.statics.findByToken = function(token: string) {
let User = this; //entire model is binded with .this
let decoded: any;
try{
decoded = jwt.verify(token, 'My Secret');
} catch(e) {
return Promise.reject('rejected');
}
return User.findOne({
_id: decoded._id,
'tokens.token': token,
'tokens.access': 'auth'
});
};
let User = mongoose.model<IUserModel>('User', userSchema);
export = User;
how i call the static methd:
import User = require('./../models/user');
import express = require("express");
/*
tsconfig.json:
"strict": true will enfore types for req, res, next - etc
*/
//creating our auth private middleware
let authenticate = (req: express.Request, res: express.Request, next: express.Request) => {
let token = req.header('x-auth');
//custom model method
User.findByToken(token).then((user) => {
// if(!user){
// return Promise.reject(); //sends you directly into catch
// }
// req.user = user;
// req.token = token;
// next();
}).catch((e) => {
res.status(401).send();
});
}
User.find
export = authenticate;
Solution 1:[1]
Look at this example. You will see that you have to write some interfaces in order to get your statics, methods, virtuals and queries right
import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { ApiProperty } from "@nestjs/swagger";
import * as mongoose from 'mongoose';
import { Document } from 'mongoose';
@Schema()
export class User extends Document {
@ApiProperty()
@Prop()
name: string;
@ApiProperty()
@Prop()
birthday: Date;
}
interface UserMethods {
sayHi()
}
interface UserQueries {
byName(name: String)
}
interface UserVirtuals {
virtualTest: string
}
export interface UserStatics {
findByName(name:string)
}
export const UserSchema = SchemaFactory.createForClass(User) as mongoose.Schema<User, mongoose.Model<User, UserQueries, UserMethods, UserVirtuals>, UserMethods, UserQueries>;
UserSchema.methods.sayHi = function () {
console.log(`Hi. My Name is ${this.name} and my birthday is ${this.birthday}`)
}
UserSchema.statics.findByName = function (name: string) {
return this.find({name: new RegExp(name, 'i')})
}
UserSchema.query.byName = function (name: string) {
return this.where({name: new RegExp(name, 'i')})
}
UserSchema.virtual("virtualTest").get(function () {
return "this is a virtual test"
})
export const UserModel = mongoose.model(User.name, UserSchema) as mongoose.Model<any, UserQueries, UserMethods, UserVirtuals> & UserStatics
And yes the <any...> in this last line is important, because your IDEA will throw an error if you User instead and tries to use your methods or virtuals etc. But no worries! The IDEA will actualy autocomplete the methods anyway. Somehow it realizes, that the userObject that you create with
UserModel.create({...})
actualy has all the new memthods and virtuals. The & UserStatics adds static methods to your UserModel, so no error is highlighted by using them.
Solution 2:[2]
let User = mongoose.model<IUserModel>('User', userSchema);
should be:
let User = mongoose.model<IUser, IUserModel>('User', userSchema);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Diesel |
