NPM unable to read file - node.js

I have written a NPM module. which needs to read a file. While creating NPM module I have placed a file in same directory with .js file and used
var file = './sqlmap_config.json';
This files gets included well when I use the code standalone. When I create NPM module, this file is looked up in parent directory where NPM module is installed and code fails.
Do I need to hard code it to
var file = './node_modules/module/sqlmap_config.json';
Or there is any other way to accomplish this

I think you are going to want to use something like :
var file = __dirName + '/sqlmap_config.json';
https://nodejs.org/api/all.html#modules_dirname

Related

npm package uses fs in wrong dir

I have made a very simple npm package to support my discord bot.
In my bot code, I am trying to use a function from my package. However, when I launch bot code, I receive this error:
Error: ENOENT: no such file or directory, open 'prefixes.json'
I have a prefixes.json file in the main dir of npm package. In the package this code (which returns an error) is executed:
const contents = fs.readFileSync(`prefixes.json`);
const jsonPrefixes = JSON.parse(contents);
This code is executed when I turn on my discord bot that is dependant on this package. prefix.json is in the same dir as index.js of my npm package. I tried ./prefix.json and prefix.json, none of which worked.
Is the error because the package tries to search in my bot dir, instead of his own? How do I overcome this?
Update: When I tried ./node_modules/kifo/prefixes.json it worked, but I don't want it like that - is there a way to provide a path relative to the package?
You need to use require() instead of fs.readFileSync():
const jsonPrefixes = require('./prefixes.json');
const contents = JSON.stringify(jsonPrefixes); // you don't actually need this
Why?
The reason why fs.readFileSync() must behave the way it does is because file API in all programming languages behave that way. Say for example you write a program called dump. The working directory must be the one the user is currently in otherwise if you do:
> cd /my/folder
> ls
test.txt
> dump test.txt
Error: cannot open /path/to/node_modules/dump/test.txt
Of course YOU DO NOT EXPECT THIS. Nor should you. You should not expect fs.readFileSync to use it's own module directory to open files from.
On the other hand, require() was designed to load javascript modules, some of which are form your own project. So require() will open files from the directory the code is in.
The require() function can load either javascript code or a JSON file. So in your case you can use require().
What if it's not JSON?
If you cannot use require() you can use the __dirname variable. It is a special variable that contains the path of the currently executing module:
const contents = fs.readFileSync(`${__dirname}/prefixes.json`);
const jsonPrefixes = JSON.parse(contents);
However for JSON I still prefer to use require().

How do I read non-JavaScript files in an NPM dependency?

I have an NPM project called my-config that is a dependency of my-api. Inside of my-config, I have the line:
instance.configs.aws = ini.parse(fs.readFileSync('./etc/aws-config.ini', 'utf-8'));
This fetches the aws-config.ini in the etc folder of the my-config dependency.
However, when I run my-api, it fails with an error, saying that it cannot locate the ini file:
Error: ENOENT: no such file or directory, open './etc/aws-config.ini'
How do I reference this folder etc that exists in my dependency, from my main project that depends on it?
Can you just try ini.parse(fs.readFileSync('etc/aws-config.ini', 'utf-8')); ?
I prefixed the path with __dirname and it seems to be working, but I haven't received a successful runtime validation yet.
ini.parse(fs.readFileSync(__dirname + '/etc/aws-config.ini', 'utf-8'));

Node global module getting current run directory

I'm trying to create a node module that has the ability to be installed globally using npm install -g mymodulename. I've got everything in the module working fine if I run node index.js in the directory of the module, but now I want to make it so that I can publish it to NPM, and it can be installed and run from any directory.
There is some code in my module that looks at certain files in the directory that it is run in. I'm finding that when I do npm install -g ./ and then go into a different directory for a test, then run my-module-command, the relative path that it is reading is from that of where my module got installed (i.e. /usr/local/bin/my-module), not the directory that I'm running it in.
How can my module that is installed globally know where it is being run from? To give an example, I am trying to read the package.json file in the directory I'm in. And it is reading the package.json file of /usr/local/bin/my-module/package.json
I've tried:
__dirname
process.args[1]
process.cwd()
And just calling straight to require('./package.json') directly and none of those work.
Edit here's some code that's breaking in index.js:
#!/usr/bin/env node
var fs = require('fs');
var path = require('path');
var currentDir = path.dirname(require.main.filename);
fs.exists(`${currentDir}/node_modules`, function(dir) {
if (!dir) throw 'node_modules does not exist';
// do stuff
});
In my package.json:
...
"bin": {
"my-module": "./index.js"
},
...
I try to do npm install -g ./ in the project directory, and then I cd into a different directory called /Users/me/Projects/different-project, where another npm project is, and run my-module, and I get node_modules does not exist. When I log out currentDir, I get /usr/local/lib/node_modules/my-module where I'm expecting is to see /Users/me/Projects/different-project.
Have you tried using ./ at the start of your file path? That should give you the current working directory (or calling process.cwd() would work too).
In your case, your code would look like:
fs.exists(`./node_modules`, function(dir) {
if (!dir) throw 'node_modules does not exist';
// do stuff
});
I can see some comments already mention this. Maybe I'm misunderstanding the question? I just had a case where I needed a global module to get the directory I'm running the script from and what I suggested above worked like a charm.

