Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

URL version of process.cwd() #49273

Closed
3 tasks
LiviaMedeiros opened this issue Aug 21, 2023 · 7 comments
Closed
3 tasks

URL version of process.cwd() #49273

LiviaMedeiros opened this issue Aug 21, 2023 · 7 comments
Labels
feature request Issues that request new features to be added to Node.js. process Issues and PRs related to the process subsystem. stale whatwg-url Issues and PRs related to the WHATWG URL implementation.

Comments

@LiviaMedeiros
Copy link
Contributor

What is the problem this feature will solve?

Right now we don't have convenient way to get current working directory in URL form such as file:///path/to/current/working/directory/.

Having easy access to this form would allow to resolve local paths using WHATWG URL constructor, i.e. new URL('../path/to/file', cwdURL), without need to import path and worry about platform-specific separators.

Getting this form in userspace is not very convenient:

// results in URL without trailing slash, indicating that it's directory and allowing to use it directly as baseURL
const cwdURL = url.pathToFileURL(process.cwd());

// appending pathname suffix to full href is semantically wrong
const cwdURL = url.pathToFileURL(process.cwd()).href + '/';

// triggers pathname setter which requires reparsing URL again
const cwdURL = url.pathToFileURL(process.cwd());
cwdURL.pathname += '/';

// three imports for one value, including `path` which we may want to avoid
const cwdURL = url.pathToFileURL(process.cwd() + path.sep);

// very bad for multiple reasons but tempting enough to appear in the wild :(
const cwdURL = `file://${process.cwd()}/`;

What is the feature you are proposing to solve the problem?

  • support URL instances with file: protocol in process.chdir(directory).
  • add process.cwdURL() that returns URL instance or string.
  • add resolve(...urls) method that would construct new absolute URL on top of cwd if all provided urls are relative. url.resolve() is not vacant and has different behaviour, so it should have different name or place.

Better naming suggestions are very welcome.

What alternatives have you considered?

  • userland module.
  • adjustments to parsing URLs with file: protocol that would resolve relative pathname against cwd instead of root, i.e.:
// current behaviour
new URL('file:./file.txt').href === 'file:///file.txt'

// proposed behaviour
new URL('file:./file.txt').href === 'file:///path/to/current/working/directory/file.txt'
@LiviaMedeiros LiviaMedeiros added feature request Issues that request new features to be added to Node.js. process Issues and PRs related to the process subsystem. whatwg-url Issues and PRs related to the WHATWG URL implementation. labels Aug 21, 2023
@aduh95
Copy link
Contributor

aduh95 commented Aug 21, 2023

What not use paths? Do you have a specific use case in mind?

@LiviaMedeiros
Copy link
Contributor Author

In general,

  1. Cases when we have to use urls. For example,
const settingsLocation = new URL('../.config/settings.json', env.MYBASEDIR ?? cwdURL());
validateOrMutate(settingsLocation);
const settings = await import(settingsLocation, { assert: { type: 'json' } });
  • any third-party module that accepts only URL, e.g. for compatibility with browsers
  • perhaps, eventually Fetch API
  1. Cases when we want to use urls. For example, if
  • we deal not only with local filesystem, e.g. to be polymorphic with file:///usr/portage/net-dialup/ and rsync://winchester.local/portage/net-dialup/
  • we want to make sure that on non-posix OS relative paths are not misinterpreted on input and not generated with backslashes on output
  • we want to write API that accepts urlstrings, and we don't want heuristics to determine if it's URL or path
  1. All of /pathToFileURL\((process\.)?cwd\(/, js:file://${cwd}, ts:file://${cwd}
  2. ESM in Node.js core: lib/repl.js lib/internal/process/pre_execution.js lib/internal/modules/esm/resolve.js lib/internal/modules/esm/loader.js

In most of these, having URL instance that is resolved against cwd would allow avoid conversion (or even double conversion) between URL and path and having a mix of these in code (which can easily become a bug farm, as many operations keep working until there is directory with %/?/#, or URL with hash, or the code runs on Windows).


As specific usecase, let's say, I want to read a file defined by URL (can be string, can be relative), in a way like

const buffer = myFsReadFileSyncByURL('./path/to/file.bin?position=30&length=8#btwAmRelativeURL');
const text = await (await myFetch('path/to/file%20with%20spaces.txt')).text();

It's simple with absolute URL, but there's no concise way to resolve relative URL into it: WHATWG URL standard doesn't support relative URLs (at least, yet), url.fileURLToPath('file:./path') resolves against / or throws if protocol is omitted.

Also as a matter of fact, even if we want to switch context from URLs to paths. we don't have relativeFileURLtoRelativePath() utility either.

@anonrig
Copy link
Member

anonrig commented Aug 22, 2023

I think what you want is similar to Rust's Path struct where you can easily mutate the pathname, get URL components and change them without sacrificing the DX and performance.

Copy link
Contributor

There has been no activity on this feature request for 5 months and it is unlikely to be implemented. It will be closed 6 months after the last non-automated comment.

For more information on how the project manages feature requests, please consult the feature request management document.

@github-actions github-actions bot added the stale label Feb 19, 2024
Copy link
Contributor

There has been no activity on this feature request and it is being closed. If you feel closing this issue is not the right thing to do, please leave a comment.

For more information on how the project manages feature requests, please consult the feature request management document.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Mar 21, 2024
@karlhorky
Copy link

karlhorky commented Apr 5, 2024

FWIW I also ran into this issue today with using process.cwd() as part of a path passed to dynamic import(), and the error was pretty confusing (and only on Windows);

$ pnpm eslint . --max-warnings 0
  
Oops! Something went wrong! :(
ESLint: 8.57.0
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'd:'
    at throwIfUnsupportedURLScheme (node:internal/modules/esm/load:239:11)
    at defaultLoad (node:internal/modules/esm/load:130:3)
    at ModuleLoader.load (node:internal/modules/esm/loader:409:13)
    at ModuleLoader.moduleProvider (node:internal/modules/esm/loader:291:56)
    at new ModuleJob (node:internal/modules/esm/module_job:65:26)
    at #createModuleJob (node:internal/modules/esm/loader:303:17)
    at ModuleLoader.getJobFromResolveResult (node:internal/modules/esm/loader:260:34)
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:241:17)
    at async ModuleLoader.import (node:internal/modules/esm/loader:328:23)
Error: Process completed with exit code 1.

Doesn't show any user code in stack trace. In my case, I was using the dynamic import inside of a eslint.config.js (ESLint Flat Config) file:

// ✅ Working on macOS and Linux, 💥 Throws error on Windows
await import(`${process.cwd()}/package.json`, {
  assert: { type: 'json' },
});

Eventually I guessed my way to figure out it was the process.cwd() failing only on Windows inside the dynamic import(), and also used pathToFileURL from node:url:

+import { pathToFileURL } from 'node:url';

-await import(`${process.cwd()}/package.json`, {
+await import(pathToFileURL(`${process.cwd()}/package.json`).href, {
  assert: { type: 'json' },
});

@karlhorky
Copy link

karlhorky commented Apr 5, 2024

@aduh95 @anonrig is there any Node.js implementer interest in making this easier to fall into the pit of success on Windows?

If so, maybe this issue could be reopened?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Issues that request new features to be added to Node.js. process Issues and PRs related to the process subsystem. stale whatwg-url Issues and PRs related to the WHATWG URL implementation.
Projects
Status: Pending Triage
Development

No branches or pull requests

5 participants
@anonrig @karlhorky @aduh95 @LiviaMedeiros and others