vite.config.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { existsSync, readdirSync, statSync } from "node:fs";
  2. import { resolve } from "node:path";
  3. import { fileURLToPath, URL } from "node:url";
  4. import type { Plugin } from "vite";
  5. import { defineConfig } from "vitest/config";
  6. const repoRoot = fileURLToPath(new URL("../..", import.meta.url)).replace(/\/+$/, "");
  7. function repoPath(p: string): string {
  8. const abs = resolve(repoRoot, p.replace(/^\/+/, ""));
  9. if (abs !== repoRoot && !abs.startsWith(`${repoRoot}/`)) {
  10. throw new Error(`path outside repo root: ${p}`);
  11. }
  12. return abs;
  13. }
  14. function nengineFsPlugin(): Plugin {
  15. return {
  16. name: "nengine-fs",
  17. configureServer(server) {
  18. server.middlewares.use((req, res, next) => {
  19. if (req.url === "/" || req.url?.startsWith("/?")) {
  20. req.url = "/apps/dev/index.html";
  21. next();
  22. return;
  23. }
  24. const url = new URL(req.url ?? "/", "http://localhost");
  25. const target = url.searchParams.get("p");
  26. if (!target) {
  27. next();
  28. return;
  29. }
  30. let abs: string;
  31. try {
  32. abs = repoPath(target);
  33. } catch {
  34. res.statusCode = 404;
  35. res.end("bad path");
  36. return;
  37. }
  38. if (url.pathname === "/__nengine_fs/readdir") {
  39. if (!existsSync(abs)) {
  40. res.statusCode = 404;
  41. res.end("ENOENT");
  42. return;
  43. }
  44. const entries = readdirSync(abs, { withFileTypes: true });
  45. const body =
  46. url.searchParams.get("detailed") === "1"
  47. ? JSON.stringify(entries.map((e) => ({ name: e.name, isDirectory: e.isDirectory() })))
  48. : JSON.stringify(entries.map((e) => e.name));
  49. res.setHeader("content-type", "application/json; charset=utf-8");
  50. res.end(body);
  51. return;
  52. }
  53. if (url.pathname === "/__nengine_fs/stat") {
  54. if (!existsSync(abs)) {
  55. res.statusCode = 404;
  56. res.end("ENOENT");
  57. return;
  58. }
  59. res.setHeader("content-type", "application/json; charset=utf-8");
  60. res.end(JSON.stringify({ isDirectory: statSync(abs).isDirectory() }));
  61. return;
  62. }
  63. if (url.pathname === "/__nengine_fs/exists") {
  64. res.setHeader("content-type", "text/plain; charset=utf-8");
  65. res.end(existsSync(abs) ? "1" : "0");
  66. return;
  67. }
  68. next();
  69. });
  70. },
  71. };
  72. }
  73. export default defineConfig({
  74. root: repoRoot,
  75. plugins: [nengineFsPlugin()],
  76. resolve: {
  77. alias: {
  78. "@nengine/core": fileURLToPath(new URL("../../packages/core/src/index.ts", import.meta.url)),
  79. "@nengine/render": fileURLToPath(new URL("../../packages/render/src/index.ts", import.meta.url)),
  80. "node:fs/promises": fileURLToPath(new URL("./src/shim/fs-promises.ts", import.meta.url)),
  81. "node:fs": fileURLToPath(new URL("./src/shim/fs.ts", import.meta.url)),
  82. "node:path": fileURLToPath(new URL("./src/shim/path.ts", import.meta.url)),
  83. "node:url": fileURLToPath(new URL("./src/shim/url.ts", import.meta.url)),
  84. },
  85. },
  86. build: {
  87. outDir: "apps/dev/dist",
  88. emptyOutDir: true,
  89. rollupOptions: {
  90. input: fileURLToPath(new URL("./index.html", import.meta.url)),
  91. },
  92. },
  93. test: {
  94. include: ["apps/dev/src/**/*.test.ts"],
  95. environment: "node",
  96. },
  97. });