applesauce-core 2.2.0 → 3.0.0

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 (57) hide show
  1. package/dist/event-store/event-set.d.ts +2 -0
  2. package/dist/event-store/event-set.js +15 -3
  3. package/dist/event-store/event-store.d.ts +54 -24
  4. package/dist/event-store/event-store.js +139 -47
  5. package/dist/event-store/interface.d.ts +36 -18
  6. package/dist/helpers/calendar-event.d.ts +36 -0
  7. package/dist/helpers/calendar-event.js +110 -0
  8. package/dist/helpers/calendar-rsvp.d.ts +15 -0
  9. package/dist/helpers/calendar-rsvp.js +38 -0
  10. package/dist/helpers/calendar.d.ts +6 -0
  11. package/dist/helpers/calendar.js +11 -0
  12. package/dist/helpers/encrypted-content-cache.js +16 -12
  13. package/dist/helpers/encrypted-content.d.ts +18 -10
  14. package/dist/helpers/encrypted-content.js +11 -3
  15. package/dist/helpers/event-cache.d.ts +15 -0
  16. package/dist/helpers/event-cache.js +32 -0
  17. package/dist/helpers/event.d.ts +1 -1
  18. package/dist/helpers/event.js +1 -1
  19. package/dist/helpers/expiration.js +1 -2
  20. package/dist/helpers/gift-wraps.d.ts +33 -13
  21. package/dist/helpers/gift-wraps.js +154 -58
  22. package/dist/helpers/hidden-content.d.ts +3 -3
  23. package/dist/helpers/hidden-content.js +2 -2
  24. package/dist/helpers/hidden-tags.d.ts +5 -10
  25. package/dist/helpers/hidden-tags.js +3 -3
  26. package/dist/helpers/highlight.d.ts +45 -0
  27. package/dist/helpers/highlight.js +76 -0
  28. package/dist/helpers/index.d.ts +8 -0
  29. package/dist/helpers/index.js +8 -0
  30. package/dist/helpers/pointers.js +1 -1
  31. package/dist/helpers/poll.d.ts +46 -0
  32. package/dist/helpers/poll.js +78 -0
  33. package/dist/helpers/stream-chat.d.ts +4 -0
  34. package/dist/helpers/stream-chat.js +9 -0
  35. package/dist/helpers/stream.d.ts +31 -0
  36. package/dist/helpers/stream.js +81 -0
  37. package/dist/logger.d.ts +1 -0
  38. package/dist/logger.js +1 -0
  39. package/dist/models/blossom.d.ts +2 -1
  40. package/dist/models/blossom.js +4 -2
  41. package/dist/models/calendar.d.ts +6 -0
  42. package/dist/models/calendar.js +15 -0
  43. package/dist/models/common.d.ts +14 -10
  44. package/dist/models/common.js +47 -76
  45. package/dist/models/contacts.d.ts +1 -1
  46. package/dist/models/contacts.js +4 -2
  47. package/dist/models/index.d.ts +1 -0
  48. package/dist/models/index.js +1 -0
  49. package/dist/models/mailboxes.d.ts +2 -1
  50. package/dist/models/mailboxes.js +4 -2
  51. package/dist/models/mutes.d.ts +3 -2
  52. package/dist/models/mutes.js +4 -2
  53. package/dist/models/profile.d.ts +2 -1
  54. package/dist/models/profile.js +4 -2
  55. package/package.json +1 -1
  56. package/dist/event-store/common.d.ts +0 -1
  57. package/dist/event-store/common.js +0 -1
@@ -1,40 +1,60 @@
1
- import { defer, distinctUntilChanged, EMPTY, endWith, filter, finalize, from, map, merge, mergeWith, of, repeat, scan, takeUntil, tap, } from "rxjs";
1
+ import { combineLatest, defer, distinctUntilChanged, EMPTY, endWith, filter, finalize, from, map, merge, mergeWith, of, repeat, scan, takeUntil, tap, } from "rxjs";
2
+ import { insertEventIntoDescendingList } from "nostr-tools/utils";
2
3
  import { createReplaceableAddress, getEventUID, getReplaceableIdentifier, isReplaceable, matchFilters, } from "../helpers/index.js";
3
4
  import { claimEvents } from "../observable/claim-events.js";
4
5
  import { claimLatest } from "../observable/claim-latest.js";
5
- import { insertEventIntoDescendingList } from "nostr-tools/utils";
6
6
  import { withImmediateValueOrDefault } from "../observable/with-immediate-value.js";
7
7
  /** A model that returns a single event or undefined when its removed */
8
- export function EventModel(id) {
8
+ export function EventModel(pointer) {
9
+ if (typeof pointer === "string")
10
+ pointer = { id: pointer };
9
11
  return (events) => merge(
10
12
  // get current event and ignore if there is none
11
13
  defer(() => {
12
- let event = events.getEvent(id);
13
- return event ? of(event) : EMPTY;
14
+ let event = events.getEvent(pointer.id);
15
+ if (event)
16
+ return of(event);
17
+ // If there is a loader, use it to get the event
18
+ if (!events.eventLoader)
19
+ return EMPTY;
20
+ return from(events.eventLoader(pointer)).pipe(filter((e) => !!e));
14
21
  }),
15
- // subscribe to updates
16
- events.insert$.pipe(filter((e) => e.id === id)),
17
- // subscribe to updates
18
- events.updated(id),
22
+ // Listen for new events
23
+ events.insert$.pipe(filter((e) => e.id === pointer.id)),
19
24
  // emit undefined when deleted
20
- events.removed(id).pipe(endWith(undefined))).pipe(
25
+ events.removed(pointer.id).pipe(endWith(undefined))).pipe(
21
26
  // claim all events
22
27
  claimLatest(events),
28
+ // ignore duplicate events
29
+ distinctUntilChanged((a, b) => a?.id === b?.id),
23
30
  // always emit undefined so the observable is synchronous
24
31
  withImmediateValueOrDefault(undefined));
25
32
  }
26
33
  /** A model that returns the latest version of a replaceable event or undefined if its removed */
27
- export function ReplaceableModel(kind, pubkey, d) {
34
+ export function ReplaceableModel(pointer) {
28
35
  return (events) => {
29
36
  let current = undefined;
30
37
  return merge(
31
38
  // lazily get current event
32
39
  defer(() => {
33
- let event = events.getReplaceable(kind, pubkey, d);
34
- return event ? of(event) : EMPTY;
40
+ let event = events.getReplaceable(pointer.kind, pointer.pubkey, pointer.identifier);
41
+ if (event)
42
+ return of(event);
43
+ else if (pointer.identifier !== undefined) {
44
+ if (!events.addressableLoader)
45
+ return EMPTY;
46
+ return from(events.addressableLoader(pointer)).pipe(filter((e) => !!e));
47
+ }
48
+ else {
49
+ if (!events.replaceableLoader)
50
+ return EMPTY;
51
+ return from(events.replaceableLoader(pointer)).pipe(filter((e) => !!e));
52
+ }
35
53
  }),
36
54
  // subscribe to new events
37
- events.insert$.pipe(filter((e) => e.pubkey == pubkey && e.kind === kind && (d !== undefined ? getReplaceableIdentifier(e) === d : true)))).pipe(
55
+ events.insert$.pipe(filter((e) => e.pubkey == pointer.pubkey &&
56
+ e.kind === pointer.kind &&
57
+ (pointer.identifier !== undefined ? getReplaceableIdentifier(e) === pointer.identifier : true)))).pipe(
38
58
  // only update if event is newer
39
59
  distinctUntilChanged((prev, event) => {
40
60
  // are the events the same? i.e. is the prev event older
@@ -108,69 +128,20 @@ export function TimelineModel(filters, includeOldVersion) {
108
128
  finalize(() => seen.clear()));
109
129
  };
110
130
  }
111
- /** A model that returns a multiple events in a map */
131
+ /**
132
+ * A model that returns a multiple events in a map
133
+ * @deprecated use multiple {@link EventModel} instead
134
+ */
112
135
  export function EventsModel(ids) {
113
- return (events) => merge(
114
- // lazily get existing events
115
- defer(() => from(ids.map((id) => events.getEvent(id)))),
116
- // subscribe to new events
117
- events.insert$.pipe(filter((e) => ids.includes(e.id))),
118
- // subscribe to updates
119
- events.update$.pipe(filter((e) => ids.includes(e.id)))).pipe(
120
- // ignore empty messages
121
- filter((e) => !!e),
122
- // claim all events until cleanup
123
- claimEvents(events),
124
- // watch for removed events
125
- mergeWith(events.remove$.pipe(filter((e) => ids.includes(e.id)), map((e) => e.id))),
126
- // merge all events into a directory
127
- scan((dir, event) => {
128
- if (typeof event === "string") {
129
- // delete event by id
130
- const clone = { ...dir };
131
- delete clone[event];
132
- return clone;
133
- }
134
- else {
135
- // add even to directory
136
- return { ...dir, [event.id]: event };
137
- }
138
- }, {}));
136
+ return (events) => combineLatest(Object.fromEntries(ids.map((id) => [id, events.model(EventModel, { id })])));
139
137
  }
140
- /** A model that returns a directory of events by their UID */
138
+ /**
139
+ * A model that returns a directory of events by their UID
140
+ * @deprecated use multiple {@link ReplaceableModel} instead
141
+ */
141
142
  export function ReplaceableSetModel(pointers) {
142
- return (events) => {
143
- const uids = new Set(pointers.map((p) => createReplaceableAddress(p.kind, p.pubkey, p.identifier)));
144
- return merge(
145
- // start with existing events
146
- defer(() => from(pointers.map((p) => events.getReplaceable(p.kind, p.pubkey, p.identifier)))),
147
- // subscribe to new events
148
- events.insert$.pipe(filter((e) => isReplaceable(e.kind) && uids.has(getEventUID(e))))).pipe(
149
- // filter out undefined
150
- filter((e) => !!e),
151
- // claim all events
152
- claimEvents(events),
153
- // convert events to add commands
154
- map((e) => ["add", e]),
155
- // watch for removed events
156
- mergeWith(events.remove$.pipe(filter((e) => isReplaceable(e.kind) && uids.has(getEventUID(e))), map((e) => ["remove", e]))),
157
- // reduce events into directory
158
- scan((dir, [action, event]) => {
159
- const uid = getEventUID(event);
160
- if (action === "add") {
161
- // add event to dir if its newer
162
- if (!dir[uid] || dir[uid].created_at < event.created_at)
163
- return { ...dir, [uid]: event };
164
- }
165
- else if (action === "remove" && dir[uid] === event) {
166
- // remove event from dir
167
- let newDir = { ...dir };
168
- delete newDir[uid];
169
- return newDir;
170
- }
171
- return dir;
172
- }, {}),
173
- // ignore changes that do not modify the directory
174
- distinctUntilChanged());
175
- };
143
+ return (events) => combineLatest(Object.fromEntries(pointers.map((pointer) => [
144
+ createReplaceableAddress(pointer.kind, pointer.pubkey, pointer.identifier),
145
+ events.model(ReplaceableModel, pointer),
146
+ ])));
176
147
  }
@@ -1,7 +1,7 @@
1
1
  import { ProfilePointer } from "nostr-tools/nip19";
2
2
  import { Model } from "../event-store/interface.js";
3
3
  /** A model that returns all contacts for a user */
4
- export declare function ContactsModel(pubkey: string): Model<ProfilePointer[]>;
4
+ export declare function ContactsModel(user: string | ProfilePointer): Model<ProfilePointer[]>;
5
5
  /** A model that returns all public contacts for a user */
6
6
  export declare function PublicContactsModel(pubkey: string): Model<ProfilePointer[] | undefined>;
7
7
  /** A model that returns all hidden contacts for a user */
@@ -3,8 +3,10 @@ import { map } from "rxjs/operators";
3
3
  import { getContacts, getHiddenContacts, getPublicContacts } from "../helpers/contacts.js";
4
4
  import { watchEventUpdates } from "../observable/index.js";
5
5
  /** A model that returns all contacts for a user */
6
- export function ContactsModel(pubkey) {
7
- return (events) => events.replaceable(kinds.Contacts, pubkey).pipe(
6
+ export function ContactsModel(user) {
7
+ if (typeof user === "string")
8
+ user = { pubkey: user };
9
+ return (events) => events.replaceable({ kind: kinds.Contacts, pubkey: user.pubkey, relays: user.relays }).pipe(
8
10
  // listen for event updates (hidden tags unlocked)
9
11
  watchEventUpdates(events),
10
12
  // Get all contacts
@@ -1,5 +1,6 @@
1
1
  export * from "./blossom.js";
2
2
  export * from "./bookmarks.js";
3
+ export * from "./calendar.js";
3
4
  export * from "./channels.js";
4
5
  export * from "./comments.js";
5
6
  export * from "./common.js";
@@ -1,5 +1,6 @@
1
1
  export * from "./blossom.js";
2
2
  export * from "./bookmarks.js";
3
+ export * from "./calendar.js";
3
4
  export * from "./channels.js";
4
5
  export * from "./comments.js";
5
6
  export * from "./common.js";
@@ -1,6 +1,7 @@
1
+ import { ProfilePointer } from "nostr-tools/nip19";
1
2
  import { Model } from "../event-store/interface.js";
2
3
  /** A model that gets and parses the inbox and outbox relays for a pubkey */
3
- export declare function MailboxesModel(pubkey: string): Model<{
4
+ export declare function MailboxesModel(user: string | ProfilePointer): Model<{
4
5
  inboxes: string[];
5
6
  outboxes: string[];
6
7
  } | undefined>;
@@ -2,8 +2,10 @@ import { kinds } from "nostr-tools";
2
2
  import { map } from "rxjs/operators";
3
3
  import { getInboxes, getOutboxes } from "../helpers/mailboxes.js";
4
4
  /** A model that gets and parses the inbox and outbox relays for a pubkey */
5
- export function MailboxesModel(pubkey) {
6
- return (events) => events.replaceable(kinds.RelayList, pubkey).pipe(map((event) => event && {
5
+ export function MailboxesModel(user) {
6
+ if (typeof user === "string")
7
+ user = { pubkey: user };
8
+ return (events) => events.replaceable({ kind: kinds.RelayList, pubkey: user.pubkey, relays: user.relays }).pipe(map((event) => event && {
7
9
  inboxes: getInboxes(event),
8
10
  outboxes: getOutboxes(event),
9
11
  }));
@@ -1,7 +1,8 @@
1
- import { Mutes } from "../helpers/mutes.js";
1
+ import { ProfilePointer } from "nostr-tools/nip19";
2
2
  import { Model } from "../event-store/interface.js";
3
+ import { Mutes } from "../helpers/mutes.js";
3
4
  /** A model that returns all a users muted things */
4
- export declare function MuteModel(pubkey: string): Model<Mutes | undefined>;
5
+ export declare function MuteModel(user: string | ProfilePointer): Model<Mutes | undefined>;
5
6
  /** A model that returns all a users public muted things */
6
7
  export declare function PublicMuteModel(pubkey: string): Model<Mutes | undefined>;
7
8
  /** A model that returns all a users hidden muted things */
@@ -3,8 +3,10 @@ import { map } from "rxjs/operators";
3
3
  import { getHiddenMutedThings, getMutedThings, getPublicMutedThings } from "../helpers/mutes.js";
4
4
  import { watchEventUpdates } from "../observable/watch-event-updates.js";
5
5
  /** A model that returns all a users muted things */
6
- export function MuteModel(pubkey) {
7
- return (events) => events.replaceable(kinds.Mutelist, pubkey).pipe(
6
+ export function MuteModel(user) {
7
+ if (typeof user === "string")
8
+ user = { pubkey: user };
9
+ return (events) => events.replaceable({ kind: kinds.Mutelist, pubkey: user.pubkey, relays: user.relays }).pipe(
8
10
  // listen for event updates (hidden tags unlocked)
9
11
  watchEventUpdates(events),
10
12
  // Get all muted things
@@ -1,4 +1,5 @@
1
1
  import { Model } from "../event-store/interface.js";
2
2
  import { ProfileContent } from "../helpers/profile.js";
3
+ import { ProfilePointer } from "nostr-tools/nip19";
3
4
  /** A model that gets and parses the kind 0 metadata for a pubkey */
4
- export declare function ProfileModel(pubkey: string): Model<ProfileContent | undefined>;
5
+ export declare function ProfileModel(user: string | ProfilePointer): Model<ProfileContent | undefined>;
@@ -3,8 +3,10 @@ import { filter, map } from "rxjs/operators";
3
3
  import { getProfileContent, isValidProfile } from "../helpers/profile.js";
4
4
  import { withImmediateValueOrDefault } from "../observable/with-immediate-value.js";
5
5
  /** A model that gets and parses the kind 0 metadata for a pubkey */
6
- export function ProfileModel(pubkey) {
7
- return (events) => events.replaceable(kinds.Metadata, pubkey).pipe(
6
+ export function ProfileModel(user) {
7
+ if (typeof user === "string")
8
+ user = { pubkey: user };
9
+ return (events) => events.replaceable({ kind: kinds.Metadata, pubkey: user.pubkey, relays: user.relays }).pipe(
8
10
  // Filter out invalid profile events
9
11
  filter(isValidProfile),
10
12
  // Parse the profile event into a ProfileContent
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "applesauce-core",
3
- "version": "2.2.0",
3
+ "version": "3.0.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};