Static site hosting via tangled

Compare changes

Choose any two refs to compare.

+5 -4
src/server.js
···
});
}
-
async start() {
-
this.app.listen(3000, () => {
-
console.log("Server is running on port 3000");
});
this.app.on("error", (error) => {
console.error("Server error:", error);
···
async function main() {
const args = yargs(process.argv.slice(2)).parse();
const configFilepath = args.config || "config.json";
const config = await Config.fromFile(configFilepath);
const handler = await Handler.fromConfig(config);
const server = new Server({
handler,
});
-
await server.start();
}
main();
···
});
}
+
async start({ port }) {
+
this.app.listen(port, () => {
+
console.log(`Server is running on port ${port}`);
});
this.app.on("error", (error) => {
console.error("Server error:", error);
···
async function main() {
const args = yargs(process.argv.slice(2)).parse();
+
const port = args.port ?? args.p ?? 3000;
const configFilepath = args.config || "config.json";
const config = await Config.fromFile(configFilepath);
const handler = await Handler.fromConfig(config);
const server = new Server({
handler,
});
+
await server.start({ port });
}
main();
+8
config.multiple.example.json
···
"branch": "main",
"baseDir": "/public",
"notFoundFilepath": "/404.html"
}
],
"subdomainOffset": 1,
···
"branch": "main",
"baseDir": "/public",
"notFoundFilepath": "/404.html"
+
},
+
{
+
"subdomain": "url-example",
+
"tangledUrl": "https://tangled.sh/@gracekind.net/tangled-pages-example",
+
"tangledUrl:comment": "This will render the same site as above, but it's an example of how to use the tangledUrl field",
+
"branch": "main",
+
"baseDir": "/public",
+
"notFoundFilepath": "/404.html"
}
],
"subdomainOffset": 1,
+12
src/atproto.js
···
return service.serviceEndpoint;
}
async function resolveDid(did) {
if (did.startsWith("did:plc:")) {
const res = await fetch(`https://plc.directory/${encodeURIComponent(did)}`);
···
return service.serviceEndpoint;
}
+
export async function resolveHandle(handle) {
+
const params = new URLSearchParams({
+
handle,
+
});
+
const res = await fetch(
+
"https://public.api.bsky.app/xrpc/com.atproto.identity.resolveHandle?" +
+
params.toString()
+
);
+
const data = await res.json();
+
return data.did;
+
}
+
async function resolveDid(did) {
if (did.startsWith("did:plc:")) {
const res = await fetch(`https://plc.directory/${encodeURIComponent(did)}`);
+30 -2
src/config.js
···
export class Config {
constructor({ site, sites, subdomainOffset, cache = false }) {
-
this.site = site;
-
this.sites = sites;
this.subdomainOffset = subdomainOffset;
this.cache = cache;
}
···
+
class SiteConfig {
+
constructor({
+
tangledUrl,
+
knotDomain,
+
ownerDid,
+
repoName,
+
branch,
+
baseDir,
+
notFoundFilepath,
+
}) {
+
if (tangledUrl) {
+
if ([ownerDid, repoName].some((v) => !!v)) {
+
throw new Error("Cannot use ownerDid and repoName with url");
+
}
+
}
+
this.tangledUrl = tangledUrl;
+
this.ownerDid = ownerDid;
+
this.repoName = repoName;
+
this.knotDomain = knotDomain;
+
this.branch = branch;
+
this.baseDir = baseDir;
+
this.notFoundFilepath = notFoundFilepath;
+
}
+
}
+
export class Config {
constructor({ site, sites, subdomainOffset, cache = false }) {
+
if (site && sites) {
+
throw new Error("Cannot use both site and sites in config");
+
}
+
this.site = site ? new SiteConfig(site) : null;
+
this.sites = sites ? sites.map((site) => new SiteConfig(site)) : null;
this.subdomainOffset = subdomainOffset;
this.cache = cache;
}
+2
README.md
···
When `cache: false`, the server fetches files from the repo on every request, so it might be slow.
## To-do
- support `cache: true` in workers
···
When `cache: false`, the server fetches files from the repo on every request, so it might be slow.
+
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).
+
## To-do
- support `cache: true` in workers
+13 -6
src/knot-client.js
···
}
async getBlob(filename) {
-
const url = `https://${this.domain}/${this.ownerDid}/${
-
this.repoName
-
}/blob/${this.branch}/${trimLeadingSlash(filename)}`;
console.log(`[KNOT CLIENT]: GET ${url}`);
const res = await fetch(url);
return await res.json();
}
async getRaw(filename) {
-
const url = `https://${this.domain}/${this.ownerDid}/${this.repoName}/raw/${
-
this.branch
-
}/${trimLeadingSlash(filename)}`;
console.log(`[KNOT CLIENT]: GET ${url}`);
const res = await fetch(url, {
responseType: "arraybuffer",
···
}
async getBlob(filename) {
+
const params = new URLSearchParams({
+
repo: `${this.ownerDid}/${this.repoName}`,
+
path: trimLeadingSlash(filename),
+
ref: this.branch,
+
});
+
const url = `https://${this.domain}/xrpc/sh.tangled.repo.blob?${params}`;
console.log(`[KNOT CLIENT]: GET ${url}`);
const res = await fetch(url);
return await res.json();
}
async getRaw(filename) {
+
const params = new URLSearchParams({
+
repo: `${this.ownerDid}/${this.repoName}`,
+
path: trimLeadingSlash(filename),
+
ref: this.branch,
+
raw: "true",
+
});
+
const url = `https://${this.domain}/xrpc/sh.tangled.repo.blob?${params}`;
console.log(`[KNOT CLIENT]: GET ${url}`);
const res = await fetch(url, {
responseType: "arraybuffer",