Skip to content

Commit 45c93ed

Browse files
authored
refactor: simplify modular architecture (#27)
1 parent 2e63a5a commit 45c93ed

9 files changed

+314
-419
lines changed

core/clients.ts

+35-64
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import type {
22
ClientToRelayMessage,
3-
ClientToRelayMessageType,
43
NostrEvent,
54
RelayToClientMessage,
6-
SubscriptionFilter,
75
SubscriptionId,
86
} from "./protocol.d.ts";
97
import {
@@ -12,21 +10,35 @@ import {
1210
NostrNodeEvent,
1311
NostrNodeModule,
1412
} from "./nodes.ts";
15-
import { NIPs } from "./nips.ts";
13+
import { importNips } from "./nips.ts";
1614

1715
// ----------------------
1816
// NIPs
1917
// ----------------------
2018

21-
const nips = await NIPs.import<ClientModule>(import.meta.url, "../nips");
19+
const NIPs = await importNips<
20+
RelayToClientMessage,
21+
ClientEventTypeRecord,
22+
Client
23+
>(import.meta.url, "../nips");
24+
25+
// ----------------------
26+
// Interfaces
27+
// ----------------------
28+
29+
export type ClientConfig = NostrNodeConfig<
30+
RelayToClientMessage,
31+
ClientEventTypeRecord
32+
>;
33+
34+
export type ClientOptions = Partial<ClientConfig>;
2235

2336
/**
2437
* A class that represents a remote Nostr client.
2538
*/
2639
export class Client extends NostrNode<
2740
RelayToClientMessage,
28-
EventDataTypeRecord,
29-
ClientFunctionParameterTypeRecord
41+
ClientEventTypeRecord
3042
> {
3143
declare ws: WebSocket;
3244

@@ -41,77 +53,36 @@ export class Client extends NostrNode<
4153
constructor(ws: WebSocket, opts?: ClientOptions) {
4254
super(ws, {
4355
...opts,
44-
modules: nips.concat(opts?.modules ?? []),
56+
modules: NIPs.concat(opts?.modules ?? []),
4557
});
4658
this.ws.addEventListener("message", (ev: MessageEvent<string>) => {
47-
// TODO: Validate the type of the message.
4859
const message = JSON.parse(ev.data) as ClientToRelayMessage;
49-
this.callFunction("handleClientToRelayMessage", {
50-
message,
51-
client: this,
52-
});
60+
// TODO: Validate the message.
61+
this.dispatchEvent(new ClientEvent("message", message));
5362
});
5463
}
5564
}
5665

57-
type ClientConfig = NostrNodeConfig<ClientFunctionParameterTypeRecord>;
58-
export type ClientOptions = Partial<ClientConfig>;
59-
6066
// ------------------------------
61-
// Functions
67+
// Events
6268
// ------------------------------
6369

64-
export type ClientModule = NostrNodeModule<ClientFunctionParameterTypeRecord>;
65-
66-
type ClientFunctionParameterTypeRecord = {
67-
[K in keyof _FunctionParameterTypeRecord]:
68-
& _FunctionParameterTypeRecord[K]
69-
& ClientFunctionContext;
70-
};
71-
72-
type _FunctionParameterTypeRecord = {
73-
"handleClientToRelayMessage": {
74-
message: ClientToRelayMessage;
75-
};
76-
"handleSubscriptionMessage": {
77-
message: SubscriptionMessage;
78-
controller: ReadableStreamDefaultController<NostrEvent>;
79-
} & SubscriptionContext;
80-
"acceptEvent": {
81-
event: NostrEvent;
82-
};
83-
};
84-
85-
interface ClientFunctionContext {
86-
client: Client;
70+
export interface ClientEventTypeRecord {
71+
"message": ClientToRelayMessage;
8772
}
8873

89-
interface SubscriptionContext {
90-
id: SubscriptionId;
91-
filters: SubscriptionFilter[];
92-
}
74+
export type ClientEventType = keyof ClientEventTypeRecord;
75+
76+
export class ClientEvent<
77+
T extends ClientEventType = ClientEventType,
78+
> extends NostrNodeEvent<ClientEventTypeRecord, T> {}
9379

9480
// ------------------------------
95-
// Events
81+
// Modules
9682
// ------------------------------
9783

98-
type EventDataTypeRecord = {
99-
[T in SubscriptionId]: SubscriptionMessage;
100-
};
101-
102-
type SubscriptionMessage = {
103-
[T in ClientToRelayMessageType]: ClientToRelayMessage<T>[1] extends
104-
SubscriptionId ? ClientToRelayMessage<T> : never;
105-
}[ClientToRelayMessageType];
106-
107-
export class ClientSubscriptionEvent extends NostrNodeEvent<
108-
EventDataTypeRecord,
109-
SubscriptionId
110-
> {
111-
constructor(
112-
type: SubscriptionId,
113-
init: MessageEventInit<SubscriptionMessage>,
114-
) {
115-
super(type, init);
116-
}
117-
}
84+
export type ClientModule = NostrNodeModule<
85+
RelayToClientMessage,
86+
ClientEventTypeRecord,
87+
Client
88+
>;

core/nips.ts

+30-29
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,34 @@
1-
import type { NIP } from "./protocol.d.ts";
2-
import { NostrNodeModule } from "./nodes.ts";
1+
import type { NIP, NostrMessage } from "./protocol.d.ts";
2+
import { EventTypeRecord, NostrNode, NostrNodeModule } from "./nodes.ts";
33

4-
export const NIPs = {
5-
/**
6-
* Import a Nostr module from a URL.
7-
*
8-
* @param meta - The path to the module to which the NIPs are attached (mostly import.meta.url).
9-
* @param root - The path to the root of NIP module to import.
10-
*/
11-
// deno-lint-ignore no-explicit-any
12-
import<M extends NostrNodeModule<any>>(
13-
meta: string,
14-
root: string,
15-
) {
16-
const url = new URL(meta);
17-
const base = url.pathname.split("/").slice(-1)[0];
18-
return Promise.all(
19-
url.searchParams.get("nips")?.split(",").map(Number).map(
20-
(nip) =>
21-
import(
22-
new URL(
23-
`${root}/${nipToString(nip)}/${base}`,
24-
import.meta.url,
25-
).href
26-
) as Promise<M>,
27-
) ?? [],
28-
);
29-
},
30-
};
4+
/**
5+
* Import a NostrNode module from a URL.
6+
*
7+
* @param meta - The path to the module to which the NIPs are attached (mostly import.meta.url).
8+
* @param root - The path to the root of NIP module to import.
9+
*/
10+
export function importNips<
11+
W extends NostrMessage = NostrMessage,
12+
R extends EventTypeRecord = EventTypeRecord,
13+
N extends NostrNode<W, R> = NostrNode<W, R>,
14+
>(
15+
meta: string,
16+
root: string,
17+
) {
18+
const url = new URL(meta);
19+
const base = url.pathname.split("/").slice(-1)[0];
20+
return Promise.all(
21+
url.searchParams.get("nips")?.split(",").map(Number).map(
22+
(nip) =>
23+
import(
24+
new URL(
25+
`${root}/${nipToString(nip)}/${base}`,
26+
import.meta.url,
27+
).href
28+
) as Promise<NostrNodeModule<W, R, N>>,
29+
) ?? [],
30+
);
31+
}
3132

3233
/**
3334
* Convert a NIP to a string. If the NIP is less than 10, a leading zero is

0 commit comments

Comments
 (0)