Skip to content

Commit

Permalink
Merge branch 'development' into setup-node-caching
Browse files Browse the repository at this point in the history
  • Loading branch information
xjamundx committed Dec 18, 2021
2 parents f57fd3c + 5641001 commit a90c42e
Show file tree
Hide file tree
Showing 23 changed files with 1,354 additions and 11,424 deletions.
11 changes: 11 additions & 0 deletions .github/dependabot.yml
@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: daily

- package-ecosystem: npm
directory: /
schedule:
interval: daily
10 changes: 6 additions & 4 deletions .github/workflows/CI.yml
Expand Up @@ -6,13 +6,12 @@ jobs:
main:
strategy:
matrix:
node: [10.12, 10, 12.0, 12, 14, 15]
eslint: [7]
node: [10.12, 10, 12.0, 12, 14, 16]
runs-on: ubuntu-latest
steps:
- name: 🛑 Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.8.0
with:
access_token: ${{ secrets.GITHUB_TOKEN }}
uses: styfle/cancel-workflow-action@0.9.1

- name: ⬇️ Checkout repo
uses: actions/checkout@v2
Expand All @@ -26,5 +25,8 @@ jobs:
- name: 📥 Download deps
run: npm ci

- name: 📥 Install ESLint v${{ matrix.eslint }}
run: npm install eslint@${{ matrix.eslint }}

- name: ▶️ Run test script
run: npm run test -- --runInBand
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
node_modules
.idea
coverage/
.eslintcache
1 change: 1 addition & 0 deletions .husky/.gitignore
@@ -0,0 +1 @@
_
4 changes: 4 additions & 0 deletions .husky/pre-commit
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged
1 change: 1 addition & 0 deletions .prettierignore
@@ -0,0 +1 @@
coverage
14 changes: 7 additions & 7 deletions LICENSE.md
@@ -1,13 +1,13 @@
Copyright (c) 2020, Jamund Ferguson

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -90,7 +90,7 @@ or start with the recommended rule set:
| [`no-new-statics`][no-new-statics] | Avoid calling `new` on a Promise static method | :bangbang: | :wrench: |
| [`no-return-in-finally`][no-return-in-finally] | Disallow return statements in `finally()` | :warning: | |
| [`valid-params`][valid-params] | Ensures the proper number of arguments are passed to Promise functions | :warning: | |
| [`prefer-await-to-then`][prefer-await-to-then] | Prefer `await` to `then()`/`catch()`/`finally()` for reading Promise values | :seven: | |
| [`prefer-await-to-then`][prefer-await-to-then] | Prefer `await` to `then()`/`catch()`/`finally()` for reading Promise values | :seven: | |
| [`prefer-await-to-callbacks`][prefer-await-to-callbacks] | Prefer async/await to the callback pattern | :seven: | |

