/
util.ts
125 lines (112 loc) · 2.96 KB
/
util.ts
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import {
basename,
createHash,
Document,
Element,
fromFileUrl,
MuxAsyncIterator,
} from "./deps.ts";
export const decoder = new TextDecoder();
export const encoder = new TextEncoder();
export function md5(data: string | ArrayBuffer): string {
const hash = createHash("md5");
hash.update(data);
return hash.toString();
}
export async function getDependencies(path: string): Promise<string[]> {
const p = Deno.run({
cmd: [Deno.execPath(), "info", "--json", path],
stdout: "piped",
stderr: "piped",
});
const [status, output, stderrOutput] = await Promise.all([
p.status(),
p.output(),
p.stderrOutput(),
]);
if (status.code !== 0) {
throw new Error(decoder.decode(stderrOutput));
}
const denoInfo = JSON.parse(decoder.decode(output)) as DenoInfo;
p.close();
return denoInfo.modules.map((m) => m.specifier);
}
export async function getLocalDependencies(path: string): Promise<string[]> {
return (await getDependencies(path)).filter((s) => s.startsWith("file:"));
}
export async function getLocalDependencyPaths(path: string): Promise<string[]> {
return (await getLocalDependencies(path)).map(fromFileUrl);
}
type Dependency = {
specifier: string;
isDynamic: boolean;
code: string;
};
type Module = {
specifier: string;
dependencies: Dependency[];
size: number;
mediaType: string;
local: string;
checksum: string;
emit: string;
};
type DenoInfo = {
root: string;
modules: Module[];
size: number;
};
/**
* querySelectorAll wrapper
*/
export function* qs(
doc: Document,
query: string,
): Generator<Element, void, void> {
for (const node of doc.querySelectorAll(query)) {
// deno-lint-ignore no-explicit-any
yield node as any as Element;
}
}
const KB = 2 ** 10;
const MB = 2 ** 20;
/**
* Returns human readable byte size expression.
*
* e.g.
* 1700 bytes -> 1.66KB
* 1300000 bytes -> 1.24MB
*/
export function byteSize(n: number) {
if (n > MB) {
return `${(n / MB).toFixed(2)}MB`;
} else if (n > KB) {
return `${(n / KB).toFixed(2)}KB`;
}
return `${n}B`;
}
// TODO(kt3k): Remove this util when https://github.com/denoland/deno_std/pull/923 is merged.
function asyncIterableToAsyncIterableIterator<T>(
iterable: AsyncIterable<T>,
): AsyncIterableIterator<T> {
const iterator = iterable[Symbol.asyncIterator]();
const iterableIterator = Object.assign(iterator, {
[Symbol.asyncIterator]() {
return iterableIterator;
},
});
return iterableIterator;
}
export function mux<T>(...iters: AsyncIterable<T>[]): AsyncIterable<T> {
return iters.reduce((mux: MuxAsyncIterator<T>, iter) => {
mux.add(asyncIterableToAsyncIterableIterator(iter));
return mux;
}, new MuxAsyncIterator<T>());
}
export function checkUniqueEntrypoints(paths: string[]): void {
// Throw if there are any duplicate basenames
const uniqueBasenames = new Set(paths.map((p) => basename(p)));
if (uniqueBasenames.size !== paths.length) {
throw new Error("Duplicate basenames");
}
}