···22export { formatLabel, labelIsSigned, signLabel } from "./util/labels.js";
33export type {
44 CreateLabelData,
55+ FormattedLabel,
56 ProcedureHandler,
67 QueryHandler,
78 SavedLabel,
89 SignedLabel,
910 SubscriptionHandler,
1111+ UnsignedLabel,
1012} from "./util/types.js";
+19-5
src/util/labels.ts
···11import { encode as cborEncode } from "@atcute/cbor";
22+import type { At } from "@atcute/client/lexicons";
33+import { toString as ui8ToString } from "uint8arrays";
24import { k256Sign } from "./crypto.js";
33-import type { Label, SignedLabel } from "./types.js";
55+import type { FormattedLabel, SignedLabel, UnsignedLabel } from "./types.js";
46import { excludeNullish } from "./util.js";
5768const LABEL_VERSION = 1;
7988-export function formatLabel(label: Label): Label {
1010+function formatLabelCbor(label: UnsignedLabel): UnsignedLabel {
911 return excludeNullish({ ...label, ver: LABEL_VERSION, neg: !!label.neg });
1012}
11131212-export function signLabel(label: Label, signingKey: Uint8Array): SignedLabel {
1313- const toSign = formatLabel(label);
1414+export function formatLabel(
1515+ label: UnsignedLabel & { sig?: Uint8Array | At.Bytes },
1616+): FormattedLabel {
1717+ const sig = label.sig instanceof Uint8Array
1818+ ? { $bytes: ui8ToString(label.sig, "base64") }
1919+ : label.sig;
2020+ if (sig && !("$bytes" in sig)) {
2121+ throw new Error("Expected sig to be an object with base64 $bytes, got " + sig);
2222+ }
2323+ return excludeNullish({ ...label, ver: LABEL_VERSION, neg: !!label.neg, sig });
2424+}
2525+2626+export function signLabel(label: UnsignedLabel, signingKey: Uint8Array): SignedLabel {
2727+ const toSign = formatLabelCbor(label);
1428 const bytes = cborEncode(toSign);
1529 const sig = k256Sign(signingKey, bytes);
1630 return { ...toSign, sig };
1731}
18321919-export function labelIsSigned<T extends Label>(label: T): label is T & { sig: Uint8Array } {
3333+export function labelIsSigned<T extends UnsignedLabel>(label: T): label is T & SignedLabel {
2034 return "sig" in label && label.sig !== undefined;
2135}
+4-3
src/util/types.ts
···11-import type { ComAtprotoLabelDefs } from "@atcute/client/lexicons";
11+import { At, ComAtprotoLabelDefs } from "@atcute/client/lexicons";
22import type { WebsocketHandler } from "@fastify/websocket";
33import type {
44 RawReplyDefaultExpression,
···3636 /** The expiration date of the label, if any. Must be in ISO 8601 format. */
3737 exp?: string | undefined;
3838}
3939-export type Label = Omit<ComAtprotoLabelDefs.Label, "sig"> & { sig?: Uint8Array };
4040-export type SignedLabel = Label & { sig: Uint8Array };
3939+export type UnsignedLabel = Omit<ComAtprotoLabelDefs.Label, "sig">;
4040+export type SignedLabel = UnsignedLabel & { sig: Uint8Array };
4141+export type FormattedLabel = UnsignedLabel & { sig?: At.Bytes };
4142export type SavedLabel = SignedLabel & { id: number };
42434344export type QueryHandler<