@openlv/signaling 0.0.1-beta.8 → 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.
- package/dist/dynamic.d.ts +1 -1
- package/dist/gundb/index.d.ts +1 -1
- package/dist/gundb/index.js +1 -1
- package/dist/gundb/index.js.map +1 -1
- package/dist/index.d.ts +58 -5
- package/dist/index.js +186 -5
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +11 -11
- package/dist/index.test.js.map +1 -1
- package/dist/messages.js +2 -0
- package/dist/messages.js.map +1 -0
- package/dist/mqtt/index.d.ts +1 -1
- package/dist/mqtt/index.js.map +1 -1
- package/dist/ntfy/index.d.ts +1 -1
- package/dist/ntfy/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/base.d.ts +0 -45
- package/dist/base.js +0 -161
- package/dist/base.js.map +0 -1
- package/dist/layer.d.ts +0 -14
- package/dist/layer.js +0 -10
- package/dist/layer.js.map +0 -1
- package/dist/messages/index.js +0 -2
- package/dist/messages/index.js.map +0 -1
- /package/dist/{messages/index.d.ts → messages.d.ts} +0 -0
package/dist/dynamic.d.ts
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
*
|
|
4
4
|
* TODO: Make this a built-in feature of session/provider
|
|
5
5
|
*/
|
|
6
|
-
export declare const dynamicSignalingLayer: (protocol: string) => Promise<import("./
|
|
6
|
+
export declare const dynamicSignalingLayer: (protocol: string) => Promise<import("./index.js").CreateSignalLayerFn>;
|
package/dist/gundb/index.d.ts
CHANGED
package/dist/gundb/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SignalNoConnectionError } from "@openlv/core/errors";
|
|
2
2
|
import Gun, {} from "gun";
|
|
3
|
-
import { createSignalingLayer } from "../
|
|
3
|
+
import { createSignalingLayer } from "../index.js";
|
|
4
4
|
import { log } from "../utils/log.js";
|
|
5
5
|
/**
|
|
6
6
|
* GunDB Signaling Layer
|
package/dist/gundb/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gundb/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,GAAG,EAAE,EAAgC,MAAM,KAAK,CAAC;AAExD,OAAO,EAAE,oBAAoB,EAA4B,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gundb/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,GAAG,EAAE,EAAgC,MAAM,KAAK,CAAC;AAExD,OAAO,EAAE,oBAAoB,EAA4B,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEtC;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAwB,CAAC,EACzC,KAAK,EACL,GAAG,GAAG,uBAAuB,GAC9B,EAAE,EAAE;IACH,IAAI,UAAoC,CAAC;IAEzC,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,OAAO;QACb,KAAK,CAAC,KAAK;YACT,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACzB,MAAM,CAAC,GAAG,IAAK,GAAuB,CAAC;gBACrC,KAAK,EAAE,CAAC,GAAG,CAAC;gBACZ,IAAI,EAAE,SAAS;gBACf,YAAY,EAAE,SAAS;aACxB,CAAC,CAAC;YAEH,UAAU,GAAG,CAAC,CAAC;YAEf,MAAM,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;QACD,QAAQ;YACN,kBAAkB;YAClB,UAAU,GAAG,SAAS,CAAC;QACzB,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,IAAI,CAAC,UAAU;gBAAE,MAAM,IAAI,uBAAuB,EAAE,CAAC;YAErD,GAAG,CAAC,2BAA2B,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YACjD,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,OAAO;YACrB,IAAI,CAAC,UAAU;gBAAE,MAAM,IAAI,uBAAuB,EAAE,CAAC;YAErD,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE;gBAChC,GAAG,CAAC,yBAAyB,EAAE,IAAI,CAAC,CAAC;gBAErC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC;gBAEtC,IAAI,CAAC,OAAO;oBAAE,OAAO;gBAErB,OAAO,CAAC,OAAO,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE;IACnB,MAAM,EAAE,OAAO;CAChB,CAAC,CAAC","sourcesContent":["import { SignalNoConnectionError } from \"@openlv/core/errors\";\nimport Gun, { type IGun, type IGunInstance } from \"gun\";\n\nimport { createSignalingLayer, type CreateSignalLayerFn } from \"../index.js\";\nimport { log } from \"../utils/log.js\";\n\n/**\n * GunDB Signaling Layer\n * https://openlv.sh/api/signaling/gun\n */\nexport const gundb: CreateSignalLayerFn = ({\n topic,\n url = \"wss://try.axe.eco/gun\",\n}) => {\n let connection: IGunInstance | undefined;\n\n return createSignalingLayer({\n type: \"gundb\",\n async setup() {\n log(\"GUNDB: Setting up\");\n const x = new (Gun as unknown as IGun)({\n peers: [url],\n file: undefined,\n localStorage: undefined,\n });\n\n connection = x;\n\n await connection?.get(topic);\n },\n teardown() {\n // connection?.();\n connection = undefined;\n },\n async publish(payload) {\n if (!connection) throw new SignalNoConnectionError();\n\n log(\"GUNDB: Publishing message\", topic, payload);\n connection.get(topic).put({ data: payload });\n },\n async subscribe(handler) {\n if (!connection) throw new SignalNoConnectionError();\n\n connection.get(topic).on((data) => {\n log(\"GUNDB: Received message\", data);\n\n const message = data.data?.toString();\n\n if (!message) return;\n\n handler(message);\n });\n },\n });\n};\n\nObject.assign(gundb, {\n __name: \"gundb\",\n});\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
|
|
1
|
+
import type { EncryptionKey, SymmetricKey } from "@openlv/core/encryption";
|
|
2
|
+
import { EventEmitter } from "eventemitter3";
|
|
3
|
+
import type { MaybePromise } from "viem";
|
|
4
|
+
export declare const SIGNAL_STATE: {
|
|
5
|
+
readonly STANDBY: "standby";
|
|
6
|
+
readonly CONNECTING: "connecting";
|
|
7
|
+
readonly READY: "ready";
|
|
8
|
+
readonly HANDSHAKE: "handshake";
|
|
9
|
+
readonly HANDSHAKE_PARTIAL: "handshake-partial";
|
|
10
|
+
readonly ENCRYPTED: "encrypted";
|
|
11
|
+
readonly ERROR: "error";
|
|
12
|
+
};
|
|
13
|
+
export type SignalState = (typeof SIGNAL_STATE)[keyof typeof SIGNAL_STATE];
|
|
14
|
+
export type SignalEventMap = {
|
|
15
|
+
state_change: (state: SignalState) => void;
|
|
16
|
+
message: (message: object) => void;
|
|
17
|
+
};
|
|
18
|
+
export type SignalBaseProperties = {
|
|
19
|
+
topic: string;
|
|
20
|
+
url: string;
|
|
21
|
+
};
|
|
22
|
+
export type SignalingBaseLayer = {
|
|
23
|
+
type: string;
|
|
24
|
+
setup: () => MaybePromise<void>;
|
|
25
|
+
teardown: () => MaybePromise<void>;
|
|
26
|
+
publish: (payload: string) => MaybePromise<void>;
|
|
27
|
+
subscribe: (handler: (payload: string) => void) => MaybePromise<void>;
|
|
28
|
+
};
|
|
29
|
+
export type CreateSignalLayerFn = (properties: SignalBaseProperties) => MaybePromise<SignalingLayerFn>;
|
|
30
|
+
export type SignalingProperties = {
|
|
31
|
+
isHost: boolean;
|
|
32
|
+
h: string;
|
|
33
|
+
k?: SymmetricKey;
|
|
34
|
+
rpDiscovered: (rpKey: string) => MaybePromise<void>;
|
|
35
|
+
decrypt: (message: string) => MaybePromise<string>;
|
|
36
|
+
encrypt: (message: string) => MaybePromise<string>;
|
|
37
|
+
publicKey: EncryptionKey;
|
|
38
|
+
canEncrypt: () => boolean;
|
|
39
|
+
};
|
|
40
|
+
export type SignalingContext = {
|
|
41
|
+
type: string;
|
|
42
|
+
send: (message: object) => MaybePromise<void>;
|
|
43
|
+
setup: () => MaybePromise<void>;
|
|
44
|
+
teardown: () => MaybePromise<void>;
|
|
45
|
+
getState: () => {
|
|
46
|
+
state: SignalState;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
export type SignalingLayer = EventEmitter<SignalEventMap> & SignalingContext;
|
|
50
|
+
export type SignalingLayerFn = (properties: SignalingProperties) => Promise<SignalingLayer>;
|
|
51
|
+
export declare const XR_PREFIX = "x";
|
|
52
|
+
export declare const XR_H_PREFIX = "h";
|
|
53
|
+
/**
|
|
54
|
+
* Base Signaling Layer implementation
|
|
55
|
+
*
|
|
56
|
+
* https://openlv.sh/api/signaling
|
|
57
|
+
*/
|
|
58
|
+
export declare const createSignalingLayer: (init: SignalingBaseLayer) => SignalingLayerFn;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,187 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { make } from "@openlv/core";
|
|
2
|
+
import { parseEncryptionKey, validatePublicKeyHash } from "@openlv/core/encryption";
|
|
3
|
+
import { EventEmitter } from "eventemitter3";
|
|
4
|
+
import { match } from "ts-pattern";
|
|
5
|
+
import { log } from "./utils/log.js";
|
|
6
|
+
export const SIGNAL_STATE = {
|
|
7
|
+
STANDBY: "standby",
|
|
8
|
+
CONNECTING: "connecting",
|
|
9
|
+
READY: "ready",
|
|
10
|
+
HANDSHAKE: "handshake",
|
|
11
|
+
HANDSHAKE_PARTIAL: "handshake-partial",
|
|
12
|
+
ENCRYPTED: "encrypted",
|
|
13
|
+
ERROR: "error",
|
|
14
|
+
};
|
|
15
|
+
export const XR_PREFIX = "x";
|
|
16
|
+
export const XR_H_PREFIX = "h";
|
|
17
|
+
/**
|
|
18
|
+
* Base Signaling Layer implementation
|
|
19
|
+
*
|
|
20
|
+
* https://openlv.sh/api/signaling
|
|
21
|
+
*/
|
|
22
|
+
export const createSignalingLayer = (init) => async ({ canEncrypt, encrypt, decrypt, rpDiscovered, h, k, publicKey, isHost, }) => {
|
|
23
|
+
const emitter = new EventEmitter();
|
|
24
|
+
let state = SIGNAL_STATE.STANDBY;
|
|
25
|
+
const setState = (_state) => {
|
|
26
|
+
state = _state;
|
|
27
|
+
emitter.emit("state_change", _state);
|
|
28
|
+
};
|
|
29
|
+
const handshakeKey = k || undefined;
|
|
30
|
+
const send = async (method, recipient, payload) => {
|
|
31
|
+
const prefix = match(method)
|
|
32
|
+
.with("handshake", () => XR_H_PREFIX)
|
|
33
|
+
.with("encrypted", () => XR_PREFIX)
|
|
34
|
+
.exhaustive();
|
|
35
|
+
const message = await match(method)
|
|
36
|
+
.with("handshake", () => {
|
|
37
|
+
if (!handshakeKey)
|
|
38
|
+
return;
|
|
39
|
+
return handshakeKey.encrypt(JSON.stringify(payload));
|
|
40
|
+
})
|
|
41
|
+
.with("encrypted", () => {
|
|
42
|
+
if (!canEncrypt())
|
|
43
|
+
return;
|
|
44
|
+
return encrypt(JSON.stringify(payload));
|
|
45
|
+
})
|
|
46
|
+
.exhaustive();
|
|
47
|
+
await init.publish(prefix + recipient + message);
|
|
48
|
+
};
|
|
49
|
+
const handleReceive = async (payload) => {
|
|
50
|
+
const prefix = payload.slice(0, XR_H_PREFIX.length);
|
|
51
|
+
const recipient = payload.slice(XR_H_PREFIX.length, XR_H_PREFIX.length + 1);
|
|
52
|
+
const body = payload.slice(XR_PREFIX.length + 1);
|
|
53
|
+
const isRecipient = (isHost ? "h" : "c") === recipient;
|
|
54
|
+
log("isRecipient", isRecipient);
|
|
55
|
+
if (!isRecipient)
|
|
56
|
+
return;
|
|
57
|
+
await match({ prefix, body })
|
|
58
|
+
.with({ prefix: XR_H_PREFIX }, async () => {
|
|
59
|
+
if (!handshakeKey)
|
|
60
|
+
return;
|
|
61
|
+
const message = await handshakeKey.decrypt(body);
|
|
62
|
+
const msg = JSON.parse(message);
|
|
63
|
+
await match({ msg, state, isHost })
|
|
64
|
+
.with({ msg: { type: "flash" }, state: SIGNAL_STATE.READY, isHost: true }, async () => {
|
|
65
|
+
setState(SIGNAL_STATE.HANDSHAKE);
|
|
66
|
+
await send("handshake", "c", {
|
|
67
|
+
type: "pubkey",
|
|
68
|
+
payload: {
|
|
69
|
+
publicKey: publicKey.toString(),
|
|
70
|
+
},
|
|
71
|
+
timestamp: Date.now(),
|
|
72
|
+
});
|
|
73
|
+
})
|
|
74
|
+
.with({ msg: { type: "pubkey" }, isHost: false, state: SIGNAL_STATE.HANDSHAKE }, async ({ msg: { payload: msgPayload } }) => {
|
|
75
|
+
try {
|
|
76
|
+
const receivedKey = await parseEncryptionKey(msgPayload.publicKey);
|
|
77
|
+
if (!await validatePublicKeyHash(receivedKey, h)) {
|
|
78
|
+
setState(SIGNAL_STATE.ERROR);
|
|
79
|
+
log("Received host public key does not match expected hash — possible tampering");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
setState(SIGNAL_STATE.ERROR);
|
|
85
|
+
log("Failed to parse received host public key");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
await rpDiscovered(msgPayload.publicKey);
|
|
89
|
+
setState(SIGNAL_STATE.HANDSHAKE_PARTIAL);
|
|
90
|
+
return await send("encrypted", "h", {
|
|
91
|
+
type: "pubkey",
|
|
92
|
+
payload: {
|
|
93
|
+
publicKey: publicKey.toString(),
|
|
94
|
+
},
|
|
95
|
+
timestamp: Date.now(),
|
|
96
|
+
});
|
|
97
|
+
})
|
|
98
|
+
.otherwise(() => {
|
|
99
|
+
log("Received invalid message H", msg);
|
|
100
|
+
});
|
|
101
|
+
})
|
|
102
|
+
.with({ prefix: XR_PREFIX }, async () => {
|
|
103
|
+
const message = await decrypt(body);
|
|
104
|
+
const msg = JSON.parse(message);
|
|
105
|
+
await match({ msg, state, isHost })
|
|
106
|
+
.with({
|
|
107
|
+
msg: { type: "pubkey" },
|
|
108
|
+
isHost: true,
|
|
109
|
+
state: SIGNAL_STATE.HANDSHAKE,
|
|
110
|
+
}, async ({ msg: { payload: msgPayload } }) => {
|
|
111
|
+
await rpDiscovered(msgPayload.publicKey);
|
|
112
|
+
setState(SIGNAL_STATE.HANDSHAKE_PARTIAL);
|
|
113
|
+
return await send("encrypted", "c", {
|
|
114
|
+
type: "ack",
|
|
115
|
+
payload: undefined,
|
|
116
|
+
timestamp: Date.now(),
|
|
117
|
+
});
|
|
118
|
+
})
|
|
119
|
+
.with({
|
|
120
|
+
msg: { type: "ack" },
|
|
121
|
+
state: SIGNAL_STATE.HANDSHAKE_PARTIAL,
|
|
122
|
+
}, async () => {
|
|
123
|
+
setState(SIGNAL_STATE.ENCRYPTED);
|
|
124
|
+
if (isHost)
|
|
125
|
+
return;
|
|
126
|
+
return await send("encrypted", "h", {
|
|
127
|
+
type: "ack",
|
|
128
|
+
payload: undefined,
|
|
129
|
+
timestamp: Date.now(),
|
|
130
|
+
});
|
|
131
|
+
})
|
|
132
|
+
.with({ msg: { type: "data" }, state: SIGNAL_STATE.ENCRYPTED }, async () => {
|
|
133
|
+
emitter.emit("message", msg.payload);
|
|
134
|
+
})
|
|
135
|
+
.otherwise(() => {
|
|
136
|
+
log("Received invalid message X", msg);
|
|
137
|
+
});
|
|
138
|
+
})
|
|
139
|
+
.otherwise(() => {
|
|
140
|
+
log("Received invalid message", payload);
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
return make(emitter, {
|
|
144
|
+
type: init.type,
|
|
145
|
+
async setup() {
|
|
146
|
+
setState(SIGNAL_STATE.CONNECTING);
|
|
147
|
+
await init.setup();
|
|
148
|
+
await init.subscribe(handleReceive);
|
|
149
|
+
if (!canEncrypt()) {
|
|
150
|
+
if (isHost) {
|
|
151
|
+
setState(SIGNAL_STATE.READY);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
setState(SIGNAL_STATE.READY);
|
|
155
|
+
await send("handshake", "h", {
|
|
156
|
+
type: "flash",
|
|
157
|
+
payload: {},
|
|
158
|
+
timestamp: Date.now(),
|
|
159
|
+
});
|
|
160
|
+
setState(SIGNAL_STATE.HANDSHAKE);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
setState(SIGNAL_STATE.ENCRYPTED);
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
async teardown() {
|
|
168
|
+
log("teardown");
|
|
169
|
+
await init.teardown?.();
|
|
170
|
+
},
|
|
171
|
+
send(message) {
|
|
172
|
+
if (!canEncrypt()) {
|
|
173
|
+
return Promise.reject(new Error("Cannot encrypt message before keys are exchanged"));
|
|
174
|
+
}
|
|
175
|
+
const them = isHost ? "c" : "h";
|
|
176
|
+
return send("encrypted", them, {
|
|
177
|
+
type: "data",
|
|
178
|
+
payload: message,
|
|
179
|
+
timestamp: Date.now(),
|
|
180
|
+
});
|
|
181
|
+
},
|
|
182
|
+
getState() {
|
|
183
|
+
return { state: state };
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
};
|
|
6
187
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,yEAAyE;AAEzE,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC","sourcesContent":["/** biome-ignore-all lint/performance/noReExportAll: package entrypoint */\n/** biome-ignore-all lint/performance/noBarrelFile: package entrypoint */\n\nexport * from \"./base.js\";\nexport * from \"./layer.js\";\nexport * from \"./messages/index.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { make } from \"@openlv/core\";\nimport type { EncryptionKey, SymmetricKey } from \"@openlv/core/encryption\";\nimport { parseEncryptionKey, validatePublicKeyHash } from \"@openlv/core/encryption\";\nimport { EventEmitter } from \"eventemitter3\";\nimport { match } from \"ts-pattern\";\nimport type { MaybePromise } from \"viem\";\n\nimport type { SignalMessage } from \"./messages.js\";\nimport { log } from \"./utils/log.js\";\n\nexport const SIGNAL_STATE = {\n STANDBY: \"standby\",\n CONNECTING: \"connecting\",\n READY: \"ready\",\n HANDSHAKE: \"handshake\",\n HANDSHAKE_PARTIAL: \"handshake-partial\",\n ENCRYPTED: \"encrypted\",\n ERROR: \"error\",\n} as const;\nexport type SignalState = (typeof SIGNAL_STATE)[keyof typeof SIGNAL_STATE];\n\nexport type SignalEventMap = {\n state_change: (state: SignalState) => void;\n message: (message: object) => void;\n};\n\nexport type SignalBaseProperties = {\n topic: string;\n url: string;\n};\n\nexport type SignalingBaseLayer = {\n type: string;\n setup: () => MaybePromise<void>;\n teardown: () => MaybePromise<void>;\n publish: (payload: string) => MaybePromise<void>;\n subscribe: (handler: (payload: string) => void) => MaybePromise<void>;\n};\n\nexport type CreateSignalLayerFn = (\n properties: SignalBaseProperties,\n) => MaybePromise<SignalingLayerFn>;\n\nexport type SignalingProperties = {\n isHost: boolean;\n h: string;\n k?: SymmetricKey;\n rpDiscovered: (rpKey: string) => MaybePromise<void>;\n // Decrypt using our private key\n decrypt: (message: string) => MaybePromise<string>;\n // Encrypt to relying party\n encrypt: (message: string) => MaybePromise<string>;\n // our public key\n publicKey: EncryptionKey;\n canEncrypt: () => boolean;\n};\n\nexport type SignalingContext = {\n type: string;\n // waitForConnection: () => Promise<void>;\n // reconnect: () => void;\n\n // Sending only works once keys are exchanged\n send: (message: object) => MaybePromise<void>;\n setup: () => MaybePromise<void>;\n teardown: () => MaybePromise<void>;\n\n getState: () => {\n state: SignalState;\n };\n};\nexport type SignalingLayer = EventEmitter<SignalEventMap> & SignalingContext;\nexport type SignalingLayerFn = (\n properties: SignalingProperties,\n) => Promise<SignalingLayer>;\n\nexport const XR_PREFIX = \"x\";\nexport const XR_H_PREFIX = \"h\";\n\n/**\n * Base Signaling Layer implementation\n *\n * https://openlv.sh/api/signaling\n */\nexport const createSignalingLayer = (\n init: SignalingBaseLayer,\n): SignalingLayerFn => async ({\n canEncrypt,\n encrypt,\n decrypt,\n rpDiscovered,\n h,\n k,\n publicKey,\n isHost,\n}: SignalingProperties) => {\n const emitter = new EventEmitter<SignalEventMap>();\n let state: SignalState = SIGNAL_STATE.STANDBY;\n const setState = (_state: SignalState) => {\n state = _state;\n emitter.emit(\"state_change\", _state);\n };\n const handshakeKey = k || undefined;\n\n const send = async (\n method: \"handshake\" | \"encrypted\",\n recipient: \"h\" | \"c\",\n payload: SignalMessage,\n ) => {\n const prefix = match(method)\n .with(\"handshake\", () => XR_H_PREFIX)\n .with(\"encrypted\", () => XR_PREFIX)\n .exhaustive();\n\n const message = await match(method)\n .with(\"handshake\", () => {\n if (!handshakeKey) return;\n\n return handshakeKey.encrypt(JSON.stringify(payload));\n })\n .with(\"encrypted\", () => {\n if (!canEncrypt()) return;\n\n return encrypt(JSON.stringify(payload));\n })\n .exhaustive();\n\n await init.publish(prefix + recipient + message);\n };\n\n const handleReceive = async (payload: string) => {\n const prefix = payload.slice(0, XR_H_PREFIX.length);\n const recipient = payload.slice(\n XR_H_PREFIX.length,\n XR_H_PREFIX.length + 1,\n );\n const body = payload.slice(XR_PREFIX.length + 1);\n const isRecipient = (isHost ? \"h\" : \"c\") === recipient;\n\n log(\"isRecipient\", isRecipient);\n\n if (!isRecipient) return;\n\n await match({ prefix, body })\n .with({ prefix: XR_H_PREFIX }, async () => {\n if (!handshakeKey) return;\n\n const message = await handshakeKey.decrypt(body);\n const msg = JSON.parse(message) as SignalMessage;\n\n await match({ msg, state, isHost })\n .with({ msg: { type: \"flash\" }, state: SIGNAL_STATE.READY, isHost: true }, async () => {\n setState(SIGNAL_STATE.HANDSHAKE);\n await send(\"handshake\", \"c\", {\n type: \"pubkey\",\n payload: {\n publicKey: publicKey.toString(),\n },\n timestamp: Date.now(),\n });\n })\n .with({ msg: { type: \"pubkey\" }, isHost: false, state: SIGNAL_STATE.HANDSHAKE }, async ({ msg: { payload: msgPayload } }) => {\n try {\n const receivedKey = await parseEncryptionKey(msgPayload.publicKey);\n\n if (!await validatePublicKeyHash(receivedKey, h)) {\n setState(SIGNAL_STATE.ERROR);\n log(\"Received host public key does not match expected hash — possible tampering\");\n\n return;\n }\n }\n catch {\n setState(SIGNAL_STATE.ERROR);\n log(\"Failed to parse received host public key\");\n\n return;\n }\n\n await rpDiscovered(msgPayload.publicKey);\n setState(SIGNAL_STATE.HANDSHAKE_PARTIAL);\n\n return await send(\"encrypted\", \"h\", {\n type: \"pubkey\",\n payload: {\n publicKey: publicKey.toString(),\n },\n timestamp: Date.now(),\n });\n })\n .otherwise(() => {\n log(\"Received invalid message H\", msg);\n });\n })\n .with({ prefix: XR_PREFIX }, async () => {\n const message = await decrypt(body);\n const msg = JSON.parse(message) as SignalMessage;\n\n await match({ msg, state, isHost })\n .with(\n {\n msg: { type: \"pubkey\" },\n isHost: true,\n state: SIGNAL_STATE.HANDSHAKE,\n },\n async ({ msg: { payload: msgPayload } }) => {\n await rpDiscovered(msgPayload.publicKey);\n setState(SIGNAL_STATE.HANDSHAKE_PARTIAL);\n\n return await send(\"encrypted\", \"c\", {\n type: \"ack\",\n payload: undefined,\n timestamp: Date.now(),\n });\n },\n )\n .with(\n {\n msg: { type: \"ack\" },\n state: SIGNAL_STATE.HANDSHAKE_PARTIAL,\n },\n async () => {\n setState(SIGNAL_STATE.ENCRYPTED);\n\n if (isHost) return;\n\n return await send(\"encrypted\", \"h\", {\n type: \"ack\",\n payload: undefined,\n timestamp: Date.now(),\n });\n },\n )\n .with({ msg: { type: \"data\" }, state: SIGNAL_STATE.ENCRYPTED }, async () => {\n emitter.emit(\"message\", msg.payload as object);\n })\n .otherwise(() => {\n log(\"Received invalid message X\", msg);\n });\n })\n .otherwise(() => {\n log(\"Received invalid message\", payload);\n });\n };\n\n return make(emitter, {\n type: init.type,\n async setup() {\n setState(SIGNAL_STATE.CONNECTING);\n await init.setup();\n await init.subscribe(handleReceive);\n\n if (!canEncrypt()) {\n if (isHost) {\n setState(SIGNAL_STATE.READY);\n }\n else {\n setState(SIGNAL_STATE.READY);\n await send(\"handshake\", \"h\", {\n type: \"flash\",\n payload: {},\n timestamp: Date.now(),\n });\n setState(SIGNAL_STATE.HANDSHAKE);\n }\n }\n else {\n setState(SIGNAL_STATE.ENCRYPTED);\n }\n },\n async teardown() {\n log(\"teardown\");\n await init.teardown?.();\n },\n send(message: object) {\n if (!canEncrypt()) {\n return Promise.reject(\n new Error(\"Cannot encrypt message before keys are exchanged\"),\n );\n }\n\n const them = isHost ? \"c\" : \"h\";\n\n return send(\"encrypted\", them, {\n type: \"data\",\n payload: message,\n timestamp: Date.now(),\n });\n },\n getState() {\n return { state: state };\n },\n });\n};\n"]}
|
package/dist/index.test.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { generateKeyPair } from "@openlv/core/encryption";
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
-
import { gundb } from "./gundb/index.js";
|
|
4
3
|
import { mqtt } from "./mqtt/index.js";
|
|
5
4
|
import { ntfy } from "./ntfy/index.js";
|
|
6
5
|
import { log } from "./utils/log.js";
|
|
@@ -58,16 +57,17 @@ const providersByType = [
|
|
|
58
57
|
],
|
|
59
58
|
],
|
|
60
59
|
],
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
],
|
|
60
|
+
// TODO: GunDB is disabled
|
|
61
|
+
// [
|
|
62
|
+
// "gundb",
|
|
63
|
+
// [
|
|
64
|
+
// [
|
|
65
|
+
// "try.axe.eco",
|
|
66
|
+
// gundb,
|
|
67
|
+
// { topic: "mytesttopic1111", url: "wss://try.axe.eco/gun" },
|
|
68
|
+
// ],
|
|
69
|
+
// ],
|
|
70
|
+
// ],
|
|
71
71
|
];
|
|
72
72
|
const testSignalingLayer = async (layer, props) => {
|
|
73
73
|
const { encryptionKey: publicKey, decryptionKey } = await generateKeyPair();
|
package/dist/index.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAG9C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { generateKeyPair } from \"@openlv/core/encryption\";\nimport { describe, expect, it } from \"vitest\";\n\nimport type { CreateSignalLayerFn, SignalBaseProperties } from \"./index.js\";\nimport { mqtt } from \"./mqtt/index.js\";\nimport { ntfy } from \"./ntfy/index.js\";\nimport { log } from \"./utils/log.js\";\n\nconst hKey = \"test\";\n\nconst providersByType: readonly [\n string,\n readonly [string, CreateSignalLayerFn, SignalBaseProperties][],\n][] = [\n [\n \"mqtt\",\n [\n [\n \"mqtt-dashboard\",\n mqtt,\n {\n topic: \"mytesttopic1111\",\n url: \"wss://mqtt-dashboard.com:8884/mqtt\",\n },\n ],\n [\n \"broker.emqx.io\",\n mqtt,\n {\n topic: \"mytesttopic1111\",\n url: \"ws://broker.emqx.io:8083/mqtt\",\n },\n ],\n [\n \"test.mosquitto.org\",\n mqtt,\n {\n topic: \"mytesttopic1111\",\n url: \"ws://test.mosquitto.org:8080/mqtt\",\n },\n ],\n [\n \"broker.itdata.nu\",\n mqtt,\n {\n topic: \"mytesttopic1111\",\n url: \"wss://broker.itdata.nu/mqtt\",\n },\n ],\n ],\n ],\n [\n \"ntfy\",\n [\n [\n \"ntfy.sh\",\n ntfy,\n { topic: \"mytesttopic1111\", url: \"https://ntfy.sh/\" },\n ],\n [\n \"ntfy.envs.net\",\n ntfy,\n { topic: \"mytesttopic1111\", url: \"https://ntfy.envs.net/\" },\n ],\n ],\n ],\n // TODO: GunDB is disabled\n // [\n // \"gundb\",\n // [\n // [\n // \"try.axe.eco\",\n // gundb,\n // { topic: \"mytesttopic1111\", url: \"wss://try.axe.eco/gun\" },\n // ],\n // ],\n // ],\n] as const;\n\nconst testSignalingLayer = async (\n layer: CreateSignalLayerFn,\n props: SignalBaseProperties,\n): Promise<void> => {\n const { encryptionKey: publicKey, decryptionKey } = await generateKeyPair();\n const h = hKey;\n\n const signalingLayer = await layer(props);\n const signalA = await signalingLayer({\n h,\n rpDiscovered: v => log(\"rpKey\", v),\n canEncrypt: () => true,\n encrypt: publicKey.encrypt,\n decrypt: decryptionKey.decrypt,\n publicKey,\n isHost: true,\n });\n const signalB = await signalingLayer({\n h,\n rpDiscovered: v => log(\"rpKey\", v),\n canEncrypt: () => true,\n encrypt: publicKey.encrypt,\n decrypt: decryptionKey.decrypt,\n publicKey,\n isHost: false,\n });\n\n expect(signalA).toBeDefined();\n expect(signalB).toBeDefined();\n\n await Promise.all([signalA.setup(), signalB.setup()]);\n\n const messageReceivedA = new Promise<void>((resolve) => {\n signalA.on(\"message\", (message) => {\n log(\"messageReceivedA\", message);\n expect(message).toEqual({ data: \"test2\" });\n resolve();\n });\n });\n const messageReceivedB = new Promise<void>((resolve) => {\n signalB.on(\"message\", (message) => {\n log(\"messageReceivedB\", message);\n expect(message).toEqual({ data: \"test1\" });\n resolve();\n });\n });\n\n await signalA.send({ data: \"test1\" });\n\n await messageReceivedB;\n\n await signalB.send({ data: \"test2\" });\n\n await messageReceivedA;\n\n await signalA.teardown();\n await signalB.teardown();\n};\n\nconst PROVIDER_TIMEOUT_MS = 5000;\n\ntype ProviderResult =\n | { url: string; ok: true; duration: number; }\n | { url: string; ok: false; error: string; };\n\nconst testProvider = async (\n layer: CreateSignalLayerFn,\n props: SignalBaseProperties,\n): Promise<ProviderResult> => {\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`Timeout after ${PROVIDER_TIMEOUT_MS}ms`)),\n PROVIDER_TIMEOUT_MS,\n ),\n );\n\n const startTime = performance.now();\n\n try {\n await Promise.race([testSignalingLayer(layer, props), timeout]);\n const duration = Math.round(performance.now() - startTime);\n\n return { url: props.url, ok: true, duration };\n }\n catch (error) {\n return {\n url: props.url,\n ok: false,\n error: (error as Error).message,\n };\n }\n};\n\nconst formatResults = (typeName: string, results: ProviderResult[]): string => {\n const passed = results.filter(r => r.ok).length;\n const total = results.length;\n\n return [\n `${typeName.toUpperCase()}: ${passed}/${total}`,\n ...results.map(r =>\n (r.ok ? `✓ ${r.url} ${r.duration}ms` : `✗ ${r.url} - ${r.error}`),\n ),\n ].join(\"\\n\");\n};\n\ndescribe.for(providersByType)(\"signaling: %s\", ([typeName, providers]) => {\n it(\n \"should pass signaling messages between peers\",\n { timeout: PROVIDER_TIMEOUT_MS * providers.length + 5000 },\n async () => {\n const results = await Promise.all(\n providers.map(([, layer, props]) => testProvider(layer, props)),\n );\n\n const summary = formatResults(typeName, results);\n\n console.log(`\\n${summary}`);\n\n const passed = results.filter(r => r.ok).length;\n\n expect(passed).toBeGreaterThan(0);\n },\n );\n});\n"]}
|
package/dist/messages.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"","sourcesContent":["export type SignalMessageBase<T extends string, P> = {\n type: T;\n payload: P;\n timestamp: number;\n};\n\n/**\n * Flash message\n * Sent to initiate handshake by non-host\n */\nexport type SignalMessageFlash = SignalMessageBase<\"flash\", object>;\n\nexport type SignalMessagePubkey = SignalMessageBase<\n \"pubkey\",\n {\n publicKey: string;\n dAppInfo?: {\n name: string;\n url: string;\n icon: string;\n };\n }\n>;\n\nexport type SignalMessageAck = SignalMessageBase<\"ack\", undefined>;\n\nexport type SignalMessageData = SignalMessageBase<\"data\", object>;\n\nexport type SignalMessage =\n | SignalMessageFlash\n | SignalMessagePubkey\n | SignalMessageAck\n | SignalMessageData;\n"]}
|
package/dist/mqtt/index.d.ts
CHANGED
package/dist/mqtt/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mqtt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAmB,MAAM,gBAAgB,CAAC;AAG7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAwB,CAAC,EACxC,GAAG,GAAG,oCAAoC,EAC1C,KAAK,GACgB,EAAE,EAAE;IACzB,IAAI,UAAkC,CAAC;IAEvC,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,MAAM;QACZ,KAAK;YACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,UAAU,GAAG,UAAU,CAAC;oBACtB,GAAG;oBACH,kCAAkC;oBAClC,yBAAyB;oBACzB,wBAAwB;iBACzB,CAAC,CAAC;gBAEH,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;oBAC5B,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;gBACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;oBAC/B,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;oBACtD,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC,CAAC,CAAC;gBAEH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;oBAC1B,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAC;gBACtD,CAAC,CAAC,CAAC;gBAEH,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,QAAQ;YACN,UAAU,EAAE,KAAK,EAAE,CAAC;YACpB,UAAU,GAAG,SAAS,CAAC;QACzB,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACvD,CAAC;YAED,UAAU,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,OAAO;YACrB,IAAI,CAAC,UAAU;gBAAE,MAAM,IAAI,uBAAuB,EAAE,CAAC;YAErD,GAAG,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YAEzC,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,EAAE;gBAClD,GAAG,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;gBAE9C,IAAI,aAAa,KAAK,KAAK;oBAAE,OAAO;gBAEpC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAElD,OAAO,CAAC,OAAO,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;YAEH,MAAM,UAAU,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC","sourcesContent":["import { SignalNoConnectionError } from \"@openlv/core/errors\";\nimport { createMqtt, type MqttClient } from \"websocket-mqtt\";\n\nimport type { CreateSignalLayerFn, SignalBaseProperties } from \"../
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mqtt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAmB,MAAM,gBAAgB,CAAC;AAG7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAwB,CAAC,EACxC,GAAG,GAAG,oCAAoC,EAC1C,KAAK,GACgB,EAAE,EAAE;IACzB,IAAI,UAAkC,CAAC;IAEvC,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,MAAM;QACZ,KAAK;YACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,UAAU,GAAG,UAAU,CAAC;oBACtB,GAAG;oBACH,kCAAkC;oBAClC,yBAAyB;oBACzB,wBAAwB;iBACzB,CAAC,CAAC;gBAEH,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;oBAC5B,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;gBACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;oBAC/B,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;oBACtD,MAAM,CAAC,KAAK,CAAC,CAAC;gBAChB,CAAC,CAAC,CAAC;gBAEH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;oBAC1B,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAC;gBACtD,CAAC,CAAC,CAAC;gBAEH,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,CAAC,CAAC,CAAC;QACL,CAAC;QACD,QAAQ;YACN,UAAU,EAAE,KAAK,EAAE,CAAC;YACpB,UAAU,GAAG,SAAS,CAAC;QACzB,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,OAAO;YACnB,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;YACvD,CAAC;YAED,UAAU,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,OAAO;YACrB,IAAI,CAAC,UAAU;gBAAE,MAAM,IAAI,uBAAuB,EAAE,CAAC;YAErD,GAAG,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;YAEzC,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,EAAE;gBAClD,GAAG,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;gBAE9C,IAAI,aAAa,KAAK,KAAK;oBAAE,OAAO;gBAEpC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAElD,OAAO,CAAC,OAAO,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;YAEH,MAAM,UAAU,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC","sourcesContent":["import { SignalNoConnectionError } from \"@openlv/core/errors\";\nimport { createMqtt, type MqttClient } from \"websocket-mqtt\";\n\nimport type { CreateSignalLayerFn, SignalBaseProperties } from \"../index.js\";\nimport { createSignalingLayer } from \"../index.js\";\nimport { log } from \"../utils/log.js\";\n\n/**\n * MQTT Signaling Layer\n *\n * https://openlv.sh/api/signaling/mqtt\n */\nexport const mqtt: CreateSignalLayerFn = ({\n url = \"wss://test.mosquitto.org:8081/mqtt\",\n topic,\n}: SignalBaseProperties) => {\n let connection: MqttClient | undefined;\n\n return createSignalingLayer({\n type: \"mqtt\",\n setup() {\n return new Promise((resolve, reject) => {\n connection = createMqtt({\n url,\n // reconnectOnConnackError: false,\n // reconnectPeriod: 5000,\n // connectTimeout: 5000,\n });\n\n connection.on(\"connect\", () => {\n resolve();\n });\n connection.on(\"error\", (error) => {\n console.error(\"MQTT: Error connecting to URL\", error);\n reject(error);\n });\n\n connection.on(\"close\", () => {\n reject(new Error(\"MQTT: Closed connection to URL\"));\n });\n\n connection.connect();\n });\n },\n teardown() {\n connection?.close();\n connection = undefined;\n },\n async publish(payload) {\n if (!connection) {\n throw new Error(\"MQTT: No connection to publish to\");\n }\n\n connection?.publish(topic, payload, { retain: false });\n },\n async subscribe(handler) {\n if (!connection) throw new SignalNoConnectionError();\n\n log(\"MQTT: Subscribing to topic\", topic);\n\n connection.on(\"message\", (receivedTopic, message) => {\n log(\"MQTT: Received message on topic\", topic);\n\n if (receivedTopic !== topic) return;\n\n const decoded = new TextDecoder().decode(message);\n\n handler(decoded);\n });\n\n await connection?.subscribe(topic);\n },\n });\n};\n\nObject.defineProperty(mqtt, \"__name\", { value: \"mqtt\" });\n"]}
|
package/dist/ntfy/index.d.ts
CHANGED
package/dist/ntfy/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ntfy/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"eventemitter3\";\nimport { match } from \"ts-pattern\";\n\nimport type { CreateSignalLayerFn } from \"../
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ntfy/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"eventemitter3\";\nimport { match } from \"ts-pattern\";\n\nimport type { CreateSignalLayerFn } from \"../index.js\";\nimport { createSignalingLayer } from \"../index.js\";\nimport { log } from \"../utils/log.js\";\nimport { parseNtfyUrl } from \"./url.js\";\n\nexport type NtfyMessage = {\n // eslint-disable-next-line no-restricted-syntax\n id: string;\n time: number;\n expires: number;\n event: string;\n topic: string;\n message: string;\n};\n\n/**\n * Ntfy Signaling Layer\n *\n * Uses HTTP Post for publishing\n * Uses WebSocket for subscribing\n *\n * URL format supports the ?auth= parameter\n * example: https://ntfy.sh/mytopic?auth=mytoken\n *\n * The same goes for apprise ntfy urls\n * example: ntfy://{token}@{hostname}/{topic}\n * example: ntfy://{user}:{password}@{hostname}/{topic}\n * https variant: ntfys://{user}:{password}@{hostname}/{topic}\n *\n * https://openlv.sh/api/signaling/ntfy\n */\nexport const ntfy: CreateSignalLayerFn = ({ topic, url }) => {\n let connection: WebSocket | undefined;\n const connectionInfo = parseNtfyUrl(url);\n const wsProtocol = match(connectionInfo.protocol)\n .with(\"https\", () => \"wss\")\n .with(\"http\", () => \"ws\")\n .exhaustive();\n const events = new EventEmitter<{ message: string; }>();\n\n return createSignalingLayer({\n type: \"ntfy\",\n async setup() {\n log(\"NTFY: Setting up\");\n\n const wsUrl\n = wsProtocol\n + \"://\"\n + connectionInfo.host\n + \"/\"\n + topic\n + \"/ws\"\n + (connectionInfo.parameters || \"\");\n\n log(\"NTFY: Connecting to WebSocket\", wsUrl);\n connection = new WebSocket(wsUrl);\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n connection?.addEventListener(\"error\", (_event) => {});\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n connection.addEventListener(\"close\", (_event) => {});\n\n const awaitOpenConfirm = new Promise<void>((resolve) => {\n connection!.addEventListener(\"message\", (event) => {\n log(\"NTFY: Received message:\", event.data);\n const data = JSON.parse(event.data) as NtfyMessage;\n\n if (data.event === \"open\") {\n resolve();\n }\n else if (data.event === \"message\") {\n events.emit(\"message\", data.message);\n }\n });\n });\n\n const awaitOpen = new Promise<void>((resolve) => {\n connection!.addEventListener(\"open\", () => {\n log(\"NTFY: Connected to WebSocket\");\n resolve();\n });\n });\n\n await awaitOpen;\n await awaitOpenConfirm;\n },\n teardown() {\n connection?.close();\n },\n async publish(body) {\n const headers = { \"Content-Type\": \"application/json\" } as HeadersInit;\n\n // TODO: Add response handling\n // @ts-expect-error - TODO: Add response handling\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const _response = await fetch(\n `${connectionInfo.protocol}://${connectionInfo.host}/${topic}`,\n { method: \"POST\", body, headers },\n );\n },\n subscribe: (handler) => {\n events.on(\"message\", handler);\n },\n });\n};\n\nObject.defineProperty(ntfy, \"__name\", { value: \"ntfy\" });\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openlv/signaling",
|
|
3
|
-
"version": "0.0.1
|
|
3
|
+
"version": "0.0.1",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"open-lavatory"
|
|
6
6
|
],
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"gun": "^0.2020.1241",
|
|
60
60
|
"websocket-mqtt": "0.0.7",
|
|
61
61
|
"ts-pattern": "^5",
|
|
62
|
-
"@openlv/core": "0.0.1
|
|
62
|
+
"@openlv/core": "0.0.1"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"typescript": "^5",
|
package/dist/base.d.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { EncryptionKey, SymmetricKey } from "@openlv/core/encryption";
|
|
2
|
-
import { EventEmitter } from "eventemitter3";
|
|
3
|
-
import type { MaybePromise } from "viem";
|
|
4
|
-
import type { SignalEventMap, SignalState } from "./layer.js";
|
|
5
|
-
export type SignalBaseProperties = {
|
|
6
|
-
topic: string;
|
|
7
|
-
url: string;
|
|
8
|
-
};
|
|
9
|
-
export type SignalingBaseLayer = {
|
|
10
|
-
type: string;
|
|
11
|
-
setup: () => MaybePromise<void>;
|
|
12
|
-
teardown: () => MaybePromise<void>;
|
|
13
|
-
publish: (payload: string) => MaybePromise<void>;
|
|
14
|
-
subscribe: (handler: (payload: string) => void) => MaybePromise<void>;
|
|
15
|
-
};
|
|
16
|
-
export type CreateSignalLayerFn = (properties: SignalBaseProperties) => MaybePromise<SignalingLayerFn>;
|
|
17
|
-
export type SignalingProperties = {
|
|
18
|
-
isHost: boolean;
|
|
19
|
-
h: string;
|
|
20
|
-
k?: SymmetricKey;
|
|
21
|
-
rpDiscovered: (rpKey: string) => MaybePromise<void>;
|
|
22
|
-
decrypt: (message: string) => MaybePromise<string>;
|
|
23
|
-
encrypt: (message: string) => MaybePromise<string>;
|
|
24
|
-
publicKey: EncryptionKey;
|
|
25
|
-
canEncrypt: () => boolean;
|
|
26
|
-
};
|
|
27
|
-
export type SignalingContext = {
|
|
28
|
-
type: string;
|
|
29
|
-
send: (message: object) => MaybePromise<void>;
|
|
30
|
-
setup: () => MaybePromise<void>;
|
|
31
|
-
teardown: () => MaybePromise<void>;
|
|
32
|
-
getState: () => {
|
|
33
|
-
state: SignalState;
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
export type SignalingLayer = EventEmitter<SignalEventMap> & SignalingContext;
|
|
37
|
-
export type SignalingLayerFn = (properties: SignalingProperties) => Promise<SignalingLayer>;
|
|
38
|
-
export declare const XR_PREFIX = "x";
|
|
39
|
-
export declare const XR_H_PREFIX = "h";
|
|
40
|
-
/**
|
|
41
|
-
* Base Signaling Layer implementation
|
|
42
|
-
*
|
|
43
|
-
* https://openlv.sh/api/signaling
|
|
44
|
-
*/
|
|
45
|
-
export declare const createSignalingLayer: (init: SignalingBaseLayer) => SignalingLayerFn;
|
package/dist/base.js
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import { make } from "@openlv/core";
|
|
2
|
-
import { EventEmitter } from "eventemitter3";
|
|
3
|
-
import { match } from "ts-pattern";
|
|
4
|
-
import { SIGNAL_STATE } from "./layer.js";
|
|
5
|
-
import { log } from "./utils/log.js";
|
|
6
|
-
export const XR_PREFIX = "x";
|
|
7
|
-
export const XR_H_PREFIX = "h";
|
|
8
|
-
/**
|
|
9
|
-
* Base Signaling Layer implementation
|
|
10
|
-
*
|
|
11
|
-
* https://openlv.sh/api/signaling
|
|
12
|
-
*/
|
|
13
|
-
export const createSignalingLayer = (init) => async ({ canEncrypt, encrypt, decrypt, rpDiscovered, k, publicKey, isHost, }) => {
|
|
14
|
-
const emitter = new EventEmitter();
|
|
15
|
-
let state = SIGNAL_STATE.STANDBY;
|
|
16
|
-
const setState = (_state) => {
|
|
17
|
-
state = _state;
|
|
18
|
-
emitter.emit("state_change", _state);
|
|
19
|
-
};
|
|
20
|
-
const handshakeKey = k || undefined;
|
|
21
|
-
const send = async (method, recipient, payload) => {
|
|
22
|
-
const prefix = match(method)
|
|
23
|
-
.with("handshake", () => XR_H_PREFIX)
|
|
24
|
-
.with("encrypted", () => XR_PREFIX)
|
|
25
|
-
.exhaustive();
|
|
26
|
-
const message = await match(method)
|
|
27
|
-
.with("handshake", () => {
|
|
28
|
-
if (!handshakeKey)
|
|
29
|
-
return;
|
|
30
|
-
return handshakeKey.encrypt(JSON.stringify(payload));
|
|
31
|
-
})
|
|
32
|
-
.with("encrypted", () => {
|
|
33
|
-
if (!canEncrypt())
|
|
34
|
-
return;
|
|
35
|
-
return encrypt(JSON.stringify(payload));
|
|
36
|
-
})
|
|
37
|
-
.exhaustive();
|
|
38
|
-
await init.publish(prefix + recipient + message);
|
|
39
|
-
};
|
|
40
|
-
const handleReceive = async (payload) => {
|
|
41
|
-
const prefix = payload.slice(0, XR_H_PREFIX.length);
|
|
42
|
-
const recipient = payload.slice(XR_H_PREFIX.length, XR_H_PREFIX.length + 1);
|
|
43
|
-
const body = payload.slice(XR_PREFIX.length + 1);
|
|
44
|
-
const isRecipient = (isHost ? "h" : "c") === recipient;
|
|
45
|
-
log("isRecipient", isRecipient);
|
|
46
|
-
if (!isRecipient)
|
|
47
|
-
return;
|
|
48
|
-
await match({ prefix, body })
|
|
49
|
-
.with({ prefix: XR_H_PREFIX }, async () => {
|
|
50
|
-
if (!handshakeKey)
|
|
51
|
-
return;
|
|
52
|
-
const message = await handshakeKey.decrypt(body);
|
|
53
|
-
const msg = JSON.parse(message);
|
|
54
|
-
await match(msg)
|
|
55
|
-
.with({ type: "flash" }, async () => {
|
|
56
|
-
if (!isHost)
|
|
57
|
-
return;
|
|
58
|
-
setState(SIGNAL_STATE.HANDSHAKE);
|
|
59
|
-
await send("handshake", "c", {
|
|
60
|
-
type: "pubkey",
|
|
61
|
-
payload: {
|
|
62
|
-
publicKey: publicKey.toString(),
|
|
63
|
-
},
|
|
64
|
-
timestamp: Date.now(),
|
|
65
|
-
});
|
|
66
|
-
})
|
|
67
|
-
.with({ type: "pubkey" }, async ({ payload }) => {
|
|
68
|
-
if (isHost)
|
|
69
|
-
return;
|
|
70
|
-
await rpDiscovered(payload.publicKey);
|
|
71
|
-
setState(SIGNAL_STATE.HANDSHAKE_PARTIAL);
|
|
72
|
-
return await send("encrypted", "h", {
|
|
73
|
-
type: "pubkey",
|
|
74
|
-
payload: {
|
|
75
|
-
publicKey: publicKey.toString(),
|
|
76
|
-
},
|
|
77
|
-
timestamp: Date.now(),
|
|
78
|
-
});
|
|
79
|
-
})
|
|
80
|
-
.otherwise(() => {
|
|
81
|
-
log("Received invalid message H", msg);
|
|
82
|
-
});
|
|
83
|
-
})
|
|
84
|
-
.with({ prefix: XR_PREFIX }, async () => {
|
|
85
|
-
const message = await decrypt(body);
|
|
86
|
-
const msg = JSON.parse(message);
|
|
87
|
-
await match(msg)
|
|
88
|
-
.with({ type: "pubkey" }, async ({ payload }) => {
|
|
89
|
-
if (!isHost)
|
|
90
|
-
return;
|
|
91
|
-
await rpDiscovered(payload.publicKey);
|
|
92
|
-
setState(SIGNAL_STATE.HANDSHAKE_PARTIAL);
|
|
93
|
-
return await send("encrypted", "c", {
|
|
94
|
-
type: "ack",
|
|
95
|
-
payload: undefined,
|
|
96
|
-
timestamp: Date.now(),
|
|
97
|
-
});
|
|
98
|
-
})
|
|
99
|
-
.with({ type: "ack" }, async () => {
|
|
100
|
-
if (state !== SIGNAL_STATE.HANDSHAKE_PARTIAL)
|
|
101
|
-
return;
|
|
102
|
-
setState(SIGNAL_STATE.ENCRYPTED);
|
|
103
|
-
if (isHost)
|
|
104
|
-
return;
|
|
105
|
-
return await send("encrypted", "h", {
|
|
106
|
-
type: "ack",
|
|
107
|
-
payload: undefined,
|
|
108
|
-
timestamp: Date.now(),
|
|
109
|
-
});
|
|
110
|
-
})
|
|
111
|
-
.with({ type: "data" }, async () => emitter.emit("message", msg.payload))
|
|
112
|
-
.otherwise(() => {
|
|
113
|
-
log("Received invalid message X", msg);
|
|
114
|
-
});
|
|
115
|
-
})
|
|
116
|
-
.otherwise(() => {
|
|
117
|
-
log("Received invalid message", payload);
|
|
118
|
-
});
|
|
119
|
-
};
|
|
120
|
-
return make(emitter, {
|
|
121
|
-
type: init.type,
|
|
122
|
-
async setup() {
|
|
123
|
-
setState(SIGNAL_STATE.CONNECTING);
|
|
124
|
-
await init.setup();
|
|
125
|
-
if (!canEncrypt()) {
|
|
126
|
-
if (!isHost) {
|
|
127
|
-
setState(SIGNAL_STATE.READY);
|
|
128
|
-
await send("handshake", "h", {
|
|
129
|
-
type: "flash",
|
|
130
|
-
payload: {},
|
|
131
|
-
timestamp: Date.now(),
|
|
132
|
-
});
|
|
133
|
-
setState(SIGNAL_STATE.HANDSHAKE);
|
|
134
|
-
}
|
|
135
|
-
if (isHost) {
|
|
136
|
-
setState(SIGNAL_STATE.READY);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
await init.subscribe(handleReceive);
|
|
140
|
-
},
|
|
141
|
-
async teardown() {
|
|
142
|
-
log("teardown");
|
|
143
|
-
await init.teardown?.();
|
|
144
|
-
},
|
|
145
|
-
send(message) {
|
|
146
|
-
if (!canEncrypt()) {
|
|
147
|
-
return Promise.reject(new Error("Cannot encrypt message before keys are exchanged"));
|
|
148
|
-
}
|
|
149
|
-
const them = isHost ? "c" : "h";
|
|
150
|
-
return send("encrypted", them, {
|
|
151
|
-
type: "data",
|
|
152
|
-
payload: message,
|
|
153
|
-
timestamp: Date.now(),
|
|
154
|
-
});
|
|
155
|
-
},
|
|
156
|
-
getState() {
|
|
157
|
-
return { state: state };
|
|
158
|
-
},
|
|
159
|
-
});
|
|
160
|
-
};
|
|
161
|
-
//# sourceMappingURL=base.js.map
|
package/dist/base.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"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","sourcesContent":["import { make } from \"@openlv/core\";\nimport type { EncryptionKey, SymmetricKey } from \"@openlv/core/encryption\";\nimport { EventEmitter } from \"eventemitter3\";\nimport { match } from \"ts-pattern\";\nimport type { MaybePromise } from \"viem\";\n\nimport type { SignalEventMap, SignalState } from \"./layer.js\";\nimport { SIGNAL_STATE } from \"./layer.js\";\nimport type { SignalMessage } from \"./messages/index.js\";\nimport { log } from \"./utils/log.js\";\n\nexport type SignalBaseProperties = {\n topic: string;\n url: string;\n};\n\nexport type SignalingBaseLayer = {\n type: string;\n setup: () => MaybePromise<void>;\n teardown: () => MaybePromise<void>;\n publish: (payload: string) => MaybePromise<void>;\n subscribe: (handler: (payload: string) => void) => MaybePromise<void>;\n};\n\nexport type CreateSignalLayerFn = (\n properties: SignalBaseProperties,\n) => MaybePromise<SignalingLayerFn>;\n\nexport type SignalingProperties = {\n isHost: boolean;\n h: string;\n k?: SymmetricKey;\n rpDiscovered: (rpKey: string) => MaybePromise<void>;\n // Decrypt using our private key\n decrypt: (message: string) => MaybePromise<string>;\n // Encrypt to relying party\n encrypt: (message: string) => MaybePromise<string>;\n // our public key\n publicKey: EncryptionKey;\n canEncrypt: () => boolean;\n};\n\nexport type SignalingContext = {\n type: string;\n // waitForConnection: () => Promise<void>;\n // reconnect: () => void;\n\n // Sending only works once keys are exchanged\n send: (message: object) => MaybePromise<void>;\n setup: () => MaybePromise<void>;\n teardown: () => MaybePromise<void>;\n\n getState: () => {\n state: SignalState;\n };\n};\nexport type SignalingLayer = EventEmitter<SignalEventMap> & SignalingContext;\nexport type SignalingLayerFn = (\n properties: SignalingProperties,\n) => Promise<SignalingLayer>;\n\nexport const XR_PREFIX = \"x\";\nexport const XR_H_PREFIX = \"h\";\n\n/**\n * Base Signaling Layer implementation\n *\n * https://openlv.sh/api/signaling\n */\nexport const createSignalingLayer = (\n init: SignalingBaseLayer,\n): SignalingLayerFn => async ({\n canEncrypt,\n encrypt,\n decrypt,\n rpDiscovered,\n k,\n publicKey,\n isHost,\n}: SignalingProperties) => {\n const emitter = new EventEmitter<SignalEventMap>();\n let state: SignalState = SIGNAL_STATE.STANDBY;\n const setState = (_state: SignalState) => {\n state = _state;\n emitter.emit(\"state_change\", _state);\n };\n const handshakeKey = k || undefined;\n\n const send = async (\n method: \"handshake\" | \"encrypted\",\n recipient: \"h\" | \"c\",\n payload: SignalMessage,\n ) => {\n const prefix = match(method)\n .with(\"handshake\", () => XR_H_PREFIX)\n .with(\"encrypted\", () => XR_PREFIX)\n .exhaustive();\n\n const message = await match(method)\n .with(\"handshake\", () => {\n if (!handshakeKey) return;\n\n return handshakeKey.encrypt(JSON.stringify(payload));\n })\n .with(\"encrypted\", () => {\n if (!canEncrypt()) return;\n\n return encrypt(JSON.stringify(payload));\n })\n .exhaustive();\n\n await init.publish(prefix + recipient + message);\n };\n\n const handleReceive = async (payload: string) => {\n const prefix = payload.slice(0, XR_H_PREFIX.length);\n const recipient = payload.slice(\n XR_H_PREFIX.length,\n XR_H_PREFIX.length + 1,\n );\n const body = payload.slice(XR_PREFIX.length + 1);\n const isRecipient = (isHost ? \"h\" : \"c\") === recipient;\n\n log(\"isRecipient\", isRecipient);\n\n if (!isRecipient) return;\n\n await match({ prefix, body })\n .with({ prefix: XR_H_PREFIX }, async () => {\n if (!handshakeKey) return;\n\n const message = await handshakeKey.decrypt(body);\n const msg = JSON.parse(message) as SignalMessage;\n\n await match(msg)\n .with({ type: \"flash\" }, async () => {\n if (!isHost) return;\n\n setState(SIGNAL_STATE.HANDSHAKE);\n await send(\"handshake\", \"c\", {\n type: \"pubkey\",\n payload: {\n publicKey: publicKey.toString(),\n },\n timestamp: Date.now(),\n });\n })\n .with({ type: \"pubkey\" }, async ({ payload }) => {\n if (isHost) return;\n\n await rpDiscovered(payload.publicKey);\n setState(SIGNAL_STATE.HANDSHAKE_PARTIAL);\n\n return await send(\"encrypted\", \"h\", {\n type: \"pubkey\",\n payload: {\n publicKey: publicKey.toString(),\n },\n timestamp: Date.now(),\n });\n })\n .otherwise(() => {\n log(\"Received invalid message H\", msg);\n });\n })\n .with({ prefix: XR_PREFIX }, async () => {\n const message = await decrypt(body);\n const msg = JSON.parse(message) as SignalMessage;\n\n await match(msg)\n .with({ type: \"pubkey\" }, async ({ payload }) => {\n if (!isHost) return;\n\n await rpDiscovered(payload.publicKey);\n setState(SIGNAL_STATE.HANDSHAKE_PARTIAL);\n\n return await send(\"encrypted\", \"c\", {\n type: \"ack\",\n payload: undefined,\n timestamp: Date.now(),\n });\n })\n .with({ type: \"ack\" }, async () => {\n if (state !== SIGNAL_STATE.HANDSHAKE_PARTIAL) return;\n\n setState(SIGNAL_STATE.ENCRYPTED);\n\n if (isHost) return;\n\n return await send(\"encrypted\", \"h\", {\n type: \"ack\",\n payload: undefined,\n timestamp: Date.now(),\n });\n })\n .with({ type: \"data\" }, async () =>\n emitter.emit(\"message\", msg.payload as object),\n )\n .otherwise(() => {\n log(\"Received invalid message X\", msg);\n });\n })\n .otherwise(() => {\n log(\"Received invalid message\", payload);\n });\n };\n\n return make(emitter, {\n type: init.type,\n async setup() {\n setState(SIGNAL_STATE.CONNECTING);\n await init.setup();\n\n if (!canEncrypt()) {\n if (!isHost) {\n setState(SIGNAL_STATE.READY);\n await send(\"handshake\", \"h\", {\n type: \"flash\",\n payload: {},\n timestamp: Date.now(),\n });\n setState(SIGNAL_STATE.HANDSHAKE);\n }\n\n if (isHost) {\n setState(SIGNAL_STATE.READY);\n }\n }\n\n await init.subscribe(handleReceive);\n },\n async teardown() {\n log(\"teardown\");\n await init.teardown?.();\n },\n send(message: object) {\n if (!canEncrypt()) {\n return Promise.reject(\n new Error(\"Cannot encrypt message before keys are exchanged\"),\n );\n }\n\n const them = isHost ? \"c\" : \"h\";\n\n return send(\"encrypted\", them, {\n type: \"data\",\n payload: message,\n timestamp: Date.now(),\n });\n },\n getState() {\n return { state: state };\n },\n });\n};\n"]}
|
package/dist/layer.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export declare const SIGNAL_STATE: {
|
|
2
|
-
readonly STANDBY: "standby";
|
|
3
|
-
readonly CONNECTING: "connecting";
|
|
4
|
-
readonly READY: "ready";
|
|
5
|
-
readonly HANDSHAKE: "handshake";
|
|
6
|
-
readonly HANDSHAKE_PARTIAL: "handshake-partial";
|
|
7
|
-
readonly ENCRYPTED: "encrypted";
|
|
8
|
-
readonly ERROR: "error";
|
|
9
|
-
};
|
|
10
|
-
export type SignalState = (typeof SIGNAL_STATE)[keyof typeof SIGNAL_STATE];
|
|
11
|
-
export type SignalEventMap = {
|
|
12
|
-
state_change: (state: SignalState) => void;
|
|
13
|
-
message: (message: object) => void;
|
|
14
|
-
};
|
package/dist/layer.js
DELETED
package/dist/layer.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"layer.js","sourceRoot":"","sources":["../src/layer.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,YAAY;IACxB,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,WAAW;IACtB,iBAAiB,EAAE,mBAAmB;IACtC,SAAS,EAAE,WAAW;IACtB,KAAK,EAAE,OAAO;CACN,CAAC","sourcesContent":["export const SIGNAL_STATE = {\n STANDBY: \"standby\",\n CONNECTING: \"connecting\",\n READY: \"ready\",\n HANDSHAKE: \"handshake\",\n HANDSHAKE_PARTIAL: \"handshake-partial\",\n ENCRYPTED: \"encrypted\",\n ERROR: \"error\",\n} as const;\nexport type SignalState = (typeof SIGNAL_STATE)[keyof typeof SIGNAL_STATE];\n\nexport type SignalEventMap = {\n state_change: (state: SignalState) => void;\n message: (message: object) => void;\n};\n"]}
|
package/dist/messages/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":"","sourcesContent":["export type SignalMessageBase<T extends string, P> = {\n type: T;\n payload: P;\n timestamp: number;\n};\n\n/**\n * Flash message\n * Sent to initiate handshake by non-host\n */\nexport type SignalMessageFlash = SignalMessageBase<\"flash\", object>;\n\nexport type SignalMessagePubkey = SignalMessageBase<\n \"pubkey\",\n {\n publicKey: string;\n dAppInfo?: {\n name: string;\n url: string;\n icon: string;\n };\n }\n>;\n\nexport type SignalMessageAck = SignalMessageBase<\"ack\", undefined>;\n\nexport type SignalMessageData = SignalMessageBase<\"data\", object>;\n\nexport type SignalMessage =\n | SignalMessageFlash\n | SignalMessagePubkey\n | SignalMessageAck\n | SignalMessageData;\n"]}
|
|
File without changes
|