{"id":17963287,"url":"https://github.com/borewit/peek-readable","last_synced_at":"2025-04-05T07:03:47.044Z","repository":{"id":21811518,"uuid":"94110458","full_name":"Borewit/peek-readable","owner":"Borewit","description":"A promise based asynchronous stream reader, which makes reading from a stream easy.","archived":false,"fork":false,"pushed_at":"2025-03-24T06:43:17.000Z","size":2939,"stargazers_count":9,"open_issues_count":1,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T06:03:54.579Z","etag":null,"topics":["peek","promise","readable","reader","seek","stream"],"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/Borewit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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},"funding":{"github":"Borewit","buy_me_a_coffee":"borewit"}},"created_at":"2017-06-12T15:16:23.000Z","updated_at":"2025-03-09T10:36:46.000Z","dependencies_parsed_at":"2024-06-18T15:33:34.832Z","dependency_job_id":"e784098c-7d3b-41e4-b1d4-81a23c68c9b5","html_url":"https://github.com/Borewit/peek-readable","commit_stats":{"total_commits":542,"total_committers":6,"mean_commits":90.33333333333333,"dds":0.5977859778597786,"last_synced_commit":"11b630a1b7e81e7fc0ad9257fc02e94af371e630"},"previous_names":["borewit/then-read-stream"],"tags_count":65,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Borewit%2Fpeek-readable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Borewit%2Fpeek-readable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Borewit%2Fpeek-readable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Borewit%2Fpeek-readable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Borewit","download_url":"https://codeload.github.com/Borewit/peek-readable/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247299831,"owners_count":20916190,"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":["peek","promise","readable","reader","seek","stream"],"created_at":"2024-10-29T11:25:08.121Z","updated_at":"2025-04-05T07:03:47.014Z","avatar_url":"https://github.com/Borewit.png","language":"TypeScript","funding_links":["https://github.com/sponsors/Borewit","https://buymeacoffee.com/borewit"],"categories":[],"sub_categories":[],"readme":"[![CI](https://github.com/Borewit/peek-readable/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/Borewit/peek-readable/actions/workflows/ci.yml)\n[![CodeQL](https://github.com/Borewit/peek-readable/actions/workflows/github-code-scanning/codeql/badge.svg?branch=master)](https://github.com/Borewit/peek-readable/actions/workflows/github-code-scanning/codeql)\n[![NPM version](https://badge.fury.io/js/peek-readable.svg)](https://npmjs.org/package/peek-readable)\n[![npm downloads](http://img.shields.io/npm/dm/peek-readable.svg)](https://npmcharts.com/compare/peek-readable?start=600\u0026interval=30)\n[![Coverage Status](https://coveralls.io/repos/github/Borewit/peek-readable/badge.svg?branch=master)](https://coveralls.io/github/Borewit/peek-readable?branch=master)\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/d4b511481b3a4634b6ca5c0724407eb9)](https://www.codacy.com/gh/Borewit/peek-readable/dashboard?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=Borewit/peek-readable\u0026amp;utm_campaign=Badge_Grade)\n[![Known Vulnerabilities](https://snyk.io/test/github/Borewit/peek-readable/badge.svg?targetFile=package.json)](https://snyk.io/test/github/Borewit/peek-readable?targetFile=package.json)\n\n# peek-readable\n\nA promise based asynchronous stream reader, which makes reading from a stream easy.\n\nAllows to read and peek from a [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams)\n\nThis module is used by [strtok3](https://github.com/Borewit/strtok3)\n\nThe `peek-readable` contains one class: `StreamReader`, which reads from a [stream.Readable](https://nodejs.org/api/stream.html#stream_class_stream_readable).\n\n- Class `StreamReader` is used to read from Node.js [stream.Readable](https://nodejs.org/api/stream.html#stream_class_stream_readable).\n- Class `WebStreamByobReader` is used to read from [ReadableStream\u003cUint8Array\u003e](https://developer.mozilla.org/docs/Web/API/ReadableStream)\n\n## Compatibility\n\nModule: version 5 migrated from [CommonJS](https://en.wikipedia.org/wiki/CommonJS) to [pure ECMAScript Module (ESM)](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).\nJavaScript is compliant with [ECMAScript 2019 (ES10)](https://en.wikipedia.org/wiki/ECMAScript#10th_Edition_%E2%80%93_ECMAScript_2019).\nRequires a modern browser or Node.js ≥ 18 engine.\n\nFor TypeScript CommonJs backward compatibility, you can use [load-esm](https://github.com/Borewit/load-esm).\n\n## Usage\n\n### Installation\n\n```shell script\nnpm install --save peek-readable\n```\n\n## API Documentation\n\nBoth `StreamReader` and `WebStreamByobReader` implement the [IStreamReader interface](#istreamreader-interface).\n\n### `IStreamReader` Interface\n\nThe `IStreamReader` interface defines the contract for a stream reader,\nwhich provides methods to read and peek data from a stream into a `Uint8Array` buffer.\nThe methods are asynchronous and return a promise that resolves with the number of bytes read.\n\n#### Methods\n\n##### `peek` function\nThis method allows you to inspect data from the stream without advancing the read pointer.\nIt reads data into the provided Uint8Array at a specified offset but does not modify the stream's internal position, \nallowing you to look ahead in the stream.\n\n```ts  \npeek(buffer: Uint8Array, offset: number, length: number): Promise\u003cnumber\u003e\n```\n\nParameters:\n- `buffer`: `Uint8Array`: The buffer into which the data will be peeked.\n  This is where the peeked data will be stored.\n- `maybeBeLess`: If true, the buffer maybe partially filled.\n\nReturns `Promise\u003cnumber\u003e`: \nA promise that resolves with the number of bytes actually peeked into the buffer. \nThis number may be less than the requested length if the end of the stream is reached.\n\n##### `read` function\n```ts  \nread(buffer: Uint8Array, offset: number, length: number): Promise\u003cnumber\u003e\n```\n\nParameters:\n- `buffer`: `Uint8Array`: The buffer into which the data will be read.\n  This is where the read data will be stored.\n- `maybeBeLess`: If true, the buffer maybe partially filled.\n\nReturns `Promise\u003cnumber\u003e`:\nA promise that resolves with the number of bytes actually read into the buffer.\nThis number may be less than the requested length if the end of the stream is reached.\n\n##### `abort` function\n\nAbort active asynchronous operation (`read` or `peak`) before it has completed.\n\n```ts  \nabort(): Promise\u003cvoid\u003e\n```\n\n## Examples\n\nIn the following example we read the first 16 bytes from a stream and store them in our buffer.\nSource code of examples can be found [here](test/examples.ts).\n\n```js\nimport fs from 'node:fs';\nimport { StreamReader } from 'peek-readable';\n\n(async () =\u003e {\n  const readable = fs.createReadStream('JPEG_example_JPG_RIP_001.jpg');\n  const streamReader = new StreamReader(readable);\n  const uint8Array = new Uint8Array(16);\n  const bytesRead = await streamReader.read(uint8Array);;\n  // buffer contains 16 bytes, if the end-of-stream has not been reached\n})();\n```\n\nEnd-of-stream detection:\n```js\n(async () =\u003e {\n\n  const fileReadStream = fs.createReadStream('JPEG_example_JPG_RIP_001.jpg');\n  const streamReader = new StreamReader(fileReadStream);\n  const buffer = Buffer.alloc(16); // or use: new Uint8Array(16);\n\n  try {\n    await streamReader.read(buffer);\n    // buffer contains 16 bytes, if the end-of-stream has not been reached\n  } catch(error) {\n    if (error instanceof EndOfStreamError) {\n      console.log('End-of-stream reached');\n    }\n  }\n})();\n```\n\nWith `peek` you can read ahead:\n```js\nimport fs from 'node:fs';\nimport { StreamReader } from 'peek-readable';\n\nfunction closeNodeStream(stream: ReadStream): Promise\u003cvoid\u003e {\n  return new Promise\u003cvoid\u003e((resolve, reject) =\u003e {\n    stream.close(err =\u003e {\n      if(err)\n        reject(err);\n      else\n        resolve();\n    });\n  })\n}\n\n(async () =\u003e {\n\n  const fileReadStream = fs.createReadStream('JPEG_example_JPG_RIP_001.jpg');\n  try {\n    const streamReader = new StreamReader(fileReadStream);\n    try {\n      const buffer = Buffer.alloc(20);\n\n      let bytesRead = await streamReader.peek(buffer.subarray(0, 3));\n      if (bytesRead === 3 \u0026\u0026 buffer[0] === 0xFF \u0026\u0026 buffer[1] === 0xD8 \u0026\u0026 buffer[2] === 0xFF) {\n        console.log('This is a JPEG file');\n      } else {\n        throw Error('Expected a JPEG file');\n      }\n\n      bytesRead = await streamReader.read(buffer); // Read JPEG header\n      if (bytesRead === 20) {\n        console.log('Got the JPEG header');\n      } else {\n        throw Error('Failed to read JPEG header');\n      }\n    } finally {\n      await streamReader.close(); // Release fileReadStream\n    }    \n  } finally {\n    await closeNodeStream(fileReadStream);\n  }\n\n\n})();\n```\n\n## Licence\n\nThis project is licensed under the [MIT License](LICENSE.txt). Feel free to use, modify, and distribute as needed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fborewit%2Fpeek-readable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fborewit%2Fpeek-readable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fborewit%2Fpeek-readable/lists"}