npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

data-point-express

v5.0.6-alpha.0

Published

Create DataPoint Express middleware

Downloads

36

Readme

DataPoint Express

Build Status codecov Coverage Status All Contributors

Create DataPoint service with Express middleware support

Requirements

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()

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