{"id":17109265,"url":"https://github.com/kevinoid/stream-compare","last_synced_at":"2026-02-02T10:34:11.286Z","repository":{"id":4356204,"uuid":"51236089","full_name":"kevinoid/stream-compare","owner":"kevinoid","description":"Compare the behavior of readable streams.","archived":false,"fork":false,"pushed_at":"2025-11-20T17:13:50.000Z","size":1014,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-20T19:12:45.483Z","etag":null,"topics":["assert","compare-data","comparison","nodejs","readable-streams","stream"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/kevinoid.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2016-02-07T05:00:01.000Z","updated_at":"2025-11-20T17:13:50.000Z","dependencies_parsed_at":"2023-01-14T11:20:36.366Z","dependency_job_id":"f4edb4ff-0b04-4557-ba8d-3da29a6c0a6c","html_url":"https://github.com/kevinoid/stream-compare","commit_stats":{"total_commits":471,"total_committers":5,"mean_commits":94.2,"dds":0.03397027600849256,"last_synced_commit":"cacd8a9f64c3d69d82565472d415561964ab3675"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/kevinoid/stream-compare","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevinoid%2Fstream-compare","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevinoid%2Fstream-compare/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevinoid%2Fstream-compare/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevinoid%2Fstream-compare/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kevinoid","download_url":"https://codeload.github.com/kevinoid/stream-compare/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kevinoid%2Fstream-compare/sbom","scorecard":{"id":557256,"data":{"date":"2025-08-11","repo":{"name":"github.com/kevinoid/stream-compare","commit":"e7c6936ee44ecf00be834bac3fcb638a6e2238c1"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/23 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/node.js.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/node.js.yml:124: update your workflow using https://app.stepsecurity.io/secureworkflow/kevinoid/stream-compare/node.js.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/kevinoid/stream-compare/node.js.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/kevinoid/stream-compare/node.js.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/node.js.yml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/kevinoid/stream-compare/node.js.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/node.js.yml:59: update your workflow using https://app.stepsecurity.io/secureworkflow/kevinoid/stream-compare/node.js.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:97: update your workflow using https://app.stepsecurity.io/secureworkflow/kevinoid/stream-compare/node.js.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/node.js.yml:99: update your workflow using https://app.stepsecurity.io/secureworkflow/kevinoid/stream-compare/node.js.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/node.js.yml:113: update your workflow using https://app.stepsecurity.io/secureworkflow/kevinoid/stream-compare/node.js.yml/main?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/node.js.yml:52","Warn: npmCommand not pinned by hash: .github/workflows/node.js.yml:108","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 third-party GitHubAction dependencies pinned","Info:   0 out of   2 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: MIT License: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 7 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T12:41:59.244Z","repository_id":4356204,"created_at":"2025-08-20T12:41:59.244Z","updated_at":"2025-08-20T12:41:59.244Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29010342,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-02T08:40:12.472Z","status":"ssl_error","status_checked_at":"2026-02-02T08:40:10.926Z","response_time":58,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["assert","compare-data","comparison","nodejs","readable-streams","stream"],"created_at":"2024-10-14T16:22:43.268Z","updated_at":"2026-02-02T10:34:11.272Z","avatar_url":"https://github.com/kevinoid.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"stream-compare\n==============\n\n[![Build Status](https://img.shields.io/github/actions/workflow/status/kevinoid/stream-compare/node.js.yml?branch=main\u0026style=flat\u0026label=build)](https://github.com/kevinoid/stream-compare/actions?query=branch%3Amain)\n[![Coverage](https://img.shields.io/codecov/c/github/kevinoid/stream-compare/main.svg?style=flat)](https://app.codecov.io/gh/kevinoid/stream-compare/branch/main)\n[![Dependency Status](https://img.shields.io/librariesio/release/npm/stream-compare.svg?style=flat)](https://libraries.io/npm/stream-compare)\n[![Supported Node Version](https://img.shields.io/node/v/stream-compare.svg?style=flat)](https://www.npmjs.com/package/stream-compare)\n[![Version on NPM](https://img.shields.io/npm/v/stream-compare.svg?style=flat)](https://www.npmjs.com/package/stream-compare)\n\nCompare the output of two Readable streams using a caller-provided\ncomparison/assertion function.\n\n## Introductory Example\n\n```js\nconst assert = require('assert');\nconst fs = require('fs');\nconst streamCompare = require('stream-compare');\n\nconst stream1 = fs.createReadStream(file);\nconst stream2 = fs.createReadStream(file);\nstreamCompare(stream1, stream2, assert.deepStrictEqual).catch((err) =\u003e {\n  console.log(err); // AssertionError if streams differ\n});\n```\n\n\n## Features\n\nThis package is similar to the\n[stream-equal](https://github.com/fent/node-stream-equal) package with several\nadditional features:\n\n- Support for caller-defined comparisons, which can return errors or values\n  not limited to equality.\n- Support for both incremental and one-shot comparisons.\n- Support for caller-defined data reduction to avoid storing the entire stream\n  history in memory before comparison.\n- Makes no assumptions about the type of values read beyond whether they\n  should be treated as objects (`objectMode`) or a stream of Buffers or\n  strings.\n- Does not do any coercion of the values read.\n- Support for comparing (caller-configurable) events emitted by the streams.\n- Support reading in flowing or non-flowing mode.\n- Support for optionally aborting comparison on stream errors.\n- Support for catching multiple end/error events (within one tick by default,\n  or an optional configurable delay).\n- Utility function for creating an incremental comparison and data-reduction\n  function from a standard data comparison function (e.g. `assert.deepEqual`).\n\n\n## Installation\n\n[This package](https://www.npmjs.com/package/stream-compare) can be installed\nusing [npm](https://www.npmjs.com/), either globally or locally, by running:\n\n```sh\nnpm install stream-compare\n```\n\n\n## Recipes\n\n### Compare Incrementally\n\nIn order to avoid unnecessary memory use for streams with large amounts of\ndata and avoid unnecessary delays for streams which produce data slowly, the\noutput can be compared incrementally and inconclusive output can be removed.\nThis is done by the incremental function.  To make this easier, the utility\nfunction `makeIncremental` creates such a function from a data comparison\nfunction and/or an events comparison function:\n\n```js\nconst options = {\n  incremental: streamCompare.makeIncremental(\n    assert.deepStrictEqual,     // Compares data\n    assert.deepStrictEqual,     // Compares events\n  ),\n};\nstreamCompare(stream1, stream2, options).catch((err) =\u003e {\n  console.log(err); // AssertionError if stream data values differ\n});\n```\n\n### Compare Data Values Separately\n\nSometimes it may be desirable to compare the values returned by `.read()` or\n`'data'` events separately, rather than concatenated together.  This can be\ndone by setting `objectMode: true` (even if the values aren't `Object`s):\n\n```js\nconst options = {\n  compare: assert.deepStrictEqual,\n  objectMode: true,\n};\nstreamCompare(stream1, stream2, options).catch((err) =\u003e {\n  console.log(err); // AssertionError if stream data values differ\n});\n```\n\n### Compare Data and Event Interleaving\n\nIn order to compare the ordering of `'data'` events with other events, add\n`'data'` to the `events` option and set `readPolicy` to `'flowing'` or\n`'none'`.  Any `'data'` events and their arguments will appear with any other\nmatching events in the `events` property of the state object.\n\n```js\nconst options = {\n  compare: assert.deepStrictEqual,\n  events: ['close', 'data', 'end', 'error'],\n  readPolicy: 'none',\n};\nstreamCompare(stream1, stream2, options).catch((err) =\u003e {\n  console.log(err); // AssertionError if stream events (including 'data') differ\n});\n```\n\n### Control comparison checkpoints\n\nThe returned Promise includes additional methods for controlling the\ncomparison.  A non-incremental compare can be run before both streams end\nusing `.checkpoint()`.  Additionally, the comparison can be concluded before\nboth streams end using `.end()`.  The full details are available in the [API\nDocumentation](https://kevinoid.github.io/stream-compare/api/StreamComparePromise.html).\n\n```js\nconst { PassThrough } = require('stream');\n\nconst stream1 = new PassThrough();\nconst stream2 = new PassThrough();\nconst comparison = streamCompare(stream1, stream2, assert.deepStrictEqual);\ncomparison.then(\n  () =\u003e console.log('streams are equal'),\n  (err) =\u003e console.log(`streams differ: ${err}`),\n);\nstream1.write('Hello');\nstream2.write('Hello');\nsetImmediate(() =\u003e {\n  comparison.checkpoint();\n\n  stream1.write(' world!');\n  stream2.write(' world!');\n\n  setImmediate(() =\u003e comparison.end());\n});\n```\n\nMore examples can be found in the [test\nspecifications](https://kevinoid.github.io/stream-compare/spec).\n\n## API Docs\n\nFor the details of using this module as a library, see the [API\nDocumentation](https://kevinoid.github.io/stream-compare/api).\n\n\n## Contributing\n\nContributions are appreciated.  Contributors agree to abide by the [Contributor\nCovenant Code of\nConduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html).\nIf this is your first time contributing to a Free and Open Source Software\nproject, consider reading [How to Contribute to Open\nSource](https://opensource.guide/how-to-contribute/)\nin the Open Source Guides.\n\nIf the desired change is large, complex, backwards-incompatible, can have\nsignificantly differing implementations, or may not be in scope for this\nproject, opening an issue before writing the code can avoid frustration and\nsave a lot of time and effort.\n\n\n## License\n\nThis project is available under the terms of the [MIT License](LICENSE.txt).\nSee the [summary at TLDRLegal](https://tldrlegal.com/license/mit-license).\n\nThe [template](https://github.com/kevinoid/node-project-template) upon which\nthis project is based is available under the terms of\n[CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevinoid%2Fstream-compare","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkevinoid%2Fstream-compare","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkevinoid%2Fstream-compare/lists"}