Static site hosting via tangled
1import {
2 getContentTypeForFilename,
3 trimLeadingSlash,
4 extname,
5 joinurl,
6} from "./helpers.js";
7import { KnotClient } from "./knot-client.js";
8
9export class PagesService {
10 constructor({
11 knotDomain,
12 ownerDid,
13 repoName,
14 branch = "main",
15 baseDir = "/",
16 notFoundFilepath = null,
17 }) {
18 this.knotDomain = knotDomain;
19 this.ownerDid = ownerDid;
20 this.repoName = repoName;
21 this.branch = branch;
22 this.baseDir = baseDir;
23 this.notFoundFilepath = notFoundFilepath;
24 this.client = new KnotClient({
25 domain: knotDomain,
26 ownerDid,
27 repoName,
28 branch,
29 });
30 }
31
32 async getFileContent(filename) {
33 let content = null;
34 const blob = await this.client.getBlob(filename);
35 if (blob.is_binary) {
36 content = await this.client.getRaw(filename);
37 } else {
38 content = blob.contents;
39 }
40 return content;
41 }
42
43 async getPage(route) {
44 let filePath = route;
45 const extension = extname(filePath);
46 if (!extension) {
47 filePath = joinurl(filePath, "index.html");
48 }
49 const fullPath = joinurl(this.baseDir, trimLeadingSlash(filePath));
50 const content = await this.getFileContent(fullPath);
51 if (!content) {
52 return this.get404();
53 }
54 return {
55 status: 200,
56 content,
57 contentType: getContentTypeForFilename(fullPath),
58 };
59 }
60
61 async get404() {
62 if (this.notFoundFilepath) {
63 const content = await this.getFileContent(this.notFoundFilepath);
64 if (!content) {
65 console.warn("'Not found' file not found", this.notFoundFilepath);
66 return { status: 404, content: "Not Found", contentType: "text/plain" };
67 }
68 return {
69 status: 404,
70 content,
71 contentType: getContentTypeForFilename(this.notFoundFilepath),
72 };
73 }
74 return { status: 404, content: "Not Found", contentType: "text/plain" };
75 }
76}