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

Add basic ESM support #854

Closed
wants to merge 1 commit into from
Closed

Add basic ESM support #854

wants to merge 1 commit into from

Conversation

c-vetter
Copy link

Fixes #746

@RyanZim @jprichardson
I honestly do not see the big challenges mentioned in #746 ­– I think, apart from documentation, this should do it. It works as intended in a project I am working on. Am I missing something, or can this be merged?

Should node change its ESM interface, that might result in a breaking change here as well. However, that seems rather unlikely and will not happen often if at all. I vote to implement this now and change later if necessary, and mark this experimental as long as the node implementation is marked experimental.

@RyanZim
Copy link
Collaborator

RyanZim commented Dec 18, 2020

The complication is that some fs methods are only available in certain places. For example, fs.lchown does not exist on some Linux distros. fs.opendir is only available on Node v12.12+ How will this code handle that?

@c-vetter
Copy link
Author

c-vetter commented Dec 19, 2020

How will this code handle that?

Currently, not at all. In such a situation, the call to fs.opendir will presently throw TypeError: opendir is not a function.

fs.lchown does not exist on some Linux distros

I was not aware that there are platform-dependent differences in fs's interfaces. The node-docs do list some platform-specific behavior, but the that needs to be handled on the consumer end anyway.

A quick web search yielded no useful information on that problem. Can you point me to some solid documentation on that? Is that a general issue, or version-dependent? On what platform could I check a proposed solution?

If this is version-dependent, the question becomes whether that is still an issue post-v12.7.0, since that is the version when the exports field was introduced. Versions before that won't use the ESM export, so they can be safely ignored.

fs.opendir is only available on Node v12.12+

That is another bag, and needs to be addressed unconditionally. I see these options:

  • Export but throw, with these alternatives:
    • Leave it as it is, but document that caveat
    • Replace each missing function with a fallback function that throws an Error including the information that some functions are missing on older versions
    • As before, but include specific version information
  • Version-specific builds, such that on older versions, one would import { mkdir } from 'fs-extra/12

Both approaches have their drawbacks, but I'm gravitating towards the export with custom errors. What do you think?

@RyanZim
Copy link
Collaborator

RyanZim commented Dec 19, 2020

It seems the situation for lchown has changed. Historical reference: nodejs/node-v0.x-archive#7382 Changed in nodejs/node#21498; released v10.6.0. However, this seems to still be the case for lchmod: https://github.com/nodejs/node/blob/daa132260d19a5a8f46253259101a586dcba6fc4/lib/fs.js#L2098-L2099

However, I did a bit of testing, and this is not an issue for us, as fs itself exports lchmod as undefined on systems where it's not supported, so we can do the same.


opendir is a different bag, since old versions don't export it at all. import { opendir } from 'fs' errors out, since opendir is not a named export. Also, review this example from an old version of node without opendir, on a platform that does not have lchmod:

import * as fs from 'fs'

console.log('lchmod' in fs) // -> true
console.log(fs.lchmod) // -> undefined

console.log('opendir' in fs) // -> false
console.log(fs.opendir) // -> undefined

This behavior is impossible to replicate without export * from 'fs' or version-specific builds. Obviously, I'm not a fan of version-specific builds. I'm not sure what's the right path forward here.

@c-vetter
Copy link
Author

The only viable option I see to achieve availability-based static exports is building the exports locally, in a post-install script. That would necessitate a rebuild on a node update. Also, specific testing may be somewhat hairy.

What do you think?

@RyanZim
Copy link
Collaborator

RyanZim commented Jan 18, 2021

Wow, nearly a month; my apologies for letting this go so long without response.

In general, I think postinstall scripts are a terrible idea. This is especially problematic for as popular a module as fs-extra, which is undoubtedly used in many environments that have ignore-scripts true set in .npmrc, for obvious security reasons.

Long-term, I'd like to consider removing promise polyfilling of fs, in favor of exporting fs-extra/promises for parity with fs/promises. With this in place, graceful-fs would be the only thing holding us back from export * from 'fs'; and the general lack of maintenance there is a problem for us in general. However, that's a lot to work though; perhaps compromises in strict export behavior will have to be made.

@RyanZim RyanZim mentioned this pull request Jul 22, 2021
@RyanZim
Copy link
Collaborator

RyanZim commented Sep 21, 2021

Here is my current proposal for a way forward; I will plan to implement this unless there's good opposition: #746 (comment)

@RyanZim
Copy link
Collaborator

RyanZim commented Oct 25, 2022

Closing in favor of #974; feel free to review there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support ESM
2 participants