serve a static website from your pds
1import { isXRPCErrorPayload, type Client } from "@atcute/client";
2import type {} from "@atcute/atproto";
3import type {} from "@atcute/bluesky";
4import type { Did } from "@atcute/lexicons";
5
6export interface Bundle {
7 /** The timestamp at which the latest version of the bundle was created. */
8 createdAt: string;
9
10 /** Human-readable summary of the deploy; notes, commit message, etc. */
11 description?: string;
12
13 /** A map of asset paths to blob references. */
14 assets: { $type: "blob"; ref: { $link: string }; mimeType: string; size: number };
15}
16
17export default class ATProto {
18 #did: Did;
19 #client: Client;
20
21 constructor(did: Did, client: Client) {
22 this.#did = did;
23 this.#client = client;
24 }
25
26 async getProfile(did: Did) {
27 const { data } = await this.#client.get("app.bsky.actor.getProfile", {
28 params: { actor: did },
29 });
30
31 if (isXRPCErrorPayload(data)) throw new Error(data.error);
32 return data;
33 }
34
35 async listBundles() {
36 const { data } = await this.#client.get("com.atproto.repo.listRecords", {
37 params: { repo: this.#did, collection: "com.jakelazaroff.athost" },
38 });
39
40 if (isXRPCErrorPayload(data)) throw new Error("couldn't load records");
41 return data;
42 }
43
44 async createBundle(rkey: string) {
45 const record = {
46 assets: {},
47 createdAt: new Date().toISOString(),
48 };
49
50 const { data } = await this.#client.post("com.atproto.repo.createRecord", {
51 input: { repo: this.#did, collection: "com.jakelazaroff.athost", rkey, record },
52 });
53
54 if (isXRPCErrorPayload(data)) throw new Error(data.error);
55 }
56
57 async getBundle(rkey: string) {
58 const { data } = await this.#client.get("com.atproto.repo.getRecord", {
59 params: { repo: this.#did, collection: "com.jakelazaroff.athost", rkey },
60 });
61
62 if (isXRPCErrorPayload(data)) throw new Error("couldn't load records");
63 return data as any as Omit<typeof data, "value"> & { value: Bundle };
64 }
65
66 async uploadFile(file: File) {
67 const { data } = await this.#client.post("com.atproto.repo.uploadBlob", { input: file });
68 if (isXRPCErrorPayload(data)) throw new Error(`couldn't upload ${file.name}`);
69
70 return data.blob;
71 }
72
73 async updateBundle(rkey: string, bundle: Bundle) {
74 const { data } = await this.#client.post("com.atproto.repo.putRecord", {
75 input: {
76 repo: this.#did,
77 collection: "com.jakelazaroff.athost",
78 rkey,
79 record: { ...(bundle as any), createdAt: new Date().toISOString() },
80 },
81 });
82
83 if (isXRPCErrorPayload(data)) throw new Error("couldn't deploy");
84 }
85
86 async deleteBundle(rkey: string) {
87 const { data } = await this.#client.post("com.atproto.repo.deleteRecord", {
88 input: { repo: this.#did, collection: "com.jakelazaroff.athost", rkey },
89 });
90
91 if (isXRPCErrorPayload(data)) throw new Error(data.error);
92 }
93}