applesauce-core 4.4.2 → 5.0.1

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 (224) hide show
  1. package/README.md +6 -2
  2. package/dist/event-factory/event-factory.d.ts +57 -0
  3. package/dist/event-factory/event-factory.js +94 -0
  4. package/dist/event-factory/index.d.ts +3 -0
  5. package/dist/event-factory/index.js +3 -0
  6. package/dist/event-factory/methods.d.ts +17 -0
  7. package/dist/event-factory/methods.js +44 -0
  8. package/dist/event-factory/types.d.ts +76 -0
  9. package/dist/event-factory/types.js +1 -0
  10. package/dist/event-store/async-delete-manager.d.ts +26 -0
  11. package/dist/event-store/async-delete-manager.js +33 -0
  12. package/dist/event-store/async-event-store.d.ts +46 -81
  13. package/dist/event-store/async-event-store.js +143 -182
  14. package/dist/event-store/delete-manager.d.ts +30 -0
  15. package/dist/event-store/delete-manager.js +99 -0
  16. package/dist/event-store/event-memory.d.ts +18 -18
  17. package/dist/event-store/event-memory.js +17 -10
  18. package/dist/event-store/event-models.d.ts +59 -0
  19. package/dist/event-store/event-models.js +121 -0
  20. package/dist/event-store/event-store.d.ts +48 -83
  21. package/dist/event-store/event-store.js +165 -181
  22. package/dist/event-store/expiration-manager.d.ts +37 -0
  23. package/dist/event-store/expiration-manager.js +97 -0
  24. package/dist/event-store/index.d.ts +4 -0
  25. package/dist/event-store/index.js +4 -0
  26. package/dist/event-store/interface.d.ts +83 -55
  27. package/dist/helpers/contacts.d.ts +3 -2
  28. package/dist/helpers/contacts.js +8 -8
  29. package/dist/helpers/delete.d.ts +9 -2
  30. package/dist/helpers/delete.js +25 -1
  31. package/dist/helpers/encrypted-content.d.ts +3 -1
  32. package/dist/helpers/encrypted-content.js +1 -2
  33. package/dist/helpers/encryption.d.ts +1 -0
  34. package/dist/helpers/encryption.js +2 -0
  35. package/dist/helpers/event-cache.d.ts +2 -2
  36. package/dist/helpers/event-cache.js +1 -1
  37. package/dist/helpers/event.d.ts +22 -6
  38. package/dist/helpers/event.js +19 -8
  39. package/dist/helpers/expiration.d.ts +1 -1
  40. package/dist/helpers/factory.d.ts +32 -0
  41. package/dist/helpers/factory.js +117 -0
  42. package/dist/helpers/filter.d.ts +17 -17
  43. package/dist/helpers/filter.js +23 -6
  44. package/dist/helpers/hidden-content.js +5 -5
  45. package/dist/helpers/hidden-tags.d.ts +6 -2
  46. package/dist/helpers/hidden-tags.js +12 -5
  47. package/dist/helpers/index.d.ts +5 -38
  48. package/dist/helpers/index.js +5 -38
  49. package/dist/helpers/keys.d.ts +8 -0
  50. package/dist/helpers/keys.js +27 -0
  51. package/dist/helpers/mailboxes.d.ts +1 -1
  52. package/dist/helpers/model.d.ts +5 -0
  53. package/dist/helpers/model.js +17 -0
  54. package/dist/helpers/pipeline.d.ts +16 -0
  55. package/dist/helpers/pipeline.js +43 -0
  56. package/dist/helpers/pointers.d.ts +35 -44
  57. package/dist/helpers/pointers.js +150 -108
  58. package/dist/helpers/profile.d.ts +23 -2
  59. package/dist/helpers/profile.js +3 -3
  60. package/dist/helpers/regexp.d.ts +19 -0
  61. package/dist/helpers/regexp.js +48 -0
  62. package/dist/helpers/relay-selection.d.ts +3 -1
  63. package/dist/helpers/relay-selection.js +33 -34
  64. package/dist/helpers/relays.d.ts +3 -6
  65. package/dist/helpers/relays.js +15 -5
  66. package/dist/helpers/string.js +8 -2
  67. package/dist/helpers/tags.d.ts +11 -3
  68. package/dist/helpers/tags.js +49 -1
  69. package/dist/helpers/url.js +10 -2
  70. package/dist/index.d.ts +4 -2
  71. package/dist/index.js +4 -2
  72. package/dist/models/{common.d.ts → base.d.ts} +5 -13
  73. package/dist/models/{common.js → base.js} +67 -73
  74. package/dist/models/contacts.d.ts +1 -1
  75. package/dist/models/contacts.js +2 -2
  76. package/dist/models/encrypted-content.d.ts +1 -1
  77. package/dist/models/index.d.ts +2 -16
  78. package/dist/models/index.js +2 -16
  79. package/dist/models/mailboxes.d.ts +1 -1
  80. package/dist/models/mailboxes.js +1 -1
  81. package/dist/models/outbox.d.ts +1 -1
  82. package/dist/models/profile.d.ts +1 -1
  83. package/dist/models/profile.js +2 -5
  84. package/dist/observable/claim-events.d.ts +1 -1
  85. package/dist/observable/claim-latest.d.ts +1 -1
  86. package/dist/observable/map-events-to-store.d.ts +2 -2
  87. package/dist/observable/map-events-to-timeline.d.ts +1 -1
  88. package/dist/observable/map-events-to-timeline.js +1 -1
  89. package/dist/observable/relay-selection.d.ts +1 -1
  90. package/dist/observable/watch-event-updates.d.ts +3 -1
  91. package/dist/observable/watch-event-updates.js +2 -0
  92. package/dist/operations/client.d.ts +4 -0
  93. package/dist/operations/client.js +23 -0
  94. package/dist/operations/content.d.ts +21 -0
  95. package/dist/operations/content.js +112 -0
  96. package/dist/operations/delete.d.ts +4 -0
  97. package/dist/operations/delete.js +26 -0
  98. package/dist/operations/encrypted-content.d.ts +4 -0
  99. package/dist/operations/encrypted-content.js +13 -0
  100. package/dist/operations/event.d.ts +39 -0
  101. package/dist/operations/event.js +107 -0
  102. package/dist/operations/hidden-content.d.ts +4 -0
  103. package/dist/operations/hidden-content.js +10 -0
  104. package/dist/operations/index.d.ts +7 -0
  105. package/dist/operations/index.js +7 -0
  106. package/dist/operations/mailboxes.d.ts +13 -0
  107. package/dist/operations/mailboxes.js +80 -0
  108. package/dist/operations/profile.d.ts +6 -0
  109. package/dist/operations/profile.js +13 -0
  110. package/dist/operations/tag/common.d.ts +23 -0
  111. package/dist/operations/tag/common.js +106 -0
  112. package/dist/operations/tag/index.d.ts +2 -0
  113. package/dist/operations/tag/index.js +2 -0
  114. package/dist/operations/tag/relay.d.ts +5 -0
  115. package/dist/operations/tag/relay.js +10 -0
  116. package/dist/operations/tags.d.ts +20 -0
  117. package/dist/operations/tags.js +93 -0
  118. package/package.json +23 -6
  119. package/dist/event-store/model-mixin.d.ts +0 -59
  120. package/dist/event-store/model-mixin.js +0 -147
  121. package/dist/helpers/app-data.d.ts +0 -39
  122. package/dist/helpers/app-data.js +0 -68
  123. package/dist/helpers/app-handlers.d.ts +0 -23
  124. package/dist/helpers/app-handlers.js +0 -68
  125. package/dist/helpers/article.d.ts +0 -15
  126. package/dist/helpers/article.js +0 -25
  127. package/dist/helpers/blossom.d.ts +0 -11
  128. package/dist/helpers/blossom.js +0 -40
  129. package/dist/helpers/bolt11.d.ts +0 -10
  130. package/dist/helpers/bolt11.js +0 -17
  131. package/dist/helpers/bookmarks.d.ts +0 -30
  132. package/dist/helpers/bookmarks.js +0 -96
  133. package/dist/helpers/calendar-event.d.ts +0 -36
  134. package/dist/helpers/calendar-event.js +0 -110
  135. package/dist/helpers/calendar-rsvp.d.ts +0 -15
  136. package/dist/helpers/calendar-rsvp.js +0 -38
  137. package/dist/helpers/calendar.d.ts +0 -6
  138. package/dist/helpers/calendar.js +0 -11
  139. package/dist/helpers/channels.d.ts +0 -10
  140. package/dist/helpers/channels.js +0 -27
  141. package/dist/helpers/comment.d.ts +0 -44
  142. package/dist/helpers/comment.js +0 -114
  143. package/dist/helpers/content.d.ts +0 -3
  144. package/dist/helpers/content.js +0 -8
  145. package/dist/helpers/emoji.d.ts +0 -21
  146. package/dist/helpers/emoji.js +0 -34
  147. package/dist/helpers/encrypted-content-cache.d.ts +0 -22
  148. package/dist/helpers/encrypted-content-cache.js +0 -139
  149. package/dist/helpers/event-tags.d.ts +0 -20
  150. package/dist/helpers/event-tags.js +0 -34
  151. package/dist/helpers/external-id.d.ts +0 -29
  152. package/dist/helpers/external-id.js +0 -20
  153. package/dist/helpers/file-metadata.d.ts +0 -50
  154. package/dist/helpers/file-metadata.js +0 -91
  155. package/dist/helpers/gift-wraps.d.ts +0 -67
  156. package/dist/helpers/gift-wraps.js +0 -205
  157. package/dist/helpers/groups.d.ts +0 -26
  158. package/dist/helpers/groups.js +0 -49
  159. package/dist/helpers/hashtag.d.ts +0 -2
  160. package/dist/helpers/hashtag.js +0 -7
  161. package/dist/helpers/highlight.d.ts +0 -45
  162. package/dist/helpers/highlight.js +0 -76
  163. package/dist/helpers/legacy-messages.d.ts +0 -32
  164. package/dist/helpers/legacy-messages.js +0 -50
  165. package/dist/helpers/lists.d.ts +0 -58
  166. package/dist/helpers/lists.js +0 -111
  167. package/dist/helpers/lnurl.d.ts +0 -8
  168. package/dist/helpers/lnurl.js +0 -44
  169. package/dist/helpers/messages.d.ts +0 -31
  170. package/dist/helpers/messages.js +0 -57
  171. package/dist/helpers/mutes.d.ts +0 -33
  172. package/dist/helpers/mutes.js +0 -110
  173. package/dist/helpers/picture-post.d.ts +0 -5
  174. package/dist/helpers/picture-post.js +0 -6
  175. package/dist/helpers/poll.d.ts +0 -46
  176. package/dist/helpers/poll.js +0 -78
  177. package/dist/helpers/reactions.d.ts +0 -8
  178. package/dist/helpers/reactions.js +0 -56
  179. package/dist/helpers/reports.d.ts +0 -28
  180. package/dist/helpers/reports.js +0 -38
  181. package/dist/helpers/share.d.ts +0 -19
  182. package/dist/helpers/share.js +0 -44
  183. package/dist/helpers/stream-chat.d.ts +0 -4
  184. package/dist/helpers/stream-chat.js +0 -9
  185. package/dist/helpers/stream.d.ts +0 -31
  186. package/dist/helpers/stream.js +0 -81
  187. package/dist/helpers/threading.d.ts +0 -55
  188. package/dist/helpers/threading.js +0 -94
  189. package/dist/helpers/user-status.d.ts +0 -18
  190. package/dist/helpers/user-status.js +0 -22
  191. package/dist/helpers/wrapped-messages.d.ts +0 -14
  192. package/dist/helpers/wrapped-messages.js +0 -22
  193. package/dist/helpers/zap.d.ts +0 -46
  194. package/dist/helpers/zap.js +0 -125
  195. package/dist/models/blossom.d.ts +0 -4
  196. package/dist/models/blossom.js +0 -10
  197. package/dist/models/bookmarks.d.ts +0 -8
  198. package/dist/models/bookmarks.js +0 -24
  199. package/dist/models/calendar.d.ts +0 -6
  200. package/dist/models/calendar.js +0 -15
  201. package/dist/models/channels.d.ts +0 -11
  202. package/dist/models/channels.js +0 -61
  203. package/dist/models/comments.d.ts +0 -4
  204. package/dist/models/comments.js +0 -11
  205. package/dist/models/gift-wrap.d.ts +0 -7
  206. package/dist/models/gift-wrap.js +0 -20
  207. package/dist/models/legacy-messages.d.ts +0 -14
  208. package/dist/models/legacy-messages.js +0 -64
  209. package/dist/models/mutes.d.ts +0 -9
  210. package/dist/models/mutes.js +0 -26
  211. package/dist/models/pins.d.ts +0 -4
  212. package/dist/models/pins.js +0 -10
  213. package/dist/models/reactions.d.ts +0 -4
  214. package/dist/models/reactions.js +0 -16
  215. package/dist/models/relays.d.ts +0 -27
  216. package/dist/models/relays.js +0 -44
  217. package/dist/models/thread.d.ts +0 -26
  218. package/dist/models/thread.js +0 -88
  219. package/dist/models/user-status.d.ts +0 -11
  220. package/dist/models/user-status.js +0 -33
  221. package/dist/models/wrapped-messages.d.ts +0 -31
  222. package/dist/models/wrapped-messages.js +0 -76
  223. package/dist/models/zaps.d.ts +0 -10
  224. package/dist/models/zaps.js +0 -26
