//! the public endpoint surface, declared once. //! //! every rendering of "what can you call here" — the ascii river, the html //! river, and /api/endpoints.json (which the static site templates from) — //! is generated from this table at comptime. the list drifted twice on //! 08-12 when it lived in four hand-maintained copies; it must not live //! anywhere else again. llms.txt is prose and stays hand-written, but the //! status contract asserts it mentions every path declared here. const std = @import("std"); pub const Group = enum { live, archive, ops }; pub const Endpoint = struct { method: []const u8, path: []const u8, desc: []const u8, group: Group, }; pub const table = [_]Endpoint{ .{ .method = "GET", .path = "/subscribe", .desc = "jetstream-compatible json firehose", .group = .live }, .{ .method = "GET", .path = "/xrpc/network.bsky.jetstream.subscribeEvents", .desc = "proposal-0015 lexicon frames: seq cursors, records, sync events", .group = .live }, .{ .method = "GET", .path = "/xrpc/network.bsky.jetstream.getZstdDictionary", .desc = "current v2 compression dictionary", .group = .live }, .{ .method = "GET", .path = "/xrpc/network.bsky.jetstream.listSegments", .desc = "browse the sealed archive", .group = .archive }, .{ .method = "GET", .path = "/xrpc/network.bsky.jetstream.getSegment", .desc = "download a sealed segment", .group = .archive }, .{ .method = "GET", .path = "/xrpc/network.bsky.jetstream.getBlock", .desc = "read one compressed block", .group = .archive }, .{ .method = "POST", .path = "/xrpc/network.bsky.jetstream.planSnapshot", .desc = "plan an archive range download", .group = .archive }, .{ .method = "GET", .path = "/status", .desc = "field report: live counters, config, provenance", .group = .ops }, .{ .method = "GET", .path = "/api/endpoints.json", .desc = "this endpoint list, as json", .group = .ops }, }; /// the display leaf: the NSID method name for xrpc paths, the whole path /// otherwise. the site bolds this part. fn leafIndex(comptime path: []const u8) usize { if (!std.mem.startsWith(u8, path, "/xrpc/")) return 0; return (std.mem.lastIndexOfScalar(u8, path, '.') orelse return 0) + 1; } fn pad(comptime s: []const u8, comptime width: usize) []const u8 { var out: []const u8 = s; while (out.len < width) out = out ++ " "; return out; } /// the ascii river's listing. xrpc NSIDs are self-describing, so only /// short non-xrpc paths carry an inline description (line-width budget). pub const text_block = blk: { var s: []const u8 = ""; var group: ?Group = null; for (table) |e| { if (group == null or group.? != e.group) { if (group != null) s = s ++ "\n"; s = s ++ " " ++ @tagName(e.group) ++ "\n"; group = e.group; } if (std.mem.startsWith(u8, e.path, "/xrpc/")) { s = s ++ " " ++ pad(e.method, 6) ++ e.path ++ "\n"; } else { s = s ++ " " ++ pad(e.method, 6) ++ pad(e.path, 21) ++ e.desc ++ "\n"; } } break :blk s; }; /// the html river's route rows (live + archive; ops render as nav links). pub const html_routes = blk: { var s: []const u8 = ""; for (table) |e| { if (e.group == .ops) continue; s = s ++ "
" ++ e.method ++ "" ++ e.path ++ "" ++ e.desc ++ "
\n"; } break :blk s; }; pub const json_path = "/api/endpoints.json"; /// the machine-readable surface the static site templates from. /// `name` is the bold display leaf, `prefix` everything before it. pub const json = blk: { var s: []const u8 = "{\"endpoints\":["; for (table, 0..) |e, i| { for (e.method ++ e.path ++ e.desc) |c| { if (c == '"' or c == '\\') @compileError("endpoint fields must not need json escaping"); } const leaf = leafIndex(e.path); if (i > 0) s = s ++ ","; s = s ++ "{\"method\":\"" ++ e.method ++ "\",\"path\":\"" ++ e.path ++ "\",\"prefix\":\"" ++ e.path[0..leaf] ++ "\",\"name\":\"" ++ e.path[leaf..] ++ "\",\"group\":\"" ++ @tagName(e.group) ++ "\",\"desc\":\"" ++ e.desc ++ "\"}"; } break :blk s ++ "]}\n"; }; // === tests === const testing = std.testing; test "every declared path appears in every generated view" { for (table) |e| { try testing.expect(std.mem.indexOf(u8, text_block, e.path) != null); try testing.expect(std.mem.indexOf(u8, json, e.path) != null); if (e.group != .ops) try testing.expect(std.mem.indexOf(u8, html_routes, e.path) != null); } } test "json parses and splits the display leaf correctly" { var arena = std.heap.ArenaAllocator.init(testing.allocator); defer arena.deinit(); const parsed = try std.json.parseFromSliceLeaky(std.json.Value, arena.allocator(), json, .{}); const eps = parsed.object.get("endpoints").?.array; try testing.expectEqual(table.len, eps.items.len); for (eps.items) |item| { const o = item.object; const prefix = o.get("prefix").?.string; const name = o.get("name").?.string; const path = o.get("path").?.string; // prefix ++ name reassembles the path, so the site can bold the leaf try testing.expect(std.mem.startsWith(u8, path, prefix)); try testing.expectEqualStrings(path[prefix.len..], name); } // the leaf of an NSID is the method name, not a file extension try testing.expect(std.mem.indexOf(u8, json, "\"name\":\"subscribeEvents\"") != null); try testing.expect(std.mem.indexOf(u8, json, "\"name\":\"/api/endpoints.json\"") != null); } test "retired surfaces stay retired" { for ([_][]const u8{ "subscribe-v2", "planBackfill" }) |gone| { try testing.expect(std.mem.indexOf(u8, json, gone) == null); try testing.expect(std.mem.indexOf(u8, text_block, gone) == null); } }