(promise);
19 |
20 | expect(err).toEqual('Error');
21 | expect(data).toBeUndefined();
22 | });
23 |
24 | it('should add external properties to the error object', async () => {
25 | const promise = Promise.reject({ error: 'Error message' });
26 |
27 | const [err] = await to<
28 | string,
29 | { error: string; extraKey: number }
30 | >(promise, {
31 | extraKey: 1
32 | });
33 |
34 | expect(err).toBeTruthy();
35 | expect((err as any).extraKey).toEqual(1);
36 | expect((err as any).error).toEqual('Error message')
37 | });
38 |
39 | it('should receive the type of the parent if no type was passed', async () => {
40 | let user: { name: string };
41 | let err: Error;
42 |
43 | [err, user] = await to(Promise.resolve({ name: '123' }));
44 |
45 | expect(user.name).toEqual('123');
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/tools/semantic-release-prepare.ts:
--------------------------------------------------------------------------------
1 | const path = require("path")
2 | const { fork } = require("child_process")
3 | const colors = require("colors")
4 |
5 | const { readFileSync, writeFileSync } = require("fs")
6 | const pkg = JSON.parse(
7 | readFileSync(path.resolve(__dirname, "..", "package.json"))
8 | )
9 |
10 | pkg.scripts.prepush = "npm run test:prod && npm run build"
11 | pkg.scripts.commitmsg = "validate-commit-msg"
12 |
13 | writeFileSync(
14 | path.resolve(__dirname, "..", "package.json"),
15 | JSON.stringify(pkg, null, 2)
16 | )
17 |
18 | // Call husky to set up the hooks
19 | fork(path.resolve(__dirname, "..", "node_modules", "husky", "bin", "install"))
20 |
21 | console.log()
22 | console.log(colors.green("Done!!"))
23 | console.log()
24 |
25 | if (pkg.repository.url.trim()) {
26 | console.log(colors.cyan("Now run:"))
27 | console.log(colors.cyan(" npm install -g semantic-release-cli"))
28 | console.log(colors.cyan(" semantic-release setup"))
29 | console.log()
30 | console.log(
31 | colors.cyan('Important! Answer NO to "Generate travis.yml" question')
32 | )
33 | console.log()
34 | console.log(
35 | colors.gray(
36 | 'Note: Make sure "repository.url" in your package.json is correct before'
37 | )
38 | )
39 | } else {
40 | console.log(
41 | colors.red(
42 | 'First you need to set the "repository.url" property in package.json'
43 | )
44 | )
45 | console.log(colors.cyan("Then run:"))
46 | console.log(colors.cyan(" npm install -g semantic-release-cli"))
47 | console.log(colors.cyan(" semantic-release setup"))
48 | console.log()
49 | console.log(
50 | colors.cyan('Important! Answer NO to "Generate travis.yml" question')
51 | )
52 | }
53 |
54 | console.log()
55 |
--------------------------------------------------------------------------------
/examples/example-1.js:
--------------------------------------------------------------------------------
1 | import to from '../../dist';
2 |
3 | const UserModel = {
4 | findById: (userId) => {
5 | return new Promise((resolve, reject) => {
6 | if(userId) {
7 | const userObjet = {
8 | id: userId,
9 | notificationsEnabled: true
10 | };
11 |
12 | return resolve(userObjet);
13 | }
14 |
15 | reject('Data is missing');
16 | });
17 | }
18 | };
19 |
20 | const TaskModel = function ({userId, name}) {
21 | return new Promise((resolve, reject) => {
22 | if(userId && name) {
23 | const newTask = {
24 | assignedUser: {
25 | id: userId
26 | }
27 | };
28 |
29 | return resolve(newTask);
30 | }
31 |
32 | reject('Data is missing');
33 | });
34 | };
35 |
36 | const NotificationService = {
37 | sendNotification: (userId, name) => {
38 | return new Promise((resolve, reject) => {
39 | if(userId && name) return resolve('Success');
40 |
41 | reject('Data is missing');
42 | });
43 | }
44 | };
45 |
46 |
47 | async function asyncTask(userId, cb) {
48 | let err, user, savedTask, notification;
49 | [ err, user ] = await to(UserModel.findById(userId));
50 | if(!(user && user.id)) return cb('No user found');
51 |
52 | [ err, savedTask] = await to(TaskModel({userId: user.id, name: 'Demo Task'}));
53 | if(err) return cb('Error occurred while saving task');
54 |
55 | if(user.notificationsEnabled) {
56 | [ err ] = await to(NotificationService.sendNotification(user.id, 'Task Created'));
57 | if(err) return cb('Error while sending notification');
58 | }
59 |
60 | if(savedTask.assignedUser.id !== user.id) {
61 | [ err, notification ] = await to(NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you'));
62 | if(err) return cb('Error while sending notification');
63 | }
64 |
65 | cb(null, savedTask);
66 | }
67 |
68 |
69 | asyncTask(1, (err, newTask) => {
70 | console.log('new task created');
71 | console.log(err);
72 | console.log(newTask);
73 | });
74 |
75 | asyncTask(null, (err, newTask) => {
76 | console.log('fail');
77 | console.log(err);
78 | console.log(newTask);
79 | });
80 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # await-to-js
2 |
3 | [![NPM version][npm-image]][npm-url]
4 | [![Downloads][download-badge]][npm-url]
5 |
6 | > Async await wrapper for easy error handling
7 |
8 |
9 |
10 | Supported by:
11 |
16 | The open-source notification infrastructure
17 |
18 |
19 | ## Pre-requisites
20 | You need to use Node 7.6 (or later) or an ES7 transpiler in order to use async/await functionality.
21 | You can use babel or typescript for that.
22 |
23 | ## Install
24 |
25 | ```sh
26 | npm i await-to-js --save
27 | ```
28 |
29 | ## Usage
30 |
31 | ```js
32 | import to from 'await-to-js';
33 | // If you use CommonJS (i.e NodeJS environment), it should be:
34 | // const to = require('await-to-js').default;
35 |
36 | async function asyncTaskWithCb(cb) {
37 | let err, user, savedTask, notification;
38 |
39 | [ err, user ] = await to(UserModel.findById(1));
40 | if(!user) return cb('No user found');
41 |
42 | [ err, savedTask ] = await to(TaskModel({userId: user.id, name: 'Demo Task'}));
43 | if(err) return cb('Error occurred while saving task');
44 |
45 | if(user.notificationsEnabled) {
46 | [ err ] = await to(NotificationService.sendNotification(user.id, 'Task Created'));
47 | if(err) return cb('Error while sending notification');
48 | }
49 |
50 | if(savedTask.assignedUser.id !== user.id) {
51 | [ err, notification ] = await to(NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you'));
52 | if(err) return cb('Error while sending notification');
53 | }
54 |
55 | cb(null, savedTask);
56 | }
57 |
58 | async function asyncFunctionWithThrow() {
59 | const [err, user] = await to(UserModel.findById(1));
60 | if (!user) throw new Error('User not found');
61 |
62 | }
63 | ```
64 |
65 | ## TypeScript usage
66 | ```javascript
67 | interface ServerResponse {
68 | test: number;
69 | }
70 |
71 | const p = Promise.resolve({test: 123});
72 |
73 | const [err, data] = await to(p);
74 | console.log(data.test);
75 | ```
76 |
77 |
78 | ## License
79 |
80 | MIT © [Dima Grossman](http://blog.grossman.io) && Tomer Barnea
81 |
82 | [npm-url]: https://npmjs.org/package/await-to-js
83 | [npm-image]: https://img.shields.io/npm/v/await-to-js.svg?style=flat-square
84 |
85 | [travis-url]: https://travis-ci.org/scopsy/await-to-js
86 | [travis-image]: https://img.shields.io/travis/scopsy/await-to-js.svg?style=flat-square
87 |
88 | [coveralls-url]: https://coveralls.io/r/scopsy/await-to-js
89 | [coveralls-image]: https://img.shields.io/coveralls/scopsy/await-to-js.svg?style=flat-square
90 |
91 | [depstat-url]: https://david-dm.org/scopsy/await-to-js
92 | [depstat-image]: https://david-dm.org/scopsy/await-to-js.svg?style=flat-square
93 |
94 | [download-badge]: http://img.shields.io/npm/dm/await-to-js.svg?style=flat-square
95 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "await-to-js",
3 | "version": "3.0.0",
4 | "description": "Async/await wrapper for easy error handling in js",
5 | "keywords": [
6 | "node",
7 | "async",
8 | "await",
9 | "async await"
10 | ],
11 | "main": "dist/await-to-js.umd.js",
12 | "module": "dist/await-to-js.es5.js",
13 | "typings": "dist/types/await-to-js.d.ts",
14 | "homepage": "https://github.com/scopsy/await-to-js#readme",
15 | "files": [
16 | "dist"
17 | ],
18 | "author": "Dima Grossman , Tomer Barnea ",
19 | "repository": {
20 | "type": "git",
21 | "url": "git+https://github.com/scopsy/await-to-js.git"
22 | },
23 | "license": "MIT",
24 | "engines": {
25 | "node": ">=6.0.0"
26 | },
27 | "scripts": {
28 | "lint": "tslint -t codeFrame 'src/**/*.ts' 'test/**/*.ts'",
29 | "prebuild": "rimraf dist",
30 | "build": "tsc && rollup -c && rimraf compiled && typedoc --out dist/docs --target es6 --theme minimal src",
31 | "start": "tsc -w & rollup -c -w",
32 | "test": "jest",
33 | "test:watch": "jest --watch",
34 | "test:prod": "npm run lint && npm run test -- --coverage --no-cache",
35 | "deploy-docs": "ts-node tools/gh-pages-publish",
36 | "report-coverage": "cat ./coverage/lcov.info | coveralls",
37 | "commit": "git-cz",
38 | "semantic-release": "semantic-release pre && npm publish && semantic-release post",
39 | "semantic-release-prepare": "ts-node tools/semantic-release-prepare",
40 | "precommit": "lint-staged"
41 | },
42 | "lint-staged": {
43 | "{src,test}/**/*.ts": [
44 | "git add"
45 | ]
46 | },
47 | "config": {
48 | "commitizen": {
49 | "path": "node_modules/cz-conventional-changelog"
50 | },
51 | "validate-commit-msg": {
52 | "types": "conventional-commit-types",
53 | "helpMessage": "Use \"npm run commit\" instead, we use conventional-changelog format :) (https://github.com/commitizen/cz-cli)"
54 | }
55 | },
56 | "jest": {
57 | "transform": {
58 | ".(ts|tsx)": "/node_modules/ts-jest/preprocessor.js"
59 | },
60 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
61 | "moduleFileExtensions": [
62 | "ts",
63 | "tsx",
64 | "js"
65 | ],
66 | "coveragePathIgnorePatterns": [
67 | "/node_modules/",
68 | "/test/"
69 | ],
70 | "coverageThreshold": {
71 | "global": {
72 | "branches": 90,
73 | "functions": 95,
74 | "lines": 95,
75 | "statements": 95
76 | }
77 | }
78 | },
79 | "devDependencies": {
80 | "@types/jest": "^21.1.0",
81 | "@types/node": "^8.0.0",
82 | "colors": "^1.1.2",
83 | "commitizen": "^2.9.6",
84 | "coveralls": "^2.13.1",
85 | "cross-env": "^5.0.1",
86 | "cz-conventional-changelog": "^2.0.0",
87 | "husky": "^0.14.0",
88 | "jest": "^21.0.0",
89 | "lint-staged": "^4.0.0",
90 | "lodash.camelcase": "^4.3.0",
91 | "prompt": "^1.0.0",
92 | "replace-in-file": "^3.0.0-beta.2",
93 | "rimraf": "^2.6.1",
94 | "rollup": "^0.50.0",
95 | "rollup-plugin-commonjs": "^8.0.2",
96 | "rollup-plugin-node-resolve": "^3.0.0",
97 | "rollup-plugin-sourcemaps": "^0.4.2",
98 | "semantic-release": "^8.0.0",
99 | "ts-jest": "^21.0.0",
100 | "ts-node": "^3.0.6",
101 | "tslint": "^5.4.3",
102 | "tslint-config-standard": "^6.0.0",
103 | "typedoc": "^0.8.0",
104 | "typescript": "^2.3.4",
105 | "validate-commit-msg": "^2.12.2"
106 | }
107 | }
108 |
--------------------------------------------------------------------------------