Giter Club home page Giter Club logo

node-mongo's Introduction

This repository is no longer maintained. Check Ship.

Node Mongo

npm version

Node Mongo is reactive extension to MongoDB API.

Features

  • ๏ธ๏ธReactive. Fires events as document stored, updated or deleted from database
  • Paging. Implements high level paging API
  • Schema validation. Validates your data before save

Installation

npm i @paralect/node-mongo

Documentation

Migrate from v2 to v3

  1. Methods updateOne and updateMany were removed. You should use update to perform update of single document, matched by a query. There is no replacement for updateMany, normally you should just perform multiple individual updates.
  2. service.count() renamed into service.countDocuments to match MongoDB driver.
  3. Use service.atomic.updateMany instead service.atomic.update to match MongoDB.
  4. service.aggregate() now returns cursor instead of list of documents. You can add toArray()
  5. Service accepts schema object instead of validateSchema method.

Connect

Usually, you need to define a file called database is does two things:

  1. Creates database instance and connects to the database
  2. Exposed factory method createService to create different services to work with MongoDB.
import config from 'config';
import { Database, Service, ServiceOptions } from '@paralect/node-mongo';

const connectionString = 'mongodb://localhost:27017';
const dbName = 'home-db';
const database = new Database(connectionString, dbName);
database.connect();

// Extended service can be used here.
function createService<T>(collectionName: string, options: ServiceOptions = {}) {
  return new Service<T>(collectionName, database, options);
}

export default {
  database,
  createService,
};

See how to add additional functionality to base serivce

Schema validation

const Joi = require('Joi');

const userSchema = Joi.object({
  _id: Joi.string(),
  createdOn: Joi.date(),
  updatedOn: Joi.date(),
  deletedOn: Joi.date(),
  name: Joi.string(),
  status: Joi.string().valid('active', 'inactive'),
});

// Pass schema object to enable schema validation
const userService = db.createService('users', { schema: userSchema });

Extend

The whole idea is to import service and extend it with custom methods:

import { Service } from '@paralect/node-mongo';

class CustomService<T> extends Service<T> {
  createOrUpdate = async (query: any, updateCallback: (item?: T) => Partial<T>) => {
    const docExists = await this.exists(query);
    if (!docExists) {
      const newDoc = updateCallback();
      return this.create(newDoc);
    }

    return this.update(query, doc => {
      return updateCallback(doc);
    });
  };
}

export default CustomService;

Query data

// find one document
const user = await userService.findOne({ name: 'Bob' });

// find many documents with pagination
const {results, pagesCount, count } = await userService.find(
  { name: 'Bob' },
  { page: 1, perPage: 30 },
);

Create or update data (and publish CUD events)

The key difference of the @paralect/node-mongo sdk is that every create, update or remove operation peforms an udpate and also publeshes CUD event. Events are used to easily update denormalized data and also to implement complex business logic without tight coupling of different entities.

  • Reactive updates (every update publishes event)
    • create โ€” create one or many documents, publishes document.created event
    • update โ€” update one document, publishes document.updated event
    • remove โ€” remove document, publishes document.removed
    • removeSoft โ€” set deleteOn field and publish document.removed event

Atomic udpates do not publish events and usually used to update denormalized data. Most the time you should be using reactive updates.

  • Atomic updates (events are not published)
    • atomic.deleteMany
    • atomic.insertMany
    • atomic.updateMany
    • findOneAndUpdate

API Reference V2.

create

const users = await userService.create([
  { name: 'Alex' },
  { name: 'Bob' },
]);

update

Update using callback function:

const updatedUser = await userService.update({ _id: '1' }, (doc) => {
  doc.name = 'Alex';
});

Update by returning fields you need to update:

const updatedUser = await userService.update({ _id: '1' }, () => ({ name: 'Alex' }));

remove

const removedUser = await userService.remove({ _id: '1' });

removeSoft

const removedUser = await userService.removeSoft({ _id: '1' });

Event handlers

SDK support two kind of events:

  • in memory events (published by default), can be lost on service failure, work out of the box.
  • transactional events guarantee that every database write will also produce an event. Transactional events can be enabled by setting { outbox: true } when creating service. Transactional events require additonal infrastructure components.

To subscribe to the in memory events you can just do following:

import { inMemoryEventBus, InMemoryEvent } from '@paralect/node-mongo';

type UserCreatedType = InMemoryEvent<any>;
type UserUpdatedType = InMemoryEvent<any>;
type UserRemovedType = InMemoryEvent<any>;

inMemoryEventBus.on('user.created', (doc: UserCreatedType) => {});

