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

express-mong

v0.10.1

Published

Mongoose wrapper to inject request object into mongoose Query, Document, and Hooks

Downloads

2

Readme

express-mong

Mongoose wrapper to inject request object into mongoose Query, Document, and Hooks

Installation

$ npm install express-mong

Introduction

express-mong is a very thin layer of mongoose 'Model' and 'Query'. It enables to have request object in almost anywhere you access mongoose instances within that request scope, and also provides same interfaces as mongoose 'Model' does including callbacks.

Places you can find request object

You can find request object in:

  • Document

  • Document middleware -- validate -- save -- remove

  • Query middleware -- count -- deleteMany -- deleteOne -- find -- findOne -- findOneAndDelete -- findOneAndRemove -- findOneAndUpdate -- update -- updateOne -- updateMany -- replaceOne

  • Aggregate middleware

  • Methods

  • Statics

  • toObject

  • toJSON

Mongoose Middleware

Usage

const express = require('express');
const Mong = require('express-mong');
const app = express();

app.use(Mong());

const testSchema = new Schema({ name: String, reqPath: String });

testSchema.pre('save', function(next) {
  const req = this.$req; // find request object from $req in document
  this.reqPath = req.path;
  next();
});

testSchema.pre('find', function() {
  const req = this.$req; // find request object from $req in query instance
  //
  // if session user is defined in request, can use it to limit the result
  // const userId = req.user._id;
  // const query = this.getQuery();
  // query.createdBy = userId;
  // this.setQuery(query);
  //
});

mongoose.model('Test', testSchema);

app.get('/test', function(req, res, next) {
  const Test = req.mong.model('Test');

  const test = new Test({ name: 'test1' });
  test.save(function(err, doc) {
    const _req = doc.$req; // find request object from $req in document
    res.send(doc.reqPath) // send '/test' set from save pre-hook
  });
});

Document Decorator

You can set decorators for each mongoose schema and expect it to be run before document(s) been returned.

...

Mong.setDecorator('Test', function() {
  this.name += this.name;
  return this;
});

app.get('/test2', function(req, res, next) {
  Test.findOne({ name: 'test1' }).then(doc => {
    res.send(doc.name); // send 'test1test1' set from decorator
  });
});

You can also set more than one decorators in options when initializing express middleware.

...

app.use(Mong({
  decorators: {
    Test: function() {
      this.name += this.name;
      return this;
    },
    ...
  }
}));

Decorators can be either sync functions or async functions.

Original Document Object

By default, the wrapper injects the original document object into returning documents. The $original is an object converted by 'toObject' method of the original document.

...
app.get('/test3', function(req, res, next) {
  const data = { name: 'test2' };
  Test.findOne({ name: 'test1' }).then(doc => {
    doc.set(data);
    console.log(doc.name); // test2
    console.log(doc.$original.name); // test1

    res.send(doc.$original.name); // send 'test1' set from original document object
  });
});

You can disable it in the options.

...

app.use(Mong({
  keepOriginal: false,
  ...
}));

Audit plugin

express-mong provides one mongoose plugin to audit user and datetime on document's creation and updates. The user document / object must be set in request object as 'req.user'.

const mongAudit = require('express-mong/plugins/audit');
...

const testSchema = new Schema({ name: String, reqPath: String });
testSchema.plugin(mongAudit);
mongoose.model('Test', testSchema);

app.get('/test', function(req, res, next) {
  console.log(req.user); // session user

  const Test = req.mong('Test');

  Test.create({ name: 'test1' }).then(doc => {
    console.log(doc.createdBy); // session user id
    console.log(doc.updatedBy); // session user id
    console.log(doc.createdAt); // created datetime
    console.log(doc.updatedAt); // updated datetime; same as createdAt

    doc.name = 'test2';
    doc.save().then(doc => {
      console.log(doc.updatedBy); // session user id
      console.log(doc.updatedAt); // updated datetime; different from createdAt

      res.send('done');
    });
  });
});

The audit option may vary depends on schemas.

const mongAudit = require('express-mong/plugins/audit');
...

const testSchema = new Schema({ name: String, reqPath: String });
const auditOptions = {
  userSchema = 'User', // default to 'User'
  createdBy = 'createdBy', // default to 'createdBy' and false to disable the field
  updatedBy = 'updatedBy', // default to 'updatedBy' and false to disable the field
  createdAt = 'createdAt', // default to 'createdAt' and false to disable the field
  updatedAt = 'updatedAt', // default to 'updatedAt' and false to disable the field
};

testSchema.plugin(mongAudit, auditOptions);
mongoose.model('Test', testSchema);

Since audit fields are generated by the plugin, you can omit them in the schema.

MIT Licensed