-
Notifications
You must be signed in to change notification settings - Fork 399
/
Copy pathuseAsyncSandpackId.ts
61 lines (52 loc) · 1.74 KB
/
useAsyncSandpackId.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
import type { SandpackBundlerFiles } from "@codesandbox/sandpack-client";
import { useId as useReactId } from "react";
import { generateRandomId } from "./stringUtils";
export const useSandpackId = () => {
if (typeof useReactId === "function") {
/* eslint-disable-next-line */
return useReactId();
} else {
return generateRandomId();
}
};
/**
* This is a hard constraint to make URLs shorter.
* For example, this id will be used to mount SW in the iframe
* so, to keep the URL valid, this must be an 9 character long string
*/
const MAX_ID_LENGTH = 9;
const sandpackClientVersion = process.env.SANDPACK_CLIENT_VERSION;
export const useAsyncSandpackId = (files: SandpackBundlerFiles) => {
if (typeof useReactId === "function") {
/* eslint-disable-next-line react-hooks/rules-of-hooks */
const reactDomId = useReactId();
return async () => {
const allCode = Object.entries(files)
.map((path, code) => path + "|" + code)
.join("|||");
const sha = await generateShortId(
allCode + reactDomId + sandpackClientVersion
);
return ensureLength(
sha.replace(/:/g, "sp").replace(/[^a-zA-Z]/g, ""),
MAX_ID_LENGTH
);
};
} else {
return () => ensureLength(generateRandomId(), MAX_ID_LENGTH);
}
};
function ensureLength(str: string, length: number) {
if (str.length > length) {
return str.slice(0, length);
} else {
return str.padEnd(length, "s");
}
}
async function generateShortId(input: string) {
const encoder = new TextEncoder();
const data = encoder.encode(input);
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return btoa(String.fromCharCode(...hashArray));
}