inMemoryEventBus.on('user.updated', (doc: UserUpdatedType) => {});

inMemoryEventBus.on('user.removed', (doc: UserRemovedType) => {});

Change Log

This project adheres to Semantic Versioning.

Every release is documented on the Github Releases page.

node-mongo's People

Contributors

allcontributors[bot] avatar alldayalone avatar anorsich avatar dzinrai avatar ezhivitsa avatar iharkrasnik avatar kuhart avatar nesterenkonikita avatar oigen43 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-mongo's Issues

Improve documentation

Current documentation is a little bit tricky to read and understand

The possible improvements that can be made:

  • Divide on sections
  • Describe API methods separately
  • Explain how it is based on monk

[Discussion] Using ship vs node-mongo

I'm currently looking for a package similar to meteor's oplog and I came across node-mongo. Since this is not maintained anymore I'm wondering what's the benefit of using node-mongo vs ship? I'm currently creating a node application that leverage the CUD operations.

Execute find and count queries in parallel for paginated requests

When find request is executed with pagination actual find and count requests are executed sequentially.

const results = await this._collection.find(query, options);
if (!hasPaging) {
return {
results,
};
}
const countOptions = {};
if (options.session) countOptions.session = options.session;
const count = await this._collection.count(query, countOptions);

Instead this could be performed in parallel noticeably improving performance for long-running DB requests

Watching changes

Hi all,

I am wondering would this allow me to watch for for a changes (Event Handlers section) and trigger something?
I've setup simple query which works just fine, but event has never been triggered when data in DB is changed

userService.on('updated', ({ doc, prevDoc }) => { console.log("Here we go, change!")});

Would this supposed to work if I update any record?

Thanks!

Unable to pass collection options

 db.createService = (collectionName, options = {}) => {
    const collection = db.get(collectionName, { castIds: false });

    return new MongoService(collection, options);
  };

I need to set default collation for the collection but there is no way to pass options to the monk method.

Feature: Soft Remove

  1. Add option { soft: bool } (default false) to the createService options which opts on the feature
  2. On remove document makes update { deletedOn: new Date() }
  3. Add function restore which makes update { $unset: { deletedOn: "" } }
  4. Add option { soft: bool } (default true) to all query methods which adds { deletedOn: { $exists: false } } to the query

To discuss:

  • Emit event restored and adjust event removed

Security issue with required lodash version

While using this package, npm throws a security warning for lodash:

 === npm audit security report ===                        
                                                                                
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                                Manual Review                                 โ”‚
โ”‚            Some vulnerabilities require your attention to resolve            โ”‚
โ”‚                                                                              โ”‚
โ”‚         Visit https://go.npm.me/audit-guide for additional guidance          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ High          โ”‚ Prototype Pollution                                          โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Package       โ”‚ lodash                                                       โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Patched in    โ”‚ >=4.17.12                                                    โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Dependency of โ”‚ @paralect/node-mongo                                         โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Path          โ”‚ @paralect/node-mongo > lodash                                โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ More info     โ”‚ https://npmjs.com/advisories/1065                            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
found 1 high severity vulnerability in 12390 scanned packages
  1 vulnerability requires manual review. See the full report for details.

This can be fixed by increasing the required lodash version from 4.17.11 to ^4.17.12

Multiple MongoDBService instances?

Hey,

I'm trying to create multiple instances of MongoDBService (each under an instance to write / read from a different collection set). Right now I'm unable to get this to work. Does this framework support this use case? Thanks.

No options are passed to the find one method

Maybe I'm missing something, but the options are not passed further in the findOne

node-mongo/src/service.ts

Lines 163 to 173 in 3274b65

findOne = async (
query: Filter<T> = { },
options: GeneralRequestOptions = {},
): Promise<T | null> => {
const collection = await this.getCollection();
query = this.addQueryDefaults(query, options);
this.validateQuery(query, options);
return collection.findOne<T>(query);
};

Feature: Scopes

Add a convenient option to append a scoping query.

For example, all entities in the DB (users, groups, templates, tasks) belong to one and only one space. In the schema, they all have spaceId field. To restrict users from space A to see the data from space B we need to add { spaceId: ctx.state.user.spaceId } to the most queries.

Obviously there should be a common mechanism for this to avoid data leaks and incorrect behavior.

Posssible solution:

const userService = db.createService('users', userSchema, { scope: 'spaceId' });
...
ctx.state.user = await userService.findUserByToken(accessToken);
userService.setScope({ spaceId: ctx.state.user.spaceId });
...
userService.findOne({ email: data.email });
[internally] => userService.findOne({ email: data.email, spaceId: ctx.state.user.spaceId });

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.