**Key**
Expand Down
3 changes: 1 addition & 2 deletions __tests__/always-return.js
Expand Up @@ -82,8 +82,7 @@ ruleTester.run('always-return', rule, {
errors: [{ message }],
},
{
code:
'hey.then(function() { if (x) { return you.then(function() { return x; }); } })',
code: 'hey.then(function() { if (x) { return you.then(function() { return x; }); } })',
errors: [{ message }],
},
{
Expand Down
18 changes: 6 additions & 12 deletions __tests__/catch-or-return.js
Expand Up @@ -20,8 +20,7 @@ ruleTester.run('catch-or-return', rule, {

// arrow function use case
{
code:
'postJSON("/smajobber/api/reportJob.json")\n\t.then(()=>this.setState())\n\t.catch(()=>this.setState())',
code: 'postJSON("/smajobber/api/reportJob.json")\n\t.then(()=>this.setState())\n\t.catch(()=>this.setState())',
parserOptions: { ecmaVersion: 6 },
},

Expand All @@ -41,8 +40,7 @@ ruleTester.run('catch-or-return', rule, {
options: [{ allowThen: true }],
},
{
code:
'frank().then(go).then().then(null, function() { /* why bother */ })',
code: 'frank().then(go).then().then(null, function() { /* why bother */ })',
options: [{ allowThen: true }],
},
{
Expand All @@ -65,8 +63,7 @@ ruleTester.run('catch-or-return', rule, {
options: [{ allowThen: true }],
},
{
code:
'frank().then(a).then(b).then(null, function() { /* why bother */ })',
code: 'frank().then(a).then(b).then(null, function() { /* why bother */ })',
options: [{ allowThen: true }],
},

Expand All @@ -80,8 +77,7 @@ ruleTester.run('catch-or-return', rule, {
options: [{ allowThen: true }],
},
{
code:
'frank().then(go).then().then(function() {}, function() { /* why bother */ })',
code: 'frank().then(go).then().then(function() {}, function() { /* why bother */ })',
options: [{ allowThen: true }],
},
{
Expand All @@ -99,8 +95,7 @@ ruleTester.run('catch-or-return', rule, {
options: [{ allowFinally: true }],
},
{
code:
'frank().then(go).then().catch(function() { /* why bother */ }).finally(fn)',
code: 'frank().then(go).then().catch(function() { /* why bother */ }).finally(fn)',
options: [{ allowFinally: true }],
},

Expand Down Expand Up @@ -167,8 +162,7 @@ ruleTester.run('catch-or-return', rule, {
errors: [{ message: catchMessage }],
},
{
code:
'frank().then(go).then().catch(function() { /* why bother */ }).finally(fn)',
code: 'frank().then(go).then().catch(function() { /* why bother */ }).finally(fn)',
errors: [{ message: catchMessage }],
},

Expand Down
3 changes: 1 addition & 2 deletions __tests__/no-callback-in-promise.js
Expand Up @@ -75,8 +75,7 @@ ruleTester.run('no-callback-in-promise', rule, {
errors: [{ message: errorMessage, column: 24 }],
},
{
code:
'a.then(function(data) { callback(data) }, function(err) { callback(err) })',
code: 'a.then(function(data) { callback(data) }, function(err) { callback(err) })',
errors: [
{ message: errorMessage },
{ column: 59, message: errorMessage },
Expand Down
18 changes: 6 additions & 12 deletions __tests__/no-return-wrap.js
Expand Up @@ -101,25 +101,21 @@ ruleTester.run('no-return-wrap', rule, {

// needs to also look at weird paths
{
code:
'doThing().then(function(x) { if (x>1) { return Promise.resolve(4) } else { throw "bad" } })',
code: 'doThing().then(function(x) { if (x>1) { return Promise.resolve(4) } else { throw "bad" } })',
errors: [{ message: resolveMessage }],
},
{
code:
'doThing().then(function(x) { if (x>1) { return Promise.reject(4) } })',
code: 'doThing().then(function(x) { if (x>1) { return Promise.reject(4) } })',
errors: [{ message: rejectMessage }],
},
{
code:
'doThing().then(null, function() { if (true && false) { return Promise.resolve() } })',
code: 'doThing().then(null, function() { if (true && false) { return Promise.resolve() } })',
errors: [{ message: resolveMessage }],
},

// should do both
{
code:
'doThing().catch(function(x) {if (x) { return Promise.resolve(4) } else { return Promise.reject() } })',
code: 'doThing().catch(function(x) {if (x) { return Promise.resolve(4) } else { return Promise.reject() } })',
errors: [{ message: resolveMessage }, { message: rejectMessage }],
},

Expand Down Expand Up @@ -201,13 +197,11 @@ ruleTester.run('no-return-wrap', rule, {

// function bind
{
code:
'doThing().then((function() { return Promise.resolve(4) }).bind(this))',
code: 'doThing().then((function() { return Promise.resolve(4) }).bind(this))',
errors: [{ message: resolveMessage }],
},
{
code:
'doThing().then((function() { return Promise.resolve(4) }).bind(this).bind(this))',
code: 'doThing().then((function() { return Promise.resolve(4) }).bind(this).bind(this))',
errors: [{ message: resolveMessage }],
},

Expand Down
3 changes: 1 addition & 2 deletions __tests__/prefer-await-to-then.js
Expand Up @@ -37,8 +37,7 @@ ruleTester.run('prefer-await-to-then', rule, {
errors: [{ message }, { message }, { message }],
},
{
code:
'async function a() { hey.then(function() { }).then(function() { }) }',
code: 'async function a() { hey.then(function() { }).then(function() { }) }',
errors: [{ message }, { message }],
},
{
Expand Down
4 changes: 2 additions & 2 deletions docs/rules/always-return.md
Expand Up @@ -19,11 +19,11 @@ myPromise.then((b) => { if (b) { return "yes" } else { return "no" } });
#### Invalid

```js
myPromise.then(function(val) {})
myPromise.then(function (val) {})
myPromise.then(() => {
doSomething()
})
myPromise.then(b => {
myPromise.then((b) => {
if (b) {
return 'yes'
} else {
Expand Down
5 changes: 1 addition & 4 deletions docs/rules/catch-or-return.md
Expand Up @@ -7,10 +7,7 @@ as well. Exceptions are made if you are returning that promise.

```js
myPromise.then(doSomething).catch(errors)
myPromise
.then(doSomething)
.then(doSomethingElse)
.catch(errors)
myPromise.then(doSomething).then(doSomethingElse).catch(errors)
function doSomethingElse() {
return myPromise.then(doSomething)
}
Expand Down
47 changes: 30 additions & 17 deletions docs/rules/no-callback-in-promise.md
@@ -1,19 +1,22 @@
# Avoid calling `cb()` inside of a `then()` or `catch()` (no-callback-in-promise)

As a general rule, callbacks should never be directly invoked inside a [Promise.prototype.then()] or [Promise.prototype.catch()] method. That's because your callback may be unintentionally be invoked twice. It also can be confusing to mix paradigms.
As a general rule, callbacks should never be directly invoked inside a
[Promise.prototype.then()] or [Promise.prototype.catch()] method. That's because
your callback may be unintentionally be invoked twice. It also can be confusing
to mix paradigms.

Take the following example:

```js
function callback(err, data) {
console.log("Callback got called with:", err, data);
throw new Error("My error");
console.log('Callback got called with:', err, data)
throw new Error('My error')
}

// note: passing `err.message` for demo purposes, normally you would pass `err`
Promise.resolve()
.then(() => callback(null, "data"))
.catch(err => callback(err.message, null));
.then(() => callback(null, 'data'))
.catch((err) => callback(err.message, null))
```

If you run this example, your output will look like the following:
Expand All @@ -25,20 +28,22 @@ Callback got called with: My error null

**How to fix it?**

Ensure that your callback invocations are wrapped by a deferred execution function such as:
Ensure that your callback invocations are wrapped by a deferred execution
function such as:

- [setImmediate()] or [process.nextTick()]: for Node.js.
- [setTimeout()]: for Browsers and Node.js.

```js
// node.js
Promise.resolve()
.then(() => setImmediate(() => callback(null, "data")))
.catch(err => setImmediate(() => callback(err.message, null)));
.then(() => setImmediate(() => callback(null, 'data')))
.catch((err) => setImmediate(() => callback(err.message, null)))

// node.js and browsers
Promise.resolve()
.then(() => setTimeout(() => callback(null, "data"), 0))
.catch(err => setTimeout(() => callback(err.message, null), 0));
.then(() => setTimeout(() => callback(null, 'data'), 0))
.catch((err) => setTimeout(() => callback(err.message, null), 0))
```

Your output will now look like the following:
Expand All @@ -47,11 +52,19 @@ Your output will now look like the following:
Callback got called with: null data
```

Finally, if your callbacks have a Node.js signature (i.e. `callback(err, data)`), consider using [util.promsify] for promisifying your callback code instead of combining the approaches.
Finally, if your callbacks have a Node.js signature (i.e.
`callback(err, data)`), consider using [util.promsify] for promisifying your
callback code instead of combining the approaches.

[util.promisify]: https://nodejs.org/dist/latest/docs/api/util.html#utilpromisifyoriginal
[Promise.prototype.then()]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
[Promise.prototype.catch()]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch
[setImmediate()]: https://nodejs.org/docs/latest-v14.x/api/timers.html#timers_setimmediate_callback_args
[process.nextTick()]: https://nodejs.org/docs/latest-v14.x/api/process.html#process_process_nexttick_callback_args
[setTimeout()]: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
[util.promisify]:
https://nodejs.org/dist/latest/docs/api/util.html#utilpromisifyoriginal
[promise.prototype.then()]:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
[promise.prototype.catch()]:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch
[setimmediate()]:
https://nodejs.org/docs/latest-v14.x/api/timers.html#timers_setimmediate_callback_args
[process.nexttick()]:
https://nodejs.org/docs/latest-v14.x/api/process.html#process_process_nexttick_callback_args
[settimeout()]:
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
21 changes: 5 additions & 16 deletions docs/rules/no-nesting.md
Expand Up @@ -3,28 +3,17 @@
#### Valid

```js
myPromise
.then(doSomething)
.then(doSomethingElse)
.catch(errors)
myPromise.then(doSomething).then(doSomethingElse).catch(errors)
```

#### Invalid

```js
myPromise.then(val =>
doSomething(val).then(doSomethingElse)
)
myPromise.then((val) => doSomething(val).then(doSomethingElse))

myPromise.then(val =>
doSomething(val).catch(errors)
)
myPromise.then((val) => doSomething(val).catch(errors))

myPromise.catch(err =>
doSomething(err).then(doSomethingElse)
)
myPromise.catch((err) => doSomething(err).then(doSomethingElse))

myPromise.catch(err =>
doSomething(err).catch(errors)
)
myPromise.catch((err) => doSomething(err).catch(errors))
```
4 changes: 2 additions & 2 deletions docs/rules/no-return-in-finally.md
Expand Up @@ -6,15 +6,15 @@ nothing would consume what's returned.
#### Valid

```js
myPromise.finally(function(val) {
myPromise.finally(function (val) {
console.log('value:', val)
})
```

#### Invalid

```js
myPromise.finally(function(val) {
myPromise.finally(function (val) {
return val
})
```

0 comments on commit a90c42e

Please sign in to comment.