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

mongoose-patcher

v0.3.0

Published

A utility for applying RFC6902 JSONPatch operations to mongoose models

Downloads

1,063

Readme

mongoose-json-patch

A utility for applying RFC6902 JSONPatch operations to mongoose models.

This library supports deep autopopulation of related models. Patch operations will be queued and applied to all populated models.

Additionally, rules can be applied to the patch for authorization checks and validation. The rules engine is json-patch-rules.

Installation

npm install --save mongoose-patcher

Usage

As a mongoose plugin

const json_patch_plugin = require('mongoose-patcher');
const options = {
    autosave: true, //should the model be automatically saved when the patch is applied?
    middleware: [...] //see middelware below
    rules: [...], //JSON Patch Rules
    rules_mode: 'whitelist', //how should rules be applied, as a blacklist or whitelist? more info below

};
SomeModel.plugin(json_patch_plugin, options); //options can be applied at the schema level, or when the patch is applied

let model_instance = await SomeModel.findOne({...});

await model_instance.jsonPatch(patch); //patches are applied asyncronously
//model_instance will now have the patch applied

Options can also be applied at the time of patching, or when the patch is applied. This can be useful for cases where rules may differ based on the authenticated user, for example:

let options;
if(req.user.role='admin')
    options = {
        rules: [], //allow admin to do everything
        rules_mode: 'blacklist'
    }
if(req.user.role='restricted')
    options = {
        rules: [
            {path: '/something/limited', op: 'replace'}
        ],
        rules_mode: 'whitelist'
    }

model_instance.jsonPatch(patch, options);

rules_mode

This controls how rules will be applied, in either 'blacklist' or 'whitelist' mode.

In 'blacklist' mode, all operations in the patch will be applied, except those that meet the rules critera.

In 'whitelist' mode, no operations will be applied unless they match the rules criteria.

For example, if you have a simple object like a movie, perhaps all of the fields on the object should be modifiable via json patch, except for the id, and the reference to the producer. This would be a good use for a blacklist:

[
    {path: '/id'},
    {path: '/publisher'}
]

Alternately, in the case of a User object, perhaps there are only a small number of paths that should be allowed to be modified - in this case, all paths will be rejected except for those explicitly allowed:

[
    {path: '/password', op: 'replace', value: '/...some regex.../'},
    {path: '/email', op: 'replace'}
    ...
]

For more information on defining rules see: json-patch-rules.

middleware

In some cases, a value should be changed or manipulated before being applied to a model, or even removed completely.

To handle these cases, middleware can be defined and passed into the options. This allows preprocessing of patch items, or the addition of 'virtual' properties on a model.

Middlware will be passed 4 params: document: the doc being patched item: the item in the patch set that matches the middleware rule next: callback function to continue matches (new in 0.2.14): the regex matches from the path match. This allows you to easily grab named capture groups from the regular expression in the path. This is useful for getting things like the index of an operation {op: 'remove', path: '^/collection/(?<index>\d)$' matches would contain the results of new RegEx(path).exec(item.path) - matches[0].groups.index would have the collection index.

let options = {
    ...
    middleware: [
        {op: 'replace', path: '/password', handler: async (document, item, next, matches) => {
            item.value = await calculateHash(item.value);
            await next(item);
        }}
    ]
    ...
}

A middleware funtion will be passed the mongoose document, the current patch item, and the next operation to perform, which is the utility operation from the patcher instance.

Currently, only the first matching middleware function will be applied, though this may change in the future if there's a need.

If you do not want the model to be modified, just return without calling next();