{"id":20181780,"url":"https://github.com/nichoth/pull-stream-util","last_synced_at":"2025-09-13T21:37:03.450Z","repository":{"id":77400157,"uuid":"105805690","full_name":"nichoth/pull-stream-util","owner":"nichoth","description":"Helpers for working with pull streams","archived":false,"fork":false,"pushed_at":"2018-09-14T18:31:48.000Z","size":54,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-13T20:22:55.660Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/nichoth/pull-stream-util#readme","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nichoth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-10-04T18:52:06.000Z","updated_at":"2022-01-24T22:16:28.000Z","dependencies_parsed_at":"2023-05-29T03:15:25.627Z","dependency_job_id":null,"html_url":"https://github.com/nichoth/pull-stream-util","commit_stats":{"total_commits":49,"total_committers":1,"mean_commits":49.0,"dds":0.0,"last_synced_commit":"4b0436c9f7f8bdf9452628d78a706be9a057d7f0"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Fpull-stream-util","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Fpull-stream-util/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Fpull-stream-util/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichoth%2Fpull-stream-util/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nichoth","download_url":"https://codeload.github.com/nichoth/pull-stream-util/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241616699,"owners_count":19991543,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T02:36:42.876Z","updated_at":"2025-03-03T06:12:30.721Z","avatar_url":"https://github.com/nichoth.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pull stream util\n\nHelpers for working with pull streams \n\n* [from event](#from-event)\n* [from emitter](#from-emitter)\n* [mux](#mux)\n* [broadcast](#broadcast)\n* [by key](#by-key)\n* [http](#http)\n* [http data](#http-data)\n* [from cb](#from-cb)\n\n-----------------------------\n\n* cat\n* chain\n* combine latest\n* join\n* many\n* notify\n* sample\n* scan\n\n## install\n\n    npm install pull-stream-util\n\n\n## examples\n\n### from event\n\nCreate a stream from a single node style event\n\n```js\nvar S = require('pull-stream')\nvar test = require('tape')\nvar EE = require('events').EventEmitter\nvar FromEvent = require('../from-event')\n\ntest('from event', function (assert) {\n    assert.plan(4)\n    var bus = new EE()\n    var fooStream = FromEvent('foo', bus)\n\n    // this event will be buffered and emitted when the stream is drained\n    bus.emit('foo', 'hello')\n\n    S(\n        fooStream,\n        S.through(console.log.bind(console)),\n        S.collect(function (err, res) {\n            assert.equal(err, null)\n            assert.deepEqual(res, ['hello', 'world'])\n        })\n    )\n\n    bus.emit('foo', 'world')\n    bus.on('removeListener', function (fn) {\n        assert.pass('should remove listener on stream end')\n    })\n\n    // end the stream and remove the listener from the event emitter\n    fooStream.end()\n\n    // ------ curry -------------\n    var barStream = FromEvent('bar')\n    S(\n        barStream(bus),\n        S.through(console.log.bind(console)),\n        S.drain(function (ev) {\n            assert.deepEqual(ev, 'bar data')\n        })\n    )\n    bus.emit('bar', 'bar data')\n})\n\n\n```\n\n\n### from emitter\n\nTake an event emitter and return a stream of it's events \n\n```js\nvar S = require('pull-stream')\nvar FromEmitter = require('../from-emitter')\nvar EE = require('events').EventEmitter\n\nvar bus = new EE()\nvar streams = FromEmitter(['foo', 'bar', 'baz'], bus)\n\nS( streams.foo(), S.log() )\n\nbus.emit('foo', 'this is the foos')\n\n// all events namespaced by key\nS( streams(), S.drain(console.log.bind(console, 'muxed events')) )\n\nbus.emit('foo', 'foo event')\nbus.emit('bar', 'bar event')\nbus.emit('baz', 'baz event')\n\n// ---------------------------------------------\n// this is the foos\n// foo event\n// muxed events [ 'foo', 'foo event' ]\n// muxed events [ 'bar', 'bar event' ]\n// muxed events [ 'baz', 'baz event' ]\n```\n\n\n### mux\n\nTake an object of streams and return a single stream of their values,\nnamespaced by key \n\n```js\nvar S = require('pull-stream')\nvar mux = require('../mux')\n\nvar streams = {\n    foo: S.values(['foo1', 'foo2']),\n    bar: S.values(['bar1', 'bar2'])\n}\n\nS(\n    mux(streams),\n    S.log()\n)\n\n// ---------------------\n// [ 'foo', 'foo1' ]\n// [ 'bar', 'bar1' ]\n// [ 'foo', 'foo2' ]\n// [ 'bar', 'bar2' ]\n\n\nvar pair = mux.namespace('type', 'data')\nconsole.log(pair)  // [ 'type', 'data' ]\nconsole.log(mux.namespace.type(pair))  // 'type'\nconsole.log(mux.namespace.data(pair))  // 'data'\n```\n\n### broadcast\n\nTake a source stream and pipe it to multiple subscribers\n\n```js\n\nvar S = require('pull-stream')\nvar broadcast = require('../broadcast')\nvar assert = require('assert')\n\n// source *must* be async, or else it will drain before we subscribe\nvar source = S(\n    S.values([1,2,3]),\n    S.asyncMap((n, cb) =\u003e process.nextTick(cb.bind(null, null, n)))\n)\n\n// take a normal source, return a function that returns a clone of\n// the source\nvar _source = broadcast(source)\n\nS( _source(), S.log() )\nS( _source(), S.map(n =\u003e n + 'a'), S.log(function onEnd () {\n    doObject()\n}) )\n\n// -------------------------------\n// 1\n// 1a\n// 2\n// 2a\n// 3\n// 3a\n\nS( _source(), S.collect(function (err, res) {\n    assert(!err)\n    assert.deepEqual(res, [1,2,3])\n}) )\n\n\nfunction doObject () {\n    var streams = {\n        a: S(\n            S.values(['1aa','2aa','3aa']),\n            S.asyncMap((n, cb) =\u003e process.nextTick(cb.bind(null, null, n)))\n        ),\n        b: S(\n            S.values(['1bb','2bb','3bb']),\n            S.asyncMap((n, cb) =\u003e process.nextTick(cb.bind(null, null, n)))\n        )\n    }\n\n    // pass in an object of streams\n    // return a function that creates an object of clones\n    var createStreams = broadcast(streams)\n    var _streams = createStreams()\n    S( _streams.a, S.collect(function (err, res) {\n        assert(!err)\n        assert.deepEqual(res, [ '1aa', '2aa', '3aa' ])\n    }) )\n    S( _streams.b, S.collect(function (err, res) {\n        assert(!err)\n        assert.deepEqual(res, [ '1bb', '2bb', '3bb' ])\n    }) )\n\n    // --------------------------------\n    // 1aa\n    // 1bb\n    // 2aa\n    // 2bb\n    // 3aa\n    // 3bb\n}\n```\n\n### by key\n\nPipe an object of sources to an object of sinks\n\n```js\nvar S = require('pull-stream')\nvar SS = require('../by-key')\n\nvar sources = {\n    foo: S.values(['foo1', 'foo2', 'foo3']),\n    bar: S.values(['bar1', 'bar2', 'bar3'])\n}\n\nvar sinks = {\n    foo: S.log(),\n    bar: S.log()\n}\n\nSS(sources, sinks)\n\n// ------------------------\n// foo1\n// foo2\n// foo3\n// bar1\n// bar2\n// bar3\n```\n\n### http\n\nCreate streams of http events from objects of request data\n\n```js\nvar S = require('pull-stream')\nvar createServer = require('http').createServer\nvar HTTPStream = require('../http')\nvar HTTPData = require('../http-data')\nvar assert = require('assert')\n\n// xhr args\nvar RequestData = HTTPData({\n    url: 'http://localhost:8000',\n    headers: { foo: 'bar' },\n    body: { test: 'test' },\n    method: 'POST',\n    json: true\n})\n\n// path and request body\nvar requestData = RequestData(['foo'], { bar: 'baz' })\n\nvar server = createServer(function onRequest (req, res) {\n    assert.equal(req.headers.foo, 'bar')\n    assert.equal(req.url, '/foo')\n\n    var data = ''\n    req.on('data', function (d) {\n        data += d\n    })\n    req.on('end', function () {\n        assert.deepEqual(JSON.parse(data), {\n            test: 'test',\n            bar: 'baz'\n        })\n    })\n\n    res.end(JSON.stringify({ hello: 'world' }))\n})\n\nserver.listen(8000, function () {\n    S(\n        HTTPStream(requestData),\n        S.collect(function (err, res) {\n            var resData = res.map(function (ev) {\n                return {\n                    type: ev.type,\n                    reqBody: ev.req.body,\n                    body: ev.body\n                }\n            })\n\n            assert.deepEqual(resData, [\n                {\n                    type: 'start',\n                    reqBody: { test: 'test', bar: 'baz' },\n                    body: undefined\n                },\n                {\n                    type: 'resolve',\n                    reqBody: { test: 'test', bar: 'baz' },\n                    body: { hello: 'world' }\n                }\n            ])\n\n            console.log('http stream', err, resData)\n            server.close()\n        })\n    )\n})\n```\n\n### http data\n\nHelper for creating request data\n\n```js\nvar HttpRequest = require('../http-data')\nvar assert = require('assert')\n\n// take this data and return a new function\nvar RequestData = HttpRequest({\n    url: 'http://localhost:8000',\n    method: 'POST',\n    headers: { foo: 'bar' },\n    body: { a: 'b' },\n    json: true\n})\n\n// merge this argument with the request body from above, \n// return new request object\nvar data = RequestData({ test: 'test' })\nconsole.log(data)\nassert.deepEqual(data, {\n    url: 'http://localhost:8000',\n    method: 'POST',\n    headers: { foo: 'bar' },\n    body: { a: 'b', test: 'test' },\n    json: true\n})\n\n// pass an array to add path segments to the `url` key,\n// return a new function\nvar FooRequest = RequestData(['foo'])\n\n// add body data, return request data\nvar fooData = FooRequest({ hello: 'world' })\nconsole.log(fooData)\nassert.deepEqual(fooData, {\n    url: 'http://localhost:8000/foo',\n    method: 'POST',\n    headers: { foo: 'bar' },\n    body: { a: 'b', hello: 'world' },\n    json: true\n})\n```\n\n\n### from cb\n\nTake an async (node style) function, and return a function that returns streams of http events, just like the http request stream in this module.\n\n```js\nvar assert = require('assert')\nvar fromCb = require('../http/from-cb')\nvar S = require('pull-stream')\n\nfunction echo (data, cb) {\n    process.nextTick(cb.bind(null, null, data))\n}\n\nS(\n    fromCb(echo)('hello'),\n    S.collect(function (err, res) {\n        console.log(res)\n        assert.deepEqual(res, [\n            { type: 'start', req: 'hello' },\n            { type: 'resolve', req: 'hello', res: 'hello', body: undefined }\n        ])\n    })\n)\n```\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnichoth%2Fpull-stream-util","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnichoth%2Fpull-stream-util","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnichoth%2Fpull-stream-util/lists"}