├── .github ├── FUNDING.yml ├── dependabot.yml ├── PULL_REQUEST_TEMPLATE.md ├── ISSUE_TEMPLATE.md └── workflows │ └── ci.yml ├── .npmignore ├── .husky ├── pre-commit └── commit-msg ├── .gitignore ├── jest.config.js ├── tsconfig.eslint.json ├── tsconfig.json ├── tsconfig.build.json ├── src └── index.ts ├── .eslintrc.js ├── LICENSE ├── tests └── index.spec.ts ├── CHANGELOG.md ├── package.json ├── CODE_OF_CONDUCT.md └── README.md /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: xobotyi 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | !/cjs 3 | !/esm 4 | !/esnext 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn lint-staged 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | package-lock.json 3 | node_modules 4 | coverage 5 | cjs 6 | esm 7 | esnext 8 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn commitlint --edit $1 5 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | coverageDirectory: './coverage', 5 | collectCoverage: false, 6 | }; 7 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: / 5 | schedule: 6 | interval: daily 7 | time: "00:00" 8 | timezone: "Etc/UTC" 9 | rebase-strategy: 'auto' 10 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": [ 4 | "./dist", 5 | "./coverage", 6 | "./node_modules" 7 | ], 8 | "include": [ 9 | ".eslintrc.js", 10 | "**/*.js", 11 | "**/*.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@xobotyi/preset-typescript/tsconfig.json", 3 | "compilerOptions": { 4 | "strict": true, 5 | "alwaysStrict": true, 6 | "module": "ESNext", 7 | "moduleResolution": "Node", 8 | "target": "ESNext", 9 | "noEmit": true, 10 | "sourceMap": false 11 | }, 12 | "include": [ 13 | "./src/**/*.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "src/index.ts" 5 | ], 6 | "compilerOptions": { 7 | "noEmit": false, 8 | "outDir": "./cjs", 9 | "declaration": true, 10 | "target": "ES5", 11 | "module": "CommonJS", 12 | "moduleResolution": "Node", 13 | "plugins": [ 14 | { 15 | "transform": "./utility/ts-transformer-js-ext.ts", 16 | "after": true 17 | } 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Before submitting a pull request,** please make sure the following is done: 2 | 3 | 1. Fork [the repository](https://github.com/xobotyi/await-of.git) and create your branch from `master`. 4 | 2. Run `npm i` in the repository root. 5 | 3. If you've fixed a bug or added code that should be tested, add tests! 6 | 4. Ensure the test suite passes (`npm run test`). 7 | 5. Format your code with [prettier](https://github.com/prettier/prettier) (`npm run format`). 8 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | type AwaitOfReturnType = Readonly<[T | undefined, Error?]>; 2 | 3 | export function of( 4 | promise: Promise 5 | ): Promise> { 6 | return Promise.resolve(promise) 7 | .then((result): Readonly<[T]> => [result]) 8 | .catch((err): Readonly<[undefined, Error]> => { 9 | if (typeof err === 'undefined') { 10 | err = new Error('Rejection with empty value'); 11 | } 12 | 13 | return [undefined, err]; 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['@xobotyi/eslint-config/base', '@xobotyi/eslint-config/typescript'], 4 | parserOptions: { 5 | project: './tsconfig.eslint.json', 6 | tsconfigRootDir: __dirname, 7 | }, 8 | rules: { 9 | 'prefer-rest-params': 'off', 10 | 'no-restricted-syntax': ['error', 'FunctionExpression', 'WithStatement'], 11 | 'no-param-reassign': 'off', 12 | }, 13 | overrides: [ 14 | { 15 | files: ['./benchmark/**/*'], 16 | rules: { 17 | 'no-console': 'off', 18 | }, 19 | }, 20 | ], 21 | }; 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Do you want to request a _feature_ or report a _bug_?** 2 | 3 | **What is the current behavior?** 4 | 5 | **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have extra dependencies other than await-of. Paste the link to your [JSFiddle](https://jsfiddle.net) or [CodeSandbox](https://codesandbox.io) example below:** 6 | 7 | **What is the expected behavior?** 8 | 9 | **Which versions of await-of, and which browser / OS / node version are affected by this issue? Did this work in previous versions of await-of?** 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Anton Zinovyev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { of } from '../src'; 2 | 3 | describe('await-of', () => { 4 | it('should return resolve result as first array`s item', async () => { 5 | const [res, err] = await of(Promise.resolve('Hello world!')); 6 | 7 | expect(err).toBeUndefined(); 8 | expect(res).toBe('Hello world!'); 9 | }); 10 | 11 | it('should return rejection result as second array`s item', async () => { 12 | // eslint-disable-next-line prefer-promise-reject-errors 13 | const [res, err] = await of(Promise.reject('Hello world!')); 14 | 15 | expect(res).toBeUndefined(); 16 | expect(err).toBe('Hello world!'); 17 | }); 18 | 19 | it('should return unhandled error as second array`s item', async () => { 20 | const [res, err] = await of( 21 | new Promise(() => { 22 | throw new Error('Unhandled error!'); 23 | }) 24 | ); 25 | 26 | expect(res).toBeUndefined(); 27 | expect(err).toBeInstanceOf(Error); 28 | expect(err?.message).toBe('Unhandled error!'); 29 | }); 30 | 31 | it('should handle empty/null value rejection', async () => { 32 | const [res, err] = await of(Promise.reject()); 33 | 34 | expect(res).toBeUndefined(); 35 | expect(err).toBeInstanceOf(Error); 36 | expect(err?.message).toBe('Rejection with empty value'); 37 | }); 38 | 39 | it('should handle empty/null value rejection', async () => { 40 | const [res, err] = await of(Promise.reject()); 41 | 42 | expect(res).toBeUndefined(); 43 | expect(err).toBeInstanceOf(Error); 44 | expect(err?.message).toBe('Rejection with empty value'); 45 | }); 46 | 47 | it('should not throw on non-thenables', async () => { 48 | // @ts-expect-error testing inappropriate use 49 | const [data, err] = await of('Hello world!'); 50 | 51 | expect(err).toBeUndefined(); 52 | expect(data).toEqual('Hello world!'); 53 | }); 54 | 55 | it('should not throw on nulls', async () => { 56 | // @ts-expect-error testing inappropriate use 57 | const [data, err] = await of(null); 58 | 59 | expect(err).toBeUndefined(); 60 | expect(data).toBeNull(); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [3.1.1](https://github.com/xobotyi/await-of/compare/v3.1.0...v3.1.1) (2021-07-21) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * update README.md and gha config ([98d78e2](https://github.com/xobotyi/await-of/commit/98d78e265f0836128450f54c363217efc575d36a)) 7 | 8 | # [3.1.0](https://github.com/xobotyi/await-of/compare/v3.0.0...v3.1.0) (2020-05-21) 9 | 10 | 11 | ### Features 12 | 13 | * add patreon funding link ([747d970](https://github.com/xobotyi/await-of/commit/747d970004e66be588a335d85db982c000194a03)) 14 | 15 | # [3.0.0](https://github.com/xobotyi/await-of/compare/v2.1.0...v3.0.0) (2020-03-18) 16 | 17 | 18 | ### chore 19 | 20 | * re-create yarn.lock file; ([017dda0](https://github.com/xobotyi/await-of/commit/017dda006868b5b020387246f158a14deb7a954a)) 21 | 22 | 23 | ### BREAKING CHANGES 24 | 25 | * the function now name exported! 26 | 27 | # [2.1.0](https://github.com/xobotyi/await-of/compare/v2.0.0...v2.1.0) (2020-03-04) 28 | 29 | 30 | ### Features 31 | 32 | * update readme badges and header; ([8fca26b](https://github.com/xobotyi/await-of/commit/8fca26bc528c32138b26f674ba0ace7f74556250)) 33 | 34 | # [2.0.0](https://github.com/xobotyi/await-of/compare/v1.3.1...v2.0.0) (2020-03-04) 35 | 36 | 37 | ### Bug Fixes 38 | 39 | * fix build; ([9ec99fa](https://github.com/xobotyi/await-of/commit/9ec99fa505dbd65d0a91b9186f26d716d067eb52)) 40 | * fix throw error in readme example; ([2eedd47](https://github.com/xobotyi/await-of/commit/2eedd4753043aea78bdebcf9f66edb8e590e33c3)) 41 | 42 | 43 | ### Features 44 | 45 | * rework the module. ([bf947c3](https://github.com/xobotyi/await-of/commit/bf947c38485fa0a3e773cfeda1515bd535cef2a5)), closes [#9](https://github.com/xobotyi/await-of/issues/9) [#15](https://github.com/xobotyi/await-of/issues/15) 46 | * specify minimal node version as requested in [#7](https://github.com/xobotyi/await-of/issues/7) ([56e8fab](https://github.com/xobotyi/await-of/commit/56e8fab3cb0b30aef9fe1d41ac58e65a705c7c88)) 47 | 48 | 49 | ### BREAKING CHANGES 50 | 51 | * now module has default export only. 52 | 53 | ## [1.3.1](https://github.com/xobotyi/await-of/compare/v1.3.0...v1.3.1) (2020-03-04) 54 | 55 | 56 | ### Bug Fixes 57 | 58 | * move code coverage push to separate job. ([1b24503](https://github.com/xobotyi/await-of/commit/1b24503810e0b65bcc70d397c7be0bbff4a00793)) 59 | * move semantic release to separate job; ([d11d674](https://github.com/xobotyi/await-of/commit/d11d674879de88952e3ceda28a91d14b74c50d66)) 60 | 61 | # [1.3.0](https://github.com/xobotyi/await-of/compare/v1.2.0...v1.3.0) (2020-03-04) 62 | 63 | 64 | ### Features 65 | 66 | * versions now managed by semantic release; ([0c2f516](https://github.com/xobotyi/await-of/commit/0c2f516fd69eff9d592e0143e10b191b7dc5b6a3)) 67 | 68 | # CHANGELOG 69 | 70 | ### v1.2 71 | 72 | - Lib is now written in TypeScript; 73 | - Added ESM build; 74 | - Now in case of empty value rejection (`undefined` or `null`) actual rejection result returned as 1st parameter and pure `Error` instance as second. 75 | No more `originalValue` prop on error instance; 76 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "await-of", 3 | "description": "await wrapper for easier errors handling without try-catch", 4 | "version": "3.1.1", 5 | "files": [ 6 | "cjs", 7 | "esm", 8 | "esnext" 9 | ], 10 | "main": "cjs/index.js", 11 | "module": "esm/index.js", 12 | "esnext": "esnext/index.js", 13 | "types": "cjs/index.d.ts", 14 | "sideEffects": false, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/xobotyi/await-of.git" 18 | }, 19 | "bugs": { 20 | "url": "https://github.com/xobotyi/await-of/issues" 21 | }, 22 | "funding": { 23 | "type": "patreon", 24 | "url": "https://www.patreon.com/xobotyi" 25 | }, 26 | "homepage": "https://github.com/xobotyi/await-of", 27 | "author": { 28 | "name": "Anton Zinovyev", 29 | "url": "https://github.com/xobotyi", 30 | "email": "xog3@yandex.ru" 31 | }, 32 | "license": "MIT", 33 | "keywords": [ 34 | "async", 35 | "await", 36 | "errors handling", 37 | "promise", 38 | "wrapper", 39 | "node", 40 | "browser" 41 | ], 42 | "devDependencies": { 43 | "@commitlint/config-conventional": "^16.0.0", 44 | "@jamesacarr/eslint-formatter-github-actions": "^0.1.0", 45 | "@jamesacarr/jest-reporter-github-actions": "^0.0.4", 46 | "@semantic-release/changelog": "^6.0.0", 47 | "@semantic-release/git": "^10.0.0", 48 | "@semantic-release/github": "^8.0.0", 49 | "@types/jest": "^27.0.0", 50 | "@xobotyi/eslint-config": "^2.2.0", 51 | "@xobotyi/preset-typescript": "^1.0.0", 52 | "commitlint": "^16.0.0", 53 | "concurrently": "^6.2.0", 54 | "eslint": "^7.31.0", 55 | "husky": "^7.0.1", 56 | "jest": "^27.0.6", 57 | "lint-staged": "^11.0.1", 58 | "rimraf": "^3.0.2", 59 | "semantic-release": "^18.0.0", 60 | "ts-jest": "^27.0.3", 61 | "ts-node": "^10.1.0", 62 | "typescript": "^4.3.5", 63 | "yarn": "^1.22.10" 64 | }, 65 | "engines": { 66 | "node": ">=7.6.0" 67 | }, 68 | "scripts": { 69 | "prepare": "husky install", 70 | "build": "yarn build:cleanup && concurrently yarn:build:cjs yarn:build:esm yarn:build:esnext --kill-others-on-fail", 71 | "build:cleanup": "rimraf ./cjs ./esm ./esnext ./types", 72 | "build:cjs": "tsc -p ./tsconfig.build.json --module CommonJS --target ES5 --outDir ./cjs", 73 | "build:esm": "tsc -p ./tsconfig.build.json --module ES6 --target ES5 --outDir ./esm", 74 | "build:esnext": "tsc -p ./tsconfig.build.json --module ESNext --target ESNext --outDir ./esnext", 75 | "lint": "eslint ./{src,tests}/**/*.ts ./*.{ts,js}", 76 | "lint:fix": "yarn lint --fix", 77 | "test": "jest --coverage=false", 78 | "test:coverage": "jest --coverage" 79 | }, 80 | "lint-staged": { 81 | "*.{js,ts}": "eslint --fix" 82 | }, 83 | "commitlint": { 84 | "extends": [ 85 | "@commitlint/config-conventional" 86 | ] 87 | }, 88 | "release": { 89 | "plugins": [ 90 | "@semantic-release/commit-analyzer", 91 | "@semantic-release/release-notes-generator", 92 | "@semantic-release/changelog", 93 | "@semantic-release/npm", 94 | "@semantic-release/git", 95 | "@semantic-release/github" 96 | ] 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # await-of 4 | 5 | await wrapper for easier errors handling without try-catch 6 | 7 | [![NPM Version](https://flat.badgen.net/npm/v/await-of)](https://www.npmjs.com/package/await-of) 8 | [![NPM Downloads](https://flat.badgen.net/npm/dm/await-of)](https://www.npmjs.com/package/await-of) 9 | [![NPM Dependents](https://flat.badgen.net/npm/dependents/await-of)](https://www.npmjs.com/package/await-of) 10 | [![Build](https://img.shields.io/github/workflow/status/xobotyi/await-of/CI?style=flat-square)](https://github.com/xobotyi/await-of/actions) 11 | [![Coverage](https://flat.badgen.net/codecov/c/github/xobotyi/await-of)](https://app.codecov.io/gh/xobotyi/await-of) 12 | [![Types](https://flat.badgen.net/npm/types/await-of)](https://www.npmjs.com/package/await-of) 13 | [![Tree Shaking](https://flat.badgen.net/bundlephobia/tree-shaking/await-of)](https://bundlephobia.com/result?p=await-of) 14 | 15 |
16 | 17 | --- 18 | 19 |
❤️Please consider starring this project to show your love and support.🙌
20 | 21 | --- 22 | 23 | 24 | ## About 25 | 26 | ES7 `async/await` gives to developers ability to write asynchronous code that look like synchronous. But under the hood it is still just a sugar on top of the ES6 `Promise`. 27 | You can write code that looks clean, but only unless you have to catch errors. To catch thrown error or handle the promise's rejection you have to surround it with `try-catch` block or fallback to pure promises and from that moment visual purity of your code is over. 28 | But there is a solution!☀️ 29 | I really like the way it's done in **Go**. It has no error throwing mechanism, but has a multi-value return and the common way to handle errors in Go is to return error as a last value, like so: 30 | 31 | ```go 32 | data, err := someErrorFunc(someStuff) 33 | if err != nil { 34 | return err 35 | } 36 | ``` 37 | 38 | _But JavaScript has no multi-value return!_ - you would say. Sad, but true. 39 | But! 40 | It has a destructuring assignment and `await-of` gives you ability to do this: 41 | 42 | ```javascript 43 | import { of } from "await-of"; 44 | 45 | async () => { 46 | let [res, err] = await of(axios.get("some.uri/to/get")); 47 | 48 | if (err) { 49 | // rethrow if its not an axios response error 50 | if (!err.response) { 51 | throw err; 52 | } 53 | 54 | res = err.response; 55 | } 56 | 57 | const { data, status = 0 } = res; 58 | 59 | console.log(data, status); 60 | }; 61 | ``` 62 | 63 | There is no modifications needed in function/promise you want to await - just pass it to the `of()` and whole the magic will be done. 64 | 65 | ## Installation 66 | 67 | ```bash 68 | npm i --save await-of 69 | ``` 70 | 71 | ## Usage 72 | 73 | ```javascript 74 | import { of } from "await-of"; 75 | 76 | async function someAsyncStuff() { 77 | let error, data; 78 | 79 | // if we don't want to handle error 80 | [data] = await of(Promise.reject(new Error("ERROR!"))); 81 | console.log(data); // undefined 82 | 83 | // if promise was rejected - it's rejection value will be treated as error 84 | [, error] = await of(Promise.reject(new Error("ERROR!"))); 85 | console.log(error); // ERROR! 86 | 87 | // or if promise has any uncaught errors it'll catch them too! 88 | [, error] = await of( 89 | new Promise(() => { 90 | throw new TypeError("ERROR!"); 91 | }) 92 | ); 93 | console.log(error.message); // ERROR! 94 | } 95 | ``` 96 | 97 | ## Tests 98 | 99 | ```bash 100 | # install dependencies if you haven't yet 101 | npm install 102 | npm run test 103 | ``` 104 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: "CI" 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | workflow_dispatch: 11 | 12 | jobs: 13 | lint: 14 | name: "Lint" 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: "Checkout" 18 | uses: actions/checkout@v2.3.4 19 | with: 20 | fetch-depth: 0 21 | 22 | - uses: c-hive/gha-yarn-cache@v2 23 | 24 | - name: "Setup Node.js" 25 | uses: actions/setup-node@v2.3.0 26 | with: 27 | node-version: 15 28 | 29 | - name: "Install dependencies" 30 | run: yarn install --frozen-lockfile 31 | 32 | - name: "Lint" 33 | run: yarn lint -f @jamesacarr/github-actions 34 | 35 | build: 36 | name: "Build" 37 | runs-on: ubuntu-latest 38 | steps: 39 | - name: "Checkout" 40 | uses: actions/checkout@v2.3.4 41 | with: 42 | fetch-depth: 0 43 | 44 | - uses: c-hive/gha-yarn-cache@v2 45 | 46 | - name: "Setup Node.js" 47 | uses: actions/setup-node@v2.3.0 48 | with: 49 | node-version: 15 50 | 51 | - name: "Install dependencies" 52 | run: yarn install --frozen-lockfile 53 | 54 | - name: "Build" 55 | run: yarn build 56 | 57 | test: 58 | name: "Test" 59 | runs-on: ubuntu-latest 60 | steps: 61 | - name: "Checkout" 62 | uses: actions/checkout@v2.3.4 63 | with: 64 | fetch-depth: 0 65 | 66 | - uses: c-hive/gha-yarn-cache@v2 67 | 68 | - name: "Setup Node.js" 69 | uses: actions/setup-node@v2.3.0 70 | with: 71 | node-version: 15 72 | 73 | - name: "Install dependencies" 74 | run: yarn install --frozen-lockfile 75 | 76 | - name: "Test" 77 | run: yarn test:coverage --testLocationInResults --reporters=default --reporters=@jamesacarr/jest-reporter-github-actions 78 | 79 | - name: "Upload coverage to Codecov" 80 | uses: codecov/codecov-action@v2.0.1 81 | with: 82 | token: ${{ secrets.CODECOV_TOKEN }} 83 | files: coverage/lcov.info 84 | fail_ci_if_error: true 85 | 86 | dependabot-merge: 87 | name: "Dependabot automerge" 88 | runs-on: ubuntu-latest 89 | needs: [ "test", "build", "lint" ] 90 | if: github.actor == 'dependabot[bot]' && github.event_name == 'pull_request' 91 | steps: 92 | - uses: fastify/github-action-merge-dependabot@v2.2.0 93 | with: 94 | github-token: ${{ secrets.GITHUB_TOKEN }} 95 | 96 | semantic-release: 97 | name: "Release" 98 | runs-on: ubuntu-latest 99 | needs: [ "test", "build", "lint" ] 100 | if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' 101 | outputs: 102 | new-release-published: ${{ steps.release.outputs.new-release-published }} 103 | steps: 104 | - name: "Checkout" 105 | uses: actions/checkout@v2.3.4 106 | with: 107 | ref: "master" 108 | 109 | - uses: c-hive/gha-yarn-cache@v2 110 | 111 | - name: "Setup Node.js" 112 | uses: actions/setup-node@v2.3.0 113 | with: 114 | node-version: 15 115 | 116 | - name: "Install dependencies" 117 | run: yarn install --frozen-lockfile 118 | 119 | - name: "Build package" 120 | run: yarn build 121 | 122 | - name: "Release" 123 | id: "release" 124 | uses: codfish/semantic-release-action@v1.9.0 125 | env: 126 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 127 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 128 | --------------------------------------------------------------------------------