Router

Introduction

TalkyJS supports @ask-utils/router to create a new RequestHandler more easily.

import { Router } from "@ask-utils/router";

export const HelloWorldIntentRouter: Router = {
    requestType: "IntentRequest",
    intentName: "HelloWorldIntent",
    handler: async (handlerInput) => {
        return handlerInput.responseBuilder
            .speak("Hello! It's a nice development. How are you?")
            .reprompt("How are you?")
            .getResponse()
    }
}

export default HelloWorldIntentRouter

We can easy to define canHandle method by using router.

Same Handler by ask-sdk

import { RequestHandler } from 'ask-sdk-core';

export const HelloWorldIntentHandler: RequestHandler = {
    async canHandle(handlerInput) {
        if (handlerInput.requestEnvelope.request.type !== 'IntentRequest') return false       
        return handlerInput.requestEnvelope.request.intent.name === "HelloWorldIntent"
    },
    async handle(handlerInput) {
        return handlerInput.responseBuilder
            .speak("Hello! It's a nice development. How are you?")
            .reprompt("How are you?")
            .getResponse()
    }
}

export default HelloWorldIntentHandler

Generate by CLI

We can easy to create a new route file from TalkyJS CLI.

$ talky g router HelloWorldIntent
? What type do you handle the request? IntentRequest
? Which type do you want to write SSML? default
CREATE src/HelloWorldIntent/HelloWorldIntent.router.ts (449 bytes)
CREATE src/HelloWorldIntent/tests/HelloWorldIntent.router.spec.ts (1246 bytes)

Add Handler to TalkyJS

We can add a new Route file by using TalkyJS API as same as ask-sdk SkillBuilder.

import { SkillFactory } from '@talkyjs/core'
import HelloWorldIntentHandler from './HelloWorldIntent/HelloWorldIntent.router'

export const handler = SkillFactory.launch()
    .addRequestRouters([
        HelloWorldIntentHandler
    ])
    .getSkill()
    .lambda()

And also we can mix a handler and a router.

import { SkillFactory } from '@talkyjs/core'
import HelloWorldIntentHandler from './HelloWorldIntent/HelloWorldIntent.router'
import GoodByeIntentHandler from './GoodByeIntent/GoodByeIntent.handler'

export const handler = SkillFactory.launch()
    .addRequestRouters([
        HelloWorldIntentHandler
    ])
    .addRequestHandlers(
        GoodByeIntentHandler
    )
    .getSkill()
    .lambda()

Situational Design

Requirement

If we want to use the Router power, we need to configure DB with DynamoDB or S3.


const config: TalkyJSSkillConfig = {
    stage: 'production',                  // [Optional] Skill Stage
    logLevel: 'error',                    // [Optional] Log level
    database: {                           // [Optional] Database configuration
        type: 's3',                       // [Optional] Database type (none / s3 / dynamodb)
        tableName: 'example-bucket-name', // [Optional] Database table name
        s3PathPrefix: 'path-prefix'       // [Optional] [Only S3] S3 path prefix
    },
    skillId: 'ask.your.skill.id',         // [Optional] Skill ID
    errorHandler: {                       // [Optional] error handler configurations
        usePreset: true,
    }
}

Invocation Count

TalkyJS records the skill user's invocation count. The number will increase when the skill launched. (IfrequestEnvelope.session.new is true, it will increase)

export const InitialLaunchRequestRouter: Router = {
    requestType: "LaunchRequest",
    situation: {
        invocationCount: {
            eq: 0
        }
    },
    handler: async (handlerInput) => {
        return handlerInput.responseBuilder
            .speak("The handle will execute when invocation count is 0")
            .getResponse()
    }
}
export const CustomLaunchRequestRouter: Router = {
    requestType: "LaunchRequest",
    situation: {
        invocationCount: {
            gte: 5,
            lte: 10
        }
    },
    handler: async (handlerInput) => {
        return handlerInput.responseBuilder
            .speak("The handle will execute when 5 <= invocation count <= 10")
            .getResponse()
    }
}
export const Custom2LaunchRequestRouter: Router = {
    requestType: "LaunchRequest",
    situation: {
        invocationCount: {
            gt: 5,
            lt: 10
        }
    },
    handler: async (handlerInput) => {
        return handlerInput.responseBuilder
        .speak("The handle will execute when 5 < invocation count < 10")
            .getResponse()
    }
}
export const DefaultLaunchRequestRouter: Router = {
    requestType: "LaunchRequest",
    handler: async (handlerInput) => {
        return handlerInput.responseBuilder
            .speak("It is fallback of the LaunchRequest")
            .getResponse()
    }
}

Conversation Turn

And in the conversation session, we can handle the conversation turn.

export const InitialHelpIntentRouter: Router = {
    requestType: "IntentRequest",
    intentName: "AMAZON.HelpIntent",
    situation: {
        turnCount: {
            eq: 1
        }
    },
    handler: async (handlerInput) => {
        return handlerInput.responseBuilder
            .speak("The handle will execute when conversation turn is 1")
            .getResponse()
    }
}
export const CustomHelpIntentRouter: Router = {
    requestType: "IntentRequest",
    intentName: "AMAZON.HelpIntent",
    situation: {
        turnCount: {
            gte: 5,
            lte: 10
        }
    },
    handler: async (handlerInput) => {
        return handlerInput.responseBuilder
            .speak("The handle will execute when 5 <= conversation turn <= 10")
            .getResponse()
    }
}
export const Custom2HelpIntentRouter: Router = {
    requestType: "IntentRequest",
    intentName: "AMAZON.HelpIntent",
    situation: {
        turnCount: {
            gt: 5,
            lt: 10
        }
    },
    handler: async (handlerInput) => {
        return handlerInput.responseBuilder
        .speak("The handle will execute when 5 < conversation turn < 10")
            .getResponse()
    }
}
export const DefaultHelpIntentRouter: Router = {
    requestType: "IntentRequest",
    intentName: "AMAZON.HelpIntent",
    handler: async (handlerInput) => {
        return handlerInput.responseBuilder
            .speak("It is fallback of the LaunchRequest")
            .getResponse()
    }
}

Custom condition

We can define custom function to handle the request. In this example, the custom matcher will check the requestEnvelope.request.locale.

export const HelpIntentForJapaneseRouter: Router = {
    requestType: "IntentRequest",
    intentName: "AMAZON.HelpIntent",
    situation: {
        custom(input) {
            return /ja/.test(input.requestEnvelope.request.locale)
        }
    },
    handler: async (handlerInput) => {
        return handlerInput.responseBuilder
            .speak("The route will execute only in ja locale.")
            .getResponse()
    }
}
Vote me on Product Hunt!

If you interested about the project, please vote me on Product Hunt!

TalkyJS - Alexa Custom Skill framework - A JavaScript framework for Amazon Alexa Skill development | Product Hunt Embed

©2020 Created by TalkyJS team