npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

yeow-fflate

v0.3.2

Published

fflate fork for Yeow: ZIP container/CRC kept in JS, raw DEFLATE and UTF-8 pluggable (default yeow-api Java bridge); promise-first API, Zip builder, no workers and no streams

Readme

yeow-fflate

fflate 的用于 Yeow 环境的 fork:保留 fflate 原生纯 JS 的容器逻辑(ZIP 结构拼装、CRC、内置 UTF-8),并把 raw DEFLATE 与 UTF-8 编解码抽象成可插拔的 codec 后端,默认桥接到 yeow-api(环境自带 DEFLATE / 编码器执行)。

设计原则

| 原则 | 实现 | | ---------------- | ----------------------------------------------------------------------------------------------------------------------- | | 单一职责 | core.ts(原生算法/容器)· backends.ts(codec 配置)· async.ts(Promise-first 异步层)· index.ts(唯一公共入口) | | Promise-first | 异步 API 直接 await;回调形态仅作 fflate 兼容 | | 不泄露内部 | 公共入口只导出公开 API;b2/wzh/mrg 等内部工具不再出现在包导出里 | | 保留 fflate 核心 | ZIP 格式、CRC32、ADLER32、纯 JS UTF-8 算法不重写,只换边界 |

架构

src/core.ts       fflate 原生同步核心(deflate/inflate/gzip/zlib/zip/unzip、
                  CRC、ZIP 拼装、内置 UTF-8)+ 底层 codec 注册原语
src/backends.ts   CodecConfig + configureCodecs / useYeowCodecs / useNativeCodecs
src/async.ts      Promise-first 异步 API + Zip 增量构建器 + ZipReader(list/stat/单文件读取)
src/index.ts      公共入口:显式导出 + 默认启用 Yeow 后端

安装

npm install yeow-fflate

环境应有 yeow-api(peer dependency)。

快速开始

import { zipSync, unzipSync, gzipSync, gunzipSync, strToU8, strFromU8 } from 'yeow-fflate';
import { fs } from 'yeow-api';

// 同步 ZIP(内部 deflate 默认走 Yeow Gzip 桥接,输出为标准 deflate 流)
const zip = zipSync({ 'a.txt': strToU8('hello yeow') }, { level: 6 });
await fs.writeFile('archive.zip', zip);                 // Uint8Array 直接写入

const loaded = await fs.readFile('archive.zip');        // 默认返回 Uint8Array
const files = unzipSync(loaded);
console.log(strFromU8(files['a.txt']));                 // hello yeow

// 同步 gzip(可被标准 gunzip 解压)
const gz = gzipSync(strToU8('hello'));
await fs.writeFile('hello.gz', gz);
const back = gunzipSync(await fs.readFile('hello.gz'));

Promise-first 异步 API

import { zip, unzip, gzip, gunzip, decompress, strToU8 } from 'yeow-fflate';
import { fs } from 'yeow-api';

const buf = await zip({ 'a.txt': strToU8('hello yeow') }, { level: 6 });
await fs.writeFile('archive.zip', buf);

const files = await unzip(await fs.readFile('archive.zip'));
const gz = await gzip(buf);
await fs.writeFile('archive.zip.gz', gz);
const out = await gunzip(await fs.readFile('archive.zip.gz'));
const out2 = await decompress(gz); // 自动识别 gzip/zlib/raw deflate

fflate 回调形态仍兼容:gzip(data, opts, cb) / gzip(data, cb)注意:回调模式返回 void——本库没有 Worker,不存在可终止的底层任务, 因此移除了 fflate 的 AsyncTerminable

增量构建:Zip(异步压缩 + 同步装配)

import { Zip, unzipSync, strToU8, strFromU8 } from 'yeow-fflate';
import { fs } from 'yeow-api';

const zip = new Zip();
await zip.add('a.txt', strToU8('hello'));               // Promise<void>,异步压缩(默认 level 6)
await zip.add('dir/b.bin', bytes, { level: 0 });        // level 0 = 不压缩存储
await zip.add('压缩/大文件.txt', big, { level: 9 });     // 中文文件名、子目录
await fs.writeFile('bundle.zip', zip.finish());         // 同步装配;与 zipSync 输出一致

const out = unzipSync(await fs.readFile('bundle.zip'));
console.log(strFromU8(out['a.txt']));                   // hello

// 需要同步压缩时使用 addSync:
const sync = new Zip();
sync.addSync('a.txt', strToU8('hello'));
await fs.writeFile('bundle-sync.zip', sync.finish());

add() 默认走注入的异步压缩器(Yeow 后端下在 Java 侧 ioExecutor 执行); 未注入异步压缩器时回退同步实现,但返回值始终是 Promise。 调用下一个 add / addSync / finish 前请先 awaitfinish() 在仍有 未完成 add 时会直接抛错,防止产出缺条目的损坏 ZIP。

