GithubHelp home page GithubHelp logo

patrick-steele-idem / app-module-path-node Goto Github PK

View Code? Open in Web Editor NEW
411.0 11.0 28.0 33 KB

Simple module to add additional directories to the Node module search for top-level app modules

License: BSD 2-Clause "Simplified" License

JavaScript 100.00%

app-module-path-node's Introduction

NPM

app-module-path

This simple module enables you to add additional directories to the Node.js module search path (for top-level app modules only). This allows application-level modules to be required as if they were installed into the node_modules directory.

Installation

npm install app-module-path --save

Usage

// ***IMPORTANT**: The following line should be added to the very
//                 beginning of your main script!
require('app-module-path').addPath(baseDir);

IMPORTANT: The search path should be modified before any modules are loaded!

Example:

In your my-app/index.js (or my-app/server.js) file:

// Add the root project directory to the app module search path:
require('app-module-path').addPath(__dirname);

Given the following example directory structure:

  • my-app/
    • src/ - Source code and application modules directory
      • foo/ - A module directory
        • index.js
      • bar/ - Another module directory
        • index.js
    • node_modules/ - Installed modules
      • installed-baz/ - An installed module
        • index.js
    • index.js - Main script

The following will work for any modules under the src directory:

// All of the following lines will work in "src/foo/index.js" and "src/bar/index.js":
var foo = require('src/foo'); // Works
var bar = require('src/bar'); // Works
var baz = require('installed-baz'); // Works

Lastly, by design, installed modules (i.e. modules under the node_modules directory) will not be able to require application-level modules so the following will not work:

// All of the following lines will *not* work in "node_modules/installed-baz/index.js"!
var foo = require('src/foo'); // Fails
var bar = require('src/bar'); // Fails

Alternate Usage (app-module-path/register)

This module supports an alternate method of adding a path to the Node.js module search path that requires less code. Requiring or importing the app-module-path/register module will result in the directory of the calling module being added to the Node.js module search path as shown below:

Explicitly enabling a directory/package

By default, app-module-path will not attempt to resolve app modules from a directory that is found to be within a node_modules directory. This behavior can be changed by explicitly enabling app-module-path to work for descendent modules of a specific directory. For example:

var packageDir = path.dirname(require.resolve('installed-module-allowed'));
require('../').enableForDir(packageDir);

ES5

require('app-module-path/register');

// Is equivalent to:
require('app-module-path').addPath(__dirname);

ES6

import "app-module-path/register";

// Is equivalent to:
import { addPath } from 'app-module-path';
addPath(__dirname);

Alternative Usage (app-module-path/cwd)

Additionally, requiring or importing app-module-path/cwd will result in the current working directory of the Node.js process being added to the module search path as shown below:

ES5

require('app-module-path/cwd');

// Is equivalent to:
require('app-module-path').addPath(process.cwd());

ES6

import "app-module-path/cwd";

// Is equivalent to:
import { addPath } from 'app-module-path';
addPath(process.cwd());

Additional Notes

  • Search path order:

    • App module paths will be added to the end of the default module search path. That is, if a module with the same name exists in both a node_modules directory and an application module directory then the module in the node_modules directory will be loaded since it is found first. This behavior is new in v2.x. In v1.x, this search order was reversed
  • Node.js compatibility:

    • This module depends on overriding/wrapping a built-in Node.js method, and it is possible (but unlikely) that this behavior could be broken in a future release of Node.js (at which point a workaround would need to be used)
    • This module will not change or break modules installed into the node_modules directory.
  • Recommendations:

    • Since this module changes the Node.js convention of how non-relative modules are resolved, it is recommended (but not required) to put all app modules in a common directory below the application root (such as my-app/src or my-app/app_modules) and then to add the application root to the search path. The require calls would then be something like require('src/foo') or require('app_modules/foo'). The common prefix makes it more clear that the module can be found in the application's modules directory and not in the node_modules directory.

Contribute

Pull requests, bug reports and feature requests welcome.

License

BSD-2-Clause

app-module-path-node's People

Contributors

ajoslin avatar aputinski avatar dizlexik avatar highflying avatar mlrawlings avatar patrick-steele-idem avatar philidem avatar timaschew avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

app-module-path-node's Issues

Can't load `constants`

Not sure if this is an issue here or elsewhere, but I can't load a file in our application called constants. It instead seems to load something maybe out of node core:

var Constants = require('constants');
console.log('constants: ', Constants);

Result, not our constants:

