{"id":15365936,"url":"https://github.com/andywer/observable-fns","last_synced_at":"2025-08-20T14:31:45.142Z","repository":{"id":37927161,"uuid":"204408725","full_name":"andywer/observable-fns","owner":"andywer","description":"🕵️‍♀️ Light-weight observable implementation and functional utilities in TypeScript","archived":false,"fork":false,"pushed_at":"2023-02-11T10:05:18.000Z","size":240,"stargazers_count":45,"open_issues_count":6,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-09T20:12:47.624Z","etag":null,"topics":["functional-js","observable","observable-fns","reactive-programming","reactive-streams","rxjs","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andywer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2019-08-26T06:18:10.000Z","updated_at":"2024-11-21T13:20:31.000Z","dependencies_parsed_at":"2024-06-18T15:36:52.202Z","dependency_job_id":"61dfa9df-8182-4f48-8976-0c85ff678a61","html_url":"https://github.com/andywer/observable-fns","commit_stats":{"total_commits":66,"total_committers":4,"mean_commits":16.5,"dds":"0.40909090909090906","last_synced_commit":"218008591c335c3b566774b095c683fa427388a5"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andywer%2Fobservable-fns","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andywer%2Fobservable-fns/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andywer%2Fobservable-fns/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andywer%2Fobservable-fns/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andywer","download_url":"https://codeload.github.com/andywer/observable-fns/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230431104,"owners_count":18224655,"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":["functional-js","observable","observable-fns","reactive-programming","reactive-streams","rxjs","typescript"],"created_at":"2024-10-01T13:16:45.075Z","updated_at":"2024-12-19T12:10:09.626Z","avatar_url":"https://github.com/andywer.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  🕵️‍♀️ observable-fns\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://travis-ci.org/andywer/observable-fns\" target=\"_blank\"\u003e\u003cimg alt=\"Build status\" src=\"https://img.shields.io/travis/andywer/observable-fns/master.svg?style=flat-square\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/observable-fns\" target=\"_blank\"\u003e\u003cimg alt=\"npm version\" src=\"https://img.shields.io/npm/v/observable-fns.svg?style=flat-square\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://bundlephobia.com/result?p=observable-fns\" target=\"_blank\"\u003e\u003cimg alt=\"Complete bundle size\" src=\"https://badgen.net/bundlephobia/min/observable-fns\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nLight-weight Observable implementation and common toolbelt functions. Based on [`zen-observable`](https://github.com/zenparsing/zen-observable), re-implemented in TypeScript. Zero dependencies, [tree-shakeable](https://bitsofco.de/what-is-tree-shaking/).\n\nThe aim is to provide a lean Observable implementation with a small footprint that's fit to be used in libraries as an alternative to the huge RxJS.\n\nFind all the provided functions and constructors in the 👉 [API Documentation](./docs/API.md)\n\n\u003cbr\u003e\n\n🧩\u0026nbsp;\u0026nbsp;Composable functional streams\n\n🚀\u0026nbsp;\u0026nbsp;map(), filter() \u0026 friends support async handlers\n\n🔩\u0026nbsp;\u0026nbsp;Based on popular [`zen-observable`](https://github.com/zenparsing/zen-observable), re-implemented in TypeScript\n\n🌳\u0026nbsp;\u0026nbsp;Zero dependencies, [tree-shakeable](https://bitsofco.de/what-is-tree-shaking/)\n\n---\n\n## Installation\n\n```\nnpm install observable-fns\n```\n\n## Observable?\n\nAn observable is basically a stream of asynchronously emitted values that you can subscribe to. In a sense it is to the event emitter what the promise is to the callback.\n\nThe main difference to a promise is that a promise only resolves once, whereas observables can yield values repeatedly. They can also fail with an error, like a promise, and they come with a completion event to indicate that no more values will be send.\n\nFor a quick introduction on how to use observables, check out the [zen-observable readme](https://github.com/zenparsing/zen-observable).\n\n```js\nimport { Observable, multicast } from \"observable-fns\"\n\nfunction subscribeToServerSentEvents(url) {\n  // multicast() will make the observable \"hot\", so multiple\n  // subscribers will share the same event source\n  return multicast(new Observable(observer =\u003e {\n    const eventStream = new EventSource(url)\n\n    eventStream.addEventListener(\"message\", message =\u003e observer.next(message))\n    eventStream.addEventListener(\"error\", error =\u003e observer.error(error))\n\n    return () =\u003e eventStream.close()\n  }))\n}\n\nsubscribeToServerSentEvents(\"http://localhost:3000/events\")\n  .filter(event =\u003e !event.isStale)\n  .subscribe(event =\u003e console.log(\"Server sent event:\", event))\n```\n\n## Usage\n\nYou can import everything you need directly from the package:\n\n```js\nimport { Observable, flatMap } from \"observable-fns\"\n```\n\nIf you write front-end code and care about bundle size, you can either depend on tree-shaking or explicitly import just the parts that you need:\n\n```js\nimport Observable from \"observable-fns/observable\"\nimport flatMap from \"observable-fns/flatMap\"\n```\n\nFunctions like `filter()`, `flatMap()`, `map()` accept asynchronous handlers – this can be a big win compared to the usual methods on `Observable.prototype` that only work with synchronous handlers.\n\nThose functions will also make sure that the values are consistently emitted in the same order as the input observable emitted them.\n\n```js\nimport { Observable, filter } from \"observable-fns\"\n\nconst existingGitHubUsersObservable = Observable.from([\"andywer\", \"bcdef\", \"charlie\"])\n  .pipe(\n    filter(async name =\u003e {\n      const response = await fetch(`https://github.com/${name}`)\n      return response.status === 200\n    })\n  )\n```\n\n## API\n\nSee [docs/API.md](./docs/API.md) for an overview of the full API.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandywer%2Fobservable-fns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandywer%2Fobservable-fns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandywer%2Fobservable-fns/lists"}