node icon indicating copy to clipboard operation
node copied to clipboard

Add a utility to convert file URL or path to one of them?

Open fisker opened this issue 2 years ago β€’ 32 comments

What is the problem this feature will solve?

It's a nice way to accept both URL and path string in API, but we need covert it to either string or URL, it would be nice to have a built-in method to do this.

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

For converting to string:

Maybe add path.from(URL | string)? @sindresorhus proposed here.

For converting to URL:

url.from(URL | string)

I'm not sure, since URL is a standard, I guess adding method URL object won't be acceptable, maybe to node:url module?

What alternatives have you considered?

No response

fisker avatar Jan 14 '22 13:01 fisker

We have a toPathIfFileURL internal API already, maybe we could expose it in the node:url module

https://github.com/nodejs/node/blob/38b7961ce6ca906ac8bad4d32c347f7a724989f9/lib/internal/url.js#L1558-L1562

For converting to URL:

url.from(URL | string)

I don't think there is any reliable way to check if a string is a path or a file URL... I'm afraid the best option here is to assume that a string is a path and call pathToFileURL(string) (which is what is doing Node.js internally as well) – or if you prefer to assume strings are URLs in your application, call new URL(string).

aduh95 avatar Jan 14 '22 14:01 aduh95

We have a toPathIfFileURL internal API already, maybe we could expose it in the node:url module

Wouldn't it be more natural to have it in node:path, since we want to convert it to a path? My proposal for path.from() was inspired by Array.from and Buffer.from type methods.

sindresorhus avatar Jan 15 '22 05:01 sindresorhus

I don't think there is any reliable way to check if a string is a path or a file URL...

To be clear, the string in that example is meant to be a file path, not a string file URL.

Example usage:

import path from 'node:path';

// Passthrough
path.from('/Users/sindresorhus/dev');
//=> '/Users/sindresorhus/dev'

path.from(new URL('file:///Users/sindresorhus/dev'));
//=> '/Users/sindresorhus/dev'

sindresorhus avatar Jan 15 '22 05:01 sindresorhus

Is this what you had in mind in terms of semantics? https://github.com/benjamingr/io.js/commit/070485195abe41dce9bf1143bb4f3e47b170f2ca#diff-6610c8d452ba38a0db8c591e06af555bc7755ace17065a066c853ffcc5271559R7-R20

benjamingr avatar Feb 16 '22 19:02 benjamingr

Yes, that's what I want.

fisker avatar Feb 17 '22 00:02 fisker

