-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathutil.ts
137 lines (123 loc) · 3.42 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
126
127
128
129
130
131
132
133
134
135
136
137
import {
basename,
crypto,
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 digest = crypto.subtle.digestSync(
"MD5",
typeof data === "string" ? new TextEncoder().encode(data) : data,
);
const byteArray = Array.from(new Uint8Array(digest));
return byteArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
}
export async function getDependencies(path: string): Promise<string[]> {
const p = new Deno.Command(Deno.execPath(), {
args: ["info", "--json", path],
stdout: "piped",
stderr: "piped",
}).spawn();
const [status, output, stderrOutput] = await Promise.all([
p.status,
p.output(),
p.stderr,
]);
if (status.code !== 0) {
throw new Error(
decoder.decode((await stderrOutput.getReader().read()).value),
);
}
const denoInfo = JSON.parse(decoder.decode(output.stdout)) as DenoInfo;
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");
}
}
/**
* Returns `true` if the URL refers to a local file,
* else retuns `false` if the URL is for an external resource.
*/
export function isLocalUrl(url: string): boolean {
return !(url.startsWith("http://") || url.startsWith("https://"));
}