{"id":16407028,"url":"https://github.com/ikatsuba/rxnode","last_synced_at":"2025-10-06T16:18:35.522Z","repository":{"id":47599573,"uuid":"305953309","full_name":"IKatsuba/rxnode","owner":"IKatsuba","description":"Rxnode - a small and fast wrapper around the nodejs API using RxJS.","archived":false,"fork":false,"pushed_at":"2024-03-15T23:32:56.000Z","size":1793,"stargazers_count":25,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-17T20:12:55.933Z","etag":null,"topics":["filesystem","fs","http","rxjs","rxnode","rxserver","typescript"],"latest_commit_sha":null,"homepage":"https://rxnode.gitbook.io/docs/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/IKatsuba.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":"contributing.md","funding":null,"license":"license.md","code_of_conduct":"code_of_conduct.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-10-21T08:09:50.000Z","updated_at":"2024-05-25T17:27:20.000Z","dependencies_parsed_at":"2024-10-27T18:24:33.990Z","dependency_job_id":"564b0820-d5d0-402f-9f08-ee17af6ad9b0","html_url":"https://github.com/IKatsuba/rxnode","commit_stats":null,"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IKatsuba%2Frxnode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IKatsuba%2Frxnode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IKatsuba%2Frxnode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IKatsuba%2Frxnode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IKatsuba","download_url":"https://codeload.github.com/IKatsuba/rxnode/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244733549,"owners_count":20501011,"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":["filesystem","fs","http","rxjs","rxnode","rxserver","typescript"],"created_at":"2024-10-11T06:11:51.187Z","updated_at":"2025-10-06T16:18:30.492Z","avatar_url":"https://github.com/IKatsuba.png","language":"TypeScript","readme":"# Rxnode\n\n## Rxnode — reactive nodejs API\n\n![](docs/assets/image%20%281%29.png)\n\nAt the beginning of 2020, my career as a frontend developer turned in an unexpected direction for me. I haven't written a single Angular component in a year. I Replaced Angular with server code and code for the CLI. It was a new and interesting experience for me, but it wasn't easy to solve my usual tasks without RxJS.\n\nLet's look at a simple example of reading and writing a file using the native features of nodejs\n\n```typescript\nimport { readFile, writeFile } from 'fs';\n\nreadFile('src/some-file.js', (error, data) =\u003e {\n  if (error) {\n    console.error(error);\n    return;\n  }\n\n  writeFile('src/some-file.js', data, (error) =\u003e {\n    if (error) {\n      console.error(error);\n      return;\n    }\n\n    console.log('Success!');\n  });\n});\n```\n\nCode with callbacks after Angular seems complicated. First, I translated callbacks to promises.\n\n```typescript\nimport * as fs from 'fs';\nimport { promisify } from 'util';\n\nconst readFile = promisify(fs.readFile);\nconst writeFile = promisify(fs.writeFile);\n\nreadFile('src/some-file.js')\n  .then((data) =\u003e writeFile('src/some-file.js', data))\n  .then(() =\u003e {\n    console.log('Success!');\n  })\n  .cacth(console.error);\n```\n\nI was OK with this solution until I needed to implement several tasks' competitive execution with a limit. RxJS has such an opportunity out of the box. Why would I invent my own algorithm on promises?\n\nThe `promisify` function is replaced by the `bindNodeCallback` function, which RxJS itself supplies.\n\n```typescript\nimport * as fs from 'fs';\nimport { bindNodeCallback, Observable } from 'rxjs';\nimport { mergeMap, switchMap } from 'rxjs/operators';\n\nconst readFile = bindNodeCallback(fs.readFile);\nconst writeFile = bindNodeCallback(fs.writeFile);\n\nlet files: Observable\u003cstring\u003e;\nconst LIMIT = 2;\n\nfiles\n  .pipe(\n    mergeMap(\n      (file) =\u003e someProcessWithFiles(file),\n      LIMIT\n  )\n  .subscribe({\n    complete() {\n      console.log('Complete!');\n    },\n  });\n```\n\nIt quickly became apparent that you need to import and wrap the API in each file or move it to the library at the project level. And when there was more than one such project, I decided to put my developments in separate packages with the `@rxnode` scopes and published [the GitHub code](https://github.com/IKatsuba/rxnode).\n\nThe project is NX Workspace. Each core package from nodejs corresponds to one library in a scope. If you want to use the `fs` package, you import functions with the same names from the`@rxnode/fs` packages.\n\n```typescript\nimport { readFile, writeFile } from '@rxnode/fs';\nimport { switchMap } from 'rxjs/operators';\n\nreadFile('src/some-file.js')\n  .pipe(switchMap((data) =\u003e writeFile('src/some-file.js', data)))\n  .subscribe({\n    complete() {\n      console.log('Complete!');\n    },\n  });\n```\n\nThis is how you can start a simple server.\n\n```typescript\nimport { createServer } from '@rxnode/http';\n\nconst server = createServer();\n\nserver.subscribe(([req, res]) =\u003e {\n  res.writeHead(200, { 'Content-Type': 'text/plain' });\n  res.end('okay');\n});\n\nserver.listen(8080).subscribe();\n```\n\nCurrently, Rxnode contains only 4 packages out of 20 planned. An up-to-date list can be found in the [documentation](https://rxnode.gitbook.io/docs/). We will be glad to receive any help in project development! We need your ideas and your hands!\n\n### About logo\n\nThe Rxnode logo features an [axolotl](https://en.wikipedia.org/wiki/Axolotl). And this is the merit of my wife, for which many thanks to her!\n\nWhile working on the library, she looked at the RxJS logo and asked me, \"Is this an axolotl?\" When I replied negatively, she suggested depicting the axolotl on the Rxnode logo in Node.js shades. So I did!\n\n{% embed url=\"https://medium.com/rxnode/rxnode-reactive-nodejs-api-f32c8e02e295\" %}\n\n## Packages\n\n- [x] [child_process](docs/libs/child-process.md)\n- [ ] cluster\n- [x] [crypto](docs/libs/crypto.md)\n- [ ] dns\n- [ ] events\n- [x] [fs](docs/libs/fs.md)\n- [x] [http](docs/libs/http.md)\n- [ ] http2\n- [ ] https\n- [ ] inspector\n- [ ] net\n- [ ] process\n- [ ] readline\n- [ ] repl\n- [ ] stream\n- [ ] tls\n- [ ] tty\n- [ ] dgram\n- [ ] util\n- [ ] worker_threads\n\n## We are supported by\n\n[![](docs/assets/gitbook.svg)](https://www.gitbook.com/)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fikatsuba%2Frxnode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fikatsuba%2Frxnode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fikatsuba%2Frxnode/lists"}