buffer-crc32
A tiny, zero-dependency CRC32 checksum library for Buffers and strings in Node.js.
Repository Health
Technical Analysis
buffer-crc32 computes CRC32 checksums for Node.js Buffers and strings, using the reference CRC implementation from the PNG specification. It accepts buffers, strings (including multi-byte Unicode text), or a numeric length to allocate, and returns a 4-byte Buffer by default, with signed() and unsigned() convenience methods available when you need a plain integer instead.
The library supports append/streaming mode, letting you pass a previous CRC value back in to continue a checksum calculation across multiple chunks without buffering the whole payload in memory. It ships with bundled TypeScript type definitions, has zero runtime dependencies, and its CI matrix tests every release against Node 8 through 21, making it a dependable low-level building block for tools that need to validate binary data such as PNG chunks, ZIP archives, or custom binary protocols.
What You Get
- A single default export function that computes CRC32 over a Buffer, string, or allocated-size input and returns a 4-byte Buffer
- signed() and unsigned() convenience methods for getting a plain JavaScript integer instead of a Buffer
- Append-mode support for continuing a CRC32 calculation across multiple chunks by passing in the previous result
- Bundled TypeScript type definitions (index.d.ts) with zero runtime dependencies
Common Use Cases
- Verifying PNG chunk integrity when building or parsing PNG files by hand
- Computing checksums for ZIP archive entries or other binary container formats
- Validating binary payloads received over a network connection or written to disk
- Adding a lightweight data-integrity check to a custom binary protocol
Under The Hood
Architecture buffer-crc32 is a single-file, dependency-free module (index.js) exposing one default export function with two attached methods (signed, unsigned). Internally, ensureBuffer() normalizes the three accepted input shapes (Buffer, string, or an integer treated as an allocation size) into a Buffer, before the core _crc32() function walks the byte array against a precomputed 256-entry Int32Array lookup table (CRC_TABLE) using the standard table-driven CRC32 algorithm derived from the PNG specification’s sample implementation. The public crc32() wrapper packages the signed integer result from _crc32() into a 4-byte Buffer via bufferizeInt(), while .signed() and .unsigned() bypass that step to return a plain JavaScript number. There is no internal layering, dependency injection, or configuration surface — the entire module is a linear pipeline (normalize input, run the CRC loop, format the output), and the only meaningful ‘core abstraction’ is the CRC_TABLE constant itself, which would need regenerating for any polynomial other than the standard CRC-32/ISO-HDLC one used by zlib and PNG.
Tech Stack The package ships as plain CommonJS source (index.js) but is built for dual consumption via unbuild@2.0.0 (build.config.js), producing dist/index.cjs and dist/index.mjs plus copied .d.cts/.d.mts declaration files at publish time (prepublishOnly). Hand-written TypeScript definitions live in index.d.ts. There are zero runtime dependencies; devDependencies are limited to tap for testing and prettier for formatting. The package.json engines field requires Node >=8, and GitHub Actions CI runs the test suite across a matrix from Node 8.x through 21.x on every push/PR, with no separate deployment target since this is a library published to npm.
Code Quality Testing uses tap (tests/crc.test.js) with focused test cases covering buffer input, string input, multi-byte Unicode strings, signed/unsigned output, append-mode chaining across multiple calls, integer-as-length input, and an explicit bad-input error path — a reasonably thorough suite for the module’s small surface area, though there is no coverage reporting configured. Error handling is explicit: ensureBuffer() throws a descriptive Error for any input type other than Buffer, number, or string, rather than failing silently. Naming is short and conventional, consistent with the module’s utility scope; there is no TypeScript source (only hand-authored .d.ts types layered on top of plain JS), and no linter is configured beyond prettier for formatting, so there is no static type-checking or lint gate enforced in CI beyond the test run itself.
API Design The public API is intentionally minimal: a single default export crc32(input, previous?) plus two attached convenience methods, crc32.signed() and crc32.unsigned(), covering the three ways consumers typically want a CRC32 result. Accepting Buffer, string, or an integer (as an allocation size) for the primary argument, and an optional previous CRC (as Buffer or number) for append/streaming mode, keeps the calling convention flat and boilerplate-free — there is no class to instantiate, no options object, and no async ceremony for what is inherently a synchronous computation. The README documents every method with runnable examples including the append-mode pattern, and bundled TypeScript overloads make the call shapes discoverable in an editor, though the append-mode argument order is a detail a first-time caller could easily get backwards without reading the example.