DADI API wrapper
A high-level library for interacting with DADI API
Overview
DADI API is a high performance RESTful API layer designed in support of API-first development and the principle of COPE.
This library provides a high-level abstraction of the REST architecture style, exposing a set of chainable methods that allow developers to compose complex read and write operations using a simplistic and natural syntax.
Getting started
-
Install the @dadi/api-wrapper
module:
npm install @dadi/api-wrapper --save
-
Add the library and configure the API settings:
var DadiAPI = require('@dadi/api-wrapper')
var api = new DadiAPI({
uri: 'http://api.example.com',
port: 80,
credentials: {
clientId: 'johndoe',
secret: 'f00b4r'
},
version: 'vjoin',
database: 'testdb'
})
-
Make a query:
api.in('users')
.whereFieldContains('name', 'john')
.whereFieldIsGreaterThan('age', 18)
.find()
.then(function (response) {
})
Methods
Each query consists of a series of chained methods to form the request, always terminated by an operation method. There are 5 terminating operations that return a Promise with the result of one or more requests to the database: create()
, delete()
, find()
, apply()
and update()
.
These operations (with the exception of create()
) can make use of a series of filtering methods to create the desired subset of documents to operate on.
Operations
.apply(callback)
Updates a list of documents with the result of individually applying callback
to them.
api.in('users')
.whereFieldExists('gender')
.apply(function (document) {
document.name = (document.gender === 'male') ? ('Mr ' + document.name) : ('Mrs ' + document.name)
return document
})
.create()
Creates a document.
api.in('users')
.create({
name: 'John Doe',
age: 45,
address: '123 Fake St'
})
.then(function (doc) {
console.log('New document:', doc)
})
.catch(function (err) {
console.log('! Error:', err)
})
.delete()
Deletes one or more documents.
api.in('users')
.whereFieldDoesNotExist('name')
.delete()
.find(options)
Returns a list of documents.
api.in('users')
.whereFieldIsGreaterThan('age', 21)
.useFields(['name', 'age'])
.find()
options
is one of the following:
extractResults
(Boolean): Selects whether just the results array should be returned, rather than the entire API response.extractMetadata
(Boolean): Selects whether just the metadata object should be returned, rather than the entire API response.
.getCollections()
Gets the list of collections for the API.
api.getCollections()
Output:
[
{
"version": "1.0",
"database": "radio",
"name": "Articles",
"slug": "articles",
"path": "/1.0/radio/articles"
},
{
"version": "1.0",
"database": "radio",
"name": "Authors",
"slug": "authors",
"path": "/1.0/radio/authors"
}
]
.getConfig()
Gets the config for a collection or for the API.
api.in('users')
.getConfig()
api.getConfig()
.getStats()
Gets collection stats.
api.in('users')
.getStats()
.getStatus()
Gets the the API status.
api.getStatus()
Output:
{
"method": "GET",
"uri": {
"href": "http://api.example.com:80/api/status",
"hostname": "api.example.com",
"path": "/api/status",
"port": "80",
"protocol": "http:"
}
}
.setConfig()
Sets the config for a collection or for the API.
var collectionConfig = {}
api.in('users')
.setConfig(collectionConfig)
var apiConfig = {}
api.setConfig(apiConfig)
.update(update)
Updates a list of documents.
api.in('users')
.whereFieldIsLessThan('age', 18)
.update({
adult: false
})
Filters
Filtering methods are used to create a subset of documents that will be affected by subsequent operation methods.
.goToPage(page)
Defines the page of documents to be used.
api.goToPage(3)
.limitTo(limit)
Defines a maximum number of documents to be retrieved.
api.limitTo(10)
.sortBy(field, order)
Selects a field to sort on and the sort direction. Order defaults to ascending (asc
).
api.sortBy('age', 'desc')
.useFields(fields)
Selects the fields to be returned in the response. Accepts array format.
api.useFields(['name', 'age'])
.where(query)
Filters documents using a MongoDB query object or a Aggregation Pipeline array. The methods above are ultimately just syntatic sugar for where()
. This method can be used for complex queries that require operations not implemented by any other method.
api.where({name: 'John Doe'})
.whereFieldBeginsWith(field, text)
Filters documents where field
begins with text
.
api.whereFieldBeginsWith('name', 'john')
.whereFieldContains(field, text)
Filters documents where field
contains text
.
api.whereFieldContains('name', 'john')
.whereFieldDoesNotContain(field, text)
Filters documents field
does not contain text
.
api.whereFieldDoesNotContain('name', 'john')
.whereFieldEndsWith(field, text)
Filters documents where field starts with text
.
api.whereFieldEndsWith('name', 'john')
.whereFieldExists(field)
Filters documents that contain a field.
api.whereFieldExists('name')
.whereFieldDoesNotExist(field)
Filters documents that do not contain a field.
api.whereFieldDoesNotExist('address')
.whereFieldIsEqualTo(field, value)
Filters documents where field
is equal to value
.
api.whereFieldIsEqualTo('age', 53)
.whereFieldIsGreaterThan(field, value)
Filters documents where field
is greater than value
.
api.whereFieldIsGreaterThan('age', 18)
.whereFieldIsGreaterThanOrEqualTo(field, value)
Filters documents where field
is greater than or equal to value
.
api.whereFieldIsGreaterThanOrEqualTo('age', 19)
.whereFieldIsLessThan(field, value)
Filters documents where field
is less than value
.
api.whereFieldIsLessThan('age', 65)
.whereFieldIsLessThanOrEqualTo(field, value)
Filters documents where field
is less than or equal to value
.
api.whereFieldIsLessThanOrEqualTo('age', 64)
.whereFieldIsOneOf(field, matches)
Filters documents where the value of field
is one of the elements of matches
.
api.whereFieldIsOneOf('name', ['John', 'Jack', 'Peter'])
.whereFieldIsNotEqualTo(field, value)
Filters documents where field
is not equal to value
.
api.whereFieldIsEqualTo('age', 53)
.whereFieldIsNotOneOf(field, matches)
Filters documents where the value of field
is not one of the elements of matches
.
api.whereFieldIsNotOneOf('name', ['Mark', 'Nathan', 'David'])
.withComposition(value)
Defines whether nested documents should be resolved using composition. The default is to let API decide based on the queried collection's settings.
api.withComposition()
api.withComposition(true)
api.withComposition(false)
Other methods
.fromEndpoint(endpoint)
Selects a custom endpoint to use. Please note that unlike collections, custom endpoints do not have a standardised syntax, so it is up to the authors to make sure the endpoint complies with standard DADI API formats, or they will not function as expected.
api.fromEndpoint('custom-endpoint')
.in(collection)
Selects the collection to use.
api.in('users')
.useDatabase(database)
Selects the database to use. Overrides any database defined in the initialisation options, and is reset when called without arguments.
api.useDatabase('testdb')
.useVersion(version)
Selects the version to use. Overrides any version defined in the initialisation options, and is reset when called without arguments.
api.useVersion('1.0')
Debug mode
With debug mode, you'll be able to see exactly how the requests made to API look like. This functionality is enabled by setting a debug
property in the config:
var DadiAPI = require('@dadi/api-wrapper')
var api = new DadiAPI({
uri: 'http://api.example.com',
port: 80,
credentials: {
clientId: 'johndoe',
secret: 'f00b4r'
},
version: 'vjoin',
database: 'testdb',
debug: true
})
[@dadi/api-wrapper] Querying URI: http://api.example.com:80/vjoin/testdb/articles?count=0