nor-mvc
Version:
Sendanor Model-View-Controller Module
286 lines (243 loc) • 7.94 kB
JavaScript
/* nor-mvc -- Model-View-Controller -- search-and-require.js */
;
if(process.browser) {
throw new TypeError("This file (nor-mvc:search-and-require.js) should not be in the bundle.");
}
require('ejs');
//var Q = require('q');
var util = require('util');
var debug = require('nor-debug');
var is = require('nor-is');
var PATH = require('path');
var FS = require('nor-fs');
var ARRAY = require('nor-array');
//var require_browserify;
//var require_browserify = require('./require-browserify.js');
//var default_layout = require('./mvc.layout.ejs');
/** Returns a predicate function for testing path extensions */
function has_extension(e) {
//if(process.env.DEBUG_MVC) {
// debug.log('has_extension(', e, ')');
//}
debug.assert(e).is('string');
return function has_extension_2(p) {
return PATH.extname(p) === e;
};
}
/** Returns a predicate function for testing sub extensions */
function has_sub_extension(e) {
//if(process.env.DEBUG_MVC) {
// debug.log('has_sub_extension(', e, ')');
//}
debug.assert(e).is('string');
return function has_sub_extension_2(p) {
var name = PATH.basename(p, PATH.extname(p));
return PATH.extname(name) === e;
};
}
/** Returns a predicate `function(path)` that will return `true` if path is a directory */
function is_directory(p) {
//if(process.env.DEBUG_MVC) {
// debug.log('is_directory(', p, ')');
//}
var stats = FS.sync.stat(p);
return stats.isDirectory() ? true : false;
}
/** Returns a predicate `function(path)` that will return `true` if result of `f(p)` was `false`, otherwise returns `false`. */
/*
function is_not(f) {
//if(process.env.DEBUG_MVC) {
// debug.log('is_not(', f, ')');
//}
debug.assert(f).is('function');
return function is_not_2(p) {
return f(p) ? false : true;
};
}
*/
/** Returns a predicate `function(path)` that will return `true` if result of `f1(p)` and `f2(p)` was `true`, otherwise returns `false`. */
function and(f1, f2) {
//if(process.env.DEBUG_MVC) {
// debug.log('and(', f1, ',', f2, ')');
//}
debug.assert(f1).is('function');
debug.assert(f2).is('function');
return function and_2(p) {
return (f1(p) && f2(p)) ? true : false;
};
}
/** Returns a predicate `function(path)` that will return `true` if result of `f1(p)` or `f2(p)` was `true`, otherwise returns `false`. */
function or(f1, f2) {
//if(process.env.DEBUG_MVC) {
// debug.log('or(', f1, ',', f2, ')');
//}
debug.assert(f1).is('function');
debug.assert(f2).is('function');
return function or_2(p) {
return (f1(p) || f2(p)) ? true : false;
};
}
/** Constructor for matched files */
function FoundFile(file) {
this.file = file;
}
/** Returns always `false` */
function nul() { return false; }
/** Search and collect all files from path
* @param opts.files {object|files} Save `FoundFile` objects into this object or array
* @returns {object} All matching files from path
*/
function search_and_collect(path, opts) {
if(process.env.DEBUG_MVC) {
debug.log('search_and_collect(', path, ',', opts, ')');
}
opts = opts || {};
debug.assert(path).is('string');
debug.assert(opts).is('object');
var primary_ext = opts.extension || '.js';
var sub_ext = opts.sub_extension;
var parent_name = opts.parent_name;
debug.assert(primary_ext).is('string');
debug.assert(sub_ext).ignore(undefined).is('string');
// opts.require_sub_extension
debug.assert(opts.require_sub_extension).ignore(undefined).is('boolean');
if(opts.require_sub_extension === undefined) {
opts.require_sub_extension = false;
}
//
function collect_file(file) {
if(is.array(opts.files)) {
opts.files.push(file);
} else if(is.obj(opts.files)) {
opts.files[file.file] = file;
}
return file;
}
//
if(!is_directory(path)) {
return collect_file(new FoundFile(path));
}
//var result_files = [];
var result = opts.result || {};
debug.assert(result).is('object');
var files = ARRAY(FS.sync.readdir(path)).map(function join_path(file) {
return PATH.join(path, file);
}).valueOf();
// Handle files
var logic = opts.require_sub_extension ? and : or;
ARRAY(files).filter(logic(has_extension(primary_ext), sub_ext ? has_sub_extension(sub_ext) : nul )).forEach(function each(file) {
var name = PATH.basename(file, PATH.extname(file));
if( sub_ext && has_extension(sub_ext)(name) ) {
name = PATH.basename(name, sub_ext);
}
if(parent_name) {
name = [parent_name, name].join('.');
}
if(result[name] !== undefined) {
//debug.warn('Multiple files conflicted for ', name, ' -- later takes preference: ', file );
throw new TypeError('Multiple files conflicted for ' + util.inspect(name) );
}
if(process.env.DEBUG_MVC) {
debug.log('result[', name, '] mapped to ', file);
}
result[name] = collect_file(new FoundFile(file));
});
// Handle sub directories
ARRAY(files).filter(is_directory).forEach(function each_2(dir) {
var name = PATH.basename(dir);
if(parent_name) {
name = [parent_name, name].join('.');
}
/*
if(result[name] !== undefined) {
//debug.warn('Multiple files conflicted for ', name, ' -- directory takes preference: ', dir);
throw new TypeError('Multiple files conflicted for ' + util.inspect(name) );
}
*/
search_and_collect(dir, {
'extension': primary_ext,
'sub_extension': sub_ext,
'require_sub_extension': opts.require_sub_extension,
'parent_name': name,
'result': result,
'files': opts.files
});
});
return result;
}
/** Search and
require all files from path
* @returns {object} All files in an object using `require()` by basenames
*/
function search_and_require(path, opts) {
//if(process.env.DEBUG_MVC) {
// debug.log('search_and_require(', path, ',', opts, ')');
//}
opts = opts || {};
debug.assert(path).is('string');
debug.assert(opts).is('object');
var primary_ext = opts.extension || '.js';
var sub_ext = opts.sub_extension;
var parent_name = opts.parent_name;
debug.assert(primary_ext).is('string');
debug.assert(sub_ext).ignore(undefined).is('string');
// opts.require_sub_extension
debug.assert(opts.require_sub_extension).ignore(undefined).is('boolean');
if(opts.require_sub_extension === undefined) {
opts.require_sub_extension = false;
}
//
if(! is_directory(path) ) {
return require(path);
}
var result = opts.result || {};
debug.assert(result).is('object');
var files = ARRAY(FS.sync.readdir(path)).map(function join_path(file) {
return PATH.join(path, file);
}).valueOf();
var logic = opts.require_sub_extension ? and : or;
ARRAY(files).filter(logic(has_extension(primary_ext), sub_ext ? has_sub_extension(sub_ext) : nul )).forEach(function each(file) {
var name = PATH.basename(file, PATH.extname(file));
if( sub_ext && has_extension(sub_ext)(name) ) {
name = PATH.basename(name, sub_ext);
}
if(parent_name) {
name = [parent_name, name].join('.');
}
if(result[name] !== undefined) {
//debug.warn('Multiple files conflicted for ', name, ' -- later takes preference: ', file );
throw new TypeError('Multiple files conflicted for ' + util.inspect(name) );
}
if(process.env.DEBUG_MVC) {
debug.log('result[', name, '] mapped to ', file);
}
result[name] = require( file );
result[name].file = file;
});
ARRAY(files).filter(is_directory).forEach(function each_2(dir) {
var name = PATH.basename(dir);
if(parent_name) {
name = [parent_name, name].join('.');
}
/*
if(result[name] !== undefined) {
//debug.warn('Multiple files conflicted for ', name, ' -- directory takes preference: ', dir);
throw new TypeError('Multiple files conflicted for ' + util.inspect(name) );
}
*/
search_and_require(dir, {
'extension': primary_ext,
'sub_extension': sub_ext,
'require_sub_extension': opts.require_sub_extension,
'parent_name': name,
'result': result
});
});
return result;
}
// Exports
module.exports = {
search_and_require: search_and_require,
search_and_collect: search_and_collect
};
/* EOF */