Skip to content

Commit

Permalink
feat: Support modules
Browse files Browse the repository at this point in the history
  • Loading branch information
Michel Blancard committed Mar 12, 2018
1 parent 5755bd5 commit ecab4eb
Show file tree
Hide file tree
Showing 22 changed files with 495 additions and 50 deletions.
7 changes: 0 additions & 7 deletions packages/botfuel-dialog/src/adapter-resolver.js
Expand Up @@ -14,7 +14,6 @@
* limitations under the License.
*/

const logger = require('logtown')('AdapterResolver');
const Resolver = require('./resolver');

/**
Expand All @@ -30,12 +29,6 @@ class AdapterResolver extends Resolver {
this.bot = bot;
}

/** @inheritdoc */
getPaths(name) {
logger.debug('getPaths', name);
return [`${this.botPath}/${name}-${this.kind}.js`, `${this.sdkPath}/${name}-${this.kind}.js`];
}

/** @inheritdoc */
resolutionSucceeded(Resolved) {
return new Resolved(this.bot);
Expand Down
7 changes: 0 additions & 7 deletions packages/botfuel-dialog/src/brain-resolver.js
Expand Up @@ -14,7 +14,6 @@
* limitations under the License.
*/

const logger = require('logtown')('BrainResolver');
const Resolver = require('./resolver');

/**
Expand All @@ -30,12 +29,6 @@ class BrainResolver extends Resolver {
this.bot = bot;
}

/** @inheritdoc */
getPaths(name) {
logger.debug('getPaths', name);
return [`${this.botPath}/${name}-${this.kind}.js`, `${this.sdkPath}/${name}-${this.kind}.js`];
}

/** @inheritdoc */
resolutionSucceeded(Resolved) {
return new Resolved(this.bot.config);
Expand Down
18 changes: 9 additions & 9 deletions packages/botfuel-dialog/src/classifier.js
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

const Fs = require('fs');
const fs = require('fs');
const crypto = require('crypto');
const fsExtra = require('fs-extra');
const Natural = require('natural');
Expand Down Expand Up @@ -97,7 +97,7 @@ class Classifier {
*/
async isModelUpToDate(modelFilePath, intentsDirPath) {
logger.debug('isModelUpToDate');
const intentFiles = Fs.readdirSync(intentsDirPath, 'utf8');
const intentFiles = fs.readdirSync(intentsDirPath, 'utf8');
const intentsMap = intentFiles
.filter(file => file.substr(-INTENT_SUFFIX.length) === INTENT_SUFFIX)
.map(fileName => ({
Expand All @@ -107,10 +107,9 @@ class Classifier {
.reduce(
(map, intent) =>
Object.assign(map, {
[intent.intentName]: Fs.readFileSync(
`${intentsDirPath}/${intent.fileName}`,
'utf8',
).toString(),
[intent.intentName]: fs
.readFileSync(`${intentsDirPath}/${intent.fileName}`, 'utf8')
.toString(),
}),
{},
);
Expand All @@ -121,7 +120,7 @@ class Classifier {
.digest('hex');

try {
const storedHash = Fs.readFileSync(this.modelMetadataFilename, 'utf8').toString();
const storedHash = fs.readFileSync(this.modelMetadataFilename, 'utf8').toString();

return hash === storedHash;
} catch (err) {
Expand Down Expand Up @@ -187,14 +186,15 @@ class Classifier {
const intentsMap = {};

this.classifier = new Natural.LogisticRegressionClassifier(this.getStemmer());
Fs.readdirSync(this.intentDirname, 'utf8')
fs
.readdirSync(this.intentDirname, 'utf8')
.filter(fileName => fileName.substr(-INTENT_SUFFIX.length) === INTENT_SUFFIX)
.map((fileName) => {
logger.debug('train: filename', fileName);
const intent = fileName.substring(0, fileName.length - INTENT_SUFFIX.length);
logger.debug('train: intent', intent);

const content = Fs.readFileSync(`${this.intentDirname}/${fileName}`, 'utf8').toString();
const content = fs.readFileSync(`${this.intentDirname}/${fileName}`, 'utf8').toString();

return content.split('\n').map((line) => {
logger.debug('train: line', line);
Expand Down
34 changes: 34 additions & 0 deletions packages/botfuel-dialog/src/config.js
Expand Up @@ -14,10 +14,12 @@
* limitations under the License.
*/

const fs = require('fs');
const path = require('path');
const { omitBy } = require('lodash');
const logger = require('logtown')('Config');
const LoggerManager = require('./logger-manager');
const ConfigurationError = require('./errors/configuration-error');

const DEFAULT_CONVERSATION_DURATION = 86400000; // one day in ms

Expand All @@ -31,6 +33,7 @@ const defaultConfig = {
name: 'memory',
},
logger: 'info',
modules: [],
nlu: {
name: 'botfuel',
intentThreshold: 0.8,
Expand Down Expand Up @@ -67,6 +70,35 @@ const resolveConfigFile = (configFileName) => {
}
};

const getComponentRoots = function (config) {
const botRoot = `${config.path}/src`;
const sdkRoot = __dirname;

const moduleRoots = config.modules.map((packageName) => {
if (typeof packageName !== 'string') {
throw new ConfigurationError(
'Parameter "modules" of configuration should be a list of package names.',
);
}
const moduleBasePath = path.dirname(require.resolve(packageName));
const { botfuelModuleRoot } = require(packageName);
if (typeof botfuelModuleRoot !== 'string') {
throw new ConfigurationError(
`Package ${packageName} should export "botfuelModuleRoot" with type string.`,
);
}
const absolutePath = path.join(moduleBasePath, botfuelModuleRoot);
if (!fs.existsSync(absolutePath)) {
throw new ConfigurationError(
`Package ${packageName} does not contain the directory "${absolutePath}".`,
);
}
return absolutePath;
});

return [botRoot, ...moduleRoots, sdkRoot];
};

/**
* Returns the configuration
* @param {Object} botConfig - the bot config
Expand All @@ -82,6 +114,8 @@ const getConfiguration = (botConfig = {}) => {
config.brain.conversationDuration =
config.brain.conversationDuration || DEFAULT_CONVERSATION_DURATION;

config.componentRoots = getComponentRoots(config);

// reconfigure the logger with the final config
LoggerManager.configure(config);
// return default config extended by bot config
Expand Down
15 changes: 10 additions & 5 deletions packages/botfuel-dialog/src/dialog-manager.js
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

const path = require('path');
const flatMap = require('lodash/flatMap');
const logger = require('logtown')('DialogManager');
const Resolver = require('./resolver');
const Dialog = require('./dialogs/dialog');
Expand All @@ -39,12 +41,15 @@ class DialogManager extends Resolver {
/** @inheritdoc */
getPaths(name) {
logger.debug('getPaths', name);
return [
`${this.botPath}/${name}-${this.kind}.${this.config.adapter.name}.js`,
`${this.botPath}/${name}-${this.kind}.js`,
`${this.sdkPath}/${name}-${this.kind}.${this.config.adapter.name}.js`,
`${this.sdkPath}/${name}-${this.kind}.js`,

const possibleFilenames = [
`${name}-${this.kind}.${this.config.adapter.name}.js`,
`${name}-${this.kind}.js`,
];

return flatMap(this.directories, directory =>
possibleFilenames.map(filename => path.join(directory, filename)),
);
}

/** @inheritdoc */
Expand Down
27 changes: 27 additions & 0 deletions packages/botfuel-dialog/src/errors/configuration-error.js
@@ -0,0 +1,27 @@
/**
* Copyright (c) 2017 - present, Botfuel (https://www.botfuel.io).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License 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.
*/

const SdkError = require('./sdk-error');

module.exports = class ConfigurationError extends SdkError {
/**
* @constructor
* @param {String} message - the error message
*/
constructor(message) {
super(message || 'Unknown configuration error');
}
};
7 changes: 0 additions & 7 deletions packages/botfuel-dialog/src/nlu-resolver.js
Expand Up @@ -14,7 +14,6 @@
* limitations under the License.
*/

const logger = require('logtown')('NluResolver');
const Resolver = require('./resolver');

/**
Expand All @@ -30,12 +29,6 @@ class NluResolver extends Resolver {
this.bot = bot;
}

/** @inheritdoc */
getPaths(name) {
logger.debug('getPaths', name);
return [`${this.botPath}/${name}-${this.kind}.js`, `${this.sdkPath}/${name}-${this.kind}.js`];
}

/** @inheritdoc */
resolutionSucceeded(Resolved) {
return new Resolved(this.bot.config);
Expand Down
42 changes: 32 additions & 10 deletions packages/botfuel-dialog/src/resolver.js
Expand Up @@ -15,8 +15,10 @@
*/

const fs = require('fs');
const path = require('path');
const logger = require('logtown')('Resolver');
const ResolutionError = require('./errors/resolution-error');
const MissingImplementationError = require('./errors/missing-implementation-error');

/**
* The adapter resolver resolves the adapter at startup.
Expand All @@ -30,8 +32,19 @@ class Resolver {
constructor(config, kind) {
this.config = config;
this.kind = kind;
this.botPath = `${config.path}/src/${kind}s`;
this.sdkPath = `${__dirname}/${kind}s`;
this.directories = config.componentRoots
.map(componentRoot => path.join(componentRoot, `${kind}s`))
.filter(fs.existsSync);
}

/**
* Gets the possible paths for a given name.
* @param {String} name - the adapter name
* @returns {[String]} the possible paths
*/
getPaths(name) {
logger.debug('getPaths', name);
return this.directories.map(directory => path.join(directory, `${name}-${this.kind}.js`));
}

/**
Expand All @@ -41,11 +54,11 @@ class Resolver {
*/
getPath(name) {
logger.debug('getPath');
for (const path of this.getPaths(name)) {
logger.debug('getPath: test path', path);
if (fs.existsSync(path)) {
logger.debug('getPath: existing path', path);
return path;
for (const componentPath of this.getPaths(name)) {
logger.debug('getPath: test path', componentPath);
if (fs.existsSync(componentPath)) {
logger.debug('getPath: existing path', componentPath);
return componentPath;
}
}
return null;
Expand All @@ -58,9 +71,9 @@ class Resolver {
*/
resolve(name) {
logger.debug('resolve', name);
const path = this.getPath(name);
if (path) {
const Resolved = require(path);
const componentPath = this.getPath(name);
if (componentPath) {
const Resolved = require(componentPath);
return this.resolutionSucceeded(Resolved);
}
throw new ResolutionError({
Expand All @@ -69,6 +82,15 @@ class Resolver {
paths: this.getPaths(name),
});
}

/**
* Instantiate a component after a successful resolution
* @param {String} Resolved - the component class
* @returns {Adapter|null} the instance or null
*/
resolutionSucceeded() {
throw new MissingImplementationError();
}
}

module.exports = Resolver;
15 changes: 10 additions & 5 deletions packages/botfuel-dialog/src/view-resolver.js
Expand Up @@ -14,6 +14,8 @@
* limitations under the License.
*/

const path = require('path');
const flatMap = require('lodash/flatMap');
const logger = require('logtown')('ViewResolver');
const Resolver = require('./resolver');

Expand All @@ -32,12 +34,15 @@ class ViewResolver extends Resolver {
/** @inheritdoc */
getPaths(name) {
logger.debug('getPaths', name);
return [
`${this.botPath}/${name}-${this.kind}.${this.config.locale}.js`,
`${this.botPath}/${name}-${this.kind}.js`,
`${this.sdkPath}/${name}-${this.kind}.${this.config.locale}.js`,
`${this.sdkPath}/${name}-${this.kind}.js`,

const possibleFilenames = [
`${name}-${this.kind}.${this.config.locale}.js`,
`${name}-${this.kind}.js`,
];

return flatMap(this.directories, directory =>
possibleFilenames.map(filename => path.join(directory, filename)),
);
}

/** @inheritdoc */
Expand Down
6 changes: 6 additions & 0 deletions packages/test-modules/.eslintrc
@@ -0,0 +1,6 @@
{
"extends": ["../../.eslintrc"],
"rules": {
"require-jsdoc": "off"
}
}
9 changes: 9 additions & 0 deletions packages/test-modules/CHANGELOG.md
@@ -0,0 +1,9 @@
# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.




**Note:** Version bump only for package test-modules

0 comments on commit ecab4eb

Please sign in to comment.