{"id":22612098,"url":"https://github.com/pshev/stream-lite","last_synced_at":"2025-04-11T08:53:55.748Z","repository":{"id":57372005,"uuid":"86351656","full_name":"pshev/stream-lite","owner":"pshev","description":"⛲️ A minimalistic and modular functional reactive programming library with familiar interface and tiny footprint.","archived":false,"fork":false,"pushed_at":"2018-03-07T20:53:02.000Z","size":286,"stargazers_count":6,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-25T06:22:55.404Z","etag":null,"topics":["async-programming","flow-control","javascript","observable","reactive-programming","stream","streams"],"latest_commit_sha":null,"homepage":"","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/pshev.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}},"created_at":"2017-03-27T15:23:44.000Z","updated_at":"2020-05-19T03:11:04.000Z","dependencies_parsed_at":"2022-08-30T14:52:13.803Z","dependency_job_id":null,"html_url":"https://github.com/pshev/stream-lite","commit_stats":null,"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pshev%2Fstream-lite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pshev%2Fstream-lite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pshev%2Fstream-lite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pshev%2Fstream-lite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pshev","download_url":"https://codeload.github.com/pshev/stream-lite/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248363381,"owners_count":21091343,"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":["async-programming","flow-control","javascript","observable","reactive-programming","stream","streams"],"created_at":"2024-12-08T17:09:55.668Z","updated_at":"2025-04-11T08:53:55.707Z","avatar_url":"https://github.com/pshev.png","language":"JavaScript","readme":"\u003cp align=\"center\" style=\"margin-top: 15px\"\u003e\n  \u003cimg alt=\"stream-lite\" title=\"Stream lite\" src=\"https://cldup.com/KjEcd2jTaI.png\" width=\"550\"\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eThe power of streams, without the overhead.\u003c/strong\u003e\n  \u003cbr\u003e\n  Extremely small and simple reactive programming library.\n  \u003cbr\u003e\n  \u003cbr\u003e\n  \u003ca href=\"http://npm.im/stream-lite\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/stream-lite.svg?style=flat-square\" alt=\"npm\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://travis-ci.org/pshev/stream-lite\"\u003e\u003cimg src=\"https://img.shields.io/travis/pshev/stream-lite.svg?style=flat-square\" alt=\"travis build\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://david-dm.org/pshev/stream-lite\"\u003e\u003cimg src=\"https://img.shields.io/david/pshev/stream-lite.svg?style=flat-square\" alt=\"dependencies\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/pshev/stream-lite\"\u003e\u003cimg src=\"https://img.shields.io/codecov/c/github/pshev/stream-lite.svg?style=flat-square\" alt=\"codecov coverage\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/semantic-release/semantic-release\"\u003e\u003cimg src=\"https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square\" alt=\"semantic-release\"\u003e\u003c/a\u003e\n  \u003ca href=\"http://commitizen.github.io/cz-cli/\"\u003e\u003cimg src=\"https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat-square\" alt=\"Commitizen friendly\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## ✨ Features:\n- [Extremely small](#size).\n- Familiar interface (mostly replicating RxJS's API)\n- Modular. Add as little or as much functionality as you want\n- Lazy streams (only active once subscribed to)\n- Only [\"hot\"](https://medium.com/@benlesh/hot-vs-cold-observables-f8094ed53339) streams\n- [Pipeable operators](https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md) support\n- [Fantasy Observable](https://github.com/staltz/fantasy-observable) compliant\n- More than 50 operators and factories available\n\n## 🔧 Installation\n\nAssuming you use [npm](https://www.npmjs.com/) as your package manager:\n```text\nnpm install --save stream-lite\n```\nThis package includes both a [CommonJS](https://nodejs.org/docs/latest/api/modules.html) and [ES2015](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) based modules.\u003cbr /\u003e\nYou can use them from [Node](https://nodejs.org/en/) environment or if you are building for the browser you can use a module bundler like [Webpack](https://webpack.js.org/), [Browserify](http://browserify.org/), or [Rollup](http://rollupjs.org).\u003cbr/\u003e\nIf you want to experiment and play around with Amnis without a module bundler or you don't use one - that's OK.\nThe `stream-lite` npm package includes precompiled production and development UMD builds in the `umd` folder. \nYou can just drop a UMD build as a `\u003cscript\u003e` tag on a page. The UMD builds make `stream-lite` available as a `window.stream` global variable and include all the functionality.\n```html\n\u003cscript type=\"application/javascript\" src=\"https://unpkg.com/stream-lite\"\u003e\u003c/script\u003e\n```\n\n## 📦🔨 Import and Usage\nThe following guide assumes you use ES2015+ but you don't have to.\u003cbr /\u003e\nThere are a few different ways of importing the functionality that you need.\n\nTo import the entire set of functionality:\n```js\nimport Stream from 'stream-lite'\nimport 'stream/add/all'\n\nStream\n  .of(1,2,3)\n  .map(x =\u003e x * 2)\n  .subscribe(x =\u003e console.log(x))\n```\nHowever the `stream-lite` module encourages shipping only the scripts that you will actually use. \u003cbr/\u003e\nOne way of doing that is to add to Stream's prototype only the methods you actually need:\n```js\nimport Stream from 'stream-lite'\nimport 'stream-lite/add/statics/of'\nimport 'stream-lite/add/operators/map'\n\nStream\n  .of(1,2,3)\n  .map(x =\u003e x * 2)\n  .subscribe(x =\u003e console.log(x))\n```\nTo not add static methods to Stream, you can import them as pure functions:\n```js\nimport {of} from 'stream-lite/statics'\nimport 'stream-lite/add/operators/map'\n\nof(1,2,3)\n  .map(x =\u003e x * 2)\n  .subscribe(x =\u003e console.log(x))\n```\nTo take this one step further and avoid patching the Stream's prototype altogether, you can use `pipeable operators`.\u003cbr/\u003e\nIf you are not familiar with pipeable operators you can learn about them [here](https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md).\u003cbr/\u003e\n```js\nimport {of} from 'stream-lite/statics'\nimport {map, filter} from 'stream-lite/operators'\n\nof(1,2,3).pipe(\n  filter(x =\u003e x % 2 === 0),\n  map(x =\u003e x * 2)\n)\n  .subscribe(x =\u003e console.log(x))\n```\nThe `stream-lite` core also provides a pipeable `subscribe` for your convenience.\u003cbr/\u003e \nSo you can bring the subscribe method inside your pipe and write the code above like so:\n```js\nimport {subscribe} from 'stream-lite'\nimport {of} from 'stream-lite/statics'\nimport {map, filter} from 'stream-lite/operators'\n\nof(1,2,3).pipe(\n  filter(x =\u003e x % 2 === 0),\n  map(x =\u003e x * 2),\n  subscribe(x =\u003e console.log(x))\n)\n```\nOr if you use the proposed JavaScript [`pipe operator`](https://github.com/tc39/proposal-pipeline-operator):\n```js\nimport {subscribe} from 'stream-lite'\nimport {of} from 'stream-lite/statics'\nimport {map, filter} from 'stream-lite/operators'\n\nof(1,2,3)\n  |\u003e filter(x =\u003e x % 2 === 0)\n  |\u003e map(x =\u003e x * 2)\n  |\u003e subscribe(x =\u003e console.log(x))\n```\n\u003e Please note: This additional syntax requires [transpiler support](https://www.npmjs.com/package/babel-plugin-transform-pipeline-operator).\n\n## \u003ca id=\"size\"\u003e\u003c/a\u003e 🎉 Size\nThe `stream-lite` package is built to bring as little overhead to your project as possible.\u003cbr/\u003e\n##### core\nThe core of the library includes the `create` function and a few prototype methods, like `subscribe` and `pipe`. \u003cbr/\u003e\nThis core is **~1KB** gzipped.\n\u003cbr/\u003e\n##### common\nA common usage will probably include around 15 most common methods and operators, which should bring about **1.8KB** to your app if you use tree-shaking. 😍\n\u003cbr/\u003e\n##### everything\nIf for some reason you feel the need to import all available operators and factories, that option is also available.\u003cbr/\u003e\nThat includes more than 50 operators and factories, and will make your app heavier by about **3.5KB** gzipped.\n\n\n\n## 📋 API\n\nThe vast majority of factories and operators are too similar to the API of RxJS, so most links will point you to RxJS documentation.\u003cbr/\u003e\nHowever there are some that don't exist in RxJS or ones with a different API. Those are marked with an astrix (*) and their documentation you will find below.\u003cbr/\u003e\nOperators marked with 🚩 are also available as statics.\n\n#### Factories\n- [`create`](#create)*\n- [`of`](https://www.learnrxjs.io/operators/creation/of.html)\n- [`empty`](https://www.learnrxjs.io/operators/creation/empty.html)\n- [`never`](https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/never.md)\n- [`error`](#error)*\n- [`fromArray`](#fromArray)*\n- [`fromObservable`](#fromObservable)*\n- [`fromEvent`](https://www.learnrxjs.io/operators/creation/fromevent.html)\n- [`fromPromise`](https://www.learnrxjs.io/operators/creation/frompromise.html)\n- [`interval`](https://www.learnrxjs.io/operators/creation/interval.html)\n- [`range`](https://www.learnrxjs.io/operators/creation/range.html)\n\n#### Methods and Operators\n- [`subscribe`](#subscribe)*\n- [`map`](https://www.learnrxjs.io/operators/transformation/map.html)\n- [`mapTo`](https://www.learnrxjs.io/operators/transformation/mapto.html)\n- [`filter`](https://www.learnrxjs.io/operators/filtering/filter.html)\n- [`scan`](#scan)*\n- [`pluck`](https://www.learnrxjs.io/operators/transformation/pluck.html)\n- [`single`](https://www.learnrxjs.io/operators/filtering/single.html)\n- [`first`](https://www.learnrxjs.io/operators/filtering/first.html)\n- [`last`](https://www.learnrxjs.io/operators/filtering/last.html)\n- [`every`](https://www.learnrxjs.io/operators/conditional/every.html)\n- [`defaultIfEmpty`](https://www.learnrxjs.io/operators/conditional/defaultifempty.html)\n- [`tap`](https://www.learnrxjs.io/operators/utility/do.html)\n- [`pairwise`](https://www.learnrxjs.io/operators/combination/pairwise.html)\n- [`delay`](https://www.learnrxjs.io/operators/utility/delay.html)\n- [`buffer`](https://www.learnrxjs.io/operators/transformation/buffer.html)\n- [`bufferWhen`](https://www.learnrxjs.io/operators/transformation/bufferwhen.html)\n- [`bufferCount`](https://www.learnrxjs.io/operators/transformation/buffercount.html)\n- [`debounce`](https://www.learnrxjs.io/operators/filtering/debounce.html)\n- [`debounceTime`](https://www.learnrxjs.io/operators/filtering/debouncetime.html)\n- [`throttle`](https://www.learnrxjs.io/operators/filtering/throttle.html)\n- [`throttleTime`](https://www.learnrxjs.io/operators/filtering/throttletime.html)\n- [`distinctUntilChanged`](https://www.learnrxjs.io/operators/filtering/distinctuntilchanged.html)\n- [`mergeMap`](#flatMap)*\n- [`flatMap`](#flatMap)*\n- [`switchMap`](https://www.learnrxjs.io/operators/transformation/switchmap.html)\n- [`concatMap`](https://www.learnrxjs.io/operators/transformation/concatmap.html)\n- [`concatMapTo`](https://www.learnrxjs.io/operators/transformation/concatmapto.html)\n- [`catchError`](https://www.learnrxjs.io/operators/error_handling/catch.html)\n- [`partition`](https://www.learnrxjs.io/operators/transformation/partition.html)\n- [`concat`](https://www.learnrxjs.io/operators/combination/concat.html) 🚩\n- [`merge`](https://www.learnrxjs.io/operators/combination/merge.html) 🚩\n- [`combine`](#combine)* 🚩\n- [`combineLatest`](https://www.learnrxjs.io/operators/combination/combinelatest.html) 🚩\n- [`startWith`](https://www.learnrxjs.io/operators/combination/startwith.html)\n- [`skip`](https://www.learnrxjs.io/operators/filtering/skip.html)\n- [`skipUntil`](https://www.learnrxjs.io/operators/filtering/skipuntil.html)\n- [`skipWhile`](https://www.learnrxjs.io/operators/filtering/skipwhile.html)\n- [`ignoreElements`](https://www.learnrxjs.io/operators/filtering/ignoreelements.html)\n- [`take`](https://www.learnrxjs.io/operators/filtering/take.html)\n- [`takeUntil`](https://www.learnrxjs.io/operators/filtering/takeuntil.html)\n- [`takeWhile`](https://www.learnrxjs.io/operators/filtering/takewhile.html)\n- [`withLatestFrom`](https://www.learnrxjs.io/operators/combination/withlatestfrom.html)\n- [`withValue`](#withValue)*\n\n## \n\n### \u003ca id=\"subscribe\"\u003e\u003c/a\u003e subscribe\n\nYou can call it in two different ways:\n\u003cbr/\u003e\nEither passing three callbacks in this following order: `next`, `error`, `complete`.\n```js\nimport {of} from 'stream-lite/statics'\n\nof(1, 2, 3).subscribe(\n  x =\u003e console.log(x),\n  err =\u003e console.error(\"There's an error!\", err),\n  () =\u003e console.log(\"We're done\")\n)\n```\nOr passing a subscription object with the `next`, `error`, `complete` functions as keys.\n```js\nimport {of} from 'stream-lite/statics'\n\nof(1, 2, 3).subscribe({\n  next: x =\u003e console.log(x),\n  error: err =\u003e console.error(\"There's an error!\", err),\n  complete: () =\u003e console.log(\"We're done\")\n})\n```\nYou can also use a pipeable version of `subscribe`: \n```js\nimport {subscribe} from 'stream-lite'\nimport {of} from 'stream-lite/statics'\nimport {map} from 'stream-lite/operators'\n\nof(1,2,3).pipe(\n  map(x =\u003e x * 2),\n  subscribe(x =\u003e console.log(x))\n)\n```\n\n### \u003ca id=\"create\"\u003e\u003c/a\u003e create\n\nThis is the only thing that is included in the core object exported from `stream-lite`.\nMost use-cases for creating a stream involve calling other factory functions, like `fromEvent` or `fromPromise`, etc.\u003cbr/\u003e\nThose are all abstractions on top of the `create` factory. Usually you want to use those.\nHowever, sometimes you may need more control and the way you achieve that in `stream-lite` is different from `RxJS`.\n\n#### Creating a stream with a producer\n\nA Producer is a simple JavaScript object with `start` and `stop` functions. `start` function will be called when the first subscriber subscribes to it.\n`stop` function will be called when the last subscriber unsubscribes or the stream completes or it errors.\nHere is an example of a producer that is used inside the `interval` factory (except with `step` parameter hard-coded):\n```js\nconst producer = {\n  counter: 0,\n  id: 0,\n  start: function(consumer) {\n    this.id = setInterval(() =\u003e consumer.next(this.counter++), 1000)\n  },\n  stop: function() {\n    clearInterval(this.id)\n  }\n}\n```\nArmed with that producer we can now easily create a new stream:\n\u003cbr/\u003e\n```js\nimport {create} from 'stream-lite'\n\nconst myIntervalStream = create(producer) \n```\nWhen subscribed to it will start emitting values every second.\n\n#### Creating a stream without a producer\n\nSometimes you just want to create an empty stream and manually push values into it.\nYou can achieve this functionality by calling `create` with no parameters:\n\u003cbr/\u003e\n```js\nimport {create} from 'stream-lite'\n\nconst manuallyControlledStream = create() \n\nmanuallyControlledStream.subscribe(x =\u003e console.log(x))\n\nmanuallyControlledStream.next(1)\nmanuallyControlledStream.next(2)\n// logs 1, 2\n```\nThis is sort of similar to how you would use RxJs's Subject.\n\n### \u003ca id=\"fromArray\"\u003e\u003c/a\u003e fromArray\n\nEquivalent to calling RxJS's [`from`](https://www.learnrxjs.io/operators/creation/from.html) with an array.\n\n\n### \u003ca id=\"fromObservable\"\u003e\u003c/a\u003e fromObservable\n\nEquivalent to calling RxJS's [`from`](https://www.learnrxjs.io/operators/creation/from.html) with an observable.\n\n### \u003ca id=\"error\"\u003e\u003c/a\u003e error\n\nSame as RxJS's [`_throw`](https://www.learnrxjs.io/operators/creation/throw.html) but with a friendlier name.\n\n### \u003ca id=\"scan\"\u003e\u003c/a\u003e scan\n\nMostly equivalent to calling RxJS's [`scan`](https://www.learnrxjs.io/operators/transformation/scan.html) except currently it requires an initial value parameter.\n\n### \u003ca id=\"flatMap\"\u003e\u003c/a\u003e flatMap\n\nAlias: `mergeMap`.\n\nEquivalent to RxJS's [`flatMap`](https://www.learnrxjs.io/operators/transformation/mergemap.html) without the support for an optional 3rd parameter `concurrent`.\n\n### \u003ca id=\"combine\"\u003e\u003c/a\u003e combine\n\nSimply an alias for [`combineLatest`](https://www.learnrxjs.io/operators/combination/combinelatest.html).\n\n### \u003ca id=\"withValue\"\u003e\u003c/a\u003e withValue\n\nAllows to emit an extra parameter in addition to one emitted from source stream.\u003cbr/\u003e\n```js\nimport {subscribe} from 'stream-lite'\nimport {of} from 'stream-lite/statics'\nimport {withValue} from 'stream-lite/operators'\n\nof(4)\n  |\u003e withValue(x =\u003e x / 2)\n  |\u003e subscribe(x =\u003e console.log(x)) // logs [4, 2]\n```\n\n## 🙏 License\nMIT","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpshev%2Fstream-lite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpshev%2Fstream-lite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpshev%2Fstream-lite/lists"}