A simple router for the Alexa alexa-app
library.
Read the alexa-app documentation before using this add-on utility.
Sample app with code usage available in the mountain top 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);
Configuration for the router.
var config = {
defaultRoute: '/',
pre: preHandler,
post: postHandler,
launch: launchHandler
};
function preHandler(request, response) {...},
function postHandler(request, response) {...},
function launchHandler(request, response) {...}
See Router Logic below.
Shorthand for app.pre = function preHandler(request, response) {...}
;
Shorthand for app.post = function postHandler(request, response) {...}
;
Shorthand for app.launch = function launchHandler(request, response) {...}
;
Shorthand for registering intents.
We never need to specify intent handlers directly, since this is done with the default route (See Router Logic for more details).
var intents = {
NumberIntent: {
'slots': {'number': 'NUMBER'},
'utterances': ['say the number {1-100|number}']
},
'AMAZON.YesIntent': null
};
This is equivalent to:
app.intent('NumberIntent',
{
'slots': {'number': 'NUMBER'},
'utterances': ['say the number {1-100|number}']
},
function(request,response) {}
);
app.intent('AMAZON.YesIntent',
function(request,response) {}
);
Format for registering routes.
Note that the url-style routing is recommended, but not currently required. For now, all routes are exact-matched only without any parameter support (coming in a future version!)
One route needs to be registered as a default route, and should be considered the 'default' state of your app (See Config section). It should handle every intent your app uses, and should handle intents as if the app was just opened.
The rest of the routes should be built as the 'router state' not the 'user state', unlike most web-style routers. In other words, .route('/summary')
doesn't indicate the user has received the summary. It instead indicates the router should handle a response about the summary. It may be easier to write /go-to-summary
instead of /summary
to indicate the user could respond with 'Yes', 'No', 'Menu', or anything else before the summary is provided. (See Router Logic for more details).
var routes = {
'/': {
'AMAZON.HelpIntent': menuHandler,
RecentActivitiesIntent: recentActivitiesHandler,
SummaryIntent: summaryHandler
},
'/go-to-summary': {
'AMAZON.NoIntent': menuHandler,
'AMAZON.YesIntent': summaryHandler
}
};
function menuHandler(request, response {...}
function recentActivitiesHandler(request, response {...}
function summaryHandler(request, response {...}
function launchHandler(request, response) {
var text = 'Welcome to my app. Would you like to hear your summary?';
response
.say(text)
.route('/go-to-summary')
.send();
}
Internally the route is saved on the route
session variable. .route(routeName)
is equivalent to:
response
.shouldEndSession(false)
.session('route', routeName)
The current route can be retrieved with request.route
.
When an intent is received, the router will look for a route handler in the following order:
- [Exact] Match a handler on the route name set in
response.route()
. - [Default] Match a handler on the route name set in
config.defaultRoute
. - [Intent] Execute the original intent handler if no route match was found (defaulted to
noop
).
Using the example routes above, consider the following:
response.route('/go-to-summary')
is set, and anAMAZON.YesIntent
is received next.summaryHandler
is called. [Exact]response.route('/go-to-summary')
is set, and aSummaryIntent
is received next.summaryHandler
is called. [Default]response.route('/go-to-summary')
is set, and aAMAZON.HelpIntent
is received next.menuHandler
is called. [Default]- No route is set, and a
SummaryIntent
is received next.summaryHandler
is called. [Default] - No route is set, and a
NumberIntent
is received next. The handler fromapp.intent('NumberIntent', ...)
is called. [Intent]
The router automatically registers any intents it find in the routes list with a blank handler, so it will be configured properly with the Alexa Skills Kit. This will never override a handler registered with intents
or app.intent()
. In other words, the 'AMAZON.YesIntent': null
in intents
above is unnecessary.
The route names are simply strings. The /
convention is used for familiarity, but not required.
All functionality is backwards compatible with alexa-app. Intents can be registered normally, the router intents are simply a shorthand for convenience.
- Allow route parameters, e.g.
/go-to-page/{page}
. - Allow query parameters, e.g.
/go-to-page?page=3&pageSize=10
. - Allow a default handler for a route, with or without specifically defined handlers. e.g.
var routes = {
'/': {...},
'/go-to-summary': {...},
'/maybe-go-to-summary': {
'AMAZON.NoIntent': menuHandler,
default: summaryHandler
},
'/force-go-to-summary': summaryHandler
};
Special thanks to Matt Kruse for his excellent alexa-app!