Skip to content

Commit 7461d0d

Browse files
committed
fix(rivetkit): resolve ESM-only secure-exec package in dynamic isolate runtime
1 parent 2cc1086 commit 7461d0d

1 file changed

Lines changed: 45 additions & 1 deletion

File tree

rivetkit-typescript/packages/rivetkit/src/dynamic/isolate-runtime.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createRequire } from "node:module";
2+
import { readFileSync } from "node:fs";
23
import { mkdir, readFile, stat } from "node:fs/promises";
34
import path from "node:path";
45
import { fileURLToPath, pathToFileURL } from "node:url";
@@ -1499,6 +1500,43 @@ async function loadIsolatedVmModule(): Promise<IsolatedVmModule> {
14991500
return isolatedVmModulePromise;
15001501
}
15011502

1503+
/**
1504+
* Resolve an ESM-only package entry by walking up from cwd to find it in
1505+
* node_modules. This handles packages that have "type": "module" and only
1506+
* define "import" in exports (no "require"), which createRequire().resolve()
1507+
* cannot handle.
1508+
*/
1509+
function resolveEsmPackageEntry(packageName: string): string | undefined {
1510+
let current = process.cwd();
1511+
while (true) {
1512+
const pkgJsonPath = path.join(
1513+
current,
1514+
"node_modules",
1515+
packageName,
1516+
"package.json",
1517+
);
1518+
try {
1519+
const content = readFileSync(pkgJsonPath, "utf-8");
1520+
const pkgJson = JSON.parse(content) as {
1521+
main?: string;
1522+
exports?: Record<string, unknown>;
1523+
};
1524+
const entryRelative =
1525+
(pkgJson.exports?.["."] as { import?: string } | undefined)
1526+
?.import ?? pkgJson.main;
1527+
if (entryRelative) {
1528+
return path.resolve(path.dirname(pkgJsonPath), entryRelative);
1529+
}
1530+
} catch {
1531+
// package.json not found at this level, keep walking up
1532+
}
1533+
const parent = path.dirname(current);
1534+
if (parent === current) break;
1535+
current = parent;
1536+
}
1537+
return undefined;
1538+
}
1539+
15021540
function resolveSecureExecEntryPath(): string {
15031541
const explicitSpecifier =
15041542
process.env.RIVETKIT_DYNAMIC_SECURE_EXEC_SPECIFIER;
@@ -1524,7 +1562,13 @@ function resolveSecureExecEntryPath(): string {
15241562
for (const packageSpecifier of packageSpecifiers) {
15251563
try {
15261564
return resolver.resolve(packageSpecifier);
1527-
} catch {}
1565+
} catch {
1566+
// createRequire().resolve() cannot resolve ESM-only packages (packages
1567+
// with "type": "module" and only "import" in exports). Fall back to
1568+
// manually finding the package in node_modules and reading its entry.
1569+
const resolved = resolveEsmPackageEntry(packageSpecifier);
1570+
if (resolved) return resolved;
1571+
}
15281572
}
15291573

15301574
const localDistCandidates = [

0 commit comments

Comments
 (0)