单文件读取 / 列表 / stat:ZipReader

import { ZipReader } from 'yeow-fflate';
import { fs } from 'yeow-api';

const reader = new ZipReader(await fs.readFile('bundle.zip')); // 只解析中央目录,不解压文件

const entries = reader.list();          // ZipEntry[]:name/compression/size/originalSize/crc/mtime/attrs
const st = reader.stat('dir/b.bin');    // 单条目元数据;不存在返回 null
reader.has('a.txt');                    // true

const file = await reader.read('dir/b.bin');          // 只解压目标文件 → Uint8Array
const text = await reader.read('a.txt', 'utf8');      // → string
const b64 = reader.readSync('a.txt', 'base64');       // 同步读取 → Base64 字符串
reader.readSync('missing.txt');                       // null

// 读取原始压缩数据(不解压):DEFLATE 条目返回 raw deflate 流
const raw = reader.readRawSync('a.txt');              // Uint8Array | null
const raw2 = await reader.readRaw('dir/b.bin');       // 仅切片,不做解压

list() / stat() 是同步操作(元数据来自中央目录,无解压开销);read / readSync 只解压指定条目,编码语义与 fs.readFile 一致(默认 Uint8Array,显式 'utf8' / 'base64' 返回字符串);readRaw / readRawSync 直接返回条目的原始压缩字节(DEFLATE 条目为 raw deflate 流,存储条目为原始文件字节),不做任何解压。

Codec 后端

包加载时默认执行 useYeowCodecs():DEFLATE 与 UTF-8 全部走 yeow-api 的环境实现。

import { configureCodecs, useYeowCodecs, useNativeCodecs } from 'yeow-fflate';

useNativeCodecs();      // 切回 fflate 原生纯 JS(压缩 + UTF-8 全部内置)
useYeowCodecs();        // 切回 Yeow 桥接(默认)

// 自定义/部分配置:省略的字段回退原生实现
configureCodecs({
  deflate: (data, opts) => myDeflateRaw(data, { level: opts.level ?? 6 }),
  inflate: (data) => myInflateRaw(data),
  deflateAsync: (data, opts) => myAsyncDeflateRaw(data, opts),  // Promise<Uint8Array>
  inflateAsync: (data) => myAsyncInflateRaw(data),
  encodeUTF8: (str) => myUtf8Encode(str),
  decodeUTF8: (bytes) => myUtf8Decode(bytes),
});

configureCodecs(null);   // 等价 useNativeCodecs():清除全部注入

约定:注入的 deflate/inflate 处理 raw DEFLATE 流(无 gzip/zlib 包装); gzip/zlib 头尾、ZIP 容器与 CRC 始终由本库拼装。dictionary 选项只被原生 实现支持——带 dictionary 的调用会自动回退原生路径。latin1 快速路径始终走内置实现。

与 fflate 的差异

  • 无 Worker、无流式 API:移除了 worker 机制与全部流式类(Deflate/Inflate/Gzip/Zip/Unzip/DecodeUTF8/Async* 等)。
  • 异步 API 为 Promise-firstawait zip(...);回调形态保留但返回 void(无 AsyncTerminable)。
  • Zip 为增量构建器await zip.add(...) 异步压缩 + addSync(...) 同步压缩 + finish() 同步装配;原 fflate 流式 Zip 已移除。
  • Codec 后端统一配置configureCodecs() 取代 setDeflater/setInflater/... 六个散落注入点(0.2.0 起这些 setter 不再对外导出)。
  • 公共导出收敛:只导出 API 与类型,err/b2/b4/wzh/... 等内部工具不再泄露。
  • UTF-8 内置strToU8/strFromU8 使用内置纯 JS 实现(默认经后端用运行时全局 TextEncoder/TextDecoder——utf-8、同步,小载荷 JS 直转、超阈值走 util 通道,性能最好)。大规模非阻塞编解码可用 yeow-api 的异步 stringToBytes/bytesToString
  • 错误码:桥接产生的错误转为 FlateErrorcode90(fflate 内置码为 1-7)。

验证

npm install
npm run verify   # 47 项检查:桥接/原生/自定义后端、async/await、回调兼容、
                 # Zip 异步 add / addSync / finish 守卫、ZipReader list/stat/单文件/readRaw、
                 # UTF-8(中文/emoji/组合字符)、ZIP/CRC、标准兼容
npm run build    # 产出 dist/index.mjs(ESM)+ dist/index.cjs(CJS)+ dist/index.d.ts

verify.mjs 通过 --alias:yeow-api=./verify-shim.mjs 在本地用 node:zlib/Buffer 模拟 yeow-api(运行时实际走 Java 侧)。

License

MIT(fork 自 fflate)。