voxa-cli
Version:
The Voxa CLI tools
247 lines • 10.8 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/*
* Copyright (c) 2018 Rain Agency <contact@rain.agency>
* Author: Rain Agency <contact@rain.agency>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* tslint:disable:forin */
const lodash_1 = __importDefault(require("lodash"));
const path_1 = __importDefault(require("path"));
const Processor_1 = require("./Processor");
class Schema {
constructor(namespace = "alexa", availableLocales = ["en-US"], voxaSheets, interactionOption) {
this.intents = [];
this.slots = [];
this.downloads = [];
this.fileContent = [];
this.views = [];
this.invocations = [];
this.publishing = [];
this.interactionOptions = {};
this.AVAILABLE_LOCALES = availableLocales;
this.NAMESPACE = namespace;
this.interactionOptions = interactionOption;
this.publishing = Processor_1.publishingProcessor(voxaSheets, this.AVAILABLE_LOCALES);
this.intents = Processor_1.intentUtterProcessor(voxaSheets, this.AVAILABLE_LOCALES);
this.downloads = Processor_1.downloadProcessor(voxaSheets, this.AVAILABLE_LOCALES);
this.views = Processor_1.viewsProcessor(voxaSheets, this.AVAILABLE_LOCALES);
this.slots = Processor_1.slotProcessor(voxaSheets, this.AVAILABLE_LOCALES);
this.invocations = Processor_1.invocationProcessor(voxaSheets, this.AVAILABLE_LOCALES);
}
intentsByPlatformAndEnvironments(locale, environment) {
return this.intents.reduce((acc, intent) => {
const diffLocale = locale !== intent.locale;
if (diffLocale) {
return acc;
}
if (!lodash_1.default.isEmpty(intent.platforms) && !intent.platforms.includes(this.NAMESPACE)) {
return acc;
}
if (!lodash_1.default.isEmpty(intent.environments) && !intent.environments.includes(environment)) {
return acc;
}
acc.push(intent);
return acc;
}, []);
}
buildDownloads() {
this.downloads.forEach(download => {
const file = {
path: this.buildFilePath(this.interactionOptions.viewsPath, `${download.locale}/${lodash_1.default.kebabCase(download.name)}.json`),
content: download.data
};
this.fileContent.push(file);
});
}
buildViewsMapping() {
function pathsFinder(object, prefixes = []) {
let paths = [];
let value;
if (typeof object === "object") {
for (const key in object) {
value = object[key];
if (typeof value === "object" && !Array.isArray(value)) {
paths = paths.concat(pathsFinder(value, prefixes.concat([key])));
}
else {
paths.push(prefixes.concat(key).join("."));
}
}
}
return paths;
}
function variablesFinder(data, viewPath) {
let variables;
let value = lodash_1.default.get(data, viewPath);
if (lodash_1.default.isString(value)) {
value = [value];
}
if (lodash_1.default.isArray(value)) {
variables = lodash_1.default.chain(value)
.filter(v => lodash_1.default.isString(v))
.map(v => v.match(/{([\s\S]+?)}/g))
.flatten()
.compact()
.map(v => v.replace("}", "").replace("{", ""))
.value();
}
return variables;
}
const viewsContent = lodash_1.default.chain(this.views)
.map(view => pathsFinder(view.data).map(viewPath => ({ locale: view.locale, viewPath })))
.flatten()
.reduce((acc, next) => {
const locales = lodash_1.default.get(acc, next.viewPath, []);
locales.push(next.locale);
acc[next.viewPath] = lodash_1.default.uniq(locales);
return acc;
}, {})
.value();
const variablesContent = lodash_1.default.chain(this.views)
.map(view => pathsFinder(view.data).map(viewPath => ({
locale: view.locale,
variables: variablesFinder(view.data, viewPath)
})))
.flatten()
.reduce((acc, next) => {
if (lodash_1.default.isArray(next.variables)) {
next.variables.map(variable => {
const locales = lodash_1.default.get(acc, variable, []);
locales.push(next.locale);
acc[variable] = lodash_1.default.uniq(locales);
});
}
return acc;
}, {})
.value();
const fileViewMap = {
path: this.buildFilePath(this.interactionOptions.viewsPath, "views.map.json"),
content: viewsContent
};
const fileVariablesMap = {
path: this.buildFilePath(this.interactionOptions.viewsPath, "variables.map.json"),
content: variablesContent
};
this.fileContent.push(fileViewMap, fileVariablesMap);
}
buildViews() {
const viewsContent = lodash_1.default.chain(this.views)
.map(view => [view.locale, { translation: view.data }])
.fromPairs()
.value();
const file = {
path: this.buildFilePath(this.interactionOptions.viewsPath, "views.json"),
content: viewsContent
};
this.fileContent.push(file);
}
buildSynonyms() {
this.slots.forEach(slot => {
const file = {
path: this.buildFilePath(this.interactionOptions.viewsPath, "synonyms", `${slot.locale}/${lodash_1.default.kebabCase(slot.name)}.json`),
content: slot.values.reduce((acc, next) => {
if (lodash_1.default.isEmpty(next.synonyms)) {
acc[next.value] = next.value;
}
else {
next.synonyms.map((syn) => {
acc[syn] = next.value;
});
}
return acc;
}, {})
};
this.fileContent.push(file);
});
}
getIntentsDefinition(locale, environment) {
const intentsByPlatformAndEnvironments = this.intentsByPlatformAndEnvironments(locale, environment);
const intents = intentsByPlatformAndEnvironments.map((rawIntent) => {
const { name, samples, slotsDefinition } = rawIntent;
const slots = lodash_1.default(slotsDefinition)
.filter(slot => this.filterByPlatform(slot))
.map((slot) => {
return {
type: slot.type,
name: slot.name.replace("{", "").replace("}", ""),
samples: slot.samples.length > 0 ? slot.samples : undefined
};
})
.value();
return { name, samples, slots };
});
return intents;
}
getSlotsByIntentsDefinition(locale, environment) {
const intents = this.getIntentsDefinition(locale, environment);
const slotsDefinitionNames = lodash_1.default.chain(intents)
.map("slots")
.flatten()
.map("type")
.uniq()
.value();
return this.slots.filter(slot => slot.locale === locale && lodash_1.default.includes(slotsDefinitionNames, slot.name));
}
mergeManifest(environment) {
const manifest = {};
const NAMESPACE = this.NAMESPACE;
this.publishing
.filter(item => lodash_1.default.isEmpty(item.environments) && item.key.includes(this.NAMESPACE))
.forEach(assignPublishingKeys);
this.publishing
.filter(item => lodash_1.default.includes(item.environments, environment) && item.key.includes(this.NAMESPACE))
.forEach(assignPublishingKeys);
return manifest;
function assignPublishingKeys(item) {
let { key, value } = item;
key = key.replace(`${NAMESPACE}.`, "");
if (key.includes("[]")) {
const keySplitByArray = key.split("[]");
key = keySplitByArray[0];
const subKey = keySplitByArray[1];
const arrayOnPublishingInformation = lodash_1.default.get(manifest, key, []);
if (!lodash_1.default.isEmpty(subKey)) {
const subObject = {};
lodash_1.default.set(subObject, subKey, value);
arrayOnPublishingInformation.push(subObject);
}
else {
arrayOnPublishingInformation.push(value);
}
value = arrayOnPublishingInformation;
}
if (key.includes("keywords") && lodash_1.default.isString(value)) {
value = value.split(",").map(lodash_1.default.trim);
}
lodash_1.default.set(manifest, key, value);
}
}
filterByPlatform(slot) {
return slot.platform === this.NAMESPACE || slot.platform === undefined;
}
buildFilePath(...names) {
return path_1.default.join(this.interactionOptions.rootPath, ...names);
}
}
exports.Schema = Schema;
//# sourceMappingURL=Schema.js.map