118 lines
5.9 KiB
TypeScript
118 lines
5.9 KiB
TypeScript
import { defineConfig, type Plugin } from "vite";
|
|
import react from "@vitejs/plugin-react";
|
|
// @ts-expect-error The runtime is Node; this project intentionally avoids a browser dependency on Node types.
|
|
import fs from "node:fs";
|
|
// @ts-expect-error The runtime is Node; this project intentionally avoids a browser dependency on Node types.
|
|
import path from "node:path";
|
|
// @ts-expect-error The runtime is Node; this project intentionally avoids a browser dependency on Node types.
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const deploymentContract = JSON.parse(
|
|
fs.readFileSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../docs/web/deployment-contract.json"), "utf8"),
|
|
) as { responseHeaders: { allResponses: Record<string, string> } };
|
|
const isolationHeaders = deploymentContract.responseHeaders.allResponses;
|
|
const runtimeEnvironment = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env;
|
|
const unisolatedSingleThreadTest = runtimeEnvironment?.WEB_TEST_UNISOLATED_SINGLE_THREAD === "1";
|
|
const developmentHeaders = unisolatedSingleThreadTest ? {} : isolationHeaders;
|
|
|
|
function preserveIsolationHeaders(): Plugin {
|
|
const install = (server: { middlewares: { use: (handler: (request: unknown, response: { setHeader: (name: string, value: string) => void }, next: () => void) => void) => void } }) => {
|
|
server.middlewares.use((_request, response, next) => {
|
|
for (const [name, value] of Object.entries(isolationHeaders)) response.setHeader(name, value);
|
|
next();
|
|
});
|
|
};
|
|
return {
|
|
name: "preserve-isolation-headers",
|
|
configureServer: install,
|
|
configurePreviewServer: install,
|
|
};
|
|
}
|
|
|
|
function serveEngineVariantModuleImports(): Plugin {
|
|
const vendorRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "public/vendor/blender");
|
|
const install = (server: { middlewares: { use: (handler: (request: unknown, response: { setHeader: (name: string, value: string | number) => void }, next: () => void) => void) => void } }) => {
|
|
server.middlewares.use((request, response, next) => {
|
|
const url = new URL((request as { url?: string }).url ?? "/", "http://vite.local");
|
|
const match = url.pathname.match(/^\/vendor\/blender\/(single|pthread)\/web_engine\.js$/);
|
|
if (!match || !url.searchParams.has("import")) { next(); return; }
|
|
const filePath = path.join(vendorRoot, match[1], "web_engine.js");
|
|
if (!fs.existsSync(filePath)) { next(); return; }
|
|
const stat = fs.statSync(filePath);
|
|
response.setHeader("Content-Type", "text/javascript; charset=utf-8");
|
|
response.setHeader("Content-Length", stat.size);
|
|
for (const [name, value] of Object.entries(developmentHeaders)) response.setHeader(name, value);
|
|
fs.createReadStream(filePath).pipe(response as never);
|
|
});
|
|
};
|
|
return {
|
|
name: "serve-engine-variant-module-imports",
|
|
configureServer: install,
|
|
configurePreviewServer: install,
|
|
};
|
|
}
|
|
|
|
function localVDBFixture(): Plugin {
|
|
const resourceRoot = runtimeEnvironment?.VDB_RESOURCE_ROOT ?? path.join(runtimeEnvironment?.HOME ?? "", "resource-library/blender-web-vdb");
|
|
const files = new Map([
|
|
["/__vdb_fixture__/manifest", { path: path.join(resourceRoot, "manifests/generated-smoke.nanovdb.json"), type: "application/json" }],
|
|
["/__vdb_fixture__/report", { path: path.join(resourceRoot, "reports/generated-smoke-conversion.json"), type: "application/json" }],
|
|
["/__vdb_fixture__/bundle", { path: path.join(resourceRoot, "nanovdb/generated-smoke.nvdb"), type: "application/x-nanovdb" }],
|
|
["/assets/volumes/generated-smoke.nanovdb.json", { path: path.join(resourceRoot, "manifests/generated-smoke.nanovdb.json"), type: "application/json" }],
|
|
["/assets/volumes/generated-smoke.nvdb", { path: path.join(resourceRoot, "nanovdb/generated-smoke.nvdb"), type: "application/x-nanovdb" }],
|
|
["/volumes/generated-smoke.nanovdb.json", { path: path.join(resourceRoot, "manifests/generated-smoke.nanovdb.json"), type: "application/json" }],
|
|
["/volumes/generated-smoke.nvdb", { path: path.join(resourceRoot, "nanovdb/generated-smoke.nvdb"), type: "application/x-nanovdb" }],
|
|
]);
|
|
return {
|
|
name: "local-vdb-fixture",
|
|
configureServer(server) {
|
|
server.middlewares.use((request, response, next) => {
|
|
const nodeRequest = request as unknown as { url?: string; headers: { range?: string } };
|
|
const pathname = nodeRequest.url?.split("?", 1)[0] ?? "";
|
|
const fixture = files.get(pathname);
|
|
if (!fixture || !fs.existsSync(fixture.path)) { next(); return; }
|
|
const stat = fs.statSync(fixture.path);
|
|
response.setHeader("Content-Type", fixture.type);
|
|
response.setHeader("Accept-Ranges", "bytes");
|
|
response.setHeader("Cache-Control", "no-store");
|
|
response.setHeader("ETag", `"vdb-${stat.size}-${Math.trunc(stat.mtimeMs)}"`);
|
|
const match = nodeRequest.headers.range?.match(/^bytes=(\d+)-(\d+)$/);
|
|
if (match) {
|
|
const start = Number(match[1]);
|
|
const end = Number(match[2]);
|
|
if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < 0 || end < start || end >= stat.size) { response.writeHead(416); response.end(); return; }
|
|
response.statusCode = 206;
|
|
response.setHeader("Content-Range", `bytes ${start}-${end}/${stat.size}`);
|
|
response.setHeader("Content-Length", end - start + 1);
|
|
fs.createReadStream(fixture.path, { start, end }).pipe(response);
|
|
return;
|
|
}
|
|
response.setHeader("Content-Length", stat.size);
|
|
fs.createReadStream(fixture.path).pipe(response);
|
|
});
|
|
},
|
|
};
|
|
}
|
|
|
|
export default defineConfig({
|
|
root: "app",
|
|
plugins: [
|
|
serveEngineVariantModuleImports(),
|
|
...(unisolatedSingleThreadTest ? [] : [preserveIsolationHeaders()]),
|
|
localVDBFixture(),
|
|
react(),
|
|
],
|
|
server: {
|
|
port: 5173,
|
|
strictPort: false,
|
|
headers: developmentHeaders,
|
|
},
|
|
preview: {
|
|
headers: developmentHeaders,
|
|
},
|
|
build: {
|
|
outDir: "../dist",
|
|
emptyOutDir: true,
|
|
},
|
|
});
|