index.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import fs from "node:fs/promises";
  2. import path from "path";
  3. import {constants} from "node:fs";
  4. import os from "os";
  5. import parseComponent from "./parseComponent.js";
  6. export default async (express, options)=>{
  7. let opts = {
  8. production: true,
  9. routesDir: "routes",
  10. assetsDir: "assets",
  11. assetsRoute: "/assets"
  12. };
  13. Object.assign(opts, options)
  14. let app = express();
  15. removeOldTmpDirs();
  16. console.time("Build time");
  17. await fs.rm(path.join(process.cwd(), ".build/"), {recursive: true, force: true});
  18. let root = path.join(process.cwd(), opts.routesDir);
  19. await addRoute(root, root, app, opts);
  20. app.use(opts.assetsRoute, express.static(opts.assetsDir));
  21. console.timeEnd("Build time");
  22. return app;
  23. }
  24. const addRoute = async (dir, root, app, opts)=>{
  25. const files = await fs.readdir(dir, {withFileTypes: true});
  26. const indexFile = await findIndexFile(dir);
  27. if(!indexFile) return;
  28. let route = dir.replace(root, "");
  29. route = route === "" ? "/" : route;
  30. if(opts.production){
  31. const bundle = await parseComponent(indexFile, opts.production);
  32. const bundleLocation = dir.replace(opts.routesDir, ".build");
  33. const htmlPath = path.join(bundleLocation, "index.html");
  34. await fs.mkdir(bundleLocation, {recursive: true});
  35. await fs.writeFile(htmlPath, bundle);
  36. app.get(route, async (req, res)=>{res.sendFile(htmlPath, {dotfiles: "allow"})});
  37. }else{
  38. app.get(route, async (req, res)=>{res.send(await parseComponent(indexFile))});
  39. }
  40. fs.rm(path.join(dir, "tmp/"), {recursive: true, force: true});
  41. for(let i = 0; i < files.length; i++){
  42. const curDir = path.join(dir, files[i].name);
  43. if(files[i].isDirectory()) {
  44. await addRoute(curDir, root, app, opts);
  45. }
  46. }
  47. }
  48. const findIndexFile = async (dir)=>{
  49. const neovanPath = path.join(dir, "index.neovan");
  50. const htmlPath = path.join(dir, "index.html");
  51. const [neovan, html] = await Promise.allSettled([
  52. fs.access(path.join(dir, "index.neovan"), constants.F_OK),
  53. fs.access(path.join(dir, "index.html"), constants.F_OK)
  54. ]);
  55. if(neovan.status === "fulfilled") return neovanPath;
  56. if(html.status === "fulfilled") return htmlPath;
  57. return null;
  58. }
  59. const removeOldTmpDirs = async ()=>{
  60. const entries = await fs.readdir(os.tmpdir());
  61. for(let i = 0; i < entries.length; i++){
  62. if(entries[i].startsWith("neovan-")){
  63. fs.rm(entries[i], {recursive: true, force: true});
  64. }
  65. }
  66. }