Marcos Casagrande
Marcos Casagrande

Reputation: 40444

Node.js' __dirname & __filename equivalent in Deno

How can I get the directory & file name of the current module?. In Node.js I would use: __dirname & __filename for that

Upvotes: 45

Views: 14802

Answers (4)

Marco Roy
Marco Roy

Reputation: 5285

new Error().stack contains not only the current file path, but also the callers/importers, which can be immensely useful in some cases.

To retrieve the originating/importing script, something like this works well:

const filePath = new Error().stack.split("\n").pop();
const fileName = filePath.match(/[/]([^./]+)\.ts/)[1];

Upvotes: 0

Marcos Casagrande
Marcos Casagrande

Reputation: 40444

Since Deno 1.40 you can now use import.meta.dirname and import.meta.filename. Here's what the various import.meta properties look like when running deno main.js:

  • import.meta.dirname: /home/foo/app
  • import.meta.filename: /home/foo/app/main.js
  • import.meta.url: file:///home/foo/app/main.js

Note that import.meta.url is a browser standard, while the other two are server-side additions.


OLD ANSWER

In Deno, there aren't variables like __dirname or __filename but you can get the same values thanks to import.meta.url

On *nix (including MacOS), you can use URL constructor for that (won't work for Windows, see next option):

const __filename = new URL('', import.meta.url).pathname;
// Will contain trailing slash
const __dirname = new URL('.', import.meta.url).pathname;

Note: On Windows __filename would be something like /C:/example/mod.ts and __dirname would be /C:/example/. But the next alternative below will work on Windows.


Alternatively, you can use std/path, which works on *nix and also Windows:

import * as path from "https://deno.land/[email protected]/path/mod.ts";

const __filename = path.fromFileUrl(import.meta.url);
// Without trailing slash
const __dirname = path.dirname(path.fromFileUrl(import.meta.url));

With that, even on Windows you get standard Windows paths (like C:\example\mod.ts and C:\example).


Another alternative for *nix (not Windows) is to use a third party module such as deno-dirname:

import __ from 'https://deno.land/x/dirname/mod.ts';
const { __filename, __dirname } = __(import.meta);

But this also provides incorrect paths on Windows.

Upvotes: 57

Raeisi
Raeisi

Reputation: 2181

For logging purposes, I extracted the directory and filenames using pure Javascript/Typescript demonstrated in the following snippet code:

function getModuleName(moduleName) {
  moduleName ||= 'UndefinedModule';
  
  if (moduleName.startsWith("file:")) {
    const parts = moduleName.split("/");
    const srcIx = parts.indexOf("src") || parts.length - 1;
    moduleName = parts.slice(srcIx).join("/");
  }

  return moduleName;
}

// for Deno compatibility
const _import = {meta: {url: 'file:///D:/Programming/Deno/test_00/main.ts' } }; // remove this line

console.log(getModuleName(_import.meta.url)); // use import.meta.url in Deno land
console.log(getModuleName('file:///D:/Programming/Deno/test_00/src/databse.ts'));
console.log(getModuleName('file:///D:/Programming/Deno/test_00/src/utils/decoder.js'));
console.log(getModuleName('MyCustomName'));

/*
output:

 main.ts
 src/database.ts
 src/utils/decoder.js
 MyCustomName
 
*/

I assumed that source code files are placed under the src directory and some other files (like main.ts) exist in the root directory.

Deno Version:

$ deno --version
deno 2.0.0-rc.9+aafe771 (canary, release, x86_64-pc-windows-msvc)
v8 12.9.202.13-rusty
typescript 5.6.2

Upvotes: 0

Andrew Koster
Andrew Koster

Reputation: 1845

This is the up-to-date fix that just works on all platforms as far as I can tell and provides complete feature parity:

import * as path from "https://deno.land/[email protected]/path/mod.ts";

const __filename = path.fromFileUrl(import.meta.url);
const __dirname = path.dirname(path.fromFileUrl(import.meta.url));

Upvotes: 7

Related Questions