{"id":22615607,"url":"https://github.com/marcellodesales/node-dirquire","last_synced_at":"2025-03-29T00:42:35.152Z","repository":{"id":142072880,"uuid":"48343408","full_name":"marcellodesales/node-dirquire","owner":"marcellodesales","description":"Load multiple Node.js modules from a given directory: filtering, error handling, less manual operations.","archived":false,"fork":false,"pushed_at":"2015-12-25T23:42:08.000Z","size":38,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-03T10:46:22.734Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marcellodesales.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-12-21T01:03:51.000Z","updated_at":"2015-12-21T04:47:19.000Z","dependencies_parsed_at":"2023-03-30T19:52:47.472Z","dependency_job_id":null,"html_url":"https://github.com/marcellodesales/node-dirquire","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcellodesales%2Fnode-dirquire","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcellodesales%2Fnode-dirquire/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcellodesales%2Fnode-dirquire/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcellodesales%2Fnode-dirquire/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcellodesales","download_url":"https://codeload.github.com/marcellodesales/node-dirquire/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246122247,"owners_count":20726822,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-08T19:08:30.011Z","updated_at":"2025-03-29T00:42:35.122Z","avatar_url":"https://github.com/marcellodesales.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# dirquire\n\n[![Travis](https://api.travis-ci.org/marcellodesales/node-dirquire.svg)](https://travis-ci.org/marcellodesales/node-dirquire) [![npm version](https://badge.fury.io/js/dirquire.svg)](http://badge.fury.io/js/dirquire) [![Codacy Badge](https://api.codacy.com/project/badge/grade/161387c5f4714867acf2e3cc8fbe9ba6)](https://www.codacy.com/app/marcellodesales/node-dirquire) [![Code Climate](https://codeclimate.com/github/marcellodesales/node-dirquire/badges/gpa.svg)](https://codeclimate.com/github/marcellodesales/node-dirquire) [![Dependency Status](https://david-dm.org/marcellodesales/node-dirquire.svg)](https://david-dm.org/marcellodesales/node-dirquire) [![devDependency Status](https://david-dm.org/marcellodesales/node-dirquire/dev-status.svg)](https://david-dm.org/marcellodesales/node-dirquire#info=devDependencies) [![Coverage Status](https://coveralls.io/repos/marcellodesales/node-dirquire/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/marcellodesales/node-dirquire?branch=master) ![License](https://img.shields.io/badge/license-MIT-lightgray.svg)\n\n[![NPM](https://nodei.co/npm/dirquire.png?downloads=true\u0026downloadRank=true\u0026stars=true)](https://nodei.co/npm/dirquire/)\n\n# Features\n\nHelps loading multiple modules from a given directory, avoiding multiple manual\nrequire statements in the module, allowing:\n\n* *Interface-based loading*: Load multiple modules from a given directory;\n* *Filtering*: Filtering which modules to load from a directory by file path;\n* *API Result*: Properly return the response as an API.\n\n# API\n\n## require(\"dirquire\")(dir, [filters]): array\n\n* *dir*: a valid path to a directory according to `fs.statSync(path).isDirectory()`.\n* *filters.extension*: optional parameter to filter file names.\n* *filters.depth*: loads files in a given depth.\n\nLoads all the files of a given\n\n```js\n  var loadedModules = require(\"dirquire\")(dir, [filters]);\n```\n\nThe result is an arry of the following api:\n\n```js\n  [{\n    fileName: \"The name of the file without the path.\",\n    filePath: \"The full path to the loaded file.\",\n    module: \"The instance of the loaded module. If an error occurs, it is undefined\",\n    error: \"The instance of the Error captured while loading the module.\"\n  }];\n```\n\nTake a look at the `fixtures` directory.\n\n## Example: Load modules without errors\n\nUsing the node cli, you can run the following fixtures used by the test cases.\n\n```js\n$ node\n\u003e require(\"dirquire\")(\"fixtures/all-modules-correct\")\n[ { fileName: 'hello.js',\n    filePath: '/home/mdesales/dev/github/marcellodesales/node-dirquire/fixtures/all-modules-correct/hello.js',\n    module: \n     { endpoint: '/hello',\n       contentType: 'text/plain',\n       init: [Function: decorate] } },\n  { fileName: 'secure.js',\n    filePath: '/home/mdesales/dev/github/marcellodesales/node-dirquire/fixtures/all-modules-correct/secure.js',\n    module: \n     { endpoint: '/secure',\n       contentType: 'text/plain',\n       init: [Function: decorate] } } ]\n```\n\n## Example: Load modules with errors\n\n* Files with syntax errors are not loaded.\n* Files that requires a module that is not located in the `node_modules`.\n\n```js\n$ node\n\u003e require(\"dirquire\")(\"fixtures/modules-with-error\")\n[ { fileName: 'illegal-token.js',\n    filePath: '/home/mdesales/dev/github/marcellodesales/node-dirquire/fixtures/modules-with-error/illegal-token.js',\n    error: [Error: Cannot load the module /home/mdesales/dev/github/marcellodesales/node-dirquire/fixtures/modules-with-error/illegal-token.js: Unexpected token ILLEGAL] },\n  { fileName: 'module-requiring-non-existent-module.js',\n    filePath: '/home/mdesales/dev/github/marcellodesales/node-dirquire/fixtures/modules-with-error/module-requiring-non-existent-module.js',\n    error: [Error: Cannot load the module /home/mdesales/dev/github/marcellodesales/node-dirquire/fixtures/modules-with-error/module-requiring-non-existent-module.js: Cannot find module 'passport-restify'] } ]\n```\n\n# Use\n\n## Simple Load\n\nLoading multiple modules with a given interface, without requiring all the modules from the\ngiven directory manually. Considering the routes directory containing `restify` or `express` routes:\n\n```sh\n$ tree my-app/routes/\nmy-app/routes/\n├── hello.js\n└── secure.js\n```\n\nEach route file implements the following interfaces: `endpoint`, `contentType`, and the function `init()`.\n\n```js\n\"use strict\";\n\n// Loads ANY logger under APP_DIR/middleware/logger\nvar logger = require(\"middleware-js\").instance().load(\"middleware/logger\");\n\n/**\n * The endpoint to be used.\n */\nmodule.exports.endpoint = \"/hello\";\n/**\n * The content type produced by this handler.\n */\nmodule.exports.contentType = \"text/plain\";\n/**\n * Decorates the server with a new route\n */\nmodule.exports.init = decorate;\n\n/**\n * Decorates the server instance with a simple hello\n */\nfunction decorate(server) {\n  logger.debug(\"Ready to annotate with the \" + module.exports.endpoint + \" route\");\n\n  // Annotate the server with a GET endpoint\n  // ATTENTION: YOU ARE REQUIRED TO CALL NEXT FOR RESTIFY TO CALL THE NEXT IN THE CHAIN!\n  // https://gist.github.com/LeCoupa/0664e885fd74152d1f90#file-1-restify-server-cheatsheet-js-L131-L146\n  server.get(module.exports.endpoint, function getHelloServerHandler(req, res, next) {\n\n    //console.log(logger === req.log); THIS IS TRUE. RESTIFY HAS AN INSTANCE OF THE LOGGER UNDER REQ\n    req.log.debug(\"Finished fulfilling request for \" + module.exports.endpoint);\n\n    res.header(\"Content-Type\", module.exports.contentType);\n    res.send(\"Hello... Be Intuitive!\");\n\n    next();\n  });\n}\n```\n\nThe following example loads all the routes with `dirquire`. \n\n* We can skip those routes that were not properly loaded;\n* Continue loading those that were properly loaded without application disruption;\n* Differently than other libraries such as `require-dir`, `dirquire` allows you to implement enterprise-gradle frameworks.\n\n```js\n  // Load the private routes not exposed\n  var _this = this;\n  var privateRoutes = [];\n\n  var routes = require(\"dirquire\")(__dirname + \"/routes\");\n  routes.forEach(function(route) {\n    if (route.error) { // problems loading the route does not prevent the application to be loaded.\n      logger.error(route.error, \"Error while loading the route\");\n      return; // continues the loop\n    }\n\n    logger.debug(\"Inializing route \" + route.module.endpoint);\n\n    // Call the route's \"init\" method... Note that the \"module\" is the reference of loaded module.\n    route.module.init(_this.server);\n\n    // Collecting the private routes$\n    privateRoutes.push({\n      endpoint: route.module.endpoint,\n      contentType: route.module.contentType\n    });\n  });\n\n  logger.info(privateRoutes, \"Loaded private routes\");\n```\n\n## Load with Filters and Directory Depth\n\nLoading multiple modules with a given interface, without requiring all the modules from the\ngiven directory manually. Considering the directory is as follows:\n\n```sh\n$ tree tasks\n./tasks/\n├── checkdeps\n│   └── checkdeps_tasks.js\n├── doc\n│   └── doc_tasks.js\n├── test\n│   └── test_tasks.js\n├── todo\n│   ├── todo_tasks.js\n│   └── xml-todos-serializer.js\n└── versioning\n    └── versioning_tasks.js\n```\n\nThe following example loads all the `_tasks.js` files, but not the `xml-todos-serializer.js`. The `depth` filter helps navigating to directories that contains more than modules required to be loaded.\n\n```js\n  var loadModules = require(\"dirquire\");\n\n  // Load the private routes not exposed\n  var filters = {\n    extension: \"*_task.js\",\n    depth: 1\n  };\n\n  // Setup each task\n  var Tasks = dirquire(dir, filters);\n  Tasks.forEach(function(Task) {\n    // Report that the task was loaded...\n    log.info(\"Verifying the task at \" + Task.filePath);\n\n    if (Task.error) {\n      // Report the error for instance...\n      log.error(Task.error.message);\n\n    } else {\n      // Execute the module\n      new Task.module().setup();\n    }\n  });\n```\n\nThe only observation is that all the returned objects must implement the same interface. In the case above,\nall the tasks are classes with the method `setup()`. That is a good application of the `Visitor` and `Iterator` Design-Patterns. \n\n# Contributing\n\nWe use the GitFlow branching mechanics, http://nvie.com/posts/a-successful-git-branching-model/.\n\n1. Fork it\n2. Create your feature branch (`git checkout -b feature/issue-XYZ origin/master --track`)\n * Adding Ids helps communicating where this feature is coming from.\n * You can also solve any open Issue in the issues tab.\n3. Commit your changes (`git commit -am 'Issue #XYZ: Add some feature to fix #444'`)\n * Adding \"fix #444\" will trigger a link to the GitHub issue #444.\n4. Push to the branch (`git push feature/issue-XYZ`)\n5. Create new Pull Request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcellodesales%2Fnode-dirquire","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcellodesales%2Fnode-dirquire","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcellodesales%2Fnode-dirquire/lists"}