解脱
Tar和tar.gz 提取无依赖和无节点 API
读取 a .tar 或者说 .tar.gz 在工作,浏览器, 在 Bun 和 在节点, 相同
代码和零依赖. Gzip 由平台自己处理
DecompressionStream('gzip') 而不是一个捆绑的充气器,这就是保持
依赖数为零,捆绑成本为零.
目录
为什么
最初的问题是在运行时安装 Drupal 缩写模块,这意味着读取
drupal.org (英语) .tar.gz 从云旗工人里面 两个明显的答案都结束了:
- 在PHP中进行. 原创建筑也没有
ext-zip也没有ext-phar,添加其中之一为 多小时 Docker 重建翻译. - 使用焦油库. 每一个受欢迎的
node:zlib, (中文(简体) ),node:fs或者说Buffer。 。 。 . 工人没有这些.
工人确实有 DecompressionStream('gzip')土生土长的 沥青只是
512字节块并有八进制头. 所以整个工作都适合 ~320行的平台
JavaScript, 出处 await 合法,没有建造旗帜必须改变.
QQ 安装
bun add @drupflare/untarl
一个入口. 这个 exports 地图声明 . 财务报告和审定财务报表 ./package.json 什么都没有
所以每个符号都来自 @drupflare/untarl 财务报告和审定财务报表 @drupflare/untarl/src/untar.ts 被拒绝
以判决者盟誓, 唯一一个模块的第二个名字是两种方式,可以导入同样的东西,没有
如何说哪一个是犬; 兄弟姐妹 cartridge 由子路径分割,因为它的模块有
不同抚养费用,这里没有什么不同.
使用量
常见的情况是两个调用:充气和分解,然后平分要写的文件.
import { tarEntryTree, untarGzip } from '@drupflare/untarl';
const response = await fetch('https://ftp.drupal.org/files/projects/token-8.x-1.15.tar.gz');
const entries = await untarGzip(response.body!);
// strip = 1 drops the `token/` wrapper every drupal.org tarball has
for (const [path, bytes] of tarEntryTree(entries, 1)) {
// write `bytes` to `path` here
}
如果您已经持有字节, 或者归档没有被 gzip, 请直接跳到解析器 :
import { parseTar } from '@drupflare/untarl';
const entries = parseTar(new Uint8Array(await file.arrayBuffer()));
const names = entries.filter((e) => e.type === 'file').map((e) => e.name);
• API
| 导出 | 签署 | 它会做什么 |
|---|---|---|
untarGzip(stream) | (ReadableStream<Uint8Array>) => Promise<TarEntry[]> | 枪口穿过 DecompressionStream,然后解析 |
parseTar(bytes) | (Uint8Array) => TarEntry[] | 忠实地解析 POSIX/ ustar 归档; 以路径为由拒绝任何内容 |
tarEntryTree(entries, strip= 1) | (TarEntry[], number) => Map<string, Uint8Array> | 平整要写的文件, 拒绝逃跑的路径 |
TarEntry | { name, size, type, mode, bytes } | 1名成员; bytes 是一个自有副本,所以可以发布归档 |
TarEntryType | 'file' | 'directory' | 数个打字板,意思相同,叠在一起 |
TarParseError | Error & { offset?: number } | 畸形、截断或异地归档 |
TarPathError | Error & { path: string } | 摆脱目标目录的成员路径 |
两个出错类型之间的分出是设计. parseTar() 忠实于字节
并很乐意将一个名字从目标目录中爬出 ..
部分. tarEntryTree() 决定什么是安全的, 是扔出的唯一一层
TarPathError分离后,您可以检查一个敌对的档案 而不分析
内容.
未信任输入
网络上的焦油球是不信任的, 所以每个读取被限制 每一个失败都是 名称 错误而不是读取过缓冲器的末端, 无限回路, 或可能 空结果 .
| 拒绝 | 错误 |
|---|---|
| 短短的下载剪接标题 | TarParseError页:1 |
(单位:千美元) size 超过缓冲的字段 | TarParseError |
a 非绝对值 size 或者说 mode | TarParseError |
| 无名条目 | TarParseError |
| 绝对成员路径 | TarPathError从 tarEntryTree() |
包含 .. | TarPathError从 tarEntryTree() |
| 敌对者 目录 名称,尽管已删除 | TarPathError: 在类型过滤器前选中 |
负或非整数 strip | RangeError |
页:1. 作者对是否 字段将字节合并为签名或未签名,因此执行时拒绝真实的档案; 八进制 并限制检查已经阻止了错误的页眉被读取。 这是决定,不是 遗漏.
* 超出范围
- 它不流 剖析. 归档是缓冲的,因为焦油头没有 后指: 不走之前的每个街区都找不到条目 。 用来画画 模块是几兆字节,这是它所构建的大小.
- 它没有跟随链接. 连线,硬链接和设备节点被消耗并投放. 模块安装中的任何内容都不应该跟随一个模块.
- 它不写文件 .
tarEntryTree()给你一个Map那些字节的土地就是你的. - 它不创建档案. 仅取出.
它能处理真正的 Drupal.org tarballs 中的形状: ustar prefix 拆分, GNU L 长
名称、 pax x编号 :g 页: 1 x 标题 path= 记录重命名其条目
描述),和 v7 将目录写作打字旗的习惯 0 带着一刀一刀.
测试
bun run typecheck
bun run test # 89 assertions across 2 specs
bun run test:coverage
89个通过时 98.68%的报表, 超过所建档案而非登录 所以上面的每个拒绝 都有一个案件会影响它.
两行被揭出. src/untar.ts:75 这是 byteAt() 防线。 每个读头都坐着
在块内,循环已经检查过,所以无法从 parseTar()。 。 。 . src/untar.ts:214
是"不推进"的警卫, 这可以证明是无法到达的: next 实值
headerAt + 512 + ceil(size / 512) * 512这样 next <= headerAt 当一个信头是
整个街区。 因为它防止的失败是绞刑而不是错误.
有关仓库
| 仓库 | 这是什么 |
|---|---|
drupflare/worker | 消费者: " Cloudflare Workers " 上的 " Drupal 11 " ,读取模块焦油丸 |
drupflare/cartridge | 在持久对象中运行被屏蔽解释器的主机侧面 |
drupflare/durabledb | 持久对象SQLite的测量极限,加上它们存活下来的编码器 |
许可证
MIT (c) 格雷戈里·米切尔 2026. 见 自由主义。 。 。 .