Skip to content

Commit

Permalink
Add fs-extra/esm ESM named import module, with just fs-extra methods
Browse files Browse the repository at this point in the history
Fixes #746
  • Loading branch information
RyanZim committed Oct 25, 2022
1 parent 572a1c9 commit f4a4149
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 4 deletions.
30 changes: 29 additions & 1 deletion README.md
Expand Up @@ -27,6 +27,8 @@ Installation
Usage
-----

### CommonJS

`fs-extra` is a drop in replacement for native `fs`. All methods in `fs` are attached to `fs-extra`. All `fs` methods return promises if the callback isn't passed.

You don't ever need to include the original `fs` module again:
Expand Down Expand Up @@ -55,6 +57,31 @@ const fs = require('fs')
const fse = require('fs-extra')
```

### ESM

There is also an `fs-extra/esm` import, that supports both default and named exports. However, note that `fs` methods are not included in `fs-extra/esm`; you still need to import `fs` and/or `fs/promises` seperately:

```js
import { readFileSync } from 'fs'
import { readFile } from 'fs/promises'
import { outputFile, outputFileSync } from 'fs-extra/esm'
```

Default exports are supported:

```js
import fs from 'fs'
import fse from 'fs-extra/esm'
// fse.readFileSync is not a function; must use fs.readFileSync
```

but you probably want to just use regular `fs-extra` instead of `fs-extra/esm` for default exports:

```js
import fs from 'fs-extra'
// both fs and fs-extra methods are defined
```

Sync vs Async vs Async/Await
-------------
Most methods are async by default. All async methods will return a promise if the callback isn't passed.
Expand Down Expand Up @@ -197,7 +224,8 @@ fs-extra contains hundreds of tests.

- `npm run lint`: runs the linter ([standard](http://standardjs.com/))
- `npm run unit`: runs the unit tests
- `npm test`: runs both the linter and the tests
- `npm run unit-esm`: runs tests for `fs-extra/esm` exports
- `npm test`: runs the linter and all tests


### Windows
Expand Down
68 changes: 68 additions & 0 deletions lib/esm.mjs
@@ -0,0 +1,68 @@
import _copy from './copy/index.js'
import _empty from './empty/index.js'
import _ensure from './ensure/index.js'
import _json from './json/index.js'
import _mkdirs from './mkdirs/index.js'
import _move from './move/index.js'
import _outputFile from './output-file/index.js'
import _pathExists from './path-exists/index.js'
import _remove from './remove/index.js'

// NOTE: Only exports fs-extra's functions; fs functions must be imported from "node:fs" or "node:fs/promises"

export const copy = _copy.copy
export const copySync = _copy.copySync
export const emptyDirSync = _empty.emptyDirSync
export const emptydirSync = _empty.emptydirSync
export const emptyDir = _empty.emptyDir
export const emptydir = _empty.emptydir
export const createFile = _ensure.createFile
export const createFileSync = _ensure.createFileSync
export const ensureFile = _ensure.ensureFile
export const ensureFileSync = _ensure.ensureFileSync
export const createLink = _ensure.createLink
export const createLinkSync = _ensure.createLinkSync
export const ensureLink = _ensure.ensureLink
export const ensureLinkSync = _ensure.ensureLinkSync
export const createSymlink = _ensure.createSymlink
export const createSymlinkSync = _ensure.createSymlinkSync
export const ensureSymlink = _ensure.ensureSymlink
export const ensureSymlinkSync = _ensure.ensureSymlinkSync
export const readJson = _json.readJson
export const readJSON = _json.readJSON
export const readJsonSync = _json.readJsonSync
export const readJSONSync = _json.readJSONSync
export const writeJson = _json.writeJson
export const writeJSON = _json.writeJSON
export const writeJsonSync = _json.writeJsonSync
export const writeJSONSync = _json.writeJSONSync
export const outputJson = _json.outputJson
export const outputJSON = _json.outputJSON
export const outputJsonSync = _json.outputJsonSync
export const outputJSONSync = _json.outputJSONSync
export const mkdirs = _mkdirs.mkdirs
export const mkdirsSync = _mkdirs.mkdirsSync
export const mkdirp = _mkdirs.mkdirp
export const mkdirpSync = _mkdirs.mkdirpSync
export const ensureDir = _mkdirs.ensureDir
export const ensureDirSync = _mkdirs.ensureDirSync
export const move = _move.move
export const moveSync = _move.moveSync
export const outputFile = _outputFile.outputFile
export const outputFileSync = _outputFile.outputFileSync
export const pathExists = _pathExists.pathExists
export const pathExistsSync = _pathExists.pathExistsSync
export const remove = _remove.remove
export const removeSync = _remove.removeSync

export default {
..._copy,
..._empty,
..._ensure,
..._json,
..._mkdirs,
..._move,
..._outputFile,
..._pathExists,
..._remove
}
10 changes: 7 additions & 3 deletions package.json
Expand Up @@ -51,16 +51,20 @@
"read-dir-files": "^0.1.1",
"standard": "^16.0.3"
},
"exports": "./lib/index.js",
"exports": {
".": "./lib/index.js",
"./esm": "./lib/esm.mjs"
},
"files": [
"lib/",
"!lib/**/__tests__/"
],
"scripts": {
"lint": "standard",
"test-find": "find ./lib/**/__tests__ -name *.test.js | xargs mocha",
"test": "npm run lint && npm run unit",
"unit": "nyc node test.js"
"test": "npm run lint && npm run unit && npm run unit-esm",
"unit": "nyc node test.js",
"unit-esm": "node test.mjs"
},
"sideEffects": false
}
116 changes: 116 additions & 0 deletions test.mjs
@@ -0,0 +1,116 @@
import assert from 'assert'
import fsLegacy from './lib/index.js'
// NOTE: eslint comments needed because we're importing the same file multiple times
import fsDefault from './lib/esm.mjs' // eslint-disable-line
import * as fsStar from './lib/esm.mjs'
import {
copy,
copySync,
emptyDirSync,
emptydirSync,
emptyDir,
emptydir,
createFile,
createFileSync,
ensureFile,
ensureFileSync,
createLink,
createLinkSync,
ensureLink,
ensureLinkSync,
createSymlink,
createSymlinkSync,
ensureSymlink,
ensureSymlinkSync,
readJson,
readJsonSync,
writeJson,
writeJsonSync,
outputJson,
outputJsonSync,
outputJSON,
outputJSONSync,
writeJSON,
writeJSONSync,
readJSON,
readJSONSync,
mkdirs,
mkdirsSync,
mkdirp,
mkdirpSync,
ensureDir,
ensureDirSync,
move,
moveSync,
outputFile,
outputFileSync,
pathExists,
pathExistsSync,
remove,
removeSync
} from './lib/esm.mjs' // eslint-disable-line
const fsNamed = [
copy,
copySync,
emptyDirSync,
emptydirSync,
emptyDir,
emptydir,
createFile,
createFileSync,
ensureFile,
ensureFileSync,
createLink,
createLinkSync,
ensureLink,
ensureLinkSync,
createSymlink,
createSymlinkSync,
ensureSymlink,
ensureSymlinkSync,
readJson,
readJsonSync,
writeJson,
writeJsonSync,
outputJson,
outputJsonSync,
outputJSON,
outputJSONSync,
writeJSON,
writeJSONSync,
readJSON,
readJSONSync,
mkdirs,
mkdirsSync,
mkdirp,
mkdirpSync,
ensureDir,
ensureDirSync,
move,
moveSync,
outputFile,
outputFileSync,
pathExists,
pathExistsSync,
remove,
removeSync
]

const keys = Object.keys(fsDefault)

assert.deepStrictEqual(Object.values(fsDefault), fsNamed, 'named and default exports should match')
assert.deepStrictEqual(
Object.entries(fsStar)
.filter(([name]) => name !== 'default') // remove "default" property here
.sort(([nameA], [nameB]) => keys.indexOf(nameA) - keys.indexOf(nameB)) // sort for exact match
.map(([name, fn]) => fn),
Object.values(fsDefault),
'star and default exports should match'
)

// default exports a subset of the legacy implementation, but functions are the same
Object.entries(fsDefault).forEach(([name, fn]) => {
assert.strictEqual(fn, fsLegacy[name], `${name}() should match legacy implementation`)
})

console.warn('ESM tests pass!')

0 comments on commit f4a4149

Please sign in to comment.