1.0.1 • Published 6 months ago

mongoose-get-models v1.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

mongoose-get-models

An easy way to manage mongoose models across packages.

What?

This package export a modelFactory<T>(schemas) function that returns a getModels(mongoose) => YourModels function that allows you to get all of your models linked to a given mongoose instance / connection. This is convenient when you have a dependency that also uses your mongoose models where you want/need to share a connection and avoid complex and annoying model definition and connection management errors.

Why?

Before writing this, every single one of our projects / services had to redefine every single one of our models. Moreover, when we tried to create a cache package that interfaced with both the db and redis, we started to get OverwriteModelErrors and issues managing which mongoose connection we were using. This package makes it easy to to do both while maintaining type safety

Basic Usage

import mongoose from 'mongoose';
import { modelFactory } from 'mongoose-get-models';
import { UserSchema, type IUser } from './user'

// Create your factory
const getModels = modelFactory<{ User: IUser }>({
  User: UserSchema
});

// Get models
const { User } = getModels(mongoose);

Useful pattern

Imagine the scenario where you have three packages, mongoose-schemas, app and a utils package that app imports.

In your schemas package:

// index.ts
import mongoose from 'mongoose';
import { modelFactory, type Models, type Mongoose } from 'mongoose-get-models';
import { UserSchema, type IUser } from './user'

type MyTypes = {
  User: IUser
}

type MyModels = Models<MyTypes>
// Create your factory
const getModelsWithConnection: (mongoose: Mongoose) => MyModels = modelFactory<MyTypes>({
  User: UserSchema
});

let mongooseInstance: Mongoose | null = null;

export function setMongooseInstance(mongoose: Mongoose) {
  mongooseInstance = mongoose;
}

export function getModels(): MyModels {
  if (!mongooseInstance) throw new Error('Mongoose not initialized');
  return getModelsWithConnection(mongooseInstance);
}

export function getModel<T extends keyof MyModels>(name: T): MyModels[T] {
  return getModels()[name]
}

In your app:

// app.ts
import mongoose from 'mongoose';
import { setMongooseInstance, getModels, getModel } from '@your-org/mongoose-schemas';
import { initialize } from '@your-org/utils'

setMongooseInstance(mongoose);
// Can call getModels any time after initialization
const { User } = getModels()
// or
const User = getModel('User')

// utils doesn't use the same instance of schemas, so we have to initialize that too
// in the utils package, we can't call getModels() on the top level since it is not
// possible to set the mongoose instance before initializing, so it's best to call
// getModel/getModels at runtime
initialize(mongoose)

// Can initialize before or after
mongoose.connect('mongodb://localhost:27017/myapp');

// anywhere else
import { getModels } from './models';
function getUser(id) {
  return getModel('User').findById(id)
}

In utils:

import { setMongooseInstance, Mongoose } from '@your-org/mongoose-schemas';
export function initialize(mongooseInstance: Mongoose): void {
  setMongooseInstance(mongooseInstance)
}

// anywhere else
import { getModels } from '@your-org/mongoose-schemas';
const { User } = getModels();

License

MIT

1.0.1

6 months ago

1.0.0

6 months ago