Skip to content

Commit

Permalink
Removed Express-dependent Integration Test
Browse files Browse the repository at this point in the history
- Removed unnecessarily exposed loadLayers function of Layers.js
- Moved layer loading functions to Layers.Loader.js
  • Loading branch information
dave-elkan committed Jun 21, 2011
1 parent ec856dd commit f5d470e
Show file tree
Hide file tree
Showing 18 changed files with 285 additions and 302 deletions.
142 changes: 142 additions & 0 deletions lib/layers/Layers.Loader.js
@@ -0,0 +1,142 @@
var fs = require('fs'),
defaults = {
excludePrefix: "Base"
};

/**
* Loads the 'layers' of an application by loading their constituant
* files, instanciating them and adding them to the server object.
*
* @param server The server object (i.e. Express app).
* @param rootPath The path to the layers directory for this app.
* @param options An optional options object.
*/
function loadLayers(server, rootPath, options) {
options = merge(defaults, options);
getLayers(rootPath).forEach(function(layer) {
if (!server[layer]) {
server[layer] = {};
}

loadFiles(server, __dirname + '/layers/' + layer, layer, options);
loadFiles(server, rootPath + "/" + layer, layer, options);
});
}

/**
* Returns a list of layer names.
*
* Finds the directories in the root path supplied
* and returns their names as the layers this application
* makes use of.
*/
function getLayers(rootPath) {
var files = getDirectoryFileListSync(rootPath),
directories = [];

files.forEach(function(fileName) {
var fullPathToFile = rootPath + "/" + fileName;
if (isDirectory(fullPathToFile)) {
directories.push(fileName.toLowerCase());
}
});

return directories;
}

/**
* Recursively loads and instantiates javascript files within a path
* adding references to them under the current layer namespace on the
* supplied server object.
*/
function loadFiles(server, path, layer, options) {
var files = getDirectoryFileListSync(path);

files.forEach(function(fileName) {
var fullPathToFile = path + "/" + fileName;
if (isDirectory(fullPathToFile)) {
loadFiles(server, fullPathToFile, layer, options);
} else if (fileName.indexOf(options.excludePrefix) != 0 && fileName.indexOf(".js") === fileName.length - 3) {
var name = getRequireName(fileName),
item = require(path + "/" + name);

if (typeof item === "function") {
item = item(server);
}

server[layer][getInstanceName(name)] = item;
}
});
}

/**
* Synchronously returns a file list from a directory.
*/
function getDirectoryFileListSync(directory) {
var files = [];
if (dirExistsSync(directory) && isDirectory(directory)) {
files = fs.readdirSync(directory);
}

return files;
}

/**
* Synchronously checks to see whether a directory exists or not.
*/
function dirExistsSync (directory) {
try {
fs.statSync(directory);
return true;
} catch (err) {
return false;
}
}

/**
* Synchronously checks whether the file at the path specified is a
* directory or not.
*/
function isDirectory(file) {
try {
var stats = fs.statSync(file);
return stats.isDirectory();
} catch (err) {
return false;
}
}

/**
* Synchronously returns the name of the file sans .js suffix.
*/
function getRequireName(file) {
return file.substr(0, file.lastIndexOf(".js"));
}

/**
* Synchronously returns the name of an instance.
*
* i.e. The name of the file with the first letter lower case.
*/
function getInstanceName(name) {
return name[0].toLowerCase() + name.substr(1);
}

/**
* Synchronously merges two objects and returns the merged result.
*/
function merge(base, inst) {
var merged = {};
for (var p in base) {
merged[p] = base[p];
}
for (var p in inst || {}) {
merged[p] = inst[p];
}

return merged;
}

module.exports = {
loadLayers: loadLayers
};
150 changes: 23 additions & 127 deletions lib/layers/layers.js
@@ -1,14 +1,8 @@
var fs = require('fs'),
defaults = {
layers: [
"controllers",
"views"
],
excludePrefix: "Base"
},
loader = require('./Layers.Loader'),
defaulthandler = {
method: "get",
middleware: []
middleware: []
};

