2.0.0 • Published 8 years ago

alexa-router v2.0.0

Weekly downloads
4
License
MIT
Repository
github
Last release
8 years ago

alexa-router

Build Status Code Climate Test Coverage Version Downloads

Why

alexa-router makes it easy for you to build custom Alexa skills with complex request/response flows.

Install

$ npm install -S alexa-router

Usage

alexa-router is available via an instance of the Router. Make sure you begin by initializing the Router.

let Alexa = require('alexa-router')
let alexa = new Alexa.Router({
  appId: 'my-app-id'
})

Once you initialize the router, you can either configure actions or dispatch a HTTP request to be routed to the actions you have configured.

Router

API

new Alexa.Router(config)

config

Required Type: Object

config.appId Required Type: String[]

Your application ID or an array with many

config.routeIntentOnly Optional Type: Boolean Default: true

Try to route IntentRequest only

config.verifySignature Optional Type: Boolean Default: true

Verifies the incoming request against a valid Amazon signature to prevent request forgery. Amazon requires verification as part of the skill submission process

config.verifyTimestamp Optional Type: Boolean Default: true

Verifies if the incoming request have a valid timestamp to prevent replay attacks

config.verifyAppId Optional Type: Boolean Default: true

Verifies if the incoming request have a valid application ID to prevent replay attacks from other applications

Examples

let alexa = new Alexa.Router({
  appId: 'my-id',
  verifySignature: false
})

alexa.action

Routes are defined via the action method

API

alexa.action(name, config)

name

Required Type: String

The action name. You can reference this action by its name when defining complex action flows.

config

Required Type: Object

config.handler(request[, params])

Required Type: Function

The handler receives a decorated HTTP request and optionally receives params if they were configured to be passed by a previous action.

request

Type: Object

The decorated Alexa Request Body(https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#Request Format) with additional methods.

request.next() Returns: Array An array of Next Action Objects set by the previous response in the session

request.response() Returns: Object A decorated Alexa Response Object

// Instantiate a new Response object
let response = request.response()

response.session(key, value) Param: key String Param: value String|Object Sets, patches, or retrieves the session's attributes

response.speech(text) Param: text String Convenience method to set speech with raw text or SSML

response.reprompt(text) Param: text String Convenience method to set reprompt with raw text or SSML

response.card(card) Param: card Object a valid Alexa Card Object(https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#Response Format) Convenience method to set the response card

response.endSession(shouldEndSession) Param: shouldEndSession Boolean A convenience to set the response shouldEndSession property

response.clearSession() Clears the current session

response.next(config) Param: config Object|Array If you pass an object it will be merged with any previous Next Action Objects that were passed

      The Next Action Object       type       Required       Type: String

      One of 'intent', 'launch', 'sessionEnded', or 'unexpected'

      action       Required       Type: String

      The name of the action that should be called if this route is activated

      intent       Required if type === 'intent'       Type: String

      The custom or built-in intent that this action should be associated with. e.g. 'AMAZON.YesIntent'

      params       Optional       Type: Any

      Any data you'd like to pass to follow request if this route is activated

params

Type: Object

Params set by a previous action

config.global

Optional Type: Object

Actions with the global key are accessible at any point in the routing flow (like a catch-all). These actions can be used to kick-off a new flow, interrupt an existing flow, etc. An action to help the user know what commands are available or cancel the request are two examples for where you might use a global action.

config.global.type Required Type: String

One of 'intent', 'launch', 'sessionEnded', or 'unexpected'

config.global.intent Required if type === 'intent' Type: String

The custom or built-in intent that this action should be associated with. e.g. 'AMAZON.YesIntent'

Examples

A simple action that can be activated by an incoming intent

alexa.action('global-hello', {
  handler: request => {...},
  global: {
    type: 'intent', // Could also be launch, sessionEnded or unexpected
    intent: 'AMAZON.YesIntent'
  }
})

You can also chain requests by responding with a list of possible actions that could be next in the interaction flow

alexa.action('event-create', {
  handler: request => {
    let response = request.response()
    response.speech('What\'s the name of your event?')

    // You can define the next actions by passing an array of actions that can come next
    response.next([
      {
        type: 'intent',
        intent: 'EventName', // Custom intent
        action: 'event-create-name'
        params: { createdAt: new Date() } // Params will be passed to the `event-create-name` handler
      },
      {
        type: 'intent',
        intent: 'AMAZON.CancelIntent', // Built-in intent
        action: 'event-cancel'
      }
    ])

    // You can also pass an individual object and it will be merged with the previous ones
    response.next({
      type: 'unexpected',
      action: 'event-unexpected'
    })

    return response
  },

  global: {
    type: 'intent',
    intent: 'EventCreate' // Custom intent
  }
})

// This action does not have the global attribute so it can only be accessed if passed
// as a `next` action
alexa.action('event-create-name', {
  handler: (request, params) => {...}
})

alexa.dispatch

The dispatch method takes a HTTP request and routes it to the appropriate action

API

alexa.dispatch(requestBody, headers)

requestBody

Required Type: 'Object'

The HTTP request body

Headers

Required Type: 'Object'

The headers present in the original incoming request

Understanding the routing mechanism

  1. Check if the incoming request was configured with next actions
  2. If next actions are present, try to resolve the next action
  3. If no action was resolved, check for an unexpected type next option
  4. If no next actions are present in the request's session, try to match a global action
  5. If no global action was found try to find an unexpected global action
  6. If no unexpected global action then throw RoutingFailed

HTTP handling

alexa-router is HTTP server agnostic. This means that you can use it with any Node.js library that can parse and reply JSON. An example using Express:

let express = require('express')
let bodyParser = require('body-parser')
let Alexa = require('alexa-router')

let app = express()
let alexa = new Alexa.Router({
  appId: 'my-app-id'
})

// Do all your routing configs
alexa.action('my-action', ...)

// Configure a route for passing JSON to alexa-router
app.post('/alexa/incoming', bodyParser.json(), (req, res) => {
  alexa.dispatch(req.body, req.headers)
  .then(result => res.json(result))
  .catch(err => {
    res.send('Somthing bad happened...').status(500)
  })
})

To-do

  • Add plugin support
  • Add more testing cases
  • Build plugins for Express, Hapi, Restify (...)

Testing

git clone https://github.com/estate/alexa-router && cd alexa-router
npm install && npm test