![Thinodium](https://thinodium.github.io/img/logo.svg)
![Follow on Twitter](https://img.shields.io/twitter/url/http/shields.io.svg?style=social&label=Follow&maxAge=2592000)
A "thin ODM" which is less opinionated and tries to give you query flexibility
whilst still providing helpful document handling.
Features:
- ES6-ready with Promises, no callbacks
- Allows you to handle connections yourself
- Add virtual fields to documents
- Fully pluggable - easy to add support for your DB of choice
- Listen to before and after events on internal asynchronous methods
- Schema validation (sjv).
Read the documentation for more.
Installation
This package requires Node 4 or above
$ npm install thinodium
This package provides the core infrastructure. To actually access a particular
database you will need to additionally install one of the following adapters:
NOTE: Please raise a PR if you want me to add your adapter to the above list.
Basic usage
Let's first create a database connection:
const Thinodium = require('thinodium');
const db = yield Thinodium.connect('rethinkdb', {
db: 'mydb',
});
Thinodium will try to load an NPM module called thinodium-rethinkdb
(which
is our intention in this example). If not
available it will try to load a module called rethinkdb
. Once loaded it will
instantiate a database connection through that module, passing in the second
parameter to connect()
.
If we wished to add a custom adapter but not as an NPM module we could simply
provide its path to connect()
:
const db = yield Thinodium.connect('path/to/custom/adapter', {
db: 'mydb',
});
Models
Once we have our database connection setup we can access models (i.e. tables)
within the database:
const model = yield db.model('User');
let user = yield model.insert({
name: 'john'
});
user.name = 'mark';
yield user.save();
let user2 = yield model.get(user.id);
console.log(user2.name);
Both get()
and insert()
return Thinodium.Document
instances.
These internally call through to the methods prefixed with raw
- methods
which you can also use directly if you do not wish to deal with Document
s.
These are documented in the API docs.
Document customization
Model documents (each representing a row in the table) can be customized. We
can add virtual fields and additional methods:
const model = yield db.model('User', {
docMethods: {
padName: function(str) {
this.name += str;
}
},
docVirtuals: {
fullName: {
get: function() {
return this.name + ' smith';
}
}
}
});
let user = yield model.insert({
name: 'john'
});
console.log(user2.fullName);
user.padName('test');
console.log(user2.fullName);
Note that you can access the parent model for a document using getModel()
:
let user = yield model.insert({
name: 'john'
});
console.log( user.getModel() === model )
Schema validation
Schema validation is performed by simple-nosql-schema, and is used if a schema is provided in the initial model config:
const model = yield db.model('User', {
schema: {
age: {
type: Number,
required: true,
},
}
});
let user1 = yield model.insert({ name: 'john', });
let user2 = yield model.insert({
name: 'john',
age: 23,
});
user2.age = 'test';
yield user2.save();
Note that schema validation is partial. If the insert or update contains a
key that is not mentioned within the schema then that key gets passed through
without any checks. This allows for flexibility - you only need to vaildate
the parts of a model's schema you're interested in.
API
Check out the API docs for information on supported methods.
Creating an Adapter
An adapter has to extend the base Database
and Model
classes and
override the necessary internal methods:
"use strict";
const Thinodium = require('thinodium');
class Database extends Thinodium.Database {
_connect (options) {
return new Promise((resolve, reject) => {
resolve(connection);
});
}
_disconnect (connection) {
return new Promise((resolve, reject) => {
resolve();
});
}
_model (connection, name, config) {
return new Model(connection, name, config);
}
}
class Model extends thinodium.Model {
rawQry() {
}
rawGet (id) {
return new Promise((resolve, reject) => {
resolve(doc);
});
}
rawGetAll (id) {
return new Promise((resolve, reject) => {
resolve(docs);
});
}
rawInsert (attrs) {
return new Promise((resolve, reject) => {
resolve(doc);
});
}
rawUpdate (id, changes, document) {
return new Promise((resolve, reject) => {
resolve();
});
}
rawRemove (id) {
return new Promise((resolve, reject) => {
resolve();
});
}
}
module.exports = Database;
Building
To run the tests:
$ npm install
$ npm test
Contributing
Contributions are welcome! Please see CONTRIBUTING.md.
License
MIT - see LICENSE.md