data-point-express
v5.0.6-alpha.0
Published
Create DataPoint Express middleware
Downloads
36
Readme
DataPoint Express
Create DataPoint service with Express middleware support
Requirements
- Node 8 LTS (or higher)
- Redis (Optional for development)
- Peer dependencies: data-point, Express
Install
NOTE: Express and DataPoint are peer dependencies
npm install --save express data-point data-point-express
Quick start
A simplistic example of creating a DataPoint Express service.
const express = require('express')
const Service = require('data-point-express')
const app = new express()
Service.create({
// add DataPoint entities
entities: {
'entry:hello-world': () => 'Hello World!!'
}
})
.then((service) => {
// expose DataPoint inspector
app.use(
'/api/inspect',
service.inspector()
)
// maps route: /api/hello-world to
// entityId: entry:hello-world
app.get(
'/api/hello-world',
service.mapTo('entry:hello-world')
)
// start Express server
app.listen(3000, (err) => {
console.log('DataPoint service ready!')
})
})
The code above should expose two paths:
- http://localhost:3000/api/inspect - DataPoint entity inspector
- http://localhost:3000/api/hello-world - should return the string
Hello World!!
Create a DataPoint Service Object
This method returns a Promise
that resolves to a DataPoint Service Object.
Service.create({
entities: Object,
entityTypes: Object,
cache: {
localTTL: Number,
redis: Object,
isRequired: true,
prefix: String
}
}):Promise<Object>
The following table describes the properties of the options
argument:
| option | type | required | description |
|:---|:---|:---|:---|
| entities | Object
| yes | DataPoint entities Object. |
| entityTypes | Object
| optional | Create your DataPoint custom entity types. |
| cache.localTTL | Number
| optional | Value in Milliseconds of in memory TTL, by default it's set to 2000
(2 seconds) |
| cache.redis | Object
| optional | Value passed to the ioredis constructor |
| cache.isRequired | Boolean
| optional | Defaults to false
. If true the service will throw an error when getting created. |
| cache.prefix | String
| optional | Defaults to os.hostname(). In production you may be using multiple node instances and might want to instead share the prefix. |
Example
Creates a new DataPoint Service:
const express = require('express')
const Service = require('data-point-express')
const app = new express()
Service.create({
// add DataPoint entities
entities: {
'entry:HelloWorld': (input, acc) => 'Hello World!!',
'entry:Greet': (input, acc) => `Hello ${acc.locals.params.person}!!`
}
})
.then(service => {
// create Express routes
app.get('/api/hello-world', service.mapTo('entry:HelloWorld'))
app.get('/api/greet/:person', service.mapTo('entry:Greet'))
app.listen(3000, (err) => {
if(err) {
throw err
}
console.info('DataPoint service ready!')
})
})
.catch(error => {
console.info('Failed to Create Service')
console.error(error)
process.exit(1)
})
Service: http://localhost:3000/api/hello-world
Returns:
Hello World!!
Service: http://localhost:3000/api/greet/darek
Returns:
Hello darek!!
DataPoint Service Object
When Service.create
is resolved it returns a service
instance that exposes the following api:
- service.mapTo() - creates an express middleware that gets mapped to a DataPoint Entity id.
- service.router() - creates an Express.Router with DataPoint aware routes.
- service.inspector() - exposes a DataPoint Entity inspector.
service.mapTo()
Maps a DataPoint entityId to a middleware method. This method returns an Express Middleware function.
service.mapTo(entityId:String):Function
arguments:
| argument | type | description |
|:---|:---|:---|
| entityId | String
| DataPoint entity Id. |
Example:
Maps path '/api/hello-world'
to entityId 'entry:HelloWorld'
app.get('/api/hello-world', service.mapTo('entry:HelloWorld'))
service.router()
Create DataPoint aware routes. This method returns a Express.Router Object.
service.router(routes:Object):Router
arguments:
| argument | type | description |
|:---|:---|:---|
| routes | Object
| Routes Object |
Example:
Create a set of routes under the path '/api'
. Notice how you can set the http method on each route as well as the priority.
app.use('/api', service.router({
helloWorld: {
priority: 100,
path: '/hello-world',
method: 'GET',
middleware: 'reducer:HelloWorld'
},
addUser: {
priority: 200,
path: '/user',
method: 'POST',
middleware: 'entry:addUser'
},
deleteUser: {
priority: 300,
path: '/user',
method: 'DELETE',
middleware: 'entry:deleteUser'
}
}))
Routes Object
This object must follow a specific structure:
{
routeId: {
path: String,
priority: Number,
enabled: Boolean,
method: String,
middleware: Array<Function|String>|Function|String
}
}
Each property of a route is described in the table below:
| property | type | description |
|:---|:---|:---|
| path | String
| Valid Express route |
| priority | Number
| Number to order the routes, since in express this order matters make sure you place these numbers correctly |
| enabled | Boolean
| Enable/disable a route from being added. true
by default, unless explicitly set to false
|
| method | String
| http method mapped to the route. Defaults to 'GET'. Available methods: 'GET', 'PUT', 'DELETE', 'POST'. |
| middleware | Array<Function|String> | This is the actual middleware function used for the route. For information on how to use please look at route.middleware |
route.middleware
Route Middleware can be written in multiple ways:
Middleware as a Function
Using standard express functions, it accepts standard Express middleware methods as described in using express middleware.
Example:
{
helloWorld: {
path: '/hello/:person',
priority: 100,
middleware: (req, res) => res.send('hello ${req.params.person}!')
}
}
Middleware as an Entity Id
You must pass a string that points to a valid DataPoint entity id; this maps the middleware to the given entity Id. The entity's resolution becomes the result sent to the client.
Example:
// data point entities:
{
'entry:HelloWorld': {
value: (input, acc) => `hello ${acc.locals.params.person}!`
}
}
// routes
{
helloWorld: {
path: '/hello/:person',
priority: 100,
middleware: 'entry:HelloWorld'
}
}
Mixed middleware
You may also use a mix of functions and entity ids, for example you may want to do authentication or parameter normalization before executing a DataPoint entity.
One caveat is that you may only pass one entity id and it must be the last middleware otherwise it throws an error.
Example:
// data point entities:
{
'entry:HelloWorld': {
value: (input, acc) => `hello ${acc.locals.params.person}!`
}
}
// routes
{
helloWorldProtected: {
path: '/hello/:person',
priority: 100,
middleware: [requireAuthentication, 'entry:HelloWorld']
},
badRoute: {
path: '/hello/:person',
priority: 100,
// this is not allowed, entity
// must be at the end.
middleware: ['entry:HelloWorld', requireAuthentication]
}
}
service.inspector()
This service comes with a DataPoint entity inspector web interface. To mount you must pass the result of service.inspector()
to Express app.use. Make sure you specify a path where to mount the inspector.
IMPORTANT: for security do not expose this middleware in production environments.
Basic implementation example:
const express = require('express')
const Service = require('data-point-express')
const app = new express()
Service.create({
// DataPoint entities
entities: {
'entry:hello-world': (input, acc) => 'Hello World!!'
}
})
.then((service) => {
// expose DataPoint inspector
app.use('/api/inspect', service.inspector())
app.listen(3000)
})
.catch(error => {
console.info('Failed to Create Service')
console.error(error)
process.exit(1)
})
Working example at /examples/inspector-demo.js
Accumulator.locals
When an entity executes through a DataPoint Middleware, it appends some useful information to the Accumulator.locals
property. These values are persistent across the execution of the request.
| Property | Type | Description |
|---|---|---|
| routeRequestType | String
| Type of route request being made: 'api', 'rdom', 'html' |
| req | Express.RequestObject
| Reference to current Express req |
| url | String
| Node's message.url |
| query | Object
| Reference to current Express req.query |
| params | Object
| Reference to current Express req.params |
| queryParams | Object
| This is a defaults merge of req.query
with req.params
|
| paramsQuery | Object
| This is a defaults merge of req.params
with req.query
|
Example:
DataPoint Reducer that prints out the acc.locals.url
to the console.
const reducer = (input, acc) => {
console.log('url that originated this call:', acc.locals.url)
return input
}
Contributing
Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.
License
This project is licensed under the Apache License Version 2.0 - see the LICENSE file for details