当前位置: 首页 > 软件库 > 数据库相关 > >

mongoose-tsgen

A plug-n-play Typescript generator for Mongoose.
授权协议 Readme
开发语言 TypeScript
所属分类 数据库相关
软件类型 开源软件
地区 不详
投 递 者 容阳焱
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

mongoose-tsgen

A plug-n-play Typescript generator for Mongoose.

Motivation

Using Mongoose with Typescript requires duplicating Mongoose Schemas using Typescript interfaces. To avoid duplication, libraries like typegoose define a custom schema syntax that is used to generate both the Mongoose Schemas and the Typescript interfaces. Unfortunately, this requires users to completely rewrite their Mongoose Schemas into an unfamiliar syntax and does not support the entire Mongoose feature set.

This library aims to remove these drawbacks by instead parsing your already-written Mongoose Schemas and generating associated Typescript interfaces. This removes the need to learn new syntax and makes this library extremely simple to integrate into an existing Mongoose project.

Features

  • �� Automatically generate Typescript typings for each Mongoose document, model and subdocument
  • �� Works out of the box, don't need to rewrite your schemas
  • Type-safe population
  • Includes a "Mongoose-less" version of each schema interface (Mongoose typings removed)

Compatibility

  • All Mongoose types, arrays and maps
  • Virtual properties
  • Mongoose method, static & query functions
  • Multiple schemas per file
  • Typescript path aliases

Mongoose version

Find your Mongoose version below and install the associated mongoose-tsgen version. Ensure to refer to each version's respective README for documentation (hyperlinked in table).

mongoose mongoose-tsgen
5.11.19+ latest
5.11.0-5.11.18 7.1.3
<5.11.0 6.0.10

Installation

mongoose-tsgen can be installed globally or locally as a dev dependency. Refer to the table above to ensure you are using the correct version.

# install with npm or yarn
npm install -D mongoose-tsgen

# install mongoose-tsgen v7.1.3 for mongoose v5.10.19 (see table above for compatibility)
npm install -D mongoose-tsgen@7.1.3

# install with yarn
yarn add -D mongoose-tsgen

The Gist

Once you've generated your typings file (see Usage), all you need to do is use the generated types in your schema definitions and throughout your project.

user.ts before:

import mongoose from "mongoose";

const UserSchema = new Schema(...);

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

user.ts after:

import mongoose from "mongoose";
import { UserDocument, UserModel, UserSchema } from "../interfaces/mongoose.gen.ts";

const UserSchema: UserSchema = new Schema(...);

export const User: UserModel = mongoose.model<UserDocument, UserModel>("User", UserSchema);

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

import { UserDocument } from "./interfaces/mongoose.gen.ts";

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

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

Note that this practice is well documented online, I've found the following two Medium articles especially useful:

Usage

mtgen [MODEL_PATH]

Generate a Typescript file containing Mongoose Schema typings.

If you run into unknown type issues, check your Mongoose version. For Mongoose v5.11+, ensure you have removed the deprecated community typings @types/mongoose.

USAGE
  $ mtgen [MODEL_PATH]

OPTIONS
  -c, --config=config     [default: ./] Path of `mtgen.config.json` or its root folder. CLI flag
                          options will take precendence over settings in `mtgen.config.json`.

  -d, --dry-run           Print output rather than writing to file.

  -h, --help              Show CLI help

  -i, --imports=imports   Custom import statements to add to the output file. Useful if you use
                          third-party types in your mongoose schema definitions. For multiple imports,
                          specify this flag more than once.

  -o, --output=output     [default: ./src/interfaces] Path of output file to write generated typings.
                          If a folder path is passed, the generator will create a `mongoose.gen.ts` file
                          in the specified folder.

  -p, --project=project   [default: ./] Path of `tsconfig.json` or its root folder.

  --debug                 Print debug information if anything isn't working

  --no-format             Disable formatting generated files with prettier.

  --no-mongoose           Don't generate types that reference mongoose (i.e. documents). Replace ObjectId with
                          string.

  --no-populate-overload  Disable augmenting mongoose with Query.populate overloads (the overloads narrow
                          the return type of populated documents queries).

