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

@rlalexander31/mongoose-sdl

v0.0.7

Published

Codegen util to generate TS definitions and Mongoose schemas from a custom SDL format

Downloads

344

Readme

Mongoose SDL

Codegen util for generating Mongoose TS types and Schemas from a custom SDL format similar to GraphQL - MGSDL.

Turn this -

enum UserStatus {
  Pending
  Active
  Inactive
}

model User {
  email: String! @index @unique
  name: String
  status: UserStatus!
}

model Project {
  creator: User! @index
  details: ProjectDetails!
}

schema ProjectDetails {
  name: String!
  alternateNames: [String!]!
  number: Number
}

Into this -

import { Types, Document } from 'mongoose';

export enum UserStatus {
  Pending = 'Pending',
  Active = 'Active',
  Inactive = 'Inactive',
}

export interface UserDocument extends Document {
  id: string;
  createdAt: Date;
  updatedAt: Date;
  email: string;
  name: string | null | undefined;
  status: UserStatus;
}

export interface ProjectDocument extends Document {
  id: string;
  createdAt: Date;
  updatedAt: Date;
  creator: Types.ObjectId;
  details: ProjectDetailsSchemaDocument;
}

export interface ProjectDetailsSchemaDocument extends Document {
  id: string;
  createdAt: Date;
  updatedAt: Date;
  name: string;
  alternateNames: string[];
  number: number | null | undefined;
}

import { Schema, model } from 'mongoose';

const ProjectDetailsSchema = new Schema<ProjectDetailsSchemaDocument>({
  name: { required: true, type: String },
  alternateNames: { required: true, type: [{ type: String, required: true }] },
  number: { type: Number },
});

const UserSchema = new Schema<UserDocument>({
  email: { required: true, index: true, unique: true, type: String },
  name: { type: String },
  status: { required: true, type: String, enum: UserStatus },
});

export const UserModel = model<UserDocument>('User', UserSchema);

const ProjectSchema = new Schema<ProjectDocument>(
  {
    creator: { required: true, index: true, type: Schema.Types.ObjectId, ref: 'User' },
    details: { required: true, type: ProjectDetailsSchema },
  },
  { timestamps: true }
);

export const ProjectModel = model<ProjectDocument>('Project', ProjectSchema);

By installing this package and adding a script to your project's package.json

{
  "scripts": {
    "generate-mongoose-schemas": "mongoose-sdl --config mgsdl.json"
  }
}

Data modeling primitives

There are a few top-level keywords:

  • model - a Mongoose model plus schema definition
  • schema- a standalone Mongoose schema that can be embedded into another schema or a model
  • enum - a TS enum
  • union - a union of several models for the purpose of supporting dynamic refs to varying kinds of models
  • external - link to a custom type in your own code so you can reference it in a virtual field definition in the SDL. Requires specifying the import path in the config file.

There are a few built-in data types for fields. ! can be appended to indicate required / non-nullable.

  • Number
  • Boolean
  • String
  • Date
  • Arrays use GQL syntax - e.g. [T] or [T!] where T is any built-in type or custom type (no nesting arrays/maps)
  • Maps use a custom syntax - e.g. Map<T> or Map<T!> where T is any built-in type or custom type (no nesting arrays/maps)

Models

Models can be referenced directly by their model name. This will create an ObjectId with a hardcoded ref to the model name.

If your field can point to multiple kinds of models dynamically, create a union of those models and reference that in your field definition. This will create an ObjectId and require you specify a custom ref function when calling the auto-generated initializer function.

ObjectId can be used directly when the type of the referenced model is unknown.

Schemas

Schemas can be referenced directly by their schema name. A reference to the schema instance will be directly embedded in the parent schema or model. See below section on Schemas for more detais.

  • Recursive schema definitions are supported. The schema is emitted without recursive fields first, then the recursive fields are patched on one at a time via schema.add()
  • Cyclical references across schemas are not supported.
  • "Nested paths" where the schema contents are directly inlined instead of referenced by instance are not supported, due to confusing Mongoose runtime behavior that is difficult to type safely and usefully.

Schemas will be emitted into the generated code according to a topological sort of their dependencies.

Directives

Directives customize generation behavior on fields:

  • @index - Pass-thru to Mongoose schema config
  • @unique - Pass-thru to Mongoose schema config
  • @immutable - Pass-thru to Mongoose schema config
  • @virtual - Indicates the field will be virtual. Allows for using external types. Requires specifying an implementation of the virtual field when calling the auto-generated initializer function.
  • @validate - Indicates the field will have a custom validator added on. Requires specifying the validator implementation for the field when calling the auto-generated initializer function.