A CLI for publishing standard.site documents to ATProto sequoia.pub
standard site lexicon cli publishing

chore: applied formatting

+80 -28
+15 -8
docs/src/index.ts
··· 12 13 const app = new Hono<{ Bindings: Bindings }>(); 14 15 app.route("/oauth", auth); 16 app.route("/subscribe", subscribe); 17 - app.use("/subscribe", cors({ 18 - origin: (origin) => origin, 19 - credentials: true, 20 - })); 21 - app.use("/subscribe/*", cors({ 22 - origin: (origin) => origin, 23 - credentials: true, 24 - })); 25 26 app.get("/api/health", (c) => { 27 return c.json({ status: "ok" });
··· 12 13 const app = new Hono<{ Bindings: Bindings }>(); 14 15 + app.use( 16 + "/subscribe", 17 + cors({ 18 + origin: (origin) => origin, 19 + credentials: true, 20 + }), 21 + ); 22 + app.use( 23 + "/subscribe/*", 24 + cors({ 25 + origin: (origin) => origin, 26 + credentials: true, 27 + }), 28 + ); 29 + 30 app.route("/oauth", auth); 31 app.route("/subscribe", subscribe); 32 33 app.get("/api/health", (c) => { 34 return c.json({ status: "ok" });
+1 -4
docs/src/lib/path-redirect.ts
··· 19 const OriginalRequest = globalThis.Request; 20 21 globalThis.Request = class extends OriginalRequest { 22 - constructor( 23 - input: RequestInfo | URL, 24 - init?: RequestInit, 25 - ) { 26 super(input, sanitizeInit(init)); 27 if (init?.redirect === "error") { 28 errorRedirectRequests.add(this);
··· 19 const OriginalRequest = globalThis.Request; 20 21 globalThis.Request = class extends OriginalRequest { 22 + constructor(input: RequestInfo | URL, init?: RequestInit) { 23 super(input, sanitizeInit(init)); 24 if (init?.redirect === "error") { 25 errorRedirectRequests.add(this);
+64 -16
docs/src/routes/subscribe.ts
··· 12 // Cache the vocs-generated stylesheet href across requests (changes on rebuild). 13 let _vocsStyleHref: string | null = null; 14 15 - async function getVocsStyleHref(assets: Fetcher, baseUrl: string): Promise<string> { 16 if (_vocsStyleHref) return _vocsStyleHref; 17 try { 18 const indexUrl = new URL("/", baseUrl).toString(); ··· 105 const session = await client.restore(did); 106 const agent = new Agent(session); 107 108 - const existingUri = await findExistingSubscription(agent, did, publicationUri); 109 if (existingUri) { 110 - return c.json({ subscribed: true, existing: true, recordUri: existingUri }); 111 } 112 113 const result = await agent.com.atproto.repo.createRecord({ ··· 119 }, 120 }); 121 122 - return c.json({ subscribed: true, existing: false, recordUri: result.data.uri }); 123 } catch (error) { 124 console.error("Subscribe POST error:", error); 125 // Treat expired/missing session as unauthenticated ··· 141 const styleHref = await getVocsStyleHref(c.env.ASSETS, c.req.url); 142 143 if (!publicationUri || !publicationUri.startsWith("at://")) { 144 - return c.html(renderError("Missing or invalid publication URI.", styleHref), 400); 145 } 146 147 const did = getSessionDid(c); ··· 154 const session = await client.restore(did); 155 const agent = new Agent(session); 156 157 - const existingUri = await findExistingSubscription(agent, did, publicationUri); 158 if (existingUri) { 159 - return c.html(renderSuccess(publicationUri, existingUri, true, styleHref)); 160 } 161 162 const result = await agent.com.atproto.repo.createRecord({ ··· 168 }, 169 }); 170 171 - return c.html(renderSuccess(publicationUri, result.data.uri, false, styleHref)); 172 } catch (error) { 173 console.error("Subscribe GET error:", error); 174 // Session expired - ask the user to sign in again 175 - return c.html(renderHandleForm(publicationUri, styleHref, "Session expired. Please sign in again.")); 176 } 177 }); 178 ··· 190 191 if (!handle || !publicationUri) { 192 const styleHref = await getVocsStyleHref(c.env.ASSETS, c.req.url); 193 - return c.html(renderError("Missing handle or publication URI.", styleHref), 400); 194 } 195 196 const returnTo = `${c.env.CLIENT_URL}/subscribe?publicationUri=${encodeURIComponent(publicationUri)}`; ··· 205 // HTML rendering 206 // ============================================================================ 207 208 - function renderHandleForm(publicationUri: string, styleHref: string, error?: string): string { 209 const errorHtml = error 210 ? `<p class="vocs_Paragraph error">${escapeHtml(error)}</p>` 211 : ""; 212 213 - return page(` 214 <h1 class="vocs_H1 vocs_Heading">Subscribe on Bluesky</h1> 215 <p class="vocs_Paragraph">Enter your Bluesky handle to subscribe to this publication.</p> 216 ${errorHtml} ··· 226 /> 227 <button type="submit" class="vocs_Button_button vocs_Button_button_accent">Continue on Bluesky</button> 228 </form> 229 - `, styleHref); 230 } 231 232 function renderSuccess( ··· 240 : "You've successfully subscribed!"; 241 const escapedPublicationUri = escapeHtml(publicationUri); 242 const escapedRecordUri = escapeHtml(recordUri); 243 - return page(` 244 <h1 class="vocs_H1 vocs_Heading">Subscribed ✓</h1> 245 <p class="vocs_Paragraph">${msg}</p> 246 <p class="vocs_Paragraph"><small>Publication: <code class="vocs_Code"><a href="https://pds.ls/${escapedPublicationUri}">${escapedPublicationUri}</a></code></small></p> 247 <p class="vocs_Paragraph"><small>Record: <code class="vocs_Code"><a href="https://pds.ls/${escapedRecordUri}">${escapedRecordUri}</a></code></small></p> 248 - `, styleHref); 249 } 250 251 function renderError(message: string, styleHref: string): string { 252 - return page(`<h1 class="vocs_H1 vocs_Heading">Error</h1><p class="vocs_Paragraph error">${escapeHtml(message)}</p>`, styleHref); 253 } 254 255 function page(body: string, styleHref: string): string {
··· 12 // Cache the vocs-generated stylesheet href across requests (changes on rebuild). 13 let _vocsStyleHref: string | null = null; 14 15 + async function getVocsStyleHref( 16 + assets: Fetcher, 17 + baseUrl: string, 18 + ): Promise<string> { 19 if (_vocsStyleHref) return _vocsStyleHref; 20 try { 21 const indexUrl = new URL("/", baseUrl).toString(); ··· 108 const session = await client.restore(did); 109 const agent = new Agent(session); 110 111 + const existingUri = await findExistingSubscription( 112 + agent, 113 + did, 114 + publicationUri, 115 + ); 116 if (existingUri) { 117 + return c.json({ 118 + subscribed: true, 119 + existing: true, 120 + recordUri: existingUri, 121 + }); 122 } 123 124 const result = await agent.com.atproto.repo.createRecord({ ··· 130 }, 131 }); 132 133 + return c.json({ 134 + subscribed: true, 135 + existing: false, 136 + recordUri: result.data.uri, 137 + }); 138 } catch (error) { 139 console.error("Subscribe POST error:", error); 140 // Treat expired/missing session as unauthenticated ··· 156 const styleHref = await getVocsStyleHref(c.env.ASSETS, c.req.url); 157 158 if (!publicationUri || !publicationUri.startsWith("at://")) { 159 + return c.html( 160 + renderError("Missing or invalid publication URI.", styleHref), 161 + 400, 162 + ); 163 } 164 165 const did = getSessionDid(c); ··· 172 const session = await client.restore(did); 173 const agent = new Agent(session); 174 175 + const existingUri = await findExistingSubscription( 176 + agent, 177 + did, 178 + publicationUri, 179 + ); 180 if (existingUri) { 181 + return c.html( 182 + renderSuccess(publicationUri, existingUri, true, styleHref), 183 + ); 184 } 185 186 const result = await agent.com.atproto.repo.createRecord({ ··· 192 }, 193 }); 194 195 + return c.html( 196 + renderSuccess(publicationUri, result.data.uri, false, styleHref), 197 + ); 198 } catch (error) { 199 console.error("Subscribe GET error:", error); 200 // Session expired - ask the user to sign in again 201 + return c.html( 202 + renderHandleForm( 203 + publicationUri, 204 + styleHref, 205 + "Session expired. Please sign in again.", 206 + ), 207 + ); 208 } 209 }); 210 ··· 222 223 if (!handle || !publicationUri) { 224 const styleHref = await getVocsStyleHref(c.env.ASSETS, c.req.url); 225 + return c.html( 226 + renderError("Missing handle or publication URI.", styleHref), 227 + 400, 228 + ); 229 } 230 231 const returnTo = `${c.env.CLIENT_URL}/subscribe?publicationUri=${encodeURIComponent(publicationUri)}`; ··· 240 // HTML rendering 241 // ============================================================================ 242 243 + function renderHandleForm( 244 + publicationUri: string, 245 + styleHref: string, 246 + error?: string, 247 + ): string { 248 const errorHtml = error 249 ? `<p class="vocs_Paragraph error">${escapeHtml(error)}</p>` 250 : ""; 251 252 + return page( 253 + ` 254 <h1 class="vocs_H1 vocs_Heading">Subscribe on Bluesky</h1> 255 <p class="vocs_Paragraph">Enter your Bluesky handle to subscribe to this publication.</p> 256 ${errorHtml} ··· 266 /> 267 <button type="submit" class="vocs_Button_button vocs_Button_button_accent">Continue on Bluesky</button> 268 </form> 269 + `, 270 + styleHref, 271 + ); 272 } 273 274 function renderSuccess( ··· 282 : "You've successfully subscribed!"; 283 const escapedPublicationUri = escapeHtml(publicationUri); 284 const escapedRecordUri = escapeHtml(recordUri); 285 + return page( 286 + ` 287 <h1 class="vocs_H1 vocs_Heading">Subscribed ✓</h1> 288 <p class="vocs_Paragraph">${msg}</p> 289 <p class="vocs_Paragraph"><small>Publication: <code class="vocs_Code"><a href="https://pds.ls/${escapedPublicationUri}">${escapedPublicationUri}</a></code></small></p> 290 <p class="vocs_Paragraph"><small>Record: <code class="vocs_Code"><a href="https://pds.ls/${escapedRecordUri}">${escapedRecordUri}</a></code></small></p> 291 + `, 292 + styleHref, 293 + ); 294 } 295 296 function renderError(message: string, styleHref: string): string { 297 + return page( 298 + `<h1 class="vocs_H1 vocs_Heading">Error</h1><p class="vocs_Paragraph error">${escapeHtml(message)}</p>`, 299 + styleHref, 300 + ); 301 } 302 303 function page(body: string, styleHref: string): string {