applesauce-relay 0.0.0-next-20250828145754 → 0.0.0-next-20250913205403
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/dist/group.d.ts +12 -4
- package/dist/group.js +20 -8
- package/dist/pool.d.ts +4 -4
- package/dist/pool.js +1 -1
- package/dist/relay.d.ts +4 -0
- package/dist/relay.js +12 -4
- package/dist/types.d.ts +3 -3
- package/package.json +6 -9
package/dist/group.d.ts
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
import { type NostrEvent } from "nostr-tools";
|
|
2
2
|
import { Observable } from "rxjs";
|
|
3
|
+
import { IEventStoreActions } from "applesauce-core";
|
|
3
4
|
import { FilterInput, IGroup, IRelay, PublishOptions, PublishResponse, RequestOptions, SubscriptionOptions, SubscriptionResponse } from "./types.js";
|
|
4
5
|
export declare class RelayGroup implements IGroup {
|
|
5
6
|
relays: IRelay[];
|
|
6
7
|
constructor(relays: IRelay[]);
|
|
7
8
|
/** Takes an array of observables and only emits EOSE when all observables have emitted EOSE */
|
|
8
|
-
protected mergeEOSE(
|
|
9
|
-
/**
|
|
9
|
+
protected mergeEOSE(requests: Observable<SubscriptionResponse>[], eventStore?: IEventStoreActions): Observable<import("nostr-tools").Event | "EOSE">;
|
|
10
|
+
/**
|
|
11
|
+
* Make a request to all relays
|
|
12
|
+
* @note This does not deduplicate events
|
|
13
|
+
*/
|
|
10
14
|
req(filters: FilterInput, id?: string): Observable<SubscriptionResponse>;
|
|
11
15
|
/** Send an event to all relays */
|
|
12
16
|
event(event: NostrEvent): Observable<PublishResponse>;
|
|
13
17
|
/** Publish an event to all relays with retries ( default 3 retries ) */
|
|
14
18
|
publish(event: NostrEvent, opts?: PublishOptions): Promise<PublishResponse[]>;
|
|
15
19
|
/** Request events from all relays with retries ( default 3 retries ) */
|
|
16
|
-
request(filters: FilterInput, opts?: RequestOptions
|
|
20
|
+
request(filters: FilterInput, opts?: RequestOptions & {
|
|
21
|
+
eventStore?: IEventStoreActions;
|
|
22
|
+
}): Observable<NostrEvent>;
|
|
17
23
|
/** Open a subscription to all relays with retries ( default 3 retries ) */
|
|
18
|
-
subscription(filters: FilterInput, opts?: SubscriptionOptions
|
|
24
|
+
subscription(filters: FilterInput, opts?: SubscriptionOptions & {
|
|
25
|
+
eventStore?: IEventStoreActions;
|
|
26
|
+
}): Observable<SubscriptionResponse>;
|
|
19
27
|
}
|
package/dist/group.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { nanoid } from "nanoid";
|
|
2
|
-
import { catchError, EMPTY, endWith, ignoreElements, merge, of } from "rxjs";
|
|
2
|
+
import { catchError, EMPTY, endWith, identity, ignoreElements, merge, of } from "rxjs";
|
|
3
|
+
import { filterDuplicateEvents } from "applesauce-core";
|
|
3
4
|
import { completeOnEose } from "./operators/complete-on-eose.js";
|
|
4
5
|
import { onlyEvents } from "./operators/only-events.js";
|
|
5
6
|
export class RelayGroup {
|
|
@@ -8,9 +9,13 @@ export class RelayGroup {
|
|
|
8
9
|
this.relays = relays;
|
|
9
10
|
}
|
|
10
11
|
/** Takes an array of observables and only emits EOSE when all observables have emitted EOSE */
|
|
11
|
-
mergeEOSE(
|
|
12
|
+
mergeEOSE(requests, eventStore) {
|
|
12
13
|
// Create stream of events only
|
|
13
|
-
const events = merge(...requests).pipe(
|
|
14
|
+
const events = merge(...requests).pipe(
|
|
15
|
+
// Ignore non event responses
|
|
16
|
+
onlyEvents(),
|
|
17
|
+
// If an event store is provided, filter duplicate events
|
|
18
|
+
eventStore ? filterDuplicateEvents(eventStore) : identity);
|
|
14
19
|
// Create stream that emits EOSE when all relays have sent EOSE
|
|
15
20
|
const eose = merge(
|
|
16
21
|
// Create a new map of requests that only emits EOSE
|
|
@@ -19,13 +24,16 @@ export class RelayGroup {
|
|
|
19
24
|
endWith("EOSE"));
|
|
20
25
|
return merge(events, eose);
|
|
21
26
|
}
|
|
22
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Make a request to all relays
|
|
29
|
+
* @note This does not deduplicate events
|
|
30
|
+
*/
|
|
23
31
|
req(filters, id = nanoid(8)) {
|
|
24
32
|
const requests = this.relays.map((relay) => relay.req(filters, id).pipe(
|
|
25
33
|
// Ignore connection errors
|
|
26
34
|
catchError(() => of("EOSE"))));
|
|
27
35
|
// Merge events and the single EOSE stream
|
|
28
|
-
return this.mergeEOSE(
|
|
36
|
+
return this.mergeEOSE(requests);
|
|
29
37
|
}
|
|
30
38
|
/** Send an event to all relays */
|
|
31
39
|
event(event) {
|
|
@@ -43,12 +51,16 @@ export class RelayGroup {
|
|
|
43
51
|
request(filters, opts) {
|
|
44
52
|
return merge(...this.relays.map((relay) => relay.request(filters, opts).pipe(
|
|
45
53
|
// Ignore individual connection errors
|
|
46
|
-
catchError(() => EMPTY))))
|
|
54
|
+
catchError(() => EMPTY)))).pipe(
|
|
55
|
+
// If an event store is provided, filter duplicate events
|
|
56
|
+
opts?.eventStore ? filterDuplicateEvents(opts.eventStore) : identity);
|
|
47
57
|
}
|
|
48
58
|
/** Open a subscription to all relays with retries ( default 3 retries ) */
|
|
49
59
|
subscription(filters, opts) {
|
|
50
|
-
return this.mergeEOSE(
|
|
60
|
+
return this.mergeEOSE(this.relays.map((relay) => relay.subscription(filters, opts).pipe(
|
|
51
61
|
// Ignore individual connection errors
|
|
52
|
-
catchError(() => EMPTY)))
|
|
62
|
+
catchError(() => EMPTY))),
|
|
63
|
+
// Pass event store so that duplicate events are removed
|
|
64
|
+
opts?.eventStore);
|
|
53
65
|
}
|
|
54
66
|
}
|
package/dist/pool.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type NostrEvent } from "nostr-tools";
|
|
|
2
2
|
import { BehaviorSubject, Observable } from "rxjs";
|
|
3
3
|
import { RelayGroup } from "./group.js";
|
|
4
4
|
import { Relay, RelayOptions } from "./relay.js";
|
|
5
|
-
import {
|
|
5
|
+
import { FilterInput, IPool, IRelay, PublishResponse, SubscriptionResponse } from "./types.js";
|
|
6
6
|
export declare class RelayPool implements IPool {
|
|
7
7
|
options?: RelayOptions | undefined;
|
|
8
8
|
groups$: BehaviorSubject<Map<string, RelayGroup>>;
|
|
@@ -24,9 +24,9 @@ export declare class RelayPool implements IPool {
|
|
|
24
24
|
/** Send an EVENT message to multiple relays */
|
|
25
25
|
event(relays: string[], event: NostrEvent): Observable<PublishResponse>;
|
|
26
26
|
/** Publish an event to multiple relays */
|
|
27
|
-
publish(relays: string[], event:
|
|
27
|
+
publish(relays: string[], event: Parameters<RelayGroup["publish"]>[0], opts?: Parameters<RelayGroup["publish"]>[1]): Promise<PublishResponse[]>;
|
|
28
28
|
/** Request events from multiple relays */
|
|
29
|
-
request(relays: string[], filters:
|
|
29
|
+
request(relays: string[], filters: Parameters<RelayGroup["request"]>[0], opts?: Parameters<RelayGroup["request"]>[1]): Observable<NostrEvent>;
|
|
30
30
|
/** Open a subscription to multiple relays */
|
|
31
|
-
subscription(relays: string[], filters:
|
|
31
|
+
subscription(relays: string[], filters: Parameters<RelayGroup["subscription"]>[0], opts?: Parameters<RelayGroup["subscription"]>[1]): Observable<SubscriptionResponse>;
|
|
32
32
|
}
|
package/dist/pool.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BehaviorSubject } from "rxjs";
|
|
2
|
+
import { normalizeURL } from "applesauce-core/helpers";
|
|
2
3
|
import { RelayGroup } from "./group.js";
|
|
3
4
|
import { Relay } from "./relay.js";
|
|
4
|
-
import { normalizeURL } from "applesauce-core/helpers";
|
|
5
5
|
export class RelayPool {
|
|
6
6
|
options;
|
|
7
7
|
groups$ = new BehaviorSubject(new Map());
|
package/dist/relay.d.ts
CHANGED
|
@@ -109,6 +109,10 @@ export declare class Relay implements IRelay {
|
|
|
109
109
|
publish(event: NostrEvent, opts?: PublishOptions): Promise<PublishResponse>;
|
|
110
110
|
/** Force close the connection */
|
|
111
111
|
close(): void;
|
|
112
|
+
/** An async method that returns the NIP-11 information document for the relay */
|
|
113
|
+
getInformation(): Promise<RelayInformation | null>;
|
|
114
|
+
/** An async method that returns the NIP-11 limitations for the relay */
|
|
115
|
+
getLimitations(): Promise<RelayInformation["limitation"] | null>;
|
|
112
116
|
/** Static method to fetch the NIP-11 information document for a relay */
|
|
113
117
|
static fetchInformationDocument(url: string): Observable<RelayInformation | null>;
|
|
114
118
|
/** Static method to create a reconnection method for each relay */
|
package/dist/relay.js
CHANGED
|
@@ -3,7 +3,7 @@ import { ensureHttpURL } from "applesauce-core/helpers";
|
|
|
3
3
|
import { simpleTimeout } from "applesauce-core/observable";
|
|
4
4
|
import { nanoid } from "nanoid";
|
|
5
5
|
import { nip42 } from "nostr-tools";
|
|
6
|
-
import { BehaviorSubject, catchError, combineLatest, defer, endWith, filter, finalize, from, identity, ignoreElements, isObservable, lastValueFrom, map, merge, mergeMap, mergeWith, NEVER, of, repeat, retry, scan, share, shareReplay, Subject, switchMap, take, takeUntil, tap, throwError, timeout, timer, } from "rxjs";
|
|
6
|
+
import { BehaviorSubject, catchError, combineLatest, defer, endWith, filter, finalize, firstValueFrom, from, identity, ignoreElements, isObservable, lastValueFrom, map, merge, mergeMap, mergeWith, NEVER, of, repeat, retry, scan, share, shareReplay, Subject, switchMap, take, takeUntil, tap, throwError, timeout, timer, } from "rxjs";
|
|
7
7
|
import { webSocket } from "rxjs/webSocket";
|
|
8
8
|
import { completeOnEose } from "./operators/complete-on-eose.js";
|
|
9
9
|
import { markFromRelay } from "./operators/mark-from-relay.js";
|
|
@@ -145,10 +145,10 @@ export class Relay {
|
|
|
145
145
|
}).pipe(
|
|
146
146
|
// if the fetch fails, return null
|
|
147
147
|
catchError(() => of(null)),
|
|
148
|
-
// cache the result
|
|
149
|
-
shareReplay(1),
|
|
150
148
|
// update the internal state
|
|
151
|
-
tap((info) => (this._nip11 = info))
|
|
149
|
+
tap((info) => (this._nip11 = info)),
|
|
150
|
+
// cache the result
|
|
151
|
+
shareReplay(1));
|
|
152
152
|
this.limitations$ = this.information$.pipe(map((info) => info?.limitation));
|
|
153
153
|
// Create observables that track if auth is required for REQ or EVENT
|
|
154
154
|
this.authRequiredForRead$ = this.receivedAuthRequiredForReq.pipe(tap((required) => required && this.log("Auth required for REQ")), shareReplay(1));
|
|
@@ -417,6 +417,14 @@ export class Relay {
|
|
|
417
417
|
close() {
|
|
418
418
|
this.socket.unsubscribe();
|
|
419
419
|
}
|
|
420
|
+
/** An async method that returns the NIP-11 information document for the relay */
|
|
421
|
+
async getInformation() {
|
|
422
|
+
return firstValueFrom(this.information$);
|
|
423
|
+
}
|
|
424
|
+
/** An async method that returns the NIP-11 limitations for the relay */
|
|
425
|
+
async getLimitations() {
|
|
426
|
+
return firstValueFrom(this.limitations$);
|
|
427
|
+
}
|
|
420
428
|
/** Static method to fetch the NIP-11 information document for a relay */
|
|
421
429
|
static fetchInformationDocument(url) {
|
|
422
430
|
return from(fetch(ensureHttpURL(url), { headers: { Accept: "application/nostr+json" } }).then((res) => res.json())).pipe(
|
package/dist/types.d.ts
CHANGED
|
@@ -103,9 +103,9 @@ export interface IPool {
|
|
|
103
103
|
/** Send an EVENT message */
|
|
104
104
|
event(relays: string[], event: NostrEvent): Observable<PublishResponse>;
|
|
105
105
|
/** Send an EVENT message to relays with retries */
|
|
106
|
-
publish(relays: string[], event:
|
|
106
|
+
publish(relays: string[], event: Parameters<IGroup["publish"]>[0], opts?: Parameters<IGroup["publish"]>[1]): Promise<PublishResponse[]>;
|
|
107
107
|
/** Send a REQ message to relays with retries */
|
|
108
|
-
request(relays: string[], filters:
|
|
108
|
+
request(relays: string[], filters: Parameters<IGroup["request"]>[0], opts?: Parameters<IGroup["request"]>[1]): Observable<NostrEvent>;
|
|
109
109
|
/** Open a subscription to relays with retries */
|
|
110
|
-
subscription(relays: string[], filters:
|
|
110
|
+
subscription(relays: string[], filters: Parameters<IGroup["subscription"]>[0], opts?: Parameters<IGroup["subscription"]>[1]): Observable<SubscriptionResponse>;
|
|
111
111
|
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "applesauce-relay",
|
|
3
|
-
"version": "0.0.0-next-
|
|
3
|
+
"version": "0.0.0-next-20250913205403",
|
|
4
4
|
"description": "nostr relay communication framework built on rxjs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"keywords": [
|
|
9
|
-
"nostr"
|
|
10
|
-
"applesauce"
|
|
9
|
+
"nostr"
|
|
11
10
|
],
|
|
12
11
|
"author": "hzrd149",
|
|
13
12
|
"license": "MIT",
|
|
14
13
|
"files": [
|
|
15
|
-
"dist"
|
|
16
|
-
"applesauce"
|
|
14
|
+
"dist"
|
|
17
15
|
],
|
|
18
16
|
"exports": {
|
|
19
17
|
".": {
|
|
@@ -54,17 +52,16 @@
|
|
|
54
52
|
},
|
|
55
53
|
"dependencies": {
|
|
56
54
|
"@noble/hashes": "^1.7.1",
|
|
57
|
-
"applesauce-core": "0.0.0-next-
|
|
55
|
+
"applesauce-core": "0.0.0-next-20250913205403",
|
|
58
56
|
"nanoid": "^5.0.9",
|
|
59
57
|
"nostr-tools": "~2.15",
|
|
60
58
|
"rxjs": "^7.8.1"
|
|
61
59
|
},
|
|
62
60
|
"devDependencies": {
|
|
63
61
|
"@hirez_io/observer-spy": "^2.2.0",
|
|
64
|
-
"applesauce-signers": "0.0.0-next-
|
|
65
|
-
"@vitest/expect": "^3.1.1",
|
|
62
|
+
"applesauce-signers": "0.0.0-next-20250913205403",
|
|
66
63
|
"typescript": "^5.7.3",
|
|
67
|
-
"vitest": "^3.2.
|
|
64
|
+
"vitest": "^3.2.4",
|
|
68
65
|
"vitest-websocket-mock": "^0.5.0"
|
|
69
66
|
},
|
|
70
67
|
"funding": {
|