Update app and tooling

This commit is contained in:
Lawrence Chen 2026-01-29 17:36:26 -08:00
parent 3046531bdd
commit e620ec7349
4950 changed files with 2975120 additions and 10 deletions

4
node_modules/promisepipe/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,4 @@
language: node_js
node_js:
- "10"
- "8"

20
node_modules/promisepipe/LICENSE generated vendored Normal file
View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2017 Esa-Matti Suuronen and Thomas Grainger
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.

92
node_modules/promisepipe/README.md generated vendored Normal file
View file

@ -0,0 +1,92 @@
# promisePipe
Safely pipe node.js streams while capturing all errors to a single promise.
## Install
npm install promisepipe
## API
```
promisePipe(<readable stream>, [transform streams...], <writeable stream>)
```
It returns a native promise. On success the resolved value will be an array of the
streams passed in. When rejected an error object is created with following
keys:
- `source`: The stream that caused the error
- `originalError`: Original error from the stream
- `message`: The error message from original error
Note: the last stream in the chain needs to be a writable stream, not a duplex/transform stream. If you use a 3rd party library which returns deplux streams instead of writable streams, you'll need to add something like [`.pipe(devnull())`](https://www.npmjs.com/package/dev-null) to the end, otherwise the promise will never resolve ([#16](https://github.com/epeli/node-promisepipe/issues/16)).
Starting with v3, all streams are destroyed if there's an error to prevent memory leaks.
## Example
```javascript
var promisePipe = require("promisepipe");
promisePipe(
fs.createReadStream(INPUT_FILE),
new UpcaseTransform(),
fs.createWriteStream(OUTPUT_FILE),
).then(function(streams){
console.log("Done writing to the output file stream!");
}, function(err) {
console.log("This stream failed:", err.source);
console.log("Original error was:", err.originalError);
});
```
or with async-wait
```javascript
var promisePipe = require("promisepipe");
(async () => {
try {
await promisePipe(
fs.createReadStream(INPUT_FILE),
new UpcaseTransform(),
fs.createWriteStream(OUTPUT_FILE)
);
console.log("Done writing to the output file stream!");
} catch (err) {
console.log("This stream failed:", err.source);
console.log("Original error was:", err.originalError);
}
})();
```
## Why?
Stream piping in node.js is cool, but error handling is not because streams
do not bubble errors to the target streams.
For example if the previous example is written like this:
```javascript
fs.createReadStream(INPUT_FILE)
.pipe(new UpcaseTransform())
.pipe(fs.createReadStream(OUTPUT_FILE))
```
It might crash your program at any time. You must handle the errors
from each stream manually like this:
```javascript
fs.createReadStream(INPUT_FILE).on("error", function(err) {
// handle the error
}).pipe(new UpcaseTransform()).on("error", function(err) {
// handle the error
}).pipe(fs.createReadStream(OUTPUT_FILE)).on("error", function(err) {
// handle the error
})
```
Handling errors this way can be very cumbersome. `promisepipe` simplifies
error handling by sending the first error occurance into a promise.

1
node_modules/promisepipe/fixtures/input.txt generated vendored Normal file
View file

@ -0,0 +1 @@
foobar

1
node_modules/promisepipe/fixtures/input.txt.x generated vendored Normal file
View file

@ -0,0 +1 @@
foobarX

1
node_modules/promisepipe/fixtures/input.txt.y generated vendored Normal file
View file

@ -0,0 +1 @@
foobarY

96
node_modules/promisepipe/index.js generated vendored Normal file
View file

