Comparing version 0.1.4 to 0.1.5
262
architect.js
@@ -1,46 +0,136 @@ | ||
var dirname = require('path').dirname; | ||
var resolve = require('path').resolve; | ||
var existsSync = require('path').existsSync; | ||
var realpathSync = require('fs').realpathSync; | ||
var EventEmitter = require('events').EventEmitter; | ||
var inherits = require('util').inherits; | ||
exports.loadConfig = loadConfig; | ||
exports.resolveConfig = resolveConfig; | ||
exports.createApp = createApp; | ||
exports.Architect = Architect; | ||
( // Module boilerplate to support node.js and AMD. | ||
(typeof module === "object" && function (m) { module.exports = m(require('events')); }) || | ||
(typeof define === "function" && function (m) { define(["events"], m); }) | ||
)(function (events) { | ||
"use strict"; | ||
var EventEmitter = events.EventEmitter; | ||
// This is assumed to be used at startup and uses sync I/O as well as can | ||
// throw exceptions. It loads and parses a config file. | ||
function loadConfig(configPath) { | ||
var config = require(configPath); | ||
var base = dirname(configPath); | ||
var exports = {}; | ||
return resolveConfig(config, base); | ||
} | ||
// Only define Node-style usage using sync I/O if in node. | ||
if (typeof module === "object") (function () { | ||
var dirname = require('path').dirname; | ||
var resolve = require('path').resolve; | ||
var existsSync = require('path').existsSync; | ||
var realpathSync = require('fs').realpathSync; | ||
var packagePathCache = {}; | ||
function resolveConfig(config, base) { | ||
config.forEach(function (plugin, index) { | ||
// Shortcut where string is used for plugin without any options. | ||
if (typeof plugin === "string") { | ||
plugin = config[index] = { packagePath: plugin }; | ||
exports.loadConfig = loadConfig; | ||
exports.resolveConfig = resolveConfig; | ||
// This is assumed to be used at startup and uses sync I/O as well as can | ||
// throw exceptions. It loads and parses a config file. | ||
function loadConfig(configPath) { | ||
var config = require(configPath); | ||
var base = dirname(configPath); | ||
return resolveConfig(config, base); | ||
} | ||
function resolveConfig(config, base) { | ||
config.forEach(function (plugin, index) { | ||
// Shortcut where string is used for plugin without any options. | ||
if (typeof plugin === "string") { | ||
plugin = config[index] = { packagePath: plugin }; | ||
} | ||
// The plugin is a package on the disk. We need to load it. | ||
if (plugin.hasOwnProperty("packagePath") && !plugin.hasOwnProperty("setup")) { | ||
plugin.packagePath = resolvePackageSync(base, plugin.packagePath); | ||
var packageConf = require(plugin.packagePath); | ||
var defaults = packageConf.plugin || {}; | ||
Object.keys(defaults).forEach(function (key) { | ||
if (!plugin.hasOwnProperty(key)) { | ||
plugin[key] = defaults[key]; | ||
} | ||
}); | ||
plugin.setup = require(dirname(plugin.packagePath)); | ||
} | ||
plugin.consumes = plugin.consumes || []; | ||
plugin.provides = plugin.provides || []; | ||
}); | ||
return config; | ||
} | ||
// Node style package resolving so that plugins' package.json can be found relative to the config file | ||
// It's not the full node require system algorithm, but it's the 99% case | ||
// This throws, make sure to wrap in try..catch | ||
function resolvePackageSync(base, packagePath) { | ||
var originalBase = base; | ||
if (!packagePathCache.hasOwnProperty(base)) { | ||
packagePathCache[base] = {}; | ||
} | ||
// The plugin is a package on the disk. We need to load it. | ||
if (plugin.hasOwnProperty("packagePath") && !plugin.hasOwnProperty("setup")) { | ||
plugin.packagePath = resolvePackageSync(base, plugin.packagePath); | ||
var packageConf = require(plugin.packagePath); | ||
var defaults = packageConf.plugin || {}; | ||
Object.keys(defaults).forEach(function (key) { | ||
if (!plugin.hasOwnProperty(key)) { | ||
plugin[key] = defaults[key]; | ||
var cache = packagePathCache[base]; | ||
if (cache.hasOwnProperty(packagePath)) { | ||
return cache[packagePath]; | ||
} | ||
var newPath; | ||
if (packagePath[0] === "." || packagePath[0] === "/") { | ||
newPath = resolve(base, packagePath, "package.json"); | ||
if (existsSync(newPath)) { | ||
newPath = realpathSync(newPath); | ||
cache[packagePath] = newPath; | ||
return newPath; | ||
} | ||
} | ||
else { | ||
while (base) { | ||
newPath = resolve(base, "node_modules", packagePath, "package.json"); | ||
if (existsSync(newPath)) { | ||
newPath = realpathSync(newPath); | ||
cache[packagePath] = newPath; | ||
return newPath; | ||
} | ||
}); | ||
plugin.setup = require(dirname(plugin.packagePath)); | ||
base = base.substr(0, base.lastIndexOf("/")); | ||
} | ||
} | ||
plugin.consumes = plugin.consumes || []; | ||
plugin.provides = plugin.provides || []; | ||
}); | ||
return config; | ||
} | ||
var err = new Error("Can't find '" + packagePath + "' relative to '" + originalBase + "'"); | ||
err.code = "ENOENT"; | ||
throw err; | ||
} | ||
}()); | ||
// Otherwise use amd to load modules. | ||
else (function () { | ||
exports.loadConfig = loadConfig; | ||
exports.resolveConfig = resolveConfig; | ||
function loadConfig(path, callback) { | ||
require([path], function (config) { | ||
resolveConfig(config, callback); | ||
}); | ||
} | ||
function resolveConfig(config, callback) { | ||
var paths = [], pluginIndexes = {}; | ||
config.forEach(function (plugin, index) { | ||
// Shortcut where string is used for plugin without any options. | ||
if (typeof plugin === "string") { | ||
plugin = config[index] = { packagePath: plugin }; | ||
} | ||
// The plugin is a package over the network. We need to load it. | ||
if (plugin.hasOwnProperty("packagePath") && !plugin.hasOwnProperty("setup")) { | ||
paths.push(plugin.packagePath); | ||
pluginIndexes[plugin.packagePath] = index; | ||
} | ||
}); | ||
// Mass-Load path-based plugins using amd's require | ||
require(paths, function () { | ||
var args = arguments; | ||
paths.forEach(function (name, i) { | ||
var module = args[i]; | ||
var plugin = config[pluginIndexes[name]]; | ||
plugin.setup = module; | ||
plugin.provides = module.provides || []; | ||
plugin.consumes = module.consumes || []; | ||
}); | ||
callback(null, config); | ||
}); | ||
} | ||
}()); | ||
exports.createApp = createApp; | ||
exports.Architect = Architect; | ||
// Check a plugin config list for bad dependencies and throw on error | ||
@@ -68,3 +158,3 @@ function checkConfig(config) { | ||
var plugins = []; | ||
config.forEach(function(pluginConfig) { | ||
config.forEach(function(pluginConfig, index) { | ||
plugins.push({ | ||
@@ -74,3 +164,3 @@ packagePath: pluginConfig.packagePath, | ||
consumes: pluginConfig.consumes.concat(), | ||
config: pluginConfig | ||
i: index | ||
}); | ||
@@ -108,3 +198,3 @@ }); | ||
}); | ||
sorted.push(plugin.config); | ||
sorted.push(config[plugin.i]); | ||
changed = true; | ||
@@ -136,3 +226,3 @@ }); | ||
try { | ||
var sortedPlugins = checkConfig(config) | ||
var sortedPlugins = checkConfig(config); | ||
} catch (err) { | ||
@@ -175,3 +265,3 @@ return app.emit("error", err); | ||
// Give createApp some time to subscribe to our "ready" event | ||
process.nextTick(startPlugins); | ||
(typeof process === "object" ? process.nextTick : setTimeout)(startPlugins); | ||
@@ -186,3 +276,3 @@ this.destroy = function() { | ||
} | ||
inherits(Architect, EventEmitter); | ||
Architect.prototype = Object.create(EventEmitter.prototype, {constructor:{value:Architect}}); | ||
@@ -194,3 +284,3 @@ Architect.prototype.getService = function(name) { | ||
return this.services[name]; | ||
} | ||
}; | ||
@@ -205,70 +295,32 @@ // Returns an event emitter that represents the app. It can emit events. | ||
function createApp(config, callback) { | ||
var app; | ||
try { | ||
var app = new Architect(config); | ||
if (callback) { | ||
app.on("error", onError); | ||
app.once("ready", onReady); | ||
function onError(err) { | ||
app.removeListener("ready", done); | ||
app.destroy(); | ||
done(err, app); | ||
} | ||
function onReady() { | ||
done(null, app); | ||
} | ||
var called = false; | ||
function done(err) { | ||
if (called) return; | ||
called = true; | ||
callback(err, app); | ||
} | ||
} | ||
return app; | ||
app = new Architect(config); | ||
} catch(err) { | ||
if (callback) { | ||
callback(err); | ||
} else { | ||
throw err; | ||
} | ||
if (!callback) throw err; | ||
return callback(err, app); | ||
} | ||
} | ||
if (callback) { | ||
app.on("error", done); | ||
app.on("ready", onReady); | ||
} | ||
return app; | ||
// Node style package resolving so that plugins' package.json can be found relative to the config file | ||
// It's not the full node require system algorithm, but it's the 99% case | ||
// This throws, make sure to wrap in try..catch | ||
var packagePathCache = {}; | ||
function resolvePackageSync(base, packagePath) { | ||
var originalBase = base; | ||
if (!packagePathCache.hasOwnProperty(base)) { | ||
packagePathCache[base] = {}; | ||
function onReady(app) { | ||
done(); | ||
} | ||
var cache = packagePathCache[base]; | ||
if (cache.hasOwnProperty(packagePath)) { | ||
return cache[packagePath]; | ||
} | ||
if (packagePath[0] === "." || packagePath[0] === "/") { | ||
var newPath = resolve(base, packagePath, "package.json"); | ||
if (existsSync(newPath)) { | ||
newPath = realpathSync(newPath); | ||
cache[packagePath] = newPath; | ||
return newPath; | ||
function done(err) { | ||
if (err) { | ||
app.destroy(); | ||
} | ||
app.removeListener("error", done); | ||
app.removeListener("ready", onReady); | ||
callback(err, app); | ||
} | ||
else { | ||
while (base) { | ||
var newPath = resolve(base, "node_modules", packagePath, "package.json"); | ||
if (existsSync(newPath)) { | ||
newPath = realpathSync(newPath); | ||
cache[packagePath] = newPath; | ||
return newPath; | ||
} | ||
base = base.substr(0, base.lastIndexOf("/")); | ||
} | ||
} | ||
var err = new Error("Can't find '" + packagePath + "' relative to '" + originalBase + "'"); | ||
err.code = "ENOENT"; | ||
throw err; | ||
} | ||
return exports; | ||
}); |
{ | ||
"name": "architect", | ||
"description": "A Simple yet powerful plugin system for node applications", | ||
"version": "0.1.4", | ||
"version": "0.1.5", | ||
"author": "ajax.org B.V. <info@ajax.org>", | ||
@@ -6,0 +6,0 @@ "contributors": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
26659
7
275
109
6
2