package/README.md CHANGED
@@ -1,12 +1,16 @@
1
1
  # applesauce-core
2
2
 
3
- AppleSauce is a collection of utilities for building reactive nostr applications. The core package provides an in-memory event database and reactive models to help you build nostr UIs with less code.
3
+ Applesauce is a collection of utilities for building reactive nostr applications. The core package provides protocol-level functionality including an in-memory event database, generic event utilities, and basic reactive models.
4
4
 
5
5
  ## Key Components
6
6
 
7
7
  - **Helpers**: Core utility methods for parsing and extracting data from nostr events
8
8
  - **EventStore**: In-memory database for storing and subscribing to nostr events
9
- - **Models**: Complex subscriptions for common nostr data patterns
9
+ - **Helpers**: Core protocol-level utility methods for working with events, tags, filters, and pointers
10
+ - **Models**: Generic models for common nostr data patterns (profiles, reactions, zaps, etc.)
11
+ - **Observable**: RxJS utilities for reactive programming
12
+
13
+ > **Note**: For NIP-specific helpers and models (NIP-10 threading, NIP-22 comments, NIP-53 streams, etc.), see the [`applesauce-common`](../common/README.md) package.
10
14
 
11
15
  ## Documentation
12
16
 
@@ -0,0 +1,57 @@
1
+ import { EventTemplate, NostrEvent, UnsignedEvent } from "../helpers/event.js";
2
+ import { ModifyTagsOptions } from "../operations/tags.js";
3
+ import { EventFactoryTemplate } from "./methods.js";
4
+ import { EventBlueprint, EventFactoryContext, EventOperation, IEventFactory } from "./types.js";
5
+ /**
6
+ * Base class that provides event creation functionality.
7
+ * This class can be extended by other packages to add additional helpful event creation methods.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * // In another package (e.g., applesauce-common)
12
+ * import { EventFactory } from "applesauce-core/event-factory";
13
+ * import { NoteBlueprint, ReactionBlueprint } from "applesauce-common/blueprints";
14
+ *
15
+ * // Add methods to the prototype
16
+ * EventFactory.prototype.note = function(content, options) {
17
+ * return this.create(NoteBlueprint, content, options);
18
+ * };
19
+ *
20
+ * EventFactory.prototype.reaction = function(event, emoji) {
21
+ * return this.create(ReactionBlueprint, event, emoji);
22
+ * };
23
+ *
24
+ * // Extend the type via module augmentation
25
+ * declare module "applesauce-core/event-factory" {
26
+ * interface EventFactory {
27
+ * note(content: string, options?: NoteBlueprintOptions): Promise<EventTemplate>;
28
+ * reaction(event: NostrEvent, emoji?: string): Promise<EventTemplate>;
29
+ * }
30
+ * }
31
+ * ```
32
+ */
33
+ export declare class EventFactory implements IEventFactory {
34
+ context: EventFactoryContext;
35
+ constructor(context?: EventFactoryContext);
36
+ /** Build an event template with operations */
37
+ build(template: EventFactoryTemplate, ...operations: (EventOperation | undefined)[]): Promise<EventTemplate>;
38
+ /** Create an event from a blueprint */
39
+ create<T extends EventTemplate | UnsignedEvent | NostrEvent>(blueprint: EventBlueprint<T>): Promise<T>;
40
+ create<T extends EventTemplate | UnsignedEvent | NostrEvent, Args extends Array<any>>(blueprint: (...args: Args) => EventBlueprint<T>, ...args: Args): Promise<T>;
41
+ /** Modify an existing event with operations and updated the created_at */
42
+ modify(draft: EventTemplate | UnsignedEvent | NostrEvent, ...operations: (EventOperation | undefined)[]): Promise<EventTemplate>;
43
+ /** Modify a lists public and hidden tags and updated the created_at */
44
+ modifyTags(event: EventTemplate | UnsignedEvent | NostrEvent, tagOperations?: ModifyTagsOptions, eventOperations?: EventOperation | (EventOperation | undefined)[]): Promise<EventTemplate>;
45
+ /** Attaches the signers pubkey to an event template */
46
+ stamp(draft: EventTemplate | UnsignedEvent): Promise<UnsignedEvent>;
47
+ /** Signs a event template with the signer */
48
+ sign(draft: EventTemplate | UnsignedEvent): Promise<NostrEvent>;
49
+ /** Sets the signer in the context */
50
+ setSigner(signer: EventFactoryContext["signer"]): void;
51
+ /** clears the signer in the context */
52
+ clearSigner(): void;
53
+ /** sets the client in the context */
54
+ setClient(client: EventFactoryContext["client"]): void;
55
+ /** clears the client in the context */
56
+ clearClient(): void;
57
+ }
@@ -0,0 +1,94 @@
1
+ import { sign, stamp } from "../operations/event.js";
2
+ import { modifyTags } from "../operations/tags.js";
3
+ import { buildEvent, modifyEvent } from "./methods.js";
4
+ /**
5
+ * Base class that provides event creation functionality.
6
+ * This class can be extended by other packages to add additional helpful event creation methods.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * // In another package (e.g., applesauce-common)
11
+ * import { EventFactory } from "applesauce-core/event-factory";
12
+ * import { NoteBlueprint, ReactionBlueprint } from "applesauce-common/blueprints";
13
+ *
14
+ * // Add methods to the prototype
15
+ * EventFactory.prototype.note = function(content, options) {
16
+ * return this.create(NoteBlueprint, content, options);
17
+ * };
18
+ *
19
+ * EventFactory.prototype.reaction = function(event, emoji) {
20
+ * return this.create(ReactionBlueprint, event, emoji);
21
+ * };
22
+ *
23
+ * // Extend the type via module augmentation
24
+ * declare module "applesauce-core/event-factory" {
25
+ * interface EventFactory {
26
+ * note(content: string, options?: NoteBlueprintOptions): Promise<EventTemplate>;
27
+ * reaction(event: NostrEvent, emoji?: string): Promise<EventTemplate>;
28
+ * }
29
+ * }
30
+ * ```
31
+ */
32
+ export class EventFactory {
33
+ context;
34
+ constructor(context = {}) {
35
+ this.context = context;
36
+ }
37
+ /** Build an event template with operations */
38
+ async build(template, ...operations) {
39
+ return await buildEvent(template, this.context, ...operations);
40
+ }
41
+ async create(blueprint, ...args) {
42
+ // Context, blueprint(context)
43
+ if (arguments.length === 1) {
44
+ return (await blueprint(this.context));
45
+ }
46
+ // Context, blueprintConstructor(...args)(context), ...args
47
+ else {
48
+ const constructor = blueprint;
49
+ return await constructor(...args)(this.context);
50
+ }
51
+ }
52
+ /** Modify an existing event with operations and updated the created_at */
53
+ async modify(draft, ...operations) {
54
+ return await modifyEvent(draft, this.context, ...operations);
55
+ }
56
+ /** Modify a lists public and hidden tags and updated the created_at */
57
+ async modifyTags(event, tagOperations, eventOperations) {
58
+ let eventOperationsArr = [];
59
+ // normalize event operation arg
60
+ if (eventOperations === undefined)
61
+ eventOperationsArr = [];
62
+ else if (typeof eventOperations === "function")
63
+ eventOperationsArr = [eventOperations];
64
+ else if (Array.isArray(eventOperations))
65
+ eventOperationsArr = eventOperations.filter((e) => !!e);
66
+ // modify event
67
+ return await this.modify(event, modifyTags(tagOperations), ...eventOperationsArr);
68
+ }
69
+ /** Attaches the signers pubkey to an event template */
70
+ async stamp(draft) {
71
+ return await stamp()(draft, this.context);
72
+ }
73
+ /** Signs a event template with the signer */
74
+ async sign(draft) {
75
+ return await sign()(draft, this.context);
76
+ }
77
+ // Helpers
78
+ /** Sets the signer in the context */
79
+ setSigner(signer) {
80
+ this.context.signer = signer;
81
+ }
82
+ /** clears the signer in the context */
83
+ clearSigner() {
84
+ this.context.signer = undefined;
85
+ }
86
+ /** sets the client in the context */
87
+ setClient(client) {
88
+ this.context.client = client;
89
+ }
90
+ /** clears the client in the context */
91
+ clearClient() {
92
+ this.context.client = undefined;
93
+ }
94
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export * from "./event-factory.js";
3
+ export * from "./methods.js";
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export * from "./event-factory.js";
3
+ export * from "./methods.js";
@@ -0,0 +1,17 @@
1
+ import { EventTemplate, NostrEvent, UnsignedEvent } from "../helpers/event.js";
2
+ import { EventBlueprint, EventFactoryContext, EventOperation } from "./types.js";
3
+ export type EventFactoryTemplate = {
4
+ kind: number;
5
+ content?: string;
6
+ tags?: string[][];
7
+ created_at?: number;
8
+ };
9
+ /** Creates an event using a template, context, and a set of operations */
10
+ export declare function buildEvent(template: EventFactoryTemplate, context: EventFactoryContext, ...operations: (EventOperation | undefined)[]): Promise<EventTemplate>;
11
+ /** Creates a blueprint function with operations */
12
+ export declare function blueprint(kind: number, ...operations: (EventOperation | undefined)[]): EventBlueprint;
13
+ /** Creates an event from a context and a blueprint */
14
+ export declare function createEvent<T extends EventTemplate | UnsignedEvent | NostrEvent>(context: EventFactoryContext, blueprint: EventBlueprint<T>): Promise<T>;
15
+ export declare function createEvent<T extends EventTemplate | UnsignedEvent | NostrEvent, Args extends Array<any>>(context: EventFactoryContext, blueprintConstructor: (...args: Args) => EventBlueprint<T>, ...args: Args): Promise<T>;
16
+ /** Modifies an event using a context and a set of operations */
17
+ export declare function modifyEvent(event: EventTemplate | UnsignedEvent | NostrEvent, context: EventFactoryContext, ...operations: (EventOperation | undefined)[]): Promise<EventTemplate>;
@@ -0,0 +1,44 @@
1
+ import { EncryptedContentSymbol } from "../helpers/encrypted-content.js";
2
+ import { isEvent } from "../helpers/event.js";
3
+ import { eventPipe } from "../helpers/pipeline.js";
4
+ import { unixNow } from "../helpers/time.js";
5
+ import { setClient } from "../operations/client.js";
6
+ import { includeReplaceableIdentifier, stripSignature, stripStamp, stripSymbols, updateCreatedAt, } from "../operations/event.js";
7
+ /** Wraps a set of operations with common event operations */
8
+ function wrapCommon(...operations) {
9
+ return eventPipe(
10
+ // Remove all symbols from the event except for the encrypted content symbol
11
+ stripSymbols([EncryptedContentSymbol]),
12
+ // Ensure all addressable events have "d" tags
13
+ includeReplaceableIdentifier(),
14
+ // Apply operations
15
+ ...operations,
16
+ // Include client tag if its set in the context
17
+ (draft, ctx) => (ctx.client ? setClient(ctx.client.name, ctx.client.address)(draft, ctx) : draft));
18
+ }
19
+ /** Creates an event using a template, context, and a set of operations */
20
+ export async function buildEvent(template, context, ...operations) {
21
+ return await wrapCommon(stripSignature(), stripStamp(), ...operations)({ created_at: unixNow(), tags: [], content: "", ...template }, context);
22
+ }
23
+ /** Creates a blueprint function with operations */
24
+ export function blueprint(kind, ...operations) {
25
+ return async (context) => await buildEvent({ kind }, context, ...operations);
26
+ }
27
+ export async function createEvent(context, blueprint, ...args) {
28
+ // Context, blueprint(context)
29
+ if (arguments.length === 2) {
30
+ return (await blueprint(context));
31
+ }
32
+ // Context, blueprintConstructor(...args)(context), ...args
33
+ else {
34
+ const constructor = blueprint;
35
+ return await constructor(...args)(context);
36
+ }
37
+ }
38
+ /** Modifies an event using a context and a set of operations */
39
+ export async function modifyEvent(event, context, ...operations) {
40
+ // NOTE: Unwrapping evnet object in order to handle cast events from applesauce-common
41
+ if ("event" in event && isEvent(event.event))
42
+ event = event.event;
43
+ return await wrapCommon(stripSignature(), stripStamp(), updateCreatedAt(), ...operations)(event, context);
44
+ }
@@ -0,0 +1,76 @@
1
+ import { EventTemplate, NostrEvent, UnsignedEvent } from "../helpers/event.js";
2
+ import { AddressPointer } from "../helpers/pointers.js";
3
+ import { ModifyTagsOptions } from "../operations/tags.js";
4
+ import { EventFactoryTemplate } from "./methods.js";
5
+ /** Nostr event signer */
6
+ export interface EventSigner {
7
+ getPublicKey: () => Promise<string> | string;
8
+ signEvent: (draft: EventTemplate | UnsignedEvent) => Promise<NostrEvent> | NostrEvent;
9
+ nip04?: {
10
+ encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
11
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
12
+ };
13
+ nip44?: {
14
+ encrypt: (pubkey: string, plaintext: string) => Promise<string> | string;
15
+ decrypt: (pubkey: string, ciphertext: string) => Promise<string> | string;
16
+ };
17
+ }
18
+ /** A context with optional methods for getting relay hints */
19
+ export interface RelayHintContext {
20
+ getEventRelayHint?: (event: string) => string | undefined | Promise<string> | Promise<undefined>;
21
+ getPubkeyRelayHint?: (pubkey: string) => string | undefined | Promise<string> | Promise<undefined>;
22
+ }
23
+ /** A context with an optional signer */
24
+ export interface EventSignerContext {
25
+ signer?: EventSigner;
26
+ }
27
+ export interface EventFactoryClient {
28
+ name: string;
29
+ address?: Omit<AddressPointer, "kind" | "relays">;
30
+ }
31
+ /** A context with an optional NIP-89 app pointer */
32
+ export interface ClientPointerContext {
33
+ client?: EventFactoryClient;
34
+ }
35
+ /** NIP-30 emoji type. this should be moved out of the core package to common */
36
+ export type Emoji = {
37
+ /** The emoji shortcode (without the ::) */
38
+ shortcode: string;
39
+ /** The URL to the emoji image */
40
+ url: string;
41
+ };
42
+ export interface EmojiContext {
43
+ /** An array of custom emojis that will be used for text notes */
44
+ emojis?: Emoji[];
45
+ }
46
+ /** All options that can be passed when building an event */
47
+ export interface EventFactoryContext extends ClientPointerContext, EventSignerContext, RelayHintContext, EmojiContext {
48
+ }
49
+ /** A single operation that modifies an events public or hidden tags array */
50
+ export type Operation<I extends unknown = unknown, R extends unknown = unknown> = (value: I, context: EventFactoryContext) => R | Promise<R>;
51
+ /** A single operation that modifies an events public or hidden tags array */
52
+ export type TagOperation = Operation<string[][], string[][]>;
53
+ /** A single operation that modifies an event */
54
+ export type EventOperation<I extends EventTemplate | UnsignedEvent | NostrEvent = EventTemplate, R extends EventTemplate | UnsignedEvent | NostrEvent = EventTemplate> = Operation<I, R>;
55
+ /** A method that creates a new event based on a set of operations */
56
+ export type EventBlueprint<T extends EventTemplate | UnsignedEvent | NostrEvent = EventTemplate> = (context: EventFactoryContext) => Promise<T>;
57
+ /**
58
+ * Core helpful event creation interface.
59
+ * Contains only methods that use blueprints from the core package.
60
+ * Other packages (like applesauce-common) can extend this interface via module augmentation.
61
+ */
62
+ export interface IEventFactory {
63
+ /** Build an event template with operations */
64
+ build(template: EventFactoryTemplate, ...operations: (EventOperation | undefined)[]): Promise<EventTemplate>;
65
+ /** Create an event from a blueprint */
66
+ create<T extends EventTemplate | UnsignedEvent | NostrEvent>(blueprint: EventBlueprint<T>): Promise<T>;
67
+ create<T extends EventTemplate | UnsignedEvent | NostrEvent, Args extends Array<any>>(blueprint: (...args: Args) => EventBlueprint<T>, ...args: Args): Promise<T>;
68
+ /** Modify an existing event with operations and updated the created_at */
69
+ modify(draft: EventTemplate | UnsignedEvent | NostrEvent, ...operations: (EventOperation | undefined)[]): Promise<EventTemplate>;
70
+ /** Modify a lists public and hidden tags and updated the created_at */
71
+ modifyTags(event: EventTemplate | UnsignedEvent | NostrEvent, tagOperations?: ModifyTagsOptions, eventOperations?: EventOperation | (EventOperation | undefined)[]): Promise<EventTemplate>;
72
+ /** Attaches the signers pubkey to an event template */
73
+ stamp(draft: EventTemplate | UnsignedEvent): Promise<UnsignedEvent>;
74
+ /** Signs a event template with the signer */
75
+ sign(draft: EventTemplate | UnsignedEvent): Promise<NostrEvent>;
76
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ import { Observable } from "rxjs";
2
+ import { NostrEvent } from "../helpers/event.js";
3
+ import { DeleteEventNotification, IAsyncDeleteManager } from "./interface.js";
4
+ /** Async manager for deletion state, ensuring users can only delete their own events */
5
+ export declare class AsyncDeleteManager implements IAsyncDeleteManager {
6
+ /** A stream of pointers that may have been deleted */
7
+ readonly deleted$: Observable<DeleteEventNotification>;
8
+ /** Internal sync delete manager instance for state */
9
+ private internal;
10
+ constructor();
11
+ /**
12
+ * Process a kind 5 delete event
13
+ * Extracts event pointers and address pointers from the delete event
14
+ * Enforces that users can only delete their own events
15
+ */
16
+ add(deleteEvent: NostrEvent): Promise<DeleteEventNotification[]>;
17
+ /**
18
+ * Check if an event is deleted
19
+ * Verifies the event was deleted by its own author
20
+ */
21
+ check(event: NostrEvent): Promise<boolean>;
22
+ /**
23
+ * Filter out all deleted events from an array of events
24
+ */
25
+ filter(events: NostrEvent[]): Promise<NostrEvent[]>;
26
+ }
@@ -0,0 +1,33 @@
1
+ import { DeleteManager } from "./delete-manager.js";
2
+ /** Async manager for deletion state, ensuring users can only delete their own events */
3
+ export class AsyncDeleteManager {
4
+ /** A stream of pointers that may have been deleted */
5
+ deleted$;
6
+ /** Internal sync delete manager instance for state */
7
+ internal;
8
+ constructor() {
9
+ this.internal = new DeleteManager();
10
+ this.deleted$ = this.internal.deleted$;
11
+ }
12
+ /**
13
+ * Process a kind 5 delete event
14
+ * Extracts event pointers and address pointers from the delete event
15
+ * Enforces that users can only delete their own events
16
+ */
17
+ async add(deleteEvent) {
18
+ return this.internal.add(deleteEvent);
19
+ }
20
+ /**
21
+ * Check if an event is deleted
22
+ * Verifies the event was deleted by its own author
23
+ */
24
+ async check(event) {
25
+ return this.internal.check(event);
26
+ }
27
+ /**
28
+ * Filter out all deleted events from an array of events
29
+ */
30
+ async filter(events) {
31
+ return this.internal.filter(events);
32
+ }
33
+ }
@@ -1,94 +1,64 @@
1
- import { Filter, NostrEvent } from "nostr-tools";
2
- import { AddressPointer, EventPointer } from "nostr-tools/nip19";
3
1
  import { Observable, Subject } from "rxjs";
4
- import { AddressPointerWithoutD } from "../helpers/pointers.js";
2
+ import { NostrEvent } from "../helpers/event.js";
3
+ import { Filter } from "../helpers/filter.js";
4
+ import { AddressPointer, AddressPointerWithoutD, EventPointer } from "../helpers/pointers.js";
5
5
  import { EventMemory } from "./event-memory.js";
6
- import { IAsyncEventDatabase, IAsyncEventStore } from "./interface.js";
7
- declare const AsyncEventStore_base: {
8
- new (...args: any[]): {
9
- [x: string]: any;
10
- models: Map<import("./interface.js").ModelConstructor<any, any[], import("./interface.js").IEventStore | IAsyncEventStore>, Map<string, Observable<any>>>;
11
- modelKeepWarm: number;
12
- model<T extends unknown, Args extends Array<any>>(constructor: import("./interface.js").ModelConstructor<T, Args, import("./interface.js").IEventStore | IAsyncEventStore>, ...args: Args): Observable<T>;
13
- filters(filters: Filter | Filter[], onlyNew?: boolean): Observable<NostrEvent>;
14
- event(pointer: string | EventPointer): Observable<NostrEvent | undefined>;
15
- replaceable(pointer: AddressPointer | AddressPointerWithoutD): Observable<NostrEvent | undefined>;
16
- replaceable(kind: number, pubkey: string, identifier?: string): Observable<NostrEvent | undefined>;
17
- addressable(pointer: AddressPointer): Observable<NostrEvent | undefined>;
18
- timeline(filters: Filter | Filter[], includeOldVersion?: boolean): Observable<NostrEvent[]>;
19
- profile(user: string | import("nostr-tools/nip19").ProfilePointer): Observable<import("../helpers/profile.js").ProfileContent | undefined>;
20
- contacts(user: string | import("nostr-tools/nip19").ProfilePointer): Observable<import("nostr-tools/nip19").ProfilePointer[]>;
21
- mutes(user: string | import("nostr-tools/nip19").ProfilePointer): Observable<import("../helpers/mutes.js").Mutes | undefined>;
22
- mailboxes(user: string | import("nostr-tools/nip19").ProfilePointer): Observable<{
23
- inboxes: string[];
24
- outboxes: string[];
25
- } | undefined>;
26
- blossomServers(user: string | import("nostr-tools/nip19").ProfilePointer): Observable<URL[]>;
27
- reactions(event: NostrEvent): Observable<import("nostr-tools").Event[]>;
28
- thread(root: string | EventPointer | AddressPointer): Observable<import("../models/thread.js").Thread>;
29
- comments(event: NostrEvent): Observable<import("nostr-tools").Event[]>;
30
- events(ids: string[]): Observable<Record<string, NostrEvent | undefined>>;
31
- replaceableSet(pointers: {
32
- kind: number;
33
- pubkey: string;
34
- identifier?: string;
35
- }[]): Observable<Record<string, NostrEvent | undefined>>;
36
- };
37
- } & {
38
- new (): {};
6
+ import { EventModels } from "./event-models.js";
7
+ import { IAsyncDeleteManager, IAsyncEventDatabase, IAsyncEventStore, IExpirationManager } from "./interface.js";
8
+ export type AsyncEventStoreOptions = {
9
+ /** Keep deleted events in the store */
10
+ keepDeleted?: boolean;
11
+ /** Keep expired events in the store */
12
+ keepExpired?: boolean;
13
+ /** Enable this to keep old versions of replaceable events */
14
+ keepOldVersions?: boolean;
15
+ /** The database to use for storing events */
16
+ database: IAsyncEventDatabase;
17
+ /** Custom {@link IAsyncDeleteManager} implementation */
18
+ deleteManager?: IAsyncDeleteManager;
19
+ /** Custom {@link IExpirationManager} implementation */
20
+ expirationManager?: IExpirationManager;
21
+ /** The method used to verify events */
22
+ verifyEvent?: (event: NostrEvent) => boolean;
39
23
  };
40
24
  /** An async wrapper around an async event database that handles replaceable events, deletes, and models */
41
- export declare class AsyncEventStore extends AsyncEventStore_base implements IAsyncEventStore {
25
+ export declare class AsyncEventStore extends EventModels implements IAsyncEventStore {
42
26
  database: IAsyncEventDatabase;
43
27
  /** Optional memory database for ensuring single event instances */
44
28
  memory: EventMemory;
29
+ /** Manager for handling event deletions with authorization */
30
+ private deletes;
31
+ /** Manager for handling event expirations */
32
+ private expiration;
45
33
  /** Enable this to keep old versions of replaceable events */
46
34
  keepOldVersions: boolean;
47
- /** Enable this to keep expired events */
35
+ /** Keep expired events in the store */
48
36
  keepExpired: boolean;
49
- /**
50
- * A method used to verify new events before added them
51
- * @returns true if the event is valid, false if it should be ignored
52
- */
53
- verifyEvent?: (event: NostrEvent) => boolean;
37
+ /** Keep deleted events in the store */
38
+ keepDeleted: boolean;
39
+ /** The method used to verify events */
40
+ private _verifyEventMethod?;
41
+ /** Get the method used to verify events */
42
+ get verifyEvent(): undefined | ((event: NostrEvent) => boolean);
43
+ /** Sets the method used to verify events */
44
+ set verifyEvent(method: undefined | ((event: NostrEvent) => boolean));
54
45
  /** A stream of new events added to the store */
55
- insert$: Subject<import("nostr-tools").Event>;
56
- /** A stream of events that have been updated */
57
- update$: Subject<import("nostr-tools").Event>;
46
+ insert$: Subject<NostrEvent>;
47
+ /** A stream of events that have been updated (Warning: this is a very noisy stream, use with caution) */
48
+ update$: Subject<NostrEvent>;
58
49
  /** A stream of events that have been removed */
59
- remove$: Subject<import("nostr-tools").Event>;
50
+ remove$: Subject<NostrEvent>;
60
51
  /**
61
52
  * A method that will be called when an event isn't found in the store
62
- * @experimental
63
- */
64
- eventLoader?: (pointer: EventPointer) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
65
- /**
66
- * A method that will be called when a replaceable event isn't found in the store
67
- * @experimental
68
- */
69
- replaceableLoader?: (pointer: AddressPointerWithoutD) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
70
- /**
71
- * A method that will be called when an addressable event isn't found in the store
72
- * @experimental
73
53
  */
74
- addressableLoader?: (pointer: AddressPointer) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
75
- constructor(database: IAsyncEventDatabase);
54
+ eventLoader?: (pointer: EventPointer | AddressPointer | AddressPointerWithoutD) => Observable<NostrEvent> | Promise<NostrEvent | undefined>;
55
+ constructor(options: AsyncEventStoreOptions);
76
56
  /** A method to add all events to memory to ensure there is only ever a single instance of an event */
77
57
  private mapToMemory;
78
- protected deletedIds: Set<string>;
79
- protected deletedCoords: Map<string, number>;
80
- protected checkDeleted(event: string | NostrEvent): boolean;
81
- protected expirations: Map<string, number>;
82
- /** Adds an event to the expiration map */
83
- protected addExpiration(event: NostrEvent): void;
84
- protected expirationTimeout: number | null;
85
- protected nextExpirationCheck: number | null;
86
- protected handleExpiringEvent(event: NostrEvent): void;
87
- /** Remove expired events from the store */
88
- protected pruneExpired(): Promise<void>;
89
- protected handleDeleteEvent(deleteEvent: NostrEvent): Promise<void>;
90
- /** Copies important metadata from and identical event to another */
91
- static mergeDuplicateEvent(source: NostrEvent, dest: NostrEvent): void;
58
+ /** Handle a delete event by pointer */
59
+ private handleDeleteNotification;
60
+ /** Handle an expired event by id */
61
+ private handleExpiredNotification;
92
62
  /**
93
63
  * Adds an event to the store and update subscriptions
94
64
  * @returns The existing event or the event that was added, if it was ignored returns null
@@ -101,9 +71,9 @@ export declare class AsyncEventStore extends AsyncEventStore_base implements IAs
101
71
  /** Add an event to the store and notifies all subscribes it has updated */
102
72
  update(event: NostrEvent): Promise<void>;
103
73
  /** Check if the store has an event by id */
104
- hasEvent(id: string): Promise<boolean>;
74
+ hasEvent(id: string | EventPointer | AddressPointer | AddressPointerWithoutD): Promise<boolean>;
105
75
  /** Get an event by id from the store */
106
- getEvent(id: string): Promise<NostrEvent | undefined>;
76
+ getEvent(id: string | EventPointer | AddressPointer | AddressPointerWithoutD): Promise<NostrEvent | undefined>;
107
77
  /** Check if the store has a replaceable event */
108
78
  hasReplaceable(kind: number, pubkey: string, d?: string): Promise<boolean>;
109
79
  /** Gets the latest version of a replaceable event */
@@ -128,9 +98,4 @@ export declare class AsyncEventStore extends AsyncEventStore_base implements IAs
128
98
  unclaimed(): Generator<NostrEvent>;
129
99
  /** Removes any event that is not being used by a subscription */
130
100
  prune(limit?: number): number;
131
- /** Returns an observable that completes when an event is removed */
132
- removed(id: string): Observable<never>;
133
- /** Creates an observable that emits when event is updated */
134
- updated(event: string | NostrEvent): Observable<NostrEvent>;
135
101
  }
136
- export {};