forked from PinSpace-Org/GistPin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompression.ts
More file actions
54 lines (44 loc) · 1.61 KB
/
Copy pathcompression.ts
File metadata and controls
54 lines (44 loc) · 1.61 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
import pako from 'pako';
const COMPRESSION_THRESHOLD_BYTES = 100_000;
export interface CompressedPayload {
compressed: true;
data: number[];
originalSize: number;
compressedSize: number;
ratio: number;
}
export interface UncompressedPayload {
compressed: false;
data: string;
}
export type DataPayload = CompressedPayload | UncompressedPayload;
export async function compressIfLarge<T>(value: T): Promise<DataPayload> {
const json = JSON.stringify(value);
const originalSize = new TextEncoder().encode(json).length;
if (originalSize < COMPRESSION_THRESHOLD_BYTES) {
return { compressed: false, data: json };
}
const bytes = pako.gzip(json);
const ratio = parseFloat(((1 - bytes.length / originalSize) * 100).toFixed(1));
return {
compressed: true,
data: Array.from(bytes),
originalSize,
compressedSize: bytes.length,
ratio,
};
}
export async function decompressPayload<T>(payload: DataPayload): Promise<T> {
if (!payload.compressed) return JSON.parse(payload.data) as T;
const json = pako.ungzip(new Uint8Array(payload.data), { to: 'string' });
return JSON.parse(json) as T;
}
export async function processLargeDataset<T>(
value: T,
): Promise<{ value: T; compressionInfo: string | null }> {
const payload = await compressIfLarge(value);
if (!payload.compressed) return { value, compressionInfo: null };
const restored = await decompressPayload<T>(payload);
const info = `Compressed ${(payload.originalSize / 1024).toFixed(1)} KB → ${(payload.compressedSize / 1024).toFixed(1)} KB (${payload.ratio}% saved)`;
return { value: restored, compressionInfo: info };
}