+2
-2
scripts/publish-docs.zig
+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
+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
+
}