Repository: jprichardson/node-fs-extra (js)

Issue:
ExperimentalWarning: The fs.promises API is experimental (Node.js 10.1.0)
<!-- Please fill out the following information if it applies to your issue: -->
- **Operating System:** MacOS 10.13.4
- **Node.js version:** 10.1.0
- **`fs-extra` version:** 5.0.0

Hello! First of all, thank you for the great work on maintaining fs-extra 🙇 

With Node.js 10.1.0 recently released, we started to see the following warning in our test suite:

```
(node:7885) ExperimentalWarning: The fs.promises API is experimental
```

It turns out the `fs` module provides a new property `promises` which triggers the warning on the first access.

You can try it out yourself:

```
$ node -v
v10.1.0
$ node -e "console.log(typeof fs.promises)"
object
(node:8277) ExperimentalWarning: The fs.promises API is experimental
```

On Node.js version 10.0.0:

```
$ node -e "console.log(typeof fs.promises)"
undefined
```

Can we fix [lib/fs/index.js](https://github.com/jprichardson/node-fs-extra/blob/7d36349abe257c15ac1b216a374de697161ba5f3/lib/fs/index.js) to not emit ExperimentalWarning until the experimental API is actually accessed?

Pull request description:
Fix fs.promises ExperimentalWarning on Node 10.1.0
Fixes #577

When fs-extra is loaded on Node.js 10.1.0, an experimental warning is printed:

```
(node:7885) ExperimentalWarning: The fs.promises API is experimental
```

This pull request fixes the problem by defining `fs.promises` as a getter property.

@RyanZim @jprichardson  could you please take a look?

Patch:
diff --git a/lib/fs/index.js b/lib/fs/index.js
index 2ca50a6..d99f768 100644
--- a/lib/fs/index.js
+++ b/lib/fs/index.js
@@ -46,6 +46,11 @@ const api = [
 
 // Export all keys:
 Object.keys(fs).forEach(key => {
+  if (key === 'promises') {
+    // fs.promises is a getter property that triggers ExperimentalWarning
+    // Don't re-export it here, the getter is defined in "lib/index.js"
+    return
+  }
   exports[key] = fs[key]
 })
 
diff --git a/lib/index.js b/lib/index.js
index 5f4222d..40e37b1 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -17,3 +17,12 @@ module.exports = Object.assign(
   require('./path-exists'),
   require('./remove')
 )
+
+// Export fs.promises as a getter property so that we don't trigger
+// ExperimentalWarning before fs.promises is actually accessed.
+const fs = require('fs')
+if (Object.getOwnPropertyDescriptor(fs, 'promises')) {
+  Object.defineProperty(module.exports, 'promises', {
+    get () { return fs.promises }
+  })
+}


Test patch:
diff --git a/lib/__tests__/promise.test.js b/lib/__tests__/promise.test.js
index 724dbad..eb6ad33 100644
--- a/lib/__tests__/promise.test.js
+++ b/lib/__tests__/promise.test.js
@@ -2,6 +2,8 @@
 
 /* eslint-env mocha */
 
+const assert = require('assert')
+const fs = require('fs')
 const fse = require('..')
 
 const methods = [
@@ -22,4 +24,12 @@ describe('promise support', () => {
       fse[method]().catch(() => done())
     })
   })
+
+  if (Object.getOwnPropertyDescriptor(fs, 'promises')) {
+    it('provides fse.promises API', () => {
+      const desc = Object.getOwnPropertyDescriptor(fse, 'promises')
+      assert.ok(desc)
+      assert.equal(typeof desc.get, 'function')
+    })
+  }
 })