commit
d570e44ddc
6 changed files with 1411 additions and 0 deletions
@ -0,0 +1,3 @@ |
|||
{ |
|||
"extends": "@joepie91/eslint-config" |
|||
} |
@ -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" |
|||
} |
|||
} |
File diff suppressed because it is too large
Loading…
Reference in new issue