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

Can’t import fs Promises API with ECMAScript Modules #21014

Closed
dieulot opened this issue May 29, 2018 · 22 comments · Fixed by #31553
Closed

Can’t import fs Promises API with ECMAScript Modules #21014

dieulot opened this issue May 29, 2018 · 22 comments · Fixed by #31553
Labels
esm Issues and PRs related to the ECMAScript Modules implementation. feature request Issues that request new features to be added to Node.js. fs Issues and PRs related to the fs subsystem / file system.

Comments

@dieulot
Copy link

dieulot commented May 29, 2018

  • Version: v10.2.1
  • Platform: Windows 10 64-bit
  • Subsystem: fs

Per the docs, “The API is accessible via require('fs').promises.”

When using ECMAScript Modules it can’t be accessed like that. One may expect to be able to load it with import {promises as fs} from 'fs', but this gives an error.

import {promises as fs} from 'fs'
        ^^^^^^^^
SyntaxError: The requested module 'fs' does not provide an export named 'promises'
    at ModuleJob._instantiate (internal/modules/esm/module_job.js:89:21)

So right now accessing the fs Promises API directly when using ECMAScript Modules requires two lines, like so:

import {default as fsWithCallbacks} from 'fs'
const fs = fsWithCallbacks.promises
@devsnek
Copy link
Member

devsnek commented May 29, 2018

it's an experimental API so the esm loader doesn't attach it as a named export.

@devsnek devsnek added question Issues that look for answers. fs Issues and PRs related to the fs subsystem / file system. esm Issues and PRs related to the ECMAScript Modules implementation. labels May 29, 2018
@dnalborczyk
Copy link
Contributor

@dieulot here is a related discussion: #20504

@jdalton
Copy link
Member

jdalton commented May 30, 2018

@dieulot I'm going to close this issue since has been answered. Feel free to ping back though for anything.

@jdalton jdalton closed this as completed May 30, 2018
@rektide
Copy link

rektide commented Dec 2, 2018

Ideally I could:
import {readFile} from 'fs/promise

The opening ask would be only mildly ghastly & ugly, getting a complete 'fs' import.

@devsnek
Copy link
Member

devsnek commented Dec 2, 2018

the original design of fs promises was as you mention it. I'm hopeful it can be restored.

@rektide
Copy link

rektide commented Dec 6, 2018

Talked with @jdalton some on twitter. He's intending to switch his standard-things/esm project over to exposing non-enumerable properties. This won't make import {readFile} from '[something-or-other]' possible (which would be the most natural & desireable in the EcmaScript module world) but it should mean we can at least import {promises} from 'fs' which is better than where we are now.

@paddotk
Copy link

paddotk commented Jul 28, 2019

@jdalton I'm using Node 10.16.0 and this still doesn't work for me.

Trying the following:

const fs = window.require('fs'); // Works
const fsPromises = window.require('fs').promises; // Nope

or

const fs = window.require('fs');
const fsPromises = fs.promises; // Nope

or

const fsPromises = window.require('fs/promises')

all doesn't work for me.

Since I need to specify window (or global), I can't use an import statement either. I'm using (the latest version of) Electron although I doubt this makes any difference..

@samdutton
Copy link

const fsPromises = require('fs').promises; works for me.

@michaelbrawn
Copy link

michaelbrawn commented Sep 6, 2019

const fsPromises = require('fs').promises; works for me.

Unfortunately, in TS, ES6, ESLint, await/async land with @typescript-eslint/no-require-imports enabled, this workaround isn't ideal.

Still waiting on something as simple as

import { readFile } from 'fs/promises'

or

import { readFile } from 'fs.promises'

or best yet,

import { readFileAsync } from 'fs'

@devsnek devsnek reopened this Sep 6, 2019
@devsnek devsnek added feature request Issues that request new features to be added to Node.js. and removed question Issues that look for answers. labels Sep 6, 2019
@devsnek
Copy link
Member

devsnek commented Sep 6, 2019

we still need a better way to do this

@robbie-mac
Copy link

I may be missing something but:

import { promises as fs } from 'fs';

isn't good enough?

@damianobarbati
Copy link

@robbie-mac it's OK, but not the best.
Why importing into the script scope the full fs library when you need just a function or a bunch of them? It's a waste of memory.
Either of:

import { readFile } from 'fs/promises'
import { readFileAsync } from 'fs'

would be ok.

The former needs node to start using the package exports mentioned here in fs: https://nodejs.org/api/esm.html#esm_package_exports

Not sure how code modules/libs work though.

@damianobarbati
Copy link

@devsnek does node team have another tentative date for experimental-modules flag removal?
I see the flag was added back into 12.x.x with #29754 because of
WICG/webcomponents#839

From what I see, we are very far from having a safe ESM import model: does this mean node will have the experimental-modules flag for a very long time? (probably another year or two years)

My concern is that due to the flag, the libraries authors aren't willing to adapt and implement "package exports" and thus the flag is stopping the whole environment from moving onwards to ESM:
jest => jestjs/jest#4842 (comment)
lodash => lodash/lodash#3775 (comment)
and so on.

Because we gotta be honest and admit that without the package exports in place, experimental-modules is totally unusable.
Behaviour is totally different between ESM and previous commonjs auto-resolution model and browser bundlers.

@devsnek
Copy link
Member

devsnek commented Nov 13, 2019

--experimental-modules flag was just removed in master. the flag that remains is --experimental-json-modules.

also, it is good that people weren't implementing anything until the flag was removed.

@marekmartins
Copy link

ECMAScript Modules default support landed in 13.2.0

https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V13.md#13.2.0

@the-spyke
Copy link

the-spyke commented Jan 28, 2020

So, what's the answer? .promises thing and callback versions look sad in 2020. And the situation with ESM .promises looks twice as sad. import { promises } from "fs"; is not funny.

Maybe just export promise based versions as fs in ESM and add fs/callback/fs/sync for legacy stuff? (I know you're not going to do this)

@GeoffreyBooth
Copy link
Member

The standard pattern I’ve seen projects follow is import { promises as fs } from 'fs'. If you want particular methods as top-level variables, you could follow that with e.g. const { readFile } = fs.

I’m not sure there will be a better way to do this anytime soon. That would involve some alternative for 'fs', like 'fs/promises' or 'fsAsync' or something, but there hasn’t been much movement on finding a consensus for new builtin modules and their names.

@the-spyke
Copy link

@GeoffreyBooth import { promises as fs } is not a pattern and misses the whole point of ESM. We're using it, but the luck of a proper solution is disappointing.

@devsnek
Copy link
Member

devsnek commented Jan 28, 2020

If #31553 is merged you will be able to do import { readFile } from 'fs/promises';

@DRoet
Copy link

DRoet commented Mar 12, 2020

what about require('dns').promises ?

@shisama
Copy link
Contributor

shisama commented Apr 20, 2020

#32953 is the PR for dns/promises.

@igor9silva
Copy link

This works now:

import fs from 'node:fs/promises'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
esm Issues and PRs related to the ECMAScript Modules implementation. feature request Issues that request new features to be added to Node.js. fs Issues and PRs related to the fs subsystem / file system.
Projects
None yet
Development

Successfully merging a pull request may close this issue.