Files
Zos/Skills/@be/node_modules/jibo-kb/lib/jibo-kb.js

2155 lines
73 KiB
JavaScript

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.jiboKb = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const fs = require("fs-extra");
const path = require("path");
const stream = require("stream");
const url = require("url");
const uuid = require("uuid");
const blobToBuffer = require("blob-to-buffer");
const decorators_1 = require("./decorators");
const log_1 = require("./log");
const log = log_1.default.createChild('Asset');
class Asset {
constructor(filenameOrURL, subtype, ext) {
if (!filenameOrURL) {
this._id = uuid.v4();
this.subtype = subtype || 'asset';
this.ext = ext;
}
else {
this.setSelfFromFilenameOrURL(filenameOrURL);
}
}
static _processError(err) {
if (err.response) {
let description = `HTTP Error Code ${err.response.status}`;
if (err.response.data) {
description += err.response.data;
}
return new Error(description);
}
else {
return new Error(err.request
? 'No response received'
: 'Unknown error');
}
}
setRootDir(rootDir) {
this.rootDir = rootDir;
}
filename() {
let filename = `${this._id}.${this.subtype}`;
if (this.ext) {
filename += `.${this.ext}`;
}
return filename;
}
fullFilenameOrURL() {
if (!this.rootDir) {
throw new Error('asset rootDir not set');
}
let filename;
if (this.rootDir.startsWith('http://')) {
filename = this._url();
}
else {
filename = this.filename();
filename = path.join(this.rootDir, 'assets', filename);
}
return filename;
}
toString() { return this.fullFilenameOrURL(); }
save(data, callback) {
if (this.rootDir.startsWith('http://')) {
if ((data instanceof Buffer) || (data instanceof stream.Readable)) {
this._saveViaWeb(data, callback);
}
else {
blobToBuffer(data, (err, buffer) => {
log.iferr(err, 'blobToBuffer');
if (!err) {
this._saveViaWeb(buffer, callback);
}
else {
callback(err);
}
});
}
}
else {
if (data instanceof Buffer) {
this._saveBuffer(data, callback);
}
else if (data instanceof stream.Readable) {
this._saveStream(data, callback);
}
else {
blobToBuffer(data, (err, buffer) => {
log.iferr(err, 'blobToBuffer');
if (!err) {
this._saveBuffer(buffer, callback);
}
else {
callback(err);
}
});
}
}
}
setSelfFromFilenameOrURL(filenameOrURL) {
if (filenameOrURL.startsWith('http://')) {
this._setSelfFromURL(filenameOrURL);
}
else {
this._setSelfFromFilename(filenameOrURL);
}
}
load(callback) {
if (this.rootDir.startsWith('http://')) {
this._loadBufferViaWeb(callback);
}
else {
let filename = this.fullFilenameOrURL();
fs.readFile(filename, (err, data) => {
log.iferr(err, 'readFile on', filename);
callback(err, data);
});
}
}
loadStream() {
if (this.rootDir.startsWith('http://')) {
return this._loadStreamViaWeb();
}
else {
let filename = this.fullFilenameOrURL();
return Promise.resolve(fs.createReadStream(filename));
}
}
loadBlob(callback) {
this.load((err, data) => {
let blob;
log.iferr(err, 'could not load asset file');
if (!err) {
blob = new Blob(data, { type: 'application/octet-binary' });
}
callback(err, blob);
});
}
remove(callback) {
if (this.rootDir.startsWith('http://')) {
this._removeViaWeb(callback);
}
else {
let filename = this.fullFilenameOrURL();
log.info('removing asset file', filename);
fs.unlink(filename, (err) => {
log.iferr(err, 'fs.unlink of', filename);
if (!err) {
log.debug('asset file', filename, 'removed from disk');
}
callback(err);
});
}
}
_url() {
if (!this.rootDir) {
throw new Error('asset rootDir not set');
}
let filename = this.filename();
return `${this.rootDir}/asset/${filename}`;
}
_saveViaWeb(data, callback) {
let url = this._url();
axios_1.default.post(url, data, {
headers: { 'Content-Type': 'application/octet-stream' }
}).then(res => callback(null, url), (err) => {
log.error('axios.post', url, err);
callback(Asset._processError(err));
});
}
_setSelfFromFilename(filename) {
if (path.isAbsolute(filename)) {
this.rootDir = path.dirname(path.dirname(filename));
filename = path.basename(filename);
}
let re = new RegExp(`^([^.]*)[.]([^.]*)([.]([^.]*))?$`);
let vals = filename.match(re);
if (!vals) {
throw new Error('filename did not parse');
}
this._id = vals[1];
this.subtype = vals[2] || '';
this.ext = vals[4] || '';
}
_setSelfFromURL(httpurl) {
let urlParts = url.parse(httpurl);
let pathParts = urlParts.pathname.split('/');
let rootPath = pathParts.slice(0, 3).join('/');
this.rootDir = `http://${urlParts.hostname}:${urlParts.port}/${rootPath}`;
let filename = pathParts[pathParts.length - 1];
this._setSelfFromFilename(filename);
}
_removeViaWeb(callback) {
let url = this._url();
axios_1.default.delete(url).then(res => callback(null), (err) => {
log.error('axios.delete', url, err);
callback(Asset._processError(err));
});
}
_saveBuffer(buffer, callback) {
if (!buffer) {
callback();
return;
}
let filename = this.fullFilenameOrURL();
fs.ensureDir(path.dirname(filename), (err) => {
log.iferr(err, 'ensureDir');
if (!err) {
log.info('writing asset file', filename);
fs.writeFile(filename, buffer, (err) => {
log.iferr(err, 'file write error', filename);
callback(err, filename);
});
}
else {
callback(err);
}
});
}
_saveStream(stream, callback) {
if (!stream) {
callback();
return;
}
let filename = this.fullFilenameOrURL();
fs.ensureDir(path.dirname(filename), (err) => {
log.iferr(err, 'ensureDir');
if (!err) {
log.info('writing asset file', filename);
let writeStream = fs.createWriteStream(filename);
stream.pipe(writeStream);
writeStream.on('finish', () => {
callback(null, filename);
});
writeStream.on('error', (err) => {
log.error('file write error', filename, err);
});
}
else {
callback(err);
}
});
}
_loadBufferViaWeb(callback) {
let url = this._url();
axios_1.default.get(url, {
responseType: 'arraybuffer',
}).then(res => callback(null, new Buffer(res.data)), (err) => {
log.error('request.get', url, err);
callback(Asset._processError(err));
});
}
_loadStreamViaWeb() {
return axios_1.default.get(this._url(), {
responseType: 'stream',
}).then(response => response.data);
}
}
__decorate([
decorators_1.promisify
], Asset.prototype, "save", null);
__decorate([
decorators_1.promisify
], Asset.prototype, "load", null);
__decorate([
decorators_1.promisify
], Asset.prototype, "loadBlob", null);
__decorate([
decorators_1.promisify
], Asset.prototype, "remove", null);
exports.default = Asset;
},{"./decorators":15,"./log":16,"axios":undefined,"blob-to-buffer":undefined,"fs-extra":undefined,"path":undefined,"stream":undefined,"url":undefined,"uuid":undefined}],2:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const log_1 = require("./log");
const log = log_1.default.createChild('Cache');
class Cache {
fetch(id, quietly = false) {
let node = undefined;
if (id in this) {
node = this[id];
}
else {
if (!quietly) {
log.warn('fetch id', id, 'not in cache');
}
}
return node;
}
add(node, quietly = false) {
if (node && node._id) {
this._add(node._id, node, quietly);
}
else {
log.error('add: can not add invalid object', node);
}
}
remove(idOrNode, quietly = false) {
let id = this._toId(idOrNode);
if (id) {
if (id in this) {
delete this[id];
}
else {
if (!quietly) {
log.warn('remove: id not in cache', id);
}
}
}
else {
log.error('remove: invalid idOrNode', idOrNode);
}
}
isPresent(idOrNode) {
let id = this._toId(idOrNode);
if (!id) {
log.error('isPresent: invalid idOrNode', idOrNode);
}
return (id in this);
}
interceptLoad(id, callback, load) {
let node = this.fetch(id, true);
if (node) {
setImmediate(() => {
callback(null, node);
});
}
else {
load(id, (err, loadedNode) => {
if (!err) {
if (loadedNode) {
this.add(loadedNode);
}
else {
this._add(id, null);
}
}
callback(err, loadedNode);
});
}
}
_add(_id, value, quietly = false) {
if (!(_id in this)) {
this[_id] = value;
}
else if (this[_id] === null) {
this[_id] = value;
}
else {
if (Object.is(value, this[_id])) {
if (!quietly) {
log.warn('add: there was already an entry in the cache for node id', _id);
}
}
else {
log.warn('add: existing entry for node id', _id, 'and new object does not match it!');
this[_id] = value;
}
}
}
_toId(idOrNode) {
if (typeof idOrNode === 'object') {
idOrNode = idOrNode._id;
}
return idOrNode;
}
}
exports.default = Cache;
},{"./log":16}],3:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Collection = require("nedb");
const log_1 = require("./log");
const log = log_1.default.createChild('Database');
class Database {
constructor(filename) {
this.filename = filename;
}
init(callback) {
this.nodes = new Collection({ filename: this.filename });
this.nodes.loadDatabase((err) => {
log.iferr(err, 'Collection#loadDatabase for nodes', this.filename);
if (!err) {
this.nodes.count({}, (err, count) => {
log.iferr(err, 'error counting nodes in', this.filename);
if (!err) {
log.info(count, 'KB node' + ((count === 1) ? '' : 's') + ' in', this.filename);
}
callback(err, count);
});
}
else {
callback(err);
}
});
}
load(id, callback) {
this.nodes.findOne({ _id: id }, (err, node) => {
log.iferr(err, 'Database#findOne of', id, 'on', this.filename);
callback(err, node);
});
}
loadList(ids, callback) {
this.nodes.find({ _id: { $in: ids } }, (err, nodes) => {
log.iferr(err, 'Database#find of _id $in ', ids, 'on', this.filename);
callback(err, nodes);
});
}
loadNodeOfType(nodeType, callback) {
this.nodes.findOne({ type: nodeType }, (err, node) => {
log.iferr(err, 'Database#findOne of type', nodeType, 'on', this.filename);
callback(err, node);
});
}
loadNodesOfType(nodeType, callback) {
let q = { type: nodeType };
this.nodes.find(q).exec((err, nodes) => {
log.iferr(err, 'Collection#find error');
callback(err, nodes);
});
}
save(node, callback) {
if (!node._id) {
throw new Error('node does not have an id');
}
this.nodes.update({ _id: node._id }, node, { upsert: true }, (err, numReplaced) => {
log.iferr(err, 'Collection#update error', this.filename);
if (err) {
node._id = undefined;
}
if (callback) {
callback(err, node);
}
});
}
remove(idOrNode, callback) {
let id = this._toId(idOrNode);
this.nodes.remove({ _id: id }, {}, (err, numRemoved) => {
log.iferr(err, 'Database#remove of', id, 'on', this.filename);
if (callback) {
callback(err, numRemoved);
}
});
}
_toId(idOrNode) {
if (typeof idOrNode === 'object') {
idOrNode = idOrNode._id;
}
return idOrNode;
}
}
exports.default = Database;
},{"./log":16,"nedb":undefined}],4:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const fsExtra = require("fs-extra");
const KnowledgeDatabase_1 = require("./KnowledgeDatabase");
const log_1 = require("./log");
const log = log_1.default.createChild('DatabaseManager');
class DatabaseManager {
static get(kbName, callback) {
let database = this.databases[kbName];
if (database) {
setImmediate(() => {
callback(null, database);
});
}
else {
this.exists(kbName, (err, exists) => {
if (err || !exists) {
callback(new Error('KB slice ' + kbName + ' does not exist, create it first'));
}
else {
database = new KnowledgeDatabase_1.default(kbName);
this.databases[kbName] = database;
database.init((err) => {
log.iferr(err, 'KnowledgeDatabase.init');
if (!err) {
callback(null, database);
}
else {
callback(err);
}
});
}
});
}
}
static exists(kbName, callback) {
const dbFilename = KnowledgeDatabase_1.default.getKbFilename(kbName);
fs.access(dbFilename, (err) => {
let exists = !err;
callback(null, exists);
});
}
get databases() {
return DatabaseManager.databases;
}
create(kbName, callback) {
if (this.databases[kbName]) {
setImmediate(() => {
callback(null, false);
});
}
else {
const dbDirectory = KnowledgeDatabase_1.default.getKbDirectory(kbName);
fsExtra.ensureDir(dbDirectory, (err) => {
if (err) {
callback(err);
}
else {
const dbFilename = KnowledgeDatabase_1.default.getKbFilename(kbName);
fs.open(dbFilename, 'ax', (err, fd) => {
let created = false;
if (err) {
if (err && err.code === 'EEXIST') {
err = null;
created = false;
}
}
else {
fs.close(fd);
created = true;
}
callback(err, created);
});
}
});
}
}
exists(kbName, callback) {
DatabaseManager.exists(kbName, callback);
}
get(kbName, callback) {
DatabaseManager.get(kbName, callback);
}
release(kbName) {
delete this.databases[kbName];
}
}
DatabaseManager.databases = {};
exports.DatabaseManager = DatabaseManager;
exports.default = DatabaseManager;
},{"./KnowledgeDatabase":6,"./log":16,"fs":undefined,"fs-extra":undefined}],5:[function(require,module,exports){
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const querystring = require("querystring");
const decorators_1 = require("./decorators");
const Model_1 = require("./Model");
const KnowledgeDatabase_1 = require("./KnowledgeDatabase");
const Node_1 = require("./Node");
const Asset_1 = require("./Asset");
const DatabaseManager_1 = require("./DatabaseManager");
const LoopModel_1 = require("./LoopModel");
const UserNode_1 = require("./UserNode");
const RobotModel_1 = require("./RobotModel");
const RobotRootNode_1 = require("./RobotRootNode");
const log_1 = require("./log");
const log = log_1.default.createChild('KnowledgeBase');
class KnowledgeBase {
constructor() {
this.Asset = Asset_1.default;
this.KnowledgeDatabase = KnowledgeDatabase_1.default;
this.Model = Model_1.default;
this.Node = Node_1.default;
this.databaseManager = new DatabaseManager_1.default();
this.onInitCallbacks = [];
this.registerModelClass('jibo/loop', LoopModel_1.default);
this.registerNodeClass('user', UserNode_1.default, 'jibo/loop');
this.registerModelClass('jibo/robot', RobotModel_1.default);
this.registerNodeClass('root', RobotRootNode_1.default, 'jibo/robot');
}
static _processError(err) {
if (err.response) {
let description = `HTTP Error Code ${err.response.status}`;
if (err.response.data) {
description += err.response.data;
}
return new Error(description);
}
else {
return new Error(err.request
? 'No response received'
: 'Unknown error');
}
}
init(service, callback) {
this.httpUrl = 'http://' + service.host + ':' + service.port;
process.nextTick(callback);
this.onInitCallbacks.forEach((onInitCallback) => {
process.nextTick(onInitCallback);
});
this.onInitCallbacks = [];
this.robot = this.createModel('/jibo/robot');
}
onInit(callback) {
if (!this.httpUrl) {
this.onInitCallbacks.push(callback);
}
else {
process.nextTick(() => {
callback(null);
});
}
}
initLoop() {
let loop = this.createModel('/jibo/loop');
this.loop = loop;
}
initMedia() {
return;
}
createSlice(sliceName, httpUrl, callback) {
if (typeof httpUrl === 'function' && !callback) {
callback = httpUrl;
httpUrl = null;
}
httpUrl = httpUrl || this.httpUrl;
let escapedName = querystring.escape(sliceName);
let url = `${this.httpUrl}/v1/kb/${escapedName}/create`;
axios_1.default.post(url).then(res => {
let created = res.data && res.data.created;
if (callback) {
callback(null, created);
}
}, (err) => {
log.error('axios.post', url, err.message);
if (callback) {
callback(KnowledgeBase._processError(err));
}
});
}
existsSlice(sliceName, httpUrl, callback) {
if (typeof httpUrl === 'function' && !callback) {
callback = httpUrl;
httpUrl = null;
}
httpUrl = httpUrl || this.httpUrl;
let escapedName = querystring.escape(sliceName);
let url = `${this.httpUrl}/v1/kb/${escapedName}/exists`;
axios_1.default.get(url).then(res => {
let exists = res.data && res.data.exists;
if (callback) {
callback(null, exists);
}
}, (err) => {
log.error('axios.get', url, err);
if (callback) {
callback(KnowledgeBase._processError(err));
}
});
}
createModel(kbNames, httpUrl) {
httpUrl = httpUrl || this.httpUrl;
if (!httpUrl) {
throw new Error('Knowledge Base has not been inited');
}
let newKBNames = [];
this._toArray(kbNames).forEach((kbName) => {
if (!kbName.startsWith('/')) {
throw new Error('kb#createModel: kb names must be rooted (must start with /)');
}
else {
kbName = kbName.substr(1);
}
newKBNames.push(kbName);
});
let ModelClass = this.findModelClass(newKBNames);
return new ModelClass(newKBNames, httpUrl);
}
registerNodeClass(nodeType, classConstructor, kbName = '*') {
Node_1.default.registerNodeClass(nodeType, classConstructor, kbName);
}
registerModelClass(kbNames, classConstructor) {
Model_1.default.registerModelClass(kbNames, classConstructor);
}
findNodeClass(nodeType, kbName) {
return Node_1.default.findNodeClass(nodeType, kbName);
}
findModelClass(kbNames) {
return Model_1.default.findModelClass(kbNames);
}
removeSlice(sliceName, callback) {
let escapedName = querystring.escape(sliceName);
let url = `${this.httpUrl}/v1/kb/${escapedName}/remove/yesiamsure`;
axios_1.default.delete(url).then(res => {
if (callback) {
callback(null);
}
}, (err) => {
log.error('axios.del', url, err);
if (callback) {
callback(KnowledgeBase._processError(err));
}
});
}
removeAll(callback) {
let url = `${this.httpUrl}/v1/removeall/yesiamsure`;
axios_1.default.delete(url).then(res => {
if (callback) {
callback(null);
}
}, (err) => {
log.error('axios.del', url, err);
if (callback) {
callback(KnowledgeBase._processError(err));
}
});
}
_toArray(items) {
if (!Array.isArray(items)) {
return [items];
}
else {
return items;
}
}
}
__decorate([
decorators_1.promisify
], KnowledgeBase.prototype, "onInit", null);
__decorate([
decorators_1.promisify
], KnowledgeBase.prototype, "createSlice", null);
__decorate([
decorators_1.promisify
], KnowledgeBase.prototype, "existsSlice", null);
__decorate([
decorators_1.promisify
], KnowledgeBase.prototype, "removeSlice", null);
__decorate([
decorators_1.promisify
], KnowledgeBase.prototype, "removeAll", null);
exports.default = KnowledgeBase;
},{"./Asset":1,"./DatabaseManager":4,"./KnowledgeDatabase":6,"./LoopModel":7,"./Model":8,"./Node":9,"./RobotModel":10,"./RobotRootNode":12,"./UserNode":13,"./decorators":15,"./log":16,"axios":undefined,"querystring":undefined}],6:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs-extra");
const path = require("path");
const Database_1 = require("./Database");
const Node_1 = require("./Node");
const log_1 = require("./log");
const log = log_1.default.createChild('KnowledgeDatabase');
const reservedNames = ['nodes', 'assets'];
const RunMode = {
SIMULATOR: "SIMULATOR",
REMOTELY: "REMOTELY",
ON_ROBOT: "ON_ROBOT",
UNIT_TESTS: "UNIT_TESTS"
};
class KnowledgeDatabase {
constructor(kbName) {
this.kbName = kbName;
KnowledgeDatabase._validateKbName(kbName);
this.dbDirectory = KnowledgeDatabase.getKbDirectory(this.kbName);
this.dbFilename = KnowledgeDatabase.getKbFilename(this.kbName);
}
static getRootDirectory() {
if (this._onRobot()) {
return '/opt/jibo/Knowledge';
}
else {
return path.join(process.env.HOME || process.env.USERPROFILE, '.jibo', 'kb');
}
}
static getKbDirectory(kbName) {
KnowledgeDatabase._validateKbName(kbName);
let rootDirectory = KnowledgeDatabase.getRootDirectory();
return path.join(rootDirectory, kbName);
}
static getKbFilename(kbName) {
KnowledgeDatabase._validateKbName(kbName);
const dbDirectory = KnowledgeDatabase.getKbDirectory(kbName);
return path.join(dbDirectory, 'nodes');
}
static _validateKbName(kbName) {
if (kbName.length > 200) {
throw new Error('kb name is too long');
}
if (/[^a-z0-9\/_-]/.test(kbName)) {
throw new Error('illegal character in kb name');
}
if (kbName.endsWith('/')) {
throw new Error('kb name ends with a slash');
}
let parts = kbName.split('/');
if (parts.length > 10) {
throw new Error('kb name has too many sub directories');
}
parts.forEach((part, n) => {
if (part.length === 0 && n !== 0) {
throw new Error('kb name component is empty');
}
if (part.length > 75) {
throw new Error('kb name component is too long');
}
if (/^[^a-z0-9]/.test(part)) {
throw new Error('kb names must start with an alphanumeric character');
}
if (reservedNames.indexOf(part) >= 0) {
throw new Error('kb name is reserved word');
}
});
}
static _onRobot() {
let runMode = process.env.runMode || process.env.RUNMODE;
if (!runMode && process.platform === 'linux' && process.arch === 'arm') {
runMode = RunMode.ON_ROBOT;
}
return (runMode === RunMode.ON_ROBOT);
}
init(callback) {
this._setupDirectory((err) => {
log.iferr(err, 'KnowledgeDatabase#_setupDirectory');
if (!err) {
this.database = new Database_1.default(this.dbFilename);
this.database.init((err, nodeCount) => {
log.iferr(err, 'Database#init');
if (!err) {
if (nodeCount === 0) {
log.info('creating root node for', this.kbName);
let NodeClass = Node_1.default.findNodeClass('root', this.kbName);
let rootNode = new NodeClass('root');
this.adoptNodeAsOurOwn(rootNode);
rootNode.save((err) => {
log.iferr(err, 'error creating initial root node for', this.kbName);
callback(err);
});
}
else {
callback(err);
}
}
else {
callback(err);
}
});
}
});
}
load(id, callback) {
this.database.load(id, (err, data) => {
if (!err) {
let node = null;
if (data) {
node = this.createNodeFromObject(data);
}
callback(null, node);
}
else {
callback(err);
}
});
}
loadList(ids, callback) {
this.database.loadList(ids, (err, data) => {
if (!err) {
let nodes = [];
if (data) {
const resultsMap = {};
data.forEach(node => {
if (node) {
resultsMap[node._id] =
this.createNodeFromObject(node);
}
});
nodes = ids.map(id => resultsMap[id] || null);
}
callback(null, nodes);
}
else {
callback(err);
}
});
}
loadRoot(callback) {
this.database.loadNodeOfType('root', (err, data) => {
log.iferr(err, 'Database#loadNodeOfType');
let node;
if (!err && data) {
node = this.createNodeFromObject(data);
}
callback(err, node);
});
}
save(node, callback) {
node.setUpdated();
this.database.save(node, (err) => {
if (callback) {
callback(err);
}
});
}
remove(idOrNode, callback) {
let id = this.toId(idOrNode);
this.database.remove(id, callback);
}
createNodeFromObject(object) {
let nodeType = object.type || 'node';
let NodeClass = Node_1.default.findNodeClass(nodeType, this.kbName);
let node = new NodeClass(null, null, object);
this.adoptNodeAsOurOwn(node);
return node;
}
createNode(nodeTypeOrClass, data) {
let NodeClass;
let nodeType;
if (typeof nodeTypeOrClass === 'function') {
NodeClass = nodeTypeOrClass;
}
else {
nodeType = nodeTypeOrClass;
NodeClass = Node_1.default.findNodeClass(nodeType, this.kbName);
if (nodeType === 'root') {
throw new Error('can not create additional root nodes');
}
}
let node;
if (nodeType && NodeClass === Node_1.default) {
node = new NodeClass(nodeType, data);
}
else {
node = new NodeClass(data);
}
this.adoptNodeAsOurOwn(node);
return node;
}
adoptNodeAsOurOwn(node) {
node.setKb(this);
}
getDirectory() {
return this.dbDirectory;
}
toId(idOrNode) {
if (typeof idOrNode === 'object') {
idOrNode = idOrNode._id;
}
return idOrNode;
}
_setupDirectory(callback) {
fs.ensureDir(this.dbDirectory, callback);
}
}
exports.default = KnowledgeDatabase;
},{"./Database":3,"./Node":9,"./log":16,"fs-extra":undefined,"path":undefined}],7:[function(require,module,exports){
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const jibo_client_framework_1 = require("jibo-client-framework");
const jibo_typed_events_1 = require("jibo-typed-events");
const decorators_1 = require("./decorators");
const Model_1 = require("./Model");
const log_1 = require("./log");
const log = log_1.default.createChild('LoopModel');
class LoopModelEvents extends jibo_typed_events_1.EventContainer {
constructor() {
super(...arguments);
this.loopUpdated = new jibo_typed_events_1.Event('Loop has been updated');
}
}
exports.LoopModelEvents = LoopModelEvents;
class LoopModel extends Model_1.default {
constructor(kbNames, httpUrl = null) {
super(kbNames, httpUrl);
this.events = new LoopModelEvents();
this._listenForWSMessages();
}
static _processError(err) {
if (err.response) {
let description = `HTTP Error Code ${err.response.status}`;
if (err.response.data) {
description += err.response.data;
}
return new Error(description);
}
else {
return new Error(err.request
? 'No response received'
: 'Unknown error');
}
}
loadLoop(callback) {
this.loadLoopAll((err, loop) => {
if (!err) {
callback(null, this._notDeclinedOrRemoved(loop));
}
else {
callback(err);
}
});
}
loadLoopInvited(callback) {
this.loadLoop(callback);
}
loadLoopActive(callback) {
this.loadLoop(callback);
}
loadLoopAll(callback) {
this.loadRoot(null, (err, rootNode) => {
log.iferr(err, 'loadRoot');
if (!err && rootNode) {
let userIds = rootNode.getEdges('user');
this.load(userIds, (err, nodes) => {
log.iferr(err, 'load');
callback(err, nodes);
});
}
else {
callback(err);
}
});
}
getUserNodeById(id, callback) {
this.loadLoop((err, loop) => {
if (err) {
return callback(err);
}
let user = loop.find((node) => {
return node.id === id;
});
if (user) {
callback(null, user);
}
else {
callback(new Error('Could not find user node for loop id ' + id));
}
});
}
getWrittenNameById(id, callback) {
this.getUserNodeById(id, (error, user) => {
if (error) {
return callback(error);
}
callback(null, user.getWrittenName());
});
}
getSpokenNameById(id, callback) {
this.getUserNodeById(id, (error, user) => {
if (error) {
return callback(error);
}
callback(null, user.toString());
});
}
fetchLoop() {
return this._onlyAccepted(this.fetchLoopAll());
}
fetchLoopInvited() {
return this.fetchLoop();
}
fetchLoopActive() {
return this.fetchLoop();
}
fetchLoopAll() {
return this.fetch(this.fetchRoot().getEdges('user'));
}
setPhoneticName(idOrNode, phoneticName, callback) {
let memberId = (typeof idOrNode === 'object') ? idOrNode._id : idOrNode;
let url = `${this.httpUrl}/v1/loop/updatePhoneticName`;
this.loadRoot((err, root) => {
log.iferr(err, 'loadRoot');
let params = {
loopId: root.data.id,
id: memberId,
phoneticName: phoneticName
};
axios_1.default.post(url, params).then(res => callback(null), (err) => {
log.error('axios.post', url, err);
callback(LoopModel._processError(err));
});
});
}
setEnrollmentFace(idOrNode, face, callback) {
let memberId = (typeof idOrNode === 'object') ? idOrNode._id : idOrNode;
let params = {
id: memberId,
face: !!face
};
this.setEnrollment(params, callback);
}
setEnrollmentVoice(idOrNode, voice, callback) {
let memberId = (typeof idOrNode === 'object') ? idOrNode._id : idOrNode;
let params = {
id: memberId,
voice: !!voice
};
this.setEnrollment(params, callback);
}
setEnrollment(params, callback) {
let url = `${this.httpUrl}/v1/loop/enrollment`;
this.loadRoot((err, root) => {
log.iferr(err, 'loadRoot');
params.loopId = root.data.id;
axios_1.default.post(url, params).then(res => {
if (callback) {
callback(null);
}
}, (err) => {
log.error('axios.post', url, err);
if (callback) {
callback(LoopModel._processError(err));
}
});
});
}
suspend(callback) {
let url = `${this.httpUrl}/v1/loop/suspend`;
this.loadRoot((err, root) => {
log.iferr(err, 'loadRoot');
let params = {
loopId: root.data.id
};
axios_1.default.post(url, params).then(res => {
if (callback) {
callback(null);
}
}, (err) => {
log.error('axios.post', url, err);
if (callback) {
callback(LoopModel._processError(err));
}
});
});
}
hasKeyBackup(callback) {
this.loadRoot((err, root) => {
log.iferr(err, 'loadRoot');
let loopId = root.data.id;
let url = `${this.httpUrl}/v1/loop/hasKeyBackup/${loopId}`;
axios_1.default.get(url).then(res => {
let hasKeyBackup = !!(res.data && res.data.hasKeyBackup);
if (callback) {
callback(null, hasKeyBackup);
}
}, (err) => {
log.error('axios.get', url, err);
if (callback) {
callback(LoopModel._processError(err));
}
});
});
}
_notDeclinedOrRemoved(loop) {
loop.forEach(user => {
if (!user.data) {
log.error('loop entry with missing data', user._id);
}
});
return loop.filter(user => user.data && user.data.status !== 'declined' && user.data.status !== 'removed');
}
_onlyAccepted(loop) {
return loop.filter(user => user.data.status === 'accepted');
}
_listenForWSMessages() {
this._wsClient = new jibo_client_framework_1.WSClient(this.httpUrl);
this._wsClient.on('message', this._wsMessageReceived.bind(this));
}
_wsMessageReceived(message) {
switch (message) {
case 'LoopUpdated':
console.log('LoopModel: received LoopUpdated event; emitting LoopModelEvents.loopUpdate');
this.events.loopUpdated.emit();
break;
default:
console.warn('LoopModel: received unknown message from KBService', message);
}
}
}
__decorate([
decorators_1.promisify
], LoopModel.prototype, "loadLoop", null);
__decorate([
decorators_1.promisify,
decorators_1.deprecate('loadLoopInvited is no longer useful, use loadLoop() instead')
], LoopModel.prototype, "loadLoopInvited", null);
__decorate([
decorators_1.promisify,
decorators_1.deprecate('loadLoopActive is no longer useful, use loadLoop() instead')
], LoopModel.prototype, "loadLoopActive", null);
__decorate([
decorators_1.promisify
], LoopModel.prototype, "loadLoopAll", null);
__decorate([
decorators_1.promisify
], LoopModel.prototype, "getUserNodeById", null);
__decorate([
decorators_1.promisify
], LoopModel.prototype, "getWrittenNameById", null);
__decorate([
decorators_1.promisify
], LoopModel.prototype, "getSpokenNameById", null);
__decorate([
decorators_1.deprecate('no longer useful, use fetchLoop() instead')
], LoopModel.prototype, "fetchLoopInvited", null);
__decorate([
decorators_1.deprecate('no longer useful, use fetchLoop() instead')
], LoopModel.prototype, "fetchLoopActive", null);
__decorate([
decorators_1.promisify
], LoopModel.prototype, "setPhoneticName", null);
__decorate([
decorators_1.promisify
], LoopModel.prototype, "setEnrollmentFace", null);
__decorate([
decorators_1.promisify
], LoopModel.prototype, "setEnrollmentVoice", null);
__decorate([
decorators_1.promisify
], LoopModel.prototype, "setEnrollment", null);
__decorate([
decorators_1.promisify
], LoopModel.prototype, "suspend", null);
__decorate([
decorators_1.promisify
], LoopModel.prototype, "hasKeyBackup", null);
exports.default = LoopModel;
},{"./Model":8,"./decorators":15,"./log":16,"axios":undefined,"jibo-client-framework":undefined,"jibo-typed-events":undefined}],8:[function(require,module,exports){
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
const async = require("async");
const decorators_1 = require("./decorators");
const Cache_1 = require("./Cache");
const DatabaseManager_1 = require("./DatabaseManager");
const WebClient_1 = require("./WebClient");
const log_1 = require("./log");
const log = log_1.default.createChild('Model');
class Model {
constructor(kbNames, httpUrl = null) {
this.kbNames = this._toArray(kbNames);
this.httpUrl = httpUrl;
this.pool = [];
if (this.httpUrl) {
this.kbNames.forEach((kbName) => {
let knowledgeDatabase = new WebClient_1.default(kbName, this.httpUrl);
this.pool.push(knowledgeDatabase);
});
}
}
static registerModelClass(kbNames, classConstructor) {
if (!Array.isArray(kbNames)) {
kbNames = [kbNames];
}
let key = kbNames.join(';');
let registry = this.modelClassRegistry;
if (registry[key]) {
log.warn('registerModelClass: overwriting previous class registered for ', key);
}
registry[key] = classConstructor;
}
static findModelClass(kbNames) {
if (!Array.isArray(kbNames)) {
kbNames = [kbNames];
}
let key = kbNames.join(';');
let ModelClass = Model;
let registry = this.modelClassRegistry;
if (registry[key]) {
ModelClass = registry[key];
}
return ModelClass;
}
init(callback) {
if (this.httpUrl) {
setImmediate(callback);
}
else {
let tasks = [];
this.kbNames.forEach((kbName) => {
tasks.push((next) => {
DatabaseManager_1.default.get(kbName, next);
});
});
async.series(tasks, (err, results) => {
log.iferr(err, 'KnowledgeDatabase#init');
if (!err) {
this.pool = results;
}
callback(err);
});
}
}
createModel(kbNames, httpUrl = null) {
kbNames = this._toArray(kbNames);
httpUrl = httpUrl || this.httpUrl;
let defaultBaseName = this.kbNames[0];
let newKBNames = [];
kbNames.forEach((kbName) => {
if (!kbName.startsWith('/')) {
kbName = '/' + defaultBaseName + '/' + kbName;
}
newKBNames.push(kbName);
});
let ModelClass = Model.findModelClass(newKBNames);
return new ModelClass(newKBNames, httpUrl);
}
createNode(nodeType, data) {
let node = this.pool[0].createNode(nodeType, data);
if (this.cache) {
this.cache.add(node);
}
return node;
}
load(ids, callback) {
if (!Array.isArray(ids)) {
this._loadOne(ids, callback);
}
else {
this._loadArray(ids, callback);
}
}
loadList(ids, callback) {
throw new Error('kb.Model.loadList is an unsupported method, use kb.Model.load');
}
fetchList(ids, quietly = false) {
throw new Error('kb.Model.fetchList is an unsupported method, use kb.Model.fetch');
}
loadRoot(kbName, callback) {
if (typeof kbName === 'function' && !callback) {
callback = kbName;
kbName = null;
}
let knowledgeDatabase;
if (!kbName) {
knowledgeDatabase = this.pool[0];
}
else {
knowledgeDatabase = this._getKnowledgeDatabase(kbName);
}
if (!knowledgeDatabase) {
setImmediate(() => {
let err = new Error('loadRoot kb slice name ' + kbName + ' not found');
callback(err);
});
}
else {
if (this.cache) {
let rootNode = this.fetchRoot(kbName, true);
if (rootNode) {
setImmediate(() => {
callback(null, rootNode);
});
}
else {
knowledgeDatabase.loadRoot((err, loadedRootNode) => {
if (!err && loadedRootNode) {
this.roots[kbName] = loadedRootNode;
}
callback(err, loadedRootNode);
});
}
}
else {
knowledgeDatabase.loadRoot(callback);
}
}
}
loadLayers(node, layers, callback) {
let action = (eachNode, callback) => callback();
this.visitLayers(node, layers, action, callback);
}
saveLayers(node, layers, callback) {
let action = (eachNode, callback) => eachNode.save(callback);
this.visitLayers(node, layers, action, callback);
}
visitLayers(node, layers, action, callback) {
if (!node) {
return callback();
}
layers = this._toArray(layers);
let visited = {};
visited[node._id] = true;
let visitNodes = (idList, callback) => {
let tasks = [];
let queue = [];
idList.forEach((id) => {
if (!(id in visited)) {
visited[id] = true;
tasks.push((next) => {
this.load(id, (err, eachNode) => {
if (!err && eachNode) {
action(eachNode, (err) => {
eachNode.getEdges(layers).forEach((everyId) => {
if (!(everyId in visited)) {
queue.push(everyId);
}
});
next(err);
});
}
else {
next(err);
}
});
});
}
});
async.series(tasks, (err) => {
if (!err && queue.length) {
visitNodes(queue, callback);
}
else {
callback(err);
}
});
};
action(node, (err) => {
log.iferr(err, 'action on initial node failed');
if (!err) {
visitNodes(node.getEdges(layers), callback);
}
else {
callback(err);
}
});
}
begin() {
let ourConstructor = this.constructor;
let model = new ourConstructor(this.kbNames, this.httpUrl);
model.enableCache();
return model;
}
fetch(ids, quietly = false) {
this._assertCache();
if (!Array.isArray(ids)) {
return this.cache.fetch(ids, quietly);
}
else {
const list = [];
const notFoundIds = [];
ids.forEach((id) => {
const node = this.cache.fetch(id, true);
if (node || node === null) {
list.push(node);
}
else {
list.push(undefined);
notFoundIds.push(id);
}
});
if (notFoundIds.length && !quietly) {
log.warn('fetchList ids were not in cache, skipped', notFoundIds.join(', '));
}
return list;
}
}
fetchRoot(kbName, quietly = false) {
this._assertCache();
if (!kbName) {
kbName = this.pool[0].kbName;
}
let root = null;
if (this.roots[kbName]) {
root = this.roots[kbName];
}
else {
if (!quietly) {
log.warn('fetchRoot for name', kbName, 'root not in cache');
}
}
return root;
}
enableCache() {
this.cache = new Cache_1.default();
this.roots = {};
}
_load(id, callback) {
const tasks = [];
this.pool.forEach((knowledgeDatabase) => {
tasks.push((node, next) => {
if (!next) {
next = node;
node = null;
}
if (!node) {
knowledgeDatabase.load(id, (err, node) => {
next(err, node);
});
}
else {
next(null, node);
}
});
});
async.waterfall(tasks, callback);
}
_loadOne(id, callback) {
if (this.cache) {
this.cache.interceptLoad(id, callback, (missingId, cacheCallback) => {
this._load(missingId, cacheCallback);
});
}
else {
this._load(id, callback);
}
}
_loadArray(ids, callback) {
const nodes = new Map();
const remainingIDs = ids.slice(0);
if (this.cache) {
const fakeLoad = (id, callback) => setImmediate(() => callback(null, null));
ids.forEach(id => {
const addNode = (err, node) => {
if (node) {
nodes[id] = node;
remainingIDs.splice(remainingIDs.indexOf(id), 1);
}
};
this.cache.interceptLoad(id, addNode, fakeLoad);
});
}
function getNodes(slice, callback) {
slice.loadList(remainingIDs, callback);
}
async.map(this.pool, getNodes, (err, allSlicesResults) => {
allSlicesResults.forEach(nodesForSlice => {
nodesForSlice.forEach(node => {
if (node && !nodes[node._id]) {
nodes[node._id] = node;
if (this.cache) {
this.cache.add(node);
}
}
});
});
callback(null, ids.map(id => nodes[id] || null));
});
}
_getKnowledgeDatabase(kbName) {
let knowledgeDatabase;
for (let n = 0; n < this.pool.length; n++) {
if (kbName === this.pool[n].kbName) {
knowledgeDatabase = this.pool[n];
break;
}
}
return knowledgeDatabase;
}
_assertCache() {
if (!this.cache) {
throw new Error('fetch method called on a Model without a cache');
}
}
_toArray(items) {
if (!Array.isArray(items)) {
return [items];
}
else {
return items;
}
}
}
Model.modelClassRegistry = {};
__decorate([
decorators_1.promisify
], Model.prototype, "load", null);
__decorate([
decorators_1.promisify
], Model.prototype, "loadRoot", null);
__decorate([
decorators_1.promisify
], Model.prototype, "loadLayers", null);
__decorate([
decorators_1.promisify
], Model.prototype, "saveLayers", null);
__decorate([
decorators_1.promisify_4
], Model.prototype, "visitLayers", null);
exports.default = Model;
},{"./Cache":2,"./DatabaseManager":4,"./WebClient":14,"./decorators":15,"./log":16,"async":undefined}],9:[function(require,module,exports){
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
const _ = require("lodash/lodash.min");
const uuid = require("uuid");
const async = require("async");
const decorators_1 = require("./decorators");
const Asset_1 = require("./Asset");
const log_1 = require("./log");
const log = log_1.default.createChild('Node');
class Node {
constructor(nodeType, data, cloneFrom) {
if (cloneFrom) {
_.extend(this, cloneFrom);
}
this._id = this._id || uuid.v4();
this.data = data || this.data || {};
this.type = nodeType || this.type || 'node';
let timestamp = Number(new Date());
this.created = this.created || timestamp;
this.updated = this.updated || timestamp;
}
static registerNodeClass(nodeType, classConstructor, kbName = '*') {
let registry = Node.nodeClassRegistry;
if (registry[kbName] && registry[kbName][nodeType]) {
log.warn('registerNodeClass: overwriting previous class registered for type', nodeType);
}
if (!registry[kbName]) {
registry[kbName] = {};
}
registry[kbName][nodeType] = classConstructor;
}
static findNodeClass(nodeType, kbName) {
let NodeClass = Node;
let registry = Node.nodeClassRegistry;
if (registry[kbName] && registry[kbName][nodeType]) {
NodeClass = registry[kbName][nodeType];
}
else if (registry['*'] && registry['*'][nodeType]) {
NodeClass = registry['*'][nodeType];
}
return NodeClass;
}
save(callback) {
this.getKb().save(this, callback);
}
remove(callback) {
this.getKb().remove(this, callback);
}
addEdges(idsOrNodes, layer) {
this.edges = this.edges || {};
this._toArray(idsOrNodes).forEach((idOrNode) => {
const { id, l } = this._resolveIdAndLayer(idOrNode, layer, 'Node#addEdges()');
this.edges[l] = this.edges[l] || [];
this.edges[l].push(id);
});
}
removeEdges(idsOrNodes, layer) {
if (this.edges) {
this._toArray(idsOrNodes).forEach((idOrNode) => {
let { id, l } = this._resolveIdAndLayer(idOrNode, layer, 'Node#removeEdges()');
if (this.edges[l]) {
_.pull(this.edges[l], id);
}
});
}
}
clearEdges(layers) {
if (this.edges) {
this._toArray(layers).forEach((layer) => {
if (this.edges[layer]) {
this.edges[layer] = [];
}
});
}
}
getEdges(layers) {
let edges = [];
this._toArray(layers).forEach((layer) => {
let theseEdges = _.get(this, 'edges.' + layer, []);
theseEdges.forEach((thisEdge) => {
if (edges.indexOf(thisEdge) < 0) {
edges.push(thisEdge);
}
});
});
return edges;
}
getLayers() {
if (this.edges) {
return Object.keys(this.edges);
}
else {
return [];
}
}
createAsset(subtype, ext) {
let asset = new Asset_1.default(null, subtype, ext);
if (this.getKb) {
let rootDir = this.getKb().getDirectory();
asset.setRootDir(rootDir);
}
else {
log.warn('createAsset: creating an asset from a node without a kb, rootDir not set');
}
this.addAssets(asset);
return asset;
}
addAssets(assets, subtype) {
this.assets = this.assets || {};
this._toArray(assets).forEach((asset) => {
let st = subtype || asset.subtype;
this.assets[st] = this.assets[st] || [];
this.assets[st].push(asset.filename());
});
}
getAssets(subtype = 'asset') {
let assets = [];
if (this.assets && this.assets[subtype]) {
let assetFilenames = this.assets[subtype];
let rootDir = this.getKb().getDirectory();
assetFilenames.forEach((filename) => {
let asset = new Asset_1.default(filename);
asset.setRootDir(rootDir);
assets.push(asset);
});
}
return assets;
}
getAllAssets() {
let assets = [];
let subtypes = this.getAssetSubtypes();
subtypes.forEach((subtype) => {
assets = assets.concat(this.getAssets(subtype));
});
return assets;
}
getAssetSubtypes() {
let subtypes = _.keys(this.assets);
return subtypes;
}
removeAsset(asset, callback) {
let st = asset.subtype;
let assetIndex = this.assets[st].indexOf(asset.filename());
this.assets[st].splice(assetIndex, 1);
asset.remove(callback);
}
removeAllAssets(callback) {
let subtypes = this.getAssetSubtypes();
let tasks = [];
subtypes.forEach((subtype) => {
let assets = this.getAssets(subtype);
assets.forEach((asset) => {
tasks.push((next) => {
this.removeAsset(asset, next);
});
});
});
async.series(tasks, callback);
}
setKb(knowledgeDatabase) {
this.getKb = () => { return knowledgeDatabase; };
return this;
}
setUpdated(timestamp) {
this.updated = timestamp || Number(new Date());
}
_resolveIdAndLayer(idOrNode, layer, methodName) {
let id;
let l;
if (typeof idOrNode === 'string') {
id = idOrNode;
if (!layer) {
throw Error(`${methodName}: must specify layer when supplying ids`);
}
l = layer;
}
else {
let node = idOrNode;
id = node._id;
l = layer || node.type;
}
return { id, l };
}
_toArray(items) {
if (!Array.isArray(items)) {
return [items];
}
else {
return items;
}
}
}
Node.nodeClassRegistry = {};
__decorate([
decorators_1.promisify
], Node.prototype, "save", null);
__decorate([
decorators_1.promisify
], Node.prototype, "remove", null);
__decorate([
decorators_1.promisify
], Node.prototype, "removeAsset", null);
__decorate([
decorators_1.promisify
], Node.prototype, "removeAllAssets", null);
exports.default = Node;
},{"./Asset":1,"./decorators":15,"./log":16,"async":undefined,"lodash/lodash.min":undefined,"uuid":undefined}],10:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Model_1 = require("./Model");
const RobotModelEvents_1 = require("./RobotModelEvents");
const jibo_client_framework_1 = require("jibo-client-framework");
class RobotModel extends Model_1.default {
constructor(kbNames, httpUrl = null) {
super(kbNames, httpUrl);
this.events = new RobotModelEvents_1.default();
this._listenForWSMessages();
}
_listenForWSMessages() {
this._wsClient = new jibo_client_framework_1.WSClient(this.httpUrl);
this._wsClient.on('message', this._wsMessageReceived.bind(this));
}
_wsMessageReceived(message) {
switch (message) {
case 'RobotUpdated':
console.log('RobotModel: received RobotUpdated event; emitting RobotModelEvents.robotUpdate');
this.events.robotUpdated.emit();
break;
default:
console.warn('RobotModel: received unknown message from KBService', message);
}
}
}
exports.default = RobotModel;
},{"./Model":8,"./RobotModelEvents":11,"jibo-client-framework":undefined}],11:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jibo_typed_events_1 = require("jibo-typed-events");
class RobotModelEvents extends jibo_typed_events_1.EventContainer {
constructor() {
super(...arguments);
this.robotUpdated = new jibo_typed_events_1.Event('Robot properties have updated');
}
}
exports.default = RobotModelEvents;
},{"jibo-typed-events":undefined}],12:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Node_1 = require("./Node");
class RobotRootNode extends Node_1.default {
get locationOverride() {
return this.data.locationOverride;
}
}
exports.default = RobotRootNode;
},{"./Node":9}],13:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Node_1 = require("./Node");
class UserNode extends Node_1.default {
get id() {
return this._id;
}
get firstName() {
return this.data.firstName;
}
get lastName() {
return this.data.lastName;
}
get nickName() {
return this.data.nickName;
}
get gender() {
return this.data.gender;
}
get isJibo() {
return !this.data.firstName;
}
getWrittenName() {
return this.data.nickName || this.data.firstName || 'Jibo';
}
toString() {
if (this.data.phoneticName) {
return this.data.phoneticName.replace(/\s+(?=[^>]*\<)/g, '');
}
return this.getWrittenName();
}
getInitials() {
if (this.isJibo) {
return 'J';
}
if (!this.data.firstName || !this.data.lastName) {
return '';
}
return this.data.firstName.charAt(0).toUpperCase() +
this.data.lastName.charAt(0).toUpperCase();
}
toLog() {
return `[UserNode id:${this._id}]`;
}
}
exports.default = UserNode;
},{"./Node":9}],14:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const async = require("async");
const axios_1 = require("axios");
const querystring = require("querystring");
const KnowledgeDatabase_1 = require("./KnowledgeDatabase");
const log_1 = require("./log");
const log = log_1.default.createChild('WebClient');
class WebClient extends KnowledgeDatabase_1.default {
static _processError(err) {
if (err.response) {
let description = `HTTP Error Code ${err.response.status}`;
if (err.response.data) {
description += err.response.data;
}
return new Error(description);
}
else {
return new Error(err.request
? 'No response received'
: 'Unknown error');
}
}
constructor(kbName, httpUrl) {
super(kbName);
this.httpUrl = httpUrl.replace(/\/$/, '');
}
init(callback) {
setImmediate(callback);
}
load(id, callback) {
let url = this._makeUrl(`/node/load/${id}`);
axios_1.default.get(url).then(res => {
const node = res.data
? this.createNodeFromObject(res.data)
: null;
callback(null, node);
}, (err) => {
log.error('axios.get', url, err);
callback(WebClient._processError(err));
});
}
loadList(ids, callback) {
let url = this._makeUrl(`/node/load`);
axios_1.default.post(url, ids).then(res => {
const nodes = res.data
? res.data.map(node => node ? this.createNodeFromObject(node) : null)
: null;
callback(null, nodes);
}, (err) => {
if (err.response && err.response.status === 400) {
log.warn('Deprecation warning: jibo-kb will soon drop support for legacy SSM without /node/load POST endpoint.');
async.map(ids, this.load.bind(this), callback);
}
else {
log.error('axios.post', url, err);
callback(WebClient._processError(err));
}
});
}
loadRoot(callback) {
let url = this._makeUrl(`/node/loadRoot`);
axios_1.default.get(url).then(res => {
const node = res.data
? this.createNodeFromObject(res.data)
: null;
callback(null, node);
}, (err) => {
log.error('axios.get', url, err);
callback(WebClient._processError(err));
});
}
save(node, callback) {
let url = this._makeUrl(`/node/save`);
axios_1.default.post(url, node).then(res => {
if (callback) {
callback(null);
}
}, (err) => {
log.error('axios.post', url, err);
if (callback) {
callback(WebClient._processError(err));
}
});
}
remove(idOrNode, callback) {
let id = this.toId(idOrNode);
let url = this._makeUrl(`/node/remove/${id}`);
axios_1.default.delete(url).then(res => {
callback(null);
}, (err) => {
log.error('axios.delete', url, err);
callback(WebClient._processError(err));
});
}
getDirectory() {
return this._makeUrl();
}
_makeUrl(addPath = '') {
let escapedName = querystring.escape(this.kbName);
return `${this.httpUrl}/v1/kb/${escapedName}` + addPath;
}
}
exports.default = WebClient;
},{"./KnowledgeDatabase":6,"./log":16,"async":undefined,"axios":undefined,"querystring":undefined}],15:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function promisify(target, propertyKey, descriptor) {
let originalMethod = descriptor.value;
descriptor.value = function () {
let result;
let args = Array.from(arguments);
let lastArg = args.slice(-1)[0];
if (typeof lastArg === 'function') {
result = originalMethod.apply(this, args);
}
else {
result = new Promise((resolve, reject) => {
let callback = function (err, arg) {
if (err) {
reject(err);
}
else {
resolve(arg);
}
};
let newArgs = args.concat(callback);
originalMethod.apply(this, newArgs);
});
}
return result;
};
return descriptor;
}
exports.promisify = promisify;
function promisify_4(target, propertyKey, descriptor) {
let originalMethod = descriptor.value;
descriptor.value = function () {
let result;
let args = Array.from(arguments);
let fourthArg = args[4];
if (typeof fourthArg === 'function') {
result = originalMethod.apply(this, args);
}
else {
let originalThis = this;
result = new Promise((resolve, reject) => {
let callback = function (err, arg) {
if (err) {
reject(err);
}
else {
resolve(arg);
}
};
let newArgs = args.concat(callback);
originalMethod.apply(originalThis, newArgs);
});
}
return result;
};
return descriptor;
}
exports.promisify_4 = promisify_4;
function deprecate(msg) {
msg = msg === undefined ? '' : msg;
function warn() {
let stack = new Error().stack;
stack = stack.split('\n').splice(4).join('\n');
if (console.groupCollapsed) {
console.groupCollapsed("%cDeprecation Warning: %c%s", "color:#614108;background:#fffbe6", "font-weight:normal;color:#614108;background:#fffbe6", msg);
console.warn(stack);
console.groupEnd();
}
else {
console.warn("Deprecation Warning:", msg);
console.warn(stack);
}
}
function doDeprecate(target, propertyKey, descriptor) {
let originalMethod = descriptor.value;
descriptor.value = function () {
warn();
return originalMethod.apply(this, arguments);
};
return descriptor;
}
return doDeprecate;
}
exports.deprecate = deprecate;
},{}],16:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const jibo_log_1 = require("jibo-log");
exports.default = new jibo_log_1.Log('Jibo.KB');
},{"jibo-log":undefined}],17:[function(require,module,exports){
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
__export(require("./KnowledgeBase"));
var Asset_1 = require("./Asset");
exports.Asset = Asset_1.default;
var Cache_1 = require("./Cache");
exports.Cache = Cache_1.default;
var Database_1 = require("./Database");
exports.Database = Database_1.default;
var DatabaseManager_1 = require("./DatabaseManager");
exports.DatabaseManager = DatabaseManager_1.default;
var KnowledgeBase_1 = require("./KnowledgeBase");
exports.KnowledgeBase = KnowledgeBase_1.default;
var KnowledgeDatabase_1 = require("./KnowledgeDatabase");
exports.KnowledgeDatabase = KnowledgeDatabase_1.default;
var LoopModel_1 = require("./LoopModel");
exports.LoopModel = LoopModel_1.default;
var RobotModel_1 = require("./RobotModel");
exports.RobotModel = RobotModel_1.default;
var Model_1 = require("./Model");
exports.Model = Model_1.default;
var Node_1 = require("./Node");
exports.Node = Node_1.default;
var UserNode_1 = require("./UserNode");
exports.UserNode = UserNode_1.default;
var RobotRootNode_1 = require("./RobotRootNode");
exports.RobotRootNode = RobotRootNode_1.default;
var WebClient_1 = require("./WebClient");
exports.WebClient = WebClient_1.default;
},{"./Asset":1,"./Cache":2,"./Database":3,"./DatabaseManager":4,"./KnowledgeBase":5,"./KnowledgeDatabase":6,"./LoopModel":7,"./Model":8,"./Node":9,"./RobotModel":10,"./RobotRootNode":12,"./UserNode":13,"./WebClient":14}]},{},[17])(17)
});
//# sourceMappingURL=jibo-kb.js.map