applesauce-common 0.0.0-next-20251220152312 → 0.0.0-next-20251231055351

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +45 -4
  2. package/dist/blueprints/__register__.d.ts +1 -0
  3. package/dist/blueprints/__register__.js +1 -0
  4. package/dist/blueprints/comment.d.ts +3 -2
  5. package/dist/blueprints/torrent.d.ts +7 -0
  6. package/dist/blueprints/torrent.js +5 -1
  7. package/dist/casts/article.d.ts +2 -0
  8. package/dist/casts/article.js +6 -0
  9. package/dist/casts/bookmarks.d.ts +3 -3
  10. package/dist/casts/bookmarks.js +18 -6
  11. package/dist/casts/comment.d.ts +2 -0
  12. package/dist/casts/comment.js +5 -0
  13. package/dist/casts/groups.d.ts +19 -0
  14. package/dist/casts/groups.js +43 -0
  15. package/dist/casts/index.d.ts +6 -0
  16. package/dist/casts/index.js +6 -0
  17. package/dist/casts/note.d.ts +8 -0
  18. package/dist/casts/note.js +30 -0
  19. package/dist/casts/profile.d.ts +8 -0
  20. package/dist/casts/profile.js +12 -0
  21. package/dist/casts/reaction.d.ts +17 -0
  22. package/dist/casts/reaction.js +46 -0
  23. package/dist/casts/relay-discovery.d.ts +29 -0
  24. package/dist/casts/relay-discovery.js +54 -0
  25. package/dist/casts/relay-monitor.d.ts +21 -0
  26. package/dist/casts/relay-monitor.js +41 -0
  27. package/dist/casts/report.d.ts +31 -0
  28. package/dist/casts/report.js +74 -0
  29. package/dist/casts/share.d.ts +2 -0
  30. package/dist/casts/share.js +6 -0
  31. package/dist/casts/torrent.d.ts +31 -0
  32. package/dist/casts/torrent.js +62 -0
  33. package/dist/casts/user.d.ts +2 -0
  34. package/dist/casts/user.js +13 -1
  35. package/dist/helpers/calendar-event.d.ts +7 -1
  36. package/dist/helpers/calendar-event.js +8 -10
  37. package/dist/helpers/channels.d.ts +1 -1
  38. package/dist/helpers/channels.js +5 -8
  39. package/dist/helpers/comment.d.ts +3 -1
  40. package/dist/helpers/comment.js +12 -2
  41. package/dist/helpers/external-id.d.ts +32 -0
  42. package/dist/helpers/external-id.js +85 -0
  43. package/dist/helpers/file-metadata.d.ts +1 -4
  44. package/dist/helpers/file-metadata.js +1 -4
  45. package/dist/helpers/groups.d.ts +11 -1
  46. package/dist/helpers/groups.js +30 -5
  47. package/dist/helpers/reports.d.ts +4 -1
  48. package/dist/helpers/reports.js +14 -10
  49. package/dist/models/blossom.d.ts +2 -2
  50. package/dist/models/blossom.js +1 -1
  51. package/dist/models/channels.js +3 -9
  52. package/dist/models/comments.d.ts +3 -2
  53. package/dist/models/comments.js +19 -1
  54. package/dist/operations/comment.d.ts +3 -2
  55. package/dist/operations/comment.js +19 -5
  56. package/dist/operations/torrent.d.ts +2 -0
  57. package/dist/operations/torrent.js +4 -0
  58. package/package.json +2 -2
package/README.md CHANGED
@@ -1,11 +1,33 @@
1
1
  # applesauce-common
2
2
 
