fix(build): include wreq-js native assets in standalone

This commit is contained in:
diegosouzapw
2026-04-25 07:32:44 -03:00
parent eada1321ff
commit f5df0d337d
3 changed files with 87 additions and 5 deletions

View File

@@ -6,6 +6,7 @@
- **fix(mitm):** Compile MITM utilities as NodeNext ESM during prepublish, copy the CommonJS MITM server into the standalone artifact, and resolve MITM data paths without relying on Next.js aliases in packaged runtime.
- **fix(build):** Move the local `.tmp/wine32` Wine prefix out of the isolated Next.js build path so Windows Electron packaging artifacts cannot trigger `EACCES` scans during Node 24 builds.
- **fix(build):** Copy the `wreq-js` native runtime directory into the isolated Next.js standalone output so packaged Playwright/E2E starts can load the instrumentation hook on Linux.
- **fix(api):** Validate the Codex Responses websocket bridge and `/v1/batches` JSON payloads with Zod before use, keeping `request.json()` route validation green and returning explicit 400 responses for invalid bodies.
- **fix(providers):** Add explicit typing to provider alias and category helpers so the strict `typecheck:noimplicit:core` CI gate passes.
- **fix(ui):** Keep the upstream proxy provider detail page labeled with a fallback "Managed via Upstream Proxy Settings" management surface when translations are unavailable.

View File

@@ -136,6 +136,41 @@ export async function pruneStandaloneArtifacts(rootDir = projectRoot, fsImpl = f
}
}
export async function syncStandaloneNativeAssets(
rootDir = projectRoot,
fsImpl = fs,
log = console
) {
const nativeAssetDirs = [
{
label: "wreq-js native runtime",
sourcePath: path.join(rootDir, "node_modules", "wreq-js", "rust"),
destinationPath: path.join(rootDir, ".next", "standalone", "node_modules", "wreq-js", "rust"),
},
];
let changed = false;
for (const entry of nativeAssetDirs) {
if (!(await exists(entry.sourcePath))) continue;
await fsImpl.mkdir(path.dirname(entry.destinationPath), { recursive: true });
await fsImpl.cp(entry.sourcePath, entry.destinationPath, {
recursive: true,
force: true,
});
log.log(
`[build-next-isolated] Copied native standalone asset: ${path.relative(
rootDir,
entry.destinationPath
)}`
);
changed = true;
}
return changed;
}
export async function main() {
const movedPaths = [];
const transientBuildPaths = getTransientBuildPaths();
@@ -175,6 +210,15 @@ export async function main() {
pruneErr
);
}
try {
await syncStandaloneNativeAssets(projectRoot);
} catch (nativeAssetErr) {
console.warn(
"[build-next-isolated] Non-fatal error copying native standalone assets:",
nativeAssetErr
);
}
}
process.exitCode = result.code;
} catch (error) {

View File

@@ -5,8 +5,13 @@ import fsSync from "node:fs";
import os from "node:os";
import path from "node:path";
const { getTransientBuildPaths, movePath, pruneStandaloneArtifacts, resolveNextBuildEnv } =
await import("../../scripts/build-next-isolated.mjs");
const {
getTransientBuildPaths,
movePath,
pruneStandaloneArtifacts,
resolveNextBuildEnv,
syncStandaloneNativeAssets,
} = await import("../../scripts/build-next-isolated.mjs");
async function withTempDir(fn) {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "omniroute-build-next-isolated-"));
@@ -74,8 +79,7 @@ test("movePath rethrows non-EXDEV rename failures", async () => {
await assert.rejects(
movePath(sourceDir, destinationDir, {
rename: async () => {
const error = new Error("permission denied");
error.code = "EACCES";
const error = Object.assign(new Error("permission denied"), { code: "EACCES" });
throw error;
},
cp: async () => {
@@ -85,7 +89,7 @@ test("movePath rethrows non-EXDEV rename failures", async () => {
throw new Error("remove fallback should not run");
},
}),
(error) => (error as any).code === "EACCES"
(error) => error instanceof Error && "code" in error && error.code === "EACCES"
);
});
});
@@ -136,3 +140,36 @@ test("pruneStandaloneArtifacts removes traced _tasks from standalone output", as
assert.equal(fsSync.existsSync(path.join(tempDir, ".next", "standalone", "_tasks")), false);
});
});
test("syncStandaloneNativeAssets copies wreq-js native runtime into standalone output", async () => {
await withTempDir(async (tempDir) => {
const sourceNativeFile = path.join(
tempDir,
"node_modules",
"wreq-js",
"rust",
"wreq-js.linux-x64-gnu.node"
);
const destinationNativeFile = path.join(
tempDir,
".next",
"standalone",
"node_modules",
"wreq-js",
"rust",
"wreq-js.linux-x64-gnu.node"
);
const logs: string[] = [];
await fs.mkdir(path.dirname(sourceNativeFile), { recursive: true });
await fs.writeFile(sourceNativeFile, "native module bytes");
const changed = await syncStandaloneNativeAssets(tempDir, fs, {
log: (message: unknown) => logs.push(String(message)),
});
assert.equal(changed, true);
assert.equal(await fs.readFile(destinationNativeFile, "utf8"), "native module bytes");
assert.match(logs[0] ?? "", /wreq-js\/rust/);
});
});