diff --git a/README.markdown b/README.markdown index 05ad1db..7b5a845 100644 --- a/README.markdown +++ b/README.markdown @@ -84,9 +84,22 @@ The architect module exposes two functions as it's main API. This function starts an architect config. The return value is an `Architect` instance. The optional callback will listen for both "error" and "ready" on the app object and report on which one happens first. -### loadConfig(configPath) +### loadConfig(configPathOrArray, [base], [callback]) -This is a sync function that loads a config file and parses all the plugins into a proper config object for use with `createApp`. While this uses sync I/O all steps along the way are memoized and I/O only occurs on the first invocation. It's safe to call this in an event loop provided a small set of configPaths are used. +This is a sync function prepares the config object for each plugin. +While this uses sync I/O all steps along the way are memoized and I/O only occurs on the first invocation. It's safe to call this in an event loop provided a small set of configPaths are used. + +It can be used in one of two ways: + +#### loadConfig(configPath, [callback]) + +Loads a config file and parses all the plugins into a proper config object for use with `createApp`. +Base path of plugins is automatically detected from the base name of the path provided. + +#### loadConfig(configArray, base, [callback]) + +Processes the existing config and adds the initialization function for each plugin present. +Note that base is required when using this method. ## Class: Architect @@ -105,4 +118,3 @@ When a plugin registers, this event is emitted. ### Event: "ready" (app) When all plugins are done, the "ready" event is emitted. The value is the Architect instance itself. - diff --git a/architect.js b/architect.js index 090b564..f023db2 100644 --- a/architect.js +++ b/architect.js @@ -26,8 +26,20 @@ if (typeof module === "object") (function () { // 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, callback) { - var config = require(configPath); - var base = dirname(configPath); + var config; + var base; + if ('string' === typeof configPath) { + config = require(configPath); + base = dirname(configPath); + } else if ('object' === typeof configPath) { + config = configPath; + if ('string' === typeof callback) { + base = callback; + callback = arguments[2]; + } + } else { + throw new Error('Unexpected type for configPath (expected config object or string path)'); + } return resolveConfig(config, base, callback); } @@ -153,7 +165,7 @@ if (typeof module === "object") (function () { } else if (packagePath) { next(null, dirname(packagePath)); - } + } else { resolvePackage(base, modulePath, next); } @@ -289,7 +301,7 @@ else (function () { function resolveConfig(config, base, callback, errback) { if (typeof base == "function") return resolveConfig(config, "", arguments[1], arguments[2]); - + var paths = [], pluginIndexes = {}; config.forEach(function (plugin, index) { // Shortcut where string is used for plugin without any options. @@ -400,7 +412,7 @@ function checkCycles(config, lookup) { unresolved[name] = false; }); }); - + Object.keys(unresolved).forEach(function(name) { if (unresolved[name] === false) delete unresolved[name]; @@ -425,7 +437,7 @@ function Architect(config) { app.config = config; app.packages = {}; app.pluginToPackage = {}; - + var isAdditionalMode; var services = app.services = { hub: { @@ -453,15 +465,15 @@ function Architect(config) { imports[name] = services[name]; }); } - + var m = /^plugins\/([^\/]+)|\/plugins\/[^\/]+\/([^\/]+)/.exec(plugin.packagePath); var packageName = m && (m[1] || m[2]); if (!app.packages[packageName]) app.packages[packageName] = []; - + if (DEBUG) { recur++; plugin.setup(plugin, imports, register); - + while (callnext && recur <= 1) { callnext = false; startPlugins(additional); @@ -484,7 +496,7 @@ function Architect(config) { recur--; } } - + function register(err, provided) { if (err) { return app.emit("error", err); } plugin.provides.forEach(function (name) { @@ -501,14 +513,14 @@ function Architect(config) { isAdditionalMode: isAdditionalMode }; app.packages[packageName].push(name); - + app.emit("service", name, services[name], plugin); }); if (provided && provided.hasOwnProperty("onDestroy")) destructors.push(provided.onDestroy); app.emit("plugin", plugin); - + if (recur) return (callnext = true); startPlugins(additional); } @@ -519,19 +531,19 @@ function Architect(config) { this.loadAdditionalPlugins = function(additionalConfig, callback){ isAdditionalMode = true; - + exports.resolveConfig(additionalConfig, function (err, additionalConfig) { if (err) return callback(err); - + app.once(ready ? "ready-additional" : "ready", function(app){ callback(null, app); }); // What about error state? - + // Check the config - hopefully this works var _sortedPlugins = checkConfig(additionalConfig, function(name){ return services[name]; }); - + if (ready) { sortedPlugins = _sortedPlugins; // Start Loading additional plugins