"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const verror_1 = require("verror"); const format_verror_1 = require("./format-verror"); /** * Accumulates multiple errors, to all be thrown together instead of one at a time. */ class ErrorBuffer { constructor() { this.errors = []; } /** * Adds the given error(s) (or other objects, which are converted to errors). */ add(...errors) { for (let error of errors) { if (error instanceof verror_1.MultiError) this.add(...error.errors()); else { if (!(error instanceof Error)) error = new Error(String(error)); else if (this.errors.indexOf(error) !== -1) { /* Deduplicate errors. * * Consider this scenario: * 1. Promise A is started. * 2. Promise B is started. It awaits the result of A. * 3. Promise C is started. It also awaits the result of A. * 4. PromiseEach is called, to collect the results of promises B and C. * 5. Promise A rejects with error E. * 6. Promise B, previously waiting on A, rejects with E. * 7. Promise C, previously waiting on A, also rejects with E. * 8. PromiseEach collects the results of [B, C]. They are { B: rejection(E), C: rejection(E) }. * 9. PromiseEach finds that B rejected with E, so it adds E to its ErrorBuffer. * 10. PromiseEach finds that C rejected with E, so it adds E to its ErrorBuffer. * 11. PromiseEach rejects with [E, E]. * * But, if ErrorBuffer deduplicates the errors it receives, then step 10 has no effect, because E is already in the ErrorBuffer. As a result, in step 11, PromiseEach rejects with E instead of [E, E]. * * Note that this deduplication only applies to instances of Error. When other values are passed in, they are converted to a new instance of Error each time, so there is no chance to deduplicate them. */ continue; } this.errors.push(error); } } } /** * Adds the given error, then throws it. If other errors have been added already, throws a `MultiError` instead. */ throw(error) { const throwSingle = !this.errors.length; this.add(error); throw throwSingle ? error : format_verror_1.PrettyVError.errorFromList(this.errors); } /** * Catches errors thrown from the given function, adding them to the array of accumulated errors. */ catching(fun) { try { return fun(); } catch (e) { this.add(e); } } /** * Catches errors thrown from the given async function or promise, adding them to the array of accumulated errors. */ async catchingAsync(fun) { try { if (typeof fun === "function") return await fun(); else return await fun; } catch (e) { this.add(e); } } /** * Throws any accumulated errors. */ check() { const error = format_verror_1.PrettyVError.errorFromList(this.errors); if (error) throw error; } get isEmpty() { return !this.errors.length; } } exports.ErrorBuffer = ErrorBuffer; //# sourceMappingURL=errors.js.map