3
- AppleSauce is a collection of utilities for building reactive nostr applications. The common package provides NIP-specific helpers and models for working with various Nostr Improvement Proposals (NIPs).
3
+ AppleSauce is a collection of utilities for building reactive nostr applications. The common package provides NIP-specific helpers, models, operations, and utilities for working with various Nostr Improvement Proposals (NIPs). This package contains all the extra functionality that applications can use with nostr events that is not directly related to the core protocol.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install applesauce-common
9
+ ```
10
+
11
+ or
12
+
13
+ ```bash
14
+ yarn add applesauce-common
15
+ ```
16
+
17
+ or
18
+
19
+ ```bash
20
+ pnpm add applesauce-common
21
+ ```
4
22
 
5
23
  ## Key Components
6
24
 
7
25
  - **Helpers**: NIP-specific utility methods for parsing and extracting data from nostr events
8
- - **Models**: Complex subscriptions for NIP-specific nostr data patterns
26
+ - **Models**: Complex reactive subscriptions for NIP-specific nostr data patterns
27
+ - **Operations**: Functions for creating and constructing nostr events according to various NIPs
28
+ - **Blueprints**: Event blueprints and templates for creating properly formatted nostr events
29
+ - **Casts**: Type casting utilities for converting between different event representations
30
+ - **Observable**: Observable utilities and operators for working with reactive streams of nostr events
9
31
 
10
32
  ## Documentation
11
33
 
@@ -48,12 +70,31 @@ thread.subscribe((thread) => {
48
70
 
49
71
  ## Supported NIPs
50
72
 
51
- This package includes helpers and models for various NIPs including:
73
+ This package includes helpers, models, and operations for various NIPs including:
52
74
 
53
75
  - NIP-10 (Threading)
76
+ - NIP-18 (Reposts)
54
77
  - NIP-22 (Comments)
55
- - NIP-53 (Streams)
56
78
  - NIP-23 (Articles)
79
+ - NIP-25 (Reactions)
80
+ - NIP-28 (Channels)
57
81
  - NIP-52 (Calendar Events)
82
+ - NIP-53 (Streams)
83
+ - NIP-57 (Zaps)
58
84
  - NIP-88 (Polls)
59
85
  - And many more...
86
+
87
+ ## Exports
88
+
89
+ The package provides several export paths:
90
+
91
+ - `applesauce-common` - Main exports (Helpers, Models, Operations, etc.)
92
+ - `applesauce-common/helpers` - All helper functions
93
+ - `applesauce-common/helpers/*` - Individual helper modules
94
+ - `applesauce-common/models` - All model functions
95
+ - `applesauce-common/models/*` - Individual model modules
96
+ - `applesauce-common/operations` - All operation functions
97
+ - `applesauce-common/operations/*` - Individual operation modules
98
+ - `applesauce-common/blueprints` - Event blueprints
99
+ - `applesauce-common/casts` - Type casting utilities
100
+ - `applesauce-common/observable` - Observable utilities
@@ -4,3 +4,4 @@ import "./note.js";
4
4
  import "./reaction.js";
5
5
  import "./share.js";
6
6
  import "./poll.js";
7
+ import "./torrent.js";
@@ -5,3 +5,4 @@ import "./note.js";
5
5
  import "./reaction.js";
6
6
  import "./share.js";
7
7
  import "./poll.js";
8
+ import "./torrent.js";
@@ -1,12 +1,13 @@
1
1
  import { NostrEvent, EventTemplate } from "applesauce-core/helpers/event";
2
2
  import { TextContentOptions } from "applesauce-core/operations/content";
3
3
  import { MetaTagOptions } from "applesauce-core/operations/event";
4
+ import { CommentPointer } from "../helpers/comment.js";
4
5
  export type CommentBlueprintOptions = TextContentOptions & MetaTagOptions;
5
6
  /** A blueprint to create a NIP-22 comment event */
6
- export declare function CommentBlueprint(parent: NostrEvent, content: string, options?: CommentBlueprintOptions): import("applesauce-core/event-factory").EventBlueprint;
7
+ export declare function CommentBlueprint(parent: NostrEvent | CommentPointer, content: string, options?: CommentBlueprintOptions): import("applesauce-core/event-factory").EventBlueprint;
7
8
  declare module "applesauce-core/event-factory" {
8
9
  interface EventFactory {
9
10
  /** Create a NIP-22 comment event */
10
- comment(parent: NostrEvent, content: string, options?: CommentBlueprintOptions): Promise<EventTemplate>;
11
+ comment(parent: NostrEvent | CommentPointer, content: string, options?: CommentBlueprintOptions): Promise<EventTemplate>;
11
12
  }
12
13
  }
@@ -1,3 +1,4 @@
1
+ import { EventTemplate } from "applesauce-core/helpers/event";
1
2
  import { MetaTagOptions } from "applesauce-core/operations/event";
2
3
  import { TorrentExternalIdentifier, TorrentFile } from "../helpers/torrent.js";
