package/package.json000644 0000003415 13276124200011565 0ustar00000000 000000 { "name": "async-done", "version": "1.3.1", "description": "Allows libraries to handle various caller provided asynchronous functions uniformly. Maps promises, observables, child processes and streams, and callbacks to callback style.", "author": "Gulp Team (http://gulpjs.com/)", "contributors": [ "Blaine Bublitz ", "Pawel Kozlowski ", "Matthew Podwysocki ", "Charles Samborski " ], "repository": "gulpjs/async-done", "license": "MIT", "engines": { "node": ">= 0.10" }, "main": "index.js", "types": "index.d.ts", "files": [ "index.js", "index.d.ts", "LICENSE" ], "scripts": { "lint": "eslint . && jscs index.js test/", "pretest": "npm run lint", "test": "mocha --async-only && npm run test-types", "test-types": "tsc -p test/types", "cover": "istanbul cover _mocha --report lcovonly", "coveralls": "npm run cover && istanbul-coveralls" }, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.2", "process-nextick-args": "^1.0.7", "stream-exhaust": "^1.0.1" }, "devDependencies": { "@types/node": "^9.3.0", "eslint": "^1.7.3", "eslint-config-gulp": "^2.0.0", "expect": "^1.19.0", "istanbul": "^0.4.3", "istanbul-coveralls": "^1.0.3", "jscs": "^2.3.5", "jscs-preset-gulp": "^1.0.0", "mocha": "^2.4.5", "pumpify": "^1.3.6", "rxjs": "^5.5.6", "through2": "^2.0.0", "typescript": "^2.6.2", "when": "^3.7.3" }, "keywords": [ "promises", "callbacks", "observables", "streams", "end", "completion", "complete", "finish", "done", "async", "error handling" ] } package/index.d.ts000644 0000006673 13276121320011211 0ustar00000000 000000 /** * Notes about these type definitions: * * - Callbacks returning multiple completion values using multiple arguments are not supported by these types. * Prefer to use Node's style by grouping your values in a single object or array. * Support for this kind of callback is blocked by Microsoft/TypeScript#5453 * * - For ease of use, `asyncDone` lets you pass callback functions with a result type `T` instead of `T | undefined`. * This matches Node's types but can lead to unsound code being typechecked. * * The following code typechecks but fails at runtime: * ```typescript * async function getString(): Promise { * return "Hello, World!"; * } * * async function evilGetString(): Promise { * throw new Error("Hello, World!"); * } * * function cb(err: Error | null, result: string): void { * // This is unsound because `result` is `undefined` when `err` is not `null`. * console.log(result.toLowerCase()); * } * * asyncDone(getString, cb); // Prints `hello, world!` * asyncDone(evilGetString, cb); // Runtime error: `TypeError: Cannot read property 'toLowerCase' of undefined` * ``` * * Enforcing stricter callbacks would require developers to use `result?: string` and assert the existence * of the result either by checking it directly or using the `!` assertion operator after testing for errors. * ```typescript * function stricterCb1(err: Error | null, result?: string): void { * if (err !== null) { * console.error(err); * return; * } * console.log(result!.toLowerCase()); * } * * function stricterCb2(err: Error | null, result?: string): void { * if (result === undefined) { * console.error("Undefined result. Error:); * console.error(err); * return; * } * console.log(result.toLowerCase()); * } * ``` */ import { ChildProcess } from "child_process"; import { EventEmitter } from "events"; import { Stream } from "stream"; declare namespace asyncDone { /** * Represents a callback function used to signal the completion of a * task without any result value. */ type VoidCallback = (err: Error | null) => void; /** * Represents a callback function used to signal the completion of a * task with a single result value. */ interface Callback { (err: null, result: T): void; // Use `result?: T` or `result: undefined` to require the consumer to assert the existence of the result // (even in case of success). See comment at the top of the file. (err: Error, result?: any): void; } /** * Minimal `Observable` interface compatible with `async-done`. * * @see https://github.com/ReactiveX/rxjs/blob/c3c56867eaf93f302ac7cd588034c7d8712f2834/src/internal/Observable.ts#L77 */ interface Observable { subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): any; } /** * Represents an async operation. */ export type AsyncTask = ((done: VoidCallback) => void) | ((done: Callback) => void) | (() => ChildProcess | EventEmitter | Observable | PromiseLike | Stream); } /** * Takes a function to execute (`fn`) and a function to call on completion (`callback`). * * @param fn Function to execute. * @param callback Function to call on completion. */ declare function asyncDone(fn: asyncDone.AsyncTask, callback: asyncDone.Callback): void; export = asyncDone; package/index.js000644 0000003137 13227222576010760 0ustar00000000 000000 'use strict'; var domain = require('domain'); var eos = require('end-of-stream'); var tick = require('process-nextick-args'); var once = require('once'); var exhaust = require('stream-exhaust'); var eosConfig = { error: false, }; function rethrowAsync(err) { process.nextTick(rethrow); function rethrow() { throw err; } } function tryCatch(fn, args) { try { return fn.apply(null, args); } catch (err) { rethrowAsync(err); } } function asyncDone(fn, cb) { cb = once(cb); var d = domain.create(); d.once('error', onError); var domainBoundFn = d.bind(fn); function done() { d.removeListener('error', onError); d.exit(); return tryCatch(cb, arguments); } function onSuccess(result) { done(null, result); } function onError(error) { if (!error) { error = new Error('Promise rejected without Error'); } done(error); } function asyncRunner() { var result = domainBoundFn(done); function onNext(state) { onNext.state = state; } function onCompleted() { onSuccess(onNext.state); } if (result && typeof result.on === 'function') { // Assume node stream d.add(result); eos(exhaust(result), eosConfig, done); return; } if (result && typeof result.subscribe === 'function') { // Assume RxJS observable result.subscribe(onNext, onError, onCompleted); return; } if (result && typeof result.then === 'function') { // Assume promise result.then(onSuccess, onError); return; } } tick(asyncRunner); } module.exports = asyncDone; package/LICENSE000644 0000002142 13227035025010302 0ustar00000000 000000 The MIT License (MIT) Copyright (c) 2015 Blaine Bublitz, Eric Schoffstall and other contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package/README.md000644 0000011543 13276121320010557 0ustar00000000 000000

# async-done [![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![AppVeyor Build Status][appveyor-image]][appveyor-url] [![Coveralls Status][coveralls-image]][coveralls-url] [![Gitter chat][gitter-image]][gitter-url] Allows libraries to handle various caller provided asynchronous functions uniformly. Maps promises, observables, child processes and streams, and callbacks to callback style. As async conventions evolve, it is useful to be able to deal with several different *styles* of async completion uniformly. With this module you can handle completion using a node-style callback, regardless of a return value that's a promise, observable, child process or stream. ## Usage ### Successful completion ```js var asyncDone = require('async-done'); asyncDone(function(done){ // do async things done(null, 2); }, function(error, result){ // `error` will be null on successful execution of the first function. // `result` will be the result from the first function. }); ``` ### Failed completion ```js var asyncDone = require('async-done'); asyncDone(function(done){ // do async things done(new Error('Some Error Occurred')); }, function(error, result){ // `error` will be an error from the first function. // `result` will be undefined on failed execution of the first function. }); ``` ## API ### `asyncDone(fn, callback)` Takes a function to execute (`fn`) and a function to call on completion (`callback`). #### `fn([done])` Optionally takes a callback to call when async tasks are complete. #### Completion and Error Resolution * `Callback` (`done`) called - Completion: called with null error - Error: called with non-null error * `Stream` or `EventEmitter` returned - Completion: [end-of-stream][end-of-stream] module - Error: [domains][domains] - __Note:__ Only actual streams are supported, not faux-streams; Therefore, modules like [`event-stream`][event-stream] are not supported. * `Child Process` returned - Completion [end-of-stream][end-of-stream] module - Error: [domains][domains] * `Promise` returned - Completion: [onFulfilled][promise-onfulfilled] method called - Error: [onRejected][promise-onrejected] method called * `Observable` (e.g. from [RxJS v5][rxjs5-observable] or [RxJS v4][rxjs5-observable]) returned - Completion: [complete][rxjs5-subscriber-complete] method called - Error: [error][rxjs5-subscriber-error] method called __Warning:__ Sync tasks are __not supported__ and your function will never complete if the one of the above strategies is not used to signal completion. However, thrown errors will be caught by the domain. #### `callback(error, result)` If an error doesn't occur in the execution of the `fn` function, the `callback` method will receive the results as its second argument. Note: Some streams don't received any results. If an error occurred in the execution of the `fn` function, The `callback` method will receive an error as its first argument. Errors can be caused by: * A thrown error * An error passed to a `done` callback * An `error` event emitted on a returned `Stream`, `EventEmitter` or `Child Process` * A rejection of a returned `Promise` - If the `Promise` is not rejected with a value, we generate a new `Error` * The `onError` handler being called on an `Observable` ## License MIT [end-of-stream]: https://www.npmjs.com/package/end-of-stream [domains]: http://nodejs.org/api/domain.html [event-stream]: https://github.com/dominictarr/event-stream [promise-onfulfilled]: http://promisesaplus.com/#point-26 [promise-onrejected]: http://promisesaplus.com/#point-30 [rx4-observable]: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/observable.md [rxjs5-observable]: http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html [rxjs5-observer-complete]: http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObserverDoc.html#instance-method-complete [rxjs5-observer-error]: http://reactivex.io/rxjs/class/es6/MiscJSDoc.js~ObserverDoc.html#instance-method-error [downloads-image]: http://img.shields.io/npm/dm/async-done.svg [npm-url]: https://www.npmjs.com/package/async-done [npm-image]: http://img.shields.io/npm/v/async-done.svg [travis-url]: https://travis-ci.org/gulpjs/async-done [travis-image]: http://img.shields.io/travis/gulpjs/async-done.svg?label=travis-ci [appveyor-url]: https://ci.appveyor.com/project/gulpjs/async-done [appveyor-image]: https://img.shields.io/appveyor/ci/gulpjs/async-done.svg?label=appveyor [coveralls-url]: https://coveralls.io/r/gulpjs/async-done [coveralls-image]: http://img.shields.io/coveralls/gulpjs/async-done/master.svg [gitter-url]: https://gitter.im/gulpjs/gulp [gitter-image]: https://badges.gitter.im/gulpjs/gulp.svg