atproto utils for zig zat.dev
atproto sdk zig

Compare changes

Choose any two refs to compare.

Changed files
+38 -3
scripts
src
internal
+2 -2
scripts/publish-docs.zig
··· 14 14 15 15 /// devlog entries 16 16 const devlog = [_]DocEntry{ 17 - .{ .path = "/001", .file = "devlog/001-self-publishing-docs.md" }, 17 + .{ .path = "/devlog/001", .file = "devlog/001-self-publishing-docs.md" }, 18 18 }; 19 19 20 20 pub fn main() !void { ··· 87 87 // devlog publication (clock_id 100 to separate from docs) 88 88 const devlog_tid = zat.Tid.fromTimestamp(1704067200000000, 100); 89 89 const devlog_pub = Publication{ 90 - .url = "https://zat.dev/devlog", 90 + .url = "https://zat.dev", 91 91 .name = "zat devlog", 92 92 .description = "building zat in public", 93 93 };
+36 -1
src/internal/json.zig
··· 125 125 }, 126 126 }; 127 127 } 128 - return std.json.parseFromValueLeaky(T, allocator, current, .{}) catch |err| { 128 + return std.json.parseFromValueLeaky(T, allocator, current, .{ .ignore_unknown_fields = true }) catch |err| { 129 129 log.debug("extractAt: parse failed for {s} at path {any}: {s} (json type: {s})", .{ 130 130 @typeName(T), 131 131 path, ··· 347 347 const result = extractAtOptional(Thing, arena.allocator(), parsed.value, .{ "data", "missing" }); 348 348 try std.testing.expect(result == null); 349 349 } 350 + 351 + test "extractAt ignores unknown fields" { 352 + // real-world case: TAP messages have extra fields (live, rev, cid) that we don't need 353 + const json_str = 354 + \\{ 355 + \\ "record": { 356 + \\ "live": true, 357 + \\ "did": "did:plc:abc123", 358 + \\ "rev": "3mbspmpaidl2a", 359 + \\ "collection": "pub.leaflet.document", 360 + \\ "rkey": "xyz789", 361 + \\ "action": "create", 362 + \\ "cid": "bafyreitest" 363 + \\ } 364 + \\} 365 + ; 366 + var arena = std.heap.ArenaAllocator.init(std.testing.allocator); 367 + defer arena.deinit(); 368 + 369 + const parsed = try std.json.parseFromSlice(std.json.Value, arena.allocator(), json_str, .{}); 370 + 371 + // only extract the fields we care about 372 + const Record = struct { 373 + collection: []const u8, 374 + action: []const u8, 375 + did: []const u8, 376 + rkey: []const u8, 377 + }; 378 + 379 + const rec = try extractAt(Record, arena.allocator(), parsed.value, .{"record"}); 380 + try std.testing.expectEqualStrings("pub.leaflet.document", rec.collection); 381 + try std.testing.expectEqualStrings("create", rec.action); 382 + try std.testing.expectEqualStrings("did:plc:abc123", rec.did); 383 + try std.testing.expectEqualStrings("xyz789", rec.rkey); 384 + }