diff --git a/apps/server/src/sandbox/archives.ts b/apps/server/src/sandbox/archives.ts index c3763dd8..dae2cb10 100644 --- a/apps/server/src/sandbox/archives.ts +++ b/apps/server/src/sandbox/archives.ts @@ -1,10 +1,25 @@ // 压缩包解压(沙箱内):zip 用 fflate,rar 用 node-unrar-js(WASM),7z 用 7z-wasm。 // WASM 库要读自己包里的 .wasm 文件:prepareArchives() 在撤销权限前预热(载入内存),之后只在内存里解压。 -import SevenZip from "7z-wasm"; +import * as SevenZipModule from "7z-wasm"; import { unzipSync } from "fflate"; import { createExtractorFromData } from "node-unrar-js"; -type Seven = Awaited>; +/** 用到的 7z-wasm 接口(Emscripten 实例:内存文件系统 + callMain) */ +interface Seven { + FS: { + writeFile(path: string, data: Uint8Array): void; + readFile(path: string): Uint8Array; + readdir(path: string): string[]; + stat(path: string): { mode: number }; + isDir(mode: number): boolean; + }; + callMain(args: string[]): unknown; +} +// 7z-wasm 是 CJS 包:tsc 与 deno check 对默认导出的理解不同,运行时取 default 或模块本身 +const SevenZip = ((SevenZipModule as unknown as { default?: unknown }).default ?? SevenZipModule) as unknown as (opts: { + print: (s: string) => void; + printErr: (s: string) => void; +}) => Promise; let seven: Seven | null = null; let warmed = false; @@ -54,13 +69,13 @@ export async function extractArchive( } const out: Record = {}; const walk = (d: string, rel: string) => { - for (const n of z.FS.readdir(d) as string[]) { + for (const n of z.FS.readdir(d)) { if (n === "." || n === "..") continue; const p = `${d}/${n}`; const r = rel ? `${rel}/${n}` : n; if (z.FS.isDir(z.FS.stat(p).mode)) walk(p, r); else { - const data = z.FS.readFile(p) as Uint8Array; + const data = z.FS.readFile(p); if (accept(r, data.length)) out[r] = data; } }