Taking absolute path from relative on Node

Asked

Viewed 1,568 times

2

I have a problem reading files in a code that is the following:

src/race.js

import { readFileSync } from "fs";
import { resolve } from "path";

export function readFile(path) {
  const absolutePath = resolve(__dirname, path);
  const content = readFileSync(absolutePath, "utf8");

  return content;
}

Well, when I use it in a file inside the folder itself src it works:

src/index.js

readFile("./kart.in")
// /home/pliavi/Projects/Kart/src/Kart.in

but I’m using the function in a folder test and when I use this function, it keeps pointing to the src instead of test:

test/race.test

readFile("./kart.test.in")
// /home/pliavi/Projects/Kart/src/Kart.test.in
// Arquivo não encontrado, pois ele está na test, não na src

How do I make it so that no matter which folder I am in, the path becomes from the current script folder?

Because there the __dirname takes the file path where the __dirname was written and not from what is running, I want to be able to use relative paths in the function as I want to use it in files in various folders but without the need to type all the way from the src.

2 answers

2

To get the absolute path of the current file you can use:

Object.defineProperty(global, '__stack', {
get: function() {
        var orig = Error.prepareStackTrace;
        Error.prepareStackTrace = function(_, stack) {
            return stack;
        };
        var err = new Error;
        Error.captureStackTrace(err, arguments.callee);
        var stack = err.stack;
        Error.prepareStackTrace = orig;
        return stack;
    }
});

Object.defineProperty(global, '__file', {
get: function() {
        return __stack[1].getFileName();
    }
});

Source: https://hk.saowen.com/a/de5f0f49d131b1fc5ae211824784134617d1d79b65e5c19d6420ac5dca423d58

With this in hand, just create a function to get the url of "__file". A regex would be enough, so you would always have the current script folder running.

console.log("Arquivo: %s", __file);

THE BEST WOULD BE:

Using the variables "__filename" and "__dirname" you will get the file path, so you can extract the path:

You can try these scripts:

1. require('path').basename(__filename);

or

2. __filename.split(path.sep).pop()

Source:

https://stackoverflow.com/questions/3133243/how-do-i-get-the-path-to-the-current-script-with-node-js

A more standardized way would be to define a constant defining the path of the files according to the environment you are. So when you are running in test environment you will search in an X folder and if you are in production environment in a Y folder.

function getPath(){

   //Busque como utilizar variáveis de sistema para seu sistema operacional(process.env)
   var environment = process.env.MEU_AMBIENTE || "test"; 

    if(environment == "test"){
       return  "SEU CAMINHO PARA ARQUIVOS DE TEST"
     }
    else
     {
       return  "SEU CAMINHO PARA ARQUIVOS DE DEV"
     }

}

If I were you, I would start defining configuration files already thinking about the environment that will work:

//Voce configura no seu sistema operacional onde seu arquivo de configuração esta
//No linux seria assim:
export ENVIRONMENT=test
export CONFIG_PATH=/etc/opt/myapp/config_folder

lib/load_config.js

'use strict'

var conf = require('nconf');
var configPath = process.env.CONFIG_PATH || ".";
var environment = process.env.ENVIRONMENT || "development";

//loading configuration file according with environment variables
conf.argv()
   .env()
   .file({ file: configPath + "/" + "config."+environment+".json"});

module.exports = conf;

config.dev.json

{
 "caminho.arquivos": "meu/caminho/de/dev"
}

config.test.json

{   
 "caminho.arquivos": "meu/caminho/de/test"
}

Example of use:

var conf = require('./lib/load_config');
var caminho = conf.get("caminho.arquivos");

This way, you just change the environment variable and you will get the expected result. What’s more, you can store all environment-dependent variables in the json file, for example using database credentials:

config.dev.json

{
 "caminho.arquivos": "meu/caminho/de/dev",
 "database.host": "ip_do_banco_de_dados",
 "database.name": "meubanco",
 "database.usuario": "meuusuario" 
 "database.senha": "minhasenha"
...
}

Example of use:

/****************************** DATABASE **************************************/
var mysql = require('mysql');

var host = nconf.get('database.host');
var user = nconf.get('database.usuario');
var password = nconf.get('database.senha');
var databaseName = nconf.get('database.name');

var conn = mysql.createConnection({
  host: host,
  user: user,
  database: databaseName,
  password: password
});
  • So that’s where __dirname takes the path from the file where __dirname was written and not from what is running, I want to be able to use relative paths, because I want to use this function in several folders, but without the need to type all the way from the src (where the function file is) or use predefined paths.

  • What you’re looking for is an anti-standard, so it’s hard to find, it’s a little illogical. You are mixing images, assorted files and source code in the same folder in different places.. I’ll give you a hiccup, but I recommend doing what I told you in that first answer...

  • Maybe it’s looking like something web or an application, I’m using it as a lib, so it can’t matter where the user will keep the files. But also I don’t think it would be a good thing to make the user use __dirname, I already got the result I wanted with other languages, but I don’t understand how it’s not something so simple in JS. Like, if seeing the require/import itself does this, I just want to read a file from a relative path, it shouldn’t be so complicated.

  • I just edited the answer, I believe this can help you. Mainly the link I left in the source, I used to generate a logger.

  • Bizarre, but it worked, and haha, every time I come up with a problem, I’m using Babel, it puts the script in mode strict and does not allow the use of callee, but I think I can get some results from your reply, thank you very much for all the time I’ve spent answering! o/ I’m just not going to put as a better answer, because I still think there is a way that is not something close to a gambiarra (no offense xD).

  • The loco, curses but does not offend Pow kkkk... Gambiarra nao, rss technical adjustment ;) For me what you are trying to do is a great Gambi, revise your architecture because it seems to me that this out of pattern what you are trying to do ;)

  • kkkkkk, nothing xD. But then, this is more of a simple thing, but the doubt hit me well, but I don’t think it’s so sneaky, have you ever seen React when you matter a picture? they use relative path from the component file, practically what I want to do is a function that does this, fetch a file from the script I’m running at that moment, I’m testing some things here, and I think I found... Just seeing if there’s no shawl before you open the answer

Show 2 more comments

0


A simple and functional way for the problem was the use of the variable module, from it I can find out who imported it and soon have the file path that is being read at that instant, using the following:

import { resolve, dirname } from "path"

const relativePath = path => resolve(dirname(module.parent.filename), path);

Obs: There is a single constraint, this function cannot be called in the file itself as it will have no parent and will launch a TypeError: Cannot read property 'filename' of null

Thanks to the answer and mainly from the source of @Vitor-Luiz-da-silva, I got some keywords that resulted in what I was looking for, because despite the Stacktrace work in most cases, it is exaggeration for what needed and does not fit very well in the context that wanted, which was a simple import instead of following the file path "the force", or even using predefined paths.

Source:
https://stackoverflow.com/questions/13651945/what-is-the-use-of-module-parent-in-node-js-how-can-i-refer-to-the-requireing

Browser other questions tagged

You are not signed in. Login or sign up in order to post.