require-tree
Advanced tools
Comparing version 0.3.3 to 1.0.1
110
index.js
// require-tree | ||
// ============ | ||
// Batch module loader for nodejs | ||
/* | ||
require() a directory tree | ||
(c) Ricardo Tomasi 2012 | ||
(c) Ricardo Tomasi 2012-2015 | ||
License: MIT <ricardo.mit-license.org> | ||
@@ -11,22 +11,15 @@ | ||
var fs = require('fs') | ||
, path = require('path') | ||
var fs = require('fs') | ||
, path = require('path') | ||
, extend = require('extend') | ||
, type = require('component-type') | ||
function type (obj) { | ||
return Object.prototype.toString.call(obj) | ||
.match(/object\s(\w+)/, '')[1] | ||
.toLowerCase() | ||
} | ||
function isDirectory (fpath) { | ||
return fs.lstatSync(fpath).isDirectory() | ||
} | ||
function extend (obj, source) { | ||
for (var key in source){ | ||
if (source.hasOwnProperty(key)) { | ||
obj[key] = source[key] | ||
} | ||
function getFilter (filter) { | ||
switch (type(filter)) { | ||
case 'array' : filter = filter.join('|') | ||
case 'string' : filter = new RegExp('^('+filter.replace('*', '.*')+')$', 'i') | ||
case 'regexp' : filter = filter.exec.bind(filter) | ||
case 'function' : return filter | ||
} | ||
return obj | ||
// return undefined | ||
} | ||
@@ -37,27 +30,20 @@ | ||
options = extend({ | ||
index: true | ||
index: 'merge' | ||
}, options) | ||
var parentDir = path.dirname(module.parent.filename) | ||
, dir = path.resolve(parentDir, directory) | ||
var baseDir = process.env.NODE_PATH || path.dirname(module.parent.filename) | ||
, dir = path.resolve(baseDir, directory) | ||
, forbidden = ['.json', '.node'] | ||
, filter = options.filter | ||
, filter = getFilter(options.filter) || Boolean | ||
, tree = {} | ||
, files = fs.readdirSync(dir) | ||
var files = fs.readdirSync(dir) | ||
files.filter(filter).forEach(function(file){ | ||
switch (type(filter)) { | ||
case 'string' : filter = new RegExp(filter) | ||
case 'regexp' : filter = filter.exec.bind(filter) | ||
case 'function': files = files.filter(filter) | ||
} | ||
files.forEach(function(file){ | ||
var ext = path.extname(file) | ||
, name = path.basename(file, ext) | ||
, fpath = path.join(dir, file) | ||
, item, obj | ||
, exported, _exported | ||
if (isDirectory(fpath)) { | ||
if (fs.lstatSync(fpath).isDirectory()) { | ||
tree[file] = require_tree(fpath, options) | ||
@@ -67,21 +53,33 @@ return | ||
if ((!options.index && name === 'index') | ||
|| forbidden.indexOf(ext) >= 0 | ||
|| !(ext in require.extensions) | ||
) return | ||
if (forbidden.indexOf(ext) >= 0 || | ||
!(ext in require.extensions) || | ||
(name === 'index' && /ignore|false/.test(options.index))) { | ||
return | ||
} | ||
obj = item = require(fpath) | ||
exported = _exported = require(fpath) | ||
if (options.keys) { | ||
var keys = getFilter(options.keys) | ||
exported = {} | ||
Object.getOwnPropertyNames(_exported).forEach(function(key){ | ||
if (keys(key)) { | ||
exported[key] = _exported[key] | ||
} | ||
}) | ||
} | ||
switch (type(options.main)) { | ||
case 'string': | ||
obj = item[options.main] | ||
exported = exported[options.main] | ||
break | ||
case 'function': | ||
obj = options.main(item, file) | ||
exported = options.main(exported, file) | ||
break | ||
case 'array': | ||
obj = {} | ||
Object.keys(item).forEach(function(key){ | ||
if (options.main.indexOf(key) >= 0) | ||
obj[key] = item[key] | ||
exported = {} | ||
Object.getOwnPropertyNames(_exported).forEach(function(key){ | ||
if (options.main.indexOf(key) >= 0) { | ||
exported[key] = _exported[key] | ||
} | ||
}) | ||
@@ -92,16 +90,20 @@ } | ||
case 'string': | ||
name = item[options.name] | ||
name = exported[options.name] | ||
break | ||
case 'function': | ||
name = options.name(item, file) | ||
name = options.name(exported, file) | ||
} | ||
if (name === 'index') { | ||
extend(tree, obj) | ||
} else { | ||
tree[name] = obj | ||
if (type(options.transform) === 'function') { | ||
exported = options.transform(exported, file, path.join(dir, file)) | ||
} | ||
options.each && options.each(obj, file, path.join(dir, file)) | ||
if (name === 'index' && options.index === 'merge') { | ||
extend(tree, exported) | ||
} else { /* if name !== 'index' || options.index === 'preserve' */ | ||
tree[name] = exported | ||
} | ||
options.each && options.each(exported, file, path.join(dir, file)) | ||
}) | ||
@@ -115,2 +117,2 @@ | ||
// Necessary to get the current `module.parent` and resolve paths correctly. | ||
delete require.cache[__filename]; | ||
delete require.cache[__filename] |
{ | ||
"name": "require-tree", | ||
"description": "require() whole directory trees", | ||
"version": "0.3.3", | ||
"description": "Batch module loader, require() for directories", | ||
"version": "1.0.1", | ||
"main": "index.js", | ||
"dependencies": {}, | ||
"dependencies": { | ||
"component-type": "^1.1.0", | ||
"extend": "^2.0.0" | ||
}, | ||
"devDependencies": { | ||
@@ -32,4 +35,8 @@ "mocha": "" | ||
"loader", | ||
"api" | ||
"api", | ||
"batch", | ||
"module", | ||
"loading", | ||
"loader" | ||
] | ||
} |
180
README.md
require-tree | ||
============ | ||
![NPM badge](https://nodei.co/npm/require-tree.png?compact=true) | ||
![NPM](https://img.shields.io/npm/v/require-tree.svg?style=flat) | ||
Require multiple files at once, creating an object tree that mirrors the directory structure. | ||
A `require()`-like method for directories, returning an object that mirrors the file tree. | ||
npm install require-tree | ||
Usage | ||
----- | ||
## Usage | ||
var require_tree = require('require-tree') | ||
Considering this file structure: | ||
// File structure: | ||
// ./models | ||
// user.js | ||
// page.js | ||
// item.js | ||
* models | ||
* user.js | ||
* page.js | ||
* item.js | ||
require_tree('./models') | ||
Requiring the `models` directory will return an object containing each exported module: | ||
// { | ||
// user: [object Object], | ||
// page: [object Object], | ||
// item: [object Object] | ||
// } | ||
```javascript | ||
var require_tree = require('require-tree') | ||
require_tree('./models') | ||
/* { | ||
user: [object Object], | ||
page: [object Object], | ||
item: [object Object] | ||
} */ | ||
``` | ||
With nested directories: | ||
Directories can be deeply nested, and`index.js` files are merged into their parent by default: | ||
// ./api | ||
// /pages | ||
// index.js | ||
// edit.js | ||
// user.js | ||
```javascript | ||
// api/user.js: | ||
module.exports = { | ||
profile: function(){}, | ||
posts: function(){} | ||
} | ||
// api/pages/index.js: | ||
module.exports = { | ||
list: function(){ ... } | ||
} | ||
// api/pages/index.js: | ||
module.exports = { | ||
list: function(){} | ||
} | ||
// api/pages/edit.js: | ||
module.exports = { | ||
getPermissions: function(){ ... }, | ||
remove: function(){ ... } | ||
} | ||
// api/pages/edit.js: | ||
module.exports = { | ||
getPermissions: function(){}, | ||
remove: function(){} | ||
} | ||
// api/user.js: | ||
module.exports = { | ||
profile: function(){ ... }, | ||
posts: function(){ ... } | ||
} | ||
var api = require_tree('./api') | ||
``` | ||
var api = require_tree('./api') | ||
This will yield | ||
// api.pages.list | ||
// api.pages.edit.getPermissions | ||
// api.pages.edit.remove | ||
// api.user.profile | ||
// api.user.posts | ||
- `api.user.profile` | ||
- `api.user.posts` | ||
- `api.pages.list` | ||
- `api.pages.edit.getPermissions` | ||
- `api.pages.edit.remove` | ||
### Limitations | ||
### Options | ||
Since v0.3 `require-tree` will resolve paths relative to the requiring module, like `require` itself. | ||
```javascript | ||
require_tree(path, { options }) | ||
``` | ||
Since it depends on `module.parent` being set correctly, either `require-tree` must be explicitly required within the current module scope, or you need to provide an absolute path like `__dirname + '/somepath'`. | ||
#### { name: string | function (exports) } | ||
Use a property of the exports object as it's key (instead of the filename) in the final object. | ||
### Options | ||
```javascript | ||
// models/user-model.js | ||
module.exports = { | ||
id: 'user', | ||
attrs: {} | ||
} | ||
{ | ||
name : [String | Function(exports, file)] // the object's property to use as key | ||
main : [String | Array | Function(exports, file)] // what keys should be exported | ||
index : [Boolean] // load 'index.js' files (`true` by default) | ||
filter : [String | RegExp | Function] // filter pattern | ||
each : [Function] // callback to run after each module | ||
} | ||
require_tree('./models', { name: 'id' }) | ||
require_tree('./models', { name: function (obj) { return obj.id } }) | ||
// => { user: { id: 'user', attrs: {} } } | ||
``` | ||
#### { filter: string | regexp | function } | ||
Filter the required files. Strings can use a wildcard '*' and are expanded into regular expressions. You can also provide your own RegExp, or a function that receives the filename as an argument, and returns `true` or `false`. | ||
```javascript | ||
require_tree('./path', { filter: '*-model' }) | ||
require_tree('./path', { filter: /^model/ }) | ||
require_tree('./path', { filter: function (filename) { return filename.indexOf('model') === 0 } }) | ||
``` | ||
#### { keys: string | array | regexp | function } | ||
Use to return only certain keys from exported objects. | ||
```javascript | ||
require_tree('./models', { keys: 'at*' }) | ||
require_tree('./models', { keys: ['attrs'] }) | ||
require_tree('./models', { keys: function (key){ return key.indexOf('attrs') >= 0 } }) | ||
// => { user: { attrs: {} } } | ||
``` | ||
#### { each: function } | ||
Callback to run after each file is required. Doesn't modify the exported object. | ||
```javascript | ||
require_tree('./items', { each: function (obj) { items.insert(obj) } }) | ||
``` | ||
#### { transform: function } | ||
Same as `each`, but can modify the exports object. | ||
```javascript | ||
require_tree('./models', { transform: function (obj) { return new Model(obj) } }) | ||
``` | ||
#### index | ||
* `merge` (default): merges the `index.js` exports at the root of it's parent | ||
* `ignore`: causes `index.js` files to *not be loaded* at all | ||
* `preserve`: puts the `index.js` export object under the `.index` property | ||
For backwards compatibility, a value of `true` is equal to `preserve`, while `false` is equal to `ignore`. | ||
- controllers | ||
- index.js | ||
- users.js | ||
- ... | ||
```javascript | ||
// controllers/index.js: | ||
module.exports = { | ||
init: function () { ... } | ||
} | ||
var controllers = require_tree('./controllers', { index: 'preserve' }) | ||
controllers.index.init() | ||
var controllers = require_tree('./controllers', { index: 'ignore' }) | ||
controllers.index // undefined | ||
var controllers = require_tree('./controllers', { index: 'merge' }) | ||
controllers.init() | ||
``` | ||
### Limitations | ||
`require-tree` must always be required in the local scope, never shared between modules or as a global. Paths are resolved relative to the parent module, like `require` itself, so it's behaviour depends on `module.parent` being set correctly. If necessary, you can use absolute paths (`__dirname + '/path'`) or set the `NODE_PATH` environment variable. |
@@ -71,11 +71,46 @@ | ||
describe('when given the index:false option', function(){ | ||
describe('when given the index option', function(){ | ||
it('should ignore index files', function(){ | ||
var poa = require_tree('./porto-alegre', { index: false }) | ||
assert.deepEqual(poa, { | ||
bairros: bairros | ||
describe('preserve', function () { | ||
it('should put index under it\'s own key', function(){ | ||
var poa = require_tree('./porto-alegre', { index: 'preserve' }) | ||
assert.deepEqual(poa, { | ||
bairros: bairros, | ||
index: { city: POA.city } | ||
}) | ||
}) | ||
it('should put index under it\'s own key (index: true)', function(){ | ||
var poa = require_tree('./porto-alegre', { index: true }) | ||
assert.deepEqual(poa, { | ||
bairros: bairros, | ||
index: { city: POA.city } | ||
}) | ||
}) | ||
}) | ||
describe('merge', function () { | ||
it('should merge index at the root', function(){ | ||
var poa = require_tree('./porto-alegre', { index: 'merge' }) | ||
assert.deepEqual(poa, { | ||
bairros: bairros, | ||
city: POA.city | ||
}) | ||
}) | ||
}) | ||
describe('ignore', function () { | ||
it('should not load index', function(){ | ||
var poa = require_tree('./porto-alegre', { index: 'ignore' }) | ||
assert.deepEqual(poa, { | ||
bairros: bairros | ||
}) | ||
}) | ||
it('should not load index (index: false)', function(){ | ||
var poa = require_tree('./porto-alegre', { index: false }) | ||
assert.deepEqual(poa, { | ||
bairros: bairros | ||
}) | ||
}) | ||
}) | ||
}) | ||
@@ -97,2 +132,14 @@ | ||
describe('when given the transform option', function (){ | ||
it('should redefine the exports object', function(){ | ||
var bairros = require_tree('./porto-alegre/bairros', { | ||
transform: function(){ return null } | ||
}) | ||
assert.deepEqual(bairros, { | ||
'bomfim': null | ||
, 'santo-antonio': null | ||
}) | ||
}) | ||
}) | ||
describe('when given the name option', function(){ | ||
@@ -147,40 +194,19 @@ | ||
describe('when given the main option', function(){ | ||
describe('when given the keys option', function(){ | ||
describe('with a function', function(){ | ||
it('should run once for each file', function(){ | ||
it('should run once for each key', function(){ | ||
var x = 0 | ||
function increment(){ x++ } | ||
require_tree('./porto-alegre/bairros', { | ||
main: increment | ||
}) | ||
assert.equal(x, 2) | ||
require_tree('./porto-alegre/bairros', { keys: increment }) | ||
assert.equal(x, 6) | ||
}) | ||
it('should define the export object', function(){ | ||
it ('should filter the exports object', function(){ | ||
var bairros = require_tree('./porto-alegre/bairros', { | ||
main: function(){ | ||
return { nil: null } | ||
} | ||
keys: ['rating', 'zone'] | ||
}) | ||
assert.deepEqual(bairros, { | ||
'bomfim': { nil: null } | ||
, 'santo-antonio': { nil: null } | ||
}) | ||
}) | ||
it('should be able to access the export object', function(){ | ||
var bairros = require_tree('./porto-alegre/bairros', { | ||
main: function(obj){ | ||
return obj.rating | ||
} | ||
}) | ||
assert.deepEqual(bairros, { | ||
'bomfim': '*****' | ||
, 'santo-antonio': '***' | ||
}) | ||
}) | ||
}) | ||
@@ -190,5 +216,5 @@ | ||
it ('should filter the exports object', function(){ | ||
it('should filter the exports object', function(){ | ||
var bairros = require_tree('./porto-alegre/bairros', { | ||
main: ['rating', 'zone'] | ||
keys: ['rating', 'zone'] | ||
}) | ||
@@ -231,3 +257,3 @@ assert.deepEqual(bairros, { | ||
var res = require_tree('./porto-alegre/bairros', { | ||
filter: 'bom' | ||
filter: 'bom*' | ||
}) | ||
@@ -234,0 +260,0 @@ assert.deepEqual(res.bomfim, bairros.bomfim) |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
16541
13
330
1
153
2
3
+ Addedcomponent-type@^1.1.0
+ Addedextend@^2.0.0
+ Addedcomponent-type@1.2.2(transitive)
+ Addedextend@2.0.2(transitive)