applesauce-actions 0.0.0-next-20251220152312 → 0.0.0-next-20251231055351

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,12 +18,12 @@ Actions are common pre-built async operations that apps can perform. They use:
18
18
  - `EventFactory` to build and sign new nostr events
19
19
  - A `publish` method to publish or save the resulting events
20
20
 
21
- The package provides an `ActionHub` class that combines these components into a single manager for easier action execution.
21
+ The package provides an `ActionRunner` class that combines these components into a single manager for easier action execution.
22
22
 
23
23
  ## Basic Usage
24
24
 
25
25
  ```typescript
26
- import { ActionHub } from "applesauce-actions";
26
+ import { ActionRunner } from "applesauce-actions";
27
27
  import { FollowUser } from "applesauce-actions/actions";
28
28
 
29
29
  async function publishEvent(event: NostrEvent) {
@@ -31,7 +31,7 @@ async function publishEvent(event: NostrEvent) {
31
31
  }
32
32
 
33
33
  // Create an action hub with your event store, factory and publish method
34
- const hub = new ActionHub(eventStore, eventFactory, publishEvent);
34
+ const hub = new ActionRunner(eventStore, eventFactory, publishEvent);
35
35
 
36
36
  // Example: Follow a user
37
37
  await hub
@@ -32,7 +32,7 @@ export type Action = (context: ActionContext) => Promise<void>;
32
32
  /** A function that takes arguments and returns an action */
33
33
  export type ActionBuilder<Args extends Array<any>> = (...args: Args) => Action;
34
34
  /** The main class that runs actions */
35
- export declare class ActionHub {
35
+ export declare class ActionRunner {
36
36
  events: IEventStoreRead & IEventStoreStreams & IEventSubscriptions & IEventStoreActions & EventModels;
37
37
  factory: EventFactory;
38
38
  private publishMethod?;
@@ -48,4 +48,6 @@ export declare class ActionHub {
48
48
  /** Run an action without publishing the events */
49
49
  exec<Args extends Array<any>>(builder: ActionBuilder<Args>, ...args: Args): Observable<NostrEvent>;
50
50
  }
51
+ /** @deprecated Use ActionRunner instead */
52
+ export declare const ActionHub: typeof ActionRunner;
51
53
  export {};
@@ -1,7 +1,7 @@
1
1
  import { castUser } from "applesauce-common/casts/user";
2
2
  import { from, identity, isObservable, lastValueFrom, Observable, switchMap, tap } from "rxjs";
3
3
  /** The main class that runs actions */
4
- export class ActionHub {
4
+ export class ActionRunner {
5
5
  events;
6
6
  factory;
7
7
  publishMethod;
@@ -37,7 +37,7 @@ export class ActionHub {
37
37
  /** Internal method for publishing events to relays */
38
38
  async publish(event, relays) {
39
39
  if (!this.publishMethod)
40
- throw new Error("Missing publish method, use ActionHub.exec");
40
+ throw new Error("Missing publish method, use ActionRunner.exec");
41
41
  // Unwrap array of events to publish
42
42
  if (Array.isArray(event)) {
43
43
  await Promise.all(event.map((e) => this.publish(e, relays)));
@@ -87,3 +87,5 @@ export class ActionHub {
87
87
  this.saveToStore ? tap((event) => this.events.add(event)) : identity);
88
88
  }
89
89
  }
90
+ /** @deprecated Use ActionRunner instead */
91
+ export const ActionHub = ActionRunner;
@@ -1,2 +1,2 @@
1
- import { Action } from "../action-hub.js";
1
+ import { Action } from "../action-runner.js";
2
2
  export declare function UpdateAppData<T>(identifier: string, data: T): Action;
@@ -1,4 +1,4 @@
1
- import { Action } from "../action-hub.js";
1
+ import { Action } from "../action-runner.js";
2
2
  /** An action that adds a relay to the 10006 blocked relays event */
3
3
  export declare function AddBlockedRelay(relay: string | string[], hidden?: boolean): Action;
4
4
  /** An action that removes a relay from the 10006 blocked relays event */
@@ -7,7 +7,9 @@ import { of, timeout } from "rxjs";
7
7
  function ModifyBlockedRelaysEvent(operations) {
8
8
  return async ({ events, factory, user, publish, sign }) => {
9
9
  const [event, outboxes] = await Promise.all([
10
- firstValueFrom(events.replaceable(kinds.BlockedRelaysList, user.pubkey).pipe(timeout({ first: 1000, with: () => of(undefined) }))),
10
+ firstValueFrom(events
11
+ .replaceable(kinds.BlockedRelaysList, user.pubkey)
12
+ .pipe(timeout({ first: 1000, with: () => of(undefined) }))),
11
13
  user.outboxes$.$first(1000, undefined),
12
14
  ]);
13
15
  // Modify or build new event
@@ -1,4 +1,4 @@
1
- import { Action } from "../action-hub.js";
1
+ import { Action } from "../action-runner.js";
2
2
  /** An action that adds a server to the Blossom servers event */
3
3
  export declare function AddBlossomServer(server: string | URL | (string | URL)[]): Action;
4
4
  /** An action that removes a server from the Blossom servers event */
@@ -1,6 +1,6 @@
1
1
  import { AddressPointer, EventPointer } from "applesauce-core/helpers";
2
2
  import { NostrEvent } from "applesauce-core/helpers/event";
3
- import { Action } from "../action-hub.js";
3
+ import { Action } from "../action-runner.js";
4
4
  /**
5
5
  * An action that adds a note or article to the bookmark list or a bookmark set
6
6
  * @param event the event to bookmark
@@ -1,6 +1,6 @@
1
1
  import { AddressPointer } from "applesauce-core/helpers";
2
2
  import { NostrEvent } from "applesauce-core/helpers/event";
3
- import { Action } from "../action-hub.js";
3
+ import { Action } from "../action-runner.js";
4
4
  /** Adds a calendar event to a calendar */
5
5
  export declare function AddEventToCalendar(calendar: NostrEvent | AddressPointer, event: NostrEvent | AddressPointer): Action;
6
6
  /** Removes a calendar event from a calendar */
@@ -0,0 +1,10 @@
1
+ import { CommentBlueprintOptions } from "applesauce-common/blueprints";
2
+ import { CommentPointer } from "applesauce-common/helpers/comment";
3
+ import { NostrEvent } from "applesauce-core/helpers/event";
4
+ import { Action } from "../action-runner.js";
5
+ /**
6
+ * Creates a comment on an event or CommentPointer and publishes it to:
7
+ * - The parent event's author's inboxes (if the author exists and pubkey is available)
8
+ * - The current user's outboxes
9
+ */
10
+ export declare function CreateComment(parent: NostrEvent | CommentPointer, content: string, options?: CommentBlueprintOptions): Action;
@@ -0,0 +1,43 @@
1
+ import { CommentBlueprint } from "applesauce-common/blueprints";
2
+ import { castUser } from "applesauce-common/casts";
3
+ import { isCommentAddressPointer, isCommentEventPointer } from "applesauce-common/helpers/comment";
4
+ import { relaySet } from "applesauce-core/helpers";
5
+ import { isEvent } from "applesauce-core/helpers/event";
6
+ /**
7
+ * Extracts the pubkey from a parent event or CommentPointer.
8
+ * Returns undefined if the pubkey is not available.
9
+ */
10
+ function getParentPubkey(parent) {
11
+ if (isEvent(parent))
12
+ return parent.pubkey;
13
+ if (isCommentEventPointer(parent))
14
+ return parent.pubkey;
15
+ if (isCommentAddressPointer(parent))
16
+ return parent.pubkey;
17
+ // CommentExternalPointer doesn't have a pubkey
18
+ return undefined;
19
+ }
20
+ /**
21
+ * Creates a comment on an event or CommentPointer and publishes it to:
22
+ * - The parent event's author's inboxes (if the author exists and pubkey is available)
23
+ * - The current user's outboxes
24
+ */
25
+ export function CreateComment(parent, content, options) {
26
+ return async ({ factory, user, publish, events, sign }) => {
27
+ // Get the parent author's pubkey from the pointer/event (without loading the full event)
28
+ const parentAuthorPubkey = getParentPubkey(parent);
29
+ // Get the parent author's inboxes in parallel with resolving the event
30
+ const [parentAuthorInboxes, userOutboxes] = await Promise.all([
31
+ // Get inboxes if we have a pubkey and it's different from current user
32
+ parentAuthorPubkey ? castUser(parentAuthorPubkey, events).inboxes$.$first(1_000, undefined) : undefined,
33
+ // Get the current user's outboxes
34
+ user.outboxes$.$first(1_000, undefined),
35
+ ]);
36
+ // Create and sign the comment
37
+ const comment = await factory.create(CommentBlueprint, parent, content, options).then(sign);
38
+ // Combine all relay lists (remove duplicates)
39
+ const relays = relaySet(parentAuthorInboxes, userOutboxes);
40
+ // Publish to all relays (inboxes and outboxes)
41
+ await publish(comment, relays.length > 0 ? relays : undefined);
42
+ };
43
+ }
@@ -1,5 +1,5 @@
1
1
  import { ProfilePointer } from "applesauce-core/helpers/pointers";
2
- import { Action } from "../action-hub.js";
2
+ import { Action } from "../action-runner.js";
3
3
  /** An action that adds a pubkey to a users contacts event */
4
4
  export declare function FollowUser(user: string | ProfilePointer): Action;
5
5
  /** An action that removes a pubkey from a users contacts event */
@@ -1,4 +1,4 @@
1
- import { Action } from "../action-hub.js";
1
+ import { Action } from "../action-runner.js";
2
2
  /** An action that adds a relay to the 10050 DM relays event */
3
3
  export declare function AddDirectMessageRelay(relay: string | string[]): Action;
4
4
  /** An action that removes a relay from the 10050 DM relays event */
@@ -1,5 +1,5 @@
1
1
  import { AddressPointer } from "applesauce-core/helpers/pointers";
2
- import { Action } from "../action-hub.js";
2
+ import { Action } from "../action-runner.js";
3
3
  /** An action that adds a relay to the 10012 favorite relays event */
4
4
  export declare function AddFavoriteRelay(relay: string | string[], hidden?: boolean): Action;
5
5
  /** An action that removes a relay from the 10012 favorite relays event */
@@ -1,6 +1,6 @@
1
1
  import { NostrEvent } from "applesauce-core/helpers/event";
2
2
  import { ProfilePointer } from "applesauce-core/helpers/pointers";
3
- import { Action } from "../action-hub.js";
3
+ import { Action } from "../action-runner.js";
4
4
  /**
5
5
  * An action that creates a new follow set
6
6
  * @throws if a follow set already exists
@@ -3,6 +3,7 @@ export * from "./blocked-relays.js";
3
3
  export * from "./blossom.js";
4
4
  export * from "./bookmarks.js";
5
5
  export * from "./calendar.js";
6
+ export * from "./comment.js";
6
7
  export * from "./contacts.js";
7
8
  export * from "./direct-message-relays.js";
8
9
  export * from "./favorite-relays.js";
@@ -3,6 +3,7 @@ export * from "./blocked-relays.js";
3
3
  export * from "./blossom.js";
4
4
  export * from "./bookmarks.js";
5
5
  export * from "./calendar.js";
6
+ export * from "./comment.js";
6
7
  export * from "./contacts.js";
7
8
  export * from "./direct-message-relays.js";
8
9
  export * from "./favorite-relays.js";
@@ -1,6 +1,6 @@
1
1
  import { LegacyMessageBlueprintOptions } from "applesauce-common/blueprints";
2
2
  import { NostrEvent } from "applesauce-core/helpers/event";
3
- import { Action } from "../action-hub.js";
3
+ import { Action } from "../action-runner.js";
4
4
  /** Sends a legacy NIP-04 message to a recipient */
5
5
  export declare function SendLegacyMessage(recipient: string, message: string, opts?: LegacyMessageBlueprintOptions): Action;
6
6
  /** Send a reply to a legacy message */
@@ -18,7 +18,7 @@ export function SendLegacyMessage(recipient, message, opts) {
18
18
  }
19
19
  /** Send a reply to a legacy message */
20
20
  export function ReplyToLegacyMessage(parent, message, opts) {
21
- return async ({ factory, sign, publish, events, }) => {
21
+ return async ({ factory, sign, publish, events }) => {
22
22
  if (parent.kind !== kinds.EncryptedDirectMessage)
23
23
  throw new Error("Legacy messages can only reply to other legacy messages");
24
24
  const signed = await factory.create(LegacyMessageReplyBlueprint, parent, message, opts).then(sign);
@@ -1,6 +1,6 @@
1
1
  import { NostrEvent } from "applesauce-core/helpers/event";
2
2
  import { AddressPointer } from "applesauce-core/helpers/pointers";
3
- import { Action } from "../action-hub.js";
3
+ import { Action } from "../action-runner.js";
4
4
  /** An action that sets or removes a NIP-15 list information */
5
5
  export declare function SetListMetadata(list: NostrEvent | AddressPointer, info: {
6
6
  title?: string;
@@ -1,4 +1,4 @@
1
- import { Action } from "../action-hub.js";
1
+ import { Action } from "../action-runner.js";
2
2
  /** An action to create a new kind 10002 relay list event */
3
3
  export declare function CreateMailboxes(inboxes: string[], outboxes: string[]): Action;
4
4
  /** An action to add an inbox relay to the kind 10002 relay list */
@@ -1,6 +1,6 @@
1
1
  import { NostrEvent } from "applesauce-core/helpers/event";
2
2
  import { EventPointer } from "applesauce-core/helpers/pointers";
3
- import { Action } from "../action-hub.js";
3
+ import { Action } from "../action-runner.js";
4
4
  /** An action that adds a pubkey to the mute list */
5
5
  export declare function MuteUser(pubkey: string, hidden?: boolean): Action;
6
6
  /** Removes a pubkey from the mute list */
@@ -1,5 +1,5 @@
1
1
  import { NostrEvent } from "applesauce-core/helpers/event";
2
- import { Action } from "../action-hub.js";
2
+ import { Action } from "../action-runner.js";
3
3
  export declare const ALLOWED_PIN_KINDS: number[];
4
4
  /** An action that pins a note to the users pin list */
5
5
  export declare function PinNote(note: NostrEvent): Action;
@@ -1,5 +1,5 @@
1
1
  import { ProfileContent } from "applesauce-core/helpers/profile";
2
- import { Action } from "../action-hub.js";
2
+ import { Action } from "../action-runner.js";
3
3
  /** An action that creates a new kind 0 profile event for a user */
4
4
  export declare function CreateProfile(content: ProfileContent): Action;
5
5
  /** An action that updates a kind 0 profile evnet for a user */
@@ -1,5 +1,5 @@
1
1
  import { NostrEvent } from "applesauce-core/helpers/event";
2
- import { Action } from "../action-hub.js";
2
+ import { Action } from "../action-runner.js";
3
3
  /** An action that adds a relay to a relay set*/
4
4
  export declare function AddRelayToRelaySet(relay: string | string[], identifier: NostrEvent | string, hidden?: boolean): Action;
5
5
  /** An action that removes a relay from a relay set */
@@ -1,4 +1,4 @@
1
- import { Action } from "../action-hub.js";
1
+ import { Action } from "../action-runner.js";
2
2
  /** An action that adds a relay to the 10007 search relays event */
3
3
  export declare function AddSearchRelay(relay: string | string[], hidden?: boolean): Action;
4
4
  /** An action that removes a relay from the 10007 search relays event */
@@ -1,7 +1,7 @@
1
1
  import { WrappedMessageBlueprintOptions } from "applesauce-common/blueprints";
2
2
  import { Rumor } from "applesauce-common/helpers/gift-wrap";
3
3
  import { GiftWrapOptions } from "applesauce-common/operations/gift-wrap";
4
- import { Action } from "../action-hub.js";
4
+ import { Action } from "../action-runner.js";
5
5
  /** Gift wraps a message to a list of participants and publishes it to their inbox relays */
6
6
  export declare function GiftWrapMessageToParticipants(message: Rumor, opts?: GiftWrapOptions): Action;
7
7
  /**
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export * from "./action-hub.js";
1
+ export * from "./action-runner.js";
2
2
  export * as Actions from "./actions/index.js";
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export * from "./action-hub.js";
1
+ export * from "./action-runner.js";
2
2
  export * as Actions from "./actions/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "applesauce-actions",
3
- "version": "0.0.0-next-20251220152312",
3
+ "version": "0.0.0-next-20251231055351",
4
4
  "description": "A package for performing common nostr actions",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -32,14 +32,14 @@
32
32
  }
33
33
  },
34
34
  "dependencies": {
35
- "applesauce-common": "0.0.0-next-20251220152312",
36
- "applesauce-core": "0.0.0-next-20251220152312",
35
+ "applesauce-common": "0.0.0-next-20251231055351",
36
+ "applesauce-core": "0.0.0-next-20251231055351",
37
37
  "rxjs": "^7.8.1"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@hirez_io/observer-spy": "^2.2.0",
41
41
  "@types/debug": "^4.1.12",
42
- "applesauce-signers": "0.0.0-next-20251220152312",
42
+ "applesauce-signers": "0.0.0-next-20251231055351",
43
43
  "nanoid": "^5.1.5",
44
44
  "rimraf": "^6.0.1",
45
45
  "typescript": "^5.8.3",