applesauce-common 0.0.0-next-20251205152544 → 0.0.0-next-20251220152312

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 (107) hide show
  1. package/dist/blueprints/__register__.d.ts +6 -0
  2. package/dist/blueprints/__register__.js +7 -0
  3. package/dist/blueprints/group-mangement.d.ts +25 -0
  4. package/dist/blueprints/group-mangement.js +40 -0
  5. package/dist/blueprints/index.d.ts +1 -0
  6. package/dist/blueprints/index.js +1 -0
  7. package/dist/casts/article.d.ts +17 -0
  8. package/dist/casts/article.js +41 -0
  9. package/dist/casts/bookmarks.d.ts +35 -0
  10. package/dist/casts/bookmarks.js +79 -0
  11. package/dist/casts/cast.d.ts +30 -0
  12. package/dist/casts/cast.js +67 -0
  13. package/dist/casts/comment.d.ts +16 -0
  14. package/dist/casts/comment.js +49 -0
  15. package/dist/casts/index.d.ts +12 -0
  16. package/dist/casts/index.js +12 -0
  17. package/dist/casts/mutes.d.ts +23 -0
  18. package/dist/casts/mutes.js +54 -0
  19. package/dist/casts/note.d.ts +17 -0
  20. package/dist/casts/note.js +46 -0
  21. package/dist/casts/profile.d.ts +16 -0
  22. package/dist/casts/profile.js +40 -0
  23. package/dist/casts/relay-lists.d.ts +33 -0
  24. package/dist/casts/relay-lists.js +72 -0
  25. package/dist/casts/share.d.ts +13 -0
  26. package/dist/casts/share.js +28 -0
  27. package/dist/casts/stream.d.ts +43 -0
  28. package/dist/casts/stream.js +116 -0
  29. package/dist/casts/user.d.ts +38 -0
  30. package/dist/casts/user.js +169 -0
  31. package/dist/casts/zap.d.ts +17 -0
  32. package/dist/casts/zap.js +47 -0
  33. package/dist/helpers/bookmark.d.ts +18 -17
  34. package/dist/helpers/bookmark.js +36 -45
  35. package/dist/helpers/calendar-event.js +12 -5
  36. package/dist/helpers/calendar-rsvp.js +3 -3
  37. package/dist/helpers/calendar.js +4 -1
  38. package/dist/helpers/comment.js +2 -0
  39. package/dist/helpers/encrypted-content-cache.js +23 -25
  40. package/dist/helpers/gift-wrap.js +11 -5
  41. package/dist/helpers/groups.d.ts +118 -6
  42. package/dist/helpers/groups.js +287 -10
  43. package/dist/helpers/highlight.js +4 -2
  44. package/dist/helpers/index.d.ts +1 -1
  45. package/dist/helpers/index.js +1 -1
  46. package/dist/helpers/lists.d.ts +0 -1
  47. package/dist/helpers/lists.js +15 -13
  48. package/dist/helpers/mute.d.ts +14 -11
  49. package/dist/helpers/mute.js +9 -4
  50. package/dist/helpers/reaction.js +11 -7
  51. package/dist/helpers/relay-list.d.ts +14 -0
  52. package/dist/helpers/relay-list.js +18 -0
  53. package/dist/helpers/share.js +3 -3
  54. package/dist/helpers/stream-chat.d.ts +4 -1
  55. package/dist/helpers/stream-chat.js +5 -2
  56. package/dist/helpers/stream.js +12 -6
  57. package/dist/helpers/user-status.js +15 -6
  58. package/dist/index.d.ts +2 -0
  59. package/dist/index.js +2 -0
  60. package/dist/models/__register__.d.ts +5 -0
  61. package/dist/models/__register__.js +6 -0
  62. package/dist/models/bookmarks.d.ts +3 -5
  63. package/dist/models/bookmarks.js +2 -10
  64. package/dist/models/calendar.js +5 -2
  65. package/dist/models/comments.js +3 -9
  66. package/dist/models/index.d.ts +4 -0
  67. package/dist/models/index.js +5 -0
  68. package/dist/models/mutes.d.ts +5 -5
  69. package/dist/models/pins.js +1 -1
  70. package/dist/models/reactions.d.ts +1 -1
  71. package/dist/models/reactions.js +3 -13
  72. package/dist/models/relay-lists.d.ts +27 -0
  73. package/dist/models/relay-lists.js +37 -0
  74. package/dist/models/shares.d.ts +3 -0
  75. package/dist/models/shares.js +5 -0
  76. package/dist/models/stream.d.ts +4 -0
  77. package/dist/models/stream.js +6 -0
  78. package/dist/models/thread.js +32 -26
  79. package/dist/models/zaps.d.ts +3 -2
  80. package/dist/models/zaps.js +5 -13
  81. package/dist/observable/cast-stream.d.ts +8 -0
  82. package/dist/observable/cast-stream.js +29 -0
  83. package/dist/observable/chainable.d.ts +50 -0
  84. package/dist/observable/chainable.js +79 -0
  85. package/dist/observable/filter-timeline-by-mutes.d.ts +6 -0
  86. package/dist/observable/filter-timeline-by-mutes.js +7 -0
  87. package/dist/observable/index.d.ts +3 -0
  88. package/dist/observable/index.js +3 -0
  89. package/dist/operations/calendar-rsvp.js +2 -0
  90. package/dist/operations/calendar.js +2 -3
  91. package/dist/operations/client.js +2 -2
  92. package/dist/operations/group.d.ts +14 -1
  93. package/dist/operations/group.js +42 -4
  94. package/dist/operations/highlight.js +21 -5
  95. package/dist/operations/index.d.ts +1 -1
  96. package/dist/operations/index.js +1 -1
  97. package/dist/operations/live-stream.js +10 -4
  98. package/dist/operations/share.js +3 -1
  99. package/dist/operations/stream-chat.d.ts +3 -2
  100. package/dist/operations/stream-chat.js +7 -2
  101. package/dist/operations/tag/bookmarks.d.ts +3 -2
  102. package/dist/operations/tag/bookmarks.js +34 -12
  103. package/dist/register.d.ts +2 -11
  104. package/dist/register.js +2 -11
  105. package/package.json +28 -3
  106. package/dist/helpers/mailboxes.d.ts +0 -7
  107. package/dist/helpers/mailboxes.js +0 -49