3
4
  export type TorrentBlueprintOptions = MetaTagOptions & {
@@ -21,3 +22,9 @@ export type TorrentBlueprintOptions = MetaTagOptions & {
21
22
  * Creates a torrent event with info hash and optional metadata
22
23
  */
23
24
  export declare function TorrentBlueprint(infoHash: string, content: string, options?: TorrentBlueprintOptions): import("applesauce-core/event-factory").EventBlueprint;
25
+ declare module "applesauce-core/event-factory" {
26
+ interface EventFactory {
27
+ /** Create a NIP-35 torrent event (kind 2003) */
28
+ torrent(infoHash: string, content: string, options?: TorrentBlueprintOptions): Promise<EventTemplate>;
29
+ }
30
+ }
@@ -1,4 +1,4 @@
1
- import { blueprint } from "applesauce-core/event-factory";
1
+ import { blueprint, EventFactory } from "applesauce-core/event-factory";
2
2
  import { eventPipe } from "applesauce-core/helpers/pipeline";
3
3
  import { setContent } from "applesauce-core/operations/content";
4
4
  import { setMetaTags } from "applesauce-core/operations/event";
@@ -23,3 +23,7 @@ export function TorrentBlueprint(infoHash, content, options) {
23
23
  ? eventPipe(...options.externalIdentifiers.map((id) => addTorrentExternalIdentifier(id)))
24
24
  : undefined, setMetaTags({ ...options, alt: options?.alt ?? `Torrent: ${options?.title ?? infoHash}` }));
25
25
  }
26
+ // Register this blueprint with EventFactory
27
+ EventFactory.prototype.torrent = function (infoHash, content, options) {
28
+ return this.create(TorrentBlueprint, infoHash, content, options);
29
+ };
@@ -1,6 +1,7 @@
1
1
  import { NostrEvent } from "applesauce-core/helpers";
2
2
  import { ArticleEvent } from "../helpers/article.js";
3
3
  import { CastRefEventStore, EventCast } from "./cast.js";
4
+ import { Reaction } from "./reaction.js";
4
5
  export declare class Article extends EventCast<ArticleEvent> {
5
6
  constructor(event: NostrEvent, store: CastRefEventStore);
6
7
  get title(): string;
@@ -14,4 +15,5 @@ export declare class Article extends EventCast<ArticleEvent> {
14
15
  get address(): `naddr1${string}`;
15
16
  /** An observable of the address with relay hints from the authors outboxes */
16
17
  get address$(): import("applesauce-core").Observable<`naddr1${string}`>;
18
+ get reactions$(): import("../observable/chainable.js").ChainableObservable<Reaction[]>;
17
19
  }
@@ -2,7 +2,10 @@ import { withImmediateValueOrDefault } from "applesauce-core";
2
2
  import { addRelayHintsToPointer, getAddressPointerForEvent, naddrEncode } from "applesauce-core/helpers";
3
3
  import { map } from "rxjs";
4
4
  import { getArticleImage, getArticlePublished, getArticleSummary, getArticleTitle, isValidArticle, } from "../helpers/article.js";
5
+ import { ReactionsModel } from "../models/reactions.js";
6
+ import { castTimelineStream } from "../observable/cast-stream.js";
5
7
  import { EventCast } from "./cast.js";
8
+ import { Reaction } from "./reaction.js";
6
9
  export class Article extends EventCast {
7
10
  constructor(event, store) {
8
11
  if (!isValidArticle(event))
@@ -38,4 +41,7 @@ export class Article extends EventCast {
38
41
  get address$() {
39
42
  return this.pointer$.pipe(map((pointer) => naddrEncode(pointer)));
40
43
  }
44
+ get reactions$() {
45
+ return this.$$ref("reactions$", (store) => store.model(ReactionsModel, this.event).pipe(castTimelineStream(Reaction, store)));
46
+ }
41
47
  }
@@ -14,9 +14,9 @@ declare class BookmarksListBase<T extends BookmarkListEvent | BookmarkSetEvent>
14
14
  /** Get the unlocked hidden bookmarks */
15
15
  get hidden(): import("../helpers/bookmark.js").BookmarkPointer[] | undefined;
16
16
  /** An observable that updates when hidden bookmarks are unlocked */
17
- get hidden$(): import("../observable/chainable.js").ChainableObservable<import("../helpers/bookmark.js").BookmarkPointer[]>;
18
- get hiddenNotes$(): import("../observable/chainable.js").ChainableObservable<Note[]>;
19
- get hiddenArticles$(): import("../observable/chainable.js").ChainableObservable<Article[]>;
17
+ get hidden$(): import("../observable/chainable.js").ChainableObservable<import("../helpers/bookmark.js").BookmarkPointer[] | undefined>;
18
+ get hiddenNotes$(): import("../observable/chainable.js").ChainableObservable<Note[] | undefined>;
19
+ get hiddenArticles$(): import("../observable/chainable.js").ChainableObservable<Article[] | undefined>;
20
20
  /** Whether the bookmark set has hidden bookmarks */
21
21
  get hasHidden(): boolean;
22
22
  /** Whether the bookmark set is unlocked */
@@ -1,5 +1,5 @@
1
1
  import { hasHiddenContent, isAddressPointer, isEventPointer, } from "applesauce-core/helpers";
2
- import { defined, watchEventUpdates } from "applesauce-core/observable";
2
+ import { watchEventUpdates } from "applesauce-core/observable";
3
3
  import { combineLatest, map, of, switchMap } from "rxjs";
4
4
  import { getBookmarks, getHiddenBookmarks, isHiddenBookmarksUnlocked, isValidBookmarkList, isValidBookmarkSet, unlockHiddenBookmarks, } from "../helpers/bookmark.js";
5
5
  import { castTimelineStream } from "../observable/cast-stream.js";
@@ -38,15 +38,27 @@ class BookmarksListBase extends EventCast {
38
38
  // Watch for event updates
39
39
  watchEventUpdates(store),
40
40
  // Get hidden bookmarks
41
- map((event) => event && getHiddenBookmarks(event)),
42
- /** Only emit when the hidden bookmarks are unlocked */
43
- defined()));
41
+ map((event) => event && getHiddenBookmarks(event))));
44
42
  }