Nodejs - can't find the .node_libraries folder

I'm new to node.js, I would like to use Step.js
https://github.com/creationix/step
The install instructions are very simple:
"Simply copy or link the lib/step.js file into your $HOME/.node_libraries folder."
The problem is that I can't find the .node_libraries folder anywhere.
I tried to create the folder myself and upload the step.js file but I get the following error:
ReferenceError: Step is not defined
I tried to create the following directories:
home/service/.node_libraries
root/.node_libraries
/usr/local/bin/.node_libraries
but none of them works.
Also, Is it possible to load Step as a module?
Thankyou
They have an npm module.
Simply run npm install --save step in the same dir your package.json resides and then you can require() it in your code like this:
var Step = require('step');
The documentation is outdated.
you should use the node package manager.
open the command line in the folder and write:
npm install step
also remember to include the module in your javascript file:
var Step = require('step');

Determine command line working directory when running node bin script

I am creating a node command line interface. It is installed globally and uses a bin file to execute.
I plan to have a command window open at the root directory of the files I am working on and then just run the command however I have been unable to determine the current working directory as process.cwd() is returning the directory of the node package. I initially assumed that since the code is being executed using a batch file as a wrapper (that is how bin files can execute without node at the beginning) then it is impossible but coffee-script manages to do it. I took a look at the coffee-script source but couldn't follow it (not experienced enough).
To test it for yourself create a package with this package.json file:
{
"name": "test-package",
"version": "1.0.0",
"bin": {
"test-package": "./bin/test-package"
},
"main": "/lib/test"
}
this test-package file in bin:
#!/usr/bin/env node
var path = require('path');
var fs = require('fs');
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
require(lib + '/test');
Could anyone shed some light onto this.
and then try and get the command line directory inside lib/test.
process.cwd() returns directory where command has been executed (not directory of the node package) if it's has not been changed by 'process.chdir' inside of application.
__filename returns absolute path to file where it is placed.
__dirname returns absolute path to directory of __filename.
If you need to load files from your module directory you need to use relative paths.
require('../lib/test');
instead of
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
require(lib + '/test');
It's always relative to file where it called from and don't depend on current work dir.
Current Working Directory
To get the current working directory, you can use:
process.cwd()
However, be aware that some scripts, notably gulp, will change the current working directory with process.chdir().
Node Module Path
You can get the path of the current module with:
__filename
__dirname
Original Directory (where the command was initiated)
If you are running a script from the command line, and you want the original directory from which the script was run, regardless of what directory the script is currently operating in, you can use:
process.env.INIT_CWD
Original directory, when working with NPM scripts
It's sometimes desirable to run an NPM script in the current directory, rather than the root of the project.
This variable is available inside npm package scripts as:
$INIT_CWD.
You must be running a recent version of NPM. If this variable is not available, make sure NPM is up to date.
This will allow you access the current path in your package.json, e.g.:
scripts: {
"customScript": "gulp customScript --path $INIT_CWD"
}
path.resolve('.') is also a reliable and clean option, because we almost always require('path'). It will give you absolute path of the directory from where it is called.
Alternatively, if you want to solely obtain the current directory of the current NodeJS script, you could try something simple like this. Note that this will not work in the Node CLI itself:
var fs = require('fs'),
path = require('path');
var dirString = path.dirname(fs.realpathSync(__filename));
// output example: "/Users/jb/workspace/abtest"
console.log('directory to start walking...', dirString);
Warning if using ES Modules
According to the ECMAScript modules docs:
CommonJS variables __filename or __dirname are not available in ES modules.
Instead, use cases can be replicated via import.meta.url.
So according to why is __dirname not defined in node?, you can do the following:
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
Here's what worked for me:
console.log(process.mainModule.filename);

Resources