Dotenv not loading env variables with correct path - node.js

Im using the dotenv library, but my env variables returns undefined
// app.ts
require('dotenv').config({path: '/.env'});
console.log(process.env.MAIN_DB_PATH) // returns undefined
// .env
MAIN_DB_PATH=./data/database.db
UPLOAD_MULTER_DIR=./module/car/uploads
My folder structure is
So it should works fine :(

To load the .env file in a different directory, you need to provide the absolute path to that file.
__dirname : the absolute path to the directory of the file where you need to load .env file (app.ts in this case)
.. : go 1 level up
Then path.resolve will give you the absolute path to .env file
const path = require('path');
require("dotenv").config({ path: path.resolve(__dirname, '..', '.env') });
console.log(process.env.MAIN_DB_PATH);

You do not need path if the .env file is at the root, but you can define a return value from config method and check if error happend
const result = dotenv.config()
if (result.error) {
throw result.error
}
console.log(result.parsed)
source: https://www.npmjs.com/package/dotenv config paragraph

Related

import.meta.url gets path of source file instead of compiled file

Since __dirname is undefined in a typescript electron project, I have resorted to
import * as path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
However, this new __dirname gets the directory of the original source file instead of the compiled file. (Paths ends up being /src/something.ts instead of /dist/something.js)
Is there a way to get the path of the compiled file being run? Am I missing some webpack, tsconfig settings?
(Unfortunately, app.getAppPath() also seems to rely on __dirname)
EDIT: I am trying to load an angular app inside electron through the protocol.registerFileProtocol since plain relative or file:// links to not seem to be loaded:
protocol.registerFileProtocol('resource', (request, callback) => {
let url = request.url.substr(11); // Remove the resource://
callback(path.join(app.getAppPath(), '/', url));
// or
callback(path.join(__dirname, '/', url));
});

Take relative file path as CLI input in a Node program

In a CLI app, I need to take in a relative path to a file, and pass an absolute path to fs.readFile. How can I accept the relative path as input but convert it to an absolute path, even if the Node script is being run from a different directory than it is in?
You can use path.resolve with process.cwd() and the input file.
When you have a path relative to the JS file you are running, you usually use path.resolve with __dirname. However, in the case where the user supplies a path as a CLI argument, they may be running the JS file from a different directory. To get the directory they are running the script from, you can use process.cwd() (Current Working Directory).
$ node some-folder/index.js ./myFile.txt
const { resolve } = require("node:path")
const { argv, cwd } = require("node:process")
// or with ESM
import { resolve } from "node:path"
import { argv, cwd } from "node:process"
const relativePath = argv[2] // input file
const absolutePath = resolve(cwd(), relativePath)
// absolutePath looks like /.../myFile.txt, but if we
// used __dirname instead of cwd(), it would be
// /.../some-folder/myFile.txt, relative to the JS file
// instead of where the file was ran from
// now you can use absolutePath with fs.readFile or etc

typescript cannot recognize .sequelizerc file

I have this .sequelizerc file:
const path = require('path');
module.exports = {
config: path.resolve('.', 'src/config/sequelizeCLIConfig.json'),
'migrations-path': path.resolve('.', 'db', 'migrations'),
};
And then I have a .ts file that generates the cli config file named generateSequelizeCLIConfig.ts, which does the following thing:
import path from 'path';
import fs from 'fs';
import config from '../../src/config';
import sequelizeRC from '../../.sequelizerc';
const env = process.env.NODE_ENV || 'development';
const targetFile = path.resolve(sequelizeRC.config);
const sequelizeCLIConfig: Record<string, any> = {};
sequelizeCLIConfig[env] = config.db;
fs.writeFile(targetFile, JSON.stringify(sequelizeCLIConfig, null, 4), err => {
if (err) {
return console.log(err);
}
console.log('The sequelizeCLI config file was saved at ' + targetFile + '!');
});
The plan is, every time I need migration, I run this script first. This script grabs the data from the config folder and generate the src/config/sequelizeCLIConfig.json. And then I run the migration with config data from this .json file.
So the file structure is this:
-.sequelizerc
-db
|-scripts
|-generateSequelizeCLIConfig.ts
-src
|-config
|-index.ts
.sequelizerc
However I got this error when compiling generateSequelizeCLIConfig.ts:
TSError: тип Unable to compile TypeScript:
db/scripts/generateSequelizeCLIConfig.ts(4,25): error TS2307: Cannot find module '../../.sequelizerc'.
So it seems .sequrlizerc is not recognized although I have double checked that this file does exist.
My guess is, .sequelizerc behind the scene is a .js file, not a .ts file, and this gives me some trouble. But I don't know how to verify this, nor how to fix it.
Any suggestions?
Try to add the .sequelizerc to your include in your tsconfig as follows:
{
..prev configs...,
include: [ ...your paths..., ".sequelizerc"],
}
Delete dot. Rename the .sequelizerc to sequelizerc

Absolute path to file throws error?

Recently I started with NodeJS and I found the require() function.
I have two JS files:
main.js in C:/Users/Admin folder and,
test.js in F: drive
Here is my test.js file:
function log(name) {
console.log(name);
}
module.exports.log = log;
and here is my main.js file:
var myModule = require("/F:/test");
myModule.log("Anonymous");
But when I type...
C:\Users\Admin>node main.js
in Node.js CMD, I get the following error statement:
Error: Cannot find module '/F:/test'
Help me to figure out the error!
You are giving the path of the file wrong.
It should be F:/test instead of /F:/test.
You can use path module to resolve the path by path.resolve and check what it resolves to. In your case it is resolving to C:\F:\test.
Update
You can check to what your provided path resolves to like below
const path = require('path');
let p = path.resolve('/F:/test');
console.log(p);// C:\F:\test
Use path module instead of specifying explicit path separators.
var path = require('path');
modulepath = path.join('F:','test');
var myModule = require(modulepath);

How do I get the path to the current script with Node.js?

How would I get the path to the script in Node.js?
I know there's process.cwd, but that only refers to the directory where the script was called, not of the script itself. For instance, say I'm in /home/kyle/ and I run the following command:
node /home/kyle/some/dir/file.js
If I call process.cwd(), I get /home/kyle/, not /home/kyle/some/dir/. Is there a way to get that directory?
I found it after looking through the documentation again. What I was looking for were the __filename and __dirname module-level variables.
__filename is the file name of the current module. This is the resolved absolute path of the current module file. (ex:/home/kyle/some/dir/file.js)
__dirname is the directory name of the current module. (ex:/home/kyle/some/dir)
So basically you can do this:
fs.readFile(path.resolve(__dirname, 'settings.json'), 'UTF-8', callback);
Use resolve() instead of concatenating with '/' or '\' else you will run into cross-platform issues.
Note: __dirname is the local path of the module or included script. If you are writing a plugin which needs to know the path of the main script it is:
require.main.filename
or, to just get the folder name:
require('path').dirname(require.main.filename)
Use __dirname!!
__dirname
The directory name of the current module. This the same as the path.dirname() of the __filename.
Example: running node example.js from /Users/mjr
console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr
https://nodejs.org/api/modules.html#modules_dirname
For ESModules you would want to use:
import.meta.url
This command returns the current directory:
var currentPath = process.cwd();
For example, to use the path to read the file:
var fs = require('fs');
fs.readFile(process.cwd() + "\\text.txt", function(err, data)
{
if(err)
console.log(err)
else
console.log(data.toString());
});
Node.js 10 supports ECMAScript modules, where __dirname and __filename are no longer available.
Then to get the path to the current ES module one has to use:
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
And for the directory containing the current module:
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
When it comes to the main script it's as simple as:
process.argv[1]
From the Node.js documentation:
process.argv
An array containing the command line arguments. The first element will be 'node', the second element will be the path to the JavaScript file. The next elements will be any additional command line arguments.
If you need to know the path of a module file then use __filename.
var settings =
JSON.parse(
require('fs').readFileSync(
require('path').resolve(
__dirname,
'settings.json'),
'utf8'));
Every Node.js program has some global variables in its environment, which represents some information about your process and one of it is __dirname.
I know this is pretty old, and the original question I was responding to is marked as duplicate and directed here, but I ran into an issue trying to get jasmine-reporters to work and didn't like the idea that I had to downgrade in order for it to work. I found out that jasmine-reporters wasn't resolving the savePath correctly and was actually putting the reports folder output in jasmine-reporters directory instead of the root directory of where I ran gulp. In order to make this work correctly I ended up using process.env.INIT_CWD to get the initial Current Working Directory which should be the directory where you ran gulp. Hope this helps someone.
var reporters = require('jasmine-reporters');
var junitReporter = new reporters.JUnitXmlReporter({
savePath: process.env.INIT_CWD + '/report/e2e/',
consolidateAll: true,
captureStdout: true
});
Use the basename method of the path module:
var path = require('path');
var filename = path.basename(__filename);
console.log(filename);
Here is the documentation the above example is taken from.
As Dan pointed out, Node is working on ECMAScript modules with the "--experimental-modules" flag. Node 12 still supports __dirname and __filename as above.
If you are using the --experimental-modules flag, there is an alternative approach.
The alternative is to get the path to the current ES module:
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(new URL(import.meta.url));
And for the directory containing the current module:
import { fileURLToPath } from 'url';
import path from 'path';
const __dirname = path.dirname(fileURLToPath(new URL(import.meta.url)));
You can use process.env.PWD to get the current app folder path.
NodeJS exposes a global variable called __dirname.
__dirname returns the full path of the folder where the JavaScript file resides.
So, as an example, for Windows, if we create a script file with the following line:
console.log(__dirname);
And run that script using:
node ./innerFolder1/innerFolder2/innerFolder3/index.js
The output will be:
C:\Users...<project-directory>\innerFolder1\innerFolder2\innerFolder3
If you are using pkg to package your app, you'll find useful this expression:
appDirectory = require('path').dirname(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0]));
process.pkg tells if the app has been packaged by pkg.
process.execPath holds the full path of the executable, which is /usr/bin/node or similar for direct invocations of scripts (node test.js), or the packaged app.
require.main.filename holds the full path of the main script, but it's empty when Node runs in interactive mode.
__dirname holds the full path of the current script, so I'm not using it (although it may be what OP asks; then better use appDirectory = process.pkg ? require('path').dirname(process.execPath) : (__dirname || require('path').dirname(process.argv[0])); noting that in interactive mode __dirname is empty.
For interactive mode, use either process.argv[0] to get the path to the Node executable or process.cwd() to get the current directory.
index.js within any folder containing modules to export
const entries = {};
for (const aFile of require('fs').readdirSync(__dirname, { withFileTypes: true }).filter(ent => ent.isFile() && ent.name !== 'index.js')) {
const [ name, suffix ] = aFile.name.split('.');
entries[name] = require(`./${aFile.name}`);
}
module.exports = entries;
This will find all files in the root of the current directory, require and export every file present with the same export name as the filename stem.
If you want something more like $0 in a shell script, try this:
var path = require('path');
var command = getCurrentScriptPath();
console.log(`Usage: ${command} <foo> <bar>`);
function getCurrentScriptPath () {
// Relative path from current working directory to the location of this script
var pathToScript = path.relative(process.cwd(), __filename);
// Check if current working dir is the same as the script
if (process.cwd() === __dirname) {
// E.g. "./foobar.js"
return '.' + path.sep + pathToScript;
} else {
// E.g. "foo/bar/baz.js"
return pathToScript;
}
}

Resources