A simple router for the Alexa alexa-app
library.
- Quick Start
- Breaking Changes
- Gotchas and Important Notes
- Going to a Route
- Route Parameters
- Backwards Compatibility
Read the alexa-app documentation before using this add-on utility.
Sample app with code usage available in the alexa-adopt-a-pet project.
npm install alexa-app alexa-app-router --save
var alexa = require('alexa-app');
var router = require('alexa-app-router');
var app = new alexa.app('app-name');
var config = {...};
var intents = {...};
var routes = {...};
router.addRouter(app, config, intents, routes);
Ul-style routing is strongly recommended. Special processing is done with route variables ({id}
) and query parameters (?limit=10&offset=5
).
var routes = {
'/': launchHandler,
'/exit': exitHandler,
'/help': helpHandler,
'/menu': menuHandler,
'/pets': findPetHandler,
'/pets/{petId}': petDetailsHandler,
'/shelters': findShelterHandler,
};
function launchHandler(request, response) {...}
...(more handler functions)
alexa-app-router
uses a special shorthand for registering intents, normal intent registration with alexa-app
is not necessary.
var intents = {
FindPetIntent: {
slots: {ANIMAL_TYPE: 'ANIMAL_TYPE'},
utterances: ['{adopt a |find a }{-|ANIMAL_TYPE}']
},
MenuIntent: {utterances: ['{menu|help}']},
...(more intents)
};
Configuration for the router.
var config = {
defaultRoutes: {
'AMAZON.CancelIntent': '/exit',
'AMAZON.HelpIntent': '/help',
'AMAZON.NextIntent': '/',
'AMAZON.PreviousIntent': '/',
'AMAZON.RepeatIntent': '/',
'AMAZON.ResumeIntent': '/',
'AMAZON.StartOverIntent': '/',
'AMAZON.StopIntent': '/exit',
'AMAZON.YesIntent': '/',
PetDetailsIntent: '/pets/{petId}',
FindPetIntent: '/pets?offset=0',
FindShelterIntent: '/shelters?limit=5',
MenuIntent: '/menu'
},
pre: preHandler,
post: postHandler,
launch: launchHandler
};
function preHandler(request, response) {...},
function postHandler(request, response) {...},
function launchHandler(request, response) {...}
Contains the default routes to use when no route is specified. These are used on first launch, and when no route has otherwise been specified.
Shorthand for app.pre = function preHandler(request, response) {...}
;
Shorthand for app.post = function postHandler(request, response) {...}
;
Shorthand for app.launch = function launchHandler(request, response) {...}
;
From 0.0.X
to 0.1.X
breaking changes were introduced:
- The whole routing paradigm has been made more intuitive, flexible, and powerful. Read the docs below for updates.
- Every intent your app uses (including Amazon default intents) must be specified in
config.defaultRoutes
.
When prompting the user for a new response, provide the .route()
command a map of routes to go to depending on the user's response. The route is chosen in the following way:
- Exact intent match from
.route()
. - Route specified on the
default
entry. - Intent match on
config.defaultRoutes
.
function launchHandler(request, response) {
var text = 'Welcome to my app. Would you like a list of commands?';
response
.say(text)
.route({
'default': '/'
'AMAZON.CancelIntent': '/exit',
'AMAZON.NoIntent': '/exit',
'AMAZON.YesIntent': '/help',
FindPetIntent: '/pets?offset=0',
FindShelterIntent: '/shelters?limit=5'
})
.send();
}
This allows two useful features:
- Since Alexa can receive any available intent at any time, you can stop unexpected intents by using the
default
route here. - You don't have to specify, for example,
'AMAZON.HelpIntent': '/help'
every time if it is set up onconfig.defaultRoutes
and you don't usedefault
;
Internally the route is saved on the route
session variable. .route(routes)
is equivalent to:
response
.shouldEndSession(false)
.session('route', routes)
Routes support both url and query string parameters.
E.g. .route('/pets/123/photos/45678?format=png&size=large')
will match the route /pets/{petId}/photos/{photoId}
.
The current route info can be retrieved with request.route
:
request.route = {
params: {
petId: '123',
photoId: '45678'
},
query: {
format: 'png',
size: 'large'
},
route: '/pets/{petId}/photos/{photoId}',
url: '/pets/123/photos/45678?format=png&size=large'
}
This allows easy management of complex state flows. Consider the following interaction with the sample routes/intents above:
- User calls the Pet skill and asks to view pets. The
config.defaultRoutes
handler forPetIntent
is set to'/pets?limit=1&offset=0'
which calls thefindPetHandler()
. - User asks for the next pet and
AMAZON.NextIntent
is triggered. In thefindPetHandler
, dynamically routeAMAZON.NextIntent
to'/pets?limit=1&offset=' + (request.route.query.offset + 1)
. - Suppose this returns a pet with an internal Id of
123
infindPetHandler()
. When the user asks for more details, aMoreDetailsIntent
is triggered. - The
MoreDetailsIntent
can be dynamically routed to'/pets/' + pet.Id
which callspetDetailsHandler()
with the pet Id.
All functionality is backwards compatible with alexa-app. Intents can be registered normally, the router intents are simply a shorthand for convenience.
Special thanks to Matt Kruse for his excellent alexa-app, and Daniel Doubrovkine for his work maintaining it!