/** * Copyright 2014 IBM Corp. * * 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. **/ var util = require("util"); var when = require("when"); var whenNode = require('when/node'); var fs = require("fs"); var path = require("path"); var crypto = require("crypto"); var UglifyJS = require("uglify-js"); var events = require("../events"); var Node; var settings; function filterNodeInfo(n) { var r = { id: n.id, name: n.name, types: n.types, enabled: n.enabled } if (n.hasOwnProperty("loaded")) { r.loaded = n.loaded; } if (n.hasOwnProperty("module")) { r.module = n.module; } if (n.hasOwnProperty("err")) { r.err = n.err.toString(); } return r; } var registry = (function() { var nodeConfigCache = null; var nodeConfigs = {}; var nodeList = []; var nodeConstructors = {}; var nodeTypeToId = {}; var nodeModules = {}; function saveNodeList() { var nodeList = {}; for (var i in nodeConfigs) { if (nodeConfigs.hasOwnProperty(i)) { var nodeConfig = nodeConfigs[i]; var n = filterNodeInfo(nodeConfig); n.file = nodeConfig.file; delete n.loaded; delete n.err; delete n.file; delete n.id; nodeList[i] = n; } } if (settings.available()) { return settings.set("nodes",nodeList); } else { return when.reject("Settings unavailable"); } } return { init: function() { if (settings.available()) { nodeConfigs = settings.get("nodes")||{}; // Restore the node id property to individual entries for (var id in nodeConfigs) { if (nodeConfigs.hasOwnProperty(id)) { nodeConfigs[id].id = id; } } } else { nodeConfigs = {}; } nodeModules = {}; nodeTypeToId = {}; nodeConstructors = {}; nodeList = []; nodeConfigCache = null; }, addNodeSet: function(id,set) { if (!set.err) { set.types.forEach(function(t) { nodeTypeToId[t] = id; }); } if (set.module) { nodeModules[set.module] = nodeModules[set.module]||{nodes:[]}; nodeModules[set.module].nodes.push(id); } nodeConfigs[id] = set; nodeList.push(id); nodeConfigCache = null; }, removeNode: function(id) { var config = nodeConfigs[id]; if (!config) { throw new Error("Unrecognised id: "+id); } delete nodeConfigs[id]; var i = nodeList.indexOf(id); if (i > -1) { nodeList.splice(i,1); } config.types.forEach(function(t) { delete nodeConstructors[t]; delete nodeTypeToId[t]; }); config.enabled = false; config.loaded = false; nodeConfigCache = null; return filterNodeInfo(config); }, removeModule: function(module) { if (!settings.available()) { throw new Error("Settings unavailable"); } var nodes = nodeModules[module]; if (!nodes) { throw new Error("Unrecognised module: "+module); } var infoList = []; for (var i=0;i 0) { result += ''; } nodeConfigCache = result; } return nodeConfigCache; }, getNodeConfig: function(id) { var config = nodeConfigs[id]; if (config) { var result = config.config; if (config.script) { result += ''; } return result; } else { return null; } }, getNodeConstructor: function(type) { var config = nodeConfigs[nodeTypeToId[type]]; if (!config || (config.enabled && !config.err)) { return nodeConstructors[type]; } return null; }, clear: function() { nodeConfigCache = null; nodeConfigs = {}; nodeList = []; nodeConstructors = {}; nodeTypeToId = {}; }, getTypeId: function(type) { return nodeTypeToId[type]; }, getModuleInfo: function(type) { return nodeModules[type]; }, enableNodeSet: function(id) { if (!settings.available()) { throw new Error("Settings unavailable"); } var config = nodeConfigs[id]; if (config) { delete config.err; config.enabled = true; if (!config.loaded) { // TODO: honour the promise this returns loadNodeModule(config); } nodeConfigCache = null; saveNodeList(); } else { throw new Error("Unrecognised id: "+id); } return filterNodeInfo(config); }, disableNodeSet: function(id) { if (!settings.available()) { throw new Error("Settings unavailable"); } var config = nodeConfigs[id]; if (config) { // TODO: persist setting config.enabled = false; nodeConfigCache = null; saveNodeList(); } else { throw new Error("Unrecognised id: "+id); } return filterNodeInfo(config); }, saveNodeList: saveNodeList, cleanNodeList: function() { var removed = false; for (var id in nodeConfigs) { if (nodeConfigs.hasOwnProperty(id)) { if (nodeConfigs[id].module && !nodeModules[nodeConfigs[id].module]) { registry.removeNode(id); removed = true; } } } if (removed) { saveNodeList(); } } } })(); function init(_settings) { Node = require("./Node"); settings = _settings; registry.init(); } /** * Synchronously walks the directory looking for node files. * Emits 'node-icon-dir' events for an icon dirs found * @param dir the directory to search * @return an array of fully-qualified paths to .js files */ function getNodeFiles(dir) { var result = []; var files = []; try { files = fs.readdirSync(dir); } catch(err) { return result; } files.sort(); files.forEach(function(fn) { var stats = fs.statSync(path.join(dir,fn)); if (stats.isFile()) { if (/\.js$/.test(fn)) { var valid = true; if (settings.nodesExcludes) { for (var i=0;i]*)data-template-name=['"]([^'"]*)['"]/gi; var match = null; while((match = regExp.exec(content)) !== null) { types.push(match[2]); } node.types = types; node.config = content; // TODO: parse out the javascript portion of the template node.script = ""; for (var i=0;i