📅 You're Invited: Meet the Socket team at RSAC (April 28 – May 1).RSVP
Socket
Sign inDemoInstall
Socket

mongoose-silo

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mongoose-silo

A wrapper around mongose to build multi-tenant applications.

1.0.2
latest
Source
npm
Version published
Weekly downloads
2
-33.33%
Maintainers
1
Weekly downloads
 
Created
Source

📦🚀 mongoose-silo

A wrapper around mongose to build multi-tenant applications

Build status

npm latest version

mongoose-silo eases the creation of multi-tenant apps by providing a wrapper around mongoose that handles the multi-tenancy for you. It works by siloing your data accross seperate databases, one per each tenant.

Highlights

  • Singleton class Silo, that manages the database context (tenant aware)
  • Swappable tenant model; call it anything eg. Admin, Org, etc.
  • Route middleware to create tenant-aware REST endpoints using tenantify or singlify.
  • Middleware and primitives to handle the tenant context
  • CLI tool to seed fixture data across all tenants

API

  • Following excerpts demonstrate the core functionality of mongose-silo:

// Initialize `mongose-silo` with the main and tenant models
const silo = Silo.initialize('mydb', 'Admin', modelsPath)

// Switch to the database for tenant `tenantId`
silo.switch(tenantId)

// Obtains a connection to the current database 
db = () => silo.getCurrentODM()

// Create a mongo document for the current tenant
orgADashboard = db().model(“Dashboard”).create(…)
  • Use the CLI to seed fixtures into your models
# run seeders for a specific tenant
# `--tenant` here` is optional, if not provided, seeders will be run for all tenants
db:seed --seed <seed-name> --tenant <tenant-name> 

# run all seeders, either for all tenants or for a specific tenant
db:seed:all

Install


# Clone our repo
git clone https://github.com/techoutlooks/mongoose-silo \
  && DOWNLOAD_DIR="$PWD/mongoose-silo"

# Run following from your project dir
npm i --save $DOWNLOAD_DIR

# It is the responsibility of user code to export the Mongo db uri
export MONGO_URL=mongodb://localhost:27017/leeram-erp?authSource=admin

Quick start

  • Initialize mongose-silo, ideally in your models/index.js directory.
// models/index.js

require('mongose-silo')
const silo = Silo.initialize('mydb', 'Admin', modelsPath)

module.exports = {
  silo, 
  db: () => silo.getCurrentODM(),
  tenantify: tenantify(silo),
  singlify: singlify(silo)
}

  • Define your models as usual, but don't register them with mongose.model(name, schema). The Silo.initialize() static factory inside mongose-silo walks your modelsPath directory, compiles your schemas, and registers them with every tenant database, automagically.

const Dashboard = mongoose.model('Dashboard', Schema({
  title: String }));

// THE CHANGE: instead of registering your model yourself, 
// simply expose your schema like so:
module.exports = { name: 'Dashboard', schema: yourSchema }

  • That's all. Now, use your models.

Remember models/schemas were pulled up automatically from the modelsPath directory and compiled, when initializing the library. You need not importing mongoose anymore.

In your controllers, replace code that looks like:

  const mongoose = require('mongoose');
  const Org = mongoose.model('Org');

with:

  const { silo, db, singlify } = require('@/models')
  const Org = db().model('Org');  // way 1
  const Org = db().Org;           // way 2

Full example:


const tenantId = 'orgA'
const { silo, db, singlify } = require('@/models/index')
silo.switch(tenantId)

await db().Dashboard.create({ 
  title: 'Org A - Weekly report' })

App routes

  • Regular route

This is meant for tenant-unaware REST calls; ie., GET with no X-Tenant-Id header, nor silo-tenant-id cookie set on the request. Below example, a trivial usecase, creates an org tenant. It uses the singlify middleware to create a route with multitenancy that:

  • inserts an org document in the main database,
  • registers models declared in the modelsPath directory per each tenant.

app.post('/org', tenantify, async (req, res) => {
  const { name, domain } = req.body

  const tenant = await silo.createTenant(domain)
  silo.switch(tenant.subdomain)

  const org = await db().Org.create({
    name, domain
  })

  res.status(201).json({
    org
  })
})

  • Tenant route

Use the tenantify middleware to switch the database context to the tenant identified in the request:


app.get('/dashboard', tenantify, async (req, res) => {
  const dashboards = await db().Dashboard.findAll()

  res.status(200).json({
    dashboards
  })
})

FAQs

Package last updated on 04 Nov 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts