Closed LucasRomier closed 8 months ago
Hi @LucasRomier,
Glad to hear its useful! Exactly why I built it for myself.
The tool does its best to determine the type of mongoose methods and generate them strongly, but sometimes it cant determine them (eg they are in a format that is not recognized). If you can paste your full schema and method definition, I can do some testing and see whats preventing it from picking the type up properly and try to add support for it.
Yes of course, I created a pastebin for you: https://pastebin.com/6yxuPRsR.
In it, I detailed the three additions that I would love to have:
Thank you for your consideration!
Best regards
Sorry for the delay @LucasRomier, planning to look at this over the weekend. Thanks for providing these details!
Hi @LucasRomier, I was able to find the problem. Finding types in a file can be a bit tricky due to the variety of ways that TS can be defined. I was able to get your file to generate proper types by making the following changes:
Plan
model as a named export. mongoose-tsgen needs to find the line which initializes the model (eg const Plan: IPlanModel = model<IPlanDocument, IPlanModel>("IPlan", PlanSchema);
but if it is not exported then it is harder)Schema.methods = {}
, Schema.statics = {}
, etc rather than passing them directly to the schema. This makes it much easier to determine the types.Lastly, if you aren't already, make sure you use the imports
CLI argument (or option in mtgen.config.json): --imports "import { Moment } from \"moment-timezone\""
. This will ensure that moment-timezone
is imported into the generated type file so that the virtual return type works properly. Usually with import statements its easier to use the mtgen.config.json file, you can see an example in the README.
Here's the resulting file:
import { Schema, model } from "mongoose";
import { IPlanModel, IPlanSchema, IPlanDocument} from "../types/mongoose-types";
import moment, { Moment } from "moment-timezone";
import { pbkdf2, randomBytes } from "crypto";
const PlanSchema: IPlanSchema = new Schema({
expiresOnRaw: {
type: Date,
default: undefined
},
secret: {
key: {
type: String,
unique: true,
default: () => randomBytes(64).toString("hex"),
required: [true, 'Secret must be set'],
},
lastKeyChange: {
type: Date
}
},
}, {
timestamps: true
});
PlanSchema.methods = {
newKey(key: string): Promise<void> {
const promise = new Promise<void>(async (resolve, reject) => {
this.secret.key = await Plan.hashKey(key);
this.secret.lastKeyChange = new Date();
try {
await this.save();
} catch (err) {
return reject(err);
}
return resolve();
});
return promise;
}
}
PlanSchema.statics = {
hashKey(key: string): Promise<string> {
const promise = new Promise<string>((resolve, reject) => {
pbkdf2(key, "12345", 1, 1, "sha256", async (err, hashed) => {
if (err) return reject(err);
resolve(hashed.toString("hex"));
});
});
return promise;
}
}
PlanSchema.virtual("expiresOn").get(function(): Moment | undefined {
if (!this.expiresOnRaw) return undefined;
return moment(this.expiresOnRaw);
});
const Plan: IPlanModel = model<IPlanDocument, IPlanModel>("IPlan", PlanSchema);
export default Plan;
Hi @francescov1,
This is perfect, thank you so much! Already found three errors where I used Number instead of number 😅...
Best regards!
Type safe mongoose is a game changer 🙌 happy to help!
Hi,
To start off, I am very fond of this extension as it has saved me countless hours of defining my Mongoose Schemas.
Would it however be possible to strongly type the parameters of my schema methods?
E.g., my method is
getAccessLog(pageSize: number, page: number, sort: "date" | "type" | "value", sortOrder: -1 | 1): Prom
Currently results in the following under the generated method typesgetAccessLog: (this: IPlanDocument, ...args: any[]) => any;
Would it be possible, to stronly type this to
getAccessLog: (this: IPlanDocument, pageSize: number, page: number, sort: "date" | "type" | "value", sortOrder: -1 | 1) => ILog[];
Thank you for your consideration!