Comparing version 0.1.7 to 0.1.8
148
architect.js
@@ -16,2 +16,4 @@ ( // Module boilerplate to support node.js and AMD. | ||
var realpathSync = require('fs').realpathSync; | ||
var exists = require('fs').exists || require('path').exists; | ||
var realpath = require('fs').realpath; | ||
var packagePathCache = {}; | ||
@@ -24,10 +26,17 @@ | ||
// throw exceptions. It loads and parses a config file. | ||
function loadConfig(configPath) { | ||
function loadConfig(configPath, callback) { | ||
var config = require(configPath); | ||
var base = dirname(configPath); | ||
return resolveConfig(config, base); | ||
return resolveConfig(config, base, callback); | ||
} | ||
function resolveConfig(config, base) { | ||
function resolveConfig(config, base, callback) { | ||
if (!callback) | ||
return resolveConfigSync(config, base); | ||
else | ||
resolveConfigAsync(config, base, callback); | ||
} | ||
function resolveConfigSync(config, base) { | ||
config.forEach(function (plugin, index) { | ||
@@ -40,3 +49,3 @@ // Shortcut where string is used for plugin without any options. | ||
if (plugin.hasOwnProperty("packagePath") && !plugin.hasOwnProperty("setup")) { | ||
var defaults = resolveModule(base, plugin.packagePath); | ||
var defaults = resolveModuleSync(base, plugin.packagePath); | ||
Object.keys(defaults).forEach(function (key) { | ||
@@ -54,5 +63,45 @@ if (!plugin.hasOwnProperty(key)) { | ||
function resolveConfigAsync(config, base, callback) { | ||
function resolveNext(i) { | ||
if (i >= config.length) { | ||
return callback(null, config); | ||
} | ||
var plugin = config[i]; | ||
// Shortcut where string is used for plugin without any options. | ||
if (typeof plugin === "string") { | ||
plugin = config[i] = { packagePath: plugin }; | ||
} | ||
// The plugin is a package on the disk. We need to load it. | ||
if (plugin.hasOwnProperty("packagePath") && !plugin.hasOwnProperty("setup")) { | ||
resolveModule(base, plugin.packagePath, function(err, defaults) { | ||
if (err) return callback(err); | ||
Object.keys(defaults).forEach(function (key) { | ||
if (!plugin.hasOwnProperty(key)) { | ||
plugin[key] = defaults[key]; | ||
} | ||
}); | ||
plugin.packagePath = defaults.packagePath; | ||
try { | ||
plugin.setup = require(plugin.packagePath); | ||
} catch(e) { | ||
return callback(e); | ||
} | ||
return resolveNext(++i); | ||
}); | ||
return; | ||
} | ||
return resolveNext(++i); | ||
} | ||
resolveNext(0); | ||
} | ||
// Loads a module, getting metadata from either it's package.json or export | ||
// object. | ||
function resolveModule(base, modulePath) { | ||
function resolveModuleSync(base, modulePath) { | ||
var packagePath; | ||
@@ -78,2 +127,37 @@ try { | ||
// Loads a module, getting metadata from either it's package.json or export | ||
// object. | ||
function resolveModule(base, modulePath, callback) { | ||
resolvePackage(base, modulePath + "/package.json", function(err, packagePath) { | ||
if (err && err.code !== "ENOENT") return callback(err); | ||
var metadata = {}; | ||
try { | ||
metadata = packagePath && require(packagePath).plugin || {}; | ||
} catch(e) { | ||
return callback(e); | ||
} | ||
(function(next) { | ||
if (packagePath) { | ||
next(null, dirname(packagePath)); | ||
} else { | ||
resolvePackage(base, modulePath, next); | ||
} | ||
})(function(err, modulePath) { | ||
if (err) return callback(err); | ||
var module; | ||
try { | ||
module = require(modulePath); | ||
} catch(e) { | ||
return callback(e); | ||
} | ||
metadata.provides = metadata.provides || module.provides || []; | ||
metadata.consumes = metadata.consumes || module.consumes || []; | ||
metadata.packagePath = modulePath; | ||
callback(null, metadata); | ||
}); | ||
}); | ||
} | ||
// Node style package resolving so that plugins' package.json can be found relative to the config file | ||
@@ -116,2 +200,56 @@ // It's not the full node require system algorithm, but it's the 99% case | ||
function resolvePackage(base, packagePath, callback) { | ||
var originalBase = base; | ||
if (!packagePathCache.hasOwnProperty(base)) { | ||
packagePathCache[base] = {}; | ||
} | ||
var cache = packagePathCache[base]; | ||
if (cache.hasOwnProperty(packagePath)) { | ||
return callback(null, cache[packagePath]); | ||
} | ||
if (packagePath[0] === "." || packagePath[0] === "/") { | ||
var newPath = resolve(base, packagePath); | ||
exists(newPath, function(exists) { | ||
if (exists) { | ||
realpath(newPath, function(err, newPath) { | ||
if (err) return callback(err); | ||
cache[packagePath] = newPath; | ||
return callback(null, newPath); | ||
}); | ||
} else { | ||
var err = new Error("Can't find '" + packagePath + "' relative to '" + originalBase + "'"); | ||
err.code = "ENOENT"; | ||
return callback(err); | ||
} | ||
}); | ||
} | ||
else { | ||
tryNext(base); | ||
} | ||
function tryNext(base) { | ||
if (!base) { | ||
var err = new Error("Can't find '" + packagePath + "' relative to '" + originalBase + "'"); | ||
err.code = "ENOENT"; | ||
return callback(err); | ||
} | ||
var newPath = resolve(base, "node_modules", packagePath); | ||
exists(newPath, function(exists) { | ||
if (exists) { | ||
realpath(newPath, function(err, newPath) { | ||
if (err) return callback(err); | ||
cache[packagePath] = newPath; | ||
return callback(null, newPath); | ||
}); | ||
} else { | ||
tryNext(base.substr(0, base.lastIndexOf("/"))); | ||
} | ||
}); | ||
} | ||
} | ||
}()); | ||
@@ -118,0 +256,0 @@ |
{ | ||
"name": "architect", | ||
"description": "A Simple yet powerful plugin system for node applications", | ||
"version": "0.1.7", | ||
"version": "0.1.8", | ||
"author": "ajax.org B.V. <info@ajax.org>", | ||
@@ -6,0 +6,0 @@ "contributors": [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23031
455
8
13