1 | # App Root Path Module
|
2 |
|
3 | [![Build Status][build-status-img]][build-status] [![Dependency Status][david-dm-img]][david-dm] [![Code Coverage Status][codecov-img]][codecov]
|
4 |
|
5 | > **Please Note:** Due to the very limited scope of this module, I do not anticipate needing to make very many changes to it. Expect long stretches of zero updates—that does not mean that the module is outdated.
|
6 |
|
7 | This simple module helps you access your application's root path from anywhere in the application without resorting to relative paths like `require("../../path")`.
|
8 |
|
9 | ## Installation
|
10 |
|
11 | ``` bash
|
12 | $ npm i -S app-root-path
|
13 | ```
|
14 |
|
15 | ## Usage
|
16 |
|
17 | To simply access the app's root path, use the module as though it were a string:
|
18 |
|
19 | ``` js
|
20 | var appRoot = require('app-root-path');
|
21 | var myModule = require(appRoot + '/lib/my-module.js');
|
22 | ```
|
23 |
|
24 | > _Side note: the module actually returns an object, but that object implements the `toString` method, so you can use it as though it were a string. There are a few edge cases where this might not be the case (most notably `console.log`), but they shouldn't affect actual use of the module, where you're almost always concatenating with an additional string._
|
25 |
|
26 | A helper function is also provided:
|
27 |
|
28 | ``` js
|
29 | var reqlib = require('app-root-path').require;
|
30 | var myModule = reqlib('/lib/my-module.js');
|
31 | ```
|
32 |
|
33 | It's a little hacky, but you can also put this method on your application's `global` object to use it everywhere in your project:
|
34 |
|
35 | ``` js
|
36 | // In app.js
|
37 | global.reqlib = require('app-root-path').require;
|
38 |
|
39 | // In lib/module/component/subcomponent.js
|
40 | var myModule = reqlib('/lib/my-module.js');
|
41 | ```
|
42 |
|
43 | Finally, you can also just resolve a module path:
|
44 |
|
45 | ``` js
|
46 | var myModulePath = require('app-root-path').resolve('/lib/my-module.js');
|
47 | ```
|
48 |
|
49 | You can explicitly set the path, using the environmental variable `APP_ROOT_PATH` or by calling `require('app-root-path').setPath('/my/app/is/here')`
|
50 |
|
51 | ## How It Works (under the hood)
|
52 |
|
53 | > No need to read this unless you're curious—or you run into a (very unlikely) case where the module does not work as expected.
|
54 |
|
55 | This module uses two different methods to determine the app's root path, depending on the circumstances.
|
56 |
|
57 | ### Primary Method
|
58 |
|
59 | If the module is located inside your project's directory, somewhere within the `node_modules` directory (whether directly, or inside a submodule), we effectively do (the actual code takes cross-platform path names/etc into consideration):
|
60 |
|
61 | ``` js
|
62 | path.resolve(__dirname).split('/node_modules')[0];
|
63 | ```
|
64 |
|
65 | This will take a path like `/var/www/node_modules/submodule/node_modules/app-root-path` and return `/var/www`. In nearly all cases, this is just what you need.
|
66 |
|
67 | ### Secondary Method (for edge cases)
|
68 |
|
69 | The node module loader will also look in a few other places for modules (for example, ones that you install globally with `npm install -g`). These can be in one of:
|
70 |
|
71 | - `$HOME/.node_modules`
|
72 | - `$HOME/.node_libraries`
|
73 | - `$PREFIX/lib/node`
|
74 |
|
75 | Or, anywhere in the `NODE_PATH` environmental variable ([see documentation](http://nodejs.org/api/modules.html#modules_loading_from_the_global_folders)).
|
76 |
|
77 | In these cases, we fall back to an alternate trick:
|
78 |
|
79 | ``` js
|
80 | path.dirname(require.main.filename);
|
81 | ```
|
82 |
|
83 | When a file is run directly from Node, `require.main` is set to that file's `module`. Each module has a `filename` property that refers to the filename of that module, so by fetching the directory name for that file, we at least get the directory of file passed to `node`. In some cases (process managers and test suites, for example) this doesn't actually give the correct directory, though, so this method is only used as a fallback.
|
84 |
|
85 | ### Edge-Case: Global CLIs
|
86 |
|
87 | If your module is installed as a global CLI, for example in `/usr/local/lib/node_modules/yourmodule`, then
|
88 | `require.main.filename` will report `/usr/local/lib/node_modules/yourmodule/bin`, which is probably not what
|
89 | you want. `app-root-path` is aware of this edge-case and will strip the `/bin` automatically.
|
90 |
|
91 | ## Change Log
|
92 |
|
93 | ### 3.1.0
|
94 | - Added TypeScript types
|
95 | - Added fallback for when `require.main` is missing (ESM imports)
|
96 |
|
97 | ### 3.0.0
|
98 | - Improved Yarn Plug'n'Play support
|
99 | - Fixed bug when used with webpack
|
100 |
|
101 | ### 2.2.1
|
102 | - Better handling of webpack
|
103 |
|
104 | ### 2.2.0
|
105 | - Added support for Yarn Plug'n'Play
|
106 | - Adjusted browser-shim to address webpack warnings
|
107 | - Bumped minimum Node version to 6
|
108 |
|
109 | ### 2.0.1
|
110 | - Minor tweaks to how electron-specific logic runs. Should help with packagers that try to resolve all `require()` statements during packaging.
|
111 |
|
112 | ### 2.0.0
|
113 | - Removed official support for node < 4.0
|
114 | - Removed support for passing `module.require` to `appRootPath.require` (which has been deprecated for a while)
|
115 | - Implemented [semantic-release](https://github.com/semantic-release/semantic-release) from here on out
|
116 | - Added browserify-compatible shim
|
117 |
|
118 | ### 1.3.0
|
119 | - Updated [electron](https://github.com/atom/electron) to match changes in version 1.0 of that project
|
120 |
|
121 | ### 1.2.1
|
122 | - Had to bump package version because 1.2.0 got published to npm as @beta
|
123 |
|
124 | ### 1.2.0
|
125 | - Special logic to resolve correctly when in an [electron](https://github.com/atom/electron) renderer process
|
126 |
|
127 | ### 1.1.0
|
128 | - Special logic to handle an edge case when used in a globally-installed CLI project
|
129 | - Fixed a bug where `setPath()` did not update `require('app-root-path').path`
|
130 | - Moved some logic outside of the `resolve()` function so that it's not called multiple times
|
131 |
|
132 | ### 1.0.0
|
133 | - No changes. Just updated the version to signify a locked API (see [semver](http://semver.org/)).
|
134 |
|
135 | ### 0.1.1
|
136 | - Added Windows support (and, theoretically, other operating systems that have a directory separator that's not "/")
|
137 |
|
138 | ### 0.1.0
|
139 | - Completely rewrote the path resolution method to account for most possible scenarios. This shouldn't cause and backwards compatibility issues, but always test your code.
|
140 | - Removed the need to pass a modules's `require()` method to the `appRootPath.require()` function. Which it's true that each module has its own `require()` method, in practice it doesn't matter, and it's **much** simpler this way.
|
141 | - Added tests
|
142 |
|
143 | ## Development Nodes
|
144 |
|
145 | When using [semantic-release](https://github.com/semantic-release/semantic-release), the preferred method
|
146 | for commits is:
|
147 |
|
148 | - `git add …`
|
149 | - `git cz` (see [commitizen](https://github.com/commitizen/cz-cli))
|
150 | - `git push`
|
151 |
|
152 | This helps ensure that commits match the expected format. Commits to `master` will cause releases.
|
153 |
|
154 | [build-status]: https://travis-ci.org/inxilpro/node-app-root-path
|
155 | [build-status-img]: https://travis-ci.org/inxilpro/node-app-root-path.svg
|
156 | [david-dm-img]: https://david-dm.org/inxilpro/node-app-root-path.svg
|
157 | [david-dm]: https://david-dm.org/inxilpro/node-app-root-path
|
158 | [codecov-img]: https://codecov.io/gh/inxilpro/node-app-root-path/branch/master/graph/badge.svg
|
159 | [codecov]: https://codecov.io/gh/inxilpro/node-app-root-path
|
160 |
|
\ | No newline at end of file |