applesauce-common 0.0.0-next-20251209200210 → 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.
- package/README.md +45 -4
- package/dist/blueprints/__register__.d.ts +7 -0
- package/dist/blueprints/__register__.js +8 -0
- package/dist/blueprints/comment.d.ts +3 -2
- package/dist/blueprints/group-mangement.d.ts +25 -0
- package/dist/blueprints/group-mangement.js +40 -0
- package/dist/blueprints/index.d.ts +1 -0
- package/dist/blueprints/index.js +1 -0
- package/dist/blueprints/torrent.d.ts +7 -0
- package/dist/blueprints/torrent.js +5 -1
- package/dist/casts/article.d.ts +19 -0
- package/dist/casts/article.js +47 -0
- package/dist/casts/bookmarks.d.ts +35 -0
- package/dist/casts/bookmarks.js +91 -0
- package/dist/casts/cast.d.ts +30 -0
- package/dist/casts/cast.js +67 -0
- package/dist/casts/comment.d.ts +18 -0
- package/dist/casts/comment.js +54 -0
- package/dist/casts/groups.d.ts +19 -0
- package/dist/casts/groups.js +43 -0
- package/dist/casts/index.d.ts +18 -0
- package/dist/casts/index.js +18 -0
- package/dist/casts/mutes.d.ts +23 -0
- package/dist/casts/mutes.js +54 -0
- package/dist/casts/note.d.ts +25 -0
- package/dist/casts/note.js +76 -0
- package/dist/casts/profile.d.ts +24 -0
- package/dist/casts/profile.js +52 -0
- package/dist/casts/reaction.d.ts +17 -0
- package/dist/casts/reaction.js +46 -0
- package/dist/casts/relay-discovery.d.ts +29 -0
- package/dist/casts/relay-discovery.js +54 -0
- package/dist/casts/relay-lists.d.ts +33 -0
- package/dist/casts/relay-lists.js +72 -0
- package/dist/casts/relay-monitor.d.ts +21 -0
- package/dist/casts/relay-monitor.js +41 -0
- package/dist/casts/report.d.ts +31 -0
- package/dist/casts/report.js +74 -0
- package/dist/casts/share.d.ts +15 -0
- package/dist/casts/share.js +34 -0
- package/dist/casts/stream.d.ts +43 -0
- package/dist/casts/stream.js +116 -0
- package/dist/casts/torrent.d.ts +31 -0
- package/dist/casts/torrent.js +62 -0
- package/dist/casts/user.d.ts +40 -0
- package/dist/casts/user.js +181 -0
- package/dist/casts/zap.d.ts +17 -0
- package/dist/casts/zap.js +47 -0
- package/dist/helpers/bookmark.d.ts +18 -17
- package/dist/helpers/bookmark.js +36 -49
- package/dist/helpers/calendar-event.d.ts +7 -1
- package/dist/helpers/calendar-event.js +8 -10
- package/dist/helpers/channels.d.ts +1 -1
- package/dist/helpers/channels.js +5 -8
- package/dist/helpers/comment.d.ts +3 -1
- package/dist/helpers/comment.js +12 -2
- package/dist/helpers/encrypted-content-cache.js +23 -25
- package/dist/helpers/external-id.d.ts +32 -0
- package/dist/helpers/external-id.js +85 -0
- package/dist/helpers/file-metadata.d.ts +1 -4
- package/dist/helpers/file-metadata.js +1 -4
- package/dist/helpers/gift-wrap.js +11 -5
- package/dist/helpers/groups.d.ts +129 -7
- package/dist/helpers/groups.js +317 -15
- package/dist/helpers/index.d.ts +1 -1
- package/dist/helpers/index.js +1 -1
- package/dist/helpers/lists.d.ts +0 -1
- package/dist/helpers/lists.js +4 -5
- package/dist/helpers/mute.d.ts +14 -11
- package/dist/helpers/mute.js +9 -4
- package/dist/helpers/relay-list.d.ts +14 -0
- package/dist/helpers/relay-list.js +18 -0
- package/dist/helpers/reports.d.ts +4 -1
- package/dist/helpers/reports.js +14 -10
- package/dist/helpers/stream-chat.d.ts +4 -1
- package/dist/helpers/stream-chat.js +4 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/models/__register__.d.ts +5 -0
- package/dist/models/__register__.js +6 -0
- package/dist/models/blossom.d.ts +2 -2
- package/dist/models/blossom.js +1 -1
- package/dist/models/bookmarks.d.ts +3 -5
- package/dist/models/bookmarks.js +2 -10
- package/dist/models/channels.js +3 -9
- package/dist/models/comments.d.ts +3 -2
- package/dist/models/comments.js +19 -1
- package/dist/models/index.d.ts +3 -1
- package/dist/models/index.js +4 -1
- package/dist/models/mutes.d.ts +5 -5
- package/dist/models/{relays.js → relay-lists.js} +2 -1
- package/dist/models/shares.d.ts +3 -0
- package/dist/models/shares.js +5 -0
- package/dist/models/thread.js +30 -24
- package/dist/observable/cast-stream.d.ts +8 -0
- package/dist/observable/cast-stream.js +29 -0
- package/dist/observable/chainable.d.ts +50 -0
- package/dist/observable/chainable.js +79 -0
- package/dist/observable/index.d.ts +2 -0
- package/dist/observable/index.js +2 -0
- package/dist/operations/comment.d.ts +3 -2
- package/dist/operations/comment.js +19 -5
- package/dist/operations/group.d.ts +14 -1
- package/dist/operations/group.js +42 -4
- package/dist/operations/index.d.ts +1 -1
- package/dist/operations/index.js +1 -1
- package/dist/operations/tag/bookmarks.d.ts +3 -2
- package/dist/operations/tag/bookmarks.js +34 -14
- package/dist/operations/torrent.d.ts +2 -0
- package/dist/operations/torrent.js +4 -0
- package/dist/register.d.ts +2 -11
- package/dist/register.js +2 -11
- package/package.json +12 -2
- package/dist/helpers/mailboxes.d.ts +0 -7
- package/dist/helpers/mailboxes.js +0 -49
- /package/dist/models/{relays.d.ts → relay-lists.d.ts} +0 -0
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
|
|
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
|
|
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
|
|
@@ -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
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
2
|
+
import { GroupMetadata, GroupPointer } from "../helpers/groups.js";
|
|
3
|
+
/** Options for group membership blueprints that support previous references */
|
|
4
|
+
export type GroupMembershipOptions = {
|
|
5
|
+
previous?: NostrEvent[];
|
|
6
|
+
reason?: string;
|
|
7
|
+
};
|
|
8
|
+
/** A blueprint for a NIP-29 join request (kind 9021) */
|
|
9
|
+
export declare function GroupJoinRequestBlueprint(group: GroupPointer, reason?: string, inviteCode?: string): import("applesauce-core/event-factory").EventBlueprint;
|
|
10
|
+
/** A blueprint for a NIP-29 leave request (kind 9022) */
|
|
11
|
+
export declare function GroupLeaveRequestBlueprint(group: GroupPointer, reason?: string): import("applesauce-core/event-factory").EventBlueprint;
|
|
12
|
+
/** A blueprint for a NIP-29 put user moderation event (kind 9000) */
|
|
13
|
+
export declare function PutUserBlueprint(group: GroupPointer, pubkey: string, roles?: string[], options?: GroupMembershipOptions): import("applesauce-core/event-factory").EventBlueprint;
|
|
14
|
+
/** A blueprint for a NIP-29 remove user moderation event (kind 9001) */
|
|
15
|
+
export declare function GroupRemoveUserBlueprint(group: GroupPointer, pubkey: string, options?: GroupMembershipOptions): import("applesauce-core/event-factory").EventBlueprint;
|
|
16
|
+
/** A blueprint for a NIP-29 edit metadata moderation event (kind 9002) */
|
|
17
|
+
export declare function GroupEditMetadataBlueprint(group: GroupPointer, fields: Partial<GroupMetadata>, options?: GroupMembershipOptions): import("applesauce-core/event-factory").EventBlueprint;
|
|
18
|
+
/** A blueprint for a NIP-29 delete event moderation event (kind 9005) */
|
|
19
|
+
export declare function GroupDeleteEventBlueprint(group: GroupPointer, eventId: string, options?: GroupMembershipOptions): import("applesauce-core/event-factory").EventBlueprint;
|
|
20
|
+
/** A blueprint for a NIP-29 create group moderation event (kind 9007) */
|
|
21
|
+
export declare function GroupCreateGroupBlueprint(group: GroupPointer, options?: GroupMembershipOptions): import("applesauce-core/event-factory").EventBlueprint;
|
|
22
|
+
/** A blueprint for a NIP-29 delete group moderation event (kind 9008) */
|
|
23
|
+
export declare function GroupDeleteGroupBlueprint(group: GroupPointer, options?: GroupMembershipOptions): import("applesauce-core/event-factory").EventBlueprint;
|
|
24
|
+
/** A blueprint for a NIP-29 create invite moderation event (kind 9009) */
|
|
25
|
+
export declare function GroupCreateInviteBlueprint(group: GroupPointer, options?: GroupMembershipOptions): import("applesauce-core/event-factory").EventBlueprint;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { blueprint } from "applesauce-core/event-factory";
|
|
2
|
+
import { setContent } from "applesauce-core/operations/content";
|
|
3
|
+
import { CREATE_GROUP_KIND, CREATE_INVITE_KIND, DELETE_EVENT_KIND, DELETE_GROUP_KIND, EDIT_METADATA_KIND, JOIN_REQUEST_KIND, LEAVE_REQUEST_KIND, PUT_USER_KIND, REMOVE_USER_KIND, } from "../helpers/groups.js";
|
|
4
|
+
import { addPreviousRefs, setDeleteEventTags, setEditMetadataTags, setGroupPointer, setJoinRequestTags, setLeaveRequestTags, setPutUserTags, setRemoveUserTags, } from "../operations/group.js";
|
|
5
|
+
/** A blueprint for a NIP-29 join request (kind 9021) */
|
|
6
|
+
export function GroupJoinRequestBlueprint(group, reason, inviteCode) {
|
|
7
|
+
return blueprint(JOIN_REQUEST_KIND, setGroupPointer(group), setJoinRequestTags(group, inviteCode), reason ? setContent(reason) : undefined);
|
|
8
|
+
}
|
|
9
|
+
/** A blueprint for a NIP-29 leave request (kind 9022) */
|
|
10
|
+
export function GroupLeaveRequestBlueprint(group, reason) {
|
|
11
|
+
return blueprint(LEAVE_REQUEST_KIND, setGroupPointer(group), setLeaveRequestTags(group), reason ? setContent(reason) : undefined);
|
|
12
|
+
}
|
|
13
|
+
/** A blueprint for a NIP-29 put user moderation event (kind 9000) */
|
|
14
|
+
export function PutUserBlueprint(group, pubkey, roles, options) {
|
|
15
|
+
return blueprint(PUT_USER_KIND, setGroupPointer(group), setPutUserTags(pubkey, roles), options?.previous && options.previous.length > 0 ? addPreviousRefs(options.previous) : undefined, options?.reason ? setContent(options.reason) : undefined);
|
|
16
|
+
}
|
|
17
|
+
/** A blueprint for a NIP-29 remove user moderation event (kind 9001) */
|
|
18
|
+
export function GroupRemoveUserBlueprint(group, pubkey, options) {
|
|
19
|
+
return blueprint(REMOVE_USER_KIND, setGroupPointer(group), setRemoveUserTags(pubkey), options?.previous && options.previous.length > 0 ? addPreviousRefs(options.previous) : undefined, options?.reason ? setContent(options.reason) : undefined);
|
|
20
|
+
}
|
|
21
|
+
/** A blueprint for a NIP-29 edit metadata moderation event (kind 9002) */
|
|
22
|
+
export function GroupEditMetadataBlueprint(group, fields, options) {
|
|
23
|
+
return blueprint(EDIT_METADATA_KIND, setGroupPointer(group), setEditMetadataTags(fields), options?.previous && options.previous.length > 0 ? addPreviousRefs(options.previous) : undefined, options?.reason ? setContent(options.reason) : undefined);
|
|
24
|
+
}
|
|
25
|
+
/** A blueprint for a NIP-29 delete event moderation event (kind 9005) */
|
|
26
|
+
export function GroupDeleteEventBlueprint(group, eventId, options) {
|
|
27
|
+
return blueprint(DELETE_EVENT_KIND, setGroupPointer(group), setDeleteEventTags(eventId), options?.previous && options.previous.length > 0 ? addPreviousRefs(options.previous) : undefined, options?.reason ? setContent(options.reason) : undefined);
|
|
28
|
+
}
|
|
29
|
+
/** A blueprint for a NIP-29 create group moderation event (kind 9007) */
|
|
30
|
+
export function GroupCreateGroupBlueprint(group, options) {
|
|
31
|
+
return blueprint(CREATE_GROUP_KIND, setGroupPointer(group), options?.previous && options.previous.length > 0 ? addPreviousRefs(options.previous) : undefined, options?.reason ? setContent(options.reason) : undefined);
|
|
32
|
+
}
|
|
33
|
+
/** A blueprint for a NIP-29 delete group moderation event (kind 9008) */
|
|
34
|
+
export function GroupDeleteGroupBlueprint(group, options) {
|
|
35
|
+
return blueprint(DELETE_GROUP_KIND, setGroupPointer(group), options?.previous && options.previous.length > 0 ? addPreviousRefs(options.previous) : undefined, options?.reason ? setContent(options.reason) : undefined);
|
|
36
|
+
}
|
|
37
|
+
/** A blueprint for a NIP-29 create invite moderation event (kind 9009) */
|
|
38
|
+
export function GroupCreateInviteBlueprint(group, options) {
|
|
39
|
+
return blueprint(CREATE_INVITE_KIND, setGroupPointer(group), options?.previous && options.previous.length > 0 ? addPreviousRefs(options.previous) : undefined, options?.reason ? setContent(options.reason) : undefined);
|
|
40
|
+
}
|
|
@@ -7,6 +7,7 @@ export * from "./file-metadata.js";
|
|
|
7
7
|
export * from "./follow-set.js";
|
|
8
8
|
export * from "./gift-wrap.js";
|
|
9
9
|
export * from "./group.js";
|
|
10
|
+
export * from "./group-mangement.js";
|
|
10
11
|
export * from "./delete.js";
|
|
11
12
|
export * from "./highlight.js";
|
|
12
13
|
export * from "./legacy-message.js";
|
package/dist/blueprints/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./file-metadata.js";
|
|
|
7
7
|
export * from "./follow-set.js";
|
|
8
8
|
export * from "./gift-wrap.js";
|
|
9
9
|
export * from "./group.js";
|
|
10
|
+
export * from "./group-mangement.js";
|
|
10
11
|
export * from "./delete.js";
|
|
11
12
|
export * from "./highlight.js";
|
|
12
13
|
export * from "./legacy-message.js";
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NostrEvent } from "applesauce-core/helpers";
|
|
2
|
+
import { ArticleEvent } from "../helpers/article.js";
|
|
3
|
+
import { CastRefEventStore, EventCast } from "./cast.js";
|
|
4
|
+
import { Reaction } from "./reaction.js";
|
|
5
|
+
export declare class Article extends EventCast<ArticleEvent> {
|
|
6
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
7
|
+
get title(): string;
|
|
8
|
+
get image(): string | undefined;
|
|
9
|
+
get summary(): string | undefined;
|
|
10
|
+
get published(): number;
|
|
11
|
+
get publishedDate(): Date;
|
|
12
|
+
get pointer(): import("nostr-tools/nip19").AddressPointer;
|
|
13
|
+
/** An observable of the address with relay hints from the authors outboxes */
|
|
14
|
+
get pointer$(): import("applesauce-core").Observable<import("nostr-tools/nip19").AddressPointer>;
|
|
15
|
+
get address(): `naddr1${string}`;
|
|
16
|
+
/** An observable of the address with relay hints from the authors outboxes */
|
|
17
|
+
get address$(): import("applesauce-core").Observable<`naddr1${string}`>;
|
|
18
|
+
get reactions$(): import("../observable/chainable.js").ChainableObservable<Reaction[]>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { withImmediateValueOrDefault } from "applesauce-core";
|
|
2
|
+
import { addRelayHintsToPointer, getAddressPointerForEvent, naddrEncode } from "applesauce-core/helpers";
|
|
3
|
+
import { map } from "rxjs";
|
|
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";
|
|
7
|
+
import { EventCast } from "./cast.js";
|
|
8
|
+
import { Reaction } from "./reaction.js";
|
|
9
|
+
export class Article extends EventCast {
|
|
10
|
+
constructor(event, store) {
|
|
11
|
+
if (!isValidArticle(event))
|
|
12
|
+
throw new Error("Invalid article");
|
|
13
|
+
super(event, store);
|
|
14
|
+
}
|
|
15
|
+
get title() {
|
|
16
|
+
return getArticleTitle(this.event);
|
|
17
|
+
}
|
|
18
|
+
get image() {
|
|
19
|
+
return getArticleImage(this.event);
|
|
20
|
+
}
|
|
21
|
+
get summary() {
|
|
22
|
+
return getArticleSummary(this.event);
|
|
23
|
+
}
|
|
24
|
+
get published() {
|
|
25
|
+
return getArticlePublished(this.event);
|
|
26
|
+
}
|
|
27
|
+
get publishedDate() {
|
|
28
|
+
return new Date(this.published * 1000);
|
|
29
|
+
}
|
|
30
|
+
get pointer() {
|
|
31
|
+
return getAddressPointerForEvent(this.event);
|
|
32
|
+
}
|
|
33
|
+
/** An observable of the address with relay hints from the authors outboxes */
|
|
34
|
+
get pointer$() {
|
|
35
|
+
return this.author.outboxes$.pipe(withImmediateValueOrDefault(undefined), map((outboxes) => (outboxes ? addRelayHintsToPointer(this.pointer, outboxes.slice(0, 3)) : this.pointer)));
|
|
36
|
+
}
|
|
37
|
+
get address() {
|
|
38
|
+
return naddrEncode(this.pointer);
|
|
39
|
+
}
|
|
40
|
+
/** An observable of the address with relay hints from the authors outboxes */
|
|
41
|
+
get address$() {
|
|
42
|
+
return this.pointer$.pipe(map((pointer) => naddrEncode(pointer)));
|
|
43
|
+
}
|
|
44
|
+
get reactions$() {
|
|
45
|
+
return this.$$ref("reactions$", (store) => store.model(ReactionsModel, this.event).pipe(castTimelineStream(Reaction, store)));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { HiddenContentSigner, NostrEvent } from "applesauce-core/helpers";
|
|
2
|
+
import { BookmarkListEvent, BookmarkSetEvent } from "../helpers/bookmark.js";
|
|
3
|
+
import { Article } from "./article.js";
|
|
4
|
+
import { CastRefEventStore, EventCast } from "./cast.js";
|
|
5
|
+
import { Note } from "./note.js";
|
|
6
|
+
/** Base class for bookmarks lists and sets */
|
|
7
|
+
declare class BookmarksListBase<T extends BookmarkListEvent | BookmarkSetEvent> extends EventCast<T> {
|
|
8
|
+
constructor(event: T, store: CastRefEventStore);
|
|
9
|
+
get bookmarks(): import("../helpers/bookmark.js").BookmarkPointer[];
|
|
10
|
+
get articles(): import("nostr-tools/nip19").AddressPointer[];
|
|
11
|
+
get notes(): import("nostr-tools/nip19").EventPointer[];
|
|
12
|
+
get notes$(): import("../observable/chainable.js").ChainableObservable<Note[]>;
|
|
13
|
+
get articles$(): import("../observable/chainable.js").ChainableObservable<Article[]>;
|
|
14
|
+
/** Get the unlocked hidden bookmarks */
|
|
15
|
+
get hidden(): import("../helpers/bookmark.js").BookmarkPointer[] | undefined;
|
|
16
|
+
/** An observable that updates when hidden bookmarks are unlocked */
|
|
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
|
+
/** Whether the bookmark set has hidden bookmarks */
|
|
21
|
+
get hasHidden(): boolean;
|
|
22
|
+
/** Whether the bookmark set is unlocked */
|
|
23
|
+
get unlocked(): boolean;
|
|
24
|
+
/** Unlocks the hidden bookmarks on the bookmark set */
|
|
25
|
+
unlock(signer: HiddenContentSigner): Promise<import("../helpers/bookmark.js").BookmarkPointer[]>;
|
|
26
|
+
}
|
|
27
|
+
/** A class for bookmarks lists (kind 10003) */
|
|
28
|
+
export declare class BookmarksList extends BookmarksListBase<BookmarkListEvent> {
|
|
29
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
30
|
+
}
|
|
31
|
+
/** A class for bookmarks sets (kind 30003) */
|
|
32
|
+
export declare class BookmarksSet extends BookmarksListBase<BookmarkSetEvent> {
|
|
33
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { hasHiddenContent, isAddressPointer, isEventPointer, } from "applesauce-core/helpers";
|
|
2
|
+
import { watchEventUpdates } from "applesauce-core/observable";
|
|
3
|
+
import { combineLatest, map, of, switchMap } from "rxjs";
|
|
4
|
+
import { getBookmarks, getHiddenBookmarks, isHiddenBookmarksUnlocked, isValidBookmarkList, isValidBookmarkSet, unlockHiddenBookmarks, } from "../helpers/bookmark.js";
|
|
5
|
+
import { castTimelineStream } from "../observable/cast-stream.js";
|
|
6
|
+
import { Article } from "./article.js";
|
|
7
|
+
import { EventCast } from "./cast.js";
|
|
8
|
+
import { Note } from "./note.js";
|
|
9
|
+
/** Base class for bookmarks lists and sets */
|
|
10
|
+
class BookmarksListBase extends EventCast {
|
|
11
|
+
constructor(event, store) {
|
|
12
|
+
if (!isValidBookmarkList(event) && !isValidBookmarkSet(event))
|
|
13
|
+
throw new Error("Invalid bookmark list or set");
|
|
14
|
+
super(event, store);
|
|
15
|
+
}
|
|
16
|
+
get bookmarks() {
|
|
17
|
+
return getBookmarks(this.event);
|
|
18
|
+
}
|
|
19
|
+
get articles() {
|
|
20
|
+
return this.bookmarks.filter((pointer) => isAddressPointer(pointer));
|
|
21
|
+
}
|
|
22
|
+
get notes() {
|
|
23
|
+
return this.bookmarks.filter((pointer) => isEventPointer(pointer));
|
|
24
|
+
}
|
|
25
|
+
get notes$() {
|
|
26
|
+
return this.$$ref("notes$", (store) => combineLatest(this.notes.map((pointer) => store.event(pointer))).pipe(map((arr) => arr.filter((e) => !!e)), castTimelineStream(Note, store)));
|
|
27
|
+
}
|
|
28
|
+
get articles$() {
|
|
29
|
+
return this.$$ref("articles$", (store) => combineLatest(this.articles.map((pointer) => store.replaceable(pointer))).pipe(map((arr) => arr.filter((e) => !!e)), castTimelineStream(Article, store)));
|
|
30
|
+
}
|
|
31
|
+
/** Get the unlocked hidden bookmarks */
|
|
32
|
+
get hidden() {
|
|
33
|
+
return getHiddenBookmarks(this.event);
|
|
34
|
+
}
|
|
35
|
+
/** An observable that updates when hidden bookmarks are unlocked */
|
|
36
|
+
get hidden$() {
|
|
37
|
+
return this.$$ref("hidden$", (store) => of(this.event).pipe(
|
|
38
|
+
// Watch for event updates
|
|
39
|
+
watchEventUpdates(store),
|
|
40
|
+
// Get hidden bookmarks
|
|
41
|
+
map((event) => event && getHiddenBookmarks(event))));
|
|
42
|
+
}
|
|
43
|
+
get hiddenNotes$() {
|
|
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
|
+
})));
|
|
52
|
+
}
|
|
53
|
+
get hiddenArticles$() {
|
|
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
|
+
})));
|
|
62
|
+
}
|
|
63
|
+
/** Whether the bookmark set has hidden bookmarks */
|
|
64
|
+
get hasHidden() {
|
|
65
|
+
return hasHiddenContent(this.event);
|
|
66
|
+
}
|
|
67
|
+
/** Whether the bookmark set is unlocked */
|
|
68
|
+
get unlocked() {
|
|
69
|
+
return isHiddenBookmarksUnlocked(this.event);
|
|
70
|
+
}
|
|
71
|
+
/** Unlocks the hidden bookmarks on the bookmark set */
|
|
72
|
+
async unlock(signer) {
|
|
73
|
+
return unlockHiddenBookmarks(this.event, signer);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** A class for bookmarks lists (kind 10003) */
|
|
77
|
+
export class BookmarksList extends BookmarksListBase {
|
|
78
|
+
constructor(event, store) {
|
|
79
|
+
if (!isValidBookmarkList(event))
|
|
80
|
+
throw new Error("Invalid bookmark list");
|
|
81
|
+
super(event, store);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** A class for bookmarks sets (kind 30003) */
|
|
85
|
+
export class BookmarksSet extends BookmarksListBase {
|
|
86
|
+
constructor(event, store) {
|
|
87
|
+
if (!isValidBookmarkSet(event))
|
|
88
|
+
throw new Error("Invalid bookmark set");
|
|
89
|
+
super(event, store);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { EventModels, IEventStoreStreams, IEventSubscriptions } from "applesauce-core/event-store";
|
|
2
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
3
|
+
import { Observable } from "rxjs";
|
|
4
|
+
import { ChainableObservable } from "../observable/chainable.js";
|
|
5
|
+
/** The type of event store that is passed to cast references */
|
|
6
|
+
export type CastRefEventStore = IEventSubscriptions & EventModels & IEventStoreStreams;
|
|
7
|
+
/** A symbol used to store all the cast instances for a given event */
|
|
8
|
+
export declare const CAST_REF_SYMBOL: unique symbol;
|
|
9
|
+
/** A symbol used to store all the casts for an event */
|
|
10
|
+
export declare const CASTS_SYMBOL: unique symbol;
|
|
11
|
+
/** A class that can be used to cast a Nostr event */
|
|
12
|
+
export type CastConstructor<C extends EventCast<NostrEvent>> = new (event: NostrEvent, store: CastRefEventStore) => C;
|
|
13
|
+
/** Cast a Nostr event to a specific class */
|
|
14
|
+
export declare function castEvent<C extends EventCast<NostrEvent>>(event: NostrEvent, cls: CastConstructor<C>, store?: CastRefEventStore): C;
|
|
15
|
+
/** The base class for all casts */
|
|
16
|
+
export declare class EventCast<T extends NostrEvent = NostrEvent> {
|
|
17
|
+
#private;
|
|
18
|
+
readonly event: T;
|
|
19
|
+
readonly store: CastRefEventStore;
|
|
20
|
+
get id(): string;
|
|
21
|
+
get uid(): string;
|
|
22
|
+
get createdAt(): Date;
|
|
23
|
+
/** Get the {@link User} that authored this event */
|
|
24
|
+
get author(): import("./user.js").User;
|
|
25
|
+
/** Return the set of relays this event was seen on */
|
|
26
|
+
get seen(): Set<string> | undefined;
|
|
27
|
+
constructor(event: T, store: CastRefEventStore);
|
|
28
|
+
/** Internal method for creating a reference */
|
|
29
|
+
protected $$ref<Return extends unknown>(key: string, builder: (store: CastRefEventStore) => Observable<Return>): ChainableObservable<Return>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { getSeenRelays } from "applesauce-core/helpers";
|
|
2
|
+
import { getEventUID, getParentEventStore } from "applesauce-core/helpers/event";
|
|
3
|
+
import { chainable } from "../observable/chainable.js";
|
|
4
|
+
import { castUser } from "./user.js";
|
|
5
|
+
/** A symbol used to store all the cast instances for a given event */
|
|
6
|
+
export const CAST_REF_SYMBOL = Symbol.for("cast-ref");
|
|
7
|
+
/** A symbol used to store all the casts for an event */
|
|
8
|
+
export const CASTS_SYMBOL = Symbol.for("casts");
|
|
9
|
+
/** Cast a Nostr event to a specific class */
|
|
10
|
+
export function castEvent(event, cls, store) {
|
|
11
|
+
const casts = Reflect.get(event, CASTS_SYMBOL);
|
|
12
|
+
// If the event has already been cast to this class, return the existing cast
|
|
13
|
+
const existing = casts?.get(cls);
|
|
14
|
+
if (existing)
|
|
15
|
+
return existing;
|
|
16
|
+
if (!store) {
|
|
17
|
+
store = getParentEventStore(event);
|
|
18
|
+
if (!store)
|
|
19
|
+
throw new Error("Event is not attached to an event store, an event store must be provided");
|
|
20
|
+
}
|
|
21
|
+
// Create a new instance of the class
|
|
22
|
+
const cast = new cls(event, store);
|
|
23
|
+
if (!casts)
|
|
24
|
+
Reflect.set(event, CASTS_SYMBOL, new Map([[cls, cast]]));
|
|
25
|
+
else
|
|
26
|
+
casts.set(cls, cast);
|
|
27
|
+
return cast;
|
|
28
|
+
}
|
|
29
|
+
/** The base class for all casts */
|
|
30
|
+
export class EventCast {
|
|
31
|
+
event;
|
|
32
|
+
store;
|
|
33
|
+
get id() {
|
|
34
|
+
return this.event.id;
|
|
35
|
+
}
|
|
36
|
+
get uid() {
|
|
37
|
+
return getEventUID(this.event);
|
|
38
|
+
}
|
|
39
|
+
get createdAt() {
|
|
40
|
+
return new Date(this.event.created_at * 1000);
|
|
41
|
+
}
|
|
42
|
+
/** Get the {@link User} that authored this event */
|
|
43
|
+
get author() {
|
|
44
|
+
return castUser(this.event, this.store);
|
|
45
|
+
}
|
|
46
|
+
/** Return the set of relays this event was seen on */
|
|
47
|
+
get seen() {
|
|
48
|
+
return getSeenRelays(this.event);
|
|
49
|
+
}
|
|
50
|
+
// Enfore kind check in constructor. this will force child classes to verify the event before calling super()
|
|
51
|
+
constructor(event, store) {
|
|
52
|
+
this.event = event;
|
|
53
|
+
this.store = store;
|
|
54
|
+
}
|
|
55
|
+
/** A cache of observable references */
|
|
56
|
+
#refs = {};
|
|
57
|
+
/** Internal method for creating a reference */
|
|
58
|
+
$$ref(key, builder) {
|
|
59
|
+
// Return cached observable
|
|
60
|
+
if (this.#refs[key])
|
|
61
|
+
return this.#refs[key];
|
|
62
|
+
// Build a new observable and cache it
|
|
63
|
+
const observable = chainable(builder(this.store));
|
|
64
|
+
this.#refs[key] = observable;
|
|
65
|
+
return observable;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NostrEvent } from "applesauce-core/helpers/event";
|
|
2
|
+
import { CommentEvent } from "../helpers/comment.js";
|
|
3
|
+
import { CastRefEventStore, EventCast } from "./cast.js";
|
|
4
|
+
import { Reaction } from "./reaction.js";
|
|
5
|
+
import { Zap } from "./zap.js";
|
|
6
|
+
/** Cast a kind 1111 event to a Comment */
|
|
7
|
+
export declare class Comment extends EventCast<CommentEvent> {
|
|
8
|
+
constructor(event: NostrEvent, store: CastRefEventStore);
|
|
9
|
+
get rootPointer(): import("../helpers/comment.js").CommentPointer;
|
|
10
|
+
get replyPointer(): import("../helpers/comment.js").CommentPointer | null;
|
|
11
|
+
/** Get the event at the root of this thread */
|
|
12
|
+
get root$(): import("../observable/chainable.js").ChainableObservable<import("nostr-tools").Event | undefined>;
|
|
13
|
+
/** Get the event that this comment is replying to */
|
|
14
|
+
get parent$(): import("../observable/chainable.js").ChainableObservable<import("nostr-tools").Event | undefined>;
|
|
15
|
+
get zaps$(): import("../observable/chainable.js").ChainableObservable<Zap[]>;
|
|
16
|
+
get replies$(): import("../observable/chainable.js").ChainableObservable<Comment[]>;
|
|
17
|
+
get reactions$(): import("../observable/chainable.js").ChainableObservable<Reaction[]>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { of } from "rxjs";
|
|
2
|
+
import { getCommentReplyPointer, getCommentRootPointer, isValidComment } from "../helpers/comment.js";
|
|
3
|
+
import { CommentsModel } from "../models/comments.js";
|
|
4
|
+
import { ReactionsModel } from "../models/reactions.js";
|
|
5
|
+
import { EventZapsModel } from "../models/zaps.js";
|
|
6
|
+
import { castTimelineStream } from "../observable/cast-stream.js";
|
|
7
|
+
import { EventCast } from "./cast.js";
|
|
8
|
+
import { Reaction } from "./reaction.js";
|
|
9
|
+
import { Zap } from "./zap.js";
|
|
10
|
+
/** Cast a kind 1111 event to a Comment */
|
|
11
|
+
export class Comment extends EventCast {
|
|
12
|
+
constructor(event, store) {
|
|
13
|
+
if (!isValidComment(event))
|
|
14
|
+
throw new Error("Invalid comment");
|
|
15
|
+
super(event, store);
|
|
16
|
+
}
|
|
17
|
+
get rootPointer() {
|
|
18
|
+
return getCommentRootPointer(this.event);
|
|
19
|
+
}
|
|
20
|
+
get replyPointer() {
|
|
21
|
+
return getCommentReplyPointer(this.event);
|
|
22
|
+
}
|
|
23
|
+
/** Get the event at the root of this thread */
|
|
24
|
+
get root$() {
|
|
25
|
+
return this.$$ref("root$", (store) => {
|
|
26
|
+
const pointer = this.rootPointer;
|
|
27
|
+
if (pointer.type === "event" || pointer.type === "address")
|
|
28
|
+
return store.event(pointer);
|
|
29
|
+
else
|
|
30
|
+
return of(undefined);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/** Get the event that this comment is replying to */
|
|
34
|
+
get parent$() {
|
|
35
|
+
return this.$$ref("parent$", (store) => {
|
|
36
|
+
const pointer = this.replyPointer;
|
|
37
|
+
if (!pointer)
|
|
38
|
+
return of(undefined);
|
|
39
|
+
else if (pointer.type === "event" || pointer.type === "address")
|
|
40
|
+
return store.event(pointer);
|
|
41
|
+
else
|
|
42
|
+
return of(undefined);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
get zaps$() {
|
|
46
|
+
return this.$$ref("zaps$", (store) => store.model(EventZapsModel, this.event).pipe(castTimelineStream(Zap, store)));
|
|
47
|
+
}
|
|
48
|
+
get replies$() {
|
|
49
|
+
return this.$$ref("replies$", (store) => store.model(CommentsModel, this.event).pipe(castTimelineStream(Comment, store)));
|
|
50
|
+
}
|
|
51
|
+
get reactions$() {
|
|
52
|
+
return this.$$ref("reactions$", (store) => store.model(ReactionsModel, this.event).pipe(castTimelineStream(Reaction, store)));
|
|
53
|
+
}
|
|
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
|
+
}
|