ask-sdk-v1adapter
Version:
Adapter from v1 Alexa Node.js SDK to v2
242 lines • 9.58 kB
JavaScript
;
/*
* Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.CreateStateHandler = exports.StateString = exports.Adapter = void 0;
const ask_sdk_1 = require("ask-sdk");
const aws_sdk_1 = require("aws-sdk");
const events_1 = require("events");
const i18n = require("i18next");
const sprintf = require("i18next-sprintf-postprocessor");
const copySessionAttributesInterceptor_1 = require("./copySessionAttributesInterceptor");
const skillEventHandlers_1 = require("./defaultHandlers/skillEventHandlers");
const handler_1 = require("./handler");
const responseBuilderShim_1 = require("./responseBuilderShim");
const responseHandlers_1 = require("./responseHandlers");
class Adapter extends events_1.EventEmitter {
constructor(event, context, callback) {
super();
if (!event.session) {
event.session = {
new: undefined,
sessionId: undefined,
user: undefined,
application: undefined,
attributes: {},
};
}
else if (!event.session.attributes) {
event.session.attributes = {};
}
this.setMaxListeners(Infinity);
this._event = event;
this._context = context;
this._callback = callback;
this.response = {
version: '1.0',
response: {},
};
this.dynamoDBClient = new aws_sdk_1.DynamoDB({
apiVersion: 'latest',
});
this.saveBeforeResponse = false;
this.v2RequestHandlers = [];
this.i18n = i18n;
this.registerHandlers(skillEventHandlers_1.SkillEventHandlers);
this.registerHandlers(responseHandlers_1.ResponseHandlers);
}
registerHandlers(...v1Handlers) {
for (const handler of v1Handlers) {
if (!IsObject(handler)) {
throw (0, ask_sdk_1.createAskSdkError)(this.constructor.name, `Argument #${handler.constructor.name} was not an Object`);
}
const eventNames = Object.keys(handler);
for (const eventName of eventNames) {
if (typeof (handler[eventName]) !== 'function') {
throw (0, ask_sdk_1.createAskSdkError)(this.constructor.name, `Event handler for '${eventName}' was not a function`);
}
let targetEventName = eventName;
if (handler[exports.StateString]) {
targetEventName += handler[exports.StateString];
}
const handlerContext = {
on: this.on.bind(this),
emit: this.emit.bind(this),
emitWithState: EmitWithState.bind(this),
handler: this,
i18n: this.i18n,
locale: this.locale,
t: (...argArray) => this.i18n.t.apply(this.i18n, argArray),
event: this._event,
attributes: this._event.session.attributes,
context: this._context,
callback: this._callback,
name: targetEventName,
isOverridden: IsOverridden.bind(this, targetEventName),
response: new responseBuilderShim_1.ResponseBuilder(this),
};
this.on(targetEventName, handler[eventName].bind(handlerContext));
}
}
}
registerV2Handlers(...requestHandlers) {
this.v2RequestHandlers = [...this.v2RequestHandlers, ...requestHandlers];
}
execute() {
// tslint:disable-next-line
this.locale = this._event.request['locale'] ? this._event.request['locale'] : 'en-US';
if (this.resources) {
this.i18n.use(sprintf).init({
lng: this.locale,
overloadTranslationOptionHandler: sprintf.overloadTranslationOptionHandler,
resources: this.resources,
returnObjects: true,
}, (err) => {
if (err) {
throw (0, ask_sdk_1.createAskSdkError)(this.constructor.name, `Error initializing i19next: ${err}`);
}
ValidateRequest.call(this);
});
}
else {
ValidateRequest.call(this);
}
}
}
exports.Adapter = Adapter;
exports.StateString = Symbol('StateString');
function CreateStateHandler(state, requestHandler) {
if (!requestHandler) {
requestHandler = {};
}
Object.defineProperty(requestHandler, exports.StateString, {
value: state || '',
enumerable: false,
});
return requestHandler;
}
exports.CreateStateHandler = CreateStateHandler;
let dynamoDbPersistenceAdapter;
function ValidateRequest() {
let requestAppId = '';
if (this._event.context) {
requestAppId = this._event.context.System.application.applicationId;
}
else if (this._event.session) {
requestAppId = this._event.session.application.applicationId;
}
if (!this.appId) {
console.log('Warning: Application ID is not set');
}
try {
if (this.appId && (requestAppId !== this.appId)) {
console.log(`The applicationIds don't match: ${requestAppId} and ${this.appId}`);
const error = (0, ask_sdk_1.createAskSdkError)('In validating request', `Invalid ApplicationId: ${this.appId}`);
if (typeof this.callback === 'undefined') {
this._context.fail(error);
}
else {
this._callback(error);
}
}
if (this.dynamoDBTableName && (!this._event.session.sessionId || this._event.session.new)) {
if (!dynamoDbPersistenceAdapter) {
dynamoDbPersistenceAdapter = new ask_sdk_1.DynamoDbPersistenceAdapter({
createTable: true,
dynamoDBClient: this.dynamoDBClient,
partitionKeyName: 'userId',
attributesName: 'mapAttr',
tableName: this.dynamoDBTableName,
});
}
dynamoDbPersistenceAdapter.getAttributes(this._event)
.then((data) => {
Object.assign(this._event.session.attributes, data);
EmitEvent.call(this);
})
.catch((error) => {
const err = (0, ask_sdk_1.createAskSdkError)(this.constructor.name, `Error fetching user state: ${error}`);
if (typeof this._callback === 'undefined') {
return this._context.fail(err);
}
else {
return this._callback(err);
}
});
}
else {
EmitEvent.call(this);
}
}
catch (e) {
console.log(`Unexpected exception '${e}':\n${e.stack}`);
if (typeof this._callback === 'undefined') {
return this._context.fail(e);
}
else {
return this._callback(e);
}
}
}
function EmitEvent() {
const packageInfo = require('../package.json');
this.state = this._event.session.attributes.STATE || '';
ask_sdk_1.SkillBuilders.custom()
.addRequestHandlers(new handler_1.Handler(this), ...this.v2RequestHandlers)
.addRequestInterceptors(new copySessionAttributesInterceptor_1.CopySessionAttributesInterceptor())
.withPersistenceAdapter(dynamoDbPersistenceAdapter)
.withApiClient(new ask_sdk_1.DefaultApiClient())
.withCustomUserAgent(`${packageInfo.name}/${packageInfo.version}`)
.create()
.invoke(this._event, this._context)
.then((responseEnvelope) => {
if (typeof this._callback === 'undefined') {
this._context.succeed(responseEnvelope);
}
else {
this._callback(null, responseEnvelope);
}
})
.catch((err) => {
if (typeof this._callback === 'undefined') {
this._context.fail(err);
}
else {
this._callback(err);
}
});
}
function EmitWithState() {
if (arguments.length === 0) {
throw (0, ask_sdk_1.createAskSdkError)(this.constructor.name, 'EmitWithState called without arguments');
}
arguments[0] = arguments[0] + this.state;
if (this.listenerCount(arguments[0]) < 1) {
arguments[0] = `Unhandled${this.state}`;
}
if (this.listenerCount(arguments[0]) < 1) {
throw (0, ask_sdk_1.createAskSdkError)(this.constructor.name, `No 'Unhandled' function defined for event: ${arguments[0]}`);
}
this.emit.apply(this, arguments);
}
function IsOverridden(name) {
return this.listenerCount(name) > 1;
}
function IsObject(obj) {
return (!!obj) && (obj.constructor === Object);
}
process.on('uncaughtException', function (err) {
console.log(`Uncaught exception: ${err}\n${err.stack}`);
throw err;
});
//# sourceMappingURL=adapter.js.map