How to get the absolute path of my NPM global package? - javascript

I'm building an NPM package that is supposed to run globally.
Inside the NPM package, there's a data folder which contains a file I need to read at runtime.
How can I get the absolute path of my NPM package, so I can read the data folder?
I'm searching for that on Google with no luck.

You can use the path module and with it either start your paths with a ./ or just omit any / at the begining of a string.
for example:
var path = require('path');
console.log(path.resolve('./');
is the same as
var path = require('path');
console.log(path.resolve('');
the resolve method is nice in that it'll resolve your relative path with an absolute path to it. Good to be safe!
To build on #explosion pills' comment, it's nice to combine __dirname and path.resolve
console.log(path.resolve(__dirname));

Related

Get installed package root path from within package

I am building an npm package which is basically an CLI tool.
It is intended to be installed globally and used as CLI with dist/clj.js, but can also be installed as a regular dependency and accessed via dist/index.js.
From inside .js files of my package (like dist/cli.js or dist/index.js) I want to get an absolute path to the root of my package (where package.json is located).
I know this can be done with __dirname but for different files in my project it require different actions:
// dist/cli.js
console.log(require('path').join(__dirname, '..'));
// dist/a/b/c/foo.js
console.log(require('path').join(__dirname, '..', '..', '..', '..'));
Is there a better way to get the root of both globally or locally installed package from any .js file inside this package regardless of the folder this package is used in?
This code seems to work from any file within package:
const path = require('path');
let packageRootPath = path.join(path.dirname(require.main.filename), '..');
.. in the end needed to jump from src/dist to the root since all my js files are located in src/dist forders.

Is it necessary to specify directory when using appendFileSync?

I'm going through some of the nodejs documentation and starting to familiarize myself with some of the more basic functions. Specifically looking at appendFileSync function.
When trying to append a file, is it necessary to specify the directory? I don't recall this being a requirement in previous versions of Node but it seems when the directory is not specified, a new file is created in the root instead of appending the file.
I'm just trying to append a basic txt file, with this it creates a new file:
const fs = require('fs');
fs.appendFileSync('notes.txt', 'Changing the text with appendFileSync');
However, when specifying the directory, it appends the file just fine making me think this is required:
const fs = require('fs');
fs.appendFileSync('./nodejs/notes-app/notes.txt', ' Colin, changed the
text with appendFileSync', function (err) {
if (err) throw err; console.log('Notes updated');
});
Node -v 12.13.0
NPM -v 6.12.0
As with all fs operations that take a file path, if you don't specify any sort an absolute path, then the path you do specify is combined with the current working directory. In a nodejs program, the default current working directory (if you don't change it programmatically) is taken from the environment in which you started the node program.
If want to control the path directly without regard to the current working directory, then specify an absolute path.
This is what the fs module documentation says about file paths:
String form paths are interpreted as UTF-8 character sequences identifying the absolute or relative filename. Relative paths will be resolved relative to the current working directory as specified by process.cwd().
Note: For some situations, a developer wants to access the file system relative to the installation of the module that is running. That is typically done by building a path that is relative to __dirname which is the location of the current module like this.
path.join(__dirname, "somefile.txt");
Of course, you can always specific a full path name starting from root if you want.

How do I require something in root project directory from inside node package library?

I wanna create a node package modules, but I have difficulty to require a file from root project directory to use inside my node package module I created.
If I have directory structure like this
- node_modules
- library_name
- lib
- index.js
- bin
- run.sh
- config.js
If the run.sh called, it will run index.js. Inside index.js, how do I resolve to root directory which later I can require config.js inside index.js?
Package binary can accept configuration path explicitly as an argument.
If package binary doesn't run as NPM script, it shouldn't rely on parent project structure.
If package binary runs via NPM script:
"scripts": {
"foo": "library_name"
}
This will set current working directory to project root, so it could be required as:
const config = require(path.join(process.cwd(), 'config'));
Both approaches can be combined; this is often used to provide configuration files with default locations to third-party CLI (Mocha, etc).
If you're in index.js and config.js is in the directory above node_modules in your diagram, then you can build a path to config.js like this:
const path = require('path');
let configFilename = path.join(__dirname, "../../../", "config.js");
__dirname is the directory that index.js is in.
The first ../ takes you up to the library_name directory.
The second ../ takes you up to the node_modules directory.
The third ../ takes you up to the parent of node_modules (what you call project root) where config.js appears to be.
If you really want your module to be independent of how it is installed or how NPM might change in the future, then you need to somehow pass in the location of the config file in any number of ways:
By making sure the current working directory is set to the project root so you can use process.cwd() to get access to the config file.
By setting an environment variable to the root directory when starting your project.
By passing the root directory in to a module constructor function.
By loading and passing the config object itself in to a module constructor function.
I create module same your module.
And I call const config = require('../config'), it work.

Install & access a local folder as a npm module

The file structure looks like this:
= (main-folder)
- package.json
- ...
= server
- index.js
- ...
= deploy-abc // new server
= src
- index.js
= src
- index.js
- ...
I am trying to install 'deploy-abc' as a module within the main-folder app. So, I ran : yarn add "/var/www/main-folder/deploy-abc". It installed correctly & I can see the 'deploy-abc' dependency listed in package.json.
However, when I try to access the deploy-abc's exported object, I get node error Error: Cannot find module 'deploy-abc'. E.g: In some file in the main folder:
const deployAbc = require("deploy-abc");
console.log(deployAbc); // error
Where am I going wrong?
As per the node docs: https://nodejs.org/api/modules.html#modules_loading_from_node_modules_folders
If the module identifier passed to require() is not a core module, and does not begin with '/', '../', or './', then Node.js starts at the parent directory of the current module, and adds /node_modules, and attempts to load the module from that location.
So, seeing as your module is now in the main folder, how you require it will depend on the relative location. If you are requiring it from say /src/index.js, then you will need:
const deployAbc = require('../deploy-abc')
You also don't need to specify the actual file in this case, as it defaults to index.js. If however the entry file was say, dabc.js or something else, you would need to also specify that in the location.
You might have to use the exact relative path. For example, const deployAbc = require("../deploy-abc")

In Node.js how can I tell the path of `this` module?

In a Node.js module I would like to open a file--i.e, with fs.readFile()--that is contained in the same directory as my module. By which I mean it is in the same directory as the ./node_modules/<module_name>/index.js file.
It looks like all relative path operations which are performed by the fs module take place relative to the directory in which Node.js is started. As such, I think I need to know how to get the path of the current Node.js module which is executing.
Thanks.
As david van brink mentioned in the comments, the correct solution is to use __dirname. This global variable will return the path of the currently executing script (i.e. you might need to use ../ to reach the root of your module).
For example:
var path = require("path");
require(path.join(__dirname, '/models'));
Just to save someone from a headache.

Categories

Resources