-
-
Notifications
You must be signed in to change notification settings - Fork 91
Expand file tree
/
Copy pathlambdafs.ts
More file actions
90 lines (78 loc) · 2.72 KB
/
lambdafs.ts
File metadata and controls
90 lines (78 loc) · 2.72 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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import { createReadStream, createWriteStream, existsSync } from "node:fs";
import { tmpdir } from "node:os";
import { basename, join } from "node:path";
import { createBrotliDecompress, createUnzip } from "node:zlib";
import { extract } from "tar-fs";
/**
* Decompresses a (tarballed) Brotli or Gzip compressed file and returns the path to the decompressed file/folder.
*
* @param filePath Path of the file to decompress.
*/
export const inflate = (filePath: string): Promise<string> => {
// Determine the output path based on the file type
const output =
filePath.includes("swiftshader") ? tmpdir() : (
join(
tmpdir(),
basename(filePath).replace(
/\.(?:t(?:ar(?:\.(?:br|gz))?|br|gz)|br|gz)$/i,
"",
),
)
);
return new Promise((resolve, reject) => {
// Quick return if the file is already decompressed
if (filePath.includes("swiftshader")) {
if (existsSync(`${output}/libGLESv2.so`)) {
resolve(output);
return;
}
} else if (existsSync(output)) {
resolve(output);
return;
}
// Optimize chunk size based on file type - use smaller chunks for better memory usage
// Brotli files tend to decompress to much larger sizes
const isBrotli = /br$/i.test(filePath);
const isGzip = /gz$/i.test(filePath);
const isTar = /\.t(?:ar(?:\.(?:br|gz))?|br|gz)$/i.test(filePath);
// Use a smaller highWaterMark for better memory efficiency
// For most serverless environments, 4MB (2**22) is more memory-efficient than 8MB
const highWaterMark = 2 ** 22;
const source = createReadStream(filePath, { highWaterMark });
let target;
// Setup error handlers first for both streams
const handleError = (error: Error) => {
reject(error);
};
source.once("error", handleError);
// Setup the appropriate target stream based on file type
if (isTar) {
target = extract(output);
target.once("finish", () => {
resolve(output);
});
} else {
target = createWriteStream(output, { mode: 0o700 });
target.once("close", () => {
resolve(output);
});
}
target.once("error", handleError);
// Pipe through the appropriate decompressor if needed
if (isBrotli || isGzip) {
// Use optimized chunk size for decompression
// 2MB (2**21) is sufficient for most brotli/gzip files
const decompressor =
isBrotli ?
createBrotliDecompress({ chunkSize: 2 ** 21 })
: createUnzip({ chunkSize: 2 ** 21 });
// Handle decompressor errors
decompressor.once("error", handleError);
// Chain the streams
source.pipe(decompressor).pipe(target);
} else {
source.pipe(target);
}
});
};