All Projects → boosterfuels → monogram

boosterfuels / monogram

Licence: Apache-2.0 license
Aspect-oriented layer on top of the MongoDB Node.js driver

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to monogram

ng-observe
Angular reactivity streamlined...
Stars: ✭ 65 (-14.47%)
Mutual labels:  rxjs, observable, streams
Redux Most
Most.js based middleware for Redux. Handle async actions with monadic streams & reactive programming.
Stars: ✭ 137 (+80.26%)
Mutual labels:  rxjs, observable, streams
Marble
Marble.js - functional reactive Node.js framework for building server-side applications, based on TypeScript and RxJS.
Stars: ✭ 1,947 (+2461.84%)
Mutual labels:  rxjs, observable
Awesome Rxjs
Awesome list of RxJS 5
Stars: ✭ 141 (+85.53%)
Mutual labels:  rxjs, observable
NCop
Composite-aspect oriented framework for .NET
Stars: ✭ 30 (-60.53%)
Mutual labels:  aspect-oriented-framework, aspect-oriented-programming
Od Virtualscroll
🚀 Observable-based virtual scroll implementation in Angular
Stars: ✭ 133 (+75%)
Mutual labels:  rxjs, observable
Rxjs Hooks
React hooks for RxJS
Stars: ✭ 1,953 (+2469.74%)
Mutual labels:  rxjs, observable
Rx Sandbox
Marble diagram DSL based test suite for RxJS 6
Stars: ✭ 151 (+98.68%)
Mutual labels:  rxjs, observable
Rx React Container
Use RxJS in React components, via HOC or Hook
Stars: ✭ 105 (+38.16%)
Mutual labels:  rxjs, observable
derivejs
DeriveJS is a reactive ODM - Object Document Mapper - framework, a "wrapper" around a database, that removes all the hassle of data-persistence by handling it transparently in the background, in a DRY manner.
Stars: ✭ 54 (-28.95%)
Mutual labels:  mongoose, odm
rxrest
Reactive rest library
Stars: ✭ 33 (-56.58%)
Mutual labels:  rxjs, observable
React Eva
Effects+View+Actions(React distributed state management solution with rxjs.)
Stars: ✭ 121 (+59.21%)
Mutual labels:  rxjs, observable
Rxios
A RxJS wrapper for axios
Stars: ✭ 119 (+56.58%)
Mutual labels:  rxjs, observable
rxjs-proxify
Turns a Stream of Objects into an Object of Streams
Stars: ✭ 34 (-55.26%)
Mutual labels:  rxjs, observable
Rxjs In Action
Code sample repository
Stars: ✭ 117 (+53.95%)
Mutual labels:  rxjs, streams
Jupyterlab Data Explorer
First class datasets in JupyterLab
Stars: ✭ 146 (+92.11%)
Mutual labels:  rxjs, observable
Angular1 Async Filter
Angular2 async pipe implemented as Angular 1 filter to handle promises & RxJS observables
Stars: ✭ 59 (-22.37%)
Mutual labels:  rxjs, observable
Rxviz
Rx Visualizer - Animated playground for Rx Observables
Stars: ✭ 1,471 (+1835.53%)
Mutual labels:  rxjs, observable
observable-profiler
Tracks new & disposed Observable subscriptions
Stars: ✭ 41 (-46.05%)
Mutual labels:  rxjs, observable
mst-effect
💫 Designed to be used with MobX-State-Tree to create asynchronous actions using RxJS.
Stars: ✭ 19 (-75%)
Mutual labels:  rxjs, observable

monogram

Action-based anti-ODM for MongoDB and Node.js

Read the intro blog post here.

Usage

const { connect } = require('monogram');
const db = await connect('mongodb://localhost:27017/test');

Usage

Actions

From an end developer perspective, monogram behaves just like the MongoDB Node.js driver. The key difference is that monogram converts collection functions into actions under the hood. Actions are an object representation of a function call.

    const Test = db.collection('Test');

    let called = 0;
    Test.pre(action => {
      ++called;
      // An _action_ is an object representation of a function call.
      // It has an `_id` property to uniquely identify it, and
      // some other properties:
      assert.deepEqual(_.omit(action, ['_id']), {
        collection: 'Test', // The name of the collection
        name: 'insertOne', // The name of the function called
        params: [{
          hello: 'world'
        }], // The parameters passed to the function
        chained: [] // Function calls chained onto this one
      });
    });

    await Test.insertOne({ hello: 'world' });

    assert.equal(called, 1);
  

Motivation: Logging

Monogram isn't an ODM/ORM like its uncle mongoose, It's a new abstraction entirely. You can call it an AOM, "action-object mapping". Why is this abstraction better? Consider the problem of logging all database operations to the console in an ODM. In mongoose, this is hard, because there's a lot of different types of middleware. In monogram, this is trivial, because all database operations are represented in a common form, actions, and all actions go through one pipeline.

    const Test = db.collection('Test');

    let called = 0;

    Test.action$.subscribe(action => {
      ++called;
      const params = action.params.
        map(p => util.inspect(p, { depth: 5 })).
        join(', ');
      const msg = `${action.collection}.${action.name}(${params})`

      assert.equal(msg,
        `Test.updateOne({ _id: 1 }, { '$set': { hello: 'world' } })`);
    });

    await Test.updateOne({ _id: 1 }, {
      $set: { hello: 'world' }
    });

    assert.equal(called, 1);
  

Enforcing Internal Best Practices

The purpose of monogram is to allow you to enforce best practices, not to prescribe best practices. Beginners are best served using a tool like mongoose, which has a lot of baked-in best practices to prevent you from shooting yourself in the foot. Monogram is more for advanced users who have established best practices they want to enforce. For example, here's how you would prevent users from calling updateOne() or updateMany() without any update operators, which would overwrite the document.

    const Test = db.collection('Test');

    let called = 0;

    // Will catch `updateOne()`, `updateMany()`, and `findOneAndUpdate()`
    // actions
    Test.pre(/update/i, action => {
      const update = action.params[1] || {};
      const keys = Object.keys(update);
      if (keys.length > 0 && !keys[0].startsWith('$')) {
        throw new Error('Not allowed to overwrite document ' +
          'using `updateOne()`, use `replaceOne() instead`');
      }
    });

    let threw = false;
    try {
      // Normally this would delete all properties on the document
      // other than `_id` and `overwrite`. This is expected behavior,
      // but you might want to disallow it. Monogram gives you a
      // framework to do so.
      await Test.updateOne({ _id: 1 }, { overwrite: 'woops!' });
    } catch (error) {
      threw = true;
      assert.equal(error.message, 'Not allowed to overwrite document ' +
        'using `updateOne()`, use `replaceOne() instead`');
    }

    assert.ok(threw);
  
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].