{"id":26758489,"url":"https://github.com/alessiofrittoli/stream-writer","last_synced_at":"2026-03-01T22:38:49.164Z","repository":{"id":273068002,"uuid":"918334063","full_name":"alessiofrittoli/stream-writer","owner":"alessiofrittoli","description":"Easly push data to a Stream","archived":false,"fork":false,"pushed_at":"2025-12-03T18:07:27.000Z","size":516,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-06T22:53:24.388Z","etag":null,"topics":["nodejs-stream","stream"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/@alessiofrittoli/stream-writer","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/alessiofrittoli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"license.md","code_of_conduct":"CODE_OF_CONDUCT.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["alessiofrittoli"]}},"created_at":"2025-01-17T18:03:31.000Z","updated_at":"2025-12-03T18:07:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"3803630a-d9c0-4cd2-a9d5-f651c896576a","html_url":"https://github.com/alessiofrittoli/stream-writer","commit_stats":null,"previous_names":["alessiofrittoli/stream-writer"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/alessiofrittoli/stream-writer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fstream-writer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fstream-writer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fstream-writer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fstream-writer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alessiofrittoli","download_url":"https://codeload.github.com/alessiofrittoli/stream-writer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fstream-writer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29987517,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T21:06:37.093Z","status":"ssl_error","status_checked_at":"2026-03-01T21:05:45.052Z","response_time":124,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["nodejs-stream","stream"],"created_at":"2025-03-28T16:29:15.326Z","updated_at":"2026-03-01T22:38:49.149Z","avatar_url":"https://github.com/alessiofrittoli.png","language":"TypeScript","funding_links":["https://github.com/sponsors/alessiofrittoli"],"categories":[],"sub_categories":[],"readme":"# Stream Writer 🪶\n\n[![NPM Latest Version][version-badge]][npm-url] [![Coverage Status][coverage-badge]][coverage-url] [![Socket Status][socket-badge]][socket-url] [![NPM Monthly Downloads][downloads-badge]][npm-url] [![Dependencies][deps-badge]][deps-url]\n\n[![GitHub Sponsor][sponsor-badge]][sponsor-url]\n\n[version-badge]: https://img.shields.io/npm/v/%40alessiofrittoli%2Fstream-writer\n[npm-url]: https://npmjs.org/package/%40alessiofrittoli%2Fstream-writer\n[coverage-badge]: https://coveralls.io/repos/github/alessiofrittoli/stream-writer/badge.svg\n[coverage-url]: https://coveralls.io/github/alessiofrittoli/stream-writer\n[socket-badge]: https://socket.dev/api/badge/npm/package/@alessiofrittoli/stream-writer\n[socket-url]: https://socket.dev/npm/package/@alessiofrittoli/stream-writer/overview\n[downloads-badge]: https://img.shields.io/npm/dm/%40alessiofrittoli%2Fstream-writer.svg\n[deps-badge]: https://img.shields.io/librariesio/release/npm/%40alessiofrittoli%2Fstream-writer\n[deps-url]: https://libraries.io/npm/%40alessiofrittoli%2Fstream-writer\n\n[sponsor-badge]: https://img.shields.io/static/v1?label=Fund%20this%20package\u0026message=%E2%9D%A4\u0026logo=GitHub\u0026color=%23DB61A2\n[sponsor-url]: https://github.com/sponsors/alessiofrittoli\n\n## Easly push data to a Stream\n\nThe `Stream` class extends the [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream) interface, providing additional convenience methods for handling streams, such as writing, closing, and aborting reducing the amount of code required for those operations.\n\nIf you're interested in a simple and effective way to read streams, take a look at [`@alessiofrittoli/stream-reader`](https://npmjs.com/package/@alessiofrittoli/stream-reader) package.\n\n### Table of Contents\n\n- [Getting started](#getting-started)\n- [Key features](#key-features)\n- [API Reference](#api-reference)\n  - [Importing the library](#importing-the-library)\n  - [Properties](#properties)\n  - [Constructor](#constructor)\n  - [Methods](#methods)\n    - [`Stream.write()`](#streamwrite)\n    - [`Stream.close()`](#streamclose)\n    - [`Stream.abort()`](#streamabort)\n- [Examples](#examples)\n  - [Writing data into a stream](#writing-data-into-a-stream)\n  - [Writing data into a stream with a custom transformer](#writing-data-into-a-stream-with-a-custom-transformer)\n  - [Aborting the stream](#aborting-the-stream)\n- [Development](#development)\n  - [Install depenendencies](#install-depenendencies)\n  - [Build the source code](#build-the-source-code)\n  - [ESLint](#eslint)\n  - [Jest](#jest)\n- [Contributing](#contributing)\n- [Security](#security)\n- [Credits](#made-with-)\n\n---\n\n### Getting started\n\nRun the following command to start using `stream-writer` in your projects:\n\n```bash\nnpm i @alessiofrittoli/stream-writer\n```\n\nor using `pnpm`\n\n```bash\npnpm i @alessiofrittoli/stream-writer\n```\n\n---\n\n### Key features\n\n#### Extends `TransformStream`\n\n- Inherits all the functionality of the [`TransformStream`](https://developer.mozilla.org/en-US/docs/Web/API/TransformStream) API, allowing for custom transformations of input to output streams.\n- Provides seamless integration with modern streaming APIs.\n\n#### Convenient Stream Management\n\n- `write` Method: A high-level abstraction for writing chunks of data into the stream. It handles readiness and ensures proper sequencing of write operations.\n- `close` Method: Safely closes the stream while preventing multiple or concurrent close operations.\n- `abort` Method: Gracefully aborts the stream with an optional reason, making it easier to handle errors or interruptions.\n\n#### Built-In Headers for Server Responses\n\n- The `headers` property contains default headers commonly used in server responses, such as:\n  - `Connection: keep-alive`\n  - `Transfer-Encoding: chunked`\n  - `Cache-Control: no-cache, no-transform`\n  - `X-Accel-Buffering: no`\n  - `Content-Encoding: none`\n\n#### Stream Writer Abstraction\n\n- The `writer` property provides direct access to the underlying `WritableStreamDefaultWriter`, enabling fine-grained control over the writable stream.\n- Ensures proper handling of stream readiness, errors, and resource management (e.g., releasing locks).\n\n#### Type Safety\n\n- Generic parameters (`I` for input, `O` for output) make the class type-safe and adaptable to various use cases, such as processing specific data types.\n\n#### Designed for Robustness\n\n- Internal mechanisms, ensure the class behaves predictably and avoids race conditions.\n\n#### Chainable API\n\n- Methods like `write`, `close`, and `abort` return the current `Stream` instance, enabling method chaining for more concise and readable code.\n\n#### Compatibility and Modularity\n\n- The `Stream` class can be used in both client-side and server-side applications where the `TransformStream` API is supported.\n- Its modular design makes it easy to extend or customize further for specific application needs.\n\n#### Focused on Developer Experience\n\n- Clear and concise API with thoughtful defaults.\n- Built-in documentation and examples make it easy to understand and integrate into existing projects.\n\nThese features make the `Stream` class a versatile and developer-friendly abstraction for working with streams in modern JavaScript and TypeScript environments.\n\n---\n\n### API Reference\n\n### Importing the library\n\n```ts\nimport { Stream } from '@alessiofrittoli/stream-writer'\n```\n\n---\n\n### Properties\n\n| Property   | Type                             | Description                                    |\n|------------|----------------------------------|------------------------------------------------|\n| `writable` | `WritableStream\u003cI\u003e`              | The writable stream instance.                  |\n| `readable` | `ReadableStream\u003cO\u003e`              | The readable stream instance.                  |\n| `writer`   | `WritableStreamDefaultWriter\u003cI\u003e` | The writer instance for the writable stream.   |\n| `closed`   | `boolean`                        | Indicates whether the stream is closed.        |\n| `headers`  | `Headers`                        | Common headers to return in a server response. |\n\n---\n\n### Constructor\n\nConstructs a new instance of the `Stream` class.\n\n| Parameter          | Type                 | Description                                           |\n|--------------------|----------------------|-------------------------------------------------------|\n| `transformer`      | `Transformer\u003cI, O\u003e`  | (Optional) A custom transformer for the stream.       |\n| `writableStrategy` | `QueuingStrategy\u003cI\u003e` | (Optional) A custom strategy for the writable stream. |\n| `readableStrategy` | `QueuingStrategy\u003cO\u003e` | (Optional) A custom strategy for the readable stream. |\n\n---\n\n### Methods\n\n#### `Stream.write()`\n\nWrites data into the stream.\n\n##### Parameters\n\n| Parameter | Type | Description                            |\n|-----------|------|----------------------------------------|\n| `chunk`   | `I`  | The data chunk to write to the stream. |\n\n##### Returns\n\nType: `Promise\u003cStream\u003e`\n\n- A Promise that resolves to the current `Stream` instance.\n\n---\n\n#### `Stream.close()`\n\nCloses the stream.\n\n- Closes the writer if it is not already closed or in the process of closing.\n- Prevents multiple close operations when .close() is not awaited.\n- Releases the lock on the writer.\n\n##### Returns\n\nType: `Promise\u003cStream\u003e`\n\n- A Promise that resolves to the current `Stream` instance.\n\n---\n\n#### `Stream.abort()`\n\nAborts the stream with an optional reason.\n\n##### Parameters\n\n| Parameter | Type     | Description                                    |\n|-----------|----------|------------------------------------------------|\n| `reason`  | `string` | (Optional) The reason for aborting the stream. |\n\n##### Returns\n\nType: `Promise\u003cStream\u003e`\n\n- A Promise that resolves to the current `Stream` instance.\n\n---\n\n### Examples\n\n#### Writing data into a stream\n\n```ts\nconst routeHandler = () =\u003e {\n  const stream = new Stream()\n  \n  const streamTask = async () =\u003e {\n    await stream.write( 'data' )\n    await stream.write( 'data 2' )\n    await stream.write( 'data 3' )\n    await stream.write( 'data 4' )\n  }\n  \n  streamTask()\n    .then( () =\u003e stream.close() )\n  \n  return new Response( stream.readable, { headers: stream.headers } )\n}\n```\n\n---\n\n#### Writing data into a stream with a custom transformer\n\n```ts\nconst routeHandler = () =\u003e {\n  const encoder = new TextEncoder()\n  const stream = (\n    new Stream\u003cstring, Uint8Array\u003e( {\n      transform( chunk, controller )\n      {\n        controller.enqueue( encoder.encode( chunk ) )\n      }\n    } )\n  )\n\n  const streamTask = async () =\u003e {\n    await stream.write( 'data' )\n    await stream.write( 'data 2' )\n    await stream.write( 'data 3' )\n    await stream.write( 'data 4' )\n  }\n\n  streamTask()\n    .then( () =\u003e stream.close() )\n\n  return new Response( stream.readable, { headers: stream.headers } )\n}\n```\n\n---\n\n#### Aborting the stream\n\n```ts\nconst routeHandler = request =\u003e {\n  request.signal.addEventListener( 'abort', () =\u003e {\n    stream.abort( 'The user aborted the request.' )\n  } )\n  \n  const stream = new Stream()\n  \n  const streamTask = async () =\u003e {\n    await stream.write( 'data' )\n    await stream.write( 'data 2' )\n    await stream.write( 'data 3' )\n    await stream.write( 'data 4' )\n  }\n  \n  streamTask()\n    .catch( error =\u003e {\n      if ( error.name === 'AbortError' ) {\n        return console.log( 'AbortError:', error.message )\n      }\n      await stream.write( error.message )\n    } )\n    .finally( () =\u003e stream.close() )\n  \n  return new Response( stream.readable, { headers: stream.headers } )\n\n}\n```\n\n---\n\nIf you're interested in a simple and effective way to read streams, take a look at [`@alessiofrittoli/stream-reader`](https://npmjs.com/package/@alessiofrittoli/stream-reader) package.\n\n---\n\n### Development\n\n#### Install depenendencies\n\n```bash\nnpm install\n```\n\nor using `pnpm`\n\n```bash\npnpm i\n```\n\n#### Build the source code\n\nRun the following command to test and build code for distribution.\n\n```bash\npnpm build\n```\n\n#### [ESLint](https://www.npmjs.com/package/eslint)\n\nwarnings / errors check.\n\n```bash\npnpm lint\n```\n\n#### [Jest](https://npmjs.com/package/jest)\n\nRun all the defined test suites by running the following:\n\n```bash\n# Run tests and watch file changes.\npnpm test:watch\n\n# Run tests in a CI environment.\npnpm test:ci\n```\n\n- See [`package.json`](./package.json) file scripts for more info.\n\nRun tests with coverage.\n\nAn HTTP server is then started to serve coverage files from `./coverage` folder.\n\n⚠️ You may see a blank page the first time you run this command. Simply refresh the browser to see the updates.\n\n```bash\ntest:coverage:serve\n```\n\n---\n\n### Contributing\n\nContributions are truly welcome!\n\nPlease refer to the [Contributing Doc](./CONTRIBUTING.md) for more information on how to start contributing to this project.\n\nHelp keep this project up to date with [GitHub Sponsor][sponsor-url].\n\n[![GitHub Sponsor][sponsor-badge]][sponsor-url]\n\n---\n\n### Security\n\nIf you believe you have found a security vulnerability, we encourage you to **_responsibly disclose this and NOT open a public issue_**. We will investigate all legitimate reports. Email `security@alessiofrittoli.it` to disclose any security vulnerabilities.\n\n### Made with ☕\n\n\u003ctable style='display:flex;gap:20px;'\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\n        \u003cimg alt=\"avatar\" src='https://avatars.githubusercontent.com/u/35973186' style='width:60px;border-radius:50%;object-fit:contain;'\u003e\n      \u003c/td\u003e\n      \u003ctd\u003e\n        \u003ctable style='display:flex;gap:2px;flex-direction:column;'\u003e\n          \u003ctbody\u003e\n              \u003ctr\u003e\n                \u003ctd\u003e\n                  \u003ca href='https://github.com/alessiofrittoli' target='_blank' rel='noopener'\u003eAlessio Frittoli\u003c/a\u003e\n                \u003c/td\u003e\n              \u003c/tr\u003e\n              \u003ctr\u003e\n                \u003ctd\u003e\n                  \u003csmall\u003e\n                    \u003ca href='https://alessiofrittoli.it' target='_blank' rel='noopener'\u003ehttps://alessiofrittoli.it\u003c/a\u003e |\n                    \u003ca href='mailto:info@alessiofrittoli.it' target='_blank' rel='noopener'\u003einfo@alessiofrittoli.it\u003c/a\u003e\n                  \u003c/small\u003e\n                \u003c/td\u003e\n              \u003c/tr\u003e\n          \u003c/tbody\u003e\n        \u003c/table\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessiofrittoli%2Fstream-writer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falessiofrittoli%2Fstream-writer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessiofrittoli%2Fstream-writer/lists"}