Specify the directory of your Mongoose schema definitions using MODEL_PATH. If left blank, all sub-directories will be searched for models/*.ts (ignores index.ts files). Files found are expected to export a Mongoose model.

See code: src/index.ts

Configuration File

All CLI options can be provided using a mtgen.config.json file. Use the --config option to provide the folder path containing this file ("./" will be searched if no path is provided). CLI options will take precendence over options in the mtgen.config.json file.

mtgen.config.json

{
  "imports": ["import Stripe from \"stripe\""],
  "output": "./src/custom/path/mongoose-types.ts"
}

Query Population

Any field with a ref property will be typed as RefDocument["_id"] | RefDocument. As part of the generated file, mongoose will be augmented with Query.populate overloads to narrow return types of populated queries (this can be disabled using the --no-populate-overload flag). A helper type PopulatedDocument and a type guard function IsPopulated will also be generated to help with handling populated documents, see usage below:

import { IsPopulated, PopulatedDocument } from "../interfaces/mongoose.gen.ts";

// UserDocument["bestFriend"] = mongoose.Types.ObjectId | UserDocument
function unsafeType(user: UserDocument) {
  // type guard
  if (IsPopulated(user.bestFriend))) {
    // user.bestFriend is confirmed to be populated, typescript will allow accessing its properties now
    console.log(user.bestFriend._id)
  }
}

// `user` is typed as a UserDocument with `bestFriend` populated
function safeType(user: PopulatedDocument<UserDocument, "bestFriend">) {
  console.log(user.bestFriend._id)
}

// due to the `Query.populate` overload, `user` will be typed as `PopulatedDocument<UserDocument, "bestFriend">`
// rather than the usual `UserDocument`
const user = await User.findById(uid).populate("bestFriend").exec()

// completely type-safe
safeType(user)

Both the mongoose populate overload and the PopulateDocument type handle nested and array types with ease; you rarely need to worry about enforcing types manually. In the case that the populated type cannot be determined, types will fallback to the generic RefDocument["_id"] | RefDocument.

Example

./src/models/user.ts

import mongoose, { Schema } from "mongoose";
import { UserDocument, UserModel, UserSchema, UserObject } from "../interfaces/mongoose.gen.ts";

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

// NOTE: `this: UserDocument` is required for virtual properties 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: UserDocument) {
  return `${this.firstName} ${this.lastName}`;
});

UserSchema.methods = {
  isMetadataString() {
    return this.metadata === "string";
  }
};

UserSchema.statics = {
  async getFriends(friendUids: UserDocument["_id"][]): Promise<UserObject[]> {
    return await this.aggregate([{ $match: { _id: { $in: friendUids } } }]);
  }
};

UserSchema.query = {
  populateFriends() {
    return this.populate("bestFriend", "firstName lastName");
  }
};

export const User = mongoose.model<UserDocument, UserModel>("User", UserSchema);

generate typings

# run mongoose-tsgen
npx mtgen

generated typings file ./src/interfaces/mongoose.gen.ts

import mongoose from "mongoose";

export type UserFriend = {
  uid: User["_id"] | User;
  nickname?: string;
  _id: mongoose.Types.ObjectId;
}

export type UserObject = User;

export type UserQueries = {
  populateFriends: () => mongoose.Query<any, UserDocument, UserQueries> & UserQueries;
}

export type UserMethods = {
  isMetadataString: (this: UserDocument) => boolean;
}

export type UserStatics = {
  getFriends: (this: UserModel, friendUids: UserDocument["_id"][]) => Promise<UserObject[]>;
}

export type UserModel = mongoose.Model<UserDocument, UserQueries> & UserStatics

export type UserSchema = mongoose.Schema<UserDocument, UserModel>

export type User = {
  email: string;
  firstName: string;
  lastName: string;
  bestFriend?: User["_id"] | User;
  friends: UserFriend[];
  city: {
    coordinates: number[];
  };
  _id: mongoose.Types.ObjectId;
}

export type UserFriendDocument = mongoose.Types.Subdocument & {
  uid: UserDocument["_id"] | UserDocument;
  nickname?: string;
  _id: mongoose.Types.ObjectId;
};

export type UserDocument = mongoose.Document<mongoose.Types.ObjectId, UserQueries> &
  UserMethods & {
    email: string;
    firstName: string;
    lastName: string;
    metadata?: any;
    bestFriend?: UserDocument["_id"] | UserDocument;
    friends: mongoose.Types.DocumentArray<UserFriendDocument>;
    city: {
      coordinates: mongoose.Types.Array<number>;
    };
    name: string;
    _id: mongoose.Types.ObjectId;
  };

Development

  • 本文已整理到 Github,地址  blog。 如果我的内容帮助到了您,欢迎点个 Star  鼓励鼓励 :) ~~ 我希望我的内容可以帮助你。现在我专注于前端领域,但我也将分享我在有限的时间内看到和感受到的东西。 Mongoose aggregate Mongoose 的 aggregate() 方法是如何将 MongoDB 的聚合框架与 Mongoose 一起使用的。Mongoose a

  • Mongoose 参考手册 标签(空格分隔): MongoDB   一般我们不直接用MongoDB的函数来操作MongoDB数据库 Mongose就是一套操作MongoDB数据库的接口. Schema 一种以文件形式存储的数据库模型骨架,无法直接通往数据库端,也就是说它不具备对数据库的操作能力.可以说是数据属性模型(传统意义的表结构),又或着是“集合”的模型骨架 /* 定义一个 Schema */

  • 快速启动 首先需要安装MongoDB和Node.js。 然后使用npm下载mongoose: npm install mongoose 接着我们直接在项目中引入mongoose,并且连接数据库就会在本地运行 MongoDB了: // index.js var mongoose = require('mongoose'); mongoose.connect('mongodb://localhost/

  • 简单的 mongoose 示例 const mongoose = require('mongoose') mongoose.connect("mongodb://localhost:27017/study", {useNewUrlParser:true}, function(err){ if(err){ console.log('Connection Error:' + err)

  • 如果想要在NodeJS中连接MongoDB,可以选择直接使用mongodb为NodeJS写的驱动包,但我更推荐使用一个比较成熟的中间件:Mongoose。 官方定义 Mongoose 官方给出了这样的定义: Mongoose: elegant mongodb object modeling for node.js Mongoose:优雅地在NodeJS中进行MongoDB对象建模 Let’s fa

  • 在创建集合时可以设置当前字段的验证规则,不符合规则就插入失败 required:true -----必选字段 minlength:3 ------字符串最小长度不能小于3 maxlength:5 -------字符串最大长度不能大于5 min:2 ------最小数值不能小于2 mx:5 -----最大数值不能大于5 enum:[‘aaaa’,‘bbbbb’,‘ccccc’] — 只能传入这三个数

  • MongoDB 和 Mongoose mongoose 建立一个 MongoDB Atlas 数据库并导入连接到它所需的软件包。将 mongodb@~3.6.0 和 mongoose@~5.4.0 添加到项目的 package.json 中。 然后,在 myApp.js 文件中请求 mongoose。 创建一个 .env 文件,给它添加一个 MONGO_URI 变量。 变量的值为 MongoDB

 相关资料
  • Mongoose 是设计用于异步环境的 MongoDB 对象模型工具,支持 promises 和 callbacks。 概述 连接到 MongoDB 首先需要定义一个连接。如果应用仅使用一个数据库,则使用mongoose.connect。如果需要创建其他连接,请使用mongoose.createConnection。 connect 和 createConnection都使用 mongodb://

  • 问题内容: 据我所知,方法是,那是,并且也喜欢,但它们不是存储在数据库中。 但是,我想知道那是和之间的唯一区别。还有其他我想念的东西吗? 问题答案: 实例方法,静态方法或虚拟方法均未存储在数据库中。方法与虚拟函数之间的区别在于,虚拟函数的访问方式类似于属性,方法的调用方式类似于函数。实例与静态实例与虚拟实例之间没有区别,因为在类上具有可访问的虚拟静态属性是没有意义的,但在类上具有某些静态实用程序或

  • Mongoose Web Server是一款易于使用的Web服务器,它可以嵌入到其它应用程序中,为其提供Web接口。 主要特写: 跨平台,支持 Windows、OS X 和 Linux 支持 CGI, SSL, SSI, Digest (MD5) 认证,WebSocket 和 WebDAV 支持断点续传和 URL 重写 基于 IP 的 ACL,支持 Windows 服务,支持 GET, POST,

  • Mongoose OS 是一个物联网固件开发框架。支持的微控制器包括 ESP32、ESP8266、CC3220、CC3200、STM32F4、STM32L4 与 STM32F7。集成了 Amazon AWS IoT、Microsoft Azure 与 Google IoT Core。 特性: 固件热更新和远程管理,可靠的更新能力,包括故障回滚、远程设备访问基础架构 安全性,内置闪存加密,支持加密芯

  • ts-mongoose Automatically infer TypeScript interfaces from mongoose schemas. Installation npm i ts-mongoose mongoose @types/mongooseyarn add ts-mongoose mongoose @types/mongoose The Problem When using

  • Mongoose PII Plugin TL;DR Store your data like your MongoDB database is getting stolen tomorrow, without sacrificing Mongoose comfort. The slightly longer intro Best practices for data storage dictate