NodeJS accessing file with relative path [duplicate] - node.js

This question already has answers here:
Proper way to reference files relative to application root in Node.JS
(5 answers)
Closed 5 years ago.
It seemed like a straight forward problem. But I amn't able to crack this.
Within helper1.js I would like to access foobar.json (from config/dev/)
root
-config
--dev
---foobar.json
-helpers
--helper1.js
I couldn't get this to work fs: how do I locate a parent folder?
Any help here would be great.

You can use the path module to join the path of the directory in which helper1.js lives to the relative path of foobar.json. This will give you the absolute path to foobar.json.
var fs = require('fs');
var path = require('path');
var jsonPath = path.join(__dirname, '..', 'config', 'dev', 'foobar.json');
var jsonString = fs.readFileSync(jsonPath, 'utf8');
This should work on Linux, OSX, and Windows assuming a UTF8 encoding.

Simple! The folder named .. is the parent folder, so you can make the path to the file you need as such
var foobar = require('../config/dev/foobar.json');
If you needed to go up two levels, you would write ../../ etc
Some more details about this in this SO answer and it's comments

Related

Understanding how path works in Node

So I have developed a Node Api and on local the path works fine, but I want to move it now to a server online, and don't know how to address the path.
This is the path in local: const path = "/Users/username/Code/projectname/api/invoices"
And what I want to do is make it work also for online, also to make sure that the folder api is what is going to be uploaded, not the one with projectname as it contains the client folder and other folders, so only the api folder.
use __dirname to get the path of the folder.
The __dirname in a node script returns the path of the folder where the current JavaScript file resides.
const path = `${__dirname}/api/invoices`
You can use the __dirname variable.
For this, you first need to import path.
const nodePath = require("path");
Then, to get the path, you need to join the directory name and your custom path together.
const path = nodePath.join(__dirname, "/api/invoices");
This should correctly join the path together.
Note: Naming conventions changed to avoid naming conflicts.
In conclusion, you can use the __dirname variable!

Write file relative to server's absolute path in node.js

Does anyone know how I can write a file relative to my server's absolute path: /var/logs/.../? Right now I am building my path like: ../../../../var/logs. I am looking for something like:
server_root/var/logs
Thanks in advance!
You can use absolute paths (/var/...), just like any other system that uses paths.
You can get the current execution path of server using rootpath variable
var path = require('path'),
var rootPath = path.normalize(__dirname + '/..'); //_dirname is from nodejs
Now you can use this to get exact path of all the directories

Get application full path in Node.js

I'm wondering if there is a best way or best practice to get the full path of application in Node.js. Example: I have a a module in sub folder /apps/myapp/data/models/mymodel.js, and I would like to get the full path of the app (not full path of the file), which will return me /apps/myapp, how do I do that? I know _dirname or _file is only relative to the file itself but not the full path of the app.
There's probably a better solution, BUT this should work:
var path = require('path');
// find the first module to be loaded
var topModule = module;
while(topModule.parent)
topModule = topModule.parent;
var appDir = path.dirname(topModule.filename);
console.log(appDir);
EDIT: Andreas proposed a better solution in the comments:
path.dirname(require.main.filename)
EDIT: another solution by Nam Nguyen
path.dirname(process.mainModule.filename)
This worked for me.. With supervisor running the app from a different dir.
require('path').dirname(Object.keys(require.cache)[0])
example.. files:
/desktop/ya/node.js
require('./ya2/submodule')();
/desktop/ya/ya2/submodule.js
module.exports = function(){
console.log(require('path').dirname(Object.keys(require.cache)[0]))
}
$ node node.js
=> /desktop/ya
$ (from /desktop) supervisor ya/node.js
=> /desktop/ya

Proper way to reference files relative to application root in Node.JS

I have a Node.JS application running on Linux at AWS EC2 that uses the fs module to read in HTML template files. Here is the current structure of the application:
/server.js
/templates/my-template.html
/services/template-reading-service.js
The HTML templates will always be in that location, however, the template-reading-service may move around to different locations (deeper subdirectories, etc.) From within the template-reading-service I use fs.readFileSync() to load the file, like so:
var templateContent = fs.readFileSync('./templates/my-template.html', 'utf8');
This throws the following error:
Error: ENOENT, no such file or directory './templates/my-template.html'
I'm assuming that is because the path './' is resolving to the '/services/' directory and not the application root. I've also tried changing the path to '../templates/my-template.html' and that worked, but it seems brittle because I imagine that is just resolving relative to 'up one directory'. If I move the template-reading-service to a deeper subdirectory, that path will break.
So, what is the proper way to reference files relative to the root of the application?
Try
var templateContent = fs.readFileSync(path.join(__dirname, '../templates') + '/my-template.html', 'utf8');
To get an absolute filesystem path to the directory where the node process is running, you can use process.cwd(). So assuming you are running /server.js as a process which implements /services/template-reading-service.js as a module, then you can do the following from /service/template-reading-service.js:
var appRoot = process.cwd(),
templateContent = fs.readFileSync(appRoot + '/templates/my-template.html', 'utf8');
If that doesn't work then you may be running /service/template-reading-service.js as a separate process, in which case you will need to have whatever launches that process pass it the path you want to treat as the primary application root. For example, if /server.js launches /service/template-reading-service.js as a separate process then /server.js should pass it its own process.cwd().
Accepted answer is wrong. Hardcoding path.join(__dirname, '../templates') will do exactly what is not wanted, making the service-XXX.js file break the main app if it moves to a sub location (as the given example services/template).
Using process.cwd() will return the root path for the file that initiated the running process (so, as example a /Myuser/myproject/server.js returns /Myuser/myproject/).
This is a duplicate of question Determine project root from a running node.js application.
On that question, the __dirname answer got the proper whipping it deserves.
Beware of the green mark, passers-by.
For ES modules, __dirname is not available, so read this answer and use:
import { resolve, dirname, join } from 'path'
import { fileURLToPath } from 'url'
import fs from 'fs'
const relativePath = a => join(dirname(fileURLToPath(import.meta.url)), a)
const content1 = fs.readFileSync(relativePath('./file.xyz'), 'utf8') // same dir
const content2 = fs.readFileSync(relativePath('../file.xyz'), 'utf8') // parent dir
We can use path madule to access the current path
const dirname = __dirname;
const path = require('path');
path.resolve(dirname, 'file.txt')
where
dirname - is give us present working directory path name
file.txt - file name required to access

How to resolve a relative path in node?

Came across this situation recently - I have an environment variable for a directory path like so:
var fooDir = process.env.FOO_DIR;
and I want to make sure this directory exists with a synchronous mkdir (at some point later):
fs.mkdirSync(fooDir, mode);
however if the user has supplied the environment variable via a realtive ~/ path node cannot resolve it
export FOO_DIR='~/foodir'
is there a way in node to resolve this without invoking a child process exec call to the actual shell? currently my solution is to do a replace myself like so:
fooDir = fooDir.replace(/^~\//, process.env.HOME + '/');
just curious if someone has a better solution.
You have it right: ~ is expanded by the shell, not the OS, just like *. None of the C file functions that node.js wraps handle ~ either, and if you want this you have to do the replacement yourself, just as you've shown. I've done this myself in C when supporting config files that allow relative file paths.
However, you should probably handle the case where HOME isn't defined; I believe this happens with non-interaction logins with bash, for example, and the user could always choose to unset it.
You can convert it to absolute path with path.join:
const path = require('path')
const absolutePath = path.join(process.cwd(), relativePath)
Check out Rekuire, it is a node module that solves the relative paths problem in NodeJs.

Resources