@ -0,0 +1,96 @@
'use strict';
class StreamError extends Error {
constructor(err, source) {
const message = err && err.message || err;
super(message);
this.source = source;
this.originalError = err;
}
}
const events = ['error', 'end', 'close', 'finish'];
function cleanupEventHandlers(stream, listener) {
events.map(e => stream.removeListener(e, listener));
}
function streamPromise(stream, state) {
if (stream === process.stdout || stream === process.stderr) {
return Promise.resolve(stream);
}
// see https://github.com/epeli/node-promisepipe/issues/2
// and https://github.com/epeli/node-promisepipe/issues/15
const isReadable = stream.readable || typeof stream._read === 'function';
function on(evt) {
function executor(resolve, reject) {
const fn = evt === 'error' ?
err => reject(new StreamError(err, stream)) :
() => {
// For readable streams, we ignore the "finish" event. However, if there
// already was an error on another stream, the "end" event may never come,
// so in that case we accept "finish" too.
if (isReadable && evt === 'finish' && !state.error) {
return;
}
cleanupEventHandlers(stream, fn);
resolve(stream);
};
stream.on(evt, fn);
}
return new Promise(executor);
}
return Promise.race(events.map(on));
}
/**
* @param {...Stream} stream
*/
function promisePipe(stream) {
let i = arguments.length;
const streams = [];
while ( i-- ) streams[i] = arguments[i];
const allStreams = streams
.reduce((current, next) => current.concat(next), []);
allStreams.reduce((current, next) => current.pipe(next));
return allStreamsDone(streams);
}
function allStreamsDone(allStreams) {
let state = {};
let firstRejection;
return Promise.all(allStreams.map(stream => streamPromise(stream, state).catch((e) => {
if (!firstRejection) {
firstRejection = e;
state.error = true;
// Close all streams as they are not closed automatically on error.
allStreams.forEach(stream => {
if (stream !== process.stdout && stream !== process.stderr) {
stream.destroy();
}
});
}
}))).then((allResults) => {
if (firstRejection) {
throw firstRejection;
}
return allResults;
});
}
module.exports = Object.assign(promisePipe, {
__esModule: true,
default: promisePipe,
justPromise: streams => allStreamsDone(streams),
StreamError,
});

27
node_modules/promisepipe/package.json generated vendored Normal file
View file

@ -0,0 +1,27 @@
{
"name": "promisepipe",
"version": "3.0.0",
"description": "Pipe node.js streams safely with Promises",
"main": "index.js",
"scripts": {
"test": "mocha test.js"
},
"repository": {
"type": "git",
"url": "https://github.com/epeli/node-promisepipe"
},
"keywords": [
"promise",
"stream"
],
"author": "Esa-Matti Suuronen",
"license": "MIT",
"bugs": {
"url": "https://github.com/epeli/node-promisepipe/issues"
},
"devDependencies": {
"mocha": "^3.2.0",
"mz": "^2.6.0"
},
"dependencies": {}
}

208
node_modules/promisepipe/test.js generated vendored Normal file
View file

