UNPKG

noflo

Version:

Flow-Based Programming environment for JavaScript

422 lines (395 loc) 13.6 kB
(function() { var ComponentLoader, EventEmitter, internalSocket, nofloGraph, utils, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; internalSocket = require('./InternalSocket'); nofloGraph = require('./Graph'); utils = require('./Utils'); EventEmitter = require('events').EventEmitter; ComponentLoader = (function(_super) { __extends(ComponentLoader, _super); function ComponentLoader(baseDir, options) { this.baseDir = baseDir; this.options = options != null ? options : {}; this.components = null; this.componentLoaders = []; this.checked = []; this.revalidate = false; this.libraryIcons = {}; this.processing = false; this.ready = false; } ComponentLoader.prototype.getModulePrefix = function(name) { if (!name) { return ''; } if (name === 'noflo') { return ''; } if (name[0] === '@') { name = name.replace(/\@[a-z\-]+\//, ''); } return name.replace('noflo-', ''); }; ComponentLoader.prototype.getModuleComponents = function(moduleName) { var cPath, definition, dependency, e, loader, loaderPath, name, prefix, _ref, _ref1, _results; if (this.checked.indexOf(moduleName) !== -1) { return; } this.checked.push(moduleName); try { definition = require("/" + moduleName + "/component.json"); } catch (_error) { e = _error; if (moduleName.substr(0, 1) === '/') { return this.getModuleComponents("noflo-" + (moduleName.substr(1))); } return; } for (dependency in definition.dependencies) { this.getModuleComponents(dependency.replace('/', '-')); } if (!definition.noflo) { return; } prefix = this.getModulePrefix(definition.name); if (definition.noflo.icon) { this.libraryIcons[prefix] = definition.noflo.icon; } if (moduleName[0] === '/') { moduleName = moduleName.substr(1); } if (definition.noflo.loader) { loaderPath = "/" + moduleName + "/" + definition.noflo.loader; this.componentLoaders.push(loaderPath); loader = require(loaderPath); this.registerLoader(loader, function() {}); } if (definition.noflo.components) { _ref = definition.noflo.components; for (name in _ref) { cPath = _ref[name]; if (cPath.indexOf('.coffee') !== -1) { cPath = cPath.replace('.coffee', '.js'); } if (cPath.substr(0, 2) === './') { cPath = cPath.substr(2); } this.registerComponent(prefix, name, "/" + moduleName + "/" + cPath); } } if (definition.noflo.graphs) { _ref1 = definition.noflo.graphs; _results = []; for (name in _ref1) { cPath = _ref1[name]; _results.push(this.registerGraph(prefix, name, "/" + moduleName + "/" + cPath)); } return _results; } }; ComponentLoader.prototype.listComponents = function(callback) { if (this.processing) { this.once('ready', (function(_this) { return function() { return callback(null, _this.components); }; })(this)); return; } if (this.components) { return callback(null, this.components); } this.ready = false; this.processing = true; return setTimeout((function(_this) { return function() { _this.components = {}; _this.getModuleComponents(_this.baseDir); _this.processing = false; _this.ready = true; _this.emit('ready', true); if (callback) { return callback(null, _this.components); } }; })(this), 1); }; ComponentLoader.prototype.load = function(name, callback, metadata) { var component, componentName; if (!this.ready) { this.listComponents((function(_this) { return function(err) { if (err) { return callback(err); } return _this.load(name, callback, metadata); }; })(this)); return; } component = this.components[name]; if (!component) { for (componentName in this.components) { if (componentName.split('/')[1] === name) { component = this.components[componentName]; break; } } if (!component) { callback(new Error("Component " + name + " not available with base " + this.baseDir)); return; } } if (this.isGraph(component)) { if (typeof process !== 'undefined' && process.execPath && process.execPath.indexOf('node') !== -1) { process.nextTick((function(_this) { return function() { return _this.loadGraph(name, component, callback, metadata); }; })(this)); } else { setTimeout((function(_this) { return function() { return _this.loadGraph(name, component, callback, metadata); }; })(this), 0); } return; } return this.createComponent(name, component, metadata, (function(_this) { return function(err, instance) { if (err) { return callback(err); } if (!instance) { callback(new Error("Component " + name + " could not be loaded.")); return; } if (name === 'Graph') { instance.baseDir = _this.baseDir; } _this.setIcon(name, instance); return callback(null, instance); }; })(this)); }; ComponentLoader.prototype.createComponent = function(name, component, metadata, callback) { var e, implementation, instance; implementation = component; if (typeof implementation === 'string') { try { implementation = require(implementation); } catch (_error) { e = _error; return callback(e); } } if (typeof implementation.getComponent === 'function') { instance = implementation.getComponent(metadata); } else if (typeof implementation === 'function') { instance = implementation(metadata); } else { callback(new Error("Invalid type " + (typeof implementation) + " for component " + name + ".")); return; } if (typeof name === 'string') { instance.componentName = name; } return callback(null, instance); }; ComponentLoader.prototype.isGraph = function(cPath) { if (typeof cPath === 'object' && cPath instanceof nofloGraph.Graph) { return true; } if (typeof cPath !== 'string') { return false; } return cPath.indexOf('.fbp') !== -1 || cPath.indexOf('.json') !== -1; }; ComponentLoader.prototype.loadGraph = function(name, component, callback, metadata) { var graph, graphImplementation, graphSocket; graphImplementation = require(this.components['Graph']); graphSocket = internalSocket.createSocket(); graph = graphImplementation.getComponent(metadata); graph.loader = this; graph.baseDir = this.baseDir; graph.inPorts.graph.attach(graphSocket); if (typeof name === 'string') { graph.componentName = name; } graphSocket.send(component); graphSocket.disconnect(); graph.inPorts.remove('graph'); this.setIcon(name, graph); return callback(null, graph); }; ComponentLoader.prototype.setIcon = function(name, instance) { var componentName, library, _ref; if (!instance.getIcon || instance.getIcon()) { return; } _ref = name.split('/'), library = _ref[0], componentName = _ref[1]; if (componentName && this.getLibraryIcon(library)) { instance.setIcon(this.getLibraryIcon(library)); return; } if (instance.isSubgraph()) { instance.setIcon('sitemap'); return; } instance.setIcon('square'); }; ComponentLoader.prototype.getLibraryIcon = function(prefix) { if (this.libraryIcons[prefix]) { return this.libraryIcons[prefix]; } return null; }; ComponentLoader.prototype.normalizeName = function(packageId, name) { var fullName, prefix; prefix = this.getModulePrefix(packageId); fullName = "" + prefix + "/" + name; if (!packageId) { fullName = name; } return fullName; }; ComponentLoader.prototype.registerComponent = function(packageId, name, cPath, callback) { var fullName; fullName = this.normalizeName(packageId, name); this.components[fullName] = cPath; if (callback) { return callback(); } }; ComponentLoader.prototype.registerGraph = function(packageId, name, gPath, callback) { return this.registerComponent(packageId, name, gPath, callback); }; ComponentLoader.prototype.registerLoader = function(loader, callback) { return loader(this, callback); }; ComponentLoader.prototype.setSource = function(packageId, name, source, language, callback) { var e, implementation; if (!this.ready) { this.listComponents((function(_this) { return function(err) { if (err) { return callback(err); } return _this.setSource(packageId, name, source, language, callback); }; })(this)); return; } if (language === 'coffeescript') { if (!window.CoffeeScript) { return callback(new Error('CoffeeScript compiler not available')); } try { source = CoffeeScript.compile(source, { bare: true }); } catch (_error) { e = _error; return callback(e); } } else if (language === 'es6' || language === 'es2015') { if (!window.babel) { return callback(new Error('Babel compiler not available')); } try { source = babel.transform(source).code; } catch (_error) { e = _error; return callback(e); } } try { source = source.replace("require('noflo')", "require('./NoFlo')"); source = source.replace('require("noflo")', 'require("./NoFlo")'); implementation = eval("(function () { var exports = {}; " + source + "; return exports; })()"); } catch (_error) { e = _error; return callback(e); } if (!(implementation || implementation.getComponent)) { return callback(new Error('Provided source failed to create a runnable component')); } return this.registerComponent(packageId, name, implementation, function() { return callback(null); }); }; ComponentLoader.prototype.getSource = function(name, callback) { var component, componentName, nameParts, path; if (!this.ready) { this.listComponents((function(_this) { return function(err) { if (err) { return callback(err); } return _this.getSource(name, callback); }; })(this)); return; } component = this.components[name]; if (!component) { for (componentName in this.components) { if (componentName.split('/')[1] === name) { component = this.components[componentName]; name = componentName; break; } } if (!component) { return callback(new Error("Component " + name + " not installed")); } } if (typeof component !== 'string') { return callback(new Error("Can't provide source for " + name + ". Not a file")); } nameParts = name.split('/'); if (nameParts.length === 1) { nameParts[1] = nameParts[0]; nameParts[0] = ''; } if (this.isGraph(component)) { nofloGraph.loadFile(component, function(err, graph) { if (err) { return callback(err); } if (!graph) { return callback(new Error('Unable to load graph')); } return callback(null, { name: nameParts[1], library: nameParts[0], code: JSON.stringify(graph.toJSON()), language: 'json' }); }); return; } path = window.require.resolve(component); if (!path) { return callback(new Error("Component " + name + " is not resolvable to a path")); } return callback(null, { name: nameParts[1], library: nameParts[0], code: window.require.modules[path].toString(), language: utils.guessLanguageFromFilename(component) }); }; ComponentLoader.prototype.clear = function() { this.components = null; this.checked = []; this.revalidate = true; this.ready = false; return this.processing = false; }; return ComponentLoader; })(EventEmitter); exports.ComponentLoader = ComponentLoader; }).call(this);