Initial commit: Nosterm client (terminal-style Nostr chat SPA)
ci / build (push) Successful in 1m3s
ci / image (push) Successful in 41s

This commit is contained in:
Robert Goodall
2026-07-24 13:47:53 -04:00
commit cd2b900639
147 changed files with 16504 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
/**
* nip-29 (managed relay-based groups) event kinds and tag helpers.
* managed groups: the relay keeps membership/metadata and enforces access.
*/
export const NIP29_KINDS = {
/** chat message posted to a group. */
chat: 9,
/** threaded reply (we show it like chat for the mvp). */
threadReply: 11,
/** admin adds a user to a group (kind 9000). */
putUser: 9000,
/** admin removes a user from a group (kind 9001). */
removeUser: 9001,
/** admin edits group metadata — name/about (kind 9002). */
editMetadata: 9002,
/** join request (kind 9021). */
joinRequest: 9021,
/** leave request (kind 9022). */
leaveRequest: 9022,
/** group metadata (name/about/picture). */
metadata: 39000,
/** group admins list. */
admins: 39001,
/** group members list. */
members: 39002
} as const;
/** addressable nip-29 list kinds the client subscribes to for group state. */
export const GROUP_META_KINDS: number[] = [
NIP29_KINDS.metadata,
NIP29_KINDS.admins,
NIP29_KINDS.members
];
/** pull all `p` tag pubkeys out of an event's tags. */
export function pubkeysFromTags(tags: string[][]): string[] {
return tags.filter((t) => t[0] === 'p' && typeof t[1] === 'string').map((t) => t[1] as string);
}
/** value of the first tag with the given name, or undefined. */
export function tagValue(tags: string[][], name: string): string | undefined {
return tags.find((t) => t[0] === name)?.[1];
}
/** kinds we treat as showable chat messages in a room timeline. */
export const CHAT_KINDS: number[] = [NIP29_KINDS.chat, NIP29_KINDS.threadReply];
/** the `h` tag carries the group id on every nip-29 event. */
export function groupTag(groupId: string): string[] {
return ['h', groupId];
}
/** pull the group id out of an event's tags, if it's there. */
export function groupIdFromTags(tags: string[][]): string | undefined {
const h = tags.find((t) => t[0] === 'h');
return h?.[1];
}