@aduh95 wdyt about an implementation that does that? ( https://github.com/nodejs/node/issues/41521#issuecomment-1042071145 )

benjamingr avatar Feb 17 '22 08:02 benjamingr

@aduh95 wdyt about an implementation that does that? ( #41521 (comment) )

I don't think we'll get consensus landing in core something that treats differently a string depending on if it starts with file: or not – what if the user meant ./file:/ (i.e. they really have a local directory named file:)?

The workarounds that come to mind are:

  • only support absolute paths – or require relative paths to start with a . (like in require calls).
  • always treat a string as a path.
  • publish this as an npm module instead (I think npm module would get away with not supporting having directory named file:).

Any combination of the above would address my concern, but I'm open to other ideas if someone thinks of something else.

aduh95 avatar Feb 17 '22 10:02 aduh95

@aduh95 I think it's safe to say "if this can be an npm module, sindre has already probably published one" :D Making small useful modules kind of their thing.

Edit: lol found it https://www.npmjs.com/package/file-url Edit2: actually that's the other side of conversion

benjamingr avatar Feb 17 '22 12:02 benjamingr

Basically: I think the main issue with this being on npm is that file urls and paths are both very common in modern Node.js and not having a utility to convert them in core is weird.

I'm sure we can bikeshed the name and semantics as long as the core use case (convert file url to path) is addressed.

Would it be better if the name was explicit path.fromFileUrl that only takes either a file:// url string or an actual URL with the file protocol and throws an error on non-file urls?

benjamingr avatar Feb 17 '22 12:02 benjamingr

I have no need for supporting file:// strings.

What I would like is:

export const from = urlOrPath => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
import path from 'path';

path.from('/Users/sindresorhus');
//=> '/Users/sindresorhus'

path.from(new URL('file:///Users/sindresorhus'));
//=> '/Users/sindresorhus'

sindresorhus avatar Feb 17 '22 13:02 sindresorhus

Would it be better if the name was explicit path.fromFileUrl that only takes either a file:// url string or an actual URL with the file protocol and throws an error on non-file urls?

No, this does not solve the request.

sindresorhus avatar Feb 17 '22 13:02 sindresorhus

So you would expect:

path.from('file:///Users/sindresorhus');
//=> file:///Users/sindresorhus

?

benjamingr avatar Feb 17 '22 13:02 benjamingr

Edit: was already mentioned above

I have no need for supporting file:// strings.

What I would like is:

export const from = urlOrPath => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
import path from 'path';

path.from('/Users/sindresorhus');
//=> '/Users/sindresorhus'

path.from(new URL('file:///Users/sindresorhus'));
//=> '/Users/sindresorhus'

So basically you would like toPathIfFileURL to become public API?

https://github.com/nodejs/node/blob/9caceb28aaa88c0f2126ae478a58b659db152481/lib/internal/url.js#L1555-L1563

targos avatar Feb 17 '22 13:02 targos

FYI: I have url-or-path published myself, and I found check protocol not that useful, and I removed recently.

fisker avatar Feb 17 '22 13:02 fisker

@benjamingr Yes

sindresorhus avatar Feb 17 '22 14:02 sindresorhus

So basically you would like toPathIfFileURL to become public API?

Yes

sindresorhus avatar Feb 17 '22 14:02 sindresorhus

Would it be fine if the name was more explicit like path.fromURL or path.fromFileURL ?

benjamingr avatar Feb 17 '22 18:02 benjamingr

I don't think we can be much more explicit than url.toPathIfFileURL.

aduh95 avatar Feb 17 '22 19:02 aduh95

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[bot] avatar Aug 17 '22 01:08 github-actions[bot]

Please keep this open.

sindresorhus avatar Aug 17 '22 01:08 sindresorhus

@MoLow wanna take a look?

benjamingr avatar Aug 17 '22 13:08 benjamingr

Sure, once I'm back from vacation

MoLow avatar Aug 17 '22 14:08 MoLow

Would it be fine if the name was more explicit like path.fromURL or path.fromFileURL ?

+1 to this, the semantics seems more concise with the rest of the API

khaosdoctor avatar Aug 24 '22 23:08 khaosdoctor

The pull request for this issue was recently closed for lack of response from one of the reviewers.

The main open question is how file URL strings ('file:///c:/foo.txt') should be handled. Should they be normalized to a path or passed through?

I would argue they should be either passed through or even throw a user-friendly error. Node.js APIs do not seem to currently handle file URL strings and I don't think they should either:

fs.readFileSync('file:///Users/sindresorhus/x.md');
// Error: ENOENT: no such file or directory, open

sindresorhus avatar Apr 22 '23 08:04 sindresorhus

Node.js APIs do not seem to currently handle file URL strings

Just to clarify, it does handle it but as a relative path (i.e. in your example it tries to read ./file:/Users/sindresorhus/x.md).

aduh95 avatar Apr 22 '23 09:04 aduh95

This solution would particularly be useful for converting import.meta.url into a file path.

SetTrend avatar Apr 28 '23 01:04 SetTrend

This solution would particularly be useful for converting import.meta.url into a file path.

You can already use fileURLToPath(import.meta.url) for that.

aduh95 avatar Apr 28 '23 03:04 aduh95

Oh, sorry. Got mislead by reading as this issue is still open.

SetTrend avatar Apr 28 '23 19:04 SetTrend

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[bot] avatar Jan 28 '24 01:01 github-actions[bot]

Please keep this open.

sindresorhus avatar Jan 28 '24 16:01 sindresorhus