constants:  { E2BIG: 7,
  EACCES: 13,
  EADDRINUSE: 98,
  EADDRNOTAVAIL: 99,
  EAFNOSUPPORT: 97,
  EAGAIN: 11,
  EALREADY: 114,
  EBADF: 9,
  EBADMSG: 74,
  EBUSY: 16,
  ECANCELED: 125,
  ECHILD: 10,
  ECONNABORTED: 103,
  ECONNREFUSED: 111,
  ECONNRESET: 104,
  ...

Other files I require from my application seem to be fine, though, so not sure what the deal is with this one. We only have one file named constants.js in our project, and don't have any constants folder in our node_modules.

How about variables in paths?

How about configuring variables and using them in paths? That would be less dynamic and therefore has more of a chance of working in client-side settings, too. For example:

require('app-module-path').setVar('ROOT', __dirname);

var foo = require('$ROOT/src/foo');

ES6 support

This works

require('app-module-path').addPath(__dirname);
const models = require('app/models');
models.User.findOne({ where: { id: 1 } }).then(user => {
  console.log(user.toJSON());
  return user;
});

The following snippet not working

require('app-module-path').addPath(__dirname);
import models from 'app/models';        // error: cannot resolve path 'app/models'
models.User.findOne({ where: { id: 1 } }).then(user => {
  console.log(user.toJSON());
  return user;
});

Implement option to choose v1.X or v2.X behaviour

Because of reasons i often prefer to unshift the module path array, rather than push onto as is the default behaviour since v2.

Perhaps one could pass an options, ie

require('app-module-path').addPath(p.join(PWD, 'node_modules', { method: 'unshift'; }));

or implement two seperate functions, ie

require('app-module-path').pushPath(p.join(PWD, 'node_modules'));
require('app-module-path').unshiftPath(p.join(PWD, 'node_modules'));

Could this be in a setup file?

Hi,

I really like your module, and have used it in the past, but I have a quick question for my current project.

I'd like to have a setup.js file which looks like this:

require('babel/polyfill');
require('app-module-path').addPath(__dirname);
require('dotenv').load();

Then in my index.js file:

require('./setup');
// something something something. This is a really cool file
var http = require('http')
// ...

Would that work?

Aliasing a path?

I really like this module, but there is something I would like to know.

Within the root of my project, i have app, config, cache and more such folders. Now, within the app folder, I have my entire app. That app is a hybrid PHP/NodeJS app. The root namespace is BIRD3\. And with WebPack, I can alias {BIRD3: "./app"} just fine.

But is there such way for NodeJS?

// ... magically alias app/ to be BIRD3
var worker = require("BIRD3/Backend/Service/JobWorker");

Kind regards, Ingwie.

Mocha OPTS

How can I include the module on Mocha config file (mocha.opts)?

-r, --require <name>                    require the given module

This will not work

--require('app-module-path').addPath('../');

This will work, but how to define the root?

--require app-module-path

not working with module package

Hi

in my package.json I have "type": "module"

{
    "type": "module",
    "main": "./server/main.js",
    "scripts": {
        "hello": "echo \"Hello\" && exit 1",
        "debug": "ndb main.js",
        "dev": "nodemon main.js",
        "start": "node main.js",
        "dev-docker": "nodemon --legacy-watch main.js"
    }
}

jsconfig.json

{
  "compilerOptions": {
    "baseUrl": "server", /*./src This is where all your code is*/
  },
  "include": ["server"]
}

In main.js

import { addPath } from 'app-module-path';
addPath(process.cwd())

trying to import like
import { authenticate, developer } from '/server/middlewares/all.js'

but getting error

ode:internal/errors:464

ErrorCaptureStackTrace(err);

^


Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/server/middlewares/all.js' imported from /app/server/routes/hello.js

at new NodeError (node:internal/errors:371:5)

at finalizeResolution (node:internal/modules/esm/resolve:321:11)

at moduleResolve (node:internal/modules/esm/resolve:756:10)

at Loader.defaultResolve [as _resolve] (node:internal/modules/esm/resolve:867:11)

at Loader.resolve (node:internal/modules/esm/loader:89:40)

at Loader.getModuleJob (node:internal/modules/esm/loader:242:28)

at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)

at link (node:internal/modules/esm/module_job:75:36) {

code: 'ERR_MODULE_NOT_FOUND'

}

environment
node 16
docker

make a note about the order of the path

image this case:

I have a module foo in my local source which I added via app-module-path-node
and the same module exist in node_modules.

in your code I see you make an unshift so the custom path will be checked first, right?
can you make a note in the readme about that?

Module loading not happening

CONTEXT
Node 9.10.1
Webstorm 2018
App-module-path v2.2.0
App module path is in node_modules - installed via npm

STRUCTURE:
node_modules is a sibling of dist
dev
---DB
---services
------firstService.js
---sharedModules
------moduleA
---------deriveFoo.js

CODE:
I have a firstService.js in the services folder that has a require statement -
require(sharedModules/moduleA/deriveFoo.js)