/**
Expand All @@ -23,9 +17,24 @@ var fs = require('fs'),
* @param wiring The wiring object. See Layers#setupWiring for more information.
* @param options An optional options object to override the defaults.
*/
var Layers = function(server, rootPath, wiring, options) {
loadLayers(server, rootPath, options);
this.setupWiring(server, wiring(server));
Layers = function(server, rootPath, wiring, options) {
loader.loadLayers(server, rootPath, options);
setupWiring.call(this, server, wiring(server));
};

/**
* This function must be defined in a framework-specific
* implementation of Layers to setup a route for that
* framework.
*
* See Layers.Express#setupRoute if you intend of implementing this function
* for a framework other than Express.
*
* @param path The path of the route to setup.
* @param handler The handler for this current route.
*/
Layers.prototype.setupRoute = function(path, handler) {
throw new Error("Must implement Layers::setupRoute");
};

/**
Expand Down Expand Up @@ -69,131 +78,18 @@ var Layers = function(server, rootPath, wiring, options) {
* cannot respond to the request then the next is tried until all of the
* handlers are extinguished at which point a 404 will be thrown.
*/
Layers.prototype.setupWiring = function(server, wiring) {
function setupWiring(server, wiring) {
var self = this;
for (var path in wiring) {
var handlers = wiring[path];
handlers.forEach(function(handler) {
self.setupRoute(server, path, merge(defaulthandler, handler));
});
}
};

/**
* This function must be defined in a framework-specific
* implementation of Layers to setup a route for that
* framework.
*
* See Layers.Express#setupRoute if you intend of implementing this function
* for a framework other than Express.
*
* @param path The path of the route to setup.
* @param handler The handler for this current route.
*/
Layers.prototype.setupRoute = function(path, handler) {
throw new Error("Must implement Layers::setupRoute");
};

/**
* Loads the 'layers' of an application by loading their constituant
* files, instanciating them and adding them to the server object.
*
* @param server The server object (i.e. Express app).
* @param rootPath The path to the layers directory for this app.
* @param options An optional options object.
*/
function loadLayers(server, rootPath, options) {
options = merge(defaults, options);
options.layers.forEach(function(layer) {
if (!server[layer]) {
server[layer] = {};
}

loadFiles(server, __dirname + '/layers/' + layer, layer, options);
loadFiles(server, rootPath + "/" + layer, layer, options);
});
}

/**
* Recursively loads and instantiates javascript files within a path
* adding references to them under the current layer namespace on the
* supplied server object.
*/
function loadFiles(server, path, layer, options) {
var files = getDirectoryFileListSync(path);

files.forEach(function(fileName) {
var fullPathToFile = path + "/" + fileName;
if (isDirectory(fullPathToFile)) {
loadFiles(server, fullPathToFile, layer, options);
} else if (fileName.indexOf(options.excludePrefix) != 0 && fileName.indexOf(".js") === fileName.length - 3) {
var name = getRequireName(fileName),
item = require(path + "/" + name);

if (typeof item === "function") {
item = item(server);
}

server[layer][getInstanceName(name)] = item;
}
});
}

/**
* Synchronously returns a file list from a directory.
*/
function getDirectoryFileListSync(directory) {
var files = [];
if (dirExistsSync(directory) && isDirectory(directory)) {
files = fs.readdirSync(directory);
}

return files;
}

/**
* Synchronously checks to see whether a directory exists or not.
*/
function dirExistsSync (directory) {
try {
fs.statSync(directory);
return true;
} catch (err) {
return false;
}
}

/**
* Synchronously checks whether the file at the path specified is a
* directory or not.
*/
function isDirectory(file) {
try {
var stats = fs.statSync(file);
return stats.isDirectory();
} catch (err) {
return false;
}
}

/**
* Returns the name of the file sans .js suffix.
*/
function getRequireName(file) {
return file.substr(0, file.lastIndexOf(".js"));
}

/**
* Returns the name of an instance.
*
* i.e. The name of the file with the first letter lower case.
*/
function getInstanceName(name) {
return name[0].toLowerCase() + name.substr(1);
}

/**
* Merges two objects and returns the merged result.
* Synchronously merges two objects and returns the merged result.
*/
function merge(base, inst) {
var merged = {};
Expand All @@ -203,7 +99,7 @@ function merge(base, inst) {
for (var p in inst || {}) {
merged[p] = inst[p];
}

return merged;
}

Expand Down
9 changes: 7 additions & 2 deletions package.json
Expand Up @@ -3,9 +3,14 @@
"description": "A package to help layered architecture for node.js",
"version": "0.0.1",
"repository": {
"url": "git://github.com/dave-elkan/node-layers.git"
"url": "git://github.com/dave-elkan/node-layers"
},
"author": "Dave Elkan <dave@edave.net> (http://www.edave.net)",
"contributors": [{
"name": "Dave Elkan",
"email": "dave@edave.net"
}
],
"directories": {
"lib": "lib"
},
Expand All @@ -18,6 +23,6 @@
"keywords": ["layers", "layered", "express", "connect", "web", "mvc", "architecture"],
"main": "index",
"engines": {
"node": ">= 0.2.6 < 0.5.0"
"node": ">= 0.4.1 < 0.5.0"
}
}

0 comments on commit f5d470e

Please sign in to comment.