UNPKG

alexa-app

Version:

A module to simplify creation of Alexa (Amazon Echo) apps (Skills) using Node.js

432 lines (330 loc) 14.3 kB
// TypeScript Version: 2.5 import * as alexa from "./alexa"; export * from "./alexa"; export type RequestHandler = (request: request, response: response) => void; export type ErrorHandler = (e: any, request: request, response: response) => void; export let apps: {[name: string]: app}; export class app { constructor(name?: string); /** * Executed before any event handlers. This is useful to setup new sessions, * validate the applicationId, or do any other kind of validations. * You can perform asynchronous functionality in pre by returning a Promise. */ pre: (request: request, response: response, type: string) => void; /** * The 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. * * You can perform asynchronous functionality in `post` by returning a * Promise similar to pre or any of the handlers. */ post: (request: request, response: response, type: string, exception: any) => void; name: string; invocationName?: string; messages: any; /** * By 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. */ persistentSession: boolean; /** Use a minimal set of utterances or the full cartesian product */ exhaustiveUtterances: boolean; /** A catch-all error handler that does nothing by default */ error?: ErrorHandler; /** * A mapping of keywords to arrays of possible values, for expansion of sample utterances */ dictionary: any; intents: {[name: string]: intent}; intent: (intentName: string, schema?: IntentSchema | RequestHandler, handler?: RequestHandler) => void; customSlots: {[name: string]: CustomSlot}; customSlot: (name: string, values: Array<CustomSlot|string>) => void; // TODO audioPlayerEventHandlers: any; audioPlayer: (eventName: string, func: RequestHandler) => void; launchFunc?: RequestHandler; launch: (func: RequestHandler) => void; sessionEndedFunc?: RequestHandler; sessionEnded: (func: RequestHandler) => void; displayElementSelectedFunc?: RequestHandler; displayElementSelected: (func: RequestHandler) => void; playbackControllerEventHandlers: {[name: string]: PlaybackController}; playbackController: (eventName: string, func: RequestHandler) => void; requestHandlers: {[name: string]: RequestHandler}; on: (handlerName: string, handler: RequestHandler) => void; /** TODO: Figure out what the promise actually contains */ request: (requestJSON: alexa.Request) => Promise<alexa.ResponseBody>; /** * @deprecated It's recommended you directly call `app.schema.*` instead * Extracts the schema and generates a schema JSON object * This is equivalent to calling `app.schemas.intent()` */ schema: () => string; /** Functions to generate schema JSON objects in Amazon's various formats */ schemas: { /** Generates a schema in the old default intent format */ intent(): string; /** Generates a schema in the new Skill Builder beta format */ skillBuilder(): string; /** * Generates a schema in the modified Skill Builder format accepted by the ask-cli tool * @param invocationName The invocation name to include in the resulting JSON. * If present, invocationName will be used. Otherwise, if app.invocationName is set, * it will be used. Otherwise, it will default to app.name. */ askcli(invocationName?: string): string; }; /** Generates a list of sample utterances */ utterances: () => string; /** * A built-in handler for AWS Lambda * The "context" param is not actually used in code, but appears for * backwards comaptibility purposes. */ handler: (event: alexa.RequestBody, context: any, callback: (error: Error, response: alexa.ResponseBody) => void) => void; /** For backwards compatibility */ lambda: () => (event: alexa.RequestBody, context: any, callback: (error: Error, response: response) => void) => void; /** * attach Alexa endpoint to an express router * * @param object options.expressApp the express instance to attach to * @param router options.router router instance to attach to the express app * @param string options.endpoint the path to attach the router to (e.g., passing 'mine' attaches to '/mine') * @param bool options.checkCert when true, applies Alexa certificate checking (default true) * @param bool options.debug when true, sets up the route to handle GET requests (default false) * @param bool options.betaSchema when true, Express debug requests will use the new Skill Builder Beta schema * @param function options.preRequest function to execute before every POST * @param function options.postRequest function to execute after every POST * @throws Error when router or expressApp options are not specified * @returns this */ express: (options: ExpressOptions) => void; } export class request { constructor(json: alexa.RequestBody) /** Returns the type of request received (LaunchRequest, IntentRequest, or SessionEndedRequest) */ type: () => "LaunchRequest"|"IntentRequest"|"SessionEndedRequest"; /** Returns the value passed in for a given slot name. */ slot: (slotName: string, defaultValue?: string) => string; /** slots['slotname'] returns the slot object */ slots: {[name: string]: slot}; /** The intent's confirmationStatus */ confirmationStatus: string; /** Check if the intent is confirmed */ isConfirmed: () => boolean; /** Return the Dialog object */ getDialog: () => dialog; /** Check if you can use session (read or write) */ hasSession: () => boolean; /** Returns the session object */ getSession: () => session; /** Returns the request context */ context: alexa.Context; /** The raw request JSON object from Amazon */ data: alexa.RequestBody; isAudioPlayer: () => boolean; isPlaybackController: () => boolean; userId?: string; applicationId?: string; /** This will only exist if the request type is `AudioPlayer` */ selectedElementToken?: string; /** @deprecated */ session: (key: string) => any; /** Returns router object to switch request to some intent, event handler, etc. */ getRouter: () => router; } export class response { resolved: boolean; response: alexa.ResponseBody; sessionObject: session; /** * Tells Alexa to say something; multiple calls to say() will be appended * to each other. All text output is treated as SSML */ say: (phrase: string) => response; /** Empties the response text */ clear: () => response; /** * Tells Alexa to re-prompt the user for a response, if it didn't hear anything valid. * Multiple calls to reprompt() will be appended to each other. */ reprompt: (phrase: string) => response; /** * Returns a card to the user's Alexa app. * Supports card(String title, String content) for backwards compat of type "Simple" */ card: (title: string|alexa.Card, content?: string) => response; /** * Return a card instructing the user how to link their account to the skill. * This internally sets the card response */ linkAccount: () => response; audioPlayerPlay: (playBehavior: string, audioItem: alexa.AudioItem) => response; /** * Plays audio stream (sends AudioPlayer.Play directive) * @see https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/custom-audioplayer-interface-reference#play-directive */ audioPlayerPlayStream: (playBehavior: string, stream: alexa.Stream) => response; /** Stops playing audio stream (sends AudioPlayer.Stop directive) */ audioPlayerStop: () => response; /** * Clears audio player queue (sends AudioPlayer.ClearQueue directive). * clearBehavior is "CLEAR_ALL" by default */ audioPlayerClearQueue: (clearBehavior?: alexa.ClearBehavior) => response; /** * Tells Alexa whether the user's session is over; sessions end by default. * You can optionally pass a reprompt message. */ shouldEndSession: (end?: boolean, reprompt?: string) => response; /** * Sends the response to the Alexa device (success) immediately. * This returns a promise that you must return to continue the * promise chain. Calling this is optional in most cases as it * will be called automatically when the handler promise chain * resolves, but you can call it and return its value in the * chain to send the response immediately. You can also use it * to send a response from `post` after failure. */ send: () => Promise<response>; /** * Triggers a response failure. * The internal promise containing the response will be rejected, and should be handled by the calling environment. * Instead of the Alexa response being returned, the failure message will be passed * similar to `response.send()`, you must return the value returned from this call to continue the promise chain. * This is equivalent to calling `throw message` in handlers * *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` */ fail: (message: string) => Promise<response>; setSessionAttributes: (attributes: any) => void; prepare: () => void; getDirectives: () => directive; directive: (directive: any) => response; /** @deprecated */ session: (key: string, val?: any) => response; /** @deprecated */ clearSession: (key?: string) => response; } // TODO: This is an Amazon-provided interface, but is more of a cluster of a half-dozen different interfaces with no documented parent interface. These are the methods/properties we're actually using. export class directive { details: any[]; set: (directive: any) => void; clear: () => void; } export class session { constructor(session: alexa.Session); isAvailable: () => boolean; isNew: () => boolean; /** * Sets a session variable. * By default, Alexa only persists session variables to the next request. * The alexa-app module makes session variables persist across multiple requests. * Note that you *must* use `.set` or `.clear` to update * session properties. Updating properties of `attributeValue` * that are objects will not persist until `.set` is called */ set: (attributeName: string, attributeValue: any) => void; /** Returns the value of a session variable */ get: (attributeName: string) => any; /** * Session details, as passed by Amazon in the request * for Object definition @see https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference#session-object */ details: alexa.Session; attributes: any; sessionId?: string; clear: (key?: string) => boolean; getAttributes: () => any; } export class router { constructor(app: any, request: alexa.Request, response: alexa.Response, request_json: string) intent: (intent: string) => Promise<response>; launch: () => Promise<response>; sessionEnded: () => Promise<response>; audioPlayer: (event: string) => Promise<response>; playbackController: (event: string) => Promise<response>; displayElementSelected: () => Promise<response>; custom: (requestType: string) => Promise<response>; } export class resolutionValue { constructor(value: alexa.ResolutionValue); name: string; id: string; } export class slotResolution { constructor(resolution: alexa.AuthorityResolution); status: string; values: resolutionValue[]; isMatched: () => boolean; /** Returns the first resolution value */ first: () => resolutionValue; } export class slot { constructor(slot: alexa.Slot); name: string; value: string; confirmationStatus: string; resolutions: slotResolution[]; isConfirmed: () => boolean; /** * Returns the `idx` resolution (if any). If `idx` is omitted, returns the first resolution. */ resolution: (idx?: number) => slotResolution; } export class dialog { constructor(dialogState: alexa.DialogState); dialogState: alexa.DialogState; /** Check if the intent's dialog is STARTED */ isStarted: () => boolean; /** Check if the intent's dialog is IN_PROGRESS */ isInProgress: () => boolean; /** Check if the intent's dialog is COMPLETED */ isCompleted: () => boolean; handleDialogDelegation: (func: RequestHandler) => void; } export class intent { name?: string; handler?: RequestHandler; dialog: dialog; slots: object | null; utterances: string[]; isDelegatedDialog: () => boolean; } export interface ExpressOptions { /** The express instance to attach to */ expressApp: any; /** Router instance to attach to the express app */ router?: any; /** The path to attach the router to (e.g., passing 'mine' attaches to '/mine') */ endpoint?: string; /** When true, applies Alexa certificate checking (default true) */ checkCert?: boolean; /** When true, sets up the route to handle GET requests (default false) */ debug?: boolean; /** Function to execute before every POST. May return altered request JSON, or undefined, or a Promise */ preRequest?(json: alexa.RequestBody, req: any, res: any): Promise<alexa.RequestBody>|alexa.RequestBody|undefined|void; /** Function to execute after every POST. May return altered request JSON, or undefined, or a Promise */ postRequest?(json: alexa.ResponseBody, req: any, res: any): Promise<alexa.ResponseBody>|alexa.ResponseBody|undefined|void; } export interface IntentSchema { dialog?: object; slots?: object; utterances?: string[]; } export interface CustomSlot { value: string; synonyms?: string[]; id?: string|null; } export interface PlaybackController { name: string; function: RequestHandler; }