{"id":13749216,"url":"https://github.com/alexa-js/alexa-app","last_synced_at":"2025-05-15T08:11:20.815Z","repository":{"id":31947290,"uuid":"35517034","full_name":"alexa-js/alexa-app","owner":"alexa-js","description":"A framework for Alexa (Amazon Echo) apps using Node.js","archived":false,"fork":false,"pushed_at":"2023-01-04T07:48:36.000Z","size":1407,"stargazers_count":1032,"open_issues_count":83,"forks_count":215,"subscribers_count":51,"default_branch":"master","last_synced_at":"2025-04-14T14:59:40.208Z","etag":null,"topics":["alexa","amazon-echo","nodejs"],"latest_commit_sha":null,"homepage":"https://www.youtube.com/watch?v=pzM4jv7k7Rg","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexa-js.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-05-12T23:08:10.000Z","updated_at":"2025-03-05T15:53:30.000Z","dependencies_parsed_at":"2023-01-14T20:15:41.414Z","dependency_job_id":null,"html_url":"https://github.com/alexa-js/alexa-app","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexa-js%2Falexa-app","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexa-js%2Falexa-app/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexa-js%2Falexa-app/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexa-js%2Falexa-app/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexa-js","download_url":"https://codeload.github.com/alexa-js/alexa-app/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254301431,"owners_count":22047904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alexa","amazon-echo","nodejs"],"created_at":"2024-08-03T07:00:57.153Z","updated_at":"2025-05-15T08:11:20.789Z","avatar_url":"https://github.com/alexa-js.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"## Table of Contents\n\n* [Stable Release](#stable-release)\n* [Introduction](#introduction)\n* [Features](#features)\n* [Examples](#examples)\n    * [AWS Lambda](#aws-lambda)\n    * [Express](#express)\n      * [Heroku Quickstart](#heroku-quickstart)\n* [API](#api)\n    * [request](#request)\n    * [response](#response)\n      * [Building SSML Responses](#building-ssml-responses)\n    * [session](#session)\n    * [slot](#slot)\n    * [slotResolution](#slotResolution)\n    * [resolutionValue](#resolutionValue)\n    * [router](#router)\n* [Request Handlers](#request-handlers)\n    * [LaunchRequest](#launchrequest)\n    * [IntentRequest](#intentrequest)\n    * [SessionEndRequest](#sessionendrequest)\n    * [Display.ElementSelected](#display-element-selected)\n    * [AudioPlayer Event Request](#audioplayer-event-request)\n    * [PlaybackController Event Request](#playbackcontroller-event-request)\n    * [Other Event Request](#other-event-request)\n* [Execute Code On Every Request](#execute-code-on-every-request)\n    * [pre()](#pre)\n    * [post()](#post)\n* [Schema and Utterances](#schema-and-utterances)\n    * [Schema Syntax](#schema-syntax)\n        * [slots](#slots)\n        * [custom slot types](#custom-slot-types)\n        * [utterances](#utterances)\n            * [Using a Dictionary](#using-a-dictionary)\n    * [Generating Schema and Utterances Output](#generating-schema-and-utterances-output)\n* [Cards](#cards)\n    * [Card Examples](#card-examples)\n* [Custom Directives](#custom-directives)\n* [Dialog](#dialog)\n* [Error Handling](#error-handling)\n* [Echo Show Support](#echo-show-support)\n* [Asynchronous Handlers Example](#asynchronous-handlers-example)\n    * [Customizing Default Error Messages](#customizing-default-error-messages)\n    * [Read/write session data](#readwrite-session-data)\n    * [Define a custom endpoint name for an app](#define-a-custom-endpoint-name-for-an-app)\n* [License](#license)\n\n# alexa-app\n\nA Node module to simplify the development of Alexa skills (applications.)\n\n[![NPM](https://img.shields.io/npm/v/alexa-app.svg)](https://www.npmjs.com/package/alexa-app/)\n[![Build Status](https://travis-ci.org/alexa-js/alexa-app.svg?branch=master)](https://travis-ci.org/alexa-js/alexa-app)\n[![Coverage Status](https://coveralls.io/repos/github/alexa-js/alexa-app/badge.svg?branch=master)](https://coveralls.io/github/alexa-js/alexa-app?branch=master)\n\n## Stable Release\n\nYou're reading the documentation for the next release of alexa-app, which should be 5.0.0. Please see [CHANGELOG](CHANGELOG.md) and make sure to read [UPGRADING](UPGRADING.md) when upgrading from a previous version. The current stable release is [4.2.3](https://github.com/alexa-js/alexa-app/tree/v4.2.3).\n\n## Introduction\n\nThis module parses HTTP JSON requests from the Alexa platform and builds the JSON response that consumed by an Alexa-compatible device, such as the Echo.\n\nIt provides a DSL for defining intents, convenience methods to more easily build the response, handle session objects, and add cards.\n\nThe intent schema definition and sample utterances are included in your application's definition, making it very simple to generate hundreds (or thousands!) of sample utterances with a few lines.\n\nThis module provides a way to host a standalone web service for an Alexa skill. If you're looking for a full-fledged application server\nor the ability to host multiple skills, check out [alexa-app-server](https://github.com/alexa-js/alexa-app-server).\n\n## Features\n\n- simplified handling of requests and generating responses\n- support for asynchronous handlers\n- easy connection into AWS Lambda or Node.js Express, etc.\n- auto-generation of intent schema and sample utterances\n- support for session data\n- comprehensive test suite\n- TypeScript type definitions for type validation, IDE autocompletion, etc\n\n## Examples\n\n### AWS Lambda\n\nAmazon skills that use alexa-app have a built-in `handler` method to handle calls from AWS Lambda.\nYou need to make sure that the Handler is set to `index.handler`, which is the default value.\n\n```javascript\nvar alexa = require(\"alexa-app\");\nvar app = new alexa.app(\"sample\");\n\napp.intent(\"number\", {\n    \"slots\": { \"number\": \"AMAZON.NUMBER\" },\n    \"utterances\": [\"say the number {-|number}\"]\n  },\n  function(request, response) {\n    var number = request.slot(\"number\");\n    response.say(\"You asked for the number \" + number);\n  }\n);\n\n// connect the alexa-app to AWS Lambda\nexports.handler = app.lambda();\n```\n\nFor backwards compatibility, or if you wish to change the Handler mapping to something other than index.handler, you can use the lambda() function.\n\nA full lambda example is available [here](example/lambda.js).\n\n### Express\n\n```javascript\nvar express = require(\"express\");\nvar alexa = require(\"alexa-app\");\nvar express_app = express();\n\nvar app = new alexa.app(\"sample\");\n\napp.intent(\"number\", {\n    \"slots\": { \"number\": \"AMAZON.NUMBER\" },\n    \"utterances\": [\"say the number {-|number}\"]\n  },\n  function(request, response) {\n    var number = request.slot(\"number\");\n    response.say(\"You asked for the number \" + number);\n  }\n);\n\n// setup the alexa app and attach it to express before anything else\napp.express({ expressApp: express_app });\n\n// now POST calls to /sample in express will be handled by the app.request() function\n// GET calls will not be handled\n\n// from here on, you can setup any other express routes or middleware as normal\n```\n\nThe express function accepts the following parameters.\n\n* `expressApp` the express app instance to attach to\n* `router` the express router instance to attach to\n* `endpoint` the path to attach the express app or router to (e.g., passing `'mine'` attaches to `/mine`)\n* `checkCert` when true, applies Alexa certificate checking _(default: true)_\n* `debug` when true, sets up the route to handle GET requests _(default: false)_\n* `preRequest` function to execute before every POST\n* `postRequest` function to execute after every POST\n\nEither `expressApp` or `router` is required.\n\nA full express example is available [here](example/express.js).\n\n#### Heroku Quickstart\n\nWant to get started quickly with alexa-app and Heroku? Simply click the button below!\n\n[![Deploy to Heroku](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy?template=https://github.com/alexa-js/alexa-app-example)\n\n## API\n\nSkills define handlers for launch, intent, and session end, just like normal Alexa development. The alexa-app module provides a layer around this functionality that simplifies the interaction. Each handler gets passed a request and response object, which are custom for this module.\n\n### request\n\n```javascript\n// return the type of request received (LaunchRequest, IntentRequest, SessionEndedRequest)\nString request.type()\n\n// return the value passed in for a given slot name\nString request.slot(\"slotName\")\n\n// return the Slot object\nSlot request.slots[\"slotName\"]\n\n// return the intent's confirmationStatus\nString request.confirmationStatus\n\n// check if the intent is confirmed\nBoolean request.isConfirmed()\n\n// return the Dialog object\nDialog request.getDialog()\n\n// check if you can use session (read or write)\nBoolean request.hasSession()\n\n// return the session object\nSession request.getSession()\n\n// return the router object\nRouter request.getRouter()\n\n// return the request context\nrequest.context\n\n// the raw request JSON object\nrequest.data\n```\n\n### response\n\nThe response JSON object is automatically built for you. All you need to do is tell it what you want to output.\n\n```javascript\n// tell Alexa to say something; multiple calls to say() will be appended to each other\n// all text output is treated as SSML\nresponse.say(String phrase)\n\n// empty the response text\nresponse.clear()\n\n// tell Alexa to re-prompt the user for a response, if it didn't hear anything valid\nresponse.reprompt(String phrase)\n\n// return a card to the user's Alexa app\n// for Object definition @see https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#card-object\n// skill supports card(String title, String content) for backwards compat of type \"Simple\"\nresponse.card(Object card)\n\n// return a card instructing the user how to link their account to the skill\n// this internally sets the card response\nresponse.linkAccount()\n\n// play audio stream (send AudioPlayer.Play directive) @see https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/custom-audioplayer-interface-reference#play-directive\n// skill supports stream(String url, String token, String expectedPreviousToken, Integer offsetInMilliseconds)\nresponse.audioPlayerPlayStream(String playBehavior, Object stream)\n\n// stop playing audio stream (send AudioPlayer.Stop directive)\nresponse.audioPlayerStop()\n\n// clear audio player queue (send AudioPlayer.ClearQueue directive)\n// clearBehavior is \"CLEAR_ALL\" by default\nresponse.audioPlayerClearQueue([ String clearBehavior ])\n\n// tell Alexa whether the user's session is over; sessions end by default\n// pass null or undefined to leave shouldEndSession undefined in the response, to satisfy newer API's\n// you can optionally pass a reprompt message\nresponse.shouldEndSession(boolean end [, String reprompt] )\n\n// send the response to the Alexa device (success) immediately\n// this returns a promise that you must return to continue the\n// promise chain. Calling this is optional in most cases as it\n// will be called automatically when the handler promise chain\n// resolves, but you can call it and return its value in the\n// chain to send the response immediately. You can also use it\n// to send a response from `post` after failure.\nasync response.send()\n\n// trigger a response failure\n// the internal promise containing the response will be rejected, and should be handled by the calling environment\n// instead of the Alexa response being returned, the failure message will be passed\n// similar to `response.send()`, you must return the value returned from this call to continue the promise chain\n// this is equivalent to calling `throw message` in handlers\n// *NOTE:* this does not generate a response compatible with Alexa, so when calling it explicitly you may want to handle the response with `.error` or `.post`\nasync response.fail(String message)\n\n// calls to response can be chained together\nreturn response.say(\"OK\").send()\n```\n\n#### Building SSML Responses\n\nUse [ssml-builder](https://github.com/mandnyc/ssml-builder) to build SSML responses.\n\nExample using basic SSML tags:\n```javascript\nvar Speech = require('ssml-builder');\n\nvar speech = new Speech()\n  .say('Hello')\n  .pause('1s')\n  .say('fellow Alexa developers')\n  .pause('500ms')\n  .say('Testing phone numbers')\n  .sayAs({\n    word: \"+1-234-567-8900\",\n    interpret: \"telephone\"\n  });\n\n// change 'true' to 'false' if you want to include the surrounding \u003cspeak/\u003e tag\nvar speechOutput = speech.ssml(true);\nresponse.say(speechOutput);\n```\n\nExample using Amazon SSML specific tags:\n```javascript\nvar AmazonSpeech = require('ssml-builder/amazon_speech');\n\nvar speech = new AmazonSpeech()\n  .say('Hello')\n  .pause('1s')\n  .whisper('I can see you when you are sleeping')\n  .pause('500ms')\n  .say('Is your phone number still')\n  .sayAs({\n    word: \"+1-234-567-8900\",\n    interpret: \"telephone\"\n  });\n\nvar speechOutput = speech.ssml();\nresponse.say(speechOutput);\n```\n\nExample using multiple reprompts. The reprompts are spoken to the user if they do not respond to the main prompt or say something that does not map to a defined intent:\n```javascript\nresponse.say('What is your request?')\n  .reprompt('Sorry, I didn\\'t catch that.')\n  .reprompt('What is your request?');\n```\n\n### session\n```javascript\n// check if you can use session (read or write)\nBoolean request.hasSession()\n\n// get the session object\nvar session = request.getSession()\n\n// set a session variable\n// by defailt, Alexa only persists session variables to the next request\n// the alexa-app module makes session variables persist across multiple requests\n// Note that you *must* use `.set` or `.clear` to update\n// session properties. Updating properties of `attributeValue`\n// that are objects will not persist until `.set` is called\nsession.set(String attributeName, String attributeValue)\n\n// return the value of a session variable\nString session.get(String attributeName)\n\n// session details, as passed by Amazon in the request\n// for Object definition @see https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#session-object\nsession.details = { ... }\n```\n\n### router\n```javascript\n// get router object\n// every method of the router returns a promise, so you can chain them or just return it back to alexa-app\nvar router = request.getRouter()\n\n// route request to 'MySuperIntent' intent handler\nPromise router.intent('MySuperIntent')\n\n// route request to Launch handler\nPromise router.launch()\n\n// route request to session ended handler\nPromise router.sessionEnded()\n\n// route request to audio player handler\nPromise router.audioPlayer('PlaybackNearlyFinished')\n\n// route request to playback controller handler\nPromise router.playbackController('NextCommandIssued')\n\n// route request to display element selected handler\nPromise router.displayElementSelected()\n\n// route request to custom handler\nPromise router.custom('CrazyCustomEvent')\n```\n\n### slot\n```javascript\n// get the slot object\nvar slot = request.slots[\"slotName\"]\n\n// return the slot's name\nString slot.name\n\n// return the slot's value\nString slot.value\n\n// return the slot's confirmationStatus\nString slot.confirmationStatus\n\n// return the slot's resolutions\nSlotResolution[] slot.resolutions\n\n// check if the slot is confirmed\nBoolean slot.isConfirmed()\n\n// return the n-th resolution\nSlotResolution slot.resolution(Integer n)\n```\n\n### slotResolution\n```javascript\n// get the resolution status code\nString resolution.status\n\n// get the list of resolution values\nResolutionValue resolution.values\n\n// check if the resolution is matched\nBoolean resolution.isMatched()\n\n// Get the first resolution value\nResolutionValue resolution.first()\n```\n\n### resolutionValue\n```javascript\n// get the value name\nString resolutionValue.name\n\n// get the value id\nString resolutionValue.id\n```\n\n## Request Handlers\n\nYour app can define a single handler for the `Launch` event and the `SessionEnded` event, and multiple intent handlers.\n\nFor switching intents, redirecting from one handler to other and other routing tasks you can use [router](#router).\n\n### LaunchRequest\n\n```javascript\napp.launch(function(request, response) {\n  response.say(\"Hello World\");\n  response.card(\"Hello World\", \"This is an example card\");\n});\n```\n\n### IntentRequest\n\nDefine the handler for multiple intents using multiple calls to `intent()`.\nAdditional Intent configuration schema like slots and sample utterances can also be passed to `intent()`, which is detailed below.\nIntent handlers that don't return an immediate response (because they do some asynchronous operation) must return a Promise. The response will be sent when the promise is resolved and fail when the promise is rejected.\nSee example further below.\n\n```javascript\napp.intent(\"live\", {\n    \"dialog\": {\n      type: \"delegate\",\n    },\n    \"slots\": {\n      \"city\": \"AMAZON.US_CITY\"\n    },\n    \"utterances\": [\n      \"in {-|city}\"\n    ]\n  },\n  function(request, response) {\n    response.say(\"You live in \" + request.slot(\"city\"));\n  }\n);\n\napp.intent(\"vacation\", function(request, response) {\n  response.say(\"You're now on vacation.\");\n});\n```\n\n#### AMAZON Specific Intents\n\nAmazon has specific intents that have to do with basic functionality of your skill that you must add.  Some examples of this are `AMAZON.HelpIntent`, `AMAZON.StopIntent`, and `AMAZON.CancelIntent`.  Here are examples of how you would specify these types of intents.\n\n```javascript\napp.intent(\"AMAZON.HelpIntent\", {\n    \"slots\": {},\n    \"utterances\": []\n  },\n  function(request, response) {\n    var helpOutput = \"You can say 'some statement' or ask 'some question'. You can also say stop or exit to quit.\";\n    var reprompt = \"What would you like to do?\";\n    // AMAZON.HelpIntent must leave session open -\u003e .shouldEndSession(false)\n    response.say(helpOutput).reprompt(reprompt).shouldEndSession(false);\n  }\n);\n\napp.intent(\"AMAZON.StopIntent\", {\n    \"slots\": {},\n    \"utterances\": []\n  }, function(request, response) {\n    var stopOutput = \"Don't You Worry. I'll be back.\";\n    response.say(stopOutput);\n  }\n);\n\napp.intent(\"AMAZON.CancelIntent\", {\n    \"slots\": {},\n    \"utterances\": []\n  }, function(request, response) {\n    var cancelOutput = \"No problem. Request cancelled.\";\n    response.say(cancelOutput);\n  }\n);\n```\n\nYou do not need to pass any utterances or slots into these intents.  Also when specifying the name of the intent just use the exact name Amazon [provides](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/built-in-intent-ref/standard-intents).\n\n### Display Element Selected\n\nDefine the handler for when a user selects an element displayed on alexa touch enabled device. For instance the [Echo Show](https://www.amazon.com/Amazon-MW46WB-Introducing-Echo-Show/dp/B01J24C0TI).\n\n```javascript\napp.displayElementSelected(function(request, response) {\n  // The request object selectedElementToken will be populated with the token that was registered\n  // the element in the display directive. To get the token associated with the directive itself,\n  // it is populated on the request.context.Display.token property.\n  handleRequestForTouchEvent(request.selectedElementToken)\n})\n```\n\n### SessionEndRequest\n\n```javascript\napp.sessionEnded(function(request, response) {\n  // cleanup the user's server-side session\n  logout(request.userId);\n  // no response required\n});\n```\n\n### AudioPlayer Event Request\n\nDefine the handler for multiple events using multiple calls to `audioPlayer()`. You can define only one handler per event. Event handlers that don't return an immediate response (because they do some asynchronous operation) must return a Promise.\n\nYou can define handlers for the following events:\n\n* PlaybackStarted\n* PlaybackFinished\n* PlaybackStopped\n* PlaybackNearlyFinished\n* PlaybackFailed\n\n\u003e Please note: \n\u003e * `PlaybackStarted` and `PlaybackFinished` accept only `Stop` or `ClearQueue` directive in response.\n\u003e * `PlaybackStopped` does not accept any response.\n\u003e * `PlaybackNearlyFinished` and `PlaybackFailed` accept any AudioPlayer directive in response.\n\nRead more about AudioPlayer request types in [AudioPlayer Interface Doc](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/custom-audioplayer-interface-reference#audioplayer-requests).\n\nThe following example will return `play` directive with a next audio on `AudioPlayer.PlaybackNearlyFinished` request.\n\n```javascript\napp.audioPlayer(\"PlaybackNearlyFinished\", function(request, response) {\n  // immediate response\n  var stream = {\n    \"url\": \"https://next-song-url\",\n    \"token\": \"some_token\",\n    \"expectedPreviousToken\": \"some_previous_token\",\n    \"offsetInMilliseconds\": 0\n  };\n  response.audioPlayerPlayStream(\"ENQUEUE\", stream);\n});\n```\n\nSee an example of asynchronous response below.\n\n```javascript\napp.audioPlayer(\"PlaybackFinished\", function(request, response) {\n  // async response\n  return getNextSongFromDBAsync()\n  .then(function(url, token) {\n    var stream = {\n      \"url\": url,\n      \"token\": token,\n      \"expectedPreviousToken\": \"some_previous_token\",\n      \"offsetInMilliseconds\": 0\n    };\n    response.audioPlayerPlayStream(\"ENQUEUE\", stream);\n  });\n});\n```\n\n### PlaybackController Event Request\n\nPlaybackController events are sent to your skill when the user interacts with player controls on a device. Define multiple handlers for various events by making multiple calls to `playbackController` with each event type.\n\nYou can define handlers for the following events:\n\n* PlayCommandIssued\n* PauseCommandIssued\n* NextCommandIssued\n* PreviousCommandIssued\n\nRead more about PlaybackController requests in the [PlaybackController Interface Reference](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/custom-playbackcontroller-interface-reference).\n\nThe following example will send a play directive to the device when a user presses the \"next\" button.\n\n```javascript\napp.playbackController('NextCommandIssued', (request, response) =\u003e {\n  var stream = {\n    \"url\": \"https://next-song-url\",\n    \"token\": \"some_token\",\n    \"expectedPreviousToken\": \"some_previous_token\",\n    \"offsetInMilliseconds\": 0\n  };\n  response.audioPlayerPlayStream(\"REPLACE_ALL\", stream);\n});\n```\n\nNote that some device interactions don't always produce PlaybackController events. See the [PlaybackController Interface Introduction](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/custom-playbackcontroller-interface-reference#introduction) for more details.\n\n### Other Event Request\n\nHandle any new requests that don't have an explicit handler type available (such as new or pre-release features) using the general `on()` and passing the event type.\n\nThe following example will handle an imaginary request of type `DeviceEngine.InputHandler` as if it were added to the Alexa API.\n\n```javascript\napp.on('DeviceEngine.InputHandler', (request, response, request_json) =\u003e {\n  response.say(\"You triggered an event from device \" + request_json.request.event.deviceName);\n});\n```\n\nNote that the raw request json is sent as the 3rd parameter to make sure the handler function has access to all data in the case that the request format differs from other handler types.\n\n## Execute Code On Every Request\n\nIn addition to specific event handlers, you can define functions that will run on every request.\n\n### pre()\n\nExecuted before any event handlers. This is useful to setup new sessions, validate the `applicationId`, or do any other kind of validations.\nYou can perform asynchronous functionality in `pre` by returning a Promise.\n\n```javascript\napp.pre = function(request, response, type) {\n  if (request.applicationId != \"amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe\") {\n    // fail ungracefully\n    throw \"Invalid applicationId\";\n    // `return response.fail(\"Invalid applicationId\")` will also work\n  }\n};\n\n// Asynchronous\napp.pre = function(request, response, type) {\n  return db.getApplicationId().then(function(appId) {\n    if (request.applicationId != appId) {\n      throw new Error(\"Invalid applicationId\");\n    }\n  });\n};\n```\n\nNote that the `post()` method still gets called, even if the `pre()` function calls `send()` or `fail()`. The post method can always override anything done before it.\n\n### post()\n\nThe last thing executed for every request. It is even called if there is an exception or if a response has already been sent. The `post()` function can change anything about the response. It can even turn a `return response.fail()` into a `return respond.send()` with entirely new content. If `post()` is called after an exception is thrown, the exception itself will be the 4th argument.\n\nYou can perform asynchronous functionality in `pre` by returning a Promise similar to `pre` or any of the handlers.\n\n```javascript\napp.post = function(request, response, type, exception) {\n  if (exception) {\n    // always turn an exception into a successful response\n    return response.clear().say(\"An error occured: \" + exception).send();\n  }\n};\n```\n\n## Schema and Utterances\n\nThe alexa-app module makes it easy to define your intent schema and generate many sample utterances. Optionally pass your schema definition along with your intent handler, and extract the generated content using either the `schemas.intent()` and `utterances()` functions on your app (if using the normal Developer portal), `schemas.skillBuilder()` if using the new Skill Builder beta, or `schemas.askcli()` if using the `ask-cli` tool.\n\n\n### Schema Syntax\n\nPass an object with two properties: slots and utterances.\n\n```javascript\napp.intent(\"sampleIntent\", {\n    \"slots\": {\n      \"NAME\": \"AMAZON.US_FIRST_NAME\",\n      \"AGE\": \"AMAZON.NUMBER\"\n    },\n    \"utterances\": [\n      \"my {name is|name's} {NAME} and {I am|I'm} {-|AGE}{ years old|}\"\n    ]\n  },\n  function(request, response) { ... }\n);\n```\n\n#### slots\n\nThe slots object is a simple `name: type` mapping. The type must be one of Amazon's [built-in slot types](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/built-in-intent-ref/slot-type-reference), such as `AMAZON.DATE` or `AMAZON.NUMBER`.\n\n#### custom slot types\n\n[Custom slot types](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interaction-model-reference#custom-slot-syntax) are supported via the following syntax.\n\n```javascript\napp.intent(\"sampleIntent\", {\n    \"slots\": {\n      \"CustomSlotName\": \"CustomSlotType\"\n    },\n    \"utterances\": [\n      \"airport {information|status} for {-|CustomSlotName}\"\n    ]\n  },\n  function(request, response) { ... }\n);\n```\n\nThis will result in the following utterance list.\n\n```\nsampleIntent     airport information for {CustomSlotName}\nsampleIntent     airport status for {CustomSlotName}\n```\n\nNote that the \"CustomSlotType\" type values must be specified in the Skill Interface's Interaction Model for the custom slot type to function correctly.\n\n#### custom slot type values\n\nIf you have custom slot types, you can define your custom slot type values as well. Custom values can either be simple strings, or more full-fledged objects if you want to take advantage of Skill Builder features like synonyms. If using synonyms, you can also take advantage of utterance expansion from alexa-utterances (including dictionary), as described below.\n\n```javascript\ntestApp.customSlot(\"animal\", [\"cat\", \"dog\"]);\n```\n\nOR\n\n```javascript\ntestApp.customSlot(\"animal\", [{\n  value: \"dog\",\n  id: \"canine\",\n  synonyms: [\"doggo\", \"pup{per|}\", \"woofmeister\"]\n}]);\n```\n\n#### utterances\n\nThe utterances syntax allows you to generate many (hundreds or even thousands) of sample utterances using just a few samples that get auto-expanded.\nAny number of sample utterances may be passed in the utterances array.\n\nThis module internally uses [alexa-utterances](https://github.com/alexa-js/alexa-utterances)\nto expand these convenient strings into a format that alexa understands. Read the documentation there for a\nthorough set of examples on how to use this.\n\n##### Using a Dictionary\n\nSeveral intents may use the same list of possible values, so you want to define them in one place, not in each intent schema. Use the app's dictionary.\n\n```javascript\napp.dictionary = {\"colors\":[\"red\",\"green\",\"blue\"]};\n...\n\"my favorite color is {colors|FAVEORITE_COLOR}\"\n\"I like {colors|COLOR}\"\n```\n\n### Generating Schema and Utterances Output\n\n#### Intent Schema Syntax\n\nIf you are using the normal Amazon developer portal, the `schemas.intent()` and `utterances()` functions will generate an\nintent schema JSON string and a list of utterances, respectively.\n\nSee [example/express.js](example/express.js) for one way to output this data.\n\n```javascript\n// returns a String representation of an Intent Schema JSON object\napp.schemas.intent() =\u003e\n\n{\n  \"intents\": [{\n    \"intent\": \"MyColorIsIntent\",\n    \"slots\": [{\n      \"name\": \"Color\",\n      \"type\": \"AMAZON.Color\"\n    }]\n  }]\n}\n\napp.utterances() =\u003e\n\nMyColorIsIntent  my color is {dark brown|Color}\nMyColorIsIntent  my color is {green|Color}\nMyColorIsIntent  my favorite color is {red|Color}\nMyColorIsIntent  my favorite color is {navy blue|Color}\nWhatsMyColorIntent whats my color\nWhatsMyColorIntent what is my color\nWhatsMyColorIntent say my color\nWhatsMyColorIntent tell me my color\nWhatsMyColorIntent whats my favorite color\nWhatsMyColorIntent what is my favorite color\nWhatsMyColorIntent say my favorite color\nWhatsMyColorIntent tell me my favorite color\nWhatsMyColorIntent tell me what my favorite color is\n```\n\n#### Skill Builder Syntax\n\nIf you are using the Skill Builder Beta, the `schemas.skillBuilder()` function will generate a single schema JSON string\nthat includes your intents with all of their utterances\n\n```javascript\napp.schemas.skillBuilder() =\u003e\n\n{\n  \"intents\": [{\n    \"name\": \"MyColorIsIntent\",\n    \"samples\": [\n      \"my color is {dark brown|Color}\",\n      \"my color is {green|Color}\",\n      \"my favorite color is {red|Color}\",\n      \"my favorite color is {navy blue|Color}\"\n    ],\n    \"slots\": [{\n      \"name\": \"Color\",\n      \"type\": \"AMAZON.Color\",\n      \"samples\": []\n    }]\n  }],\n  \"types\": [{\n    \"name\": \"MyCustomColor\",\n    \"values\": [{\n      \"id\": null,\n      \"name\": {\n        \"value\": \"aquamarine\",\n        \"synonyms\": [\"aqua\", \"seafoam\", \"teal\"]\n      }\n    }]\n  }];\n}\n```\n\n#### ask-cli Schema\n\nThe [ask-cli](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/ask-cli-intro) tool accepts a schema in the same format as the Skill Builder, but is structured slightly differently. The `schemas.askcli()` function generates a JSON string suitable to be used with the `ask deploy` command.\n\nThis schema format requires you to specify the invocation name for your skill. You can set this for your skill by setting `app.invocationName`. If you need to use different invocation names for the same skill (e.g. you have both a staging and production version), the schema function itself can take in an invocation name which overwrites the app's default.\n\n```javascript\napp.schemas.askcli(\"favorite color\") =\u003e\n\n{\n  \"interactionModel\": {\n    \"languageModel\": {\n      \"invocationName\": \"favorite color\"\n      \"intents\": [{\n        \"name\": \"MyColorIsIntent\",\n        \"samples\": [\n          \"my color is {dark brown|Color}\",\n          \"my color is {green|Color}\",\n          \"my favorite color is {red|Color}\",\n          \"my favorite color is {navy blue|Color}\"\n        ],\n        \"slots\": [{\n          \"name\": \"Color\",\n          \"type\": \"AMAZON.Color\",\n          \"samples\": []\n        }]\n      }],\n      \"types\": [{\n        \"name\": \"MyCustomColor\",\n        \"values\": [{\n          \"id\": null,\n          \"name\": {\n            \"value\": \"aquamarine\",\n            \"synonyms\": [\"aqua\", \"seafoam\", \"teal\"]\n          }\n        }]\n      }];\n    }\n  }\n}\n```\n\n## Cards\n\nThe `response.card(Object card)` method allows you to send [Home Cards](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/providing-home-cards-for-the-amazon-alexa-app) on the Alexa app, the companion app available for Fire OS, Android, iOS, and desktop web browsers.\n\nThe full specification for the `card` object passed to this method can be found [here](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#card-object).\n\nThe full specification for the permission card can be found [here](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/device-address-api#sample-response-with-permission-card).\n\nCards do not support SSML.\n\nIf you just want to display a card that presents the user to link their account call `response.linkAccount()` as a shortcut.\n\n### Card Examples\n\nDisplay text only, aka [Simple](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/providing-home-cards-for-the-amazon-alexa-app#Creating%20a%20Basic%20Home%20Card%20to%20Display%20Text).\n\n```javascript\nresponse.card({\n  type: \"Simple\",\n  title: \"My Cool Card\", // this is not required for type Simple\n  content: \"This is the\\ncontent of my card\"\n});\n```\n\nDisplay text and image, aka [Standard](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/providing-home-cards-for-the-amazon-alexa-app#Creating%20a%20Home%20Card%20to%20Display%20Text%20and%20an%20Image).\n\nMake sure to read the restrictions on hosting the images. Must support CORS AND SSL cert signed by an Amazon approved certification authority.\n\n```javascript\nresponse.card({\n  type: \"Standard\",\n  title: \"My Cool Card\", // this is not required for type Simple or Standard\n  text: \"Your ride is on the way to 123 Main Street!\\nEstimated cost for this ride: $25\",\n  image: { // image is optional\n    smallImageUrl: \"https://carfu.com/resources/card-images/race-car-small.png\", // required\n    largeImageUrl: \"https://carfu.com/resources/card-images/race-car-large.png\"\n  }\n});\n```\n\nDisplay a card that presents the user to grant information to your skill, aka [AskForPermissionsConsent](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/device-address-api#sample-response-with-permission-card).\n\nIf the request was for the country and postal code, then the permissions value in this response will be `read::alexa:device:all:address:country_and_postal_code`.\n\n```javascript\nresponse.card({\n  type: \"AskForPermissionsConsent\",\n  permissions: [ \"read::alexa:device:all:address\" ] // full address\n});\n```\n\n## Custom Directives\n\nThe `response.directive(Object directive)` method allows you to set custom directive objects to devices to perform a specific device-level actions.\n\nThe full specification for the `directive` object passed to this method can be found [here](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#response-format).\n\nThe `alexa-app` library has special handling for AudioPlayer directives, so you only need to use this method for more general custom directives.\n\nThe `response.directive` adds your directive object to the directives array in the response. To clear the directives from the response, call `response.getDirectives().clear()`.\n\n## Dialog\n\nThe full specification for the dialog directives that can be used can be found [here](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/dialog-interface-reference). See [Custom Directives](#custom-directives) above for an example on manually sending dialog directives.\n\nNote that skills must meet Alexa's [requirements to use the `Dialog` directive](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/dialog-interface-reference#dialog-reqs).\n\nThe `alexa-app` library has special handling for enabling Alexa to handle Dialog directly. To\nconfigure `alexa-app` to delegate dialog to Alexa, enable the handling\nper-intent via the schema:\n\n```javascript\napp.intent(\"sampleIntent\", {\n    \"dialog\": {\n      type: \"delegate\"\n    },\n    \"slots\": { ... },\n    \"utterances\": [ ... ],\n  },\n  function(request, response) { ... }\n);\n```\n\n### dialog object\n\n```javascript\n// return the Dialog object\nDialog request.getDialog()\n\n// return the intent's dialogState\nString dialog.dialogState\n\n// check if the intent's dialog is STARTED\nBoolean dialog.isStarted()\n\n// check if the intent's dialog is IN_PROGRESS\nBoolean dialog.isInProgress()\n\n// check if the intent's dialog is COMPLETED\nBoolean dialog.isCompleted()\n```\n\n## Error Handling\n\nWhen handler functions throw exceptions, they will trigger a rejection in the promise chain. If the response has not already been sent, `.post` will be triggered which will allow you to force a successful response. If `post` does not alter the response, then a failed response will be sent. You can use this to throw an exception to or call `return response.fail(\"message\")` to force a failure, but this *does not* generate a response compatible with Alexa.\n\nThe `.error` handler method will capture any errors in the chain. The default behavior of `.error` is to trigger `response.send` if the response has not already been sent, but you can force or continue failure by returning a rejected promise or `throw`ing inside the error handler. Returning a promise allows you to do asynchronous operations in the error handler.\n\nIdeally, you should catch errors in your handlers and respond with an appropriate output to the user. Any exceptions can be handled by a generic error handler which you can define for your app. If you want error handling to be asynchronous, it must return a promise.\n\n```javascript\napp.error = function(exception, request, response) {\n  response.say(\"Sorry, something bad happened\");\n};\n```\n\nIf you do want exceptions to bubble out to the caller (and potentially cause Express to crash, for example), you can throw the exception from the error handler.\n\n```javascript\napp.error = function(exception, request, response) {\n  console.error(exception);\n  throw exception;\n};\n```\n\n## Echo Show Support\n\nWith the addition of [custom directives](#custom-directives) and support for [display elements]((#display-element-selected)) being selected, this library fully supports the Echo Show. Note that it is up to the developer to detect if the device can handle a display directive. If a display directive is returned to a non-visual device it will throw an error. One technique is to leverage the `app.post` call and remove any directives if the device does not support a UI. For example:\n\n```\napp.post(req, res, type, exception) {\n  // If the device does not support display directives then remove them from the response\n  if (!system.supportsDisplay(req))) {\n    res.response.response.directives = []\n  }\n}\n```\n\nPlease refer to [Amazon's documentation](https://developer.amazon.com/docs/custom-skills/display-interface-reference.html#display-template-reference) for the list of supported template markup.\n\n## Asynchronous Handlers Example\n\nIf an intent or other request handler (including `pre` and `post`, but *not* `error`) will return a response later, it must a `Promise`. This tells the alexa-app library not to send the response automatically.\n\nIf the Promise resolves, the response will be sent. If it is rejected, it is treated as an error.\n\n```javascript\napp.intent(\"checkStatus\", function(request, response) {\n  // `getAsync` returns a Promise in this example. When\n  // returning a Promise, the response is sent after it\n  // resolves. If rejected, it is treated as an error.\n  return http.getAsync(\"http://server.com/status.html\").then(function (rc) {\n    response.say(rc.statusText);\n  });\n});\n```\n\nIf you want to respond immediately, you can use `return response.send()` to complete the respones. Using `throw msg` or `return response.fail(msg)` will trigger immediate failure. **Note:** `.post` is still run once after `response.send()` or `response.fail()` are called.\n\n```javascript\napp.intent(\"checkStatus\", function(request, response) {\n  if (currentStatus == \"bad\") {\n    return response.fail(\"bad status\");\n  }\n  else if (currentStatus == \"good\") {\n    response.say(\"good status\");\n    return response.send();\n  }\n\n  return http.getAsync(\"http://server.com/status.html\").then(function (rc) {\n    if (rc.body == \"bad\") {\n      throw \"bad status\";\n    }\n    response.say(\"good status\");\n    // return `response.send` to continue the promise chain\n    return response.send();\n  });\n});\n```\n\n### Customizing Default Error Messages\n\n```javascript\napp.messages.NO_INTENT_FOUND = \"Why you called dat intent? I don't know bout dat\";\n```\n\nSee the code for default messages you can override.\n\n### Read/write session data\n\n```javascript\napp.launch(function(request, response) {\n  request.getSession().set(\"number\", 42);\n  response.say(\"Would you like to know the number?\");\n  response.shouldEndSession(false);\n});\n\napp.intent(\"tellme\", function(request, response) {\n  var session = request.getSession();\n  response.say(\"The number is \" + session.get(\"number\"));\n  // clear only the 'number' attribute from the session\n  session.clear(\"number\");\n});\n\n// the session variables can be entirely cleared, or cleared by key\napp.intent(\"clear\", function(request, response) {\n  var session = request.getSession();\n  session.clear(); // or: session.clear(\"key\") to clear a single value\n  response.say(\"Session cleared!\");\n});\n```\n\nBy default, alexa-app will persist every request session attribute into the response. This way, any session attributes you set will be sent on every subsequent request, as is typical in most web programming environments. If you wish to disable this feature, you can do so by setting `app.persistentSession` to `false`.\n\n```javascript\nvar app = new alexa.app(\"test\");\napp.persistentSession = false;\n```\n\n### Define a custom endpoint name for an app\n\nWhen mapped to express, the default endpoint for each app is the name of the app. You can customize this using the second parameter to the `app()` method.\n\n```javascript\nvar app = new alexa.app(\"hello\", \"myEndpointName\");\n```\n\nAll named apps can be found in the `alexa.apps` object, keyed by name. The value is the app itself.\n\n## License\n\nCopyright (c) 2016-2017 Matt Kruse\n\nMIT License, see [LICENSE](LICENSE.md) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexa-js%2Falexa-app","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexa-js%2Falexa-app","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexa-js%2Falexa-app/lists"}