Repository navigation
Expand file tree
/
Copy pathdispatch.ts
More file actions
72 lines (61 loc) · 2.24 KB
/
Copy pathdispatch.ts
File metadata and controls
72 lines (61 loc) · 2.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import fs from "node:fs/promises";
import { PROPS_SCAN_WINDOW, RAW_PROPS_REGEX } from "./constants.js";
import { UnpackerReadError } from "./errors.js";
import { findSeaBlob } from "./sea/parser.js";
import { findBunArchive } from "./bun/parser.js";
import { findNexeArchive } from "./nexe/unpacker.js";
import { findCaxaArchive } from "./caxa/unpacker.js";
import type {
FormatOption,
FormatUnpacker,
UnpackFormat,
} from "./types.js";
import PkgUnpacker from "./pkg/unpacker.js";
import SeaUnpacker from "./sea/unpacker.js";
import BunUnpacker from "./bun/unpacker.js";
import NexeUnpacker from "./nexe/unpacker.js";
import CaxaUnpacker from "./caxa/unpacker.js";
const DETECT_PATTERN = new RegExp(RAW_PROPS_REGEX.source);
export async function detectFormat(filePath: string): Promise<UnpackFormat> {
const handle = await fs.open(filePath, "r");
try {
const { size } = await handle.stat();
const windowSize = Math.min(size, PROPS_SCAN_WINDOW);
const tail = Buffer.alloc(windowSize);
await handle.read({
buffer: tail,
offset: 0,
length: windowSize,
position: size - windowSize,
});
if (DETECT_PATTERN.test(tail.toString("utf-8"))) return "pkg";
if (findBunArchive(tail)) return "bun";
} finally {
await handle.close();
}
const file = await fs.readFile(filePath);
if (findSeaBlob(file)) return "sea";
if (findNexeArchive(file)) return "nexe";
if (findCaxaArchive(file)) return "caxa";
throw new UnpackerReadError(`Unsupported binary format: ${filePath}.`);
}
export async function createUnpacker(
filePath: string,
format: FormatOption = "auto",
): Promise<FormatUnpacker> {
const resolved = format === "auto" ? await detectFormat(filePath) : format;
switch (resolved) {
case "pkg":
return PkgUnpacker.create(filePath);
case "sea":
return SeaUnpacker.create(filePath);
case "bun":
return BunUnpacker.create(filePath);
case "nexe":
return NexeUnpacker.create(filePath);
case "caxa":
return CaxaUnpacker.create(filePath);
default:
throw new Error(`Unknown format: ${format}.`);
}
}