From 1c900bda2fe590e972ae26ff6b7b4d77fd2ba395 Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 16:58:48 -0600 Subject: [PATCH 01/12] rewrite js as ts --- index.js | 11 --- lib/compress-stream.js | 127 ------------------------- lib/uncompress-stream.js | 97 ------------------- src/index.ts | 13 +++ lib/checksum.js => src/lib/checksum.ts | 21 ++-- src/lib/compress-stream.ts | 117 +++++++++++++++++++++++ src/lib/uncompress-stream.ts | 115 ++++++++++++++++++++++ 7 files changed, 258 insertions(+), 243 deletions(-) delete mode 100644 index.js delete mode 100644 lib/compress-stream.js delete mode 100644 lib/uncompress-stream.js create mode 100644 src/index.ts rename lib/checksum.js => src/lib/checksum.ts (55%) create mode 100644 src/lib/compress-stream.ts create mode 100644 src/lib/uncompress-stream.ts diff --git a/index.js b/index.js deleted file mode 100644 index afe7579..0000000 --- a/index.js +++ /dev/null @@ -1,11 +0,0 @@ -var CompressStream = require('./lib/compress-stream') - , UncompressStream = require('./lib/uncompress-stream') - -module.exports = { - createUncompressStream: function (opts) { - return new UncompressStream(opts) - } - , createCompressStream: function (opts) { - return new CompressStream(opts) - } -} \ No newline at end of file diff --git a/lib/compress-stream.js b/lib/compress-stream.js deleted file mode 100644 index a9049fd..0000000 --- a/lib/compress-stream.js +++ /dev/null @@ -1,127 +0,0 @@ -/** - * As per the snappy framing format for streams, the size of any uncompressed chunk can be - * no longer than 65536 bytes. - * - * From: https://github.com/google/snappy/blob/main/framing_format.txt#L90:L92 - */ -const UNCOMPRESSED_CHUNK_SIZE = 65536; - -var Transform = require('stream').Transform - , util = require('util') - - , snappy = require('snappy') - , bufferFrom = require('buffer-from') - - , checksum = require('./checksum') - - , IDENTIFIER_FRAME = bufferFrom([ - 0xff, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61, 0x50, 0x70, 0x59 - ]) - , COMPRESSED = bufferFrom([ 0x00 ]) - , UNCOMPRESSED = bufferFrom([ 0x01 ]) - - , CompressStream = function (opts) { - if (!(this instanceof CompressStream)) - return new CompressStream(opts) - - this.asyncCompress = (opts && typeof(opts.asyncCompress) === 'boolean') ? opts.asyncCompress : false - Transform.call(this) - - // first push the identifier frame - this.push(IDENTIFIER_FRAME) - } - -util.inherits(CompressStream, Transform) - -CompressStream.prototype._compressed = function (chunk, compressed) { - var size = compressed.length + 4 - - this.push( - Buffer.concat([ - COMPRESSED - , bufferFrom([ size, size >> 8, size >> 16 ]) - , checksum(chunk) - , compressed - ]) - ) -} - -CompressStream.prototype._uncompressed = function (chunk) { - var size = chunk.length + 4 - - this.push( - Buffer.concat([ - UNCOMPRESSED - , bufferFrom([ size, size >> 8, size >> 16 ]) - , checksum(chunk) - , chunk - ]) - ) -} - -/** - * Some compression benchmarks : - * - * i) Sync compress via snappy.compressSync ({asyncCompress:false}) default - * ii) Async compress via snappy.compress ({asyncCompress:true}) - * iii) No chunking (Original) - * - * | Size | sync compress | async compress | original (no chunking) | - * |--------------------|---------------|----------------|------------------------| - * | 10kb (1 chunk) | 0.0229 ms | 0.0385 ms | 0.0388 ms | - * | 100kb (2 chunks) | 0.0562 ms | 0.1051 ms | 0.0844 ms | - * | 1000kb (16 chunks) | 0.382 ms | 0.7971 ms | 0.1998 ms | - * - */ - - -CompressStream.prototype._transform = function(chunk, enc, callback) { - const self = this; - - function asyncCompressNext(startFrom) { - const endAt = startFrom + Math.min(chunk.length - startFrom, UNCOMPRESSED_CHUNK_SIZE); - const bytesChunk = chunk.slice(startFrom, endAt); - snappy.compress(bytesChunk, function(err, compressed) { - if (err) { - callback(err) - } else { - - if (compressed.length < bytesChunk.length) - self._compressed(bytesChunk, compressed) - else - self._uncompressed(bytesChunk) - - if (endAt < chunk.length) { - asyncCompressNext(endAt) - } else { - callback() - } - } - }) - } - - function syncCompress() { - try { - for (let startFrom = 0; startFrom < chunk.length; startFrom += UNCOMPRESSED_CHUNK_SIZE) { - const endAt = startFrom + Math.min(chunk.length - startFrom, UNCOMPRESSED_CHUNK_SIZE); - const bytesChunk = chunk.slice(startFrom, endAt); - const compressed = snappy.compressSync(bytesChunk) - - if (compressed.length < bytesChunk.length) - self._compressed(bytesChunk, compressed) - else - self._uncompressed(bytesChunk) - } - callback(); - } catch (err) { - return callback(err); - } - } - if (this.asyncCompress) { - asyncCompressNext(0) - } else { - syncCompress(); - } -} - -module.exports = CompressStream diff --git a/lib/uncompress-stream.js b/lib/uncompress-stream.js deleted file mode 100644 index a29aefd..0000000 --- a/lib/uncompress-stream.js +++ /dev/null @@ -1,97 +0,0 @@ - -var Transform = require('stream').Transform - , util = require('util') - - , bufferEqual = require('buffer-equal') - , bufferFrom = require('buffer-from') - , BufferList = require('bl') - , snappy = require('snappy') - - , IDENTIFIER = bufferFrom([ - 0x73, 0x4e, 0x61, 0x50, 0x70, 0x59 - ]) - , frameSize = function (buffer, offset) { - return buffer.get(offset) + (buffer.get(offset + 1) << 8) + (buffer.get(offset + 2) << 16) - } - , getType = function (value) { - if (value === 0xff) - return 'identifier' - if (value === 0x00) - return 'compressed' - if (value === 0x01) - return 'uncompressed' - if (value === 0xfe) - return 'padding' - // TODO: Handle the other cases described in the spec - } - - , UncompressStream = function (opts) { - var asBuffer = (opts && typeof(opts.asBuffer) === 'boolean') ? opts.asBuffer : true - - Transform.call(this, { objectMode: !asBuffer }) - this.asBuffer = asBuffer - this.foundIdentifier = false - this.buffer = new BufferList() - } - -util.inherits(UncompressStream, Transform) - -UncompressStream.prototype._parse = function (callback) { - if (this.buffer.length < 4) - return callback() - - var self = this - , size = frameSize(this.buffer, 1) - , type = getType(this.buffer.get(0)) - , data = this.buffer.slice(4, 4 + size) - - if (this.buffer.length - 4 < size) - return callback() - - this.buffer.consume(4 + size) - - if (!this.foundIdentifier && type !== 'identifier') - return callback(new Error('malformed input: must begin with an identifier')) - - if (type === 'identifier') { - if(!bufferEqual(data, IDENTIFIER)) - return callback(new Error('malformed input: bad identifier')) - - this.foundIdentifier = true - return this._parse(callback) - } - - if (type === 'compressed') { - // TODO: check that the checksum matches - snappy.uncompress(data.slice(4), { asBuffer: this.asBuffer }, function (err, raw) { - if(err) { - return callback(err) - } - self.push(raw) - self._parse(callback) - }) - return - } - - if (type === 'uncompressed') { - // TODO: check that the checksum matches - data = data.slice(4) - - if (!this.asBuffer) - data = data.toString() - - this.push(data) - this._parse(callback) - } - - if (type === 'padding') { - return this._parse(callback) - } -} - -UncompressStream.prototype._transform = function (chunk, enc, callback) { - this.buffer.append(chunk) - this._parse(callback) -} - -module.exports = UncompressStream \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..ef0b229 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,13 @@ +import { CompressStream, CompressStreamOptions } from './lib/compress-stream'; +import { UncompressStream, UncompressStreamOptions } from './lib/uncompress-stream'; + +export function createUncompressStream(opts?: UncompressStreamOptions): UncompressStream { + return new UncompressStream(opts); +} + +export function createCompressStream(opts?: CompressStreamOptions): CompressStream { + return new CompressStream(opts); +} + +export { CompressStream, UncompressStream }; +export type { CompressStreamOptions, UncompressStreamOptions }; \ No newline at end of file diff --git a/lib/checksum.js b/src/lib/checksum.ts similarity index 55% rename from lib/checksum.js rename to src/lib/checksum.ts index ea78251..430365e 100644 --- a/lib/checksum.js +++ b/src/lib/checksum.ts @@ -1,9 +1,8 @@ -var crc32c = require('@chainsafe/fast-crc32c').calculate -var bufferAlloc = require('buffer-alloc') +import { calculate } from '@chainsafe/fast-crc32c'; -module.exports = function (value) { - var x = crc32c(value) - var result = bufferAlloc(4) +export function checksum(value: Uint8Array): Uint8Array { + const x = calculate(value); + const result = new Uint8Array(4); // As defined in section 3 of https://github.com/google/snappy/blob/master/framing_format.txt // And other implementations for reference: @@ -12,7 +11,13 @@ module.exports = function (value) { // Mask the right hand to (32 - 17) = 15 bits -> 0x7fff, to keep correct 32 bit values. // Shift the left hand with >>> for correct 32 bit intermediate result. // Then final >>> 0 for 32 bits output - result.writeUInt32LE(((((x >>> 15) | ((x & 0x7fff) << 17)) + 0xa282ead8)) >>> 0, 0, true) + const masked = ((((x >>> 15) | ((x & 0x7fff) << 17)) + 0xa282ead8)) >>> 0; + + // Write the 32-bit value in little-endian format + result[0] = masked & 0xff; + result[1] = (masked >> 8) & 0xff; + result[2] = (masked >> 16) & 0xff; + result[3] = (masked >> 24) & 0xff; - return result -} \ No newline at end of file + return result; +} \ No newline at end of file diff --git a/src/lib/compress-stream.ts b/src/lib/compress-stream.ts new file mode 100644 index 0000000..fa7ad77 --- /dev/null +++ b/src/lib/compress-stream.ts @@ -0,0 +1,117 @@ +import { Transform } from 'stream'; +import { compress } from 'snappy'; +import { checksum } from './checksum'; + +/** + * As per the snappy framing format for streams, the size of any uncompressed chunk can be + * no longer than 65536 bytes. + * + * From: https://github.com/google/snappy/blob/main/framing_format.txt#L90:L92 + */ +const UNCOMPRESSED_CHUNK_SIZE = 65536; + +const IDENTIFIER_FRAME = new Uint8Array([ + 0xff, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61, 0x50, 0x70, 0x59 +]); +const COMPRESSED = new Uint8Array([0x00]); +const UNCOMPRESSED = new Uint8Array([0x01]); + +export interface CompressStreamOptions { + asyncCompress?: boolean; +} + +export class CompressStream extends Transform { + private asyncCompress: boolean; + + constructor(opts: CompressStreamOptions = {}) { + super(); + this.asyncCompress = opts.asyncCompress ?? false; + // first push the identifier frame + this.push(IDENTIFIER_FRAME); + } + + private _compressed(chunk: Uint8Array, compressed: Uint8Array): void { + const size = compressed.length + 4; + const sizeBytes = new Uint8Array(3); + sizeBytes[0] = size & 0xff; + sizeBytes[1] = (size >> 8) & 0xff; + sizeBytes[2] = (size >> 16) & 0xff; + + const result = new Uint8Array(1 + 3 + 4 + compressed.length); + result.set(COMPRESSED, 0); + result.set(sizeBytes, 1); + result.set(checksum(chunk), 4); + result.set(compressed, 8); + + this.push(result); + } + + private _uncompressed(chunk: Uint8Array): void { + const size = chunk.length + 4; + const sizeBytes = new Uint8Array(3); + sizeBytes[0] = size & 0xff; + sizeBytes[1] = (size >> 8) & 0xff; + sizeBytes[2] = (size >> 16) & 0xff; + + const result = new Uint8Array(1 + 3 + 4 + chunk.length); + result.set(UNCOMPRESSED, 0); + result.set(sizeBytes, 1); + result.set(checksum(chunk), 4); + result.set(chunk, 8); + + this.push(result); + } + + _transform(chunk: Uint8Array, _enc: string, callback: (error?: Error | null) => void): void { + if (this.asyncCompress) { + this._asyncTransform(chunk, callback); + } else { + this._syncTransform(chunk, callback); + } + } + + private async _asyncTransform(chunk: Uint8Array, callback: (error?: Error | null) => void): Promise { + const processChunk = async (startFrom: number): Promise => { + const endAt = startFrom + Math.min(chunk.length - startFrom, UNCOMPRESSED_CHUNK_SIZE); + const bytesChunk = chunk.slice(startFrom, endAt); + + try { + const compressed = await compress(Buffer.from(bytesChunk)); + if (compressed.length < bytesChunk.length) { + this._compressed(bytesChunk, compressed); + } else { + this._uncompressed(bytesChunk); + } + + if (endAt < chunk.length) { + await processChunk(endAt); + } else { + callback(); + } + } catch (err) { + callback(err as Error); + } + }; + + await processChunk(0); + } + + private async _syncTransform(chunk: Uint8Array, callback: (error?: Error | null) => void): Promise { + try { + for (let i = 0; i < chunk.length; i += UNCOMPRESSED_CHUNK_SIZE) { + const endAt = Math.min(i + UNCOMPRESSED_CHUNK_SIZE, chunk.length); + const bytesChunk = chunk.slice(i, endAt); + const compressed = await compress(Buffer.from(bytesChunk)); + + if (compressed.length < bytesChunk.length) { + this._compressed(bytesChunk, compressed); + } else { + this._uncompressed(bytesChunk); + } + } + callback(); + } catch (err) { + callback(err as Error); + } + } +} \ No newline at end of file diff --git a/src/lib/uncompress-stream.ts b/src/lib/uncompress-stream.ts new file mode 100644 index 0000000..6ef006b --- /dev/null +++ b/src/lib/uncompress-stream.ts @@ -0,0 +1,115 @@ +import { Transform } from 'stream'; +import { uncompress } from 'snappy'; + +const IDENTIFIER = new Uint8Array([ + 0x73, 0x4e, 0x61, 0x50, 0x70, 0x59 +]); + +export interface UncompressStreamOptions { + asBuffer?: boolean; +} + +type FrameType = 'identifier' | 'compressed' | 'uncompressed' | 'padding'; + +export class UncompressStream extends Transform { + private asBuffer: boolean; + private foundIdentifier: boolean; + private buffer: Uint8Array[]; + + constructor(opts: UncompressStreamOptions = {}) { + super({ objectMode: !opts.asBuffer }); + this.asBuffer = opts.asBuffer ?? true; + this.foundIdentifier = false; + this.buffer = []; + } + + private frameSize(buffer: Uint8Array, offset: number): number { + return buffer[offset] + (buffer[offset + 1] << 8) + (buffer[offset + 2] << 16); + } + + private getType(value: number): FrameType { + if (value === 0xff) return 'identifier'; + if (value === 0x00) return 'compressed'; + if (value === 0x01) return 'uncompressed'; + if (value === 0xfe) return 'padding'; + throw new Error('unknown frame type'); + } + + private concatBuffers(): Uint8Array { + const totalLength = this.buffer.reduce((sum, buf) => sum + buf.length, 0); + const result = new Uint8Array(totalLength); + let offset = 0; + for (const buf of this.buffer) { + result.set(buf, offset); + offset += buf.length; + } + return result; + } + + private _parse(callback: (error?: Error | null) => void): void { + const buffer = this.concatBuffers(); + if (buffer.length < 4) { + return callback(); + } + + const size = this.frameSize(buffer, 1); + const type = this.getType(buffer[0]); + const data = buffer.slice(4, 4 + size); + + if (buffer.length - 4 < size) { + return callback(); + } + + this.buffer = [buffer.slice(4 + size)]; + + if (!this.foundIdentifier && type !== 'identifier') { + return callback(new Error('malformed input: must begin with an identifier')); + } + + if (type === 'identifier') { + if (!this.areEqual(data, IDENTIFIER)) { + return callback(new Error('malformed input: bad identifier')); + } + this.foundIdentifier = true; + return this._parse(callback); + } + + if (type === 'compressed') { + // TODO: check that the checksum matches + uncompress(Buffer.from(data.slice(4)), { asBuffer: this.asBuffer }) + .then((raw) => { + this.push(raw); + this._parse(callback); + }) + .catch((err) => { + callback(err); + }); + return; + } + + if (type === 'uncompressed') { + // TODO: check that the checksum matches + const result = data.slice(4); + this.push(this.asBuffer ? result : new TextDecoder().decode(result)); + this._parse(callback); + return; + } + + if (type === 'padding') { + return this._parse(callback); + } + } + + private areEqual(a: Uint8Array, b: Uint8Array): boolean { + if (a.length !== b.length) return false; + for (let i = 0; i < a.length; i++) { + if (a[i] !== b[i]) return false; + } + return true; + } + + _transform(chunk: Uint8Array, _enc: string, callback: (error?: Error | null) => void): void { + this.buffer.push(chunk); + this._parse(callback); + } +} \ No newline at end of file From 3449fc07d492201daccc42928c1de2815d6e9b72 Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 17:00:02 -0600 Subject: [PATCH 02/12] update and remove dependencies --- package.json | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index fb95368..137ed86 100644 --- a/package.json +++ b/package.json @@ -17,16 +17,14 @@ ], "license": "MIT", "devDependencies": { - "async-benchmark": "^1.0.0", - "tap": "^11.0.1" + "@types/node": "^22.15.3", + "typescript": "^5.8.3", + "vitest": "^3.1.2", + "tsx": "^4.19.1" }, "dependencies": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "buffer-equal": "1.0.0", - "buffer-from": "^1.1.1", - "@chainsafe/fast-crc32c": "^4.0.0", - "snappy": "^6.3.5" + "@chainsafe/fast-crc32c": "^4.2.0", + "snappy": "^7.2.2" }, "directories": { "test": "test" From 61a37ab780f315ffe7c9e31cdb682ec6cab78e0e Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 17:00:30 -0600 Subject: [PATCH 03/12] rewrite tests in vitest --- test/checksum-test.js | 44 ------- test/checksum.test.ts | 24 ++++ test/compress-test.js | 66 ---------- test/compress.test.ts | 76 ++++++++++++ test/uncompress-test.js | 267 ---------------------------------------- test/uncompress.test.ts | 92 ++++++++++++++ 6 files changed, 192 insertions(+), 377 deletions(-) delete mode 100644 test/checksum-test.js create mode 100644 test/checksum.test.ts delete mode 100644 test/compress-test.js create mode 100644 test/compress.test.ts delete mode 100644 test/uncompress-test.js create mode 100644 test/uncompress.test.ts diff --git a/test/checksum-test.js b/test/checksum-test.js deleted file mode 100644 index 285a483..0000000 --- a/test/checksum-test.js +++ /dev/null @@ -1,44 +0,0 @@ -var checksum = require("../lib/checksum"); -var fs = require("fs"); -var join = require("path").join; -var test = require("tap").test; -var bufferAlloc = require('buffer-alloc') - -function bufferToArray(buffer) { - var array = new Array(buffer.length); - for (var i = 0; i < buffer.length; ++i) { - array[i] = buffer[i]; - } - return array; -} - -if ("UPDATE_EXPECTED" in process.env) { - var expectedRows = []; - for (var i = 0; i < 1000; ++i) { - var buffer = bufferAlloc(1); - buffer[0] = i; - - console.log(checksum(buffer)); - - expectedRows.push(bufferToArray(checksum(buffer))); - } - - fs.writeFileSync( - join(__dirname, "checksum.expected"), - JSON.stringify(expectedRows) - ); -} - -var expectedRows = JSON.parse( - fs.readFileSync(join(__dirname, "checksum.expected")) -); - -test("Checksum", function (t) { - expectedRows.forEach(function (expected, index) { - var buffer = bufferAlloc(1); - buffer[0] = index; - var actual = bufferToArray(checksum(buffer)); - t.deepEqual(actual, expected, 'Buffer created from ' + index); - }); - t.end(); -}); diff --git a/test/checksum.test.ts b/test/checksum.test.ts new file mode 100644 index 0000000..8f52cc3 --- /dev/null +++ b/test/checksum.test.ts @@ -0,0 +1,24 @@ +import { describe, it, expect } from 'vitest'; +import { checksum } from '../src/lib/checksum'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +function bufferToArray(buffer: Uint8Array): number[] { + return Array.from(buffer); +} + +// Read the expected test data +const expectedRows = JSON.parse( + readFileSync(join(__dirname, 'checksum.expected'), 'utf-8') +); + +describe('Checksum', () => { + it('should match expected checksums for values 0-999', () => { + expectedRows.forEach((expected: number[], index: number) => { + const buffer = new Uint8Array(1); + buffer[0] = index; + const actual = bufferToArray(checksum(buffer)); + expect(actual).toEqual(expected); + }); + }); +}); \ No newline at end of file diff --git a/test/compress-test.js b/test/compress-test.js deleted file mode 100644 index fd5d57d..0000000 --- a/test/compress-test.js +++ /dev/null @@ -1,66 +0,0 @@ -const spawn = require('child_process').spawn, - createCompressStream = require('../').createCompressStream, - test = require('tap').test, - largerInput = require('fs').readFileSync(__filename) - -const UNCOMPRESSED_CHUNK_SIZE = 65536 -let superLargeInput = largerInput; -for (let i = largerInput.length; i <= UNCOMPRESSED_CHUNK_SIZE; i += largerInput.length) { - superLargeInput = Buffer.concat([superLargeInput, largerInput]); -} - -[{ - testName: "small", - testString: "beep boop", - asyncCompress: true -}, { - testName: "small", - testString: "beep boop", - asyncCompress: false -}, { - testName: "large", - testString: largerInput, - asyncCompress: true -}, { - testName: "large", - testString: largerInput, - asyncCompress: false -}, { - testName: "super large", - testString: superLargeInput, - asyncCompress: true -}, { - testName: "super large", - testString: superLargeInput, - asyncCompress: false -}].forEach(({ - testName, - testString, - asyncCompress -}) => { - - test(`compress ${testName} input - asyncCompress=${asyncCompress}`, function(t) { - const child = spawn('python', ['-m', 'snappy', '-d']), - compressStream = createCompressStream({ - asyncCompress - }) - let data = '' - - child.stdout.on('data', function(chunk) { - data = data + chunk.toString() - }) - - child.stdout.on('end', function() { - t.equal(data, testString.toString()) - t.end() - }) - - child.stderr.pipe(process.stderr) - - compressStream.pipe(child.stdin) - - compressStream.write(testString) - compressStream.end() - }) - -}) \ No newline at end of file diff --git a/test/compress.test.ts b/test/compress.test.ts new file mode 100644 index 0000000..39c4e4a --- /dev/null +++ b/test/compress.test.ts @@ -0,0 +1,76 @@ +import { createCompressStream, createUncompressStream } from '../src'; +import { assert, describe, it } from 'vitest'; +import { readFileSync } from 'fs'; + +const UNCOMPRESSED_CHUNK_SIZE = 65536; +const largerInput = readFileSync(__filename); +let superLargeInput = new Uint8Array(largerInput); +for (let i = largerInput.length; i <= UNCOMPRESSED_CHUNK_SIZE; i += largerInput.length) { + superLargeInput = new Uint8Array([...superLargeInput, ...largerInput]); +} + +const testCases = [ + { + testName: "small", + testString: "beep boop", + asyncCompress: true + }, + { + testName: "small", + testString: "beep boop", + asyncCompress: false + }, + { + testName: "large", + testString: largerInput, + asyncCompress: true + }, + { + testName: "large", + testString: largerInput, + asyncCompress: false + }, + { + testName: "super large", + testString: superLargeInput, + asyncCompress: true + }, + { + testName: "super large", + testString: superLargeInput, + asyncCompress: false + } +]; + +describe('compress', () => { + testCases.forEach(({ testName, testString, asyncCompress }) => { + it(`should compress ${testName} input - asyncCompress=${asyncCompress}`, async () => { + const decompressed = await new Promise((resolve, reject) => { + const compressStream = createCompressStream({ asyncCompress }); + const uncompressStream = createUncompressStream(); + const chunks: Uint8Array[] = []; + + uncompressStream.on('data', (chunk: Uint8Array) => { + chunks.push(chunk); + }); + + uncompressStream.on('end', () => { + const result = Buffer.concat(chunks); + resolve(result); + }); + + uncompressStream.on('error', reject); + compressStream.on('error', reject); + + compressStream.pipe(uncompressStream); + compressStream.write(testString); + compressStream.end(); + }); + + const expected = typeof testString === 'string' + ? Buffer.from(testString) + : Buffer.from(testString); + assert.deepEqual(decompressed, expected); + }); + }); +}); \ No newline at end of file diff --git a/test/uncompress-test.js b/test/uncompress-test.js deleted file mode 100644 index af5975a..0000000 --- a/test/uncompress-test.js +++ /dev/null @@ -1,267 +0,0 @@ -var spawn = require('child_process').spawn - - , createUncompressStream = require('../').createUncompressStream - , test = require('tap').test - , bufferFrom = require('buffer-from') - - , largerInput = require('fs').readFileSync(__filename) - , largerInputString = largerInput.toString() - -test('uncompress small string', function (t) { - var child = spawn('python', [ '-m', 'snappy', '-c' ]) - , uncompressStream = createUncompressStream({ asBuffer: false }) - , data = '' - - uncompressStream.on('data', function (chunk) { - data = data + chunk - t.equal(typeof(chunk), 'string') - }) - - uncompressStream.on('end', function () { - t.equal(data, 'beep boop') - t.end() - }) - - child.stdout.pipe(uncompressStream) - - child.stdin.write('beep boop') - child.stdin.end() -}) - -test('uncompress small Buffer', function (t) { - var child = spawn('python', [ '-m', 'snappy', '-c' ]) - , uncompressStream = createUncompressStream() - , data = [] - - uncompressStream.on('data', function (chunk) { - data.push(chunk) - t.ok(Buffer.isBuffer(chunk)) - }) - - uncompressStream.on('end', function () { - t.deepEqual(Buffer.concat(data), bufferFrom('beep boop')) - t.end() - }) - - child.stdout.pipe(uncompressStream) - - child.stdin.write(bufferFrom('beep boop')) - child.stdin.end() -}) - -test('uncompress large string', function (t) { - var child = spawn('python', [ '-m', 'snappy', '-c' ]) - , uncompressStream = createUncompressStream({ asBuffer: false }) - , data = '' - - uncompressStream.on('data', function (chunk) { - data = data + chunk - t.equal(typeof(chunk), 'string') - }) - - uncompressStream.on('end', function () { - t.equal(data, largerInputString) - t.end() - }) - - child.stdout.pipe(uncompressStream) - - child.stdin.write(largerInput) - child.stdin.end() -}) - -test('uncompress large string', function (t) { - var child = spawn('python', [ '-m', 'snappy', '-c' ]) - , uncompressStream = createUncompressStream() - , data = [] - - uncompressStream.on('data', function (chunk) { - data.push(chunk) - t.ok(Buffer.isBuffer(chunk)) - }) - - uncompressStream.on('end', function () { - t.deepEqual(Buffer.concat(data), largerInput) - t.end() - }) - - - child.stdout.pipe(uncompressStream) - - child.stdin.write(largerInput) - child.stdin.end() -}) - -test('uncompress with bad identifier', function (t) { - var uncompressStream = createUncompressStream() - - uncompressStream.on('error', function (err) { - t.equal(err.message, 'malformed input: bad identifier') - t.end() - }) - - uncompressStream.write( - bufferFrom([ 0xff, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61, 0x50, 0x70, 0x60 ]) - ) - uncompressStream.end() -}) - -test('uncompress with bad first frame', function (t) { - var uncompressStream = createUncompressStream() - - uncompressStream.on('error', function (err) { - t.equal(err.message, 'malformed input: must begin with an identifier') - t.end() - }) - - uncompressStream.write( - bufferFrom([ 0x0, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61, 0x50, 0x70, 0x60 ]) - ) - uncompressStream.end() -}) - -test('uncompress large String in small pieces', function (t) { - var child = spawn('python', [ '-m', 'snappy', '-c' ]) - , uncompressStream = createUncompressStream() - , data = [] - - uncompressStream.on('data', function (chunk) { - data.push(chunk) - t.ok(Buffer.isBuffer(chunk)) - }) - - uncompressStream.on('end', function () { - t.deepEqual(Buffer.concat(data), largerInput) - t.end() - }) - - child.stdout.on('data', function (chunk) { - var i = 0; - - while (i < chunk.length) { - uncompressStream.write(bufferFrom([ chunk[i] ])) - i++ - } - }) - - child.stdout.once('end', function () { - uncompressStream.end() - }) - - child.stdin.write(largerInput) - child.stdin.end() -}) - -test('uncompress small Buffer across multiple chunks', function (t) { - var uncompressStream = createUncompressStream() - , data = [] - , IDENTIFIER = bufferFrom([ - 0xff, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61, 0x50, 0x70, 0x59 - ]) - - uncompressStream.on('data', function (chunk) { - data.push(chunk) - t.ok(Buffer.isBuffer(chunk)) - }) - - uncompressStream.on('end', function () { - t.deepEqual(Buffer.concat(data), bufferFrom('beep boop')) - t.end() - }) - - // identifier - uncompressStream.write(IDENTIFIER) - // "beep" - uncompressStream.write(bufferFrom([0x01, 0x08, 0x00, 0x00, 0xfb, 0x5e, 0xc9, 0x6e, 0x62, 0x65, 0x65, 0x70])) - // " boop" - uncompressStream.write(bufferFrom([0x01, 0x09, 0x00, 0x00, 0x5f, 0xae, 0xb4, 0x84, 0x20, 0x62, 0x6f, 0x6f, 0x70])) - uncompressStream.end() -}) - -test('uncompress large string across multiple chunks', function (t) { - var child1 = spawn('python', [ '-m', 'snappy', '-c' ]) - , IDENTIFIER = bufferFrom([ - 0xff, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61, 0x50, 0x70, 0x59 - ]) - , uncompressStream = createUncompressStream({ asBuffer: false }) - , data = '' - - uncompressStream.on('data', function (chunk) { - data = data + chunk - t.equal(typeof(chunk), 'string') - }) - - uncompressStream.on('end', function () { - t.equal(data, largerInputString + largerInputString) - t.end() - }) - - // manually pipe processes in so we can remove identifiers - child1.stdout.on('data', function(chunk) { - uncompressStream.write(chunk.slice(10)) - }) - - child1.once('close', function () { - var child2 = spawn('python', [ '-m', 'snappy', '-c' ]) - - child2.stdout.on('data', function(chunk) { - uncompressStream.write(chunk.slice(10)) - uncompressStream.end() - }) - - // trigger second write after first write - child2.stdin.write(largerInput) - child2.stdin.end() - }) - - // write identifier only once - uncompressStream.write(IDENTIFIER) - - child1.stdin.write(largerInput) - child1.stdin.end() -}) - -test('uncompress large string with padding chunks', function (t) { - var child1 = spawn('python', [ '-m', 'snappy', '-c' ]) - , IDENTIFIER = bufferFrom([ - 0xff, 0x06, 0x00, 0x00, 0x73, 0x4e, 0x61, 0x50, 0x70, 0x59 - ]) - , uncompressStream = createUncompressStream({ asBuffer: false }) - , data = '' - - uncompressStream.on('data', function (chunk) { - data = data + chunk - t.equal(typeof(chunk), 'string') - }) - - uncompressStream.on('end', function () { - t.equal(data, largerInputString + largerInputString) - t.end() - }) - - // manually pipe processes in so we can remove identifiers - child1.stdout.on('data', function(chunk) { - uncompressStream.write(chunk.slice(10)) - // padding - uncompressStream.write(Buffer.from([0xfe, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])) - }) - - child1.on('close', () => { - var child2 = spawn('python', [ '-m', 'snappy', '-c' ]) - - child2.stdout.on('data', function(chunk) { - uncompressStream.write(chunk.slice(10)) - uncompressStream.end() - }) - - // trigger second write after first write - child2.stdin.write(largerInput) - child2.stdin.end() - }) - - // write identifier only once - uncompressStream.write(IDENTIFIER) - - child1.stdin.write(largerInput) - child1.stdin.end() -}) \ No newline at end of file diff --git a/test/uncompress.test.ts b/test/uncompress.test.ts new file mode 100644 index 0000000..9a5a403 --- /dev/null +++ b/test/uncompress.test.ts @@ -0,0 +1,92 @@ +import { createCompressStream, createUncompressStream } from '../src'; +import { assert, describe, it } from 'vitest'; +import { readFileSync } from 'fs'; + +const UNCOMPRESSED_CHUNK_SIZE = 65536; +const largerInput = readFileSync(__filename); +let superLargeInput = new Uint8Array(largerInput); +for (let i = largerInput.length; i <= UNCOMPRESSED_CHUNK_SIZE; i += largerInput.length) { + superLargeInput = new Uint8Array([...superLargeInput, ...largerInput]); +} + +const testCases = [ + { + testName: "small string", + input: "beep boop", + asBuffer: false + }, + { + testName: "small buffer", + input: new TextEncoder().encode("beep boop"), + asBuffer: true + }, + { + testName: "large string", + input: new TextDecoder().decode(largerInput), + asBuffer: false + }, + { + testName: "large buffer", + input: largerInput, + asBuffer: true + }, + { + testName: "super large string", + input: new TextDecoder().decode(superLargeInput), + asBuffer: false + }, + { + testName: "super large buffer", + input: superLargeInput, + asBuffer: true + } +]; + +describe('uncompress', () => { + testCases.forEach(({ testName, input, asBuffer }) => { + it(`should uncompress ${testName}`, async () => { + const decompressed = await new Promise((resolve, reject) => { + const compressStream = createCompressStream(); + const uncompressStream = createUncompressStream({ asBuffer }); + const chunks: (string | Uint8Array)[] = []; + + uncompressStream.on('data', (chunk: string | Uint8Array) => { + chunks.push(chunk); + }); + + uncompressStream.on('end', () => { + const result = asBuffer + ? Buffer.concat(chunks as Uint8Array[]) + : (chunks as string[]).join(''); + resolve(result); + }); + + uncompressStream.on('error', reject); + compressStream.on('error', reject); + + compressStream.pipe(uncompressStream); + compressStream.write(input); + compressStream.end(); + }); + + const expected = typeof input === 'string' + ? input + : Buffer.from(input); + assert.deepEqual(decompressed, expected); + }); + }); + + it('should handle bad identifier', async () => { + return new Promise((resolve, reject) => { + const uncompressStream = createUncompressStream(); + + uncompressStream.on('error', (err: Error) => { + assert.equal(err.message, 'malformed input: bad identifier'); + resolve(undefined); + }); + + uncompressStream.write(new Uint8Array([0xff, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])); + uncompressStream.end(); + }); + }); +}); \ No newline at end of file From 9ef12c37b7e51a3cbf3354957db005414d2c685b Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 17:00:44 -0600 Subject: [PATCH 04/12] config files --- tsconfig.json | 17 +++++++++++++++++ vitest.config.ts | 8 ++++++++ 2 files changed, 25 insertions(+) create mode 100644 tsconfig.json create mode 100644 vitest.config.ts diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9c6e414 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "CommonJS", + "lib": ["ES2022"], + "declaration": true, + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "test"] +} \ No newline at end of file diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..8d2baed --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + environment: 'node', + include: ['test/**/*.test.ts'], + }, +}); \ No newline at end of file From d8c0f58ae7931f961952489a7a00b5a4e4cdb9dc Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 17:00:53 -0600 Subject: [PATCH 05/12] rewrite example in ts --- example.js | 19 ------------------- example.ts | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 19 deletions(-) delete mode 100644 example.js create mode 100644 example.ts diff --git a/example.js b/example.js deleted file mode 100644 index 87f2475..0000000 --- a/example.js +++ /dev/null @@ -1,19 +0,0 @@ -var snappyStream = require('./index.js') - , compressStream = snappyStream.createCompressStream() - , uncompressStream = snappyStream.createUncompressStream({ - asBuffer: false // optional option, asBuffer = false means that the stream emits strings, default: true - }) - -compressStream.on('data', function (chunk) { - console.log('Som data from the compressed stream', chunk) - uncompressStream.write(chunk) -}) - -uncompressStream.on('data', function (chunk) { - console.log('The data that was originally written') - console.log(chunk) -}) - -compressStream.write('hello') -compressStream.write('world') -compressStream.end() \ No newline at end of file diff --git a/example.ts b/example.ts new file mode 100644 index 0000000..d8bd6ef --- /dev/null +++ b/example.ts @@ -0,0 +1,23 @@ +import { createCompressStream, createUncompressStream } from './src/index.ts'; + +// Create streams with proper type annotations +const compressStream = createCompressStream(); +const uncompressStream = createUncompressStream({ + asBuffer: false // Optional: emit strings instead of buffers +}); + +// Set up event handlers with proper types +compressStream.on('data', (chunk: Uint8Array) => { + console.log('Some data from the compressed stream:', chunk); + uncompressStream.write(chunk); +}); + +uncompressStream.on('data', (chunk: string) => { + console.log('The data that was originally written:'); + console.log(chunk); +}); + +// Write some data +compressStream.write('hello'); +compressStream.write('world'); +compressStream.end(); \ No newline at end of file From c3b1164b1f0819ff027aa842632802e65c5c25c0 Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 17:01:02 -0600 Subject: [PATCH 06/12] delete benchmark.js --- benchmark.js | 81 ---------------------------------------------------- 1 file changed, 81 deletions(-) delete mode 100644 benchmark.js diff --git a/benchmark.js b/benchmark.js deleted file mode 100644 index 02b4d00..0000000 --- a/benchmark.js +++ /dev/null @@ -1,81 +0,0 @@ -var benchmark = require('async-benchmark') - , input = Buffer.concat([ - require('fs').readFileSync(__dirname + '/lib/compress-stream.js') - , require('fs').readFileSync(__dirname + '/lib/uncompress-stream.js') - , require('fs').readFileSync(__dirname + '/index.js') - ]) - , snappy = require('./') - , zlib = require('zlib') - , exec = require('child_process').exec - - , benchmarkSnappy = function (callback) { - var stream = snappy.createCompressStream() - - // read the initial identifier frame - stream.once('data', function () { - benchmark( - 'snappyStream.createCompressStream()' - , function (done) { - // read data twice - first emitted chunk is the header - // and the second one is the payload - stream.once('data', done) - stream.write(input) - } - , function (err, event) { - console.log(event.target.toString()) - } - ) - }) - } - , benchmarkGzip = function (callback) { - var stream = zlib.createGzip({ - flush: zlib.Z_FULL_FLUSH - }) - - benchmark( - 'zlib.createGzip()' - , function (done) { - stream.once('data', done) - stream.write(input) - } - , function (err, event) { - console.log(event.target.toString()) - } - ) - } - , benchmarkPassThrough = function (callback) { - var stream = require('stream').PassThrough() - benchmark( - 'passthrough stream (no compression)' - , function (done) { - stream.once('data', done) - stream.write(input) - } - , function (err, event) { - console.log(event.target.toString()) - } - ) - } - , runBenchmarks = function () { - exec('node ' + __filename + ' passthrough', function (err, stdout) { - process.stdout.write(stdout) - exec('node ' + __filename + ' gzip', function (err, stdout) { - process.stdout.write(stdout) - exec('node ' + __filename + ' snappy', function (err, stdout) { - process.stdout.write(stdout) - }) - }) - }) - } - -if (process.argv[2] === 'snappy') - benchmarkSnappy() - -else if (process.argv[2] === 'gzip') - benchmarkGzip() - -else if (process.argv[2] === 'passthrough') - benchmarkPassThrough() - -else - runBenchmarks() \ No newline at end of file From cbe499a3a269fda845a38656de094368bf4ef9a0 Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 17:01:26 -0600 Subject: [PATCH 07/12] delete changelog --- CHANGELOG.md | 66 ---------------------------------------------------- 1 file changed, 66 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index d173212..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,66 +0,0 @@ -# Changelog - -## [5.1.2](https://github.com/ChainSafe/node-snappy-stream/compare/v5.1.1...v5.1.2) (2023-01-12) - - -### Bug Fixes - -* migrate to @chainsafe/fast-crc32c 4.0.0 ([#17](https://github.com/ChainSafe/node-snappy-stream/issues/17)) ([fb67a6c](https://github.com/ChainSafe/node-snappy-stream/commit/fb67a6c53681c567b7457ad8ea6f4df428b13843)) - - -### Miscellaneous - -* update readme ([78b25c2](https://github.com/ChainSafe/node-snappy-stream/commit/78b25c2e07559d1ca57b5f6da6cc2d1d7a6343a6)) - -### [5.1.1](https://github.com/ChainSafe/node-snappy-stream/compare/v5.1.0...v5.1.1) (2022-04-28) - - -### Bug Fixes - -* Fix self reference ([#11](https://github.com/ChainSafe/node-snappy-stream/issues/11)) ([2b11904](https://github.com/ChainSafe/node-snappy-stream/commit/2b119040d9c6fcdaf94c504deb3e6a839f6251ba)) - -## [5.1.0](https://github.com/ChainSafe/node-snappy-stream/compare/v5.0.3...v5.1.0) (2022-04-27) - - -### Features - -* add async chunk compress ([#6](https://github.com/ChainSafe/node-snappy-stream/issues/6)) ([29d3780](https://github.com/ChainSafe/node-snappy-stream/commit/29d378012bc7a1e612e3c8c5b9cef32b5cb6c04f)) - -### [5.0.3](https://github.com/ChainSafe/node-snappy-stream/compare/v5.0.2...v5.0.3) (2022-04-27) - - -### Bug Fixes - -* compressor didn't chunkify big payload ([#3](https://github.com/ChainSafe/node-snappy-stream/issues/3)) ([a658af0](https://github.com/ChainSafe/node-snappy-stream/commit/a658af0c165d2b7885f99aa7b6e297f93d530701)) - - -### Miscellaneous - -* automatic release ([#4](https://github.com/ChainSafe/node-snappy-stream/issues/4)) ([2051ada](https://github.com/ChainSafe/node-snappy-stream/commit/2051ada25695c0f8f381b638435d47a2c759bde0)) -* **master:** release 5.0.1 ([#5](https://github.com/ChainSafe/node-snappy-stream/issues/5)) ([f646c2f](https://github.com/ChainSafe/node-snappy-stream/commit/f646c2f1be28e03ffca60e2633614a188dd39c17)) -* **master:** release 5.0.2 ([#8](https://github.com/ChainSafe/node-snappy-stream/issues/8)) ([7967349](https://github.com/ChainSafe/node-snappy-stream/commit/7967349142fce27eb67750c67957039858cee2a7)) - -### [5.0.2](https://github.com/ChainSafe/node-snappy-stream/compare/v5.0.1...v5.0.2) (2022-04-27) - - -### Bug Fixes - -* compressor didn't chunkify big payload ([#3](https://github.com/ChainSafe/node-snappy-stream/issues/3)) ([a658af0](https://github.com/ChainSafe/node-snappy-stream/commit/a658af0c165d2b7885f99aa7b6e297f93d530701)) - - -### Miscellaneous - -* automatic release ([#4](https://github.com/ChainSafe/node-snappy-stream/issues/4)) ([2051ada](https://github.com/ChainSafe/node-snappy-stream/commit/2051ada25695c0f8f381b638435d47a2c759bde0)) -* **master:** release 5.0.1 ([#5](https://github.com/ChainSafe/node-snappy-stream/issues/5)) ([f646c2f](https://github.com/ChainSafe/node-snappy-stream/commit/f646c2f1be28e03ffca60e2633614a188dd39c17)) - -### [5.0.1](https://github.com/ChainSafe/node-snappy-stream/compare/v5.0.0...v5.0.1) (2022-04-26) - - -### Bug Fixes - -* compressor didn't chunkify big payload ([#3](https://github.com/ChainSafe/node-snappy-stream/issues/3)) ([a658af0](https://github.com/ChainSafe/node-snappy-stream/commit/a658af0c165d2b7885f99aa7b6e297f93d530701)) - - -### Miscellaneous - -* automatic release ([#4](https://github.com/ChainSafe/node-snappy-stream/issues/4)) ([2051ada](https://github.com/ChainSafe/node-snappy-stream/commit/2051ada25695c0f8f381b638435d47a2c759bde0)) From 499f6b9660665ca84d2e1e7f2a26b98c3556bc6d Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 17:03:22 -0600 Subject: [PATCH 08/12] update package.json --- package-lock.json | 2091 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 26 +- 2 files changed, 2108 insertions(+), 9 deletions(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..ba1ac6c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2091 @@ +{ + "name": "@chainsafe/snappy-stream", + "version": "6.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@chainsafe/snappy-stream", + "version": "6.0.0", + "license": "MIT", + "dependencies": { + "@chainsafe/fast-crc32c": "^4.2.0", + "snappy": "^7.2.2" + }, + "devDependencies": { + "@types/node": "^22.15.3", + "tsx": "^4.19.1", + "typescript": "^5.8.3", + "vitest": "^3.1.2" + }, + "engines": { + "node": ">=22.14.0" + } + }, + "node_modules/@chainsafe/fast-crc32c": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@chainsafe/fast-crc32c/-/fast-crc32c-4.2.0.tgz", + "integrity": "sha512-wbVJ3q1DBuYqs1VGwLe9o5VIDQtxGpSVzr7UY9Hq2SQ283fU6AouII/pwioS9MbiiIK42jDxtY0uLFmTuenb0g==", + "license": "MIT", + "optionalDependencies": { + "@node-rs/crc32": "^1.10.6" + } + }, + "node_modules/@emnapi/core": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", + "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", + "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", + "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", + "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", + "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", + "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", + "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", + "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", + "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", + "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", + "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", + "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", + "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", + "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", + "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", + "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", + "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", + "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", + "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", + "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", + "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", + "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", + "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", + "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", + "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", + "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", + "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@napi-rs/snappy-android-arm-eabi": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm-eabi/-/snappy-android-arm-eabi-7.2.2.tgz", + "integrity": "sha512-H7DuVkPCK5BlAr1NfSU8bDEN7gYs+R78pSHhDng83QxRnCLmVIZk33ymmIwurmoA1HrdTxbkbuNl+lMvNqnytw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-android-arm64": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-android-arm64/-/snappy-android-arm64-7.2.2.tgz", + "integrity": "sha512-2R/A3qok+nGtpVK8oUMcrIi5OMDckGYNoBLFyli3zp8w6IArPRfg1yOfVUcHvpUDTo9T7LOS1fXgMOoC796eQw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-darwin-arm64": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-arm64/-/snappy-darwin-arm64-7.2.2.tgz", + "integrity": "sha512-USgArHbfrmdbuq33bD5ssbkPIoT7YCXCRLmZpDS6dMDrx+iM7eD2BecNbOOo7/v1eu6TRmQ0xOzeQ6I/9FIi5g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-darwin-x64": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-darwin-x64/-/snappy-darwin-x64-7.2.2.tgz", + "integrity": "sha512-0APDu8iO5iT0IJKblk2lH0VpWSl9zOZndZKnBYIc+ei1npw2L5QvuErFOTeTdHBtzvUHASB+9bvgaWnQo4PvTQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-freebsd-x64": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-freebsd-x64/-/snappy-freebsd-x64-7.2.2.tgz", + "integrity": "sha512-mRTCJsuzy0o/B0Hnp9CwNB5V6cOJ4wedDTWEthsdKHSsQlO7WU9W1yP7H3Qv3Ccp/ZfMyrmG98Ad7u7lG58WXA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-linux-arm-gnueabihf": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm-gnueabihf/-/snappy-linux-arm-gnueabihf-7.2.2.tgz", + "integrity": "sha512-v1uzm8+6uYjasBPcFkv90VLZ+WhLzr/tnfkZ/iD9mHYiULqkqpRuC8zvc3FZaJy5wLQE9zTDkTJN1IvUcZ+Vcg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-linux-arm64-gnu": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-gnu/-/snappy-linux-arm64-gnu-7.2.2.tgz", + "integrity": "sha512-LrEMa5pBScs4GXWOn6ZYXfQ72IzoolZw5txqUHVGs8eK4g1HR9HTHhb2oY5ySNaKakG5sOgMsb1rwaEnjhChmQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-linux-arm64-musl": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-arm64-musl/-/snappy-linux-arm64-musl-7.2.2.tgz", + "integrity": "sha512-3orWZo9hUpGQcB+3aTLW7UFDqNCQfbr0+MvV67x8nMNYj5eAeUtMmUE/HxLznHO4eZ1qSqiTwLbVx05/Socdlw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-linux-x64-gnu": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-gnu/-/snappy-linux-x64-gnu-7.2.2.tgz", + "integrity": "sha512-jZt8Jit/HHDcavt80zxEkDpH+R1Ic0ssiVCoueASzMXa7vwPJeF4ZxZyqUw4qeSy7n8UUExomu8G8ZbP6VKhgw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-linux-x64-musl": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-linux-x64-musl/-/snappy-linux-x64-musl-7.2.2.tgz", + "integrity": "sha512-Dh96IXgcZrV39a+Tej/owcd9vr5ihiZ3KRix11rr1v0MWtVb61+H1GXXlz6+Zcx9y8jM1NmOuiIuJwkV4vZ4WA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-win32-arm64-msvc": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-arm64-msvc/-/snappy-win32-arm64-msvc-7.2.2.tgz", + "integrity": "sha512-9No0b3xGbHSWv2wtLEn3MO76Yopn1U2TdemZpCaEgOGccz1V+a/1d16Piz3ofSmnA13HGFz3h9NwZH9EOaIgYA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-win32-ia32-msvc": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-ia32-msvc/-/snappy-win32-ia32-msvc-7.2.2.tgz", + "integrity": "sha512-QiGe+0G86J74Qz1JcHtBwM3OYdTni1hX1PFyLRo3HhQUSpmi13Bzc1En7APn+6Pvo7gkrcy81dObGLDSxFAkQQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/snappy-win32-x64-msvc": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/snappy-win32-x64-msvc/-/snappy-win32-x64-msvc-7.2.2.tgz", + "integrity": "sha512-a43cyx1nK0daw6BZxVcvDEXxKMFLSBSDTAhsFD0VqSKcC7MGUBMaqyoWUcMiI7LBSz4bxUmxDWKfCYzpEmeb3w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.9.tgz", + "integrity": "sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.0", + "@emnapi/runtime": "^1.4.0", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@node-rs/crc32": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32/-/crc32-1.10.6.tgz", + "integrity": "sha512-+llXfqt+UzgoDzT9of5vPQPGqTAVCohU74I9zIBkNo5TH6s2P31DFJOGsJQKN207f0GHnYv5pV3wh3BCY/un/A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@node-rs/crc32-android-arm-eabi": "1.10.6", + "@node-rs/crc32-android-arm64": "1.10.6", + "@node-rs/crc32-darwin-arm64": "1.10.6", + "@node-rs/crc32-darwin-x64": "1.10.6", + "@node-rs/crc32-freebsd-x64": "1.10.6", + "@node-rs/crc32-linux-arm-gnueabihf": "1.10.6", + "@node-rs/crc32-linux-arm64-gnu": "1.10.6", + "@node-rs/crc32-linux-arm64-musl": "1.10.6", + "@node-rs/crc32-linux-x64-gnu": "1.10.6", + "@node-rs/crc32-linux-x64-musl": "1.10.6", + "@node-rs/crc32-wasm32-wasi": "1.10.6", + "@node-rs/crc32-win32-arm64-msvc": "1.10.6", + "@node-rs/crc32-win32-ia32-msvc": "1.10.6", + "@node-rs/crc32-win32-x64-msvc": "1.10.6" + } + }, + "node_modules/@node-rs/crc32-android-arm-eabi": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-android-arm-eabi/-/crc32-android-arm-eabi-1.10.6.tgz", + "integrity": "sha512-vZAMuJXm3TpWPOkkhxdrofWDv+Q+I2oO7ucLRbXyAPmXFNDhHtBxbO1rk9Qzz+M3eep8ieS4/+jCL1Q0zacNMQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-android-arm64": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-android-arm64/-/crc32-android-arm64-1.10.6.tgz", + "integrity": "sha512-Vl/JbjCinCw/H9gEpZveWCMjxjcEChDcDBM8S4hKay5yyoRCUHJPuKr4sjVDBeOm+1nwU3oOm6Ca8dyblwp4/w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-darwin-arm64": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-darwin-arm64/-/crc32-darwin-arm64-1.10.6.tgz", + "integrity": "sha512-kARYANp5GnmsQiViA5Qu74weYQ3phOHSYQf0G+U5wB3NB5JmBHnZcOc46Ig21tTypWtdv7u63TaltJQE41noyg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-darwin-x64": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-darwin-x64/-/crc32-darwin-x64-1.10.6.tgz", + "integrity": "sha512-Q99bevJVMfLTISpkpKBlXgtPUItrvTWKFyiqoKH5IvscZmLV++NH4V13Pa17GTBmv9n18OwzgQY4/SRq6PQNVA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-freebsd-x64": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-freebsd-x64/-/crc32-freebsd-x64-1.10.6.tgz", + "integrity": "sha512-66hpawbNjrgnS9EDMErta/lpaqOMrL6a6ee+nlI2viduVOmRZWm9Rg9XdGTK/+c4bQLdtC6jOd+Kp4EyGRYkAg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-linux-arm-gnueabihf": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm-gnueabihf/-/crc32-linux-arm-gnueabihf-1.10.6.tgz", + "integrity": "sha512-E8Z0WChH7X6ankbVm8J/Yym19Cq3otx6l4NFPS6JW/cWdjv7iw+Sps2huSug+TBprjbcEA+s4TvEwfDI1KScjg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-linux-arm64-gnu": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm64-gnu/-/crc32-linux-arm64-gnu-1.10.6.tgz", + "integrity": "sha512-LmWcfDbqAvypX0bQjQVPmQGazh4dLiVklkgHxpV4P0TcQ1DT86H/SWpMBMs/ncF8DGuCQ05cNyMv1iddUDugoQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-linux-arm64-musl": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-arm64-musl/-/crc32-linux-arm64-musl-1.10.6.tgz", + "integrity": "sha512-k8ra/bmg0hwRrIEE8JL1p32WfaN9gDlUUpQRWsbxd1WhjqvXea7kKO6K4DwVxyxlPhBS9Gkb5Urq7Y4mXANzaw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-linux-x64-gnu": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-x64-gnu/-/crc32-linux-x64-gnu-1.10.6.tgz", + "integrity": "sha512-IfjtqcuFK7JrSZ9mlAFhb83xgium30PguvRjIMI45C3FJwu18bnLk1oR619IYb/zetQT82MObgmqfKOtgemEKw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-linux-x64-musl": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-linux-x64-musl/-/crc32-linux-x64-musl-1.10.6.tgz", + "integrity": "sha512-LbFYsA5M9pNunOweSt6uhxenYQF94v3bHDAQRPTQ3rnjn+mK6IC7YTAYoBjvoJP8lVzcvk9hRj8wp4Jyh6Y80g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-wasm32-wasi": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-wasm32-wasi/-/crc32-wasm32-wasi-1.10.6.tgz", + "integrity": "sha512-KaejdLgHMPsRaxnM+OG9L9XdWL2TabNx80HLdsCOoX9BVhEkfh39OeahBo8lBmidylKbLGMQoGfIKDjq0YMStw==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.5" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@node-rs/crc32-win32-arm64-msvc": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-arm64-msvc/-/crc32-win32-arm64-msvc-1.10.6.tgz", + "integrity": "sha512-x50AXiSxn5Ccn+dCjLf1T7ZpdBiV1Sp5aC+H2ijhJO4alwznvXgWbopPRVhbp2nj0i+Gb6kkDUEyU+508KAdGQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-win32-ia32-msvc": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-ia32-msvc/-/crc32-win32-ia32-msvc-1.10.6.tgz", + "integrity": "sha512-DpDxQLaErJF9l36aghe1Mx+cOnYLKYo6qVPqPL9ukJ5rAGLtCdU0C+Zoi3gs9ySm8zmbFgazq/LvmsZYU42aBw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@node-rs/crc32-win32-x64-msvc": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/@node-rs/crc32-win32-x64-msvc/-/crc32-win32-x64-msvc-1.10.6.tgz", + "integrity": "sha512-5B1vXosIIBw1m2Rcnw62IIfH7W9s9f7H7Ma0rRuhT8HR4Xh8QCgw6NJSI2S2MCngsGktYnAhyUvs81b7efTyQw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.1.tgz", + "integrity": "sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.1.tgz", + "integrity": "sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.1.tgz", + "integrity": "sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.1.tgz", + "integrity": "sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.1.tgz", + "integrity": "sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.1.tgz", + "integrity": "sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.1.tgz", + "integrity": "sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.1.tgz", + "integrity": "sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.1.tgz", + "integrity": "sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.1.tgz", + "integrity": "sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.1.tgz", + "integrity": "sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.1.tgz", + "integrity": "sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.1.tgz", + "integrity": "sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.1.tgz", + "integrity": "sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.1.tgz", + "integrity": "sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.1.tgz", + "integrity": "sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.1.tgz", + "integrity": "sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.1.tgz", + "integrity": "sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.1.tgz", + "integrity": "sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.1.tgz", + "integrity": "sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz", + "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@vitest/expect": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz", + "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz", + "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.1.2", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", + "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz", + "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.1.2", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz", + "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.1.2", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz", + "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz", + "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.1.2", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chai": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", + "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", + "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.3", + "@esbuild/android-arm": "0.25.3", + "@esbuild/android-arm64": "0.25.3", + "@esbuild/android-x64": "0.25.3", + "@esbuild/darwin-arm64": "0.25.3", + "@esbuild/darwin-x64": "0.25.3", + "@esbuild/freebsd-arm64": "0.25.3", + "@esbuild/freebsd-x64": "0.25.3", + "@esbuild/linux-arm": "0.25.3", + "@esbuild/linux-arm64": "0.25.3", + "@esbuild/linux-ia32": "0.25.3", + "@esbuild/linux-loong64": "0.25.3", + "@esbuild/linux-mips64el": "0.25.3", + "@esbuild/linux-ppc64": "0.25.3", + "@esbuild/linux-riscv64": "0.25.3", + "@esbuild/linux-s390x": "0.25.3", + "@esbuild/linux-x64": "0.25.3", + "@esbuild/netbsd-arm64": "0.25.3", + "@esbuild/netbsd-x64": "0.25.3", + "@esbuild/openbsd-arm64": "0.25.3", + "@esbuild/openbsd-x64": "0.25.3", + "@esbuild/sunos-x64": "0.25.3", + "@esbuild/win32-arm64": "0.25.3", + "@esbuild/win32-ia32": "0.25.3", + "@esbuild/win32-x64": "0.25.3" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.1.tgz", + "integrity": "sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/loupe": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", + "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rollup": { + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.1.tgz", + "integrity": "sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.7" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.40.1", + "@rollup/rollup-android-arm64": "4.40.1", + "@rollup/rollup-darwin-arm64": "4.40.1", + "@rollup/rollup-darwin-x64": "4.40.1", + "@rollup/rollup-freebsd-arm64": "4.40.1", + "@rollup/rollup-freebsd-x64": "4.40.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.40.1", + "@rollup/rollup-linux-arm-musleabihf": "4.40.1", + "@rollup/rollup-linux-arm64-gnu": "4.40.1", + "@rollup/rollup-linux-arm64-musl": "4.40.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.40.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.40.1", + "@rollup/rollup-linux-riscv64-gnu": "4.40.1", + "@rollup/rollup-linux-riscv64-musl": "4.40.1", + "@rollup/rollup-linux-s390x-gnu": "4.40.1", + "@rollup/rollup-linux-x64-gnu": "4.40.1", + "@rollup/rollup-linux-x64-musl": "4.40.1", + "@rollup/rollup-win32-arm64-msvc": "4.40.1", + "@rollup/rollup-win32-ia32-msvc": "4.40.1", + "@rollup/rollup-win32-x64-msvc": "4.40.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/snappy": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/snappy/-/snappy-7.2.2.tgz", + "integrity": "sha512-iADMq1kY0v3vJmGTuKcFWSXt15qYUz7wFkArOrsSg0IFfI3nJqIJvK2/ZbEIndg7erIJLtAVX2nSOqPz7DcwbA==", + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/snappy-android-arm-eabi": "7.2.2", + "@napi-rs/snappy-android-arm64": "7.2.2", + "@napi-rs/snappy-darwin-arm64": "7.2.2", + "@napi-rs/snappy-darwin-x64": "7.2.2", + "@napi-rs/snappy-freebsd-x64": "7.2.2", + "@napi-rs/snappy-linux-arm-gnueabihf": "7.2.2", + "@napi-rs/snappy-linux-arm64-gnu": "7.2.2", + "@napi-rs/snappy-linux-arm64-musl": "7.2.2", + "@napi-rs/snappy-linux-x64-gnu": "7.2.2", + "@napi-rs/snappy-linux-x64-musl": "7.2.2", + "@napi-rs/snappy-win32-arm64-msvc": "7.2.2", + "@napi-rs/snappy-win32-ia32-msvc": "7.2.2", + "@napi-rs/snappy-win32-x64-msvc": "7.2.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinypool": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/tsx": { + "version": "4.19.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", + "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.3.tgz", + "integrity": "sha512-5nXH+QsELbFKhsEfWLkHrvgRpTdGJzqOZ+utSdmPTvwHmvU6ITTm3xx+mRusihkcI8GeC7lCDyn3kDtiki9scw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.2.tgz", + "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.0", + "es-module-lexer": "^1.6.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.2.tgz", + "integrity": "sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "3.1.2", + "@vitest/mocker": "3.1.2", + "@vitest/pretty-format": "^3.1.2", + "@vitest/runner": "3.1.2", + "@vitest/snapshot": "3.1.2", + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", + "chai": "^5.2.0", + "debug": "^4.4.0", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.13", + "tinypool": "^1.0.2", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "3.1.2", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.1.2", + "@vitest/ui": "3.1.2", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + } + } +} diff --git a/package.json b/package.json index 137ed86..13b9f1f 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,14 @@ { - "name": "@chainsafe/snappy-stream", - "version": "5.1.2", - "description": "Compress data over a Stream using the snappy framing format", - "main": "index.js", + "name": "@scottypoi/snappy-stream", + "version": "1.0.0", + "description": "Compress and decompress data over a Stream using the snappy framing format", + "main": "dist/index.js", + "types": "dist/index.d.ts", "scripts": { - "test": "tap test/*-test.js" + "build": "tsc", + "test": "vitest run", + "test:watch": "vitest", + "prepublishOnly": "npm run build" }, "keywords": [ "snappy", @@ -13,7 +17,8 @@ ], "contributors": [ "David Björklund ", - "ChainSafe " + "ChainSafe ", + "ScottyPoi " ], "license": "MIT", "devDependencies": { @@ -31,10 +36,13 @@ }, "repository": { "type": "git", - "url": "https://github.com/chainsafe/node-snappy-stream.git" + "url": "https://github.com/ScottyPoi/snappy-stream.git" }, "bugs": { - "url": "https://github.com/chainsafe/node-snappy-stream/issues" + "url": "https://github.com/ScottyPoi/snappy-stream/issues" }, - "homepage": "https://github.com/chainsafe/node-snappy-stream" + "homepage": "https://github.com/ScottyPoi/snappy-stream", + "engines": { + "node": ">=22.14.0" + } } From a704dddf412259bd1b346ee32302d761a84ba1a7 Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 17:03:32 -0600 Subject: [PATCH 09/12] update gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 973dbe2..d4e0572 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ node_modules .idea -yarn.lock \ No newline at end of file +dist \ No newline at end of file From efda16f3b38350f2bb262d1254113cd3606951fc Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 17:07:55 -0600 Subject: [PATCH 10/12] replace readme with updated --- README.md | 57 +++++++++++++++++++++++++++++++ readme.md | 100 ------------------------------------------------------ 2 files changed, 57 insertions(+), 100 deletions(-) create mode 100644 README.md delete mode 100644 readme.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..f1ade66 --- /dev/null +++ b/README.md @@ -0,0 +1,57 @@ +# snappy-stream + +Compress data over a Stream using the snappy framing format + + +## Installation + +``` +npm install @scottypoi/snappy-stream +``` + + +## Example + +### Input + +```typescript +// ./example.ts +``` + +### Output + +``` +Som data from the compressed stream +Som data from the compressed stream +The data that was originally written +hello +Som data from the compressed stream +The data that was originally written +world +``` + + + +## Licence + +Copyright (c) 2025 ScottyPoi + +This software is released under the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/readme.md b/readme.md deleted file mode 100644 index c849d27..0000000 --- a/readme.md +++ /dev/null @@ -1,100 +0,0 @@ -# snappy-stream[![Node.js CI/CD](https://github.com/ChainSafe/node-snappy-stream/actions/workflows/main.yaml/badge.svg?branch=master&event=push)](https://github.com/ChainSafe/node-snappy-stream/actions/workflows/main.yaml) - -Compress data over a Stream using the snappy framing format - -[![Npm package version](https://badgen.net/npm/v/@chainsafe/snappy-stream)](https://npmjs.com/package/@chainsafe/snappy-stream) -[![Npm package monthly downloads](https://badgen.net/npm/dm/@chainsafe/snappy-stream)](https://npmjs.ccom/package/@chainsafe/snappy-stream) -[![Npm package license](https://badgen.net/npm/license/@chainsafe/snappy-stream)](https://npmjs.com/package/@chainsafe/snappy-stream) - - -## Installation - -``` -npm install @chainsafe/snappy-stream -``` - -## Benchmark - -`snappy` is notably faster than gzip (as can be seen in [benchmarks](https://github.com/kesla/node-snappy#benchmark)). - -`snappy-stream` however is only _slightly_ faster than gzip, because of the overhead of creating a Stream to begin with. - -This is the result I'm seeing on my laptop (Macbook Air from 2012) running `node benchmark` (for now only testing compression) - -``` - passthrough stream (no compression) x 644 ops/sec ±0.90% (84 runs sampled) - zlib.createGzip() x 667 ops/sec ±0.50% (89 runs sampled) - snappyStream.createCompressStream() x 690 ops/sec ±0.89% (86 runs sampled) -``` - -## Example - -### Input - -```javascript -var snappyStream = require('snappy-stream') - , compressStream = snappyStream.createCompressStream() - , uncompressStream = snappyStream.createUncompressStream({ - asBuffer: false // optional option, asBuffer = false means that the stream emits strings, default: true - }) - -compressStream.on('data', function (chunk) { - console.log('Som data from the compressed stream', chunk) - uncompressStream.write(chunk) -}) - -uncompressStream.on('data', function (chunk) { - console.log('The data that was originally written') - console.log(chunk) -}) - -compressStream.write('hello') -compressStream.write('world') -compressStream.end() -``` - -### Output - -``` -Som data from the compressed stream -Som data from the compressed stream -The data that was originally written -hello -Som data from the compressed stream -The data that was originally written -world -``` - -## Running tests - -The tests are using the [https://pypi.python.org/pypi/python-snappy](python-snappy) library, so you need to install that first for it to work: - -``` -[sudo] pip install python-snappy -``` - -You also need to install the snappy library on your machine, using your favourite package manager (e.g. `sudo apt-get install libsnappy-dev` or `brew install snappy`). - -## Licence - -Copyright (c) 2014 David Björklund - -This software is released under the MIT license: - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. From a07149b684c348ddd0e7661d70469d4d0ca37edd Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 17:12:58 -0600 Subject: [PATCH 11/12] fix package name --- README.md | 4 ++-- package.json | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f1ade66..49b1128 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# snappy-stream +# ts-snappy-stream Compress data over a Stream using the snappy framing format @@ -6,7 +6,7 @@ Compress data over a Stream using the snappy framing format ## Installation ``` -npm install @scottypoi/snappy-stream +npm install @scottypoi/ts-snappy-stream ``` diff --git a/package.json b/package.json index 13b9f1f..b9ab669 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@scottypoi/snappy-stream", + "name": "@scottypoi/ts-snappy-stream", "version": "1.0.0", "description": "Compress and decompress data over a Stream using the snappy framing format", "main": "dist/index.js", @@ -36,12 +36,12 @@ }, "repository": { "type": "git", - "url": "https://github.com/ScottyPoi/snappy-stream.git" + "url": "https://github.com/ScottyPoi/ts-snappy-stream.git" }, "bugs": { - "url": "https://github.com/ScottyPoi/snappy-stream/issues" + "url": "https://github.com/ScottyPoi/ts-snappy-stream/issues" }, - "homepage": "https://github.com/ScottyPoi/snappy-stream", + "homepage": "https://github.com/ScottyPoi/ts-snappy-stream", "engines": { "node": ">=22.14.0" } From a64e91479d47a5929e632af6bbf4c2a044d79ee7 Mon Sep 17 00:00:00 2001 From: ScottyPoi Date: Tue, 29 Apr 2025 17:22:16 -0600 Subject: [PATCH 12/12] remove crc32c dependency --- package.json | 1 - src/lib/checksum.ts | 78 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index b9ab669..22c2793 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "tsx": "^4.19.1" }, "dependencies": { - "@chainsafe/fast-crc32c": "^4.2.0", "snappy": "^7.2.2" }, "directories": { diff --git a/src/lib/checksum.ts b/src/lib/checksum.ts index 430365e..4035503 100644 --- a/src/lib/checksum.ts +++ b/src/lib/checksum.ts @@ -1,4 +1,3 @@ -import { calculate } from '@chainsafe/fast-crc32c'; export function checksum(value: Uint8Array): Uint8Array { const x = calculate(value); @@ -20,4 +19,79 @@ export function checksum(value: Uint8Array): Uint8Array { result[3] = (masked >> 24) & 0xff; return result; -} \ No newline at end of file +} + +var kCRCTable = Int32Array.of( + 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, + 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb, + 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, + 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, + 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, + 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, + 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, + 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b, + 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, + 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, + 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5, + 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, + 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, + 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a, + 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, + 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, + 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48, + 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, + 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, + 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198, + 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, + 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, + 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8, + 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, + 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, + 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789, + 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, + 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, + 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9, + 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, + 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, + 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829, + 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, + 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, + 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043, + 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, + 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, + 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc, + 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, + 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, + 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652, + 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, + 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, + 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982, + 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, + 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, + 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2, + 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, + 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, + 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f, + 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, + 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, + 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f, + 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, + 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, + 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f, + 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, + 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, + 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321, + 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, + 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, + 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e, + 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, + 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351, +); + +export function calculate(buf: Uint8Array, initial?: number) { + let crc = (initial ?? 0) ^ -1; + for (let i = 0; i < buf.length; i++) { + crc = kCRCTable[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8); + } + return (crc ^ -1) >>> 0; + }