Skip to content

Commit 8c02a74

Browse files
committed
Add helper to find runtime
1 parent ae03be4 commit 8c02a74

File tree

2 files changed

+123
-1
lines changed

2 files changed

+123
-1
lines changed

.prettierignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
server/out
33
analysis/examples
44
analysis/reanalyze/examples
5-
tools/tests
5+
tools/tests
6+
.history/

server/src/find-runtime.ts

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { readdir, stat as statAsync } from "fs/promises";
2+
import { join } from "path";
3+
4+
// Efficient parallel folder traversal to find node_modules directories
5+
async function findNodeModulesDirs(
6+
rootPath: string,
7+
maxDepth = 12,
8+
): Promise<string[]> {
9+
const nodeModulesDirs: string[] = [];
10+
const stack: Array<{ dir: string; depth: number }> = [
11+
{ dir: rootPath, depth: 0 },
12+
];
13+
const visited = new Set<string>();
14+
15+
while (stack.length) {
16+
const { dir, depth } = stack.pop()!;
17+
if (depth > maxDepth || visited.has(dir)) continue;
18+
visited.add(dir);
19+
20+
let entries: string[];
21+
try {
22+
entries = await readdir(dir);
23+
} catch {
24+
continue;
25+
}
26+
27+
if (entries.includes("node_modules")) {
28+
const nm = join(dir, "node_modules");
29+
try {
30+
const st = await statAsync(nm);
31+
if (st.isDirectory()) {
32+
nodeModulesDirs.push(nm);
33+
// Do NOT push deeper here to keep same behavior (stop at first node_modules in this branch)
34+
continue;
35+
}
36+
} catch {}
37+
}
38+
39+
for (const entry of entries) {
40+
if (entry === "node_modules" || entry.startsWith(".")) continue;
41+
const full = join(dir, entry);
42+
try {
43+
const st = await statAsync(full);
44+
if (st.isDirectory()) {
45+
stack.push({ dir: full, depth: depth + 1 });
46+
}
47+
} catch {}
48+
}
49+
}
50+
51+
return nodeModulesDirs;
52+
}
53+
54+
// Custom function to find Deno vendorized @rescript/runtime directories
55+
async function findDenoRescriptRuntime(nodeModulesPath: string) {
56+
// We only care about the Deno vendorized layout:
57+
// <nodeModulesPath>/.deno/@rescript+runtime@<version>/node_modules/@rescript/runtime
58+
const denoRoot = join(nodeModulesPath, ".deno");
59+
let entries: string[];
60+
try {
61+
entries = await readdir(denoRoot);
62+
} catch {
63+
return [];
64+
}
65+
66+
// Collect all @rescript+runtime@<version> vendor dirs
67+
const vendorDirs = entries.filter((e) => e.startsWith("@rescript+runtime@"));
68+
if (vendorDirs.length === 0) return [];
69+
70+
// Optionally pick “latest” by version; for now we return all valid matches.
71+
const results: string[] = [];
72+
for (const dir of vendorDirs) {
73+
const runtimePath = join(
74+
denoRoot,
75+
dir,
76+
"node_modules",
77+
"@rescript",
78+
"runtime",
79+
);
80+
try {
81+
const st = await statAsync(runtimePath);
82+
if (st.isDirectory()) results.push(runtimePath);
83+
} catch {
84+
// Ignore inaccessible / missing path
85+
}
86+
}
87+
88+
return results;
89+
}
90+
91+
export async function findRuntime(project: string) {
92+
// Find all node_modules directories using efficient traversal
93+
const node_modules = await findNodeModulesDirs(project);
94+
95+
const rescriptRuntimeDirs = await Promise.all(
96+
node_modules.map(async (nm) => {
97+
const results = [];
98+
99+
// Check for standard layout: @rescript/runtime
100+
const standardPath = join(nm, "@rescript", "runtime");
101+
try {
102+
const stat = await statAsync(standardPath);
103+
if (stat.isDirectory()) {
104+
results.push(standardPath);
105+
// If we found standard layout, no need to search for Deno layouts
106+
return results;
107+
}
108+
} catch (e) {
109+
// Directory doesn't exist, continue
110+
}
111+
112+
// Only check for Deno vendorized layouts if standard layout wasn't found
113+
const denoResults = await findDenoRescriptRuntime(nm);
114+
results.push(...denoResults);
115+
116+
return results;
117+
}),
118+
).then((results) => results.flatMap((x) => x));
119+
120+
return rescriptRuntimeDirs;
121+
}

0 commit comments

Comments
 (0)