forked from heygen-com/hyperframes
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathruntimeSource.ts
More file actions
98 lines (84 loc) · 3.28 KB
/
Copy pathruntimeSource.ts
File metadata and controls
98 lines (84 loc) · 3.28 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
91
92
93
94
95
96
97
98
import { createHash } from "node:crypto";
import { existsSync, readFileSync } from "node:fs";
import { resolve, dirname } from "node:path";
const ARTIFACT_NAMES = ["hyperframe-runtime.js", "hyperframe.runtime.iife.js"];
/**
* Resolve the runtime JS source for the studio preview server.
*
* Three resolution strategies, in priority order:
*
* 1. esbuild from source (dev only — gated on entry.ts existence)
* 2. Inlined constant (production — baked into @hyperframes/core at build time)
* 3. Pre-built artifact (fallback — reads IIFE file from dist/)
*/
export async function loadRuntimeSource(): Promise<string | null> {
return (await buildFromSource()) ?? (await getInlinedRuntime()) ?? readPrebuiltArtifact();
}
export async function loadRuntimeSourceSignature(): Promise<string | null> {
const source = await loadRuntimeSource();
if (!source) return null;
return createHash("sha256").update(source).digest("hex");
}
export function hashSignatureParts(parts: Array<string | null | undefined>): string {
const hash = createHash("sha256");
for (const part of parts) {
hash.update(part ?? "");
hash.update("\n--hf-signature-part--\n");
}
return hash.digest("hex");
}
// ── Strategy 1: live build from source (dev only) ──────────────────────────
const ENTRY_TS = resolve(__dirname, "..", "..", "..", "core", "src", "runtime", "entry.ts");
async function buildFromSource(): Promise<string | null> {
if (!existsSync(ENTRY_TS)) return null;
try {
const mod = await import("@hyperframes/core");
if (typeof mod.loadHyperframeRuntimeSource === "function") {
const source = mod.loadHyperframeRuntimeSource();
if (source) return source;
}
} catch {
// esbuild failed — fall through to inlined / artifact
}
return null;
}
// ── Strategy 2: inlined constant from core build ──────────────────────────
async function getInlinedRuntime(): Promise<string | null> {
try {
const mod = await import("@hyperframes/core");
if (typeof mod.getHyperframeRuntimeScript === "function") {
return mod.getHyperframeRuntimeScript() ?? null;
}
} catch {
// Not available — fall through to artifact
}
return null;
}
// ── Strategy 3: pre-built IIFE artifact ───────────────────────────────────
function readPrebuiltArtifact(): string | null {
return readFromDir(__dirname) ?? readFromCoreDistDir() ?? readFromNodeModules();
}
function readFromDir(dir: string): string | null {
for (const name of ARTIFACT_NAMES) {
const path = resolve(dir, name);
if (existsSync(path)) return readFileSync(path, "utf-8");
}
return null;
}
function readFromCoreDistDir(): string | null {
return readFromDir(resolve(__dirname, "..", "..", "..", "core", "dist"));
}
function readFromNodeModules(): string | null {
const subPaths = ["node_modules/hyperframes/dist", "node_modules/@hyperframes/core/dist"];
let dir = __dirname;
for (;;) {
for (const sub of subPaths) {
const result = readFromDir(resolve(dir, sub));
if (result) return result;
}
const parent = dirname(dir);
if (parent === dir) break;
dir = parent;
}
return null;
}