+5
-4
src/server.js
+5
-4
src/server.js
···
22
22
});
23
23
}
24
24
25
-
async start() {
26
-
this.app.listen(3000, () => {
27
-
console.log("Server is running on port 3000");
25
+
async start({ port }) {
26
+
this.app.listen(port, () => {
27
+
console.log(`Server is running on port ${port}`);
28
28
});
29
29
this.app.on("error", (error) => {
30
30
console.error("Server error:", error);
···
34
34
35
35
async function main() {
36
36
const args = yargs(process.argv.slice(2)).parse();
37
+
const port = args.port ?? args.p ?? 3000;
37
38
const configFilepath = args.config || "config.json";
38
39
const config = await Config.fromFile(configFilepath);
39
40
const handler = await Handler.fromConfig(config);
40
41
const server = new Server({
41
42
handler,
42
43
});
43
-
await server.start();
44
+
await server.start({ port });
44
45
}
45
46
46
47
main();
+8
config.multiple.example.json
+8
config.multiple.example.json
···
7
7
"branch": "main",
8
8
"baseDir": "/public",
9
9
"notFoundFilepath": "/404.html"
10
+
},
11
+
{
12
+
"subdomain": "url-example",
13
+
"tangledUrl": "https://tangled.sh/@gracekind.net/tangled-pages-example",
14
+
"tangledUrl:comment": "This will render the same site as above, but it's an example of how to use the tangledUrl field",
15
+
"branch": "main",
16
+
"baseDir": "/public",
17
+
"notFoundFilepath": "/404.html"
10
18
}
11
19
],
12
20
"subdomainOffset": 1,
+12
src/atproto.js
+12
src/atproto.js
···
10
10
return service.serviceEndpoint;
11
11
}
12
12
13
+
export async function resolveHandle(handle) {
14
+
const params = new URLSearchParams({
15
+
handle,
16
+
});
17
+
const res = await fetch(
18
+
"https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?" +
19
+
params.toString()
20
+
);
21
+
const data = await res.json();
22
+
return data.did;
23
+
}
24
+
13
25
async function resolveDid(did) {
14
26
if (did.startsWith("did:plc:")) {
15
27
const res = await fetch(`https://plc.directory/${encodeURIComponent(did)}`);
+30
-2
src/config.js
+30
-2
src/config.js
···
1
+
class SiteConfig {
2
+
constructor({
3
+
tangledUrl,
4
+
knotDomain,
5
+
ownerDid,
6
+
repoName,
7
+
branch,
8
+
baseDir,
9
+
notFoundFilepath,
10
+
}) {
11
+
if (tangledUrl) {
12
+
if ([ownerDid, repoName].some((v) => !!v)) {
13
+
throw new Error("Cannot use ownerDid and repoName with url");
14
+
}
15
+
}
16
+
this.tangledUrl = tangledUrl;
17
+
this.ownerDid = ownerDid;
18
+
this.repoName = repoName;
19
+
this.knotDomain = knotDomain;
20
+
this.branch = branch;
21
+
this.baseDir = baseDir;
22
+
this.notFoundFilepath = notFoundFilepath;
23
+
}
24
+
}
25
+
1
26
export class Config {
2
27
constructor({ site, sites, subdomainOffset, cache = false }) {
3
-
this.site = site;
4
-
this.sites = sites;
28
+
if (site && sites) {
29
+
throw new Error("Cannot use both site and sites in config");
30
+
}
31
+
this.site = site ? new SiteConfig(site) : null;
32
+
this.sites = sites ? sites.map((site) => new SiteConfig(site)) : null;
5
33
this.subdomainOffset = subdomainOffset;
6
34
this.cache = cache;
7
35
}
+2
README.md
+2
README.md
···
53
53
54
54
When `cache: false`, the server fetches files from the repo on every request, so it might be slow.
55
55
56
+
This library fetches html from the repo directly, so there's no build step. As a workaround, you can add a commit hook to build your site locally and include the built files in your repo (or as a git submodule).
57
+
56
58
## To-do
57
59
58
60
- support `cache: true` in workers
+13
-6
src/knot-client.js
+13
-6
src/knot-client.js
···
9
9
}
10
10
11
11
async getBlob(filename) {
12
-
const url = `https://${this.domain}/${this.ownerDid}/${
13
-
this.repoName
14
-
}/blob/${this.branch}/${trimLeadingSlash(filename)}`;
12
+
const params = new URLSearchParams({
13
+
repo: `${this.ownerDid}/${this.repoName}`,
14
+
path: trimLeadingSlash(filename),
15
+
ref: this.branch,
16
+
});
17
+
const url = `https://${this.domain}/xrpc/sh.tangled.repo.blob?${params}`;
15
18
console.log(`[KNOT CLIENT]: GET ${url}`);
16
19
const res = await fetch(url);
17
20
return await res.json();
18
21
}
19
22
20
23
async getRaw(filename) {
21
-
const url = `https://${this.domain}/${this.ownerDid}/${this.repoName}/raw/${
22
-
this.branch
23
-
}/${trimLeadingSlash(filename)}`;
24
+
const params = new URLSearchParams({
25
+
repo: `${this.ownerDid}/${this.repoName}`,
26
+
path: trimLeadingSlash(filename),
27
+
ref: this.branch,
28
+
raw: "true",
29
+
});
30
+
const url = `https://${this.domain}/xrpc/sh.tangled.repo.blob?${params}`;
24
31
console.log(`[KNOT CLIENT]: GET ${url}`);
25
32
const res = await fetch(url, {
26
33
responseType: "arraybuffer",