@@ -0,0 +1,79 @@
1
+ import { filter, firstValueFrom, isObservable, lastValueFrom, map, of, switchMap, timeout } from "rxjs";
2
+ /**
3
+ * A symbol used to mark an Observable as chainable
4
+ */
5
+ const CHAINABLE_CACHE_SYMBOL = Symbol.for("chainable-cache");
6
+ /**
7
+ * Wraps an Observable in a Proxy that enables property chaining.
8
+ * When accessing a property ending with `$`, it uses switchMap to chain
9
+ * to that property's observable value.
10
+ * When accessing a non-observable property, it returns an Observable of that property's value.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const author$ = chainable(note.author$);
15
+ * const outboxes$ = author$.outboxes$; // Observable<string[] | undefined>
16
+ * const displayName$ = author$.displayName; // Observable<string | undefined>
17
+ * ```
18
+ */
19
+ export function chainable(observable) {
20
+ // Create a Proxy that intercepts property access
21
+ const proxy = new Proxy(observable, {
22
+ get(target$, prop) {
23
+ const cache = observable[CHAINABLE_CACHE_SYMBOL] ||
24
+ (observable[CHAINABLE_CACHE_SYMBOL] = {});
25
+ // Forward all Observable methods and properties
26
+ if (prop in target$ || typeof prop === "symbol") {
27
+ const value = target$[prop];
28
+ // If it's a function, bind it to the target
29
+ if (typeof value === "function")
30
+ return value.bind(target$);
31
+ return value;
32
+ }
33
+ if (typeof prop === "string") {
34
+ // Return cached observable if it exists
35
+ const cached = cache[prop];
36
+ if (cached)
37
+ return cached;
38
+ // Otherwise, create a new observable
39
+ let prop$;
40
+ // Extra observalbe helpers to make it easier to work with observables
41
+ if (prop === "$first") {
42
+ return (...args) => firstValueFrom(target$.pipe(filter((v) => v !== undefined && v !== null), args.length === 2
43
+ ? timeout({ first: args[0], with: () => of(args[1]) })
44
+ : timeout({ first: args[0] ?? 10_000 })));
45
+ }
46
+ else if (prop === "$last") {
47
+ return (...args) => lastValueFrom(target$.pipe(filter((v) => v !== undefined && v !== null), args.length === 2
48
+ ? timeout({ first: args[0], with: () => of(args[1]) })
49
+ : timeout({ first: args[0] ?? 10_000 })));
50
+ }
51
+ // Handle property access for properties ending with $
52
+ else if (prop.endsWith("$")) {
53
+ // Use switchMap to chain to the nested observable
54
+ prop$ = target$.pipe(switchMap((target) => {
55
+ const value = target === undefined || target === null ? target : target[prop];
56
+ // If value is an observable, return it
57
+ if (isObservable(value))
58
+ return value;
59
+ // Otherwise wrap it in an observable
60
+ else
61
+ return of(value);
62
+ }));
63
+ }
64
+ // For non-$ properties, return an Observable of the property value
65
+ else {
66
+ prop$ = target$.pipe(
67
+ // Access the property on the value if target is not undefined or null
68
+ map((target) => (target === undefined || target === null ? target : target[prop])));
69
+ }
70
+ // Make the chained observable chainable too
71
+ const observable = chainable(prop$);
72
+ cache[prop] = observable;
73
+ return observable;
74
+ }
75
+ throw new Error(`Unable to access property "${prop}" on chainable observable`);
76
+ },
77
+ });
78
+ return proxy;
79
+ }
@@ -0,0 +1,6 @@
1
+ import { IAsyncEventStore, IEventModelMixin, IEventStore } from "applesauce-core";
2
+ import { NostrEvent } from "applesauce-core/helpers/event";
3
+ import { ProfilePointer } from "applesauce-core/helpers/pointers";
4
+ import { MonoTypeOperatorFunction } from "rxjs";
5
+ /** Filters a timeline of events by a users mutes */
6
+ export declare function filterTimelineByMutes<T extends NostrEvent>(eventStore: IEventModelMixin<IEventStore | IAsyncEventStore>, user: string | ProfilePointer): MonoTypeOperatorFunction<T[]>;
@@ -0,0 +1,7 @@
1
+ import { combineLatest, map } from "rxjs";
2
+ import { matchMutes } from "../helpers/mute.js";
3
+ import { MuteModel } from "../models/mutes.js";
4
+ /** Filters a timeline of events by a users mutes */
5
+ export function filterTimelineByMutes(eventStore, user) {
6
+ return (source) => combineLatest([source, eventStore.model(MuteModel, user)]).pipe(map(([source, mutes]) => (mutes ? source.filter((event) => matchMutes(mutes, event)) : source)));
7
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./filter-timeline-by-mutes.js";
2
+ export * from "./cast-stream.js";
3
+ export * from "./chainable.js";
@@ -0,0 +1,3 @@
1
+ export * from "./filter-timeline-by-mutes.js";
2
+ export * from "./cast-stream.js";
3
+ export * from "./chainable.js";
@@ -16,6 +16,8 @@ export function setCalendarEvent(pointer, relay) {
16
16
  if (pointer.kind !== DATE_BASED_CALENDAR_EVENT_KIND && pointer.kind !== TIME_BASED_CALENDAR_EVENT_KIND)
17
17
  throw new Error("RSVP pointer must be to a calendar event");
18
18
  let addressPointer = isAddressPointer(pointer) ? pointer : getAddressPointerForEvent(pointer);
19
+ if (addressPointer === null)
20
+ throw new Error("Calendar event is not addressable");
19
21
  let eventPointer = isAddressPointer(pointer)
20
22
  ? undefined
21
23
  : { id: pointer.id, kind: pointer.kind, author: pointer.pubkey };
@@ -1,4 +1,3 @@
1
- import { getAddressPointerForEvent, isAddressPointer } from "applesauce-core/helpers/pointers";
2
1
  import { addAddressPointerTag, removeAddressPointerTag } from "applesauce-core/operations/tag/common";
3
2
  import { includeSingletonTag, modifyPublicTags } from "applesauce-core/operations/tags";
4
3
  /** Sets the title of a calendar */
@@ -7,9 +6,9 @@ export function setTitle(title) {
7
6
  }
8
7
  /** Adds a calendar event tags to a calendar event */
9
8
  export function addEvent(event) {
10
- return modifyPublicTags(addAddressPointerTag(isAddressPointer(event) ? event : getAddressPointerForEvent(event)));
9
+ return modifyPublicTags(addAddressPointerTag(event));
11
10
  }
12
11
  /** Removes a calendar event tags from a calendar event */
13
12
  export function removeEvent(event) {
14
- return modifyPublicTags(removeAddressPointerTag(isAddressPointer(event) ? event : getAddressPointerForEvent(event)));
13
+ return modifyPublicTags(removeAddressPointerTag(event));
15
14
  }
@@ -1,5 +1,5 @@
1
1
  import { kinds } from "applesauce-core/helpers/event";
2
- import { getCoordinateFromAddressPointer } from "applesauce-core/helpers/pointers";
2
+ import { getReplaceableAddressFromPointer } from "applesauce-core/helpers/pointers";
3
3
  import { fillAndTrimTag } from "applesauce-core/helpers/tags";
4
4
  import { includeSingletonTag } from "applesauce-core/operations/tags";
5
5
  // A list of event kinds to never attach the "client" tag to
@@ -11,7 +11,7 @@ export function setClient(name, pointer, replace = true) {
11
11
  return draft;
12
12
  else {
13
13
  const coordinate = pointer
14
- ? getCoordinateFromAddressPointer({
14
+ ? getReplaceableAddressFromPointer({
15
15
  pubkey: pointer.pubkey,
16
16
  identifier: pointer.identifier,
17
17
  kind: kinds.Handlerinformation,
@@ -1,6 +1,7 @@
1
1
  import { EventOperation } from "applesauce-core/event-factory";
2
+ import { EventPointer, ProfilePointer } from "applesauce-core/helpers";
2
3
  import { NostrEvent } from "applesauce-core/helpers/event";
3
- import { GroupPointer } from "../helpers/groups.js";
4
+ import { GroupMetadata, GroupPointer } from "../helpers/groups.js";
4
5
  /** Adds a "group" tag to a list */
5
6
  export declare function addGroupTag(group: GroupPointer): EventOperation;
6
7
  /** Removes a "group" tag from a list */
@@ -9,3 +10,15 @@ export declare function removeGroupTag(group: GroupPointer): EventOperation;
9
10
  export declare function setGroupPointer(group: GroupPointer): EventOperation;
10
11
  /** Adds "previous" tags for group messages */
11
12
  export declare function addPreviousRefs(previous: NostrEvent[], count?: number): EventOperation;
13
+ /** Sets tags for a join request (kind 9021) */
14
+ export declare function setJoinRequestTags(group: GroupPointer, inviteCode?: string): EventOperation;
15
+ /** Sets tags for a leave request (kind 9022) */
16
+ export declare function setLeaveRequestTags(group: GroupPointer): EventOperation;
17
+ /** Sets tags for put user (kind 9000) */
18
+ export declare function setPutUserTags(user: string | ProfilePointer, roles?: string[]): EventOperation;
19
+ /** Sets tags for remove user (kind 9001) */
20
+ export declare function setRemoveUserTags(user: string | ProfilePointer): EventOperation;
21
+ /** Sets tags for edit metadata (kind 9002) */
22
+ export declare function setEditMetadataTags(fields: Partial<GroupMetadata>): EventOperation;
23
+ /** Sets tags for delete event (kind 9005) */
24
+ export declare function setDeleteEventTags(event: string | EventPointer | NostrEvent): EventOperation;
@@ -1,6 +1,18 @@
1
- import { ensureNamedValueTag } from "applesauce-core/helpers";
2
- import { includeSingletonTag, modifyPublicTags } from "applesauce-core/operations/tags";
3
- import { createGroupHTagFromGroupPointer, createGroupTagFromGroupPointer } from "../helpers/groups.js";
1
+ import { ensureNamedValueTag, ensureWebSocketURL, fillAndTrimTag, } from "applesauce-core/helpers";
2
+ import { addEventPointerTag, addNameValueTag, addProfilePointerTag, setSingletonTag, } from "applesauce-core/operations/tag/common";
3
+ import { modifyPublicTags } from "applesauce-core/operations/tags";
4
+ /** Creates a "h" tag for chat messages from a {@link GroupPointer} */
5
+ function createGroupHTagFromGroupPointer(group) {
6
+ return fillAndTrimTag(["h", group.id, ensureWebSocketURL(group.relay)]);
7
+ }
8
+ /** Creates a "group" tag from a {@link GroupPointer} */
9
+ function createGroupTagFromGroupPointer(group) {
10
+ return fillAndTrimTag(["group", group.id, ensureWebSocketURL(group.relay), group.name], 3);
11
+ }
12
+ /** A tag operation for setting the "h" tag for a group */
13
+ function setGroupHTag(group) {
14
+ return setSingletonTag(createGroupHTagFromGroupPointer(group));
15
+ }
4
16
  /** Adds a "group" tag to a list */
5
17
  export function addGroupTag(group) {
6
18
  return modifyPublicTags((tags) => {
@@ -15,7 +27,7 @@ export function removeGroupTag(group) {
15
27
  }
16
28
  /** Sets the "h" tag for NIP-29 group messages or other events */
17
29
  export function setGroupPointer(group) {
18
- return includeSingletonTag(createGroupHTagFromGroupPointer(group), true);
30
+ return modifyPublicTags(setGroupHTag(group));
19
31
  }
20
32
  /** Adds "previous" tags for group messages */
21
33
  export function addPreviousRefs(previous, count = 6) {
@@ -32,3 +44,29 @@ export function addPreviousRefs(previous, count = 6) {
32
44
  return { ...draft, tags };
33
45
  };
34
46
  }
47
+ /** Sets tags for a join request (kind 9021) */
48
+ export function setJoinRequestTags(group, inviteCode) {
49
+ return modifyPublicTags(setGroupHTag(group), inviteCode ? addNameValueTag(["code", inviteCode]) : undefined);
50
+ }
51
+ /** Sets tags for a leave request (kind 9022) */
52
+ export function setLeaveRequestTags(group) {
53
+ return modifyPublicTags(setGroupHTag(group));
54
+ }
55
+ /** Sets tags for put user (kind 9000) */
56
+ export function setPutUserTags(user, roles) {
57
+ const pubkey = typeof user === "string" ? user : user.pubkey;
58
+ const tag = roles && roles.length > 0 ? ["p", pubkey, ...roles] : ["p", pubkey];
59
+ return modifyPublicTags(addNameValueTag(tag));
60
+ }
61
+ /** Sets tags for remove user (kind 9001) */
62
+ export function setRemoveUserTags(user) {
63
+ return modifyPublicTags(addProfilePointerTag(user));
64
+ }
65
+ /** Sets tags for edit metadata (kind 9002) */
66
+ export function setEditMetadataTags(fields) {
67
+ return modifyPublicTags(fields.name !== undefined ? setSingletonTag(["name", fields.name]) : undefined, fields.picture !== undefined ? setSingletonTag(["picture", fields.picture]) : undefined, fields.about !== undefined ? setSingletonTag(["about", fields.about]) : undefined, fields.isPublic ? setSingletonTag(["public"]) : undefined, fields.isPrivate ? setSingletonTag(["private"]) : undefined, fields.isOpen ? setSingletonTag(["open"]) : undefined, fields.isClosed ? setSingletonTag(["closed"]) : undefined);
68
+ }
69
+ /** Sets tags for delete event (kind 9005) */
70
+ export function setDeleteEventTags(event) {
71
+ return modifyPublicTags(addEventPointerTag(event));
72
+ }
@@ -10,18 +10,34 @@ export function setHighlightContent(content) {
10
10
  /** Sets the source event that was highlighted using an 'e' tag */
11
11
  export function setSource(source) {
12
12
  if (isEvent(source)) {
13
- if (isReplaceable(source.kind))
14
- return modifyPublicTags(addEventPointerTag(source, true), addAddressPointerTag(getAddressPointerForEvent(source), true));
15
- else
13
+ if (isReplaceable(source.kind)) {
14
+ const address = getAddressPointerForEvent(source);
15
+ if (address) {
16
+ // Include both the event pointer and address pointer
17
+ return modifyPublicTags(addEventPointerTag(source, true), addAddressPointerTag(address, true));
18
+ }
19
+ else {
20
+ // Just include the event pointer
21
+ return modifyPublicTags(addEventPointerTag(source, true));
22
+ }
23
+ }
24
+ else {
25
+ // Include the event pointer for normal events
16
26
  return modifyPublicTags(addEventPointerTag(source, true));
27
+ }
17
28
  }
18
29
  else if (isAddressPointer(source)) {
30
+ // Include "a" tag for address pointers
19
31
  return modifyPublicTags(addAddressPointerTag(source, true));
20
32
  }
21
- else if (isEventPointer(source))
33
+ else if (isEventPointer(source)) {
34
+ // Include "e" tag for event pointers
22
35
  return modifyPublicTags(addEventPointerTag(source, true));
23
- else if (typeof source === "string")
36
+ }
37
+ else if (typeof source === "string") {
38
+ // Include "r" tags for URLs
24
39
  return includeSingletonTag(["r", source]);
40
+ }
25
41
  else
26
42
  throw new Error("Invalid source");
27
43
  }
@@ -8,7 +8,7 @@ export * as Comment from "./comment.js";
8
8
  export * as FileMetadata from "./file-metadata.js";
9
9
  export * as Geohash from "./geohash.js";
10
10
  export * as GiftWrap from "./gift-wrap.js";
11
- export * as Groups from "./group.js";
11
+ export * as Group from "./group.js";
12
12
  export * as Hashtags from "./hashtags.js";
13
13
  export * as Highlight from "./highlight.js";
14
14
  export * as LegacyMessage from "./legacy-message.js";
@@ -8,7 +8,7 @@ export * as Comment from "./comment.js";
8
8
  export * as FileMetadata from "./file-metadata.js";
9
9
  export * as Geohash from "./geohash.js";
10
10
  export * as GiftWrap from "./gift-wrap.js";
11
- export * as Groups from "./group.js";
11
+ export * as Group from "./group.js";
12
12
  export * as Hashtags from "./hashtags.js";
13
13
  export * as Highlight from "./highlight.js";
14
14
  export * as LegacyMessage from "./legacy-message.js";
@@ -3,9 +3,15 @@ import { getAddressPointerForEvent } from "applesauce-core/helpers/pointers";
3
3
  /** Includes the "a" tag for live streams */
4
4
  export function includeLiveStreamTag(stream) {
5
5
  return async (draft, ctx) => {
6
- let tags = Array.from(draft.tags);
7
- const hint = await ctx.getEventRelayHint?.(stream.id);
8
- tags = ensureMarkedAddressPointerTag(tags, getAddressPointerForEvent(stream, hint ? [hint] : undefined), "root");
9
- return { ...draft, tags };
6
+ const pointer = getAddressPointerForEvent(stream);
7
+ if (!pointer)
8
+ throw new Error("Stream is not addressable");
9
+ // add relay hint if there isn't one
10
+ if (pointer.relays?.[0] === undefined && ctx.getEventRelayHint) {
11
+ const hint = await ctx.getEventRelayHint(stream.id);
12
+ if (hint)
13
+ pointer.relays = [hint];
14
+ }
15
+ return { ...draft, tags: ensureMarkedAddressPointerTag(draft.tags, pointer, "root") };
10
16
  };
11
17
  }
@@ -12,7 +12,9 @@ export function setShareTags(event) {
12
12
  tags = ensureEventPointerTag(tags, getEventPointerForEvent(event, hint ? [hint] : undefined));
13
13
  // add "a" tag
14
14
  if (isAddressableKind(event.kind)) {
15
- tags = ensureAddressPointerTag(tags, getAddressPointerForEvent(event, hint ? [hint] : undefined));
15
+ const pointer = getAddressPointerForEvent(event, hint ? [hint] : undefined);
16
+ if (pointer)
17
+ tags = ensureAddressPointerTag(tags, pointer);
16
18
  }
17
19
  // add "p" tag for notify
18
20
  const pubkeyHint = await ctx.getPubkeyRelayHint?.(event.pubkey);
@@ -1,7 +1,8 @@
1
+ import { EventOperation } from "applesauce-core";
1
2
  import { NostrEvent } from "applesauce-core/helpers/event";
2
3
  import { AddressPointer } from "applesauce-core/helpers/pointers";
3
4
  import { TextContentOptions } from "applesauce-core/operations/content";
4
5
  /** Sets the message content for a stream chat event */
5
- export declare function setMessage(content: string, options?: TextContentOptions): import("applesauce-core").EventOperation;
6
+ export declare function setMessage(content: string, options?: TextContentOptions): EventOperation;
6
7
  /** Sets the stream for a stream chat event */
7
- export declare function setStream(stream: AddressPointer | NostrEvent): import("applesauce-core").EventOperation<import("nostr-tools").Event | import("nostr-tools/core").UnsignedEvent | import("nostr-tools/core").EventTemplate, import("nostr-tools").Event | import("nostr-tools/core").UnsignedEvent | import("nostr-tools/core").EventTemplate>;
8
+ export declare function setStream(stream: AddressPointer | NostrEvent): EventOperation;
@@ -21,7 +21,12 @@ export function setMessage(content, options) {
21
21
  }
22
22
  /** Sets the stream for a stream chat event */
23
23
  export function setStream(stream) {
24
+ let pointer;
24
25
  if (!isAddressPointer(stream))
25
- stream = getAddressPointerForEvent(stream);
26
- return modifyPublicTags((tags) => ensureAddressPointerTag(tags, stream));
26
+ pointer = getAddressPointerForEvent(stream);
27
+ else
28
+ pointer = stream;
29
+ if (pointer === null)
30
+ throw new Error("Stream is not an addressable event");
31
+ return modifyPublicTags((tags) => ensureAddressPointerTag(tags, pointer));
27
32
  }
@@ -1,6 +1,7 @@
1
1
  import { TagOperation } from "applesauce-core/event-factory";
2
2
  import { NostrEvent } from "applesauce-core/helpers/event";
3
+ import { AddressPointer, EventPointer } from "applesauce-core/helpers/pointers";
3
4
  /** Adds an "e" or "a" tag to a bookmark list or set */
4
- export declare function addEventBookmarkTag(event: NostrEvent): TagOperation;
5
+ export declare function addEventBookmarkTag(event: NostrEvent | EventPointer | AddressPointer): TagOperation;
5
6
  /** Removes an "e" or "a" tag from a bookmark list or set */
6
- export declare function removeEventBookmarkTag(event: NostrEvent): TagOperation;
7
+ export declare function removeEventBookmarkTag(event: NostrEvent | EventPointer | AddressPointer): TagOperation;
@@ -1,20 +1,42 @@
1
- import { isReplaceable } from "applesauce-core/helpers";
2
- import { kinds } from "applesauce-core/helpers/event";
3
- import { getAddressPointerForEvent } from "applesauce-core/helpers/pointers";
1
+ import { isEvent, isReplaceable, kinds } from "applesauce-core/helpers/event";
2
+ import { isAddressPointer, isEventPointer } from "applesauce-core/helpers/pointers";
4
3
  import { addAddressPointerTag, addEventPointerTag, removeAddressPointerTag, removeEventPointerTag, } from "applesauce-core/operations/tag/common";
5
4
  /** Adds an "e" or "a" tag to a bookmark list or set */
6
5
  export function addEventBookmarkTag(event) {
7
- if (event.kind !== kinds.ShortTextNote && event.kind !== kinds.LongFormArticle)
6
+ // Validate event kind if event or address pointer
7
+ if ((isEvent(event) || isAddressPointer(event)) &&
8
+ event.kind !== kinds.ShortTextNote &&
9
+ event.kind !== kinds.LongFormArticle)
8
10
  throw new Error(`Event kind (${event.kind}) cant not be added to bookmarks`);
9
- return isReplaceable(event.kind)
10
- ? addAddressPointerTag(getAddressPointerForEvent(event))
11
- : addEventPointerTag(event.id);
11
+ if (isEvent(event)) {
12
+ // Add "a" tag for replaceable articles
13
+ if (isReplaceable(event.kind))
14
+ return addAddressPointerTag(event);
15
+ // Add "e" tag for non-replaceable notes
16
+ else
17
+ return addEventPointerTag(event);
18
+ }
19
+ // "e" tags for note event pointers
20
+ else if (isEventPointer(event))
21
+ return addEventPointerTag(event);
22
+ // "a" tags for address pointers
23
+ else
24
+ return addAddressPointerTag(event);
12
25
  }
13
26
  /** Removes an "e" or "a" tag from a bookmark list or set */
14
27
  export function removeEventBookmarkTag(event) {
15
- if (event.kind !== kinds.ShortTextNote && event.kind !== kinds.LongFormArticle)
16
- throw new Error(`Event kind (${event.kind}) cant not be added to bookmarks`);
17
- return isReplaceable(event.kind)
18
- ? removeAddressPointerTag(getAddressPointerForEvent(event))
19
- : removeEventPointerTag(event.id);
28
+ if (isEvent(event)) {
29
+ // Remove "a" tag for replaceable articles
30
+ if (isReplaceable(event.kind))
31
+ return removeAddressPointerTag(event);
32
+ // Remove "e" tag for non-replaceable notes
33
+ else
34
+ return removeEventPointerTag(event);
35
+ }
36
+ // "e" tags for note event pointers
37
+ else if (isEventPointer(event))
38
+ return removeEventPointerTag(event);
39
+ // "a" tags for address pointers
40
+ else
41
+ return removeAddressPointerTag(event);
20
42
  }
@@ -1,11 +1,2 @@
1
- import "./models/blossom.js";
2
- import "./models/mutes.js";
3
- import "./models/reactions.js";
4
- import "./models/comments.js";
5
- import "./models/thread.js";
6
- import "./blueprints/comment.js";
7
- import "./blueprints/delete.js";
8
- import "./blueprints/note.js";
9
- import "./blueprints/reaction.js";
10
- import "./blueprints/share.js";
11
- import "./blueprints/poll.js";
1
+ import "./models/__register__.js";
2
+ import "./blueprints/__register__.js";
package/dist/register.js CHANGED
@@ -1,13 +1,4 @@
1
1
  // Import models that should register with the event store
2
- import "./models/blossom.js";
3
- import "./models/mutes.js";
4
- import "./models/reactions.js";
5
- import "./models/comments.js";
6
- import "./models/thread.js";
2
+ import "./models/__register__.js";
7
3
  // Import blueprints that should register with the event factory
8
- import "./blueprints/comment.js";
9
- import "./blueprints/delete.js";
10
- import "./blueprints/note.js";
11
- import "./blueprints/reaction.js";
12
- import "./blueprints/share.js";
13
- import "./blueprints/poll.js";
4
+ import "./blueprints/__register__.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "applesauce-common",
3
- "version": "0.0.0-next-20251205152544",
3
+ "version": "0.0.0-next-20251220152312",
4
4
  "description": "Common NIP-specific helpers and models for applesauce",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -59,23 +59,48 @@
59
59
  "import": "./dist/blueprints/*.js",
60
60
  "require": "./dist/blueprints/*.js",
61
61
  "types": "./dist/blueprints/*.d.ts"
62
+ },
63
+ "./observable": {
64
+ "import": "./dist/observable/index.js",
65
+ "require": "./dist/observable/index.js",
66
+ "types": "./dist/observable/index.d.ts"
67
+ },
68
+ "./observable/*": {
69
+ "import": "./dist/observable/*.js",
70
+ "require": "./dist/observable/*.js",
71
+ "types": "./dist/observable/*.d.ts"
72
+ },
73
+ "./casts": {
74
+ "import": "./dist/casts/index.js",
75
+ "require": "./dist/casts/index.js",
76
+ "types": "./dist/casts/index.d.ts"
77
+ },
78
+ "./casts/*": {
79
+ "import": "./dist/casts/*.js",
80
+ "require": "./dist/casts/*.js",
81
+ "types": "./dist/casts/*.d.ts"
62
82
  }
63
83
  },
64
84
  "dependencies": {
65
85
  "@scure/base": "^1.2.4",
66
- "applesauce-core": "0.0.0-next-20251205152544",
86
+ "applesauce-core": "0.0.0-next-20251220152312",
67
87
  "hash-sum": "^2.0.0",
68
88
  "light-bolt11-decoder": "^3.2.0",
69
89
  "rxjs": "^7.8.1"
70
90
  },
71
91
  "devDependencies": {
72
92
  "@hirez_io/observer-spy": "^2.2.0",
93
+ "@nostrability/schemata": "github:nostrability/schemata",
73
94
  "@types/debug": "^4.1.12",
74
95
  "@types/hash-sum": "^1.0.2",
96
+ "@types/node": "^22.19.1",
97
+ "ajv": "^8.17.1",
98
+ "ajv-formats": "^3.0.1",
75
99
  "nostr-tools": "^2.18",
76
100
  "rimraf": "^6.0.1",
77
101
  "typescript": "^5.8.3",
78
- "vitest": "^4.0.15"
102
+ "vitest": "^4.0.15",
103
+ "yaml": "^2.8.2"
79
104
  },
80
105
  "funding": {
81
106
  "type": "lightning",
@@ -1,7 +0,0 @@
1
- import { NostrEvent } from "applesauce-core/helpers/event";
2
- export declare const MailboxesInboxesSymbol: unique symbol;
3
- export declare const MailboxesOutboxesSymbol: unique symbol;
4
- /** Parses a 10002 event and stores the inboxes in the event using the {@link MailboxesInboxesSymbol} symbol */
5
- export declare function getInboxes(event: NostrEvent): string[];
6
- /** Parses a 10002 event and stores the outboxes in the event using the {@link MailboxesOutboxesSymbol} symbol */
7
- export declare function getOutboxes(event: NostrEvent): string[];
@@ -1,49 +0,0 @@
1
- import { getOrComputeCachedValue } from "applesauce-core/helpers/cache";
2
- import { isSafeRelayURL } from "applesauce-core/helpers/relays";
3
- import { isRTag } from "applesauce-core/helpers/tags";
4
- import { normalizeURL } from "applesauce-core/helpers/url";
5
- export const MailboxesInboxesSymbol = Symbol.for("mailboxes-inboxes");
6
- export const MailboxesOutboxesSymbol = Symbol.for("mailboxes-outboxes");
7
- /** Parses a 10002 event and stores the inboxes in the event using the {@link MailboxesInboxesSymbol} symbol */
8
- export function getInboxes(event) {
9
- return getOrComputeCachedValue(event, MailboxesInboxesSymbol, () => {
10
- const inboxes = [];
11
- for (const tag of event.tags) {
12
- if (!isRTag(tag))
13
- continue;
14
- try {
15
- const [, url, mode] = tag;
16
- if (url && isSafeRelayURL(url) && !inboxes.includes(url) && (mode === "read" || mode === undefined)) {
17
- inboxes.push(normalizeURL(url));
18
- }
19
- }
20
- catch {
21
- // Ignore invalid url tags
22
- }
23
- }
24
- return inboxes;
25
- });
26
- }
27
- /** Parses a 10002 event and stores the outboxes in the event using the {@link MailboxesOutboxesSymbol} symbol */
28
- export function getOutboxes(event) {
29
- return getOrComputeCachedValue(event, MailboxesOutboxesSymbol, () => {
30
- const outboxes = [];
31
- for (const tag of event.tags) {
32
- if (!isRTag(tag))
33
- continue;
34
- try {
35
- const [name, url, mode] = tag;
36
- if (name === "r" &&
37
- isSafeRelayURL(url) &&
38
- !outboxes.includes(url) &&
39
- (mode === "write" || mode === undefined)) {
40
- outboxes.push(normalizeURL(url));
41
- }
42
- }
43
- catch {
44
- // Ignore invalid url tags
45
- }
46
- }
47
- return outboxes;
48
- });
49
- }