├── .gitignore ├── .travis.yml ├── Changes.md ├── LICENSE ├── Readme.md ├── index.js ├── package.json └── test ├── controllers ├── .hidden │ └── stuff.js ├── main-Controller.js ├── notthis.js ├── other-Controller.js ├── sub-dir │ └── other-Controller.js └── unrelated │ └── foo.txt ├── filterdir ├── .svn │ └── stuff.js ├── root.js └── sub │ └── hello.js ├── mydir ├── .stuff.js ├── foo.js ├── hello.js └── sub │ ├── config.json │ ├── no.2js │ └── yes.js ├── resolved ├── onearg.js └── twoargs.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.un~ 2 | node_modules/ 3 | package-lock.json 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.8' 4 | - '0.10' 5 | - '0.12' 6 | - '1.8' 7 | - '2.5' 8 | - '3.3' 9 | - '4.9' 10 | - '5.12' 11 | - '6.14' 12 | - '7.10' 13 | - '8.11' 14 | - '9.11' 15 | - '10.5' 16 | 17 | sudo: false 18 | 19 | before_install: npm config set shrinkwrap false 20 | 21 | script: npm test 22 | -------------------------------------------------------------------------------- /Changes.md: -------------------------------------------------------------------------------- 1 | # Changes 2 | 3 | This file is a manually maintained list of changes for each release. Feel free 4 | to add your changes here when sending pull requests. Also send corrections if 5 | you spot any mistakes. 6 | 7 | ## v3.0.0 (2018-07-02) 8 | 9 | * Drop support for Node.js 0.6 and below #54 #56 10 | * Skip adding keys for directories without modules #51 #53 11 | 12 | ## v2.2.0 (2017-02-18) 13 | 14 | * Accept "filter" RegExps without any capture groups #43 #46 15 | 16 | ## v2.1.0 (2016-12-09) 17 | 18 | * Accept a function for "filter" option #27 #31 19 | 20 | ## v2.0.0 (2015-10-17) 21 | 22 | * Add "recursive" argument to control directory recursion #21 23 | * Default "excludeDirs" and "filter" if not provided in options #19 24 | * Ignore dot files & folder by default #12 25 | * Update the "map" property to map directory names #20 26 | 27 | ## Older releases 28 | 29 | These releases were done before maintaining this file: 30 | 31 | * [v1.1.0](https://github.com/felixge/node-require-all/compare/v1.0.0...v1.1.0) 32 | (2015-05-19) 33 | * [v1.0.0](https://github.com/felixge/node-require-all/compare/v0.0.8...v1.0.0) 34 | (2014-12-01) 35 | * [v0.0.8](https://github.com/felixge/node-require-all/compare/v0.0.6...v0.0.8) 36 | (2013-08-19) 37 | * [v0.0.6](https://github.com/felixge/node-require-all/compare/v0.0.4...v0.0.6) 38 | (2013-03-13) 39 | * [v0.0.4](https://github.com/felixge/node-require-all/compare/v0.0.3...v0.0.4) 40 | (2012-06-12) 41 | * [v0.0.3](https://github.com/felixge/node-require-all/compare/v0.0.2...v0.0.3) 42 | (2012-01-12) 43 | * [v0.0.2](https://github.com/felixge/node-require-all/compare/v0.0.1...v0.0.2) 44 | (2011-12-19) 45 | * [v0.0.1](https://github.com/felixge/node-require-all/commits/v0.0.1) 46 | (2011-12-14) 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # require-all 2 | 3 | An easy way to require all files within a directory. 4 | 5 | [![NPM Version][npm-image]][npm-url] 6 | [![NPM Downloads][downloads-image]][downloads-url] 7 | [![Build Status][travis-image]][travis-url] 8 | 9 | ## Usage 10 | 11 | ```js 12 | var controllers = require('require-all')({ 13 | dirname : __dirname + '/controllers', 14 | filter : /(.+Controller)\.js$/, 15 | excludeDirs : /^\.(git|svn)$/, 16 | recursive : true 17 | }); 18 | 19 | // controllers now is an object with references to all modules matching the filter 20 | // for example: 21 | // { HomeController: function HomeController() {...}, ...} 22 | ``` 23 | 24 | ## Advanced usage 25 | 26 | If your objective is to simply require all .js and .json files in a directory 27 | you can just pass a string to require-all: 28 | 29 | ``` js 30 | var libs = require('require-all')(__dirname + '/lib'); 31 | ``` 32 | 33 | ### Constructed object usage 34 | 35 | If your directory contains files that all export constructors, you can require 36 | them all and automatically construct the objects using `resolve`: 37 | 38 | ```js 39 | var controllers = require('require-all')({ 40 | dirname : __dirname + '/controllers', 41 | filter : /(.+Controller)\.js$/, 42 | resolve : function (Controller) { 43 | return new Controller(); 44 | } 45 | }); 46 | ``` 47 | 48 | ### Alternative property names 49 | 50 | If your directory contains files where the names do not match what you want in 51 | the resulting property (for example, you want camelCase but the file names are 52 | snake_case), then you can use the `map` function. The `map` function is called 53 | on both file and directory names, as they are added to the resulting object. 54 | 55 | ```js 56 | var controllers = require('require-all')({ 57 | dirname : __dirname + '/controllers', 58 | filter : /(.+Controller)\.js$/, 59 | map : function (name, path) { 60 | return name.replace(/_([a-z])/g, function (m, c) { 61 | return c.toUpperCase(); 62 | }); 63 | } 64 | }); 65 | ``` 66 | 67 | ### Filtering files 68 | 69 | If your directory contains files that you do not want to require, or that you 70 | want only a part of the file's name to be used as the property name, `filter` 71 | can be a regular expression. In the following example, the `filter` is set to 72 | `/^(.+Controller)\.js$/`, which means only files that end in "Controller.js" 73 | are required, and the resulting property name will be the name of the file 74 | without the ".js" extension. For example, the file "MainController.js" will 75 | match, and since the first capture group will contain "MainController", that 76 | will be the property name used. If no capture group is used, then the entire 77 | match will be used as the name. 78 | 79 | ```js 80 | var controllers = require('require-all')({ 81 | dirname : __dirname + '/controllers', 82 | filter : /^(.+Controller)\.js$/ 83 | }); 84 | ``` 85 | 86 | For even more advanced usage, the `filter` option also accepts a function that 87 | is invoked with the file name as the first argument. The filter function is 88 | expected to return a falsy value to ignore the file, otherwise a string to use 89 | as the property name. 90 | 91 | ```js 92 | var controllers = requireAll({ 93 | dirname : __dirname + '/controllers', 94 | filter : function (fileName) { 95 | var parts = fileName.split('-'); 96 | if (parts[1] !== 'Controller.js') return; 97 | return parts[0]; 98 | } 99 | }); 100 | ``` 101 | 102 | Note that empty directories are always excluded from the end result. 103 | 104 | [npm-image]: https://img.shields.io/npm/v/require-all.svg 105 | [npm-url]: https://npmjs.org/package/require-all 106 | [downloads-image]: https://img.shields.io/npm/dm/require-all.svg 107 | [downloads-url]: https://npmjs.org/package/require-all 108 | [travis-image]: https://img.shields.io/travis/felixge/node-require-all/master.svg 109 | [travis-url]: https://travis-ci.org/felixge/node-require-all 110 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | var DEFAULT_EXCLUDE_DIR = /^\./; 4 | var DEFAULT_FILTER = /^([^\.].*)\.js(on)?$/; 5 | var DEFAULT_RECURSIVE = true; 6 | 7 | module.exports = function requireAll(options) { 8 | var dirname = typeof options === 'string' ? options : options.dirname; 9 | var excludeDirs = options.excludeDirs === undefined ? DEFAULT_EXCLUDE_DIR : options.excludeDirs; 10 | var filter = options.filter === undefined ? DEFAULT_FILTER : options.filter; 11 | var modules = {}; 12 | var recursive = options.recursive === undefined ? DEFAULT_RECURSIVE : options.recursive; 13 | var resolve = options.resolve || identity; 14 | var map = options.map || identity; 15 | 16 | function excludeDirectory(dirname) { 17 | return !recursive || 18 | (excludeDirs && dirname.match(excludeDirs)); 19 | } 20 | 21 | function filterFile(filename) { 22 | if (typeof filter === 'function') { 23 | return filter(filename); 24 | } 25 | 26 | var match = filename.match(filter); 27 | if (!match) return; 28 | 29 | return match[1] || match[0]; 30 | } 31 | 32 | var files = fs.readdirSync(dirname); 33 | 34 | files.forEach(function (file) { 35 | var filepath = dirname + '/' + file; 36 | if (fs.statSync(filepath).isDirectory()) { 37 | 38 | if (excludeDirectory(file)) return; 39 | 40 | var subModules = requireAll({ 41 | dirname: filepath, 42 | filter: filter, 43 | excludeDirs: excludeDirs, 44 | map: map, 45 | resolve: resolve 46 | }); 47 | 48 | if (Object.keys(subModules).length === 0) return; 49 | 50 | modules[map(file, filepath)] = subModules; 51 | 52 | } else { 53 | var name = filterFile(file); 54 | if (!name) return; 55 | 56 | modules[map(name, filepath)] = resolve(require(filepath)); 57 | } 58 | }); 59 | 60 | return modules; 61 | }; 62 | 63 | function identity(val) { 64 | return val; 65 | } 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "require-all", 3 | "description": "An easy way to require all files within a directory.", 4 | "version": "3.0.0", 5 | "author": "Felix Geisendörfer (http://debuggable.com/)", 6 | "contributors": [ 7 | "Douglas Christopher Wilson ", 8 | "Prince Obiechine Onyenike ", 9 | "Nuno Job (http://nunojob.com)" 10 | ], 11 | "license": "MIT", 12 | "repository": "felixge/node-require-all", 13 | "files": [ 14 | "Changes.md", 15 | "LICENSE", 16 | "index.js", 17 | "Readme.md" 18 | ], 19 | "engines": { 20 | "node": ">= 0.8" 21 | }, 22 | "scripts": { 23 | "test": "node test/test.js" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/controllers/.hidden/stuff.js: -------------------------------------------------------------------------------- 1 | module.exports = { gute: 'nacht' }; 2 | -------------------------------------------------------------------------------- /test/controllers/main-Controller.js: -------------------------------------------------------------------------------- 1 | exports.index = 1; 2 | exports.show = 2; 3 | exports.add = 3; 4 | exports.edit = 4; 5 | -------------------------------------------------------------------------------- /test/controllers/notthis.js: -------------------------------------------------------------------------------- 1 | exports.yes = 'no'; 2 | -------------------------------------------------------------------------------- /test/controllers/other-Controller.js: -------------------------------------------------------------------------------- 1 | exports.index = 1; 2 | exports.show = 'nothing' 3 | -------------------------------------------------------------------------------- /test/controllers/sub-dir/other-Controller.js: -------------------------------------------------------------------------------- 1 | exports.index = 1; 2 | exports.show = 2; 3 | -------------------------------------------------------------------------------- /test/controllers/unrelated/foo.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/felixge/node-require-all/5c6c878dae8d63da77acd62789fb17300c190f7a/test/controllers/unrelated/foo.txt -------------------------------------------------------------------------------- /test/filterdir/.svn/stuff.js: -------------------------------------------------------------------------------- 1 | module.exports = { gute: 'nacht' }; 2 | -------------------------------------------------------------------------------- /test/filterdir/root.js: -------------------------------------------------------------------------------- 1 | module.exports = { guten: 'tag' }; 2 | -------------------------------------------------------------------------------- /test/filterdir/sub/hello.js: -------------------------------------------------------------------------------- 1 | module.exports = { guten: 'abend' }; 2 | -------------------------------------------------------------------------------- /test/mydir/.stuff.js: -------------------------------------------------------------------------------- 1 | module.exports = { gute: 'nacht' }; 2 | -------------------------------------------------------------------------------- /test/mydir/foo.js: -------------------------------------------------------------------------------- 1 | module.exports = 'bar'; 2 | -------------------------------------------------------------------------------- /test/mydir/hello.js: -------------------------------------------------------------------------------- 1 | exports.world = true; 2 | exports.universe = 42; 3 | -------------------------------------------------------------------------------- /test/mydir/sub/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "settingA": "A", 3 | "settingB": "B" 4 | } 5 | -------------------------------------------------------------------------------- /test/mydir/sub/no.2js: -------------------------------------------------------------------------------- 1 | module.exports = true; 2 | -------------------------------------------------------------------------------- /test/mydir/sub/yes.js: -------------------------------------------------------------------------------- 1 | module.exports = true; 2 | -------------------------------------------------------------------------------- /test/resolved/onearg.js: -------------------------------------------------------------------------------- 1 | module.exports = function (arg1, arg2) { 2 | return arg1; 3 | } 4 | -------------------------------------------------------------------------------- /test/resolved/twoargs.js: -------------------------------------------------------------------------------- 1 | module.exports = function (arg1, arg2) { 2 | return arg2; 3 | } 4 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var requireAll = require('..'); 3 | 4 | var controllers = requireAll({ 5 | dirname: __dirname + '/controllers', 6 | filter: /(.+Controller)\.js$/ 7 | }); 8 | 9 | assert.deepEqual(controllers, { 10 | 'main-Controller': { 11 | index: 1, 12 | show: 2, 13 | add: 3, 14 | edit: 4 15 | }, 16 | 17 | 'other-Controller': { 18 | index: 1, 19 | show: 'nothing' 20 | }, 21 | 22 | 'sub-dir': { 23 | 'other-Controller': { 24 | index: 1, 25 | show: 2 26 | } 27 | } 28 | }); 29 | 30 | var controllersTop = requireAll({ 31 | dirname: __dirname + '/controllers', 32 | filter: /(.+Controller)\.js$/, 33 | recursive: false 34 | }); 35 | 36 | assert.deepEqual(controllersTop, { 37 | 'main-Controller': { 38 | index: 1, 39 | show: 2, 40 | add: 3, 41 | edit: 4 42 | }, 43 | 44 | 'other-Controller': { 45 | index: 1, 46 | show: 'nothing' 47 | } 48 | }); 49 | 50 | var controllersMap = requireAll({ 51 | dirname: __dirname + '/controllers', 52 | filter: /(.+Controller)\.js$/, 53 | map: function (name) { 54 | return name.replace(/-([A-Z])/, function (m, c) { 55 | return '_' + c.toLowerCase(); 56 | }); 57 | } 58 | }); 59 | 60 | assert.deepEqual(controllersMap, { 61 | main_controller: { 62 | index: 1, 63 | show: 2, 64 | add: 3, 65 | edit: 4 66 | }, 67 | 68 | other_controller: { 69 | index: 1, 70 | show: 'nothing' 71 | }, 72 | 73 | 'sub-dir': { 74 | other_controller: { 75 | index: 1, 76 | show: 2 77 | } 78 | } 79 | }); 80 | 81 | var controllersMap = requireAll({ 82 | dirname: __dirname + '/controllers', 83 | filter: /.+Controller\.js$/ 84 | }); 85 | 86 | assert.deepEqual(controllersMap, { 87 | 'main-Controller.js': { 88 | index: 1, 89 | show: 2, 90 | add: 3, 91 | edit: 4 92 | }, 93 | 'other-Controller.js': { 94 | index: 1, 95 | show: 'nothing' 96 | }, 97 | 'sub-dir': { 98 | 'other-Controller.js': { 99 | index: 1, 100 | show: 2 101 | } 102 | } 103 | }); 104 | 105 | controllersMap = requireAll({ 106 | dirname: __dirname + '/controllers', 107 | filter: /(.+Controller)\.js$/, 108 | map: function (name) { 109 | return name.replace(/-([A-Za-z])/, function (m, c) { 110 | return '_' + c.toLowerCase(); 111 | }); 112 | } 113 | }); 114 | 115 | assert.deepEqual(controllersMap, { 116 | main_controller: { 117 | index: 1, 118 | show: 2, 119 | add: 3, 120 | edit: 4 121 | }, 122 | 123 | other_controller: { 124 | index: 1, 125 | show: 'nothing' 126 | }, 127 | 128 | sub_dir: { 129 | other_controller: { 130 | index: 1, 131 | show: 2 132 | } 133 | } 134 | }); 135 | 136 | controllersMap = requireAll({ 137 | dirname: __dirname + '/controllers', 138 | filter: /(.+Controller)\.js$/, 139 | map: function (name) { 140 | return name.replace(/-([A-Za-z])/, function (m, c) { 141 | return '_' + c.toLowerCase(); 142 | }); 143 | } 144 | }); 145 | 146 | assert.deepEqual(controllersMap, { 147 | main_controller: { 148 | index: 1, 149 | show: 2, 150 | add: 3, 151 | edit: 4 152 | }, 153 | 154 | other_controller: { 155 | index: 1, 156 | show: 'nothing' 157 | }, 158 | 159 | sub_dir: { 160 | other_controller: { 161 | index: 1, 162 | show: 2 163 | } 164 | } 165 | }); 166 | 167 | var mydir = requireAll({ 168 | dirname: __dirname + '/mydir' 169 | }); 170 | 171 | var mydir_contents = { 172 | foo: 'bar', 173 | hello: { 174 | world: true, 175 | universe: 42 176 | }, 177 | sub: { 178 | config: { 179 | settingA: 'A', 180 | settingB: 'B' 181 | }, 182 | yes: true 183 | } 184 | }; 185 | 186 | assert.deepEqual(mydir, mydir_contents); 187 | 188 | var defaults = requireAll(__dirname + '/mydir'); 189 | 190 | assert.deepEqual(defaults, mydir_contents); 191 | 192 | var unfiltered = requireAll({ 193 | dirname: __dirname + '/filterdir', 194 | filter: /(.+)\.js$/, 195 | excludeDirs: false 196 | }); 197 | 198 | assert(unfiltered['.svn']); 199 | assert(unfiltered.root); 200 | assert(unfiltered.sub); 201 | 202 | var excludedSvn = requireAll({ 203 | dirname: __dirname + '/filterdir', 204 | filter: /(.+)\.js$/, 205 | excludeDirs: /^\.svn$/ 206 | }); 207 | 208 | assert.equal(excludedSvn['.svn'], undefined); 209 | assert.ok(excludedSvn.root); 210 | assert.ok(excludedSvn.sub); 211 | 212 | var excludedSvnAndSub = requireAll({ 213 | dirname: __dirname + '/filterdir', 214 | filter: /(.+)\.js$/, 215 | excludeDirs: /^(\.svn|sub)$/ 216 | }); 217 | 218 | assert.equal(excludedSvnAndSub['.svn'], undefined); 219 | assert.ok(excludedSvnAndSub.root); 220 | assert.equal(excludedSvnAndSub.sub, undefined); 221 | 222 | var resolvedValues = requireAll({ 223 | dirname: __dirname + '/resolved', 224 | filter: /(.+)\.js$/, 225 | resolve: function (fn) { 226 | return fn('arg1', 'arg2'); 227 | } 228 | }); 229 | 230 | assert.equal(resolvedValues.onearg, 'arg1'); 231 | assert.equal(resolvedValues.twoargs, 'arg2'); 232 | 233 | var filterFunction = requireAll({ 234 | dirname: __dirname + '/controllers', 235 | filter: function (fileName) { 236 | var parts = fileName.split('-'); 237 | if (parts[1] !== 'Controller.js') return; 238 | return parts[0]; 239 | } 240 | }); 241 | 242 | assert.deepEqual(filterFunction, { 243 | 'main': { 244 | index: 1, 245 | show: 2, 246 | add: 3, 247 | edit: 4 248 | }, 249 | 250 | 'other': { 251 | index: 1, 252 | show: 'nothing' 253 | }, 254 | 255 | 'sub-dir': { 256 | 'other': { 257 | index: 1, 258 | show: 2 259 | } 260 | } 261 | }); 262 | --------------------------------------------------------------------------------