A decentralized music tracking and discovery platform built on AT Protocol 🎵
rocksky.app
spotify
atproto
lastfm
musicbrainz
scrobbling
listenbrainz
1import type { Registry, NamedType, TypeRef } from "./registry";
2
3const HEADER = `// AUTO-GENERATED FILE — DO NOT EDIT.
4// Source: apps/api/lexicons/**/*.json
5// Regenerate via: bun run lexgen:types
6
7export interface BlobRef {
8 $type?: "blob";
9 ref?: { $link?: string };
10 mimeType?: string;
11 size?: number;
12}
13
14export type CidLink = string;
15export type DateTime = string;
16export type AtUri = string;
17export type AtIdentifier = string;
18export type Did = string;
19export type Cid = string;
20export type Uri = string;
21`;
22
23function tsType(t: TypeRef): string {
24 switch (t.kind) {
25 case "primitive":
26 switch (t.name) {
27 case "string":
28 return "string";
29 case "integer":
30 return "number";
31 case "boolean":
32 return "boolean";
33 case "bytes":
34 return "Uint8Array";
35 case "blob":
36 return "BlobRef";
37 case "cid-link":
38 return "CidLink";
39 case "cid":
40 return "Cid";
41 case "datetime":
42 return "DateTime";
43 case "at-uri":
44 return "AtUri";
45 case "uri":
46 return "Uri";
47 case "at-identifier":
48 return "AtIdentifier";
49 case "did":
50 return "Did";
51 }
52 case "array":
53 return `${tsType(t.items)}[]`;
54 case "ref":
55 return t.targetId === "unknown" ? "unknown" : t.targetId;
56 case "union":
57 return t.options.length === 0 ? "unknown" : t.options.map((o) => (o === "unknown" ? "unknown" : o)).join(" | ");
58 case "unknown":
59 return "unknown";
60 }
61}
62
63function jsdoc(desc?: string, indent = " "): string {
64 if (!desc) return "";
65 const clean = desc.replace(/\*\//g, "*\\/").trim();
66 return `${indent}/** ${clean} */\n`;
67}
68
69function emitInterface(t: NamedType): string {
70 const head = jsdoc(t.description, "") + `export interface ${t.name} {\n`;
71 const body = t.fields
72 .map((f) => {
73 const doc = jsdoc(f.description, " ");
74 const opt = f.required ? "" : "?";
75 return `${doc} ${f.name}${opt}: ${tsType(f.type)};`;
76 })
77 .join("\n");
78 return head + body + "\n}\n";
79}
80
81export function emitTypescript(reg: Registry): string {
82 const parts = [HEADER, ...reg.types.map(emitInterface)];
83 return parts.join("\n");
84}