@abndnce/pulsar-client 0.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.
@@ -0,0 +1,32 @@
1
+ //#region lib/connection/types.d.ts
2
+ /**
3
+ * Every client connection, regardless of transport mode, satisfies this interface.
4
+ */
5
+ interface PulsarClientConnection {
6
+ keepalive: RTCDataChannel;
7
+ pc: RTCPeerConnection;
8
+ close(): Promise<void>;
9
+ }
10
+ //#endregion
11
+ //#region lib/connection/direct.d.ts
12
+ /**
13
+ * Connect to a remote Pulsar server in direct mode.
14
+ *
15
+ * Designed for browsers, using the native `RTCPeerConnection` API.
16
+ *
17
+ * @param host Server IP address
18
+ * @param port Server UDP port
19
+ * @returns A connected PulsarClientConnection with an open keepalive channel.
20
+ */
21
+ declare function connectDirect(host: string, port: number): Promise<PulsarClientConnection>;
22
+ //#endregion
23
+ //#region lib/connection/nostr.d.ts
24
+ /**
25
+ * Connect via a Nostr relay (placeholder).
26
+ *
27
+ * In the future, this will implement a Nostr-based signaling layer for
28
+ * establishing peer connections through a Nostr relay.
29
+ */
30
+ declare function connectNostr(_relay: string, _pubkey: string): Promise<PulsarClientConnection>;
31
+ //#endregion
32
+ export { type PulsarClientConnection, connectDirect, connectNostr };
package/dist/index.mjs ADDED
@@ -0,0 +1,81 @@
1
+ //#region ../core/credentials.ts
2
+ const PULSAR_UFRAG = "pulsar";
3
+ const PULSAR_PWD = "pulsarpulsarpulsarpuls";
4
+ const PULSAR_FINGERPRINT = "F1:85:10:8F:36:FF:58:D8:D0:4B:52:D7:ED:DC:5C:28:AE:7D:DB:54:0E:2A:DD:C7:C3:94:EA:A1:27:D0:4E:78";
5
+ //#endregion
6
+ //#region lib/connection/direct.ts
7
+ /**
8
+ * Connect to a remote Pulsar server in direct mode.
9
+ *
10
+ * Designed for browsers, using the native `RTCPeerConnection` API.
11
+ *
12
+ * @param host Server IP address
13
+ * @param port Server UDP port
14
+ * @returns A connected PulsarClientConnection with an open keepalive channel.
15
+ */
16
+ async function connectDirect(host, port) {
17
+ const pc = new RTCPeerConnection();
18
+ const keepalive = pc.createDataChannel("keepalive", { ordered: true });
19
+ const offer = await pc.createOffer();
20
+ const mungedSdp = offer.sdp.replace(/^a=ice-ufrag:.*$/m, `a=ice-ufrag:${PULSAR_UFRAG}`).replace(/^a=ice-pwd:.*$/m, `a=ice-pwd:${PULSAR_PWD}`).replace(/^a=fingerprint:.*$/m, `a=fingerprint:sha-256 ${PULSAR_FINGERPRINT}`);
21
+ if (mungedSdp === offer.sdp) throw new Error("SDP munging failed – could not replace ICE credentials");
22
+ await pc.setLocalDescription({
23
+ type: "offer",
24
+ sdp: mungedSdp
25
+ });
26
+ const remoteSdp = [
27
+ "v=0",
28
+ "o=- 111 222 IN IP4 0.0.0.0",
29
+ "s=-",
30
+ "t=0 0",
31
+ `m=application ${port} UDP/DTLS/SCTP webrtc-datachannel`,
32
+ `c=IN IP4 ${host}`,
33
+ "a=mid:0",
34
+ `a=ice-ufrag:${PULSAR_UFRAG}`,
35
+ `a=ice-pwd:${PULSAR_PWD}`,
36
+ `a=fingerprint:sha-256 ${PULSAR_FINGERPRINT}`,
37
+ "a=setup:active",
38
+ "a=sctp-port:5000",
39
+ `a=candidate:1 1 UDP 2130706431 ${host} ${port} typ host`,
40
+ "a=end-of-candidates"
41
+ ].join("\r\n");
42
+ await pc.setRemoteDescription({
43
+ type: "answer",
44
+ sdp: remoteSdp
45
+ });
46
+ await new Promise((resolve, reject) => {
47
+ const timeout = setTimeout(() => {
48
+ reject(/* @__PURE__ */ new Error("Connection timed out after 30s"));
49
+ }, 3e4);
50
+ pc.onconnectionstatechange = () => {
51
+ if (pc.connectionState === "connected") {
52
+ clearTimeout(timeout);
53
+ resolve();
54
+ } else if (pc.connectionState === "failed" || pc.connectionState === "disconnected") {
55
+ clearTimeout(timeout);
56
+ reject(/* @__PURE__ */ new Error(`Connection failed: ${pc.connectionState}`));
57
+ }
58
+ };
59
+ });
60
+ return {
61
+ keepalive,
62
+ pc,
63
+ async close() {
64
+ keepalive.close();
65
+ pc.close();
66
+ }
67
+ };
68
+ }
69
+ //#endregion
70
+ //#region lib/connection/nostr.ts
71
+ /**
72
+ * Connect via a Nostr relay (placeholder).
73
+ *
74
+ * In the future, this will implement a Nostr-based signaling layer for
75
+ * establishing peer connections through a Nostr relay.
76
+ */
77
+ async function connectNostr(_relay, _pubkey) {
78
+ throw new Error("Nostr mode not yet implemented");
79
+ }
80
+ //#endregion
81
+ export { connectDirect, connectNostr };
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@abndnce/pulsar-client",
3
+ "type": "module",
4
+ "version": "0.0.1",
5
+ "homepage": "https://github.com/abndnce/pulsar",
6
+ "license": "MIT",
7
+ "exports": {
8
+ ".": "./dist/index.mjs",
9
+ "./package.json": "./package.json"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "devDependencies": {
15
+ "tsdown": "^0.22.0",
16
+ "typescript": "^6.0.3"
17
+ },
18
+ "scripts": {
19
+ "build": "tsdown",
20
+ "dev": "tsdown --watch",
21
+ "test": "vitest",
22
+ "typecheck": "tsc --noEmit"
23
+ }
24
+ }