@ -0,0 +1,208 @@
/*global it, describe, beforeEach */
var stream = require("stream");
var fs = require("mz/fs");
var assert = require("assert");
var util = require("util");
var promisePipe = require("./index");
var StreamError = promisePipe.StreamError;
var INPUT = __dirname + "/fixtures/input.txt";
var OUTPUT = __dirname + "/fixtures/output.txt";
function Upcase(){
stream.Transform.call(this);
}
function W () {
stream.Writable.call(this);
}
function raise(err) {
throw err;
}
util.inherits(Upcase, stream.Transform);
util.inherits(W, stream.Writable);
Upcase.prototype._transform = function(chunk, encoding, cb) {
if (/X/.test(chunk.toString())) {
cb(new Error("X is not allowed"));
return;
}
this.str = (this.str || '') + chunk.toString();
this.push(chunk.toString().toUpperCase());
cb();
};
Upcase.prototype._flush = function(cb) {
setTimeout(() => {
if (/Y/.test(this.str)) {
cb(new Error("Y is not allowed"));
return;
}
cb()
}, 1);
};
W.prototype._write = function () {
this.emit("error", new Error("Write failed"));
this.emit("error", new Error("Write failed"));
};
describe("promisePipe", function() {
beforeEach(function() {
return fs
.unlink(OUTPUT)
.catch(err => err.code === "ENOENT" || raise(err));
});
it("can do basic piping", function() {
var input = fs.createReadStream(INPUT);
var output = fs.createWriteStream(OUTPUT);
return promisePipe(input, output).then(function(pipeChain) {
assert.equal(input, pipeChain[0], "Resolved promise passes stream pipe chain back");
assert.equal(output, pipeChain[1]);
return fs
.readFile(OUTPUT)
.then(data => assert.equal(data.toString().trim(), "foobar"));
});
});
["stdout", "stderr"].forEach(function(stdio) {
it("can pipe to " + stdio, function() {
var input = fs.createReadStream(INPUT);
return promisePipe(input, process[stdio]);
});
it("can handle errors when dest is " + stdio, function() {
var input = fs.createReadStream("bad");
var output = process[stdio];
return promisePipe(input, output)
.catch(err => err)
.then(function(err) {
assert(err);
assert.equal(err.originalError.code, "ENOENT");
assert.equal(err.source, input);
});
});
});
it("can handle errors from source", function() {
var input = fs.createReadStream("bad");
var output = fs.createWriteStream(OUTPUT);
return promisePipe(input, output)
.catch(err => err)
.then(function(err) {
assert(err);
assert.equal(err.originalError.code, "ENOENT");
assert.equal(err.source, input);
});
});
it("can handle errors from target", function() {
var input = fs.createReadStream(INPUT);
var output = fs.createWriteStream("/bad");
return promisePipe(input, output)
.catch(err => err)
.then(function(err) {
assert(err);
assert.ok([ "EACCES", "EPERM" ].includes(err.originalError.code));
});
});
it("can pipe via transforms", function() {
var input = fs.createReadStream(INPUT);
var output = fs.createWriteStream(OUTPUT);
return promisePipe(input, new Upcase(), output).then(function() {
return fs
.readFile(OUTPUT)
.then(data => assert.equal(data.toString().trim(), "FOOBAR"));
});
});
it("can handle errors from transforms", function() {
var input = fs.createReadStream(INPUT + ".x");
var output = fs.createWriteStream(OUTPUT);
return promisePipe(input, new Upcase(), output)
.catch(err => err)
.then(function(err) {
assert(err);
assert.equal(err.originalError.message, "X is not allowed");
});
});
it("can handle errors from _flush in transforms", function() {
var input = fs.createReadStream(INPUT + ".y");
var output = fs.createWriteStream(OUTPUT);
const upcase = new Upcase()
return promisePipe(input, upcase, output)
.catch(err => err)
.then(function(err) {
assert(err);
assert.equal(err.originalError.message, "Y is not allowed");
});
});
it("can handle multiple errors", function() {
var input = fs.createReadStream(INPUT);
return promisePipe(input, new W())
.catch(err => err)
.then(function(err) {
assert(err);
assert.equal(err.originalError.message, "Write failed");
});
});
it("closes streams on errors", function() {
var input = fs.createReadStream(INPUT + ".x");
var output = fs.createWriteStream(OUTPUT);
return promisePipe(input, new Upcase(), output)
.catch(err => err)
.then(function() {
return fs.unlink(OUTPUT);
});
});
it("resolves chains with transform streams on error", function() {
var input = fs.createReadStream(INPUT);
var output = fs.createWriteStream("/bad");
return promisePipe(input, new Upcase(), output)
.catch(err => err)
.then(function(err) {
assert(err);
assert.ok([ "EACCES", "EPERM" ].includes(err.originalError.code));
});
});
});
describe('StreamError', function() {
it('uses the provided error message', function() {
var err = new StreamError({message: 'foo'});
assert.equal(err.message,'foo');
});
it('uses assign message as error string param', function() {
var err = new StreamError('foo');
assert.equal(err.message,'foo');
});
it('should not throw if no message', function() {
var err = new StreamError();
assert.equal(err.message,'');
});
});