Understanding how path works in Node - node.js

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!

Related

Is it possible to use computer path in Node?

Normally in node one would use a path similar to this:
../js/hereIsMyJs.js
However in mac for example (pc is different)
the path can be ~/Desktop/Ohms/js/hereIsMyJs.js
Is there any module or way to use the computer path I just presented in node?
I'm using a module that requires the path to where the file should be placed.
It has to work dynamic so the optimal solution would be for me just to feed it the "computer" path.
const fileName = '~/Desktop/Ohms/somewhere/here.jpg'
QRCode.toFile(fileName, 'https://example.com')
To achieve what you want, it's normal to use node's native path.resolve https://nodejs.org/api/path.html#path_path_resolve_paths
// Start from current directory, and gives absolute path valid to the current OS.
console.log( path.resolve("../js/hereIsMyJs.js") ); // ie: C:\\projects\\js\\hereIsMyJs.js
// It also accepts multiple arguments, so you can feed it partial paths
path.resolve( "..", "js" ,"hereIsMyJs.js" ); // same result as above.
Other things worth to mention:
The tilde character ~ is short for the home directory in the *nix world. And works most places not windows.
In node you can use require('os').homedir() to get the home directory
There is also __dirname (gives absolute path of the directory containing the currently executing file) and process.cwd() which gives the directory from where you executed your file
And finally there is path.join() which is similar to resolve, but works for joining relative paths, and doesn't care about the current directory.

Why does require() not require an absolute path but an express.static() does?

I am trying to run my index.js script from outside the project directory. My project structure is as follows:
app
- config
- config.js
- public
- index.html
- src
- index.js
Now when I run my src/index.js from outside my app folder, require() is able to resolve the relative paths
const config = require(`../config/config`);
On the other hand express.static is not able to resolve such relative paths.
e.g. app.use(express.static("../public"));
Why do I need to use path.join and get the absolute path?
require() works off __dirname which is independent of what the current directory was when your app was loaded. It's always the directory where the module is located in, so it is consistent.
express.static() when used with relative paths uses the directory that the main app was launched form, so if you use relative paths, its behavior varies depending upon how you launch the app.
From the express doc for serving static files:
However, the path that you provide to the express.static function is
relative to the directory from where you launch your node process. If
you run the express app from another directory, it’s safer to use the
absolute path of the directory that you want to serve
So, if you want the directory to be module relative, you have to manually combine your path with __dirname to make a full path, as you have discovered.

Nodejs difference between ./folderpath vs ../folderpath

I'm new in nodejs. I try to use some file in my filesystem. I would like to get them through some realtive path. Here is the structure:
-app
-resources
-tmp
-file1
-file2
-common
-common.js
-etc
So, I would like to reach the file1 and file2 in my resources/tmp folder from the common.js file in int common folder. I used two relative path methodic:
// First , wrong one
var tmpfolder = '../resources/tmp';
// Second, good one
var tmpfolder = './resources/tmp';
The file absolute path is something like this:
C:\Users\xy\Documents\work\nodejs\projects\project_wrapper_folder\project_folder\resources\tmp
If I log the first relative path I got this result:
C:\Users\xy\Documents\work\nodejs\projects\project_folder\resources\tmp
which is wrong, because it does not contains the wrapper folder.
But the second works fine.
Can somebody explain me this behaviour?
UPDATE
I see the meaning if '../', thanks your explanations!
I have tried #Lissy answer: "So baring that in mind ./ will resolve to the value of your project root..." that sounds great, but the result is not.
I have this logic in my app:
var tmpfolder = require('./otherFolder/orhetFile');
where otherFolder is the subfolder of my project_folder. So, when I used this here, I got an error called Cannot find module ...
But if I use this './' in fs module, here: /project_folder/otherFolder_2/otherFile_2 like:
var path = `./resources/tmp`;
fs.mkdirsSync(path);
It works!
these is strange for me. If './' means the current folder, than the example above sould not work (but it's works).
But if the './' means path of the project root, the example with require should work (but does not work).
Strange for me, is there some meaning of require or fs??
In Summary
./my-file means look at the root, whereas ../my-file, means come out of the current directory, and look in the parent folder.
Explanation of Relative and Absolute Paths in Node.js
The default document root is set with the NODE_PATH environment variable (however it would be terrible practice to modify that). So baring that in mind ./ will resolve to the value of your project root.
And so let tmpfolder = require('./resources/tmp'); would resolve to
C:\Users\......\project_wrapper_folder\project_folder\resources\tmp as you have seen
A relative path is denoted by not starting with ./, so for example let tmpfolder = require('my-scripts/some-script'); would look in the current directory for another folder called my-scripts.
Following on from that ../ is relative to the current directory, but goes out one (to it's parent) and looks from there. You can go out two directories by doing ../../my-dir and so on (this is not great practice though, as it can get hard to manage if you have ../../../../../../)
Better method
You can use the __dirname constant in Node to locate the directory name of the current module.
e.g.
fs.readFile(__dirname + '/../foo.bar');
Useful Links
I think you'll find this article on Better local require() paths for Node.js very useful.
Also, for a bit of further reading, here is the official Node.js documentation on paths
The .. means the previous dir. So you are getting out from project_wrapper_folder and then add to the script dir resources\tmp and that way the project_wrapper_folder is no longer in the relative path.
Lets assume you are inside a folder called app.
when you use ../resources/tmp, it will come out of the app folder and will search for tmp inside resources folder.
when you use ./resources/tmp, it will look within the app folder for resources folder and tmp inside it.
../ points to the parent directory while ./ points to current working directory.
A dot basically means "go one folder back in the path"
So:
'./' points at the folder you are in.(in your case the folder common/)
'../' points at the folder that contains the folder you are in. (in your case the folder app/)

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