summary refs log tree commit diff stats
path: root/src/index.ts
blob: e35368db7a3bb31340eb903d1c6cdc5e1b19c5c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import path from "node:path";
import fs, { Stats } from "node:fs";
import fsp from "node:fs/promises";
import util from "node:util";

import { withHtmlLiveReload } from "bun-html-live-reload";
import containsPath from "contains-path";

import readConfig from "./config";

const base = "../website/";
const publicDir = path.resolve(base, "public") + path.sep;

const config = readConfig(base);
const defaultHeaders = config.extra.headers;

function getFilename(name: string): string {
  return path.join(publicDir, `${name}`);
}

type File = {
  filename: string;
  size: number;
  mtime: string;
};

let files = new Map<string, File>();

function registerFile(pathname: string, absPath: string, stat: Stats): void {
  pathname = "/" + (pathname === "." || pathname === "./" ? "" : pathname);

  if (files.get(pathname) !== undefined) {
    console.warn("File already registered:", pathname);
  }
  files.set(pathname, {
    filename: absPath,
    size: stat.size,
    mtime: stat.mtime.toUTCString(),
  });
}

function walkDirectory(root: string, dir: string) {
  const absDir = path.join(root, dir);
  for (let pathname of fs.readdirSync(absDir)) {
    const relPath = path.join(dir, pathname);
    const absPath = path.join(absDir, pathname);
    const stat = fs.statSync(absPath);
    if (stat.isDirectory()) {
      walkDirectory(root, relPath + path.sep);
    } else if (stat.isFile()) {
      if (pathname === "index.html") {
        registerFile(path.dirname(relPath), absPath, stat);
        registerFile(path.dirname(relPath) + path.sep, absPath, stat);
      }
      registerFile(relPath, absPath, stat);
    }
  }
}

walkDirectory(publicDir, "");

export default withHtmlLiveReload({
  fetch: async function (request) {
    const pathname = new URL(request.url).pathname;
    if (files.has(pathname)) {
      const file = files.get(pathname);
      console.info("filename", file.filename);
      return new Response(Bun.file(file.filename), {
        headers: defaultHeaders,
        status: 200,
      });
    }
    return new Response(Bun.file(getFilename("404.html")), {
      headers: Object.assign({}, defaultHeaders, {
        "cache-control": "max-age=5, no-cache",
      }),
      status: 404,
      statusText: "Not Found",
    });
  },
});