Webstorm is configured to start the server with serverStart.js containing the following lines:
require('app-module-path').addPath(__dirname + '/dist/server/dev/sharedModules');
require('./dist/server/dev').init(9001, 'dev');

My module is not being found, and Node server stops with Error that the deriveFoo module can't be found.

Please help
Thanks

Cannot add path '../modules'?

I need to add the custom resolve path '../modules' to node but can't seem to do so?

What am I missing in using this module correct?

Below 'router' is called from a module 'app/index.js' and I have a modules folder for shared modules a level up.

require('app-module-path').addPath('../modules');
const Router = require('router');

How to get vscode intellisense??

I'm using this lib for addressing modules in my project but I lose Intellisense in vscode editor.
anyone know how to handle this issue?

Jest

it doesn't work when running jest. any ideas?

unable to resolve my modules

Hi,

I'm trying to use this module in my application. it is working fine.
Now, i'm trying to make a feature of my application as a module and try to use your module with in that module, this time it is giving problem and not resolving my module submodules.

Here is the folder structure:

App-
      - server.js
      - node_modules
                 -myModule
                             - index.js
                             - lib
                                  - conf
                                       - ConfigMgr.js
                                  - processors
                                       - DataProcessor.js
                           - node_modules
                                    app-module-path

server.js : 
      require('myModule');

myModule/index.js : 
var amp = require('app-module-path')
amp.addPath(path.join(__dirname, "lib");

var DataProcessor = require("processors/DataProcessor");
module.exports = DataProcessor

myModule/lib/processors/DataProcessor:
     var ConfigMgr = require("conf/ConfigMgr"); -- failing here. 

The same structure worked fine as an application. But when i tried it as a module, it is not resolving the packages.

Please add a LICENSE file

This is a very minor issue, but I think it's really good idea to have a license file in the source repo. The README text is helpful, but GitHub auto-recognizes the LICENSE files which is very helpful.

clarification on 'additional directories'

Hey Patrick,

Really cool idea here, I wonder if it supports more than one directory, I am working on a Drupal inspired CMS and it would be fantastic if I could require themes, libraries, and app_modules in different directories as real modules, is this something you have implemented?

Edit, I forgot to add an index to my module, the fault was mine.

Thanks!
Adam

Doesn't work with 'imports'?

I am trying to use this along with mocha. My setup looks something like this:

src/js/... lots of files
test/ ... tests

When I compile things, I give src/js as a base dir to browserify, so all the imports in files in src/js use absolute paths starting at src/js. So, I need to have the same base dir (src/js) set up in the tests.

The problem is that, when I have imports in my test files, they seem to be hoisted to the top, so they run before the addPath command can run. If I use "require" to import stuff into a top-level test file, then it works. So, this is not a big deal, but slightly annoying. Is there any way around this, or a recommended aproach? Perhaps you should point this out in the README, at least.

A typo in README

There is a typo in README:

// All of the following lines will work not work in "node_modules/installed-baz/index.js"!

Can't find `package.json`

Everything works great, but I can't seem to require package.json from anywhere after requiring 'app-module-path'. Am I missing something about the usage? I'm able to get other files from the root directory of the path, as well as things nested in sub-folders.

Any help would be appreciated.

it not working in node_modules?

my app is working in node_modules as a module,but app-module-path seems to not working in node_module. it can not add path in module.paths

specify how this works in readme.md

Hi all

Checking this library out - trying to figure out how it works - it looks like it doesn't use NODE_PATH (that wouldn't really be possible given the nature of this), so how does it work?

I probably won't use it unless I know how it works, will try to poke around some more to figure it out

Fix for applications installed globally

We have a CLI project that is installed globally through npm's bin declaration.

This creates a sysLink and installs the application in the global node_modules folder
/usr/local/bin/ -> ../lib/node_modules//entryPoint.js

The issue I'm running into is that when ran normally app-module-path runs perfectly but as soon as our project is installed globally all requires revert to default behavior.

Looking at the code I think what's happening is that app-module-path is being perhaps overly zealous when disabling itself because the application path includes 'node_modules'. (because it's installed globally)

var paths = old_nodeModulePaths.call(this, from);

// Only include the app module path for top-level modules
    // that were not installed:
    if (from.indexOf('node_modules') === -1) {
        paths = appModulePaths.concat(paths);
    }

It looks like app-root-path has identified this issue as well and added some extra logic to account for this fringe case.

Seems to make things a little more complicated.

Any chance this is something you would consider accounting for?

require node_modules before try to require local files

I found an unexpected (as i believe) behavior:

If i have a file like 'marko.json' in my project root folder;
After i add project root folder to 'app-module-path'. Next time i require('marko') it will return the marko.json contents instead of the marko node_module;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.