45
43
  get hiddenNotes$() {
46
- return this.$$ref("hiddenNotes$", (store) => this.hidden$.pipe(switchMap((hidden) => combineLatest(hidden.filter((pointer) => isEventPointer(pointer)).map((pointer) => store.event(pointer)))), map((arr) => arr.filter((e) => !!e)), castTimelineStream(Note, store)));
44
+ return this.$$ref("hiddenNotes$", (store) => this.hidden$.pipe(switchMap((hidden) => {
45
+ if (hidden === undefined)
46
+ return of(undefined);
47
+ const eventPointers = hidden.filter((pointer) => isEventPointer(pointer));
48
+ if (eventPointers.length === 0)
49
+ return of([]);
50
+ return combineLatest(eventPointers.map((pointer) => store.event(pointer))).pipe(map((arr) => arr.filter((e) => !!e)), castTimelineStream(Note, store));
51
+ })));
47
52
  }
48
53
  get hiddenArticles$() {
49
- return this.$$ref("hiddenArticles$", (store) => this.hidden$.pipe(switchMap((hidden) => combineLatest(hidden.filter((pointer) => isAddressPointer(pointer)).map((pointer) => store.replaceable(pointer)))), map((arr) => arr.filter((e) => !!e)), castTimelineStream(Article, store)));
54
+ return this.$$ref("hiddenArticles$", (store) => this.hidden$.pipe(switchMap((hidden) => {
55
+ if (hidden === undefined)
56
+ return of(undefined);
57
+ const addressPointers = hidden.filter((pointer) => isAddressPointer(pointer));
58
+ if (addressPointers.length === 0)
59
+ return of([]);
60
+ return combineLatest(addressPointers.map((pointer) => store.replaceable(pointer))).pipe(map((arr) => arr.filter((e) => !!e)), castTimelineStream(Article, store));
61
+ })));
50
62
  }
51
63
  /** Whether the bookmark set has hidden bookmarks */
