import { createReadStream, cpSync, existsSync, statSync } from "node:fs"; import { createRequire } from "node:module"; import { dirname, resolve, sep } from "node:path"; import { fileURLToPath } from "node:url"; import { defineConfig, loadEnv, type Plugin } from "vite"; import react from "@vitejs/plugin-react"; import wasm from "vite-plugin-wasm"; const mapAdapterEntry = fileURLToPath(import.meta.resolve("@nodedc/map-cesium-react")); const cesiumPackageJson = createRequire(mapAdapterEntry).resolve("cesium/package.json"); const cesiumBuildRoot = resolve( dirname(cesiumPackageJson), "Build", "Cesium", ); const cesiumRuntimeDirectories = ["Assets", "ThirdParty", "Widgets", "Workers"] as const; function cesiumRuntimeAssets(): Plugin { return { name: "mission-core-cesium-runtime-assets", config: () => ({ define: { CESIUM_BASE_URL: JSON.stringify("/cesium"), }, }), configureServer(server) { server.middlewares.use("/cesium", (request, response, next) => { const pathname = new URL(request.url ?? "/", "http://localhost").pathname; const target = resolve(cesiumBuildRoot, `.${decodeURIComponent(pathname)}`); if (!target.startsWith(`${cesiumBuildRoot}${sep}`) || !existsSync(target)) { next(); return; } const stats = statSync(target); if (!stats.isFile()) { next(); return; } if (target.endsWith(".js")) response.setHeader("Content-Type", "text/javascript"); else if (target.endsWith(".json")) response.setHeader("Content-Type", "application/json"); else if (target.endsWith(".css")) response.setHeader("Content-Type", "text/css"); else if (target.endsWith(".wasm")) response.setHeader("Content-Type", "application/wasm"); else if (target.endsWith(".png")) response.setHeader("Content-Type", "image/png"); else if (target.endsWith(".svg")) response.setHeader("Content-Type", "image/svg+xml"); else if (target.endsWith(".jpg") || target.endsWith(".jpeg")) { response.setHeader("Content-Type", "image/jpeg"); } createReadStream(target).pipe(response); }); }, writeBundle(options) { const outputDirectory = resolve( process.cwd(), typeof options.dir === "string" ? options.dir : "dist", "cesium", ); cesiumRuntimeDirectories.forEach((directory) => { cpSync( resolve(cesiumBuildRoot, directory), resolve(outputDirectory, directory), { recursive: true }, ); }); }, }; } export default defineConfig(({ mode }) => { const env = loadEnv(mode, process.cwd(), ""); const apiTarget = env.VITE_API_TARGET || "http://127.0.0.1:8000"; return { plugins: [react(), wasm(), cesiumRuntimeAssets()], resolve: { alias: { "@mission-core/sensor-sdk": fileURLToPath(new URL("../../packages/sensor-ui/src/pluginSdk.ts", import.meta.url)), "@mission-core/plugin-sdk": fileURLToPath( new URL("./src/core/device-plugins/frontendSdk.ts", import.meta.url), ), "@xgrids-k1/frontend": fileURLToPath( new URL("../../plugins/xgrids-k1/frontend/src", import.meta.url), ), }, dedupe: ["react", "react-dom", "@nodedc/ui-react"], }, optimizeDeps: { // Rerun resolves its WASM asset relative to the package entrypoint. Vite's // dependency pre-bundler flattens that entrypoint and leaves the WASM URL // pointing at the SPA fallback, which browsers reject as text/html. exclude: ["@rerun-io/web-viewer"], }, build: { target: "esnext", rollupOptions: { input: { app: fileURLToPath(new URL("./index.html", import.meta.url)), rerun: fileURLToPath(new URL("./rerun-runtime.html", import.meta.url)), }, }, }, server: { host: "127.0.0.1", port: 5173, strictPort: true, fs: { allow: [ fileURLToPath(new URL(".", import.meta.url)), fileURLToPath(new URL("../../plugins/xgrids-k1", import.meta.url)), fileURLToPath(new URL("../../../NODEDC_DESIGN_GUIDELINE/packages", import.meta.url)), ], }, proxy: { "/api": { target: apiTarget, changeOrigin: false, ws: true, }, }, }, preview: { host: "127.0.0.1", port: 4173, strictPort: true, proxy: { "/api": { target: apiTarget, changeOrigin: false, ws: true, }, }, }, }; });