web_lib

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

commit c592084edfc46f3ed3441081fa920856d5b0e191
parent 4001dfc948a57aa6b5acb900013506ea805364bc
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Fri, 23 May 2025 02:45:31 +0000

utils-nostr: add nip-22 comments events, refactor tags utils, refactor ndk utils. add/edit types

Diffstat:
Mutils-nostr/src/lib/ndk.ts | 85++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Mutils-nostr/src/lib/tags.ts | 40++++++++++++++++++++++++++++++++++++++--
Mutils-nostr/src/lib/types.ts | 21+++++++++++++--------
Mutils-nostr/src/services/events/lib.ts | 34+++++++++++++++++-----------------
Mutils-nostr/src/services/events/types.ts | 2+-
Mutils-nostr/src/types.ts | 11+++++++++++
6 files changed, 138 insertions(+), 55 deletions(-)

diff --git a/utils-nostr/src/lib/ndk.ts b/utils-nostr/src/lib/ndk.ts @@ -1,17 +1,30 @@ -import { INostrClassified, INostrFollow, INostrJobRequest, INostrReaction, NostrEventTags, tags_classified, tags_follow_list, tags_job_request, tags_reaction, time_now_ms, type INostrMetadata } from '$root'; -import NDK, { NDKEvent, NDKKind, NDKPrivateKeySigner, NDKUser } from '@nostr-dev-kit/ndk'; +import { INostrClassified, INostrComment, INostrFollow, INostrJobRequest, INostrReaction, NostrEventTags, tags_classified, tags_comment, tags_follow_list, tags_job_request, tags_reaction, time_now_ms, type INostrMetadata } from '$root'; +import NDK, { NDKCacheAdapter, NDKEvent, NDKKind, NDKPrivateKeySigner, NDKUser } from '@nostr-dev-kit/ndk'; export type NDKEventFigure<T extends object> = { - $ndk: NDK; - $ndk_user: NDKUser; + ndk: NDK; + ndk_user: NDKUser; + date_published?: Date; } & T; +export const create_ndk = (explicitRelayUrls: string[], cacheAdapter?: NDKCacheAdapter): NDK => { + return new NDK({ + explicitRelayUrls, + enableOutboxModel: false, + cacheAdapter + }); +}; + +export const create_ndk_signer = (secret_key: string): NDKPrivateKeySigner => { + return new NDKPrivateKeySigner(secret_key); +}; + export const ndk_init = async (opts: { - $ndk: NDK; + ndk: NDK; secret_key: string; }): Promise<NDKUser | undefined> => { try { - const { $ndk: ndk, secret_key } = opts; + const { ndk, secret_key } = opts; const signer = new NDKPrivateKeySigner(secret_key); ndk.signer = signer; const user = await signer.user(); @@ -32,10 +45,12 @@ export const ndk_event = async (opts: NDKEventFigure<{ } }>): Promise<NDKEvent | undefined> => { try { - const { $ndk: ndk, $ndk_user: ndk_user, basis } = opts; + const { ndk: ndk, ndk_user: ndk_user, basis } = opts; const time_now = time_now_ms(); + const published_at = opts.date_published ? Math.floor(opts.date_published.getTime() / 1000).toString() + : time_now.toString() const tags: NostrEventTags = [ - ['published_at', time_now.toString()], + ['published_at', published_at], ]; if (basis.tags?.length) tags.push(...basis.tags); const ev = new NDKEvent(ndk, { @@ -52,12 +67,12 @@ export const ndk_event = async (opts: NDKEventFigure<{ }; export const ndk_event_metadata = async (opts: NDKEventFigure<{ - metadata: INostrMetadata + data: INostrMetadata }>): Promise<NDKEvent | undefined> => { - const { $ndk, $ndk_user, metadata: data } = opts; + const { ndk, ndk_user, data } = opts; return await ndk_event({ - $ndk, - $ndk_user, + ndk, + ndk_user, basis: { kind: 0, content: JSON.stringify(data), @@ -66,27 +81,27 @@ export const ndk_event_metadata = async (opts: NDKEventFigure<{ }; export const ndk_event_follows = async (opts: NDKEventFigure<{ - list: INostrFollow[]; + data: INostrFollow; }>): Promise<NDKEvent | undefined> => { - const { $ndk, $ndk_user, list: data } = opts; + const { ndk, ndk_user, data } = opts; return await ndk_event({ - $ndk, - $ndk_user, + ndk, + ndk_user, basis: { kind: 3, content: ``, - tags: tags_follow_list(data), + tags: tags_follow_list(data.list), }, }); }; export const ndk_event_classified = async (opts: NDKEventFigure<{ - classified: INostrClassified; + data: INostrClassified; }>): Promise<NDKEvent | undefined> => { - const { $ndk, $ndk_user, classified: data } = opts; + const { ndk, ndk_user, data } = opts; return await ndk_event({ - $ndk, - $ndk_user, + ndk, + ndk_user, basis: { kind: NDKKind.Classified, content: ``, @@ -98,10 +113,10 @@ export const ndk_event_classified = async (opts: NDKEventFigure<{ export const ndk_event_job_request = async (opts: NDKEventFigure<{ data: INostrJobRequest; }>): Promise<NDKEvent | undefined> => { - const { $ndk, $ndk_user, data } = opts; + const { ndk, ndk_user, data } = opts; return await ndk_event({ - $ndk, - $ndk_user, + ndk, + ndk_user, basis: { kind: NDKKind.DVMReqDiscoveryNostrContent, content: ``, @@ -113,10 +128,10 @@ export const ndk_event_job_request = async (opts: NDKEventFigure<{ export const ndk_event_reaction = async (opts: NDKEventFigure<{ data: INostrReaction; }>): Promise<NDKEvent | undefined> => { - const { $ndk, $ndk_user, data } = opts; + const { ndk, ndk_user, data } = opts; return await ndk_event({ - $ndk, - $ndk_user, + ndk, + ndk_user, basis: { kind: NDKKind.Reaction, content: data.content, @@ -124,3 +139,19 @@ export const ndk_event_reaction = async (opts: NDKEventFigure<{ }, }); }; + +export const ndk_event_comment = async (opts: NDKEventFigure<{ + data: INostrComment; +}>): Promise<NDKEvent | undefined> => { + const { ndk, ndk_user, data } = opts; + return await ndk_event({ + ndk, + ndk_user, + basis: { + kind: NDKKind.GenericReply, + content: data.content, + tags: tags_comment(data) + }, + }); +}; + diff --git a/utils-nostr/src/lib/tags.ts b/utils-nostr/src/lib/tags.ts @@ -1,4 +1,4 @@ -import { INostrClassified, INostrJobRequest, INostrReaction, NostrEventTagClient, NostrEventTagLocation, NostrEventTagMediaUpload, NostrEventTagPrice, NostrEventTagPriceDiscount, NostrEventTagQuantity, type INostrFollow, type NostrEventTag, type NostrEventTags } from "$root"; +import { INostrClassified, INostrComment, INostrFollowList, INostrJobRequest, INostrReaction, NostrEventTagClient, NostrEventTagLocation, NostrEventTagMediaUpload, NostrEventTagPrice, NostrEventTagPriceDiscount, NostrEventTagQuantity, type NostrEventTag, type NostrEventTags } from "$root"; import ngeotags, { type InputData as NostrGeotagsInputData } from "nostr-geotags"; export const tag_client = (opts: NostrEventTagClient, d_tag?: string): NostrEventTag => { @@ -8,7 +8,7 @@ export const tag_client = (opts: NostrEventTagClient, d_tag?: string): NostrEven return tag; }; -export const tags_follow_list = (list: INostrFollow[]): NostrEventTags => { +export const tags_follow_list = (list: INostrFollowList[]): NostrEventTags => { return list.map(({ public_key, relay_url, contact_name }) => { const entry = [`p`, public_key]; if (relay_url) entry.push(relay_url); @@ -113,3 +113,38 @@ export const tags_reaction = (opts: INostrReaction): NostrEventTags => { if (ref_event.d_tag) tags.push([`a`, `${ref_kind}:${ref_author}:${ref_event.d_tag}`, ...ref_event.relays || ``]) return tags; }; + +export const tags_comment = (opts: INostrComment): NostrEventTags => { + const { root_event, ref_event } = opts; + + const root = { + kind: root_event.kind.toString(), + author: root_event.author, + id: root_event.id, + d_tag: root_event.d_tag, + relays: root_event.relays || [], + }; + + const parent = (ref_event && ref_event.id) + ? { + kind: ref_event.kind.toString(), + author: ref_event.author, + id: ref_event.id, + d_tag: ref_event.d_tag, + relays: ref_event.relays || [], + } + : root; + + const tags: NostrEventTags = [ + ["E", root.id, ...root.relays], + ["P", root.author], + ["K", root.kind], + ...(root.d_tag ? [["A", `${root.kind}:${root.author}:${root.d_tag}`, ...root.relays]] : []), + ["e", parent.id, ...parent.relays], + ["p", parent.author], + ["k", parent.kind], + ...(parent.d_tag ? [["a", `${parent.kind}:${parent.author}:${parent.d_tag}`, ...parent.relays]] : []), + ]; + + return tags; +}; +\ No newline at end of file diff --git a/utils-nostr/src/lib/types.ts b/utils-nostr/src/lib/types.ts @@ -1,3 +1,4 @@ +import { NostrEventReferenced } from "$root"; import { ListingOrder } from "@radroots/radroots-common-bindings"; import { type EventTemplate as NostrToolsEventTemplate } from "nostr-tools"; @@ -14,12 +15,16 @@ export type INostrMetadata = { bot?: boolean; }; -export type INostrFollow = { +export type INostrFollowList = { public_key: string; relay_url?: string; contact_name?: string; }; +export type INostrFollow = { + list: INostrFollowList[] +}; + export type NostrEventTagQuantity = { amt: string; unit: string; @@ -140,12 +145,12 @@ export type NostrEventTagClient = { }; export type INostrReaction = { - ref_event: { - id: string; - kind: number; - author: string; - relays?: string[]; - d_tag?: string; - }, + ref_event: NostrEventReferenced; + content: string; +}; + +export type INostrComment = { + root_event: NostrEventReferenced; + ref_event?: NostrEventReferenced; content: string; }; \ No newline at end of file diff --git a/utils-nostr/src/services/events/lib.ts b/utils-nostr/src/services/events/lib.ts @@ -40,12 +40,12 @@ export class NostrEventService implements INostrEventService { return lib_nostr_nevent_encode(opts); }; - public metadata = async ($ndk: NDK, opts: INostrMetadata): Promise<INostrEventServiceEventResolve> => { - const $ndk_user = await this.resolve_ndk_user($ndk); - if (`err` in $ndk_user) return $ndk_user; + public metadata = async (ndk: NDK, opts: INostrMetadata): Promise<INostrEventServiceEventResolve> => { + const ndk_user = await this.resolve_ndk_user(ndk); + if (`err` in ndk_user) return ndk_user; const ev = await ndk_event({ - $ndk, - $ndk_user, + ndk, + ndk_user, basis: { kind: NDKKind.Metadata, content: JSON.stringify(opts), @@ -54,24 +54,24 @@ export class NostrEventService implements INostrEventService { return this.resolve_ndk_event(ev); } - public follows = async ($ndk: NDK, list: INostrFollow[]): Promise<INostrEventServiceEventResolve> => { - const $ndk_user = await this.resolve_ndk_user($ndk); - if (`err` in $ndk_user) return $ndk_user; + public follows = async (ndk: NDK, data: INostrFollow): Promise<INostrEventServiceEventResolve> => { + const ndk_user = await this.resolve_ndk_user(ndk); + if (`err` in ndk_user) return ndk_user; const ev = await ndk_event_follows({ - $ndk, - $ndk_user, - list + ndk, + ndk_user, + data }); return this.resolve_ndk_event(ev); } - public classified = async ($ndk: NDK, classified: INostrClassified): Promise<INostrEventServiceEventResolve> => { - const $ndk_user = await this.resolve_ndk_user($ndk); - if (`err` in $ndk_user) return $ndk_user; + public classified = async (ndk: NDK, data: INostrClassified): Promise<INostrEventServiceEventResolve> => { + const ndk_user = await this.resolve_ndk_user(ndk); + if (`err` in ndk_user) return ndk_user; const ev = await ndk_event_classified({ - $ndk, - $ndk_user, - classified + ndk, + ndk_user, + data }); return this.resolve_ndk_event(ev); } diff --git a/utils-nostr/src/services/events/types.ts b/utils-nostr/src/services/events/types.ts @@ -19,6 +19,6 @@ export type INostrEventService = { nostr_event_verify: (event: NostrToolsEvent) => boolean; nevent_encode: (opts: INostrEventServiceNeventEncode) => string; metadata: (ndk: NDK, opts: INostrMetadata) => Promise<INostrEventServiceEventResolve>; - follows: (ndk: NDK, opts: INostrFollow[]) => Promise<INostrEventServiceEventResolve>; + follows: (ndk: NDK, opts: INostrFollow) => Promise<INostrEventServiceEventResolve>; classified: (ndk: NDK, opts: INostrClassified) => Promise<INostrEventServiceEventResolve>; }; diff --git a/utils-nostr/src/types.ts b/utils-nostr/src/types.ts @@ -1,4 +1,14 @@ +import { NDKEvent } from "@nostr-dev-kit/ndk"; + +export type NostrNdkEvent = NDKEvent; export type NostrEventTag = string[]; export type NostrEventTags = NostrEventTag[]; export type ErrorMessage<T extends string> = { err: T }; export type ResolveError<T> = T | ErrorMessage<string>; +export type NostrEventReferenced = { + id: string; + kind: number; + author: string; + relays?: string[]; + d_tag?: string; +} +\ No newline at end of file