Simply Alexa skill framework with ask-sdk.
$ npm i -S @talkyjs/core
import { SkillFactory } from '@talkyjs/core'
export const handler = SkillFactory.launch()
.addRequestHandlers({
canHandle(input) {
return input.requestEnvelope.request.type === 'LaunchRequest'
},
handle(input) {
return input.responseBuilder.speak('Hello').getResponse()
}
})
.createLambdaHandler()
We can easy to set up a several skill configuration.
import { SkillFactory, TalkyJSSkillConfig } from '@talkyjs/core'
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
},
apiClient: { // SMAPI and Alexa API Client configuration
useDefault: true, // Use DefaultApiClient
// client: new DefaultApiClient() // If you have own ApiClient, put here
},
skillId: 'ask.your.skill.id', // [Optional] Skill ID
errorHandler: { // [Optional] error handler configurations
usePreset: true, // [Optional] Use preset error handler
sentry: { // [Optional] Error tracker configuration (sentry)
dsn: process.env.SENTRY.DSN // [Optional] Sentry dsn
}
}
}
export const handler = SkillFactory.launch(config)
.addRequestHandlers({
canHandle(input) {
return input.requestEnvelope.request.type === 'LaunchRequest'
},
handle(input) {
return input.responseBuilder.speak('Hello').getResponse()
}
})
.createLambdaHandler()
@talkyjs has a various utility classes and function. But almost feature has a compatibility to ask-sdk.
Easy to setup, easty to customize.
We can choose these stage to run the skill
stage | feature |
---|---|
development | Add devleopment helper handler (IntentReflector) |
production | Ignore development utilties |
RequstType | IntentName | action |
---|---|---|
SessionEndedRequest | - | Record the ended reason |
IntentRequest | AMAZON.RepeatIntent | Repeat the last response (Only in session) |
AlexaSkillEvent.SkillDisabled | - | Delete the user data from the persistent attributes |
ErrorHandler | - | Log the Error and return the error resposne (Supported lang: Japanese / English) |
Automatically log these props.
- Request
- Response
TalkyJS has a extended persistentAttributesManager.
import { PersistentAttributesManager, SkillFactory } from '@talkyjs/core';
SkillFactory.launch({
database: {
type: 's3', // or 'dynamodb'. When select 'none', it does not work!
tableName: 'example-bucket'
}
}).addRequestHandlers({
canHandle(input) {
return input.requestEnvelope.request.type === 'LaunchRequest'
},
async handle(input) {
// Create manager
const persistenceManager = new PersistentAttributesManager(input.attributesManager)
// Get saved data with default value
const { name } = await persistenceManager.getPersistentAttributes({
name: 'sir'
})
// Update parameter with merging exists attributes
await persistenceManager.updatePersistentAttributes({
now: new Date().toISOString()
})
return input.responseBuilder.speak(`Hello ${name}`).getResponse()
}
})
And all persistent attributes using the manager will saved at the ResponseInterceptor automatically. So, the database connection has been optimized.
We can define attributes for your own Skill
type MySkillData = {
name: string;
favoritesCities: string[];
preferedLevel: 'easy' | 'normal' | 'hard'
}
class MySkillPersistentAttributesManager extends PersistentAttributesManager<MySkillData> {
protected readonly defaultAttributes = {
name: '',
favoritesCities: [],
preferedLevel: 'normal' as const
}
}
And use own class intead of default class.
SkillFactory.launch({
database: {
type: 's3',
tableName: 'example-bucket'
}
}).addRequestHandlers({
canHandle(input) {
return input.requestEnvelope.request.type === 'LaunchRequest'
},
async handle(input) {
const persistenceAdapter = new MySkillPersistentAttributesManager(input.attributesManager)
const { name } = await persistenceAdapter.getPersistentAttributes()
await persistenceAdapter.updatePersistentAttributes({
preferedLevel: 'hard'
})
await persistenceAdapter.save()
return input.responseBuilder.speak(`Hello ${name}`).getResponse()
}
})
We can save it to execute await persistenceAdapter.save()
method.
And the method is checking is the attributes updated.
// Update attributes
await persistenceManager.updatePersistentAttributes({
now: new Date().toISOString()
})
// Save now!
await persistenceAdapter.save()
// Nothing to do (Because no attributes has been updated)
await persistenceAdapter.save()
// Update attributes second time
await persistenceManager.updatePersistentAttributes({
now: new Date().toISOString()
})
// Save!
await persistenceAdapter.save()