From 75d454cc7a87d2da8ddfb730d4d09b56d77e96b2 Mon Sep 17 00:00:00 2001 From: Jay Date: Fri, 24 Oct 2025 13:40:52 -0400 Subject: [PATCH] Converted event/json conversion module. --- src/event.test.ts | 3 --- src/event.ts | 2 ++ src/event_json.test.ts | 56 ++++++++++++++++++++++++++++++++++++++++++ src/event_json.ts | 40 ++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 3 deletions(-) delete mode 100644 src/event.test.ts create mode 100644 src/event_json.test.ts create mode 100644 src/event_json.ts diff --git a/src/event.test.ts b/src/event.test.ts deleted file mode 100644 index 31d1451..0000000 --- a/src/event.test.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { test } from "vitest"; - -test("placeholder", () => {}); diff --git a/src/event.ts b/src/event.ts index a29ba6b..643225a 100644 --- a/src/event.ts +++ b/src/event.ts @@ -1,3 +1,4 @@ +import { EventJSON } from "./event_json"; import { EventID } from "./id"; import { Sign } from "./sign"; import { Validate } from "./validate"; @@ -6,4 +7,5 @@ export const Event = { ...EventID, ...Sign, ...Validate, + ...EventJSON, }; diff --git a/src/event_json.test.ts b/src/event_json.test.ts new file mode 100644 index 0000000..31d609e --- /dev/null +++ b/src/event_json.test.ts @@ -0,0 +1,56 @@ +import { describe, expect, test } from "vitest"; + +import { EventJSON } from "./event_json"; +import type { EventData } from "./types"; +import { testEvent, testEventJSON, testPK } from "./util.test"; +import { Validate } from "./validate"; + +describe("Event JSON", () => { + test("unmarshal event JSON", () => { + const event = EventJSON.fromJSON(JSON.parse(testEventJSON)); + expect(() => Validate.validate(event)).not.toThrow(); + expectEqualEvents(event, testEvent); + }); + + test("marshal event JSON", () => { + const eventJSON = JSON.stringify(EventJSON.toJSON(testEvent)); + expect(eventJSON).toBe(testEventJSON); + }); + + test("event JSON round trip", () => { + const event: EventData = { + id: "86e856d0527dd08527498cd8afd8a7d296bde37e4757a8921f034f0b344df3ad", + pubkey: testPK, + created_at: 1760740551, + kind: 1, + tags: [ + ["a", "value"], + ["b", "value", "optional"], + ["name", "value", "optional", "optional"], + ], + content: "hello world", + sig: "c05fe02a9c082ff56aad2b16b5347498a21665f02f050ba086dbe6bd593c8cd448505d2831d1c0340acc1793eaf89b7c0cb21bb696c71da6b8d6b857702bb557", + }; + + const expectedJSON = `{"id":"86e856d0527dd08527498cd8afd8a7d296bde37e4757a8921f034f0b344df3ad","pubkey":"cfa87f35acbde29ba1ab3ee42de527b2cad33ac487e80cf2d6405ea0042c8fef","created_at":1760740551,"kind":1,"tags":[["a","value"],["b","value","optional"],["name","value","optional","optional"]],"content":"hello world","sig":"c05fe02a9c082ff56aad2b16b5347498a21665f02f050ba086dbe6bd593c8cd448505d2831d1c0340acc1793eaf89b7c0cb21bb696c71da6b8d6b857702bb557"}`; + + expect(() => Validate.validate(event)).not.toThrow(); + + const eventJSON = JSON.stringify(EventJSON.toJSON(event)); + expect(eventJSON).toBe(expectedJSON); + + const unmarshalledEvent = EventJSON.fromJSON(JSON.parse(eventJSON)); + expect(() => Validate.validate(unmarshalledEvent)).not.toThrow(); + expectEqualEvents(unmarshalledEvent, event); + }); +}); + +function expectEqualEvents(got: EventData, want: EventData): void { + expect(got.id).toBe(want.id); + expect(got.pubkey).toBe(want.pubkey); + expect(got.created_at).toBe(want.created_at); + expect(got.kind).toBe(want.kind); + expect(got.content).toBe(want.content); + expect(got.sig).toBe(want.sig); + expect(got.tags).toEqual(want.tags); +} diff --git a/src/event_json.ts b/src/event_json.ts new file mode 100644 index 0000000..76fb281 --- /dev/null +++ b/src/event_json.ts @@ -0,0 +1,40 @@ +import type { EventData } from "./types"; + +/** + * Converts an event to a plain object suitable for JSON.stringify(). + * @param event - Event to convert + * @returns Plain object matching JSON structure + */ +function toJSON(event: EventData): object { + return { + id: event.id, + pubkey: event.pubkey, + created_at: event.created_at, + kind: event.kind, + tags: event.tags, + content: event.content, + sig: event.sig, + }; +} + +/** + * Parses an event from JSON data. + * @param json - Parsed JSON object + * @returns Event instance + */ +function fromJSON(json: any): EventData { + return { + id: json.id || "", + pubkey: json.pubkey || "", + created_at: json.created_at || 0, + kind: json.kind || 0, + tags: json.tags || [], + content: json.content || "", + sig: json.sig || "", + }; +} + +export const EventJSON = { + toJSON, + fromJSON, +};