3 Commits

9 changed files with 208 additions and 95 deletions
Split View
  1. +1
    -1
      example.js
  2. +39
    -31
      index.js
  3. +8
    -1
      package.json
  4. +6
    -0
      src/readable/attach-handlers.js
  5. +10
    -0
      src/readable/index.js
  6. +44
    -22
      src/readable/push-buffer.js
  7. +9
    -0
      src/writable/index.js
  8. +9
    -1
      src/writable/write-to-stream.js
  9. +82
    -39
      yarn.lock

+ 1
- 1
example.js View File

@ -33,7 +33,7 @@ return Promise.try(() => {
return pipe([
rangeNumbers(0, 10),
map((line) => String(line) + "\n"),
map((number) => String(number) + "\n"),
fromNodeStream(fs.createWriteStream("numbers.txt", { encoding: "utf8" }))
]).read();
}).then((result) => {


+ 39
- 31
index.js View File

@ -8,6 +8,7 @@ const propagatePeek = require("@promistream/propagate-peek");
const propagateAbort = require("@promistream/propagate-abort");
const pipe = require("@promistream/pipe");
const isEndOfStream = require("@promistream/is-end-of-stream");
const debug = require("debug");
const createDefer = require("./src/create-defer");
const wireUpReadableInterface = require("./src/readable");
@ -64,22 +65,28 @@ function fromReadable(stream) {
});
}
let debugWritable = debug("promistream:from-node-stream:writable");
function fromWritable(stream) {
let upstreamHasEnded = false;
let mostRecentSource = { abort: function() {} }; // FIXME: Replace with a proper spec-compliant dummy stream
let convertedStream = simpleSink({
onResult: (result) => {
debugWritable("Received value");
return writable.write(result);
},
onEnd: () => {
debugWritable("Upstream reported end-of-stream");
upstreamHasEnded = true;
return writable.end();
},
onAbort: (_reason) => {
debugWritable("Pipeline was aborted");
return writable.destroy();
},
onSourceChanged: (source) => {
debugWritable("A source change occurred");
mostRecentSource = source;
}
});
@ -100,8 +107,9 @@ function fromWritable(stream) {
return convertedStream;
}
let debugTransform = debug("promistream:from-node-stream:transform");
function fromTransform(stream) {
let completionDefer;
let endHandled = false;
// FIXME: we need to specifically watch for the `error` and `end` events on the readable interface, to know when the transform stream has fully completed processing
@ -109,19 +117,15 @@ function fromTransform(stream) {
// request, destroy
let readable = wireUpReadableInterface(stream, {
onEnd: () => {
if (completionDefer != null) {
completionDefer.resolve();
}
debugTransform("Received end/close event from underlying stream");
},
onError: (error) => {
if (completionDefer != null) {
completionDefer.reject(error);
}
onError: () => {
debugTransform("Received error event from underlying stream");
}
});
// write, end, destroy
var writable = wireUpWritableInterface(stream);
let writable = wireUpWritableInterface(stream);
let convertedStream = {
_promistreamVersion: 0,
@ -129,32 +133,36 @@ function fromTransform(stream) {
abort: propagateAbort,
peek: propagatePeek,
read: function produceValue_nodeTransformStream(source) {
return Promise.try(() => {
return source.read();
}).then((value) => {
writable.write(value);
// This will quite possibly return an empty buffer, but that is fine; the `buffer` stream downstream from us will just keep reading (and therefore queueing up new items to be transformed) until it gets some results.
return readable.consumeImmediateBuffer();
}).catch(isEndOfStream, (marker) => {
// Wait for transform stream to drain fully, `error`/`end` event, and then return whatever buffer remains.
// FIXME: Error propagation logic is pretty shaky here. Verify that we don't end up with double error reports.
if (endHandled === false) {
if (endHandled) {
// NOTE: This logic exists at the start, not in the upstream EndOfStream handling code, because any number of buffer reads may be required before the wrapped Node stream can be closed
// NOTE: The push-buffer will automatically produce EndOfStream markers once the buffer has run out and the underlying stream has closed, so long as we're using the wireUpReadableInterface function
return Promise.try(() => {
return readable.request();
}).then((result) => {
return [ result ];
});
} else {
return Promise.try(() => {
debugTransform("Doing upstream read...");
return source.read();
}).then((value) => {
debugTransform("Writing upstream value to writable interface");
writable.write(value);
// This will quite possibly return an empty buffer, but that is fine; the `buffer` stream downstream from us will just keep reading (and therefore queueing up new items to be transformed) until it gets some results.
debugTransform("Consuming immediate buffer from readable interface");
return readable.consumeImmediateBuffer();
}).catch(isEndOfStream, () => {
debugTransform("End of upstream reached");
endHandled = true;
debugTransform("Closing via writable interface");
writable.end();
return Promise.try(() => {
let { promise, defer } = createDefer();
completionDefer = defer;
return promise;
}).then(() => {
return readable.consumeImmediateBuffer();
});
} else {
throw marker;
}
});
// Return nothing, let the next read call (and all of those after that) deal with either underlying stream completion or buffered results
return [];
});
}
}
};


+ 8
- 1
package.json View File

@ -1,6 +1,6 @@
{
"name": "@promistream/from-node-stream",
"version": "0.1.0",
"version": "0.1.1",
"main": "index.js",
"repository": "http://git.cryto.net/promistream/from-node-stream.git",
"author": "Sven Slootweg <admin@cryto.net>",
@ -16,6 +16,13 @@
"@promistream/simple-sink": "^0.1.0",
"@promistream/simple-source": "^0.1.1",
"bluebird": "^3.7.2",
"debug": "^4.3.1",
"p-event": "^4.2.0",
"split-filter": "^1.1.3"
},
"devDependencies": {
"@promistream/buffered-map": "^0.1.0",
"@promistream/collect": "^0.1.1",
"@promistream/range-numbers": "^0.1.2"
}
}

+ 6
- 0
src/readable/attach-handlers.js View File

@ -1,7 +1,10 @@
"use strict";
const debug = require("debug")("promistream:from-node-stream:readable:attach-handlers");
module.exports = function attachReadableStreamHandlers({ stream, onClose, onError, onData }) {
function detachEventHandlers() {
debug("Detaching event handlers");
stream.removeListener("end", onCloseWrapper);
stream.removeListener("close", onCloseWrapper);
stream.removeListener("error", onErrorWrapper);
@ -9,6 +12,7 @@ module.exports = function attachReadableStreamHandlers({ stream, onClose, onErro
}
function attachEventHandlers() {
debug("Attaching event handlers");
stream.on("end", onCloseWrapper);
stream.on("close", onCloseWrapper);
stream.on("error", onErrorWrapper);
@ -16,11 +20,13 @@ module.exports = function attachReadableStreamHandlers({ stream, onClose, onErro
}
function onCloseWrapper() {
debug("onCloseWrapper called");
onClose();
detachEventHandlers();
}
function onErrorWrapper(error) {
debug("onErrorWrapper called");
onError(error);
detachEventHandlers();
}


+ 10
- 0
src/readable/index.js View File

@ -1,5 +1,7 @@
"use strict";
const debug = require("debug")("promistream:from-node-stream:readable");
const attachHandlers = require("./attach-handlers");
const createPushBuffer = require("./push-buffer");
const destroyStream = require("../destroy-stream");
@ -9,6 +11,7 @@ module.exports = function wireUpReadableInterface(stream, { onEnd, onError } = {
let pushBuffer = createPushBuffer({
onPause: function () {
if (stream.pause != null) {
debug("Pausing underlying stream");
stream.pause();
return true; // FIXME: Can we verify whether the pausing was successful, somehow? Eg. to deal with streams with `readable` event handlers attached.
} else {
@ -17,6 +20,7 @@ module.exports = function wireUpReadableInterface(stream, { onEnd, onError } = {
},
onResume: function () {
if (stream.resume != null) {
debug("Resuming underlying stream");
stream.resume();
return true;
} else {
@ -29,6 +33,12 @@ module.exports = function wireUpReadableInterface(stream, { onEnd, onError } = {
attachHandlers({
stream: stream,
onData: (data) => {
if (Buffer.isBuffer(data)) {
debug(`Chunk emitted of length ${data.length}`);
} else {
debug(`Value emitted`);
}
pushBuffer.queueValue(data);
},
onError: (error) => {


+ 44
- 22
src/readable/push-buffer.js View File

@ -5,6 +5,7 @@
const splitFilter = require("split-filter");
const unreachable = require("@joepie91/unreachable")("@promistream/from-node-stream");
const EndOfStream = require("@promistream/end-of-stream");
const debug = require("debug")("promistream:from-node-stream:push-buffer");
const warn = require("../warn");
const createDefer = require("../create-defer");
@ -18,6 +19,7 @@ module.exports = function createPushBuffer(options) {
return false;
};
// TODO: Use @joepie91/consumable here?
let itemBuffer = [];
let requestQueue = [];
let isPaused = false;
@ -35,33 +37,40 @@ module.exports = function createPushBuffer(options) {
function attemptDrain() {
// NOTE: This must remain fully synchronous, if we want to avoid unnecessary pauses in the `data` handler
while (requestQueue.length > 0) {
let hasItems = (itemBuffer.length > 0);
let hasResponse = (hasEnded || hasItems);
if (hasResponse) {
let defer = requestQueue.shift();
if (hasItems) {
// FIXME: Does this correctly deal with an error event produced as a result of an abort?
let item = itemBuffer.shift();
if (item.type === "value") {
defer.resolve(item.value);
} else if (item.type === "error") {
defer.reject(item.error);
debug("Drain attempt started");
if (requestQueue.length > 0) {
while (requestQueue.length > 0) {
let hasItems = (itemBuffer.length > 0);
let hasResponse = (hasEnded || hasItems);
if (hasResponse) {
debug("Satisfying queued request");
let defer = requestQueue.shift();
if (hasItems) {
// FIXME: Does this correctly deal with an error event produced as a result of an abort?
let item = itemBuffer.shift();
if (item.type === "value") {
defer.resolve(item.value);
} else if (item.type === "error") {
defer.reject(item.error);
} else {
unreachable(`Unexpected item type '${item.type}'`);
}
} else if (hasEnded) {
defer.reject(new EndOfStream());
} else {
unreachable(`Unexpected item type '${item.type}'`);
unreachable("Invalid response state, neither has items in queue nor ended");
}
} else if (hasEnded) {
defer.reject(new EndOfStream());
} else {
unreachable("Invalid response state, neither has items in queue nor ended");
debug("No data available to satisfy queued request");
break;
}
} else {
break;
}
} else {
debug("No outstanding requests to satisfy");
}
resumeIfEmpty();
@ -69,6 +78,7 @@ module.exports = function createPushBuffer(options) {
return {
queueValue: function (value) {
debug("Queueing value");
itemBuffer.push({ type: "value", value: value });
attemptDrain();
@ -84,22 +94,28 @@ module.exports = function createPushBuffer(options) {
}
},
queueError: function (error) {
debug("Queueing error");
itemBuffer.push({ type: "error", error: error });
attemptDrain();
},
queueRequest: function () {
debug("Queueing read request");
let { defer, promise } = createDefer();
requestQueue.push(defer);
attemptDrain();
return promise;
},
markEnded: function () {
debug("Marking as ended");
hasEnded = true;
attemptDrain();
},
consumeImmediateBuffer: function () {
debug("Post-drain remaining buffer requested");
attemptDrain();
debug("Returning immediate buffer");
// FIXME: Only return successful items here?
if (requestQueue.length > 0) {
// We won't ever serve up the buffer until any individual-item requests have been fulfilled.
@ -107,10 +123,16 @@ module.exports = function createPushBuffer(options) {
} else {
let [ values, errors ] = splitFilter(itemBuffer, (item) => item.type === "value");
debug(`Buffer contains ${errors.length} errors and ${values.length} values`);
if (errors.length > 0) {
debug("Throwing first error");
itemBuffer = values; // In case we ever write code that will do something with the remaining values in the buffer
throw errors[0].error;
} else {
debug(`Returning ${values.length} values`);
itemBuffer = [];
resumeIfEmpty(); // Ensure that we haven't left the source stream in a paused state, because that would deadlock the pipeline
return values.map((item) => item.value);


+ 9
- 0
src/writable/index.js View File

@ -1,5 +1,8 @@
"use strict";
const pEvent = require("p-event");
const debug = require("debug")("promistream:from-node-stream:writable");
const attachHandlers = require("./attach-handlers");
const writeToStream = require("./write-to-stream");
const isStdioStream = require("../is-stdio-stream");
@ -30,7 +33,13 @@ module.exports = function wireUpWritableInterface(stream, { onEnd, onError } = {
end: function () {
// stdout/stderr cannot be ended like other streams
if (!isStdioStream(stream)) {
debug("Ending stream");
let finishPromise = pEvent(stream, "finish");
stream.end();
return finishPromise;
} else {
debug("Not ending stream because it is stdio");
}
},
destroy: function () {


+ 9
- 1
src/writable/write-to-stream.js View File

@ -1,5 +1,7 @@
"use strict";
const debug = require("debug")("promistream:from-node-stream:writable");
const isStdioStream = require("../is-stdio-stream");
module.exports = function writeToStream(stream, value) {
@ -7,10 +9,16 @@ module.exports = function writeToStream(stream, value) {
let canWriteMore = stream.write(value);
if (canWriteMore) {
debug("Stream can accept more data");
return;
} else {
debug("Stream is backed up, waiting for drain event...");
// TODO: Use p-event instead?
return new Promise((resolve, _reject) => {
stream.once("drain", () => resolve());
stream.once("drain", () => {
debug("Drain event received");
resolve();
});
});
}
} else {


+ 82
- 39
yarn.lock View File

@ -15,7 +15,7 @@
default-value "^1.0.0"
error-chain "^0.1.0"
"@promistream/buffer@^0.1.0":
"@promistream/buffer@^0.1.0", "@promistream/buffer@^0.1.2":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@promistream/buffer/-/buffer-0.1.2.tgz#73c63476aa5cfeb111298b791a33d8008384721b"
integrity sha512-EquWW7HTpjngNkMxHhxww0rvODWAaEN715BXQWP9zXkm+CXdhYmadeol7G2kMPTTYuYjKFmiNUdjjfm/z2puyg==
@ -24,6 +24,22 @@
"@promistream/propagate-abort" "^0.1.2"
bluebird "^3.5.4"
"@promistream/buffered-map@^0.1.0":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@promistream/buffered-map/-/buffered-map-0.1.1.tgz#7c0f2542102b0a9f8b738100ea4587a084dcb110"
integrity sha512-6KIcJEW75oJmKzYEJoGTm+vZgwH7oeOJCLJj9eRKnqSYaGFBtWWyyEN0uEui5qrXbPqFW4l0Eu609HhRWPc3Gg==
dependencies:
"@promistream/buffer" "^0.1.2"
"@promistream/map" "^0.1.1"
"@promistream/pipe" "^0.1.4"
"@promistream/collect@^0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@promistream/collect/-/collect-0.1.1.tgz#085360a66c5cab7616833542009212be34a447ff"
integrity sha512-zXnp8SFm2dFsvJBASLfYMUxfaNkvzyhU56WT1iAXxlN5w2Rb0vArP2pIXvpbiSVrWkUObNeZ8t715nGxqsWEow==
dependencies:
"@promistream/simple-sink" "^0.1.0"
"@promistream/end-of-stream@^0.1.0", "@promistream/end-of-stream@^0.1.1":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@promistream/end-of-stream/-/end-of-stream-0.1.2.tgz#45820c8d29353c480c0219920db95ba075396438"
@ -42,7 +58,19 @@
resolved "https://registry.yarnpkg.com/@promistream/is-end-of-stream/-/is-end-of-stream-0.1.1.tgz#7f84e630c9e49a92739df6a8c574eff99dd4c09d"
integrity sha512-GZn7W0wrUen7kkgWCcwFFgr0g/ftfuddnuK/Tp0MLWCCJA4hyAboglCZP0JzEJdi34gClEP8lCfDwGekw18LHg==
"@promistream/pipe@^0.1.1":
"@promistream/map@^0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@promistream/map/-/map-0.1.1.tgz#2f771372e5d1dd12f41b6efd57874014d406f123"
integrity sha512-ggyNqWlvNXVY9Gf/pLUgbHROK8mEqu46hbpJftmN9etPr724YPhL+vxA7+9b6bBmTLAU1Tw4Th3BWG5EHVBn1g==
dependencies:
"@promistream/propagate-abort" "^0.1.2"
"@promistream/propagate-peek" "^0.1.0"
"@validatem/core" "^0.3.12"
"@validatem/is-function" "^0.1.0"
"@validatem/required" "^0.1.1"
bluebird "^3.5.4"
"@promistream/pipe@^0.1.1", "@promistream/pipe@^0.1.4":
version "0.1.4"
resolved "https://registry.yarnpkg.com/@promistream/pipe/-/pipe-0.1.4.tgz#ef05fe582a33768c7eb56ad20635e1b7b48ac95b"
integrity sha512-4js6lhu/aTNEMosIBFcCz8Rkxc1S2V4zzI2QvZp9HqglhL5UTuxnv5VbU2ZlPFAFVID1aJOurZ8KdiVagHfOCw==
@ -66,6 +94,14 @@
resolved "https://registry.yarnpkg.com/@promistream/propagate-peek/-/propagate-peek-0.1.1.tgz#c7dd69efcd894c408d7a3e9713b6a9036f70a501"
integrity sha512-4xfkSmtPQzlvL4+KCquPHX7sPXiAACGJac/y7fB3Sv6ZKXAT/cjTfms1nEjlDGn1nroN0MzReBza2HnpF59deg==
"@promistream/range-numbers@^0.1.2":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@promistream/range-numbers/-/range-numbers-0.1.2.tgz#2e5bbe012338eb238ee7ba469cde3ecb8a135239"
integrity sha512-yoCstn6vYhGjl0swIspyVUck3N/X8B97yODcbrCd2sqaFJoLClepIW9Fz24lZ26PHQc6pZTUrubrw+Fc7Dcvng==
dependencies:
"@promistream/end-of-stream" "^0.1.0"
"@promistream/simple-source" "^0.1.0"
"@promistream/simple-sink@^0.1.0":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@promistream/simple-sink/-/simple-sink-0.1.1.tgz#e3808179102ffe4bc10d70d681f19c649e1f3811"
@ -82,7 +118,7 @@
"@validatem/wrap-value-as-option" "^0.1.0"
bluebird "^3.5.4"
"@promistream/simple-source@^0.1.1":
"@promistream/simple-source@^0.1.0", "@promistream/simple-source@^0.1.1":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@promistream/simple-source/-/simple-source-0.1.3.tgz#8139ed088f8249eb9a93287fc04213008325cf06"
integrity sha512-rmpEW0Ec/9Ajrgnx0FHV+mYk4uZ+X3tRhACexUjeal6Jxgzp1oITES59+y2FZA86/a7VPCaadXBA6sWuRfcc3w==
@ -144,7 +180,7 @@
resolved "https://registry.yarnpkg.com/@validatem/combinator/-/combinator-0.1.2.tgz#eab893d55f1643b9c6857eaf6ff7ed2a728e89ff"
integrity sha512-vE8t1tNXknmN62FlN6LxQmA2c6TwVKZ+fl/Wit3H2unFdOhu7SZj2kRPGjAXdK/ARh/3svYfUBeD75pea0j1Sw==
"@validatem/core@^0.3.10", "@validatem/core@^0.3.15":
"@validatem/core@^0.3.10", "@validatem/core@^0.3.11", "@validatem/core@^0.3.12", "@validatem/core@^0.3.15":
version "0.3.15"
resolved "https://registry.yarnpkg.com/@validatem/core/-/core-0.3.15.tgz#645a0734dbc6efa3a5c39c62c5f2d8fa773f89f3"
integrity sha512-4nBLGzgpPrPsZ5DDXDXwL5p+GUEvpAFt6I3/YUHoah+ckYmKNh9qwmWKkFZHxJVdRrTewGFRj0FPw5fqje1yxA==
@ -170,32 +206,6 @@
supports-color "^7.1.0"
syncpipe "^1.0.0"
"@validatem/core@^0.3.11", "@validatem/core@^0.3.12":
version "0.3.12"
resolved "https://registry.yarnpkg.com/@validatem/core/-/core-0.3.12.tgz#e4e8a566850571bf55412862e88a3b06e75c8072"
integrity sha512-ngrFk6PT/pPZntpleG6q55SByongNxRk7wJhUiCihyv4yqIqqG+bNGH4wb6yW33IHefreWxkkJ53yM1Yj9srNA==
dependencies:
"@validatem/annotate-errors" "^0.1.2"
"@validatem/any-property" "^0.1.0"
"@validatem/error" "^1.0.0"
"@validatem/match-validation-error" "^0.1.0"
"@validatem/match-versioned-special" "^0.1.0"
"@validatem/match-virtual-property" "^0.1.0"
"@validatem/normalize-rules" "^0.1.0"
"@validatem/required" "^0.1.0"
"@validatem/validation-result" "^0.1.1"
"@validatem/virtual-property" "^0.1.0"
as-expression "^1.0.0"
assure-array "^1.0.0"
create-error "^0.3.1"
default-value "^1.0.0"
execall "^2.0.0"
flatten "^1.0.3"
indent-string "^4.0.0"
is-arguments "^1.0.4"
supports-color "^7.1.0"
syncpipe "^1.0.0"
"@validatem/default-to@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@validatem/default-to/-/default-to-0.1.0.tgz#62766a3ca24d2f61a96c713bcb629a5b3c6427c5"
@ -460,6 +470,13 @@ create-error@^0.3.1:
resolved "https://registry.yarnpkg.com/create-error/-/create-error-0.3.1.tgz#69810245a629e654432bf04377360003a5351a23"
integrity sha1-aYECRaYp5lRDK/BDdzYAA6U1GiM=
debug@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
dependencies:
ms "2.1.2"
default-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/default-value/-/default-value-1.0.0.tgz#8c6f52a5a1193fe78fdc9f86eb71d16c9757c83a"
@ -559,9 +576,11 @@ indent-string@^4.0.0:
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
is-arguments@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3"
integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9"
integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==
dependencies:
call-bind "^1.0.0"
is-boolean-object@^1.0.1:
version "1.1.0"
@ -571,9 +590,9 @@ is-boolean-object@^1.0.1:
call-bind "^1.0.0"
is-callable@^1.1.5:
version "1.2.0"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb"
integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==
version "1.2.3"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e"
integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==
is-plain-obj@^2.1.0:
version "2.1.0"
@ -595,6 +614,30 @@ is.object@^1.0.0:
resolved "https://registry.yarnpkg.com/is.object/-/is.object-1.0.0.tgz#e4f4117e9f083b35c8df5cf817ea3efb0452fdfa"
integrity sha1-5PQRfp8IOzXI31z4F+o++wRS/fo=
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
p-event@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5"
integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==
dependencies:
p-timeout "^3.1.0"
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
p-timeout@^3.1.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe"
integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==
dependencies:
p-finally "^1.0.0"
split-filter-n@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/split-filter-n/-/split-filter-n-1.1.2.tgz#268be1ec9c4d93dfb27b030c06165ac1b6f70f66"
@ -613,9 +656,9 @@ supports-color@^5.3.0:
has-flag "^3.0.0"
supports-color@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1"
integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==
version "7.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
dependencies:
has-flag "^4.0.0"


Loading…
Cancel
Save