Comparing version 0.0.1 to 0.1.0
"use strict"; | ||
var conf = null; | ||
var async = require( 'async' ); | ||
var moduleConfig = null; | ||
module.exports.init = function ( params, callback ) { | ||
module.exports.init = function ( config, callback ) { | ||
conf = { | ||
moduleConfig = { | ||
express: null, | ||
storage: null | ||
}.mixin( params ); | ||
}.mixin( config ); | ||
if ( !conf.express ) { | ||
if ( !config.express ) { | ||
throw "no express supplied to core"; | ||
} | ||
if ( !conf.storage ) { | ||
if ( !config.storage ) { | ||
throw "no storage supplied to core"; | ||
@@ -26,17 +27,13 @@ } | ||
function dereferencePointers( conf, environment, callback, context ) { | ||
callback( conf ); | ||
} | ||
function getAuthKey( req ) { | ||
function applyInheritance( conf, environment, callback, context ) { | ||
callback( conf ); | ||
return { key: null }.mixin( req.query ).key || req.header( 'key' ); | ||
} | ||
function getAuthKey( req ) { | ||
return { key: null }.mixin( req.query ).key || req.header( 'key' ); | ||
} | ||
function checkAuth( req, res, next ) { | ||
var key = getAuthKey( req ); | ||
conf.storage.isAuthorized( key, function ( authorized ) { | ||
moduleConfig.storage.isAuthorized( key, function ( authorized ) { | ||
if ( authorized ) { | ||
@@ -52,3 +49,3 @@ next(); | ||
function onPutConf( req, res ) { | ||
function onPostConf( req, res ) { | ||
@@ -62,3 +59,4 @@ res = getResponder( req, res ); | ||
} | ||
conf.storage.setConf( path, JSON.parse( req.body ), function ( err ) { | ||
moduleConfig.storage.setConf( path, JSON.parse( req.body ), function ( err ) { | ||
if ( err ) { | ||
@@ -75,5 +73,5 @@ res( 500 ); | ||
function onGetConf( req, res ) { | ||
res = getResponder( req, res ); | ||
var path = getPath( req ); | ||
var environment = { env: '*' }.mixin( req.query ).env; | ||
@@ -85,19 +83,90 @@ if ( !path ) { | ||
conf.storage.getConf( path, function ( err, conf ) { | ||
// strip environment from path | ||
var environment = path.replace( /^\.([^\.]*)\.?.*/, '$1' ); | ||
path = path.replace( /^\.[^\.]*\.?/, '' ); | ||
if ( err && err !== 'could not retrieve conf' ) { | ||
res( 500 ); | ||
return; | ||
if ( path.length < 1 ) { | ||
res( 400 ); | ||
} | ||
getConf( path, environment, function ( conf ) { | ||
if ( conf === null ) { | ||
res( 404 ); | ||
} | ||
applyInheritance( conf, environment, function ( conf ) { | ||
dereferencePointers( conf, environment, function ( conf ) { | ||
if ( conf === null ) { | ||
res( 404 ); | ||
else { | ||
res( 200, conf ); | ||
} | ||
} ); | ||
} | ||
/** | ||
* getConf is responsible for the core logic in the API. It handles applying all extensions and wildcard lookups. | ||
* | ||
* External Params: | ||
* @param path the dot notation path to pull from the storage engine | ||
* @param environment the name of the environment to pull the configuration for | ||
* @param callback | ||
* | ||
* Recursive Params: | ||
* @param context | ||
*/ | ||
function getConf( path, environment, callback, context ) { | ||
// relative paths need to be auto-prefixed with the environment | ||
if ( path.match( /^[^\.]/ ) ) { | ||
path = "." + environment + "." + path; | ||
} | ||
if ( !context ) { | ||
context = { | ||
pathsSeen: {} | ||
}; | ||
} | ||
// avoid circular references | ||
if ( context.pathsSeen[path] ) { | ||
callback( undefined ); | ||
return; | ||
} | ||
context.pathsSeen[path] = true; | ||
// calculate catch all path | ||
var catchAllPath = ".*." + path.replace( /^\.[^\.]*\./, '' ); | ||
if ( catchAllPath === path ) { | ||
catchAllPath = false; | ||
} | ||
// try exact path | ||
moduleConfig.storage.getConf( path, function ( err, conf ) { | ||
// if there was an error, don't try for wildcard | ||
if ( err ) { | ||
callback( undefined ); | ||
} | ||
// not found, try wildcard | ||
else if ( conf === null && catchAllPath ) { | ||
moduleConfig.storage.getConf( catchAllPath, function ( err, conf ) { | ||
// error searching for wild card | ||
if ( err ) { | ||
callback( undefined ); | ||
} | ||
// wild card found | ||
else { | ||
res( 200, conf ); | ||
applyAbstractions( conf, environment, context, callback ); | ||
} | ||
} ); | ||
} ); | ||
} | ||
// exact path found | ||
else { | ||
applyAbstractions( conf, environment, context, callback ); | ||
} | ||
} ); | ||
@@ -107,2 +176,98 @@ | ||
function applyAbstractions( conf, environment, context, callback ) { | ||
// only arrays and objects can have abstraction, everything else just returns | ||
if ( !Array.isArray( conf ) && !Object.isObject( conf ) ) { | ||
callback( conf ); | ||
return; | ||
} | ||
var pathsToExtend = []; | ||
var currentPath = null; | ||
var currentPathRef = null; | ||
var currentPathRefTemp = null; | ||
var currentSubTree = null; | ||
var currentPathTail = null; | ||
// seed the inspection loop | ||
var pathsToCheck = [ | ||
['seed'] | ||
]; | ||
conf = { | ||
seed: conf | ||
}; | ||
function extendPath( extendedPath, currentPathRef, override ) { | ||
pathsToExtend.push( function ( callback ) { | ||
getConf( extendedPath, environment, function ( conf ) { | ||
if ( override && conf ) { | ||
conf = conf.mixin( override ); | ||
} | ||
callback( null, { | ||
path: currentPathRef, | ||
conf: conf | ||
} ); | ||
}, context ); | ||
} ); | ||
} | ||
while ( pathsToCheck.length > 0 ) { | ||
// get current path and subtree on that path | ||
currentPath = pathsToCheck.pop(); | ||
currentPathRef = currentPath.clone(); // we need an unmodified current path for later | ||
currentSubTree = conf; // we start at the root | ||
currentPathTail = currentPath.pop(); // we don't dereference the last field, because we want to modify it in place | ||
while ( currentPath.length > 0 ) { | ||
currentSubTree = currentSubTree[ currentPath.shift() ]; | ||
} | ||
// seed pathsToCheck | ||
if ( Array.isArray( currentSubTree[currentPathTail] ) ) { | ||
for ( var i = 0; i < currentSubTree[currentPathTail].length; i++ ) { | ||
currentPathRefTemp = currentPathRef.clone(); | ||
currentPathRefTemp.push( i ); | ||
pathsToCheck.push( currentPathRefTemp ); | ||
} | ||
} | ||
else if ( Object.isObject( currentSubTree[currentPathTail] ) ) { | ||
if ( currentSubTree[currentPathTail].__extend ) { | ||
extendPath( currentSubTree[currentPathTail].__extend, currentPathRef.clone(), currentSubTree[currentPathTail].__override || null ); | ||
} | ||
else { | ||
for ( var field in currentSubTree[currentPathTail] ) { | ||
if ( currentSubTree[currentPathTail].hasOwnProperty( field ) ) { | ||
currentPathRefTemp = currentPathRef.clone(); | ||
currentPathRefTemp.push( field ); | ||
pathsToCheck.push( currentPathRefTemp ); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
if ( pathsToExtend.length > 0 ) { | ||
async.parallel( pathsToExtend, function ( err, results ) { | ||
if ( Array.isArray( results ) ) { | ||
for ( var i = 0; i < results.length; i++ ) { | ||
currentPath = results[i].path; | ||
currentSubTree = conf; | ||
currentPathTail = currentPath.pop(); // we don't dereference the last field, because we want to modify it in place | ||
while ( currentPath.length > 0 ) { | ||
currentSubTree = currentSubTree[ currentPath.shift() ]; | ||
} | ||
currentSubTree[currentPathTail] = results[i].conf; | ||
} | ||
} | ||
callback( conf.seed ); | ||
} ); | ||
} | ||
else { | ||
callback( conf.seed ); | ||
} | ||
} | ||
function onDeleteConf( req, res ) { | ||
@@ -117,3 +282,3 @@ res = getResponder( req, res ); | ||
conf.storage.delConf( path, function ( err ) { | ||
moduleConfig.storage.delConf( path, function ( err ) { | ||
if ( err ) { | ||
@@ -128,4 +293,4 @@ res( 500 ); | ||
function onPutAuth( req, res ) { | ||
conf.storage.generateAuthKey( function ( key ) { | ||
function onPostAuth( req, res ) { | ||
moduleConfig.storage.generateAuthKey( function ( key ) { | ||
res = getResponder( req, res ); | ||
@@ -143,3 +308,3 @@ if ( key ) { | ||
var key = getAuthKey( req ); | ||
conf.storage.delAuthKey( key, function ( err ) { | ||
moduleConfig.storage.delAuthKey( key, function ( err ) { | ||
res = getResponder( req, res ); | ||
@@ -165,3 +330,3 @@ | ||
var path = req.path.replace( /\//g, '.' ).replace( /^\.conf\./, '' ); | ||
var path = req.path.replace( /\//g, '.' ).replace( /^\.conf/, '' ).replace( /\.$/, '' ); | ||
@@ -177,7 +342,7 @@ if ( path.length < 1 ) { | ||
function storeRequestBody( req, res, next ) { | ||
var body = ""; | ||
req.setEncoding( 'utf8' ); | ||
console.log( 'hi' ); | ||
req.on( 'data', function ( data ) { | ||
console.log( 'got data', data ); | ||
body += data; | ||
@@ -187,3 +352,2 @@ } ); | ||
req.on( 'end', function () { | ||
console.log( 'end' ); | ||
req.body = body; | ||
@@ -201,9 +365,9 @@ next(); | ||
// create configuration routes | ||
conf.express.get( /^\/conf.*/, checkAuth, getMiddlewareWrapper( onGetConf ) ); | ||
conf.express.put( /^\/conf.*/, storeRequestBody, checkAuth, getMiddlewareWrapper( onPutConf ) ); | ||
conf.express.delete( /^\/conf.*/, checkAuth, getMiddlewareWrapper( onDeleteConf ) ); | ||
moduleConfig.express.get( /^\/conf.*/, checkAuth, getMiddlewareWrapper( onGetConf ) ); | ||
moduleConfig.express.post( /^\/conf.*/, storeRequestBody, checkAuth, getMiddlewareWrapper( onPostConf ) ); | ||
moduleConfig.express.delete( /^\/conf.*/, checkAuth, getMiddlewareWrapper( onDeleteConf ) ); | ||
// create auth management routes | ||
conf.express.put( "/auth", checkAuth, getMiddlewareWrapper( onPutAuth ) ); | ||
conf.express.delete( "/auth", checkAuth, getMiddlewareWrapper( onDeleteAuth ) ); | ||
moduleConfig.express.post( "/auth", checkAuth, getMiddlewareWrapper( onPostAuth ) ); | ||
moduleConfig.express.delete( "/auth", checkAuth, getMiddlewareWrapper( onDeleteAuth ) ); | ||
@@ -210,0 +374,0 @@ } |
@@ -5,3 +5,3 @@ { | ||
"author": "Anthony Hildoer <anthony@bluerival.com>", | ||
"version": "0.0.1", | ||
"version": "0.1.0", | ||
"repository": { | ||
@@ -14,3 +14,4 @@ "type": "git", | ||
"redis": "~0", | ||
"core-extensions": "~0" | ||
"core-extensions": "~0", | ||
"async": "~0" | ||
}, | ||
@@ -17,0 +18,0 @@ "keywords": [ |
@@ -71,11 +71,11 @@ "use strict"; | ||
module.exports.getConf = function ( key, callback ) { | ||
getRaw( key, 'conf', callback ); | ||
getRaw( key, 'moduleConfig', callback ); | ||
}; | ||
module.exports.setConf = function ( key, conf, callback ) { | ||
setRaw( key, 'conf', conf, callback ); | ||
setRaw( key, 'moduleConfig', conf, callback ); | ||
}; | ||
module.exports.delConf = function ( key, callback ) { | ||
delRaw( key, 'conf', callback ); | ||
delRaw( key, 'moduleConfig', callback ); | ||
}; | ||
@@ -130,9 +130,7 @@ | ||
data = decodeData( data ); | ||
if ( err || !data ) { | ||
executeCallback( callback, "could not retrieve " + type, null ); | ||
if ( err ) { | ||
executeCallback( callback, err, null ); | ||
} | ||
else { | ||
executeCallback( callback, null, data ); | ||
executeCallback( callback, null, decodeData( data ) ); | ||
} | ||
@@ -139,0 +137,0 @@ |
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
21250
19
686
4
+ Addedasync@~0
+ Addedasync@0.9.2(transitive)