web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

commit 8262fb08ca3dbe172633e9e67f3cfbbc43941ed1
parent 23a87521e2c97476c01d203854eb5b7ce4a533df
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Fri,  8 Aug 2025 23:25:06 +0000

utils-nostr: add `reaction` nip-25 schemas, types, event parsing utils

Diffstat:
Mutils-nostr/src/events/comment/lib.ts | 4++--
Autils-nostr/src/events/reaction/lib.ts | 19+++++++++++++++++++
Autils-nostr/src/events/reaction/parse.ts | 15+++++++++++++++
Mutils-nostr/src/events/subscription.ts | 14+++++++++++---
Mutils-nostr/src/schemas/lib.ts | 8++++++--
Mutils-nostr/src/types/lib.ts | 3++-
Mutils-nostr/src/utils/tags.ts | 15++++++++++++++-
7 files changed, 69 insertions(+), 9 deletions(-)

diff --git a/utils-nostr/src/events/comment/lib.ts b/utils-nostr/src/events/comment/lib.ts @@ -1,6 +1,6 @@ import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; -import { NostrEventComment } from "../../types/lib"; -import { NDKEventFigure } from "../../types/ndk"; +import { NostrEventComment } from "../../types/lib.js"; +import { NDKEventFigure } from "../../types/ndk.js"; import { tags_comment } from "../../utils/tags.js"; import { ndk_event } from "../lib.js"; diff --git a/utils-nostr/src/events/reaction/lib.ts b/utils-nostr/src/events/reaction/lib.ts @@ -0,0 +1,18 @@ +import { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk"; +import { NostrEventReaction } from "../../types/lib.js"; +import { NDKEventFigure } from "../../types/ndk.js"; +import { tags_reaction } from "../../utils/tags.js"; +import { ndk_event } from "../lib.js"; + +export const ndk_event_reaction = async (opts: NDKEventFigure<{ data: NostrEventReaction; }>): Promise<NDKEvent | undefined> => { + const { ndk, ndk_user, data } = opts; + return await ndk_event({ + ndk, + ndk_user, + basis: { + kind: NDKKind.Reaction, + content: data.content, + tags: tags_reaction(data) + }, + }); +}; +\ No newline at end of file diff --git a/utils-nostr/src/events/reaction/parse.ts b/utils-nostr/src/events/reaction/parse.ts @@ -0,0 +1,15 @@ +import { NDKEvent } from "@nostr-dev-kit/ndk"; +import { nostr_event_reaction_schema } from "../../schemas/lib.js"; +import { NostrEventReaction } from "../../types/lib.js"; + +export const parse_nostr_reaction_event = (event: NDKEvent): NostrEventReaction | undefined => { + if (!event || typeof event.content !== 'string' || event.kind !== 7) return undefined; + + try { + const parsed = JSON.parse(event.content); + const result = nostr_event_reaction_schema.parse(parsed); + return result; + } catch { + return undefined; + } +}; diff --git a/utils-nostr/src/events/subscription.ts b/utils-nostr/src/events/subscription.ts @@ -1,13 +1,15 @@ import { NDKEvent } from "@nostr-dev-kit/ndk"; -import { NostrEventComment, NostrEventListing, type NostrEventMetadata } from "../types/lib.js"; +import { NostrEventComment, NostrEventListing, NostrEventReaction, type NostrEventMetadata } from "../types/lib.js"; import { parse_nostr_comment_event } from "./comment/parse.js"; import { parse_nostr_listing_event } from "./listing/parse.js"; import { parse_nostr_metadata_event } from "./metadata/parse.js"; +import { parse_nostr_reaction_event } from "./reaction/parse.js"; export type NdkEventPayload = | { kind: 0; metadata: NostrEventMetadata; } | { kind: 30402; listing: NostrEventListing; } - | { kind: 1111; listing: NostrEventComment; } + | { kind: 1111; comment: NostrEventComment; } + | { kind: 7; reaction: NostrEventReaction; } export const on_ndk_event = (event: NDKEvent): NdkEventPayload | undefined => { if (!event || typeof event.kind !== 'number') return undefined; @@ -26,8 +28,14 @@ export const on_ndk_event = (event: NDKEvent): NdkEventPayload | undefined => { case 1111: { const data = parse_nostr_comment_event(event); if (!data) return; - return { kind: event.kind, listing: data }; + return { kind: event.kind, comment: data }; + }; + case 7: { + const data = parse_nostr_reaction_event(event); + if (!data) return; + return { kind: event.kind, reaction: data }; }; + default: return undefined; } }; diff --git a/utils-nostr/src/schemas/lib.ts b/utils-nostr/src/schemas/lib.ts @@ -122,4 +122,9 @@ export const nostr_event_comment_schema = z.object({ root_event: nostr_event_referenced_schema, ref_event: nostr_event_referenced_schema.optional(), content: z.string().min(1), -}); -\ No newline at end of file +}); + +export const nostr_event_reaction_schema = z.object({ + ref_event: nostr_event_referenced_schema, + content: z.string().min(1), +}); diff --git a/utils-nostr/src/types/lib.ts b/utils-nostr/src/types/lib.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { nostr_event_comment_schema, nostr_event_listing_schema, nostr_event_metadata_schema, nostr_event_referenced_schema, nostr_tag_client_schema, nostr_tag_discount_schema, nostr_tag_image_schema, nostr_tag_listing_schema, nostr_tag_location_schema, nostr_tag_price_schema, nostr_tag_quantity_schema } from "../schemas/lib.js"; +import { nostr_event_comment_schema, nostr_event_listing_schema, nostr_event_metadata_schema, nostr_event_reaction_schema, nostr_event_referenced_schema, nostr_tag_client_schema, nostr_tag_discount_schema, nostr_tag_image_schema, nostr_tag_listing_schema, nostr_tag_location_schema, nostr_tag_price_schema, nostr_tag_quantity_schema } from "../schemas/lib.js"; export type NostrEventMetadata = z.infer<typeof nostr_event_metadata_schema>; export type NostrEventListing = z.infer<typeof nostr_event_listing_schema> @@ -12,6 +12,7 @@ export type NostrTagQuantity = z.infer<typeof nostr_tag_quantity_schema> export type NostrTagListing = z.infer<typeof nostr_tag_listing_schema> export type NostrEventComment = z.infer<typeof nostr_event_comment_schema> export type NostrEventReferenced = z.infer<typeof nostr_event_referenced_schema> +export type NostrEventReaction = z.infer<typeof nostr_event_reaction_schema> export type NostrEventTag = string[]; export type NostrEventTags = NostrEventTag[]; diff --git a/utils-nostr/src/utils/tags.ts b/utils-nostr/src/utils/tags.ts @@ -1,5 +1,5 @@ import ngeotags, { type InputData as NostrGeotagsInputData } from "nostr-geotags"; -import { NostrEventComment, NostrEventListing, NostrEventTag, NostrEventTagClient, NostrEventTagImage, NostrEventTagLocation, NostrEventTagPrice, NostrEventTagPriceDiscount, NostrEventTagQuantity, NostrEventTags } from "../types/lib.js"; +import { NostrEventComment, NostrEventListing, NostrEventReaction, NostrEventTag, NostrEventTagClient, NostrEventTagImage, NostrEventTagLocation, NostrEventTagPrice, NostrEventTagPriceDiscount, NostrEventTagQuantity, NostrEventTags } from "../types/lib.js"; export const tag_client = (opts: NostrEventTagClient, d_tag?: string): NostrEventTag => { const tag = [`client`, opts.name]; @@ -107,4 +107,17 @@ export const tags_comment = (opts: NostrEventComment): NostrEventTags => { ]; return tags; +}; + +export const tags_reaction = (opts: NostrEventReaction): NostrEventTags => { + const { ref_event } = opts; + const ref_kind = ref_event.kind.toString(); + const ref_author = ref_event.author; + const tags: NostrEventTags = [ + [`e`, ref_event.id, ...ref_event.relays || ``], + [`p`, ref_author], + [`k`, ref_kind], + ]; + if (ref_event.d_tag) tags.push([`a`, `${ref_kind}:${ref_author}:${ref_event.d_tag}`, ...ref_event.relays || ``]) + return tags; }; \ No newline at end of file