Initial commit
commit
d570e44ddc
@ -0,0 +1 @@
|
|||||||
|
node_modules
|
@ -0,0 +1,31 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const Promise = require("bluebird");
|
||||||
|
|
||||||
|
const derivedStream = require("./");
|
||||||
|
const pipe = require("@promistream/pipe");
|
||||||
|
const collect = require("@promistream/collect");
|
||||||
|
const rangeNumbers = require("@promistream/range-numbers");
|
||||||
|
|
||||||
|
return Promise.try(() => {
|
||||||
|
let producedStream = pipe([
|
||||||
|
rangeNumbers(0, 10),
|
||||||
|
derivedStream((source) => {
|
||||||
|
/* NOTE: This example doesn't actually do anything *useful*. It
|
||||||
|
only demonstrates the higher-order stream mechanism.
|
||||||
|
Real-world code implementing eg. load-balanced stream forks
|
||||||
|
would probably do something like producing an array of multiple
|
||||||
|
streams here (instead of a single pipeline), and do some
|
||||||
|
internal routing of source values across them. */
|
||||||
|
|
||||||
|
return pipe([
|
||||||
|
source,
|
||||||
|
collect()
|
||||||
|
]);
|
||||||
|
})
|
||||||
|
]).read();
|
||||||
|
|
||||||
|
return producedStream.read();
|
||||||
|
}).then((result) => {
|
||||||
|
console.log(result); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
|
||||||
|
});
|
@ -0,0 +1,58 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const Promise = require("bluebird");
|
||||||
|
const Aborted = require("@promistream/aborted");
|
||||||
|
const EndOfStream = require("@promistream/end-of-stream");
|
||||||
|
const errorChain = require("error-chain");
|
||||||
|
|
||||||
|
const { validateArguments } = require("@validatem/core");
|
||||||
|
const required = require("@validatem/required");
|
||||||
|
const isFunction = require("@validatem/is-function");
|
||||||
|
|
||||||
|
module.exports = function simpleSource(_deriver) {
|
||||||
|
let [ deriver ] = validateArguments(arguments, {
|
||||||
|
deriver: [ required, isFunction ]
|
||||||
|
});
|
||||||
|
|
||||||
|
let hasBeenDerived = false;
|
||||||
|
let errorReason = null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
_promistreamVersion: 0,
|
||||||
|
description: `derived stream`,
|
||||||
|
peek: function peekValue_derivedStream(_source) {
|
||||||
|
// A derived-stream is guaranteed to produce a value; either a new stream, or an EndOfStream, or an Aborted marker
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
read: function produceValue_derivedStream(source) {
|
||||||
|
// TODO: Abstract out the abort handling here and in `abort`? The logic is almost entirely shared between `simple-source` and `derived-stream`.
|
||||||
|
if (errorReason != null) {
|
||||||
|
if (errorReason === true) {
|
||||||
|
throw new Aborted("Stream was aborted");
|
||||||
|
} else if (errorReason instanceof Error) {
|
||||||
|
throw new errorChain.chain(errorReason, Aborted, `Stream was aborted due to error: ${errorReason.message}`);
|
||||||
|
}
|
||||||
|
} else if (hasBeenDerived === true) {
|
||||||
|
throw new EndOfStream;
|
||||||
|
} else {
|
||||||
|
hasBeenDerived = true;
|
||||||
|
return deriver(source);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
abort: function abort_simpleSource(reason, _source) {
|
||||||
|
// NOTE: Even though a `source` is provided, we don't do anything with it; higher-order stream producers should *not* propagate aborts upstream, as a read from such a producer would never constitute a read upstream.
|
||||||
|
return Promise.try(() => { // FIXME: Remove Promise.try here?
|
||||||
|
if (errorReason == null) {
|
||||||
|
if (reason === true || reason instanceof Error) {
|
||||||
|
errorReason = reason;
|
||||||
|
} else {
|
||||||
|
throw new Error("You must specify a reason (either `true` or an Error object) when aborting a stream");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// FIXME: Require this behaviour in the spec? Or is there a composability-related reason to permit/require quietly ignoring this, to make it idempotent? (Duplicate of simple-source)
|
||||||
|
throw new Error(`The stream is already aborted`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "@promistream/derived-stream",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": "http://git.cryto.net/promistream/derived-stream.git",
|
||||||
|
"author": "Sven Slootweg <admin@cryto.net>",
|
||||||
|
"license": "WTFPL OR CC0-1.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@promistream/aborted": "^0.1.1",
|
||||||
|
"@promistream/end-of-stream": "^0.1.1",
|
||||||
|
"@validatem/core": "^0.3.12",
|
||||||
|
"@validatem/is-function": "^0.1.0",
|
||||||
|
"@validatem/required": "^0.1.1",
|
||||||
|
"bluebird": "^3.7.2",
|
||||||
|
"error-chain": "^0.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@joepie91/eslint-config": "^1.1.0",
|
||||||
|
"@promistream/collect": "^0.1.1",
|
||||||
|
"@promistream/pipe": "^0.1.0",
|
||||||
|
"@promistream/range-numbers": "^0.1.2",
|
||||||
|
"eslint": "^7.29.0"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue