Olek
Olek

Reputation: 43

How to comfortably work with paths that are relative to the working directory in Deno?

My original motivation was to run a Deno script from Crontab on Ubuntu.

First I did not know that paths are relative to the working directory, not the executing module.

My script was reading and writing files to a disk, so I got errors like

error: Uncaught NotFound: No such file or directory (os error 2)

I was pointed out that this problem can be solved with import.meta.url.

I modified the path to resolve it from import.meta.url and this solution worked fine with read/write operations.

But I encountered another problem with .env file. It was a surprise to me that even the dotenv module uses paths relative to the working directory.

The dotenv module has the option to specify the path with config({path:___}), but I think it is too much to overwrite the default location.

Eventually, changing the working directory to the script's root directory before running the script in crontab was a simpler solution.

* * * * * cd ____; deno run ___

But I still have doubts if this is the most efficient way.

Is there something better to changing a directory in such cases?

It would be nice to have a mode when running deno, which would make paths relative to the executing module excluding modules which are imported with URLs.

Upvotes: 3

Views: 3703

Answers (1)

jsejcksn
jsejcksn

Reputation: 33796

I think you're looking for Deno.mainModule, which is a reference to the file URL of the entrypoint module you passed to deno. You can use it with the deno.land/std/path module to get the directory of the entrypoint for your program, and then use Deno.chdir() to change your current working directory so that all relative paths (which are implicitly relative to Deno.cwd()) are then relative to that directory.

/repo/relative-path.ts:

import * as path from 'https://deno.land/[email protected]/path/mod.ts';
export {path};

export const mainModuleDir = path.dirname(path.fromFileUrl(Deno.mainModule));

/repo/main.ts:

import {mainModuleDir, path} from './relative-path.ts';

Deno.chdir(mainModuleDir);

const entrypointRelativePath = path.resolve('hello', 'world.json');
console.log(entrypointRelativePath);

Then, run your script:

$ cd /different/unrelated/path
$ deno run --allow-read /repo/main.ts
/repo/hello/world.json

You can use mainModuleDir as a base for any entrypoint-relative paths you need.

Upvotes: 3

Related Questions