npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mongoose-tsgen-feathers

v1.3.0

Published

A Typescript interface generator for Mongoose that works out of the box.

Downloads

5

Readme

mongoose-tsgen

An out-of-the-box Typescript interface generator for Mongoose.

oclif Version npm License

Features

  • [x] Automatically generate an index.d.ts file containing Typescript interfaces for each Mongoose document, model and subdocument
  • [x] Works out of the box, don't need to rewrite your schemas
  • [x] Add custom interfaces (i.e. a subset of a document for use by a client)
  • [x] Multiple search patterns and import strategies to require minimal input and configuration

Compatibility

  • [x] All Mongoose types and arrays
  • [x] Virtual properties
  • [x] Both Typescript and Javascript schema files (if using Javascript, you will want to convert to Typescript upon generating the index.d.ts file)
  • [x] Typescript path aliases
  • [x] Mongoose method and static functions - These could be improved, they currently get typed as Function without parameter and return types
  • [ ] Support for Model.Create. Currently new Model must be used.
  • [ ] Setting subdocument arrays without casting to any (currently you need to do user.friends = [{ uid, name }] as any).

Would love any help with the last few listed features above.

Installation

$ npm install -D mongoose-tsgen
$ npx mtgen --help # print usage

Usage

mtgen [ROOT_PATH]

Generate an index.d.ts file containing Mongoose Schema interfaces.

USAGE
  $ mtgen [ROOT_PATH - default = "."]

OPTIONS
  -d, --dry-run          print output rather than writing to file
  -h, --help             show CLI help
  -j, --js               search for Mongoose schemas in Javascript files rather than in Typescript files
  -o, --output=output    [default: ./src/types/mongoose] path of output index.d.ts file
  -p, --project=project  [default: ./] path of tsconfig.json or its root folder

All sub-directories of ROOT_PATH will be searched for a /models/ folder. If such folder contains an index.ts (or index.js) file, all Mongoose models are expected to be exported from here. If such file does not exist, all *.ts (or *.js) files in this folder are expected to export a Mongoose model.

NOTE: --output requires a folder path or a file path ending in index.d.ts. If the path does not exist, it will be created.

See code: src/index.ts

Example

./src/models/user.ts

// NOTE: you will need to import these types after your first ever run of the CLI
// See the 'Initializing Schemas' section
import mongoose, { IUser, IUserModel } from "mongoose";
const { Schema } = mongoose;

const UserSchema = new Schema({
  email: {
    type: String,
    required: true
  },
  firstName: {
    type: String,
    required: true
  },
  lastName: {
    type: String,
    required: true
  },
  metadata: Schema.Types.Mixed,
  friends: [
    {
      uid: {
        type: Schema.Types.ObjectId,
        ref: "User",
        required: true
      },
      nickname: String
    }
  ],
  city: {
    coordinates: {
      type: [Number],
      index: "2dsphere"
    }
  }
});

// NOTE: `this: IUser` and `this: IUserModel` is to tell TS the type of `this' value using the "fake this" feature
// you will need to add these in after your first ever run of the CLI

UserSchema.virtual("name").get(function(this: IUser) { return `${this.firstName} ${this.lastName}` });

// method functions
UserSchema.methods = {
  isMetadataString(this: IUser) { return typeof this.metadata === "string"; }
}

// static functions
UserSchema.statics = {
  // friendUids could also use the type `ObjectId[]` here
  async getFriends(this: IUserModel, friendUids: IUser["_id"][]) {
    return await this.aggregate([ { $match: { _id: { $in: friendUids } } } ]);
  }
}

export const User: IUserModel = mongoose.model<IUser, IUserModel>("User", UserSchema);
export default User;

generate interfaces

$ mtgen

generated interface file ./src/types/mongoose/index.d.ts

// ######################################## THIS FILE WAS GENERATED BY MONGOOSE-TSGEN ######################################## //

// NOTE: ANY CHANGES MADE WILL BE OVERWRITTEN ON SUBSEQUENT EXECUTIONS OF MONGOOSE-TSGEN.
// TO ADD CUSTOM INTERFACES, DEFINE THEM IN THE `custom.d.ts` FILE.

import mongoose from "mongoose";
type ObjectId = mongoose.Types.ObjectId;

declare module "mongoose" {

	interface IUserFriend extends mongoose.Types.Subdocument {
		uid: IUser["_id"] | IUser;
		nickname?: string;
	}

	export interface IUserModel extends Model<IUser> {
		getFriends: Function;
	}

	export interface IUser extends Document {
		email: string;
		metadata?: any;
		firstName: string;
		lastName: string;
		friends: Types.DocumentArray<IUserFriend>;
		cityCoordinates?: Types.Array<number>;
		name: any;
		isMetadataString: Function;
	}

}

Initializing Schemas

Once you've generated your index.d.ts file, all you need to do is add the following types to your schema definitions:

user.ts before:

import mongoose from "mongoose";

const UserSchema = new Schema(...);

export const User = mongoose.model("User", UserSchema);
export default User;

user.ts after:

import mongoose, { IUser, IUserModel } from "mongoose";

const UserSchema = new Schema(...);

export const User: IUserModel = mongoose.model<IUser, IUserModel>("User", UserSchema);
export default User;

Then you can import the interfaces across your application from the Mongoose module and use them for document types:

// import interface from mongoose module
import { IUser } from "mongoose"

async function getUser(uid: string): IUser {
  // user will be of type IUser
  const user = await User.findById(uid);
  return user;
}

async function editEmail(user: IUser, newEmail: string): IUser {
  user.email = newEmail;
  return await user.save();
}