Determining the path in fs.readFile() - node.js

var fs = require('fs');
var obj = JSON.parse(fs.readFileSync('./config.json', 'utf8'));
This is the code for my app (index.js) . It uses a file named config.json using a relative path ./config.json. When I compile this into my mac using $pkg index.js, I obtain a test-macos file that is my app. Both the app and the config.json file are located in the same folder named project (this is why I can use the relative path ./config.json). However, once runnning the app I run into an error:
/Users/amelie/Documents/project/test-macos ;
exit; internal/fs/utils.js:312
throw err;
^ Error: ENOENT: no such file or directory, open './config.json'.
Therefore it seems that my app cannot find the config.json file. I could determine an absolute path but I need these two files to always be together because I need the path in the variable
var obj = JSON.parse(fs.readFileSync('./config.json', 'utf8'));
to be always the same since I share those files to other people and the absolute path would therefore change. Is there a way to do this ?

Related

Requiring a project file from an npm module

I have an npm module that requires a config file (provided by the user).
Is there a way to tell that module to look for a specific file in the user's directory ?
I want something like this:
In the module
const config = require(USER_ROOT_DIRECTORY + '/config.json');
In the user's project
/node_modules (contains the module file)
/src/index.js
/config.json
In the index.js file
const module = require('module'); // will automatically get the config.json file's content
You can use absolute path since you know with npm module requires what file simply add the path inside the module file better to add in index.js example-
var config = require('./subfolder/config.json')

Node get path of the requiring parent file

I'm writing a node module and need to read a file in the same directory as the file which requires my module.
For instance, I have app.js and in the same folder, template.html.
In some unknown directory is module.js and app.js requires it.
How can I read template.html from module.js?
Inside your file you will have a module global (not actually a global)
you can get the parent object using module.parent and the filename with module.parent.filename then you could extract the folder
so from from your module.js you can use module.parent.filename.
http://nodejs.org/api/modules.html
p = require('path')
template = p.join(p.dirname(module.parent.filename),'template.html')
And if you are looking for the path of the file which was executed then you can use require.main.filename
Have a look here: http://nodejs.org/docs/latest/api/globals.html#globals_dirname
The you can just do this from within app.js:
var path = __dirname + '/template.html';
Then you can send this path to your module.js via some function or API.
Then your module can just use this path.
Inside a "module.js", the trick is using module.parent.filename
I don't personally like using globals, and for certain files (like configuration or templates), managing module require stack isn't so hard.
module.parent is mapped to the parent requiring module (which could be app.js as in your example).
Combining module.parent.filename with the path module gets you a few useful things like:
var path = require('path');
var parent_path = path.dirname(module.parent.filename);
var parent_relative = path.resolve(path.join(parent_path, '../', 'view'));
var template = path.join(parent_path,'./views/template.html');
I don't like using globals for anything to do with paths, I get spagetti ../../../dir./s

What is the difference between require('mypackage.js') and require('mypackage')?

Both these require statements appear to work the same way:
var Mypackage = require('mypackage.js');
var Mypackage require('mypackage');
Is there a difference between them?
Here is the answer:
Module.prototype.load = function(filename) {
debug('load ' + JSON.stringify(filename) +
' for module ' + JSON.stringify(this.id));
assert(!this.loaded);
this.filename = filename;
this.paths = Module._nodeModulePaths(path.dirname(filename));
var extension = path.extname(filename) || '.js';
if (!Module._extensions[extension]) extension = '.js';
Module._extensions[extension](this, filename);
this.loaded = true;
};
Node.JS looks to see if the given module is a core module. (e.g. http, fs, etc.)
Always takes the precedence in the loading modules.
If the given module is not a core module (e.g. http, fs, etc.), Node.js will then begin to search for a directory named, node_modules.
It will start in the current directory (relative to the currently-executing file in Node.JS) and then work its way up the folder hierarchy, checking each level for a node_modules folder.
Once Node.JS finds the node_modules folder, it will then attempt to load the given module either as a (.js) JavaScript file or as a named sub-directory; if it finds the named sub-directory, it will then attempt to load the file in various ways. So, for example
If you make a request to load the module, "utils" and its a directory not a .js file then:Node.JS will search a hierarchical directory for node_modules and
utils in the following ways:
./node_modules/utils.js
./node_modules/utils/index.js
./node_modules/utils/package.json
If Node.JS still can't find the file in above steps, Node.js will then start to look into the directory paths from environment variables i.e. NODE_PATH set on your machine(obviously set by Node.JS installer file if you are on windows)
Not Found in all the above steps then, prints a stack trace to stderE.g.: Error:Cannot find module 'yourfile'
For more information: link is here even the cyclic require() is explained very well.

Relative file system write path within module

I have a executable node / javascript script that has a debug boolean, if set to true a couple of files will be written. This executable is also node module. Depending on the working directory of the user running the script it seems that the function can't find the directory to write files into.
The module is structured like this
output/
lib/
helpers.js
index.js
My original reasoning would be to have the path be.
helper.write = function(data,filename){
if(typeof data !== "string") data = JSON.stringify(data);
fs.writeFileSync("./output/"+filename, data);
};
However this works when running the script from within the node_module folder
fs.writeFileSync("process.cwd()+"/node_modules/the_module/output/"+filename, data);
Like this
node ./my_app/node_modules/the_module/index.js
This gets even more confusing if the modules is used in another executable file that uses the library.
node ./my_app/run.js
Is there a way to save the file independent from all of these variables?
If I understand the question correctly, you want to always write to a path relative to the current script. To get the name of the directory that the currently executing script resides in, you can use __dirname like so:
var path = require('path');
helper.write = function(data,filename){
if(typeof data !== "string") data = JSON.stringify(data);
var file = path.join(__dirname, 'output', filename);
fs.writeFileSync(file, data);
};
That being said, I don't think it's good practice to be writing files inside of your node_modules directory. I'd recommend that your module require the full path to a file somewhere else in the file system. If the caller wishes to write to an output directory in its own project tree, you can again use the same __dirname trick.

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

Resources