52
64
  get hasHidden() {
@@ -1,6 +1,7 @@
1
1
  import { NostrEvent } from "applesauce-core/helpers/event";
2
2
  import { CommentEvent } from "../helpers/comment.js";
3
3
  import { CastRefEventStore, EventCast } from "./cast.js";
4
+ import { Reaction } from "./reaction.js";
4
5
  import { Zap } from "./zap.js";
5
6
  /** Cast a kind 1111 event to a Comment */
6
7
  export declare class Comment extends EventCast<CommentEvent> {
@@ -13,4 +14,5 @@ export declare class Comment extends EventCast<CommentEvent> {
13
14
  get parent$(): import("../observable/chainable.js").ChainableObservable<import("nostr-tools").Event | undefined>;
14
15
  get zaps$(): import("../observable/chainable.js").ChainableObservable<Zap[]>;
15
16
  get replies$(): import("../observable/chainable.js").ChainableObservable<Comment[]>;
17
+ get reactions$(): import("../observable/chainable.js").ChainableObservable<Reaction[]>;
16
18
  }
@@ -1,9 +1,11 @@
1
1
  import { of } from "rxjs";
2
2
  import { getCommentReplyPointer, getCommentRootPointer, isValidComment } from "../helpers/comment.js";
3
3
  import { CommentsModel } from "../models/comments.js";
4
+ import { ReactionsModel } from "../models/reactions.js";
4
5
  import { EventZapsModel } from "../models/zaps.js";
5
6
  import { castTimelineStream } from "../observable/cast-stream.js";
6
7
  import { EventCast } from "./cast.js";
8
+ import { Reaction } from "./reaction.js";
7
9
  import { Zap } from "./zap.js";
8
10
  /** Cast a kind 1111 event to a Comment */
9
11
  export class Comment extends EventCast {
@@ -46,4 +48,7 @@ export class Comment extends EventCast {
46
48
  get replies$() {
47
49
  return this.$$ref("replies$", (store) => store.model(CommentsModel, this.event).pipe(castTimelineStream(Comment, store)));
48
50
  }
51
+ get reactions$() {
52
+ return this.$$ref("reactions$", (store) => store.model(ReactionsModel, this.event).pipe(castTimelineStream(Reaction, store)));
53
+ }
49
54
  }
@@ -0,0 +1,19 @@
1
+ import { HiddenContentSigner } from "applesauce-core/helpers";
2
+ import { KnownEvent, NostrEvent } from "applesauce-core/helpers/event";
3
+ import { GROUPS_LIST_KIND } from "../helpers/groups.js";
4
+ import { CastRefEventStore, EventCast } from "./cast.js";
5
+ export declare class GroupsList extends EventCast<KnownEvent<typeof GROUPS_LIST_KIND>> {
6
+ constructor(event: NostrEvent, store: CastRefEventStore);
7
+ /** The public groups in the list */
8
+ get groups(): import("../helpers/groups.js").GroupPointer[];
9
+ /** Get the unlocked hidden groups */
10
+ get hidden(): import("../helpers/groups.js").GroupPointer[] | undefined;
11
+ /** An observable that updates when hidden groups are unlocked */
12
+ get hidden$(): import("../observable/chainable.js").ChainableObservable<import("../helpers/groups.js").GroupPointer[] | undefined>;
13
+ /** Whether the groups list has hidden groups */
14
+ get hasHidden(): boolean;
15
+ /** Whether the groups list is unlocked */
16
+ get unlocked(): boolean;
17
+ /** Unlocks the hidden groups on the groups list */
18
+ unlock(signer: HiddenContentSigner): Promise<import("../helpers/groups.js").GroupPointer[]>;
19
+ }
@@ -0,0 +1,43 @@
1
+ import { hasHiddenContent } from "applesauce-core/helpers";
2
+ import { watchEventUpdates } from "applesauce-core/observable";
3
+ import { map, of } from "rxjs";
4
+ import { getHiddenGroups, getPublicGroups, GROUPS_LIST_KIND, isHiddenGroupsUnlocked, unlockHiddenGroups, } from "../helpers/groups.js";
5
+ import { EventCast } from "./cast.js";
6
+ function isValidGroupsList(event) {
7
+ return event.kind === GROUPS_LIST_KIND;
8
+ }
9
+ export class GroupsList extends EventCast {
10
+ constructor(event, store) {
11
+ if (!isValidGroupsList(event))
12
+ throw new Error("Invalid groups list");
13
+ super(event, store);
14
+ }
15
+ /** The public groups in the list */
16
+ get groups() {
17
+ return getPublicGroups(this.event);
18
+ }
19
+ /** Get the unlocked hidden groups */
20
+ get hidden() {
21
+ return getHiddenGroups(this.event);
22
+ }
23
+ /** An observable that updates when hidden groups are unlocked */
24
+ get hidden$() {
25
+ return this.$$ref("hidden$", (store) => of(this.event).pipe(
26
+ // Watch for event updates
27
+ watchEventUpdates(store),
28
+ // Get hidden groups
29
+ map((event) => event && getHiddenGroups(event))));
30
+ }
31
+ /** Whether the groups list has hidden groups */
32
+ get hasHidden() {
33
+ return hasHiddenContent(this.event);
34
+ }
35
+ /** Whether the groups list is unlocked */
36
+ get unlocked() {
37
+ return isHiddenGroupsUnlocked(this.event);
38
+ }
39
+ /** Unlocks the hidden groups on the groups list */
40
+ async unlock(signer) {
41
+ return unlockHiddenGroups(this.event, signer);
42
+ }
43
+ }
@@ -2,11 +2,17 @@ export * from "./article.js";
2
2
  export * from "./bookmarks.js";
3
3
  export * from "./cast.js";
4
4
  export * from "./comment.js";
5
+ export * from "./groups.js";
5
6
  export * from "./mutes.js";
6
7
  export * from "./note.js";
7
8
  export * from "./profile.js";
9
+ export * from "./reaction.js";
10
+ export * from "./relay-discovery.js";
8
11
  export * from "./relay-lists.js";
12
+ export * from "./relay-monitor.js";
13
+ export * from "./report.js";
9
14
  export * from "./share.js";
10
15
  export * from "./stream.js";
16
+ export * from "./torrent.js";
11
17
  export * from "./user.js";
12
18
  export * from "./zap.js";
@@ -2,11 +2,17 @@ export * from "./article.js";
2
2
  export * from "./bookmarks.js";
3
3
  export * from "./cast.js";
4
4
  export * from "./comment.js";
5
+ export * from "./groups.js";
5
6
  export * from "./mutes.js";
6
7
  export * from "./note.js";
7
8
  export * from "./profile.js";
9
+ export * from "./reaction.js";
10
+ export * from "./relay-discovery.js";
8
11
  export * from "./relay-lists.js";
12
+ export * from "./relay-monitor.js";
13
+ export * from "./report.js";
9
14
  export * from "./share.js";
10
15
  export * from "./stream.js";
16
+ export * from "./torrent.js";
11
17
  export * from "./user.js";
12
18
  export * from "./zap.js";
@@ -1,6 +1,7 @@
1
1
  import { EventPointer, KnownEvent, NostrEvent } from "applesauce-core/helpers";
2
2
  import { CastRefEventStore, EventCast } from "./cast.js";
3
3
  import { Comment } from "./comment.js";
4
+ import { Reaction } from "./reaction.js";
4
5
  import { Share } from "./share.js";
5
6
  import { Zap } from "./zap.js";
6
7
  export declare class Note extends EventCast<KnownEvent<1>> {
@@ -10,8 +11,15 @@ export declare class Note extends EventCast<KnownEvent<1>> {
10
11
  get isRoot(): boolean;
11
12
  /** An array of events that this note is quoting */
12
13
  get quotePointers(): EventPointer[];
14
+ /** Gets the NIP-10 root event */
15
+ get threadRoot$(): import("../observable/chainable.js").ChainableObservable<import("nostr-tools").Event | undefined>;
16
+ /** Gets the NIP-10 reply event */
17
+ get replyingTo$(): import("../observable/chainable.js").ChainableObservable<import("nostr-tools").Event | undefined>;
18
+ /** Gets the NIP-10 replies to this event */
13
19
  get replies$(): import("../observable/chainable.js").ChainableObservable<Note[]>;
20
+ /** Gets the NIP-22 comments to this event */
14
21
  get comments$(): import("../observable/chainable.js").ChainableObservable<Comment[]>;
15
22
  get zaps$(): import("../observable/chainable.js").ChainableObservable<Zap[]>;
16
23
  get shares$(): import("../observable/chainable.js").ChainableObservable<Share[]>;
24
+ get reactions$(): import("../observable/chainable.js").ChainableObservable<Reaction[]>;
17
25
  }
@@ -1,14 +1,17 @@
1
1
  import { getEventPointerFromQTag, isQTag, kinds, processTags, } from "applesauce-core/helpers";
2
2
  import { getNip10References } from "../helpers/threading.js";
3
3
  import { CommentsModel } from "../models/comments.js";
4
+ import { ReactionsModel } from "../models/reactions.js";
4
5
  import { SharesModel } from "../models/shares.js";
5
6
  import { RepliesModel } from "../models/thread.js";
6
7
  import { EventZapsModel } from "../models/zaps.js";
7
8
  import { castTimelineStream } from "../observable/cast-stream.js";
8
9
  import { EventCast } from "./cast.js";
9
10
  import { Comment } from "./comment.js";
11
+ import { Reaction } from "./reaction.js";
10
12
  import { Share } from "./share.js";
11
13
  import { Zap } from "./zap.js";
14
+ import { of } from "rxjs";
12
15
  function isValidNote(event) {
13
16
  return event.kind === kinds.ShortTextNote;
14
17
  }
@@ -31,9 +34,33 @@ export class Note extends EventCast {
31
34
  get quotePointers() {
32
35
  return processTags(this.event.tags, (t) => (isQTag(t) ? t : undefined), (t) => getEventPointerFromQTag(t) ?? undefined);
33
36
  }
37
+ /** Gets the NIP-10 root event */
38
+ get threadRoot$() {
39
+ return this.$$ref("threadRoot$", (store) => {
40
+ const pointer = this.references.root;
41
+ // Return undefined if no root reference
42
+ if (pointer === undefined)
43
+ return of(undefined);
44
+ // Get the event by either the address or event pointer
45
+ return store.event(pointer.a ?? pointer.e);
46
+ });
47
+ }
48
+ /** Gets the NIP-10 reply event */
49
+ get replyingTo$() {
50
+ return this.$$ref("replyingTo$", (store) => {
51
+ const pointer = this.references.reply;
52
+ // Return undefined if no reply reference
53
+ if (pointer === undefined)
54
+ return of(undefined);
55
+ // Get the event by either the address or event pointer
56
+ return store.event(pointer.a ?? pointer.e);
57
+ });
58
+ }
59
+ /** Gets the NIP-10 replies to this event */
34
60
  get replies$() {
35
61
  return this.$$ref("replies$", (store) => store.model(RepliesModel, this.event, [kinds.ShortTextNote]).pipe(castTimelineStream(Note, store)));
36
62
  }
63
+ /** Gets the NIP-22 comments to this event */
37
64
  get comments$() {
38
65
  return this.$$ref("comments$", (store) => store.model(CommentsModel, this.event).pipe(castTimelineStream(Comment, store)));
39
66
  }
@@ -43,4 +70,7 @@ export class Note extends EventCast {
43
70
  get shares$() {
44
71
  return this.$$ref("shares$", (store) => store.model(SharesModel, this.event).pipe(castTimelineStream(Share, store)));
45
72
  }
73
+ get reactions$() {
74
+ return this.$$ref("reactions$", (store) => store.model(ReactionsModel, this.event).pipe(castTimelineStream(Reaction, store)));
75
+ }
46
76
  }
@@ -8,9 +8,17 @@ export declare class Profile extends EventCast<ProfileEvent> {
8
8
  get displayName(): string | undefined;
9
9
  get about(): string | undefined;
10
10
  get picture(): string | undefined;
11
+ get banner(): string | undefined;
11
12
  get dnsIdentity(): string | undefined;
12
13
  get website(): string | undefined;
13
14
  get lud16(): string | undefined;
14
15
  get lud06(): string | undefined;
15
16
  get lightningAddress(): string | undefined;
17
+ get bot(): boolean | undefined;
18
+ get birthday(): {
19
+ year?: number;
20
+ month?: number;
21
+ day?: number;
22
+ } | undefined;
23
+ get languages(): string[] | undefined;
16
24
  }
@@ -22,6 +22,9 @@ export class Profile extends EventCast {
22
22
  get picture() {
23
23
  return getProfilePicture(this.metadata);
24
24
  }
25
+ get banner() {
26
+ return this.metadata.banner;
27
+ }
25
28
  get dnsIdentity() {
26
29
  return this.metadata.nip05;
27
30
  }
@@ -37,4 +40,13 @@ export class Profile extends EventCast {
37
40
  get lightningAddress() {
38
41
  return this.metadata.lud16 || this.metadata.lud06;
39
42
  }
43
+ get bot() {
44
+ return this.metadata.bot;
45
+ }
46
+ get birthday() {
47
+ return this.metadata.birthday;
48
+ }
49
+ get languages() {
50
+ return this.metadata.languages;
51
+ }
40
52
  }
@@ -0,0 +1,17 @@
1
+ import { KnownEvent, NostrEvent } from "applesauce-core/helpers/event";
2
+ import { CastRefEventStore, EventCast } from "./cast.js";
3
+ export declare class Reaction extends EventCast<KnownEvent<7>> {
4
+ constructor(event: NostrEvent, store: CastRefEventStore);
5
+ /** Get the emoji content of the reaction (defaults to "+" if empty) */
6
+ get content(): string;
7
+ /** Get the custom emoji if this reaction uses a custom emoji */
8
+ get emoji(): import("../helpers/emoji.js").Emoji | undefined;
9
+ /** Get the event pointer for the event being reacted to */
10
+ get eventPointer(): import("nostr-tools/nip19").EventPointer | undefined;
11
+ /** Get the address pointer for the event being reacted to (for replaceable events) */
12
+ get addressPointer(): import("nostr-tools/nip19").AddressPointer | undefined;
13
+ /** Get the pointer (event or address) for the event being reacted to */
14
+ get pointer(): import("nostr-tools/nip19").EventPointer | import("nostr-tools/nip19").AddressPointer | undefined;
15
+ /** Get the event that this reaction is reacting to */
16
+ get reactedTo$(): import("../observable/chainable.js").ChainableObservable<import("nostr-tools").Event | undefined>;
17
+ }
@@ -0,0 +1,46 @@
1
+ import { kinds } from "applesauce-core/helpers/event";
2
+ import { of } from "rxjs";
3
+ import { getReactionEmoji } from "../helpers/emoji.js";
4
+ import { getReactionAddressPointer, getReactionEventPointer } from "../helpers/reaction.js";
5
+ import { EventCast } from "./cast.js";
6
+ import { addRelayHintsToPointer } from "applesauce-core/helpers";
7
+ function isValidReaction(event) {
8
+ return event.kind === kinds.Reaction;
9
+ }
10
+ export class Reaction extends EventCast {
11
+ constructor(event, store) {
12
+ if (!isValidReaction(event))
13
+ throw new Error("Invalid reaction");
14
+ super(event, store);
15
+ }
16
+ /** Get the emoji content of the reaction (defaults to "+" if empty) */
17
+ get content() {
18
+ return this.event.content || "+";
19
+ }
20
+ /** Get the custom emoji if this reaction uses a custom emoji */
21
+ get emoji() {
22
+ return getReactionEmoji(this.event);
23
+ }
24
+ /** Get the event pointer for the event being reacted to */
25
+ get eventPointer() {
26
+ return getReactionEventPointer(this.event);
27
+ }
28
+ /** Get the address pointer for the event being reacted to (for replaceable events) */
29
+ get addressPointer() {
30
+ return getReactionAddressPointer(this.event);
31
+ }
32
+ /** Get the pointer (event or address) for the event being reacted to */
33
+ get pointer() {
34
+ return this.addressPointer || this.eventPointer;
35
+ }
36
+ /** Get the event that this reaction is reacting to */
37
+ get reactedTo$() {
38
+ return this.$$ref("reactedTo$", (store) => {
39
+ const pointer = this.pointer;
40
+ if (!pointer)
41
+ return of(undefined);
42
+ else
43
+ return store.event(addRelayHintsToPointer(pointer, this.seen));
44
+ });
45
+ }
46
+ }
@@ -0,0 +1,29 @@
1
+ import { NostrEvent } from "applesauce-core/helpers";
2
+ import { RelayDiscoveryEvent } from "../helpers/relay-discovery.js";
3
+ import { CastRefEventStore, EventCast } from "./cast.js";
4
+ /** Cast a kind 30166 event to a RelayDiscovery */
5
+ export declare class RelayDiscovery extends EventCast<RelayDiscoveryEvent> {
6
+ constructor(event: NostrEvent, store: CastRefEventStore);
7
+ /** Gets the relay URL from this discovery event (from the `d` tag) */
8
+ get url(): string | undefined;
9
+ /** Gets the round-trip time (RTT) for opening the relay connection (in milliseconds) */
10
+ get rttOpen(): number | undefined;
11
+ /** Gets the round-trip time (RTT) for reading from the relay (in milliseconds) */
12
+ get rttRead(): number | undefined;
13
+ /** Gets the round-trip time (RTT) for writing to the relay (in milliseconds) */
14
+ get rttWrite(): number | undefined;
15
+ /** Gets the network type from this discovery event (clearnet, tor, i2p, loki) */
16
+ get networkType(): string | undefined;
17
+ /** Gets all relay attributes from this discovery event (from `W` tags) */
18
+ get attributes(): string[];
19
+ /** Gets all supported NIPs from this discovery event (from `N` tags) */
20
+ get supportedNIPs(): string[];
21
+ /** Gets all requirements from this discovery event (from `R` tags) */
22
+ get requirements(): string[];
23
+ /** Gets all topics from this discovery event (from `t` tags) */
24
+ get topics(): string[];
25
+ /** Gets all accepted and unaccepted kinds from this discovery event (from `k` tags) */
26
+ get acceptedKinds(): string[];
27
+ /** Gets the geohash from this discovery event (NIP-52 geohash) */
28
+ get geohash(): string | undefined;
29
+ }
@@ -0,0 +1,54 @@
1
+ import { getRelayDiscoveryAcceptedKinds, getRelayDiscoveryAttributes, getRelayDiscoveryGeohash, getRelayDiscoveryNetworkType, getRelayDiscoveryRequirements, getRelayDiscoveryRTT, getRelayDiscoverySupportedNIPs, getRelayDiscoveryTopics, getRelayDiscoveryURL, isValidRelayDiscovery, } from "../helpers/relay-discovery.js";
2
+ import { EventCast } from "./cast.js";
3
+ /** Cast a kind 30166 event to a RelayDiscovery */
4
+ export class RelayDiscovery extends EventCast {
5
+ constructor(event, store) {
6
+ if (!isValidRelayDiscovery(event))
7
+ throw new Error("Invalid relay discovery event");
8
+ super(event, store);
9
+ }
10
+ /** Gets the relay URL from this discovery event (from the `d` tag) */
11
+ get url() {
12
+ return getRelayDiscoveryURL(this.event);
13
+ }
14
+ /** Gets the round-trip time (RTT) for opening the relay connection (in milliseconds) */
15
+ get rttOpen() {
16
+ return getRelayDiscoveryRTT(this.event, "open");
17
+ }
18
+ /** Gets the round-trip time (RTT) for reading from the relay (in milliseconds) */
19
+ get rttRead() {
20
+ return getRelayDiscoveryRTT(this.event, "read");
21
+ }
22
+ /** Gets the round-trip time (RTT) for writing to the relay (in milliseconds) */
23
+ get rttWrite() {
24
+ return getRelayDiscoveryRTT(this.event, "write");
25
+ }
26
+ /** Gets the network type from this discovery event (clearnet, tor, i2p, loki) */
27
+ get networkType() {
28
+ return getRelayDiscoveryNetworkType(this.event);
29
+ }
30
+ /** Gets all relay attributes from this discovery event (from `W` tags) */
31
+ get attributes() {
32
+ return getRelayDiscoveryAttributes(this.event);
33
+ }
34
+ /** Gets all supported NIPs from this discovery event (from `N` tags) */
35
+ get supportedNIPs() {
36
+ return getRelayDiscoverySupportedNIPs(this.event);
37
+ }
38
+ /** Gets all requirements from this discovery event (from `R` tags) */
39
+ get requirements() {
40
+ return getRelayDiscoveryRequirements(this.event);
41
+ }
42
+ /** Gets all topics from this discovery event (from `t` tags) */
43
+ get topics() {
44
+ return getRelayDiscoveryTopics(this.event);
45
+ }
46
+ /** Gets all accepted and unaccepted kinds from this discovery event (from `k` tags) */
47
+ get acceptedKinds() {
48
+ return getRelayDiscoveryAcceptedKinds(this.event);
49
+ }
50
+ /** Gets the geohash from this discovery event (NIP-52 geohash) */
51
+ get geohash() {
52
+ return getRelayDiscoveryGeohash(this.event);
53
+ }
54
+ }