2022-02-21 08:32:36 +00:00
|
|
|
import * as path from "https://deno.land/std@0.125.0/path/mod.ts";
|
|
|
|
import FileInfo = Deno.FileInfo;
|
|
|
|
|
|
|
|
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
|
|
|
|
import { oakCors } from "https://deno.land/x/cors@v1.2.0/mod.ts";
|
|
|
|
import { readAll } from "https://deno.land/std@0.126.0/streams/mod.ts";
|
2022-02-22 13:18:37 +00:00
|
|
|
import { exists } from "https://deno.land/std@0.126.0/fs/mod.ts";
|
2022-02-21 08:32:36 +00:00
|
|
|
|
2022-02-27 09:17:43 +00:00
|
|
|
import { recursiveReaddir } from "https://deno.land/x/recursive_readdir@v2.0.0/mod.ts";
|
|
|
|
|
2022-02-26 12:26:31 +00:00
|
|
|
type PageMeta = {
|
2022-02-25 14:34:00 +00:00
|
|
|
name: string;
|
|
|
|
lastModified: number;
|
|
|
|
};
|
|
|
|
|
2022-02-22 13:18:37 +00:00
|
|
|
const fsPrefix = "/fs";
|
2022-02-26 12:26:31 +00:00
|
|
|
const pagesPath = "../pages";
|
2022-02-21 08:32:36 +00:00
|
|
|
|
|
|
|
const fsRouter = new Router();
|
|
|
|
|
2022-02-25 14:34:00 +00:00
|
|
|
fsRouter.use(oakCors({ methods: ["OPTIONS", "GET", "PUT", "POST"] }));
|
2022-02-21 08:32:36 +00:00
|
|
|
|
2022-02-22 13:18:37 +00:00
|
|
|
fsRouter.get("/", async (context) => {
|
2022-02-26 12:26:31 +00:00
|
|
|
const localPath = pagesPath;
|
|
|
|
let fileNames: PageMeta[] = [];
|
2022-02-27 09:17:43 +00:00
|
|
|
const markdownFiles = (await recursiveReaddir(localPath)).filter(
|
|
|
|
(file: string) => path.extname(file) === ".md"
|
|
|
|
);
|
|
|
|
for (const p of markdownFiles) {
|
|
|
|
const stat = await Deno.stat(p);
|
|
|
|
fileNames.push({
|
|
|
|
name: p.substring(
|
|
|
|
localPath.length + 1,
|
|
|
|
p.length - path.extname(p).length
|
|
|
|
),
|
|
|
|
lastModified: stat.mtime?.getTime()!,
|
|
|
|
});
|
2022-02-22 13:18:37 +00:00
|
|
|
}
|
|
|
|
context.response.body = JSON.stringify(fileNames);
|
2022-02-21 08:32:36 +00:00
|
|
|
});
|
|
|
|
|
2022-02-27 09:17:43 +00:00
|
|
|
fsRouter.get("/:page(.*)", async (context) => {
|
2022-02-26 12:26:31 +00:00
|
|
|
const pageName = context.params.page;
|
|
|
|
const localPath = `${pagesPath}/${pageName}.md`;
|
2022-02-22 13:18:37 +00:00
|
|
|
try {
|
2022-02-25 14:34:00 +00:00
|
|
|
const stat = await Deno.stat(localPath);
|
2022-02-22 13:18:37 +00:00
|
|
|
const text = await Deno.readTextFile(localPath);
|
2022-02-25 14:34:00 +00:00
|
|
|
context.response.headers.set("Last-Modified", "" + stat.mtime?.getTime());
|
2022-02-22 13:18:37 +00:00
|
|
|
context.response.body = text;
|
|
|
|
} catch (e) {
|
|
|
|
context.response.status = 404;
|
|
|
|
context.response.body = "";
|
|
|
|
}
|
2022-02-21 08:32:36 +00:00
|
|
|
});
|
|
|
|
|
2022-02-27 09:17:43 +00:00
|
|
|
fsRouter.options("/:page(.*)", async (context) => {
|
2022-02-26 12:26:31 +00:00
|
|
|
const localPath = `${pagesPath}/${context.params.page}.md`;
|
2022-02-22 13:18:37 +00:00
|
|
|
try {
|
|
|
|
const stat = await Deno.stat(localPath);
|
|
|
|
context.response.headers.set("Content-length", `${stat.size}`);
|
2022-02-25 14:34:00 +00:00
|
|
|
context.response.headers.set("Last-Modified", "" + stat.mtime?.getTime());
|
2022-02-22 13:18:37 +00:00
|
|
|
} catch (e) {
|
2022-02-25 14:34:00 +00:00
|
|
|
// For CORS
|
2022-02-22 13:18:37 +00:00
|
|
|
context.response.status = 200;
|
|
|
|
context.response.body = "";
|
|
|
|
}
|
|
|
|
});
|
2022-02-21 08:32:36 +00:00
|
|
|
|
2022-02-27 09:17:43 +00:00
|
|
|
fsRouter.put("/:page(.*)", async (context) => {
|
2022-02-26 12:26:31 +00:00
|
|
|
const pageName = context.params.page;
|
|
|
|
const localPath = `${pagesPath}/${pageName}.md`;
|
|
|
|
const existingPage = await exists(localPath);
|
2022-02-27 09:17:43 +00:00
|
|
|
let dirName = path.dirname(localPath);
|
|
|
|
if (!(await exists(dirName))) {
|
|
|
|
await Deno.mkdir(dirName, {
|
|
|
|
recursive: true,
|
|
|
|
});
|
|
|
|
}
|
2022-02-22 13:18:37 +00:00
|
|
|
let file;
|
|
|
|
try {
|
|
|
|
file = await Deno.create(localPath);
|
|
|
|
} catch (e) {
|
|
|
|
console.error("Error opening file for writing", localPath, e);
|
|
|
|
context.response.status = 500;
|
|
|
|
context.response.body = e.message;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const result = context.request.body({ type: "reader" });
|
|
|
|
const text = await readAll(result.value);
|
|
|
|
file.write(text);
|
|
|
|
file.close();
|
2022-02-25 14:34:00 +00:00
|
|
|
const stat = await Deno.stat(localPath);
|
2022-02-22 13:18:37 +00:00
|
|
|
console.log("Wrote to", localPath);
|
2022-02-26 12:26:31 +00:00
|
|
|
context.response.status = existingPage ? 200 : 201;
|
2022-02-25 14:34:00 +00:00
|
|
|
context.response.headers.set("Last-Modified", "" + stat.mtime?.getTime());
|
2022-02-22 13:18:37 +00:00
|
|
|
context.response.body = "OK";
|
2022-02-21 08:32:36 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
const app = new Application();
|
2022-02-22 13:18:37 +00:00
|
|
|
app.use(
|
|
|
|
new Router()
|
|
|
|
.use(fsPrefix, fsRouter.routes(), fsRouter.allowedMethods())
|
|
|
|
.routes()
|
|
|
|
);
|
2022-02-21 08:32:36 +00:00
|
|
|
app.use(async (context, next) => {
|
2022-02-22 13:18:37 +00:00
|
|
|
try {
|
|
|
|
await context.send({
|
|
|
|
root: "../webapp/dist",
|
|
|
|
index: "index.html",
|
|
|
|
});
|
|
|
|
} catch {
|
|
|
|
next();
|
|
|
|
}
|
2022-02-21 08:32:36 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
await app.listen({ port: 2222 });
|