Waveorb database adapter specification
This repository defines the Waveorb database adapter specification. It contains tests for writing adapters that are compatible with Waveorb generated actions. The idea is that you should be able to use the same code with different backends when writing your Waveorb app.
The API is based on the MongoDB API but not necessarily 100% compatible.
At the moment these adapters exist:
- RunDB - based on NeDB
- MongoWave - based on MongoDB
- WaveDB - based on LevelDB
- ConfigDB - human readable YAML DB for development
API Interface
The adaptor should at least include these functions and properties:
- connection - function that returns a usable connection to the database
- create - creates a new document and returns its id, takes a values object as parameter.
- update - updates a document, takes query and values objects as parameters, returns the number of updated documents (updates multiple)
- delete - deletes a document, takes a query parameter and returns the number of deleted documents (deletes multiple)
- find - finds documents, takes a query parameter, returns an array of matching documents
- get - get a single document, takes a query parameter, returns an object with first matching document or null
- count - same options as find, but returns the number of matching documents
The functions can be async functions or regular functions. The connection
function is usually used as a plugin, the rest of the database functions are used in corresponding Waveorb actions.
The id field in this specification should just be id
and not _id
. References to other collections and separators in general shuld be using an underscore and be lower case like in project_id
and created_at
.
Usage
Say you have the following action in your application:
// in /app/actions/project/find.js
module.exports = {
main: async function($) {
const { query = {}, fields = {}, sort = {}, skip = 0, limit = 0 } = $.params
return await $.app.db('project').find(query, { fields, sort, skip, limit })
}
}
Then you can do this in your db plugin to use different adaptors for development and production without changing your server code:
// in /app/plugins/db.js
const db = process.env.NODE_ENV == 'production'
? require('configdb')
: require('mongowave')
module.exports = async function(app) {
app.db = process.env.NODE_ENV == 'production'
? await db(app.config.db)
: db
}
This will use configdb
in development and mongowave
in production.
Specification
This example uses MongoWave as an example. If you want to write your own adaptor, clone this repository and use the tests, but change the content of the index.js
file.
You can actually run the tests out of the box to get you started:
npm install
npm run tests
Connect to database
const connection = require('mongowave')
const db = await connection()
Create document
// Returns the created id: { id: '507f191e810c19729de860ea' }
// Takes only 1 argument: values
const result = await db('project').create({ name: 'hello' })
Create multiple documents
// Returns the the created count and the created ids:
// { n: 2, ids: ['507f191e810c19729de860ea', '607f191e810c19729de860eb'] }
// Takes only 1 argument: values, must be array of objects
const result = await db('project').create([{ name: 'hello' }, { name: 'bye' }])
Update document (updates multiple if query matches)
// Returns the number of updated documents: { n: 1 }
// Takes 2 arguments: query, values
const result = await db('project').update({ id: '507f191e810c19729de860ea' }, { name: 'bye' })
Delete document (deletes multiple if query matches)
// Returns the number of deleted documents: { n: 1 }
// Takes 1 argument: query
const result = await db('project').delete({ id: '507f191e810c19729de860ea' })
Find document
// Returns an array of matching documents
// Takes 2 arguments: query, options
// Find all
const result = await db('project').find()
// Find all with name 'bye'
const result = await db('project').find({ name: 'bye' })
// Find with sorting on 'name' field descending, use 1 for ascending
const result = await db('project').find({}, { sort: { name: -1 } })
// Find only 2
const result = await db('project').find({}, { limit: 2 })
// Find but skip 2
const result = await db('project').find({}, { skip: 2 })
// Find all but don't include the 'name' field in the result
const result = await db('project').find({}, { fields: { name: false } })
// Find all with 'level' field greater than 5
const result = await db('project').find({ level: { $gt: 5 }})
All of the mongodb query operators should work.
Get document
// Returns the first matching document
// Takes 2 arguments: query, options
const result = await db('project').get({ name: 'bye' })
Count documents
// Returns the count of the matching query
// Takes 2 arguments: query, options
const result = await db('project').count({ name: 'bye' })
The database client
db.client
MIT Licensed. Enjoy!