Get application full path in Node.js - 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

Related

How can I read a pdf file with express and node

I'm trying to read a pdf... and my idea is to convert it to a text. I have read the pdf-parser documentation and I don't understand why it is giving me this error, has anyone ever used pdf-parser?
Has anyone had this error?
It would be very helpful, I have never worked with it and the videos I watched use it very easily, but it breaks the code for me.
const url = require("./prueba.pdf");
const pdf = require("pdf-parse");
const fs = require("fs");
const pdffile = fs.readFileSync(url);
console.log(pdffile);
pdf(pdffile).then(function (data) {
console.log(data.text);
});
The path ./prueba.pdf is not correct, unless you run the node command from the ..\api\src\routes subdirectory, which I doubt.
Unlike paths in a require command, paths in an fs.readFileSync command are interpreted relative to the directory where you started the node process.

How to access the base package form a node_module

I am looking to access a JSON config file that the user would place next to their package.json from a node_module package that I created. Is there a best approach to do this. I tried a relative import but that didn't really work and I am not sure how best to accomplish dynamic imports if the config file doesn't exist because I want to allow it to not exist as well.
Here is how I tried to handle dynamic imports though:
export const overrides = (function () {
try {
return require('../../../../../../overrides.json');
} catch (_err) {
return null;
}
})();
Also I tried fs but I get a browser config error I am not sure if that is something else. I should research but I didn't understand the docs around that.
using a library
This worked for me: find-package-json
Basically on any js file who needs the base, home or workspace path, do this:
var finder = require('find-package-json');
var path = require('path');
var f = finder(__dirname);
var rootDirectory = path.dirname(f.next().filename);
rootDirectory will be the location of the folder in which the main package.json exist.
If you want to optimize, get the appRootPath variable at the start of your app and store/propagate the variable to the hole nodejs system.
no libraries
Without any library, this worked for me:
console.log("root directory: "+require('path').resolve('./'));
This will get you the root directory of your nodejs app no matter if you are using npm run start or node foo/bar/index.js
More ways to get the root directory here:
Determine project root from a running node.js application
usage
If you achieve to obtain the root directory of your nodejs app and your file is at the package.json level, use this variable like this to locate any file at root level:
rootDirectory+"/overrides.json"

require('../') in a script in the node_modules/.bin

I am trying to figure out how the sequelize auto script works in the node_modules directory of a node project.
The very first statement has me stumped:
var sequelizeAuto = require('../');
I don't understand why or how this works [how can you include a whole directory as a package?
Perhaps the runner (npx sequelize-auto) provides a special environment? How do I figure it out?
github: sequelize-auto script
Relative paths fallback to index.js if no file is mentioned.
var sequelizeAuto = require('../');
The above line is essentially a shorthand for :
var sequelizeAuto = require('../index.js');

Setting Up Node.js App Directory

I'm completely new to using Node.js and even utilizing the command line, so this question may be extremely elementary, but I am unable to find a solution.
I am trying to set up an app directory using Node.js and NPM. For some reason, whenever I try to use the port:5000 I get a "Cannot GET/" error. My question is, why is my setup for my app directory not working?
I have installed connect and serve-static, and yet it will not retrieve files and listen on port 5000. I have created a server.js file in my user, kstach1. Here is the code I have within that file:
var connect = require('connect');
var serveStatic = require('serve-static');
var app = connect();
app.use(serveStatic('../angularjs'));
app.listen(5000);
So, I don't quite understand why this won't reference my folder of angularjs, where I want to store my app. I have tested it by adding a file within the folder called test.html, and entered localhost:5000/test.html, and still get the "Cannot GET/test.html" error.
I know that Node is working correctly because I can enter scripts into the command line and they give the correct output. I do this as a user (kstach1).
The only thing I can think of that I may be doing wrong, is where my files are located. I have the angularjs folder located in the root user folder on my Mac (kstach1), as well as the server.js file. Is this incorrect? If this is not the issue, is it because of where Node is installed (usr/local/bin/node)? My research to this point has led me to think that my problem could also be that I need to add the installation directory to my path. However, I don't want to mess with this unless I know that is the case.
Any help would be greatly appreciated.
I did a little research on the serve-static package and copied the code you provided.
My project folder is located at "C:\teststatic" and the folder with the static files is: "C:\angularjs", also using "text.html" that is located in the 'angularjs' folder.
When running the code you provided and going to localhost:5000 it indeed returns "Cannot GET/". This is most likely because there is no "/" file declared.
Going to localhost:5000/test.html works for me, so you could try setting a "/" like this:
app.use(serveStatic('../angularjs', {'index': ['test.html', 'index.html']}));
And see if that works for you. If not, you should double check directory names / locations.
EDIT:
From reading the comment you posted: try this instead:
app.use(serveStatic('angularjs'));
I suggest moving your angularjs folder up into your main project's directory in a public/ folder. Its a pretty standard convention to have all of your static assets in public/. You can then use the path module to automatically resolve your path, inserting this where you have '../angularjs': path.join(__dirname, 'public').
So, your code would look like this:
var connect = require('connect');
var serveStatic = require('serve-static');
var app = connect();
var path = require('path');
app.use(serveStatic(path.join(__dirname, 'public'));
app.listen(5000);
And, your directory structure would look like this:
server.js
public/
angularjs/
test.html
You should then be able to use localhost:5000/angularjs/test.html to view your test.html

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