@myrialabs/zipkit 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +329 -0
- package/dist/bench/corpus.d.ts +21 -0
- package/dist/bench/corpus.d.ts.map +1 -0
- package/dist/bench/corpus.js +92 -0
- package/dist/bench/corpus.js.map +1 -0
- package/dist/checksum.d.ts +29 -0
- package/dist/checksum.d.ts.map +1 -0
- package/dist/checksum.js +35 -0
- package/dist/checksum.js.map +1 -0
- package/dist/cli.d.ts +17 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +427 -0
- package/dist/cli.js.map +1 -0
- package/dist/codecs/brotli.d.ts +6 -0
- package/dist/codecs/brotli.d.ts.map +1 -0
- package/dist/codecs/brotli.js +15 -0
- package/dist/codecs/brotli.js.map +1 -0
- package/dist/codecs/bzip2.d.ts +6 -0
- package/dist/codecs/bzip2.d.ts.map +1 -0
- package/dist/codecs/bzip2.js +15 -0
- package/dist/codecs/bzip2.js.map +1 -0
- package/dist/codecs/deflate.d.ts +6 -0
- package/dist/codecs/deflate.d.ts.map +1 -0
- package/dist/codecs/deflate.js +25 -0
- package/dist/codecs/deflate.js.map +1 -0
- package/dist/codecs/gzip.d.ts +6 -0
- package/dist/codecs/gzip.d.ts.map +1 -0
- package/dist/codecs/gzip.js +25 -0
- package/dist/codecs/gzip.js.map +1 -0
- package/dist/codecs/image.d.ts +5 -0
- package/dist/codecs/image.d.ts.map +1 -0
- package/dist/codecs/image.js +16 -0
- package/dist/codecs/image.js.map +1 -0
- package/dist/codecs/index.d.ts +18 -0
- package/dist/codecs/index.d.ts.map +1 -0
- package/dist/codecs/index.js +18 -0
- package/dist/codecs/index.js.map +1 -0
- package/dist/codecs/lz4.d.ts +6 -0
- package/dist/codecs/lz4.d.ts.map +1 -0
- package/dist/codecs/lz4.js +17 -0
- package/dist/codecs/lz4.js.map +1 -0
- package/dist/codecs/lzma.d.ts +6 -0
- package/dist/codecs/lzma.d.ts.map +1 -0
- package/dist/codecs/lzma.js +15 -0
- package/dist/codecs/lzma.js.map +1 -0
- package/dist/codecs/snappy.d.ts +6 -0
- package/dist/codecs/snappy.d.ts.map +1 -0
- package/dist/codecs/snappy.js +14 -0
- package/dist/codecs/snappy.js.map +1 -0
- package/dist/codecs/video.d.ts +13 -0
- package/dist/codecs/video.d.ts.map +1 -0
- package/dist/codecs/video.js +26 -0
- package/dist/codecs/video.js.map +1 -0
- package/dist/codecs/xz.d.ts +6 -0
- package/dist/codecs/xz.d.ts.map +1 -0
- package/dist/codecs/xz.js +30 -0
- package/dist/codecs/xz.js.map +1 -0
- package/dist/codecs/zlib.d.ts +6 -0
- package/dist/codecs/zlib.d.ts.map +1 -0
- package/dist/codecs/zlib.js +15 -0
- package/dist/codecs/zlib.js.map +1 -0
- package/dist/codecs/zstd.d.ts +6 -0
- package/dist/codecs/zstd.d.ts.map +1 -0
- package/dist/codecs/zstd.js +24 -0
- package/dist/codecs/zstd.js.map +1 -0
- package/dist/compress.d.ts +20 -0
- package/dist/compress.d.ts.map +1 -0
- package/dist/compress.js +83 -0
- package/dist/compress.js.map +1 -0
- package/dist/delta.d.ts +30 -0
- package/dist/delta.d.ts.map +1 -0
- package/dist/delta.js +44 -0
- package/dist/delta.js.map +1 -0
- package/dist/detect.d.ts +46 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +86 -0
- package/dist/detect.js.map +1 -0
- package/dist/dictionary.d.ts +37 -0
- package/dist/dictionary.d.ts.map +1 -0
- package/dist/dictionary.js +71 -0
- package/dist/dictionary.js.map +1 -0
- package/dist/engine.d.ts +102 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +204 -0
- package/dist/engine.js.map +1 -0
- package/dist/fsa.d.ts +54 -0
- package/dist/fsa.d.ts.map +1 -0
- package/dist/fsa.js +45 -0
- package/dist/fsa.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +21 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +42 -0
- package/dist/internal.js.map +1 -0
- package/dist/middleware/elysia.d.ts +15 -0
- package/dist/middleware/elysia.d.ts.map +1 -0
- package/dist/middleware/elysia.js +43 -0
- package/dist/middleware/elysia.js.map +1 -0
- package/dist/middleware/express.d.ts +17 -0
- package/dist/middleware/express.d.ts.map +1 -0
- package/dist/middleware/express.js +62 -0
- package/dist/middleware/express.js.map +1 -0
- package/dist/middleware/hono.d.ts +17 -0
- package/dist/middleware/hono.d.ts.map +1 -0
- package/dist/middleware/hono.js +41 -0
- package/dist/middleware/hono.js.map +1 -0
- package/dist/middleware/index.d.ts +14 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +14 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/shared.d.ts +29 -0
- package/dist/middleware/shared.d.ts.map +1 -0
- package/dist/middleware/shared.js +47 -0
- package/dist/middleware/shared.js.map +1 -0
- package/dist/pack.d.ts +36 -0
- package/dist/pack.d.ts.map +1 -0
- package/dist/pack.js +75 -0
- package/dist/pack.js.map +1 -0
- package/dist/parallel/index.d.ts +56 -0
- package/dist/parallel/index.d.ts.map +1 -0
- package/dist/parallel/index.js +158 -0
- package/dist/parallel/index.js.map +1 -0
- package/dist/sevenzip/index.d.ts +45 -0
- package/dist/sevenzip/index.d.ts.map +1 -0
- package/dist/sevenzip/index.js +646 -0
- package/dist/sevenzip/index.js.map +1 -0
- package/dist/streams/index.d.ts +32 -0
- package/dist/streams/index.d.ts.map +1 -0
- package/dist/streams/index.js +74 -0
- package/dist/streams/index.js.map +1 -0
- package/dist/string.d.ts +38 -0
- package/dist/string.d.ts.map +1 -0
- package/dist/string.js +64 -0
- package/dist/string.js.map +1 -0
- package/dist/tar/index.d.ts +99 -0
- package/dist/tar/index.d.ts.map +1 -0
- package/dist/tar/index.js +380 -0
- package/dist/tar/index.js.map +1 -0
- package/dist/types.d.ts +59 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +22 -0
- package/dist/types.js.map +1 -0
- package/dist/workers/index.d.ts +58 -0
- package/dist/workers/index.d.ts.map +1 -0
- package/dist/workers/index.js +158 -0
- package/dist/workers/index.js.map +1 -0
- package/dist/workers/worker.d.ts +18 -0
- package/dist/workers/worker.d.ts.map +1 -0
- package/dist/workers/worker.js +45 -0
- package/dist/workers/worker.js.map +1 -0
- package/dist/zip/crypto/aes.d.ts +25 -0
- package/dist/zip/crypto/aes.d.ts.map +1 -0
- package/dist/zip/crypto/aes.js +156 -0
- package/dist/zip/crypto/aes.js.map +1 -0
- package/dist/zip/crypto/winzip.d.ts +28 -0
- package/dist/zip/crypto/winzip.d.ts.map +1 -0
- package/dist/zip/crypto/winzip.js +87 -0
- package/dist/zip/crypto/winzip.js.map +1 -0
- package/dist/zip/crypto/zipcrypto.d.ts +14 -0
- package/dist/zip/crypto/zipcrypto.d.ts.map +1 -0
- package/dist/zip/crypto/zipcrypto.js +65 -0
- package/dist/zip/crypto/zipcrypto.js.map +1 -0
- package/dist/zip/datetime.d.ts +9 -0
- package/dist/zip/datetime.d.ts.map +1 -0
- package/dist/zip/datetime.js +13 -0
- package/dist/zip/datetime.js.map +1 -0
- package/dist/zip/index.d.ts +134 -0
- package/dist/zip/index.d.ts.map +1 -0
- package/dist/zip/index.js +473 -0
- package/dist/zip/index.js.map +1 -0
- package/dist/zip/stream.d.ts +38 -0
- package/dist/zip/stream.d.ts.map +1 -0
- package/dist/zip/stream.js +240 -0
- package/dist/zip/stream.js.map +1 -0
- package/dist/zipkit.d.ts +74 -0
- package/dist/zipkit.d.ts.map +1 -0
- package/dist/zipkit.js +168 -0
- package/dist/zipkit.js.map +1 -0
- package/engine/dist/zipkit-engine.mjs +2 -0
- package/engine/dist/zipkit-engine.wasm +0 -0
- package/package.json +137 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Myria Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://zipkit.myrialabs.dev/favicon.svg" alt="ZipKit" width="72" height="72" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">ZipKit</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Overkill compression for Node, Bun & the browser.</strong><br />
|
|
9
|
+
gzip · deflate · zlib · zstd · lz4 · snappy · brotli · lzma · bzip2 · ZIP —
|
|
10
|
+
one tiny, typed API over a single Wasm engine.
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<a href="https://demo.zipkit.myrialabs.dev/">Demo</a> ·
|
|
15
|
+
<a href="https://zipkit.myrialabs.dev/">Website</a> ·
|
|
16
|
+
<a href="https://www.npmjs.com/package/@myrialabs/zipkit">npm</a> ·
|
|
17
|
+
<a href="./docs/api.md">API reference</a> ·
|
|
18
|
+
<a href="./docs/cli.md">CLI reference</a> ·
|
|
19
|
+
<a href="./examples/README.md">Examples</a> ·
|
|
20
|
+
<a href="https://github.com/myrialabs/zipkit/issues">Issues</a>
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
<p align="center">
|
|
24
|
+
<a href="https://www.npmjs.com/package/@myrialabs/zipkit"><img src="https://img.shields.io/npm/v/@myrialabs%2Fzipkit" alt="npm version" /></a>
|
|
25
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT" /></a>
|
|
26
|
+
<img src="https://img.shields.io/badge/runtime-Node%2018%2B%20%7C%20Bun%20%7C%20Browser-black" alt="Node 18+, Bun and Browser" />
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
ZipKit compiles best-in-class C compression libraries (libdeflate, zstd, lz4,
|
|
32
|
+
brotli, snappy, LZMA, bzip2) into one WebAssembly engine, then wraps them in a
|
|
33
|
+
small TypeScript API. The default path is adaptive: native speed where the runtime
|
|
34
|
+
wins, the portable engine where it wins, and libdeflate density when ratio matters.
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { gzip, gunzip, zstd, unzstd, zip, unzip, compress, decompress } from '@myrialabs/zipkit';
|
|
38
|
+
|
|
39
|
+
const gz = await gzip(bytes); // balanced default
|
|
40
|
+
const back = await gunzip(gz);
|
|
41
|
+
|
|
42
|
+
const fast = await zstd(bytes, { mode: 'speed' });
|
|
43
|
+
const exact = await unzstd(fast);
|
|
44
|
+
|
|
45
|
+
const archive = await zip([{ name: 'data.bin', data: bytes }]);
|
|
46
|
+
const files = await unzip(archive);
|
|
47
|
+
|
|
48
|
+
const small = await compress(bytes, 'zstd', { mode: 'ratio' });
|
|
49
|
+
const orig = await decompress(small); // auto-detects the format
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
zipkit compress data.json --codec zstd # CLI
|
|
54
|
+
zipkit zip site.zip index.html app.js --method zstd
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Why ZipKit
|
|
58
|
+
|
|
59
|
+
- **One simple API, every codec** — named imports (`gzip`, `zstd`, `zip`) when you
|
|
60
|
+
know what you want, or `compress()` / `decompress()` for generic dispatch.
|
|
61
|
+
- **One clear option** — `mode: 'speed' | 'balanced' | 'ratio'`. No tuning maze;
|
|
62
|
+
`level` is still available when you need exact control.
|
|
63
|
+
- **Adaptive performance** — ZipKit chooses native Bun zlib/zstd where it wins,
|
|
64
|
+
the Wasm engine where it wins, and libdeflate for density.
|
|
65
|
+
- **Denser gzip when you ask for ratio** — `mode: 'ratio'` uses libdeflate for
|
|
66
|
+
gzip/deflate/zlib and beats runtime zlib output size on every benchmark dataset.
|
|
67
|
+
- **Runs everywhere** — Node 18+, Bun, and the browser, from the same import. No
|
|
68
|
+
Bun required; native APIs are accelerators only when present.
|
|
69
|
+
- **More than fflate** — feature parity with fflate plus zstd/brotli/lzma/bzip2/xz,
|
|
70
|
+
ZIP-with-zstd, **streaming & AES-encrypted ZIP**, **tar** and **7z** containers,
|
|
71
|
+
**zstd dictionaries** and **delta** compression, native `TransformStream`s, and
|
|
72
|
+
lossless image (QOI) and video (frame-delta) codecs.
|
|
73
|
+
- **Typed & documented** — TypeScript-first, JSDoc on every export, tree-shakeable
|
|
74
|
+
named imports, `sideEffects: false`.
|
|
75
|
+
|
|
76
|
+
## Install
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
bun add @myrialabs/zipkit # or: npm i @myrialabs/zipkit / pnpm add @myrialabs/zipkit
|
|
80
|
+
bun add -g @myrialabs/zipkit # CLI
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Quick start
|
|
84
|
+
|
|
85
|
+
| Task | API |
|
|
86
|
+
| --- | --- |
|
|
87
|
+
| Compress | `await zstd(bytes)` |
|
|
88
|
+
| Decompress | `await unzstd(bytes)` |
|
|
89
|
+
| Generic + auto-detect | `await compress(bytes, 'gzip')` · `await decompress(bytes)` |
|
|
90
|
+
| Just the smallest | `await pack(bytes)` · `await unpack(packed)` |
|
|
91
|
+
| Prefer speed | `await gzip(bytes, { mode: 'speed' })` |
|
|
92
|
+
| Prefer ratio | `await zstd(bytes, { mode: 'ratio' })` |
|
|
93
|
+
| ZIP archive | `await zip([{ name, data }])` · `await unzip(archive)` |
|
|
94
|
+
| Encrypted ZIP | `await zip(entries, { password })` · `await unzip(a, { password })` |
|
|
95
|
+
| Streaming ZIP | `zipStream(entries).pipeTo(dest)` |
|
|
96
|
+
| tar / tarball | `tar(entries)` · `await tarGz(entries)` (`@myrialabs/zipkit/tar`) |
|
|
97
|
+
| 7z | `await sevenZip(entries)` · `await unSevenZip(a)` (`@myrialabs/zipkit/sevenzip`) |
|
|
98
|
+
| xz | `await xz(bytes)` · `await unxz(bytes)` |
|
|
99
|
+
| Dictionary / delta | `compressWithDictionary` · `compressDelta` |
|
|
100
|
+
| Stream codec | `readable.pipeThrough(compressionStream('gzip'))` |
|
|
101
|
+
|
|
102
|
+
> **Auto-detect scope.** `decompress()` decodes the self-describing codecs —
|
|
103
|
+
> **gzip, zlib, zstd, xz** — and recognizes container formats (ZIP, tar, 7z,
|
|
104
|
+
> bzip2, lz4-frame), pointing you to the right reader. For headerless or
|
|
105
|
+
> ZipKit-framed codecs (brotli, snappy, lz4, lzma, bzip2) name the codec:
|
|
106
|
+
> `decompressWith(bytes, 'brotli')`.
|
|
107
|
+
|
|
108
|
+
### The two API styles
|
|
109
|
+
|
|
110
|
+
**Named functions** (async, tree-shakeable) — the default. Each lazily loads the
|
|
111
|
+
shared engine the first time it's called.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
import { brotli, unbrotli } from '@myrialabs/zipkit';
|
|
115
|
+
const c = await brotli(bytes, { mode: 'ratio' });
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**The `ZipKit` class** (synchronous) — load the engine once, then call
|
|
119
|
+
synchronously. It accepts the same `mode` option as the async helpers while still
|
|
120
|
+
supporting the old numeric level argument (`zk.gzip(bytes, 6)`).
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import { ZipKit } from '@myrialabs/zipkit';
|
|
124
|
+
const zk = await ZipKit.load();
|
|
125
|
+
const gz = zk.gzip(bytes, { mode: 'speed' }); // sync
|
|
126
|
+
const smallest = zk.pack(bytes); // tries brotli/lzma/bzip2/zstd-max, keeps the smallest
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Performance
|
|
130
|
+
|
|
131
|
+
Bun 1.3.14, every codec against its best competitor. Reproduce with
|
|
132
|
+
`bun run bench.ts`; the full tables (three datasets + parallel + ZIP archive vs
|
|
133
|
+
JSZip/fflate) live in [bench-results.md](./bench-results.md). All roundtrips are
|
|
134
|
+
byte-identical.
|
|
135
|
+
|
|
136
|
+
Representative — **E-commerce API**, ~97 KB JSON (throughput, higher is faster):
|
|
137
|
+
|
|
138
|
+
| Codec | Implementation | Ratio | Compress | Decompress |
|
|
139
|
+
|-------|----------------|------:|---------:|-----------:|
|
|
140
|
+
| **gzip** | | | | |
|
|
141
|
+
| | ZipKit | 5.1% | 396 MB/s | 2.7 GB/s |
|
|
142
|
+
| | ZipKit (ratio) | 4.9% | 51 MB/s | 2.6 GB/s |
|
|
143
|
+
| | fflate | 5.9% | 55 MB/s | 122 MB/s |
|
|
144
|
+
| | Bun.gzipSync | 5.1% | 380 MB/s | 2.5 GB/s |
|
|
145
|
+
| **deflate** | | | | |
|
|
146
|
+
| | ZipKit | 5.1% | 400 MB/s | 2.7 GB/s |
|
|
147
|
+
| | ZipKit (ratio) | 4.9% | 50 MB/s | 2.5 GB/s |
|
|
148
|
+
| | fflate | 5.9% | 68 MB/s | 119 MB/s |
|
|
149
|
+
| | Bun.deflateSync | 5.1% | 399 MB/s | 2.7 GB/s |
|
|
150
|
+
| **zlib** | | | | |
|
|
151
|
+
| | ZipKit | 6.0% | 273 MB/s | 1.2 GB/s |
|
|
152
|
+
| | ZipKit (ratio) | 4.9% | 53 MB/s | 2.0 GB/s |
|
|
153
|
+
| | fflate | 5.9% | 63 MB/s | 112 MB/s |
|
|
154
|
+
| **zstd** | | | | |
|
|
155
|
+
| | ZipKit | 5.6% | 1.5 GB/s | 3.4 GB/s |
|
|
156
|
+
| | ZipKit (ratio) | 3.9% | 2 MB/s | 5.3 GB/s |
|
|
157
|
+
| | zstd-wasm | 5.6% | 354 MB/s | 978 MB/s |
|
|
158
|
+
| | Bun.zstdCompressSync | 5.6% | 1.9 GB/s | 3.5 GB/s |
|
|
159
|
+
| **lz4** | | | | |
|
|
160
|
+
| | ZipKit | 12.9% | 1018 MB/s | 2.1 GB/s |
|
|
161
|
+
| | lz4js | 12.5% | 399 MB/s | 515 MB/s |
|
|
162
|
+
| **snappy** | | | | |
|
|
163
|
+
| | ZipKit | 13.5% | 599 MB/s | 1.5 GB/s |
|
|
164
|
+
| | snappyjs | 13.5% | 358 MB/s | 437 MB/s |
|
|
165
|
+
| **brotli** | | | | |
|
|
166
|
+
| | ZipKit | 4.1% | 107 MB/s | 844 MB/s |
|
|
167
|
+
| | ZipKit (ratio) | 3.4% | 611.5 KB/s | 1.8 GB/s |
|
|
168
|
+
| | brotli-wasm | 4.1% | 42 MB/s | 560 MB/s |
|
|
169
|
+
| **lzma** | | | | |
|
|
170
|
+
| | ZipKit | 3.8% | 18 MB/s | 423 MB/s |
|
|
171
|
+
| **bzip2** | | | | |
|
|
172
|
+
| | ZipKit | 3.4% | 17 MB/s | 83 MB/s |
|
|
173
|
+
|
|
174
|
+
What the full run adds beyond this table:
|
|
175
|
+
|
|
176
|
+
- **Against portable JS** (fflate, pako, zstd-wasm, brotli-wasm), ZipKit
|
|
177
|
+
compresses several× faster at an equal-or-better ratio across all datasets.
|
|
178
|
+
- **`mode: 'ratio'`** trades speed for size: libdeflate gzip/deflate is denser
|
|
179
|
+
than native zlib, and brotli/lzma/bzip2 reach the smallest output (~3.3–3.8% on JSON).
|
|
180
|
+
- **Parallel** (8 cores, 34 MB logs) is the multi-core path native libs lack:
|
|
181
|
+
`compressParallel` gzip runs **5.4× faster** than `Bun.gzipSync`, same output size.
|
|
182
|
+
- **ZIP archives** fan entry compression across the pool: a 20-file, 8 MB archive
|
|
183
|
+
packs **8.9× faster** than `fflate` and **7.8× faster** than JSZip, 10% smaller.
|
|
184
|
+
- **Dictionary & delta** target what generic codecs handle poorly: a zstd
|
|
185
|
+
dictionary makes 500 small JSON records **~66% smaller** than per-record zstd,
|
|
186
|
+
and `compressDelta` encodes a one-line edit to a 64 KB doc **>250× smaller**
|
|
187
|
+
than recompressing it. `xz` is included in every codec table too.
|
|
188
|
+
|
|
189
|
+
## Streaming
|
|
190
|
+
|
|
191
|
+
Web-standard `TransformStream`s for every codec. gzip / zlib / deflate are backed by
|
|
192
|
+
the platform's native `CompressionStream` (true incremental streaming); the rest
|
|
193
|
+
buffer and compress on flush.
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { compressionStream } from '@myrialabs/zipkit/streams';
|
|
197
|
+
|
|
198
|
+
await fetch(url)
|
|
199
|
+
.then((r) => r.body!)
|
|
200
|
+
.then((body) => body.pipeThrough(compressionStream('gzip')).pipeTo(dest));
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## ZIP archives
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
import { zip, unzip } from '@myrialabs/zipkit';
|
|
207
|
+
|
|
208
|
+
const archive = await zip([
|
|
209
|
+
{ name: 'index.html', data: html },
|
|
210
|
+
{ name: 'app.js', data: js, method: 'zstd' }, // denser, ZipKit-aware peers
|
|
211
|
+
{ name: 'logo.png', data: png, method: 'store', unixPermissions: 0o644 }
|
|
212
|
+
]);
|
|
213
|
+
|
|
214
|
+
const files = await unzip(archive, { filter: (e) => e.name.endsWith('.js') });
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
`store` and `deflate` entries interoperate with every standard ZIP tool; `zstd`
|
|
218
|
+
entries (method 93) are much denser between ZipKit-aware peers. ZIP64 kicks in
|
|
219
|
+
automatically beyond 4 GB / 65 535 entries.
|
|
220
|
+
|
|
221
|
+
**Encrypted** (WinZip AES-256, reads back in 7-Zip/WinZip), **streaming** (never
|
|
222
|
+
buffers the whole archive), and **integrity-checked**:
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
const enc = await zip(entries, { password: 'secret' }); // AES-256 (AE-2)
|
|
226
|
+
const out = await unzip(enc, { password: 'secret', verify: true });
|
|
227
|
+
|
|
228
|
+
import { zipStream } from '@myrialabs/zipkit/zip';
|
|
229
|
+
await zipStream(entries).pipeTo(destination); // memory-bounded
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## tar, 7z & xz
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
import { tar, tarGz, untarGz } from '@myrialabs/zipkit/tar';
|
|
236
|
+
import { sevenZip, unSevenZip } from '@myrialabs/zipkit/sevenzip';
|
|
237
|
+
import { xz, unxz } from '@myrialabs/zipkit/xz';
|
|
238
|
+
|
|
239
|
+
const tgz = await tarGz([{ name: 'a.txt', data }]); // .tar.gz (also tarZstd)
|
|
240
|
+
const archive = await sevenZip([{ name: 'a.txt', data }]); // 7-Zip-compatible
|
|
241
|
+
const x = await xz(data, { level: 9 }); // standard .xz
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
tar is POSIX `ustar`+PAX (Unix-`tar`/Docker compatible); 7z reads/writes
|
|
245
|
+
copy/LZMA(2) and interoperates with 7-Zip both directions; xz is the full
|
|
246
|
+
streaming `.xz` container.
|
|
247
|
+
|
|
248
|
+
## Dictionary & delta
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
import { trainDictionary, compressWithDictionary } from '@myrialabs/zipkit/dictionary';
|
|
252
|
+
import { compressDelta, applyDelta } from '@myrialabs/zipkit/delta';
|
|
253
|
+
|
|
254
|
+
const dict = await trainDictionary(samples); // many small similar payloads
|
|
255
|
+
const small = await compressWithDictionary(record, dict);
|
|
256
|
+
|
|
257
|
+
const patch = await compressDelta(prevRevision, newRevision); // logs/chat/state
|
|
258
|
+
const restored = await applyDelta(prevRevision, patch);
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## HTTP middleware
|
|
262
|
+
|
|
263
|
+
`Accept-Encoding`-negotiating compression for Elysia, Express, and Hono
|
|
264
|
+
(brotli → zstd → gzip → deflate).
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
import { Elysia } from 'elysia';
|
|
268
|
+
import { elysia as compression } from '@myrialabs/zipkit/middleware';
|
|
269
|
+
|
|
270
|
+
new Elysia()
|
|
271
|
+
.onAfterHandle(compression())
|
|
272
|
+
.get('/', () => ({ rows: Array.from({ length: 200 }, (_, i) => ({ i })) }))
|
|
273
|
+
.listen(3000);
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import express from 'express';
|
|
278
|
+
import { express as compression } from '@myrialabs/zipkit/middleware';
|
|
279
|
+
|
|
280
|
+
const app = express();
|
|
281
|
+
app.use(compression());
|
|
282
|
+
app.get('/', (_req, res) => res.json({ rows: Array.from({ length: 200 }, (_, i) => ({ i })) }));
|
|
283
|
+
app.listen(3000);
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
import { Hono } from 'hono';
|
|
288
|
+
import { hono as compression } from '@myrialabs/zipkit/middleware';
|
|
289
|
+
|
|
290
|
+
const app = new Hono();
|
|
291
|
+
app.use('*', compression());
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Browser
|
|
295
|
+
|
|
296
|
+
The engine loads its `.wasm` via `import.meta.url`, which Vite, webpack 5, esbuild,
|
|
297
|
+
and Rollup resolve as an asset out of the box. See [docs/browser.md](./docs/browser.md).
|
|
298
|
+
|
|
299
|
+
The combined engine is ~1.4 MB of `.wasm` (every codec in one module), loaded
|
|
300
|
+
once and cached. Keep it off your initial bundle with a dynamic import
|
|
301
|
+
(`const { gzip } = await import('@myrialabs/zipkit')`), or skip the engine entirely for
|
|
302
|
+
gzip/zlib/deflate by using [`@myrialabs/zipkit/streams`](./docs/streaming.md), which run on
|
|
303
|
+
the browser's native `CompressionStream`. Per-codec Wasm splitting is on the
|
|
304
|
+
roadmap.
|
|
305
|
+
|
|
306
|
+
## Documentation
|
|
307
|
+
|
|
308
|
+
- [API reference](./docs/api.md) — every export, option, and method.
|
|
309
|
+
- [CLI reference](./docs/cli.md) — every command and flag.
|
|
310
|
+
- [Algorithms](./docs/algorithms.md) — which codec to use, with benchmark tables.
|
|
311
|
+
- [Streaming](./docs/streaming.md) · [ZIP](./docs/zip.md) · [Browser](./docs/browser.md)
|
|
312
|
+
- [Examples](./examples/README.md) — runnable scenarios.
|
|
313
|
+
|
|
314
|
+
## Support
|
|
315
|
+
|
|
316
|
+
If ZipKit is useful to you, consider supporting its development:
|
|
317
|
+
|
|
318
|
+
| Method | Address / Link |
|
|
319
|
+
|--------|----------------|
|
|
320
|
+
| Bitcoin (BTC) | `bc1qd9fyx4r84cce2a9hkjksetah802knadw5msls3` |
|
|
321
|
+
| Solana (SOL) | `Ev3P4KLF1PNC5C9rZYP8M3DdssyBQAQAiNJkvNmPQPVs` |
|
|
322
|
+
| Ethereum (ERC-20) | `0x61D826e5b666AA5345302EEEd485Acca39b1AFCF` |
|
|
323
|
+
| USDT (TRC-20) | `TLH49i3EoVKhFyLb6u2JUXZWScK7uzksdC` |
|
|
324
|
+
| Saweria | [saweria.co/myrialabs](https://saweria.co/myrialabs) |
|
|
325
|
+
|
|
326
|
+
## License
|
|
327
|
+
|
|
328
|
+
MIT — see [LICENSE](LICENSE). Bundles several open-source C libraries; see
|
|
329
|
+
[their licenses](./docs/algorithms.md#third-party-licenses).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic benchmark corpora.
|
|
3
|
+
*
|
|
4
|
+
* `zipkit bench` with no file compares codecs on these built-in datasets, so
|
|
5
|
+
* ratio/timing comparisons across versions or PRs are apple-to-apple instead of
|
|
6
|
+
* depending on whatever file a user happened to pass. Everything is generated
|
|
7
|
+
* from a fixed seed (no `Math.random`, no bundled fixtures bloating the
|
|
8
|
+
* package), so the same input bytes are reproduced on every machine and run.
|
|
9
|
+
*/
|
|
10
|
+
/** A named benchmark dataset. */
|
|
11
|
+
export interface CorpusEntry {
|
|
12
|
+
/** Short identifier, e.g. `'text'`. */
|
|
13
|
+
name: string;
|
|
14
|
+
/** One-line description of what the dataset models. */
|
|
15
|
+
description: string;
|
|
16
|
+
/** The dataset bytes. */
|
|
17
|
+
data: Uint8Array;
|
|
18
|
+
}
|
|
19
|
+
/** Build the standard corpus at roughly `bytesPerSet` bytes per dataset (default 256 KB). */
|
|
20
|
+
export declare function presetCorpus(bytesPerSet?: number): CorpusEntry[];
|
|
21
|
+
//# sourceMappingURL=corpus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corpus.d.ts","sourceRoot":"","sources":["../../src/bench/corpus.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,iCAAiC;AACjC,MAAM,WAAW,WAAW;IAC3B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,IAAI,EAAE,UAAU,CAAC;CACjB;AAkFD,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,WAAW,SAAa,GAAG,WAAW,EAAE,CAOpE"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic benchmark corpora.
|
|
3
|
+
*
|
|
4
|
+
* `zipkit bench` with no file compares codecs on these built-in datasets, so
|
|
5
|
+
* ratio/timing comparisons across versions or PRs are apple-to-apple instead of
|
|
6
|
+
* depending on whatever file a user happened to pass. Everything is generated
|
|
7
|
+
* from a fixed seed (no `Math.random`, no bundled fixtures bloating the
|
|
8
|
+
* package), so the same input bytes are reproduced on every machine and run.
|
|
9
|
+
*/
|
|
10
|
+
/** A tiny deterministic PRNG (mulberry32) — reproducible, no global state. */
|
|
11
|
+
function rng(seed) {
|
|
12
|
+
let a = seed >>> 0;
|
|
13
|
+
return () => {
|
|
14
|
+
a |= 0;
|
|
15
|
+
a = (a + 0x6d2b79f5) | 0;
|
|
16
|
+
let t = Math.imul(a ^ (a >>> 15), 1 | a);
|
|
17
|
+
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
|
18
|
+
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const WORDS = ('the quick brown fox jumps over a lazy dog while data flows through pipes and ' +
|
|
22
|
+
'buffers compress into smaller frames across every runtime node bun browser ' +
|
|
23
|
+
'engine codec stream archive entry header footer index block size ratio').split(' ');
|
|
24
|
+
/** Natural-language-like English text — exercises entropy coding and matching. */
|
|
25
|
+
function textCorpus(targetBytes) {
|
|
26
|
+
const next = rng(0x1234abcd);
|
|
27
|
+
let s = '';
|
|
28
|
+
while (s.length < targetBytes) {
|
|
29
|
+
const len = 6 + Math.floor(next() * 14);
|
|
30
|
+
const line = [];
|
|
31
|
+
for (let i = 0; i < len; i++)
|
|
32
|
+
line.push(WORDS[Math.floor(next() * WORDS.length)]);
|
|
33
|
+
s += line.join(' ') + '.\n';
|
|
34
|
+
}
|
|
35
|
+
return new TextEncoder().encode(s.slice(0, targetBytes));
|
|
36
|
+
}
|
|
37
|
+
/** Repetitive structured JSON records — the everyday API/log-payload shape. */
|
|
38
|
+
function jsonCorpus(targetBytes) {
|
|
39
|
+
const next = rng(0x55aa00ff);
|
|
40
|
+
const levels = ['debug', 'info', 'warn', 'error'];
|
|
41
|
+
const svcs = ['api', 'auth', 'cache', 'db', 'queue'];
|
|
42
|
+
const records = [];
|
|
43
|
+
let size = 0;
|
|
44
|
+
let i = 0;
|
|
45
|
+
while (size < targetBytes) {
|
|
46
|
+
const rec = JSON.stringify({
|
|
47
|
+
ts: 1_700_000_000 + i,
|
|
48
|
+
level: levels[Math.floor(next() * levels.length)],
|
|
49
|
+
svc: svcs[Math.floor(next() * svcs.length)],
|
|
50
|
+
id: Math.floor(next() * 1_000_000),
|
|
51
|
+
ok: next() > 0.1,
|
|
52
|
+
msg: `request ${i} processed in ${Math.floor(next() * 500)}ms`
|
|
53
|
+
});
|
|
54
|
+
records.push(rec);
|
|
55
|
+
size += rec.length + 1;
|
|
56
|
+
i++;
|
|
57
|
+
}
|
|
58
|
+
return new TextEncoder().encode('[' + records.join(',\n') + ']');
|
|
59
|
+
}
|
|
60
|
+
/** Semi-structured log lines with timestamps and repeated tokens. */
|
|
61
|
+
function logCorpus(targetBytes) {
|
|
62
|
+
const next = rng(0x0f0f0f0f);
|
|
63
|
+
const paths = ['/api/users', '/api/orders', '/health', '/assets/app.js', '/login'];
|
|
64
|
+
let s = '';
|
|
65
|
+
let i = 0;
|
|
66
|
+
while (s.length < targetBytes) {
|
|
67
|
+
const ms = 1_700_000_000_000 + i * 137;
|
|
68
|
+
s += `${ms} GET ${paths[Math.floor(next() * paths.length)]} ${200 + Math.floor(next() * 5) * 100} ${Math.floor(next() * 9999)}b\n`;
|
|
69
|
+
i++;
|
|
70
|
+
}
|
|
71
|
+
return new TextEncoder().encode(s.slice(0, targetBytes));
|
|
72
|
+
}
|
|
73
|
+
/** High-entropy bytes with light structure — a near-incompressible baseline. */
|
|
74
|
+
function binaryCorpus(targetBytes) {
|
|
75
|
+
const next = rng(0xdeadbeef);
|
|
76
|
+
const out = new Uint8Array(targetBytes);
|
|
77
|
+
for (let i = 0; i < targetBytes; i++) {
|
|
78
|
+
// Mostly random, but with occasional runs so it isn't pure noise.
|
|
79
|
+
out[i] = next() < 0.15 ? 0 : Math.floor(next() * 256);
|
|
80
|
+
}
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
/** Build the standard corpus at roughly `bytesPerSet` bytes per dataset (default 256 KB). */
|
|
84
|
+
export function presetCorpus(bytesPerSet = 256 * 1024) {
|
|
85
|
+
return [
|
|
86
|
+
{ name: 'text', description: 'English-like natural-language text', data: textCorpus(bytesPerSet) },
|
|
87
|
+
{ name: 'json', description: 'repetitive structured JSON records', data: jsonCorpus(bytesPerSet) },
|
|
88
|
+
{ name: 'log', description: 'semi-structured server log lines', data: logCorpus(bytesPerSet) },
|
|
89
|
+
{ name: 'binary', description: 'high-entropy bytes (near-incompressible)', data: binaryCorpus(bytesPerSet) }
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=corpus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corpus.js","sourceRoot":"","sources":["../../src/bench/corpus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Explicit integrity helpers.
|
|
3
|
+
*
|
|
4
|
+
* The codecs already validate their own framed checksums on decode (gzip's
|
|
5
|
+
* CRC-32, zstd's optional content checksum), and {@link import('./zip/index.js').unzip}
|
|
6
|
+
* takes a `verify` option to re-check every entry. This module exposes the raw
|
|
7
|
+
* CRC-32 so callers can verify or fingerprint arbitrary bytes themselves — the
|
|
8
|
+
* same libdeflate SIMD routine the ZIP container uses, not a byte-at-a-time
|
|
9
|
+
* table.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* CRC-32 (IEEE 802.3) of `data`. Pass a prior result as `seed` to continue a
|
|
13
|
+
* running checksum across chunks. Returned as an unsigned 32-bit integer.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { crc32 } from '@myrialabs/zipkit';
|
|
18
|
+
* const sum = await crc32(bytes);
|
|
19
|
+
* const running = await crc32(part2, await crc32(part1));
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function crc32(data: Uint8Array, seed?: number): Promise<number>;
|
|
23
|
+
/**
|
|
24
|
+
* Verify `data` against an expected CRC-32, returning `true` on a match. A thin
|
|
25
|
+
* convenience over {@link crc32} for the common "does this match what I stored"
|
|
26
|
+
* check.
|
|
27
|
+
*/
|
|
28
|
+
export declare function verifyChecksum(data: Uint8Array, expected: number): Promise<boolean>;
|
|
29
|
+
//# sourceMappingURL=checksum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksum.d.ts","sourceRoot":"","sources":["../src/checksum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;;;;;;;;;GAUG;AACH,wBAAsB,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,SAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAGvE;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAEzF"}
|
package/dist/checksum.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Explicit integrity helpers.
|
|
3
|
+
*
|
|
4
|
+
* The codecs already validate their own framed checksums on decode (gzip's
|
|
5
|
+
* CRC-32, zstd's optional content checksum), and {@link import('./zip/index.js').unzip}
|
|
6
|
+
* takes a `verify` option to re-check every entry. This module exposes the raw
|
|
7
|
+
* CRC-32 so callers can verify or fingerprint arbitrary bytes themselves — the
|
|
8
|
+
* same libdeflate SIMD routine the ZIP container uses, not a byte-at-a-time
|
|
9
|
+
* table.
|
|
10
|
+
*/
|
|
11
|
+
import { getEngine } from './engine.js';
|
|
12
|
+
/**
|
|
13
|
+
* CRC-32 (IEEE 802.3) of `data`. Pass a prior result as `seed` to continue a
|
|
14
|
+
* running checksum across chunks. Returned as an unsigned 32-bit integer.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { crc32 } from '@myrialabs/zipkit';
|
|
19
|
+
* const sum = await crc32(bytes);
|
|
20
|
+
* const running = await crc32(part2, await crc32(part1));
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export async function crc32(data, seed = 0) {
|
|
24
|
+
const e = await getEngine();
|
|
25
|
+
return e.crc32(data, seed) >>> 0;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Verify `data` against an expected CRC-32, returning `true` on a match. A thin
|
|
29
|
+
* convenience over {@link crc32} for the common "does this match what I stored"
|
|
30
|
+
* check.
|
|
31
|
+
*/
|
|
32
|
+
export async function verifyChecksum(data, expected) {
|
|
33
|
+
return (await crc32(data)) === (expected >>> 0);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=checksum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksum.js","sourceRoot":"","sources":["../src/checksum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAgB,EAAE,IAAI,GAAG,CAAC;IACrD,MAAM,CAAC,GAAG,MAAM,SAAS,EAAE,CAAC;IAC5B,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAgB,EAAE,QAAgB;IACtE,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC;AACjD,CAAC"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* zipkit CLI
|
|
4
|
+
*
|
|
5
|
+
* A thin command line over the library, so ZipKit can be used straight from a
|
|
6
|
+
* terminal (`npm i -g @myrialabs/zipkit` / `bun add -g @myrialabs/zipkit`).
|
|
7
|
+
*
|
|
8
|
+
* zipkit compress <file> [--codec zstd] [--mode ratio] [--level N] [-o out]
|
|
9
|
+
* zipkit decompress <file> [--codec gzip] [-o out] (auto-detects by default)
|
|
10
|
+
* zipkit zip <archive.zip> <files...> [--method deflate|zstd|store]
|
|
11
|
+
* zipkit unzip <archive.zip> [-d <dir>]
|
|
12
|
+
* zipkit info <file> Inspect a file (format, or ZIP listing)
|
|
13
|
+
* zipkit bench <file> Compare every codec on a file
|
|
14
|
+
* zipkit version | help
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;GAaG"}
|