serve a static website from your pds

Refactor detail page

Changed files
+40 -15
src
lib
routes
~
sites
[name]
+13 -6
src/lib/atproto.ts
··· 6 6 export interface Bundle { 7 7 description?: string; 8 8 assets: Record<string, { $type: "blob"; ref: { $link: string }; mimeType: string; size: number }>; 9 + fallback?: { 10 + path: string; 11 + status?: number; 12 + }; 9 13 createdAt: string; 10 14 } 11 15 ··· 55 59 }); 56 60 57 61 if (isXRPCErrorPayload(data)) throw new Error("couldn't load records"); 58 - return data; 62 + return data as any as Omit<typeof data, "value"> & { value: Bundle }; 59 63 } 60 64 61 - async updateBundle(rkey: string, description: string, files: File[]) { 62 - const bundle: Bundle = { description, assets: {}, createdAt: new Date().toISOString() }; 63 - 65 + async uploadFiles(files: File[]) { 66 + const assets: Bundle["assets"] = {}; 64 67 for (const file of files) { 65 68 if (!(file instanceof File)) continue; 66 69 ··· 68 71 if (isXRPCErrorPayload(data)) throw new Error("couldn't upload file"); 69 72 70 73 const filepath = file.webkitRelativePath?.replace(/^.+\//, "") ?? file.name; 71 - bundle.assets[filepath] = { 74 + assets[filepath] = { 72 75 $type: "blob", 73 76 ref: data.blob.ref, 74 77 mimeType: file.type, ··· 76 79 }; 77 80 } 78 81 82 + return assets; 83 + } 84 + 85 + async updateBundle(rkey: string, bundle: Bundle) { 79 86 const { data } = await this.#client.post("com.atproto.repo.putRecord", { 80 87 input: { 81 88 repo: this.#did, 82 89 collection: "com.jakelazaroff.test", 83 90 rkey, 84 - record: bundle as any, 91 + record: { ...(bundle as any), createdAt: new Date().toISOString() }, 85 92 }, 86 93 }); 87 94 if (isXRPCErrorPayload(data)) throw new Error("couldn't deploy");
+27 -9
src/routes/~/sites/[name]/+page.svelte
··· 7 7 8 8 let { params, data } = $props(); 9 9 10 - const atp = client(data.session); 10 + let rkey = $derived(data.record.uri.split("/").at(-1) ?? ""); 11 + const atp = $derived(client(data.session)); 11 12 12 13 const defaultDescription = "Uploaded from website"; 13 14 ··· 28 29 const form = e.currentTarget; 29 30 const formdata = new FormData(form); 30 31 31 - const rkey = formdata.get("rkey"); 32 - if (typeof rkey !== "string") throw new Error("invalid rkey"); 33 - 34 32 let description = formdata.get("description"); 35 33 if (typeof description !== "string" || !description) description = defaultDescription; 36 34 37 35 const files = formdata.getAll("files").filter(entry => entry instanceof File); 38 - await atp.updateBundle(rkey, description, files); 36 + const assets = await atp.uploadFiles(files); 37 + 38 + await atp.updateBundle(rkey, { ...(data.record.value as any), assets }); 39 39 invalidate(`rkey:${rkey}`); 40 40 form.reset(); 41 + } 42 + 43 + async function updateBundle(e: SubmitEvent & { currentTarget: HTMLFormElement }) { 44 + e.preventDefault(); 45 + const form = e.currentTarget; 46 + const formdata = new FormData(form); 47 + 48 + // todo: implement me 41 49 } 42 50 </script> 43 51 ··· 93 101 <Icon name="toggle" /> 94 102 <span>Settings</span> 95 103 </h3> 96 - <form> 104 + <form onsubmit={updateBundle}> 97 105 <fieldset> 98 106 <legend>Fallback</legend> 99 107 <label> 100 108 <span>path</span> 101 - <input name="fallback_path" /> 109 + <input name="fallback_path" group={data.record.value.fallback?.path} /> 102 110 </label> 103 111 <label> 104 112 <span>200</span> 105 - <input type="radio" name="fallback_status" value="200" /> 113 + <input 114 + type="radio" 115 + name="fallback_status" 116 + value="200" 117 + group={data.record.value.fallback?.status} 118 + /> 106 119 </label> 107 120 <label> 108 121 <span>404</span> 109 - <input type="radio" name="fallback_status" value="404" /> 122 + <input 123 + type="radio" 124 + name="fallback_status" 125 + value="404" 126 + group={data.record.value.fallback?.status} 127 + /> 110 128 </label> 111 129 </fieldset> 112 130 <button>save</button>