{"id":23994767,"url":"https://github.com/nberlette/brocha","last_synced_at":"2026-02-26T16:01:16.001Z","repository":{"id":270526170,"uuid":"496834827","full_name":"nberlette/brocha","owner":"nberlette","description":"Universal brotli decompressor, implemented in 100% TypeScript. Performant, portable, platform-agnostic, and dependency-free.","archived":false,"fork":false,"pushed_at":"2026-01-01T09:00:52.000Z","size":7615,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-06T03:49:22.649Z","etag":null,"topics":["brocha","brotli","brotli-decompressor","compression","decompressor","deno","jsr","lz77","standalone","typescript","universal"],"latest_commit_sha":null,"homepage":"https://jsr.io/@nick/brocha/doc","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/nberlette.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"ko_fi":"nberlette"}},"created_at":"2022-05-27T02:20:04.000Z","updated_at":"2026-01-01T08:57:34.000Z","dependencies_parsed_at":"2025-02-15T08:23:39.767Z","dependency_job_id":"20b8c75a-6ee6-46d8-83c3-d943bf4abc50","html_url":"https://github.com/nberlette/brocha","commit_stats":null,"previous_names":["nberlette/brocha"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/nberlette/brocha","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberlette%2Fbrocha","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberlette%2Fbrocha/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberlette%2Fbrocha/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberlette%2Fbrocha/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nberlette","download_url":"https://codeload.github.com/nberlette/brocha/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nberlette%2Fbrocha/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29863764,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-26T08:51:08.701Z","status":"ssl_error","status_checked_at":"2026-02-26T08:50:19.607Z","response_time":89,"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":["brocha","brotli","brotli-decompressor","compression","decompressor","deno","jsr","lz77","standalone","typescript","universal"],"created_at":"2025-01-07T21:20:31.188Z","updated_at":"2026-02-26T16:01:15.956Z","avatar_url":"https://github.com/nberlette.png","language":"TypeScript","readme":"\u003cdiv align=\"center\"\u003e\n\n[\u003cpicture\u003e\u003csource media=\"(prefers-color-scheme: dark)\" type=\"image/png\" srcset=\"https://raw.githubusercontent.com/nberlette/brocha/34e6873fabf3357f117deda7930d1eb222207f7a/.github/assets/banner.png\" /\u003e\u003csource media=\"(prefers-color-scheme: light)\" type=\"image/png\" srcset=\"https://raw.githubusercontent.com/nberlette/brocha/34e6873fabf3357f117deda7930d1eb222207f7a/.github/assets/banner_light.png\" /\u003e\u003csource type=\"image/svg+xml\" srcset=\"https://raw.githubusercontent.com/nberlette/brocha/34e6873fabf3357f117deda7930d1eb222207f7a/.github/assets/banner.svg\" /\u003e\u003cimg src=\"https://raw.githubusercontent.com/nberlette/brocha/34e6873fabf3357f117deda7930d1eb222207f7a/.github/assets/banner.png\" alt=\"@nick/brocha\" /\u003e\u003c/picture\u003e][jsr]\n\n# `brocha`\n\n##### Fast universal [Brotli] decompression in 100% TypeScript\n\n![][badge-jsr-score] ![][badge-jsr-pkg] ![][badge-npm]\n\n---\n\n\u003c/div\u003e\n\nThis package provides a blazing fast TypeScript implementation of the [Brotli]\ndecompression algorithm, suitable for use in any ES2015+ environment. It offers\na performant, portable, and reliable alternative to existing solutions, with\nsupport for custom dictionaries and a small footprint.\n\n[Benchmarks](#benchmarks) show it to be nearly as fast as WebAssembly-based\ndecoders, and significantly faster than JavaScript-only alternatives.\n\n## Install\n\n\u003cpicture align=\"left\" width=\"32\" height=\"48\"\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.iconify.design/simple-icons:deno.svg?height=2.75rem\u0026width=3rem\u0026color=%23fff\" /\u003e\n  \u003cimg align=\"left\" src=\"https://api.iconify.design/simple-icons:deno.svg?height=2.75rem\u0026width=3rem\" alt=\"Deno\" width=\"32\" height=\"48\" /\u003e\n\u003c/picture\u003e\n\n```sh\ndeno add jsr:@nick/brocha\n```\n\n\u003cimg align=\"left\" src=\"https://api.iconify.design/simple-icons:jsr.svg?color=%23fb0\" alt=\"JSR\" width=\"32\" height=\"48\" /\u003e\n\n```sh\nnpx jsr add @nick/brocha\n```\n\n\u003cimg align=\"left\" src=\"https://api.iconify.design/logos:bun.svg\" alt=\"Bun\" width=\"32\" height=\"48\" /\u003e\n\n```sh\nbunx jsr add @nick/brocha\n```\n\n\u003cimg align=\"left\" src=\"https://api.iconify.design/devicon:pnpm.svg?height=2.5rem\u0026width=2.5rem\u0026inline=true\" alt=\"PNPM\" width=\"32\" height=\"48\" /\u003e\n\n```sh\npnpm dlx jsr add @nick/brocha\n```\n\n\u003cimg align=\"left\" src=\"https://api.iconify.design/logos:yarn.svg?height=2rem\u0026width=2rem\u0026inline=true\" alt=\"Yarn\" width=\"32\" height=\"48\" /\u003e\n\n```sh\nyarn add @nick/brocha\n```\n\n\u003cbr\u003e\n\n**Mirrored on NPM as `brocha`**:\n\n\u003cimg align=\"left\" src=\"https://api.iconify.design/logos:npm.svg?height=2rem\u0026width=2rem\u0026inline=true\" alt=\"NPM\" width=\"32\" height=\"48\" /\u003e\n\n```sh\nnpm i brocha\n```\n\n---\n\n## Usage\n\n```ts\nimport { decompress } from \"@nick/brocha\";\n\nconst response = await fetch(\"file:///compressed.br\");\nconst compressedData = new Uint8Array(await response.arrayBuffer());\n\nconst decompressedData = decompress(compressedData);\n\nconsole.log(\n  `Decompressed ${compressedData.length}B -\u003e ${decompressedData.length}B`,\n);\n```\n\n\u003e [!TIP]\n\u003e\n\u003e The `decompress` function is ready to use immediately upon import. Simply pass\n\u003e in your Brotli-compressed data and receive the decompressed `Uint8Array`.\n\n---\n\n## API\n\n### `decompress`\n\nDecompresses Brotli-encoded data into a `Uint8Array`.\n\n#### Signature\n\n```ts ignore\ndecompress(input: BufferSource, options?: BrotliDecodeOptions): Uint8Array;\n```\n\n#### Parameters\n\n- `input`: The Brotli-compressed [`BufferSource`] to be decoded.\n- `options`: Optional decompression options, allowing you to use a custom\n  dictionary.\n\n#### Returns\n\n- `Uint8Array`: The decompressed data.\n\n#### Examples\n\n**Decompressing a Brotli-compressed file:**\n\n```ts no-eval\nimport { decompress } from \"@nick/brocha\";\nimport * as fs from \"node:fs\";\n\nconst compressed = fs.readFileSync(\"data.br\");\nconst decompressed = decompress(compressed);\n\nconst inputKB = (compressed.byteLength / 1024).toFixed(0);\nconst outputKB = (decompressed.byteLength / 1024).toFixed(0);\nconsole.log(\n  `${inputKB}K → ${outputKB}K (+${(outputKB / inputKB).toFixed(2)}x)`,\n);\n// Example log: \"115K → 483K (+4.20x)\"\n```\n\n**Using a custom dictionary:**\n\n```ts no-eval\nimport { decompress } from \"@nick/brocha\";\n\nconst compressedData = /* Brotli-compressed data */;\nconst dictionary = new Uint8Array([/* custom dictionary bytes */]);\n\nconst options = { customDictionary: dictionary };\nconst decompressedData = decompress(compressedData, options);\n\nconsole.log(decompressedData);\n```\n\n---\n\n### `BrotliDecodeOptions`\n\nOptions to customize the behavior of the Brotli decompression process.\n\n```ts\ninterface BrotliDecodeOptions {\n  customDictionary?: BufferSource | null;\n}\n```\n\n#### `customDictionary` (`BufferSource | null`)\n\nCustom dictionary to use for the Brotli decompression.\n\n##### Default\n\n`null` _(uses the default dictionary)_\n\n##### Remarks\n\nThe dictionary **must** be a valid Brotli dictionary that **exactly** matches\nthe one used when the input data was compressed. Otherwise, the decompressor\nwill either throw an exception or corrupted data will be returned.\n\n---\n\n## Benchmarks\n\nThis package is designed to be lightweight and fast, with a focus on performance\nand efficiency. The following benchmarks were run on a 2021 MacBook Pro with an\nM1 Pro chip using Deno 2.1.2.\n\nThe results demonstrate the performance of this package compared to other\npopular Brotli decompression tools, suggesting it is a viable alternative to\nexisting [WebAssembly-based solutions](#webassembly-decoders).\n\n- Performance is mostly on par with WebAssembly decoders like [brotli-wasm],\n  which typically show small speed advantages of ~15-20% over this package.\n- Compared to other pure-JS implementations (specifically [npm:brotli]),\n  `brocha` consistently clocks speeds ~1.75x faster across all benchmarks.\n- Performance is about 35-50% that of the native Node.js `node:zlib` module.\n\n\u003e [!NOTE]\n\u003e\n\u003e The native `node:zlib` module is written in C++ and is highly optimized for\n\u003e performance. While _\"~2.5x slower\"_ sounds like a poor result, it's actually\n\u003e quite fast for a pure JavaScript implementation, which will never be able to\n\u003e match the performance of a native module.\n\n```sh\n\u003e deno bench -A --no-check\n\nbenchmark             time/iter (avg)        iter/s      (min … max)           p75      p99     p995\n--------------------- ----------------------------- --------------------- --------------------------\n\ngroup basic json (6.5 KB -\u003e 27.5 KB)\n\njsr:@nick/brocha             399.0 µs         2,506 (324.8 µs …   3.1 ms) 381.8 µs   1.6 ms   2.1 ms\nnpm:brotli                   666.1 µs         1,501 (553.7 µs …   3.0 ms) 626.2 µs   1.9 ms   2.3 ms\nnpm:brotli-wasm              322.5 µs         3,101 (265.4 µs …   7.0 ms) 276.6 µs   1.7 ms   2.5 ms\nnpm:brotli-dec-wasm          306.7 µs         3,261 (279.2 µs …   4.7 ms) 288.3 µs 915.1 µs   1.6 ms\nnode:zlib                    144.5 µs         6,921 (136.5 µs …   1.8 ms) 141.8 µs 194.1 µs 245.7 µs\n\nsummary\n  jsr:@nick/brocha\n     2.76x slower than node:zlib\n     1.30x slower than npm:brotli-dec-wasm\n     1.24x slower than npm:brotli-wasm\n     1.67x faster than npm:brotli\n\ngroup dprint-plugin-graphql.wasm (147 KB -\u003e 768 KB)\n\njsr:@nick/brocha               6.5 ms         154.0 (  6.0 ms …   7.7 ms)   6.7 ms   7.7 ms   7.7 ms\nnpm:brotli                    12.2 ms          82.1 ( 10.6 ms …  57.6 ms)  11.3 ms  57.6 ms  57.6 ms\nnpm:brotli-wasm                6.5 ms         153.3 (  5.9 ms …  31.6 ms)   6.1 ms  31.6 ms  31.6 ms\nnpm:brotli-dec-wasm            6.3 ms         158.8 (  6.2 ms …   7.1 ms)   6.3 ms   7.1 ms   7.1 ms\nnode:zlib                      3.4 ms         292.2 (  3.2 ms …   4.6 ms)   3.5 ms   4.2 ms   4.6 ms\n\nsummary\n  jsr:@nick/brocha\n     1.90x slower than node:zlib\n     1.03x slower than npm:brotli-dec-wasm\n     1.00x faster than npm:brotli-wasm\n     1.88x faster than npm:brotli\n\ngroup dprint-plugin-jupyter.wasm (354 KB -\u003e 1.68 MB)\n\njsr:@nick/brocha              14.4 ms          69.6 ( 13.8 ms …  15.1 ms)  14.5 ms  15.1 ms  15.1 ms\nnpm:brotli                    26.2 ms          38.1 ( 25.3 ms …  30.1 ms)  26.7 ms  30.1 ms  30.1 ms\nnpm:brotli-wasm               13.9 ms          71.8 ( 13.6 ms …  15.4 ms)  14.0 ms  15.4 ms  15.4 ms\nnpm:brotli-dec-wasm           14.8 ms          67.4 ( 14.4 ms …  16.6 ms)  14.9 ms  16.6 ms  16.6 ms\nnode:zlib                      8.8 ms         114.2 (  8.5 ms …  10.1 ms)   8.8 ms  10.1 ms  10.1 ms\n\nsummary\n  jsr:@nick/brocha\n     1.64x slower than node:zlib\n     1.03x slower than npm:brotli-wasm\n     1.03x faster than npm:brotli-dec-wasm\n     1.82x faster than npm:brotli\n\ngroup dprint-plugin-typescript.wasm (746 KB -\u003e 4.01 MB)\n\njsr:@nick/brocha              36.5 ms          27.4 ( 33.3 ms …  41.5 ms)  37.8 ms  41.5 ms  41.5 ms\nnpm:brotli                    63.4 ms          15.8 ( 59.6 ms …  76.9 ms)  64.4 ms  76.9 ms  76.9 ms\nnpm:brotli-wasm               31.6 ms          31.6 ( 30.8 ms …  32.4 ms)  31.9 ms  32.4 ms  32.4 ms\nnpm:brotli-dec-wasm           33.8 ms          29.6 ( 33.0 ms …  34.4 ms)  34.0 ms  34.4 ms  34.4 ms\nnode:zlib                     18.6 ms          53.8 ( 17.9 ms …  19.6 ms)  18.8 ms  19.6 ms  19.6 ms\n\nsummary\n  jsr:@nick/brocha\n     1.96x slower than node:zlib\n     1.16x slower than npm:brotli-wasm\n     1.08x slower than npm:brotli-dec-wasm\n     1.74x faster than npm:brotli\n\ngroup ten megs of lipsum (1.71 MB -\u003e 9.77 MB)\n\njsr:@nick/brocha              65.3 ms          15.3 ( 63.3 ms …  69.5 ms)  65.6 ms  69.5 ms  69.5 ms\nnpm:brotli                   117.3 ms           8.5 (111.7 ms … 122.4 ms) 119.8 ms 122.4 ms 122.4 ms\nnpm:brotli-wasm               49.1 ms          20.4 ( 46.3 ms …  51.7 ms)  49.7 ms  51.7 ms  51.7 ms\nnpm:brotli-dec-wasm           56.4 ms          17.7 ( 52.5 ms …  76.7 ms)  56.6 ms  76.7 ms  76.7 ms\nnode:zlib                     33.1 ms          30.2 ( 29.7 ms …  91.5 ms)  31.0 ms  91.5 ms  91.5 ms\n\nsummary\n  jsr:@nick/brocha\n     1.97x slower than node:zlib\n     1.33x slower than npm:brotli-wasm\n     1.16x slower than npm:brotli-dec-wasm\n     1.80x faster than npm:brotli\n```\n\n\u003e The `decompress` function from this package is the baseline, with some other\n\u003e popular Brotli decompression tools for comparison.\n\n---\n\n### Prior Art\n\nThis project was adapted from the original [brotli] source code, developed by\nthe Google Brotli team and licensed under the MIT license.\n\n#### WebAssembly Decoders\n\n- [brotli-decompressor]\n- [brotli-dec-wasm]\n- [brotli-wasm]\n\n#### JavaScript Decoders\n\n- [npm:brotli]\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n##### [MIT] © [Nicholas Berlette]. All rights reserved.\n\n###### [GitHub] • [Issues] • [JSR] • [NPM]\n\n\u003cbr\u003e\n\n[![JSR][JSR-badge]][JSR] [![JSR][badge-jsr-score]][JSR]\n\n\u003c/div\u003e\n\n[MIT]: https://nick.mit-license.org \"MIT © 2024+ Nicholas Berlette. All rights reserved.\"\n[Nicholas Berlette]: https://github.com/nberlette \"Nicholas Berlette on GitHub\"\n[GitHub]: https://github.com/nberlette/brocha \"View the @nick/brocha project on GitHub\"\n[Issues]: https://github.com/nberlette/brocha/issues \"View issues for the @nick/brocha project on GitHub\"\n[JSR]: https://jsr.io/@nick/brocha/doc \"View the @nick/brocha documentation on jsr.io\"\n[NPM]: https://www.npmjs.com/package/brocha \"View the brocha package on npm\"\n[brotli-decompressor]: https://crates.io/crates/brotli-decompressor \"View the brotli-decompressor crate on crates.io\"\n[brotli-wasm]: https://crates.io/brotli-wasm \"View the brotli-wasm crate on crates.io\"\n[brotli-dec-wasm]: https://crates.io/brotli-dec-wasm \"View the brotli-dec-wasm crate on crates.io\"\n[jsr-badge]: https://jsr.io/badges/@nick \"Install @nick/brocha with JSR\"\n[badge-npm]: https://img.shields.io/npm/v/brocha?logo=npm\u0026color=firebrick\u0026labelColor=firebrick\u0026label= \"View brocha on npm\"\n[badge-jsr-nick]: https://jsr.io/badges/@nick \"View all of @nick's packages on jsr.io\"\n[badge-jsr-pkg]: https://jsr.io/badges/@nick/brocha \"View @nick/brocha on jsr.io\"\n[badge-jsr-score]: https://jsr.io/badges/@nick/brocha/score \"View the score for @nick/brocha on jsr.io\"\n[brotli]: https://github.com/google/brotli \"View the Brotli project on GitHub\"\n[npm:brotli]: https://www.npmjs.com/package/brotli \"View the brotli package on npm\"\n[npm:brocha]: https://www.npmjs.com/package/brocha \"View the brocha package on npm\"\n[`BufferSource`]: https://developer.mozilla.org/en-US/docs/Web/API/BufferSource \"MDN Web Docs: BufferSource\"\n","funding_links":["https://ko-fi.com/nberlette"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnberlette%2Fbrocha","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnberlette%2Fbrocha","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnberlette%2Fbrocha/lists"}