Path to Application Support on Mac in Node.js - node.js

I'm attempting to read a file on the path on Mac ~/Library/Application Support/file_name.cert but cannot reach it using the fs.readFileSync Node.js module.
How do I read this file?

From what you wrote I am guessing the '~' character is the culprit. Your shell normally replaces this with your home directory, but this is not the case with Node.js (or any other program). So you'll have to replace it with your home directory like so:
// Incorrect path due to ~
//const filename = '~/Library/Application Support/file_name.cert';
// Correct path
const filename = process.env.HOME + '/Library/Application Support/file_name.cert';
// Now read will succeed
const data = fs.readFileSync(filename, 'utf8');

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.

Determining the path in fs.readFile()

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 ?

fs.readFileSync is not file relative? Node.js

Suppose I have a file at the root of my project called file.xml.
Suppose I have a test file in tests/ called "test.js" and it has
const file = fs.readFileSync("../file.xml");
If I now run node ./tests/test.js from the root of my project it says ../file.xml does not exist. If I run the same command from within the tests directory, then it works.
It seems fs.readFileSync is relative to the directory where the script is invoked from, instead of where the script actually is. If I wrote fs.readFileSync("./file.xml") in test.js it would look more confusing and is not consistent with relative paths in a require statement which are file relative.
Why is this? How can I avoid having to rewrite the paths in my fs.readFileSync?
You can resolve the path relative the location of the source file - rather than the current directory - using path.resolve:
const path = require("path");
const file = fs.readFileSync(path.resolve(__dirname, "../file.xml"));
Just to expand on the above, if you are using fs.readFileSync with TypeScript (and of course CommonJS) here's the syntax:
import fs from 'fs';
import path from 'path';
const logo = fs.readFileSync(path.resolve(__dirname, './assets/img/logo.svg'));
This is because fs.readFileSync() is resolved relative to the current working directory, see the Node.js File System docs for more info.
Source: Relative fs.readFileSync paths with Node.js
And of course, the CommonJS format:
const fs = require('fs');
const path = require('path');
const logo = fs.readFileSync(path.resolve(__dirname, './assets/img/logo.svg'));
Another alternative if you are using type module is to use process.cwd()
package.json
{
"type": "module",
}
console.log(process.cwd() + relative_path) // /User/your_user/path_to_folder

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