this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Abstract out label utility functions

futurGH d65ce416 ff12d41f

+55 -27
+16 -27
src/LabelerServer.ts
··· 1 - import { encode as cborEncode } from "@atcute/cbor"; 2 1 import type { ComAtprotoLabelDefs } from "@atproto/api"; 3 2 import { Keypair, Secp256k1Keypair } from "@atproto/crypto"; 4 3 import { ErrorFrame, InvalidRequestError, MessageFrame, XRPCError } from "@atproto/xrpc-server"; ··· 8 7 import { Server } from "node:http"; 9 8 import { fromString as ui8FromString } from "uint8arrays"; 10 9 import type { WebSocket } from "ws"; 11 - import { SignedLabel, StrictPartial } from "./util.js"; 12 - 13 - const LABEL_VERSION = 1; 10 + import { formatLabel, labelIsSigned, signLabel } from "./util/labels.js"; 11 + import { SignedLabel } from "./util/types.js"; 14 12 15 13 export interface LabelerOptions { 16 14 did: string; ··· 64 62 if (this.server?.listening) this.server?.close(callback); 65 63 } 66 64 67 - async signLabel(label: ComAtprotoLabelDefs.Label): Promise<SignedLabel> { 68 - const toSign = this.formatLabel(label); 69 - const bytes = cborEncode(toSign); 70 - const sig = await this.signingKey.sign(bytes); 71 - return { ...toSign, sig }; 72 - } 73 - 74 - private formatLabel<T extends ComAtprotoLabelDefs.Label>(label: T): StrictPartial<T> { 75 - const { src, uri, cid, val, neg, cts, exp } = label; 76 - return { 77 - ver: LABEL_VERSION, 78 - src, 79 - uri, 80 - ...(cid ? { cid } : {}), 81 - val, 82 - ...(neg ? { neg } : {}), 83 - cts, 84 - ...(exp ? { exp } : {}), 85 - } as never; 65 + async createLabel(label: ComAtprotoLabelDefs.Label): Promise<SignedLabel> { 66 + const signed = labelIsSigned(label) ? label : await signLabel(label, this.signingKey); 67 + const stmt = this.db.prepare(` 68 + INSERT INTO labels (src, uri, cid, val, neg, cts, exp, sig) 69 + VALUES (?, ?, ?, ?, ?, ?, ?, ?) 70 + `); 71 + const { src, uri, cid, val, neg, cts, exp, sig } = signed; 72 + stmt.run(src, uri, cid, val, neg, cts, exp, sig); 73 + return signed; 86 74 } 87 75 88 76 private async ensureSignedLabel(label: ComAtprotoLabelDefs.Label): Promise<SignedLabel> { 89 - if (!label.sig) { 90 - const signed = await this.signLabel(label); 77 + if (!labelIsSigned(label)) { 78 + const signed = await signLabel(label, this.signingKey); 91 79 const stmt = this.db.prepare(` 92 80 UPDATE labels 93 81 SET sig = ? ··· 96 84 if (!stmt.changes) throw new Error("Failed to update label with signature"); 97 85 return signed; 98 86 } 99 - return this.formatLabel(label) as ComAtprotoLabelDefs.Label & { sig: Uint8Array }; 87 + return formatLabel(label); 100 88 } 101 89 102 90 queryLabelsHandler: express.RequestHandler = async (req, res) => { ··· 158 146 } 159 147 }; 160 148 161 - subscribeLabelsHandler: WebsocketRequestHandler = (ws, req) => { 149 + subscribeLabelsHandler: WebsocketRequestHandler = async (ws, req) => { 162 150 const cursor = parseInt(req.params.cursor); 163 151 164 152 if (cursor && !Number.isNaN(cursor)) { ··· 181 169 `); 182 170 183 171 for (const row of stmt.iterate(cursor)) { 172 + await this.ensureSignedLabel(row); 184 173 const { id: seq, ...label } = row; 185 174 const frame = new MessageFrame({ seq, labels: [label] }, { type: "#labels" }); 186 175 ws.send(frame.toBytes());
src/util.ts src/util/types.ts
+39
src/util/labels.ts
··· 1 + import type { ComAtprotoLabelDefs } from "@atproto/api"; 2 + import type { SignedLabel, StrictPartial } from "./types.js"; 3 + import { encode as cborEncode } from "@atcute/cbor"; 4 + import type { Keypair } from "@atproto/crypto"; 5 + 6 + const LABEL_VERSION = 1; 7 + 8 + export function formatLabel<T extends ComAtprotoLabelDefs.Label>(label: T): StrictPartial<T> { 9 + const { src, uri, cid, val, neg, cts, exp } = label; 10 + return { 11 + ver: LABEL_VERSION, 12 + src, 13 + uri, 14 + ...(cid ? { cid } : {}), 15 + val, 16 + ...(!!neg ? { neg } : {}), 17 + cts, 18 + ...(exp ? { exp } : {}), 19 + } as never; 20 + } 21 + 22 + export async function signLabel(label: ComAtprotoLabelDefs.Label, signingKey: Keypair): Promise<SignedLabel> { 23 + const toSign = formatLabel(label); 24 + const bytes = cborEncode(toSign); 25 + const sig = await signingKey.sign(bytes); 26 + return { ...toSign, sig }; 27 + } 28 + 29 + export function labelIsSigned<T extends ComAtprotoLabelDefs.Label>( 30 + label: T, 31 + ): label is T & { sig: Uint8Array } { 32 + return label.sig !== undefined; 33 + } 34 + 35 + export function assertLabelIsSigned<T extends ComAtprotoLabelDefs.Label>( 36 + label: T, 37 + ): asserts label is T & { sig: Uint8Array } { 38 + if (!label.sig) throw new Error("Label is not signed"); 39 + }