0.0.2 • Published 7 years ago

pkg-require v0.0.2

Weekly downloads
5
License
MIT
Repository
github
Last release
7 years ago

Build Status Coverage Status npm Dependency Status

pkg-require

require node files relative to your package root directory

npm i -S pkg-require

How we got here

Imagine this directory tree

root
├── foo
│   └── foo.js
├── package.json
└── some
    └── deep
        └── dir
            └── tree
                └── bar.js

Now if you're in bar.js and want to require foo.js you need to go all the way up to the root dir and then specify the file you want.

const foo = require('../../../../foo/foo');

This is annoying for a few reasons:

  • hard to read
  • hard to write
  • needs to be maintained if you move bar.js around
  • needs to be maintained if you move foo.js around, which cannot be done with a simple search and replace as you may have different numbers of '../' in different files requiring foo.js

Wouldn't it be simpler if you can just write

const foo = require('foo/foo');

and it would just understand that you mean to require a module relative to your root directory? What do you mean by root directory? The one that contains package.json.

pkg-require

pkg-require will do exactly this. It looks all the way up your directory tree until it finds the first package.json, and then it will resolve all requires from that directory.

TLDR Example

// create an instance that will find the nearest parent dir containing package.json from your __dirname
const pkgRequire = require('pkg-require')(__dirname);

// require a file relative to the your package.json directory 
const foo = pkgRequire('foo/foo')

// get the absolute path for a file
const absolutePathToFoo = pkgRequire.resolve('foo/foo')

// get the absolute path to your root directory
const packageRootPath = pkgRequire.root()

now you can go write useful code instead of counting how many levels you need to go up to require a file.

API

init

create a new instance for the package based on current file directory

const pkgRequire = require('pkg-require')(__dirname);

pkgRequire()

require a file by passing its path relative to the directory containing package.json

const foo = pkgRequire('foo/foo')

resolve()

resolve a file/dir absolute path by passing its path relative to the directory containing package.json

const absolutePathToFoo = pkgRequire.resolve('foo/foo')

root()

return the absolute path to the parent directory containing package.json

const packageRootPath = pkgRequire.root()

Other Solutions/Hacks

There are a bunch of ways people have been dealing with this problem, which include

  • creating a sym link in node_modules to your project dir
  • modifying $NODE_PATH
  • calling require.main.require
  • using a global variable for base directory
  • overriding/mutating the global require

these solutions are not just hacky and almost impossible to track, most of these solutions will wreak havoc if you use them in package installed with npm, or if you have a few of packages installed doing these hacks.

pkg-require does not involve any such hacks, it's a pure function with no side effects or mutations. It takes __dirname as an input, finds the first parent directory containing package.json, and uses that directory to resolve all files. This way it can work for nested modules and multiple modules because each module will pass its own __dirname and get a different instance of the module.