A module for building models and adapters for multiple data sources
JavaScript
Latest commit 7a3ac96 Mar 21, 2016 @Fluidbyte Fluidbyte 2.1.2
Permalink
Failed to load latest commit information.
build
examples
src
test
.codeclimate.yml
.editorconfig
.eslintrc
.gitignore
.jshintrc
.npmignore
LICENSE.txt
README.md
esdoc.json
package.json
wercker.yml

README.md

wercker status Code Climate Test Coverage

Modli

Modli is an NPM module designed to help create unified data modelling, validation and CRUD operations across numerous data sources. It accomplishes this by exposing a model object and an adapter object which are extended upon eachother with the desired adapter for a data source to create a more standard, extensible object.

Installation

npm install modli --save

Getting Started

Below is an example of a basic setup where a model and an adapter are added. Once added they are available to be use'd to create an instance of the object with the methods from the adapter, validation, etc.

In this example, the modli-nedb is utilized (npm install modli-nedb --save).

// Import all the Modli methods
import { model, adapter, use } from 'modli';
// Import the adapter to use
import nedb from 'modli-nedb';

// Create adapter object
adapter.add({
  name: 'testNEDB',
  // Uses the built-in NeDB adapter
  source: nedb,
  // Initiates adapter with following config
  config: {
    inMemoryOnly: true
  }
});

// Add a Model
model.add({
  // Set a name
  name: 'testUser',
  // Set the version
  version: 1,
  // Define the schema
  schema: {
    id: { type: 'number', required: true },
    fname: { type: 'string' },
    lname: { type: 'string' },
    email: { type: 'email', required: true }
  }
});

// Create user object by using the model and adapter
const user = use('testUser', 'testNEDB');

The above example will return the model object with a number of methods for performing data operations. This will always include core CRUD methods:

// Create
user.create({ /*...data...*/ }).then(/*...*/).catch(/*...*/);

// Read
user.read({ /*...query...*/ }).then(/*...*/).catch(/*...*/);

// Update
user.update({ /*...query, data...*/ }).then(/*...*/).catch(/*...*/);

// Delete
user.delete({ /*...query...*/ }).then(/*...*/).catch(/*...*/);

Yes, it's all based on Promises. You're welcome.

Plugins

Modli supports easy addition of custom functionality through plugins. Using the above example, a plugin can be added to extend the Modli instance:

// Create a plugin function
const getSchemas = function () {
  return this.schemas;
}

// Use the `plugin` method to add the plugin
user.plugin(getSchemas);

// Call the plugin
const schemas = user.getSchemas(); // <- would return all schemas in user

Custom Adapters

While the team behind Modli provides a number of adapters, Modli core is also designed to accept a path to a custom adapter:

adapter.use({
  name: 'myCustomAdapter',
  source: 'path/to/myCustomAdapter'
  config: {
    /*...custom config properties...*/
  }
});

To see a functional example of a custom adapter see /examples/custom-adapter

Extending Adapters

Adapters can be esily extended upon. For example, a custom method could be added to the NeDB adapter used in the Getting Started section:

import nedb from 'modli-nedb';

nedb.extend('myCustomMethod', (someVal) => {
  // Just return the value passed
  return someVal;
});

All adapters contain the extend method which becomes part of the created object when a model and adapter are use'd, so the adapter can be extended before initialization with a model, or inline:

// Initial setup
adapter.add({ name: 'myAdapter', /*...*/ });
model.add({ name: 'myModel', /*...*/ });
// Usable object
const myTest = use('myModel', 'myAdapter');

// Extend...
myTest.extend('myCustomMethod', (someVal) => {
  // Just return the value passed
  return someVal;
});

The above would allow you to then call myTest.myCustomMethod('foo') and expect the response to be foo.

Validate Model Data

Validation of model data is done by the adapter when data is being insertered, i.e. create and update procedures. The adapter inherits the model's validate method which utilizes the Obey library to ensure properties are correct.

Validation Error Formatting

By default, the validation method's fail response will return the Obey error object. This can be overridden using the following:

model.customValidationError = (err) => {
  // ... custom formatting here ...
};

For example, if you wanted to just show the "human" error response text:

model.customValidationError = (err) => {
  return err[0].message;
}

The above would return "id" must be a number if the above model was tested with an invalid string id when the expected input was an integer.

Adapters and Validation

When the adapter is extended upon the model to which it is applied it exposes the model's validate method. Adapters can utilize this via the following:

const validationErrors = this.validate(body, version);

The validate method in the above returns errors to the validationErrors constant. If no validation errors are present it simply returns null.

The version paramater is optional and will default to the latest (last added) model if not specificed.

Adapters and Sanitization

The sanitize method is available for creating a cross-adapter compatible method for parsing data after read. The default action of this method is a simple return of the data, this can be easily overwritten on a model:

modelName.sanitize = data => {
  // Perform actions on data...
}

Makefile and Scripts

A Makefile is included for managing build and install tasks. The commands are then referenced in the package.json scripts if that is the preferred task method:

  • all (default) will run all build tasks
  • start will run the main script
  • clean will remove the /node_modules directories
  • build will transpile ES2015 code in /src to /build
  • test will run all spec files in /test/src
  • test-cover will run code coverage on all tests
  • lint will lint all files in /src

Testing

Running make test will run the full test suite.

Test Inidividual File

An individual spec can be run by specifying the FILE. This is convenient when working on an individual adapter.

make test FILE=/some.spec.js

The FILE is relative to the /test directory.

Deploys

For deploying releases, the deploy TAG={VERSION} can be used where VERSION can be:

<newversion> | major | minor | patch | premajor

Both make {COMMAND} and npm run {COMMAND} work for any of the above commands.

License

Modli is licensed under the MIT license. Please see LICENSE.txt for full details.

Credits

Modli was designed and created at TechnologyAdvice.