@openlv/session 0.0.1-beta.9 → 0.0.2

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/events.d.ts CHANGED
@@ -1,4 +1,10 @@
1
- import type { SessionStateObject } from "./base.js";
1
+ import type { SessionStateObject } from "./index.js";
2
2
  export type SessionEvents = {
3
3
  state_change: (state?: SessionStateObject) => void;
4
+ /**
5
+ * Emitted when a request arrives from the remote peer — before the reply
6
+ * is sent. Useful for observability, logging, or UI integration without
7
+ * needing to intercept the `onMessage` callback.
8
+ */
9
+ request: (payload: object | string) => void;
4
10
  };
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"","sourcesContent":["import type { SessionStateObject } from \"./index.js\";\n\nexport type SessionEvents = {\n state_change: (state?: SessionStateObject) => void;\n /**\n * Emitted when a request arrives from the remote peer — before the reply\n * is sent. Useful for observability, logging, or UI integration without\n * needing to intercept the `onMessage` callback.\n */\n request: (payload: object | string) => void;\n};\n"]}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,58 @@
1
- /** biome-ignore-all lint/performance/noBarrelFile: package entrypoint */
1
+ import { type SessionHandshakeParameters, type SessionLinkParameters } from "@openlv/core";
2
+ import { type SignalingLayer, type SignalingProtocol, type SignalState } from "@openlv/signaling";
3
+ import { type TLayer, type TransportLayer } from "@openlv/transport";
4
+ import { EventEmitter } from "eventemitter3";
5
+ import type { SessionEvents } from "./events.js";
6
+ export declare const SESSION_STATE: {
7
+ readonly CREATED: "created";
8
+ readonly SIGNALING: "signaling";
9
+ readonly READY: "ready";
10
+ readonly LINKING: "linking";
11
+ readonly CONNECTED: "connected";
12
+ readonly DISCONNECTED: "disconnected";
13
+ };
14
+ export type SessionState = (typeof SESSION_STATE)[keyof typeof SESSION_STATE];
15
+ export type SessionStateObject = {
16
+ status: SessionState;
17
+ signaling?: {
18
+ state: SignalState;
19
+ };
20
+ };
2
21
  /**
3
- * Open Lavatory Protocol - Decentralized Wallet Connection Library
22
+ * an OpenLV Session
4
23
  *
5
- * A privacy-first, peer-to-peer protocol for connecting dApps with wallets
6
- * without relying on centralized infrastructure.
24
+ * https://openlv.sh/api/session
7
25
  */
8
- export * from "./base.js";
26
+ export type Session = {
27
+ getState(): SessionStateObject;
28
+ getHandshakeParameters(): SessionHandshakeParameters;
29
+ connect(): Promise<void>;
30
+ waitForLink(): Promise<void>;
31
+ close(): Promise<void>;
32
+ /**
33
+ * Send a request to the remote peer and await a correlated response.
34
+ *
35
+ * Two-phase timeout:
36
+ * - `ackTimeout` (default 10 s): the remote peer must send back an ack
37
+ * within this window, confirming it received the message.
38
+ * - After an ack arrives the wait is extended to `responseTimeout`
39
+ * (default 1 hour) — enough for user-interactive flows such as
40
+ * `eth_sendTransaction` or `personal_sign`.
41
+ */
42
+ send(message: object, ackTimeout?: number, responseTimeout?: number): Promise<unknown>;
43
+ emitter: EventEmitter<SessionEvents>;
44
+ _internal: {
45
+ signal: SignalingLayer;
46
+ transport: TransportLayer;
47
+ };
48
+ };
49
+ /**
50
+ * OpenLV Session
51
+ *
52
+ * https://openlv.sh/api/session
53
+ */
54
+ export declare const createSession: (initParameters: SessionLinkParameters, signalLayer: SignalingProtocol, transportLayer: TLayer, onMessage: (message: object) => Promise<object | string>) => Promise<Session>;
55
+ /**
56
+ * Connect to a session from its openlv:// URL
57
+ */
58
+ export declare const connectSession: (connectionUrl: string, onMessage: (message: object) => Promise<object | string>, transport: TLayer) => Promise<Session>;
package/dist/index.js CHANGED
@@ -1,10 +1,273 @@
1
- /** biome-ignore-all lint/performance/noBarrelFile: package entrypoint */
1
+ import { decodeConnectionURL, OPENLV_PROTOCOL_VERSION, } from "@openlv/core";
2
+ import { deriveSymmetricKey, generateHandshakeKey, generateSessionId, initEncryptionKeys, initHash, parseEncryptionKey, } from "@openlv/core/encryption";
3
+ import { SIGNAL_STATE, } from "@openlv/signaling";
4
+ import { dynamicSignalingLayer } from "@openlv/signaling/dynamic";
5
+ import { TRANSPORT_STATE, } from "@openlv/transport";
6
+ import { EventEmitter } from "eventemitter3";
7
+ import { log } from "./utils/log.js";
8
+ export const SESSION_STATE = {
9
+ CREATED: "created",
10
+ SIGNALING: "signaling",
11
+ READY: "ready",
12
+ LINKING: "linking",
13
+ CONNECTED: "connected",
14
+ DISCONNECTED: "disconnected",
15
+ };
2
16
  /**
3
- * Open Lavatory Protocol - Decentralized Wallet Connection Library
17
+ * OpenLV Session
4
18
  *
5
- * A privacy-first, peer-to-peer protocol for connecting dApps with wallets
6
- * without relying on centralized infrastructure.
19
+ * https://openlv.sh/api/session
7
20
  */
8
- // biome-ignore lint/performance/noReExportAll: package entrypoint
9
- export * from "./base.js";
21
+ export const createSession = async (initParameters, signalLayer, transportLayer, onMessage) => {
22
+ const emitter = new EventEmitter();
23
+ const messages = new EventEmitter();
24
+ const sessionId = "sessionId" in initParameters
25
+ ? initParameters.sessionId
26
+ : generateSessionId();
27
+ const { encryptionKey, decryptionKey: { decrypt }, } = await initEncryptionKeys(initParameters);
28
+ let relyingPublicKey;
29
+ const handshakeKey = "k" in initParameters
30
+ ? await deriveSymmetricKey(initParameters.k)
31
+ : await generateHandshakeKey();
32
+ const { hash, isHost } = await initHash("h" in initParameters ? initParameters.h : undefined, encryptionKey);
33
+ let status = SESSION_STATE.CREATED;
34
+ const protocol = initParameters.p;
35
+ const server = initParameters.s;
36
+ const updateStatus = (newStatus) => {
37
+ log("updateStatus", newStatus);
38
+ status = newStatus;
39
+ emitter.emit("state_change", { status, signaling: signal.getState() });
40
+ };
41
+ const signaling = await signalLayer({
42
+ topic: sessionId,
43
+ url: server,
44
+ });
45
+ const signal = await signaling({
46
+ h: hash,
47
+ canEncrypt() {
48
+ return relyingPublicKey !== undefined;
49
+ },
50
+ async encrypt(message) {
51
+ if (!relyingPublicKey) {
52
+ throw new Error("Relying party public key not found");
53
+ }
54
+ log(`encrypting to ${relyingPublicKey.toString()}`, message);
55
+ return await relyingPublicKey.encrypt(message);
56
+ },
57
+ decrypt,
58
+ publicKey: encryptionKey,
59
+ k: handshakeKey,
60
+ async rpDiscovered(rpKey) {
61
+ const role = isHost ? "host" : "client";
62
+ log(`rpKey discovered by ${role}`, rpKey);
63
+ relyingPublicKey = await parseEncryptionKey(rpKey);
64
+ },
65
+ isHost,
66
+ });
67
+ const transport = transportLayer({
68
+ encrypt(message) {
69
+ if (!relyingPublicKey) {
70
+ throw new Error("Relying party public key not found");
71
+ }
72
+ return relyingPublicKey?.encrypt(message);
73
+ },
74
+ decrypt,
75
+ isHost,
76
+ onmessage: async (message) => {
77
+ log("Session: received message from transport", message);
78
+ if (message["type"] === "request") {
79
+ const messageId = message["messageId"];
80
+ // Immediately acknowledge receipt so the sender's ack-timeout does
81
+ // not fire while the handler (which may await user interaction) runs.
82
+ await transport.send({ type: "ack", messageId });
83
+ // Notify observers before processing (e.g. wallet UI can show a
84
+ // pending indicator before the handler resolves).
85
+ emitter.emit("request", message["payload"]);
86
+ const data = await onMessage(message["payload"]);
87
+ const response = {
88
+ type: "response",
89
+ messageId,
90
+ payload: data,
91
+ };
92
+ await transport.send(response);
93
+ }
94
+ if (message["type"] === "response" || message["type"] === "ack") {
95
+ // Both acks and responses are forwarded to the send() correlator.
96
+ messages.emit("message", message);
97
+ }
98
+ },
99
+ async subsend(message) {
100
+ log("Session: sending trans msg to signal", message);
101
+ const sessionMessage = {
102
+ type: "request",
103
+ messageId: crypto.randomUUID(),
104
+ payload: message,
105
+ };
106
+ await signal.send(sessionMessage);
107
+ },
108
+ });
109
+ transport.emitter.on("state_change", (state) => {
110
+ log("transport state change", state);
111
+ if (state === TRANSPORT_STATE.CONNECTED) {
112
+ updateStatus(SESSION_STATE.CONNECTED);
113
+ }
114
+ });
115
+ const startTransport = async () => {
116
+ await transport.setup();
117
+ };
118
+ // let transport: TransportLayer | undefined;
119
+ const onSignalMessage = async (message) => {
120
+ log("Session: received message from signaling", message);
121
+ const sessionMsg = message;
122
+ if (sessionMsg.type === "response") {
123
+ log("Session: received data message", sessionMsg.payload);
124
+ messages.emit("message", sessionMsg);
125
+ }
126
+ if (sessionMsg.type === "request") {
127
+ log("Session: received request message", sessionMsg.payload);
128
+ await transport.handle(sessionMsg.payload);
129
+ }
130
+ };
131
+ return {
132
+ connect: async () => {
133
+ updateStatus(SESSION_STATE.SIGNALING);
134
+ log("connecting to session, isHost:", isHost);
135
+ // TODO: implement
136
+ log("connecting to session");
137
+ signal.on("message", onSignalMessage);
138
+ signal.on("state_change", (state) => {
139
+ log("signal state change", state);
140
+ if (state === SIGNAL_STATE.READY) {
141
+ updateStatus(SESSION_STATE.READY);
142
+ }
143
+ if ([
144
+ SIGNAL_STATE.HANDSHAKE,
145
+ SIGNAL_STATE.HANDSHAKE_PARTIAL,
146
+ ].includes(state)) {
147
+ updateStatus(SESSION_STATE.LINKING);
148
+ }
149
+ if (state === SIGNAL_STATE.ENCRYPTED) {
150
+ startTransport();
151
+ }
152
+ if (state === SIGNAL_STATE.ERROR) {
153
+ log("signaling error — marking session disconnected");
154
+ updateStatus(SESSION_STATE.DISCONNECTED);
155
+ }
156
+ });
157
+ // TODO: handle errors in setup nicely in modal UI
158
+ await signal.setup();
159
+ },
160
+ async close() {
161
+ log("session teardown");
162
+ signal.off("message", onSignalMessage);
163
+ await Promise.all([
164
+ transport.teardown(),
165
+ signal.teardown(),
166
+ ]);
167
+ updateStatus(SESSION_STATE.DISCONNECTED);
168
+ },
169
+ getState() {
170
+ return {
171
+ status,
172
+ signaling: signal.getState(),
173
+ // transport: transport.getState(),
174
+ };
175
+ },
176
+ getHandshakeParameters() {
177
+ return {
178
+ version: OPENLV_PROTOCOL_VERSION,
179
+ sessionId,
180
+ h: hash,
181
+ k: handshakeKey.toString(),
182
+ p: protocol,
183
+ s: server,
184
+ };
185
+ },
186
+ waitForLink: async () => {
187
+ if (status === SESSION_STATE.CONNECTED)
188
+ return;
189
+ if (status === SESSION_STATE.DISCONNECTED) {
190
+ throw new Error("Session failed to connect");
191
+ }
192
+ return new Promise((resolve, reject) => {
193
+ const handler = (state) => {
194
+ if (state?.status === SESSION_STATE.CONNECTED) {
195
+ emitter.off("state_change", handler);
196
+ resolve();
197
+ }
198
+ else if (state?.status === SESSION_STATE.DISCONNECTED) {
199
+ emitter.off("state_change", handler);
200
+ reject(new Error("Session failed to connect"));
201
+ }
202
+ };
203
+ emitter.on("state_change", handler);
204
+ });
205
+ },
206
+ async send(message, ackTimeout = 10000, responseTimeout = 60 * 60000) {
207
+ if (signal.getState().state !== SIGNAL_STATE.ENCRYPTED) {
208
+ throw new Error("Session not ready");
209
+ }
210
+ const messageId = crypto.randomUUID();
211
+ const sessionMessage = {
212
+ type: "request",
213
+ messageId,
214
+ payload: message,
215
+ };
216
+ await transport.send(sessionMessage);
217
+ return new Promise((resolve, reject) => {
218
+ let ackReceived = false;
219
+ // eslint-disable-next-line prefer-const
220
+ let ackTimer;
221
+ let responseTimer;
222
+ const cleanup = () => {
223
+ clearTimeout(ackTimer);
224
+ clearTimeout(responseTimer);
225
+ messages.off("message", handler);
226
+ };
227
+ const handler = (msg) => {
228
+ if (msg.messageId !== messageId)
229
+ return;
230
+ if (msg.type === "ack" && !ackReceived) {
231
+ ackReceived = true;
232
+ clearTimeout(ackTimer);
233
+ // The other side confirmed receipt; wait for the full response.
234
+ responseTimer = setTimeout(() => {
235
+ cleanup();
236
+ reject(new Error("Request timed out: no response after acknowledgement"));
237
+ }, responseTimeout);
238
+ return;
239
+ }
240
+ if (msg.type === "response") {
241
+ cleanup();
242
+ resolve(msg.payload);
243
+ }
244
+ };
245
+ messages.on("message", handler);
246
+ // Short window for the ack — tells us the peer is alive and processing.
247
+ ackTimer = setTimeout(() => {
248
+ if (!ackReceived) {
249
+ cleanup();
250
+ reject(new Error("Request timed out: remote peer did not acknowledge"));
251
+ }
252
+ }, ackTimeout);
253
+ });
254
+ },
255
+ _internal: {
256
+ signal,
257
+ transport,
258
+ },
259
+ emitter,
260
+ };
261
+ };
262
+ /**
263
+ * Connect to a session from its openlv:// URL
264
+ */
265
+ export const connectSession = async (connectionUrl, onMessage, transport) => {
266
+ const initParameters = decodeConnectionURL(connectionUrl);
267
+ const signaling = await dynamicSignalingLayer(initParameters.p);
268
+ if (!signaling) {
269
+ throw new Error(`Invalid signaling protocol: ${initParameters.p}`);
270
+ }
271
+ return createSession(initParameters, signaling, transport, onMessage);
272
+ };
10
273
  //# 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,yEAAyE;AAEzE;;;;;GAKG;AAEH,kEAAkE;AAClE,cAAc,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n decodeConnectionURL,\n OPENLV_PROTOCOL_VERSION,\n type SessionHandshakeParameters,\n type SessionLinkParameters,\n} from \"@openlv/core\";\nimport {\n deriveSymmetricKey,\n type EncryptionKey,\n generateHandshakeKey,\n generateSessionId,\n initEncryptionKeys,\n initHash,\n parseEncryptionKey,\n} from \"@openlv/core/encryption\";\nimport {\n SIGNAL_STATE,\n type SignalingLayer,\n type SignalingProtocol,\n type SignalState,\n} from \"@openlv/signaling\";\nimport { dynamicSignalingLayer } from \"@openlv/signaling/dynamic\";\nimport {\n type TLayer,\n TRANSPORT_STATE,\n type TransportLayer,\n type TransportMessage,\n} from \"@openlv/transport\";\nimport { EventEmitter } from \"eventemitter3\";\n\nimport type { SessionEvents } from \"./events.js\";\nimport type { SessionMessage } from \"./messages/index.js\";\nimport { log } from \"./utils/log.js\";\n\nexport const SESSION_STATE = {\n CREATED: \"created\",\n SIGNALING: \"signaling\",\n READY: \"ready\",\n LINKING: \"linking\",\n CONNECTED: \"connected\",\n DISCONNECTED: \"disconnected\",\n} as const;\nexport type SessionState = (typeof SESSION_STATE)[keyof typeof SESSION_STATE];\n\nexport type SessionStateObject = {\n status: SessionState;\n signaling?: {\n state: SignalState;\n };\n};\n\n/**\n * an OpenLV Session\n *\n * https://openlv.sh/api/session\n */\nexport type Session = {\n getState(): SessionStateObject;\n getHandshakeParameters(): SessionHandshakeParameters;\n connect(): Promise<void>;\n waitForLink(): Promise<void>;\n close(): Promise<void>;\n /**\n * Send a request to the remote peer and await a correlated response.\n *\n * Two-phase timeout:\n * - `ackTimeout` (default 10 s): the remote peer must send back an ack\n * within this window, confirming it received the message.\n * - After an ack arrives the wait is extended to `responseTimeout`\n * (default 1 hour) — enough for user-interactive flows such as\n * `eth_sendTransaction` or `personal_sign`.\n */\n send(message: object, ackTimeout?: number, responseTimeout?: number): Promise<unknown>;\n emitter: EventEmitter<SessionEvents>;\n _internal: {\n signal: SignalingLayer;\n transport: TransportLayer;\n };\n};\n\n/**\n * OpenLV Session\n *\n * https://openlv.sh/api/session\n */\nexport const createSession = async (\n initParameters: SessionLinkParameters,\n signalLayer: SignalingProtocol,\n transportLayer: TLayer,\n onMessage: (message: object) => Promise<object | string>,\n): Promise<Session> => {\n const emitter = new EventEmitter<SessionEvents>();\n const messages = new EventEmitter<{ message: SessionMessage; }>();\n const sessionId\n = \"sessionId\" in initParameters\n ? initParameters.sessionId\n : generateSessionId();\n const {\n encryptionKey,\n decryptionKey: { decrypt },\n } = await initEncryptionKeys(initParameters);\n let relyingPublicKey: EncryptionKey | undefined;\n const handshakeKey\n = \"k\" in initParameters\n ? await deriveSymmetricKey(initParameters.k)\n : await generateHandshakeKey();\n const { hash, isHost } = await initHash(\n \"h\" in initParameters ? initParameters.h : undefined,\n encryptionKey,\n );\n let status: SessionState = SESSION_STATE.CREATED;\n const protocol = initParameters.p;\n const server = initParameters.s;\n\n const updateStatus = (newStatus: SessionState) => {\n log(\"updateStatus\", newStatus);\n status = newStatus;\n emitter.emit(\"state_change\", { status, signaling: signal.getState() });\n };\n\n const signaling = await signalLayer({\n topic: sessionId,\n url: server,\n });\n const signal = await signaling({\n h: hash,\n canEncrypt() {\n return relyingPublicKey !== undefined;\n },\n async encrypt(message) {\n if (!relyingPublicKey) {\n throw new Error(\"Relying party public key not found\");\n }\n\n log(`encrypting to ${relyingPublicKey.toString()}`, message);\n\n return await relyingPublicKey.encrypt(message);\n },\n decrypt,\n publicKey: encryptionKey,\n k: handshakeKey,\n async rpDiscovered(rpKey) {\n const role = isHost ? \"host\" : \"client\";\n\n log(`rpKey discovered by ${role}`, rpKey);\n\n relyingPublicKey = await parseEncryptionKey(rpKey);\n },\n isHost,\n });\n\n const transport = transportLayer({\n encrypt(message) {\n if (!relyingPublicKey) {\n throw new Error(\"Relying party public key not found\");\n }\n\n return relyingPublicKey?.encrypt(message);\n },\n decrypt,\n isHost,\n onmessage: async (message: { type: string; payload: object; messageId: string; }) => {\n log(\"Session: received message from transport\", message);\n\n if (message[\"type\"] === \"request\") {\n const messageId = message[\"messageId\"] as string;\n\n // Immediately acknowledge receipt so the sender's ack-timeout does\n // not fire while the handler (which may await user interaction) runs.\n await transport.send({ type: \"ack\", messageId } satisfies SessionMessage);\n\n // Notify observers before processing (e.g. wallet UI can show a\n // pending indicator before the handler resolves).\n emitter.emit(\"request\", message[\"payload\"] as object);\n\n const data = await onMessage(message[\"payload\"] as object);\n const response: SessionMessage = {\n type: \"response\",\n messageId,\n payload: data,\n };\n\n await transport.send(response);\n }\n\n if (message[\"type\"] === \"response\" || message[\"type\"] === \"ack\") {\n // Both acks and responses are forwarded to the send() correlator.\n messages.emit(\"message\", message as SessionMessage);\n }\n },\n async subsend(message) {\n log(\"Session: sending trans msg to signal\", message);\n const sessionMessage: SessionMessage = {\n type: \"request\",\n messageId: crypto.randomUUID(),\n payload: message,\n };\n\n await signal.send(sessionMessage);\n },\n });\n\n transport.emitter.on(\"state_change\", (state) => {\n log(\"transport state change\", state);\n\n if (state === TRANSPORT_STATE.CONNECTED) {\n updateStatus(SESSION_STATE.CONNECTED);\n }\n });\n\n const startTransport = async () => {\n await transport.setup();\n };\n\n // let transport: TransportLayer | undefined;\n const onSignalMessage = async (message: object) => {\n log(\"Session: received message from signaling\", message);\n\n const sessionMsg = message as SessionMessage;\n\n if (sessionMsg.type === \"response\") {\n log(\"Session: received data message\", sessionMsg.payload);\n messages.emit(\"message\", sessionMsg);\n }\n\n if (sessionMsg.type === \"request\") {\n log(\"Session: received request message\", sessionMsg.payload);\n\n await transport.handle(sessionMsg.payload as TransportMessage);\n }\n };\n\n return {\n connect: async () => {\n updateStatus(SESSION_STATE.SIGNALING);\n log(\"connecting to session, isHost:\", isHost);\n // TODO: implement\n log(\"connecting to session\");\n\n signal.on(\"message\", onSignalMessage);\n\n signal.on(\"state_change\", (state) => {\n log(\"signal state change\", state);\n\n if (state === SIGNAL_STATE.READY) {\n updateStatus(SESSION_STATE.READY);\n }\n\n if (\n (\n [\n SIGNAL_STATE.HANDSHAKE,\n SIGNAL_STATE.HANDSHAKE_PARTIAL,\n ] as SignalState[]\n ).includes(state)\n ) {\n updateStatus(SESSION_STATE.LINKING);\n }\n\n if (state === SIGNAL_STATE.ENCRYPTED) {\n startTransport();\n }\n\n if (state === SIGNAL_STATE.ERROR) {\n log(\"signaling error — marking session disconnected\");\n updateStatus(SESSION_STATE.DISCONNECTED);\n }\n });\n\n // TODO: handle errors in setup nicely in modal UI\n await signal.setup();\n },\n async close() {\n log(\"session teardown\");\n signal.off(\"message\", onSignalMessage);\n await Promise.all([\n transport.teardown(),\n signal.teardown(),\n ]);\n updateStatus(SESSION_STATE.DISCONNECTED);\n },\n getState() {\n return {\n status,\n signaling: signal.getState(),\n // transport: transport.getState(),\n };\n },\n getHandshakeParameters() {\n return {\n version: OPENLV_PROTOCOL_VERSION,\n sessionId,\n h: hash,\n k: handshakeKey.toString(),\n p: protocol,\n s: server,\n };\n },\n waitForLink: async () => {\n if (status === SESSION_STATE.CONNECTED) return;\n\n if (status === SESSION_STATE.DISCONNECTED) {\n throw new Error(\"Session failed to connect\");\n }\n\n return new Promise<void>((resolve, reject) => {\n const handler = (state?: SessionStateObject) => {\n if (state?.status === SESSION_STATE.CONNECTED) {\n emitter.off(\"state_change\", handler);\n resolve();\n }\n else if (state?.status === SESSION_STATE.DISCONNECTED) {\n emitter.off(\"state_change\", handler);\n reject(new Error(\"Session failed to connect\"));\n }\n };\n\n emitter.on(\"state_change\", handler);\n });\n },\n async send(\n message: object,\n ackTimeout: number = 10_000,\n responseTimeout: number = 60 * 60_000,\n ) {\n if (signal.getState().state !== SIGNAL_STATE.ENCRYPTED) {\n throw new Error(\"Session not ready\");\n }\n\n const messageId = crypto.randomUUID();\n const sessionMessage: SessionMessage = {\n type: \"request\",\n messageId,\n payload: message,\n };\n\n await transport.send(sessionMessage);\n\n return new Promise<unknown>((resolve, reject) => {\n let ackReceived = false;\n // eslint-disable-next-line prefer-const\n let ackTimer: ReturnType<typeof setTimeout> | undefined;\n let responseTimer: ReturnType<typeof setTimeout> | undefined;\n\n const cleanup = () => {\n clearTimeout(ackTimer);\n clearTimeout(responseTimer);\n messages.off(\"message\", handler);\n };\n\n const handler = (msg: SessionMessage) => {\n if (msg.messageId !== messageId) return;\n\n if (msg.type === \"ack\" && !ackReceived) {\n ackReceived = true;\n clearTimeout(ackTimer);\n // The other side confirmed receipt; wait for the full response.\n responseTimer = setTimeout(() => {\n cleanup();\n reject(new Error(\"Request timed out: no response after acknowledgement\"));\n }, responseTimeout);\n\n return;\n }\n\n if (msg.type === \"response\") {\n cleanup();\n resolve(msg.payload);\n }\n };\n\n messages.on(\"message\", handler);\n\n // Short window for the ack — tells us the peer is alive and processing.\n ackTimer = setTimeout(() => {\n if (!ackReceived) {\n cleanup();\n reject(new Error(\"Request timed out: remote peer did not acknowledge\"));\n }\n }, ackTimeout);\n });\n },\n _internal: {\n signal,\n transport,\n },\n emitter,\n };\n};\n\n/**\n * Connect to a session from its openlv:// URL\n */\nexport const connectSession = async (\n connectionUrl: string,\n onMessage: (message: object) => Promise<object | string>,\n transport: TLayer,\n): Promise<Session> => {\n const initParameters = decodeConnectionURL(connectionUrl);\n\n const signaling = await dynamicSignalingLayer(initParameters.p);\n\n if (!signaling) {\n throw new Error(`Invalid signaling protocol: ${initParameters.p}`);\n }\n\n return createSession(initParameters, signaling, transport, onMessage);\n};\n"]}
@@ -1,14 +1,15 @@
1
1
  import { decodeConnectionURL, encodeConnectionURL } from "@openlv/core";
2
2
  import { ntfy } from "@openlv/signaling/ntfy";
3
+ import { webrtc } from "@openlv/transport/webrtc";
3
4
  import { describe, expect, test } from "vitest";
4
- import { connectSession, createSession } from "./base.js";
5
+ import { connectSession, createSession } from "./index.js";
5
6
  describe("Session", () => {
6
7
  test("Should be able to create a session", async () => {
7
8
  const sessionA = await createSession({
8
9
  sessionId: "mytestsession111",
9
10
  p: "ntfy",
10
11
  s: "https://ntfy.sh/",
11
- }, ntfy, async (message) => {
12
+ }, ntfy, webrtc(), async (message) => {
12
13
  console.log("sessionA received message", message);
13
14
  return { result: "success" };
14
15
  });
@@ -21,12 +22,12 @@ describe("Session", () => {
21
22
  const decodedUrl = decodeConnectionURL(encodedUrl);
22
23
  expect(decodedUrl).toEqual(handshakeParametersA);
23
24
  //
24
- await new Promise((resolve) => setTimeout(resolve, 1000));
25
+ await new Promise(resolve => setTimeout(resolve, 1000));
25
26
  console.log("Connecting to session B");
26
27
  const sessionB = await connectSession(encodedUrl, async (message) => {
27
28
  console.log("sessionB received message", message);
28
29
  return { result: "success" };
29
- });
30
+ }, webrtc());
30
31
  console.log(sessionB.getState());
31
32
  await sessionB.connect();
32
33
  await Promise.all([sessionA.waitForLink(), sessionB.waitForLink()]);
@@ -1 +1 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1D,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,IAAI,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAClC;YACE,SAAS,EAAE,kBAAkB;YAC7B,CAAC,EAAE,MAAM;YACT,CAAC,EAAE,kBAAkB;SACtB,EACD,IAAI,EACJ,KAAK,EAAE,OAAO,EAAE,EAAE;YAChB,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;YAElD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC/B,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEjC,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;QAEzB,MAAM,oBAAoB,GAAG,QAAQ,CAAC,sBAAsB,EAAE,CAAC;QAC/D,MAAM,UAAU,GAAG,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;QAE7D,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAExB,MAAM,UAAU,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAEnD,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAEjD,EAAE;QACF,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAE1D,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QAEvC,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YAClE,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;YAElD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjC,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;QAEzB,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAEpE,EAAE;QACF,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEtC,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAEvD,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAElC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3D,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,IAAI,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QACpD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAClC;YACE,SAAS,EAAE,kBAAkB;YAC7B,CAAC,EAAE,MAAM;YACT,CAAC,EAAE,kBAAkB;SACtB,EACD,IAAI,EACJ,MAAM,EAAE,EACR,KAAK,EAAE,OAAO,EAAE,EAAE;YAChB,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;YAElD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC/B,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEjC,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;QAEzB,MAAM,oBAAoB,GAAG,QAAQ,CAAC,sBAAsB,EAAE,CAAC;QAC/D,MAAM,UAAU,GAAG,mBAAmB,CAAC,oBAAoB,CAAC,CAAC;QAE7D,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAExB,MAAM,UAAU,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;QAEnD,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAEjD,EAAE;QACF,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAExD,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QAEvC,MAAM,QAAQ,GAAG,MAAM,cAAc,CACnC,UAAU,EACV,KAAK,EAAE,OAAO,EAAE,EAAE;YAChB,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;YAElD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC/B,CAAC,EACD,MAAM,EAAE,CACT,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjC,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;QAEzB,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAEpE,EAAE;QACF,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEtC,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAEvD,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAElC,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { decodeConnectionURL, encodeConnectionURL } from \"@openlv/core\";\nimport { ntfy } from \"@openlv/signaling/ntfy\";\nimport { webrtc } from \"@openlv/transport/webrtc\";\nimport { describe, expect, test } from \"vitest\";\n\nimport { connectSession, createSession } from \"./index.js\";\n\ndescribe(\"Session\", () => {\n test(\"Should be able to create a session\", async () => {\n const sessionA = await createSession(\n {\n sessionId: \"mytestsession111\",\n p: \"ntfy\",\n s: \"https://ntfy.sh/\",\n },\n ntfy,\n webrtc(),\n async (message) => {\n console.log(\"sessionA received message\", message);\n\n return { result: \"success\" };\n },\n );\n\n expect(sessionA).toBeDefined();\n console.log(sessionA.getState());\n\n await sessionA.connect();\n\n const handshakeParametersA = sessionA.getHandshakeParameters();\n const encodedUrl = encodeConnectionURL(handshakeParametersA);\n\n console.log(encodedUrl);\n\n const decodedUrl = decodeConnectionURL(encodedUrl);\n\n expect(decodedUrl).toEqual(handshakeParametersA);\n\n //\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n console.log(\"Connecting to session B\");\n\n const sessionB = await connectSession(\n encodedUrl,\n async (message) => {\n console.log(\"sessionB received message\", message);\n\n return { result: \"success\" };\n },\n webrtc(),\n );\n\n console.log(sessionB.getState());\n await sessionB.connect();\n\n await Promise.all([sessionA.waitForLink(), sessionB.waitForLink()]);\n\n //\n console.log(\"A\", sessionA.getState());\n console.log(\"B\", sessionB.getState());\n\n const response = await sessionA.send({ data: \"test\" });\n\n console.log(\"response\", response);\n\n expect(response).toEqual({ result: \"success\" });\n });\n});\n"]}
@@ -1,4 +1,4 @@
1
- export type SessionMessage = SessionMessageRequest | SessionMessageResponse;
1
+ export type SessionMessage = SessionMessageRequest | SessionMessageResponse | SessionMessageAck;
2
2
  export type SessionMessageRequest = {
3
3
  type: "request";
4
4
  messageId: string;
@@ -9,3 +9,7 @@ export type SessionMessageResponse = {
9
9
  messageId: string;
10
10
  payload: object | string;
11
11
  };
12
+ export type SessionMessageAck = {
13
+ type: "ack";
14
+ messageId: string;
15
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/messages/index.ts"],"names":[],"mappings":"","sourcesContent":["export type SessionMessage =\n | SessionMessageRequest\n | SessionMessageResponse\n | SessionMessageAck;\n\nexport type SessionMessageRequest = {\n type: \"request\";\n messageId: string;\n payload: object | string;\n};\n\nexport type SessionMessageResponse = {\n type: \"response\";\n messageId: string;\n payload: object | string;\n};\n\nexport type SessionMessageAck = {\n type: \"ack\";\n messageId: string;\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/utils/log.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,CAAiC,EAAE,EAAE,CAC1D,OAAO,CAAC,GAAG,CACT,WAAW;AACX,sCAAsC;AACtC,yCAAyC;AACzC,GAAG,CAAC,CACL,CAAC"}
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/utils/log.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,GAAG,CAAiC,EAAE,EAAE,CAC1D,OAAO,CAAC,GAAG,CACT,WAAW;AACX,sCAAsC;AACtC,yCAAyC;AACzC,GAAG,CAAC,CACL,CAAC","sourcesContent":["export const log = (...x: Parameters<typeof console.log>) =>\n console.log(\n \"[session]\",\n // \"color: orange; font-weight: bold\",\n // \"color: inherit; font-weight: normal\",\n ...x,\n );\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openlv/session",
3
- "version": "0.0.1-beta.9",
3
+ "version": "0.0.2",
4
4
  "keywords": [
5
5
  "open-lavatory"
6
6
  ],
@@ -25,11 +25,6 @@
25
25
  "types": "./dist/index.d.ts",
26
26
  "import": "./dist/index.js",
27
27
  "default": "./dist/index.js"
28
- },
29
- "./provider": {
30
- "types": "./dist/provider.d.ts",
31
- "import": "./dist/provider.js",
32
- "default": "./dist/provider.js"
33
28
  }
34
29
  },
35
30
  "main": "./dist/index.js",
@@ -42,13 +37,13 @@
42
37
  "eventemitter3": "^5.0.1",
43
38
  "globals": "^16.2.0",
44
39
  "ts-pattern": "^5",
45
- "@openlv/core": "0.0.1-beta.8",
46
- "@openlv/signaling": "0.0.1-beta.7",
47
- "@openlv/transport": "0.0.1-beta.6"
40
+ "@openlv/signaling": "0.0.2",
41
+ "@openlv/transport": "0.0.2",
42
+ "@openlv/core": "0.0.1"
48
43
  },
49
44
  "devDependencies": {
50
45
  "@vitest/browser-playwright": "^4.0.8",
51
- "playwright": "^1.56.1",
46
+ "playwright": "1.58.1",
52
47
  "typescript": "^5",
53
48
  "vitest": "^4"
54
49
  },
@@ -63,7 +58,6 @@
63
58
  },
64
59
  "scripts": {
65
60
  "build": "tsc",
66
- "test": "vitest",
67
- "test:install": "playwright install --with-deps"
61
+ "test": "vitest"
68
62
  }
69
63
  }
package/dist/base.d.ts DELETED
@@ -1,48 +0,0 @@
1
- import { type SessionHandshakeParameters, type SessionLinkParameters } from "@openlv/core";
2
- import { type CreateSignalLayerFn, type SignalingLayer, type SignalState } from "@openlv/signaling";
3
- import { type TransportLayer } from "@openlv/transport";
4
- import { EventEmitter } from "eventemitter3";
5
- import type { SessionEvents } from "./events.js";
6
- export declare const SESSION_STATE: {
7
- readonly CREATED: "created";
8
- readonly SIGNALING: "signaling";
9
- readonly READY: "ready";
10
- readonly LINKING: "linking";
11
- readonly CONNECTED: "connected";
12
- readonly DISCONNECTED: "disconnected";
13
- };
14
- export type SessionState = (typeof SESSION_STATE)[keyof typeof SESSION_STATE];
15
- export type SessionStateObject = {
16
- status: SessionState;
17
- signaling?: {
18
- state: SignalState;
19
- };
20
- };
21
- /**
22
- * an OpenLV Session
23
- *
24
- * https://openlv.sh/api/session
25
- */
26
- export type Session = {
27
- getState(): SessionStateObject;
28
- getHandshakeParameters(): SessionHandshakeParameters;
29
- connect(): Promise<void>;
30
- waitForLink(): Promise<void>;
31
- close(): Promise<void>;
32
- send(message: object, timeout?: number): Promise<unknown>;
33
- emitter: EventEmitter<SessionEvents>;
34
- _internal: {
35
- signal: SignalingLayer;
36
- transport: TransportLayer;
37
- };
38
- };
39
- /**
40
- * OpenLV Session
41
- *
42
- * https://openlv.sh/api/session
43
- */
44
- export declare const createSession: (initParameters: SessionLinkParameters, signalLayer: CreateSignalLayerFn, onMessage: (message: object) => Promise<object | string>) => Promise<Session>;
45
- /**
46
- * Connect to a session from its openlv:// URL
47
- */
48
- export declare const connectSession: (connectionUrl: string, onMessage: (message: object) => Promise<object | string>) => Promise<Session>;
package/dist/base.js DELETED
@@ -1,234 +0,0 @@
1
- import { decodeConnectionURL, OPENLV_PROTOCOL_VERSION, } from "@openlv/core";
2
- import { deriveSymmetricKey, generateHandshakeKey, generateSessionId, initEncryptionKeys, initHash, parseEncryptionKey, } from "@openlv/core/encryption";
3
- import { SIGNAL_STATE, } from "@openlv/signaling";
4
- import { dynamicSignalingLayer } from "@openlv/signaling/dynamic";
5
- import { TRANSPORT_STATE, } from "@openlv/transport";
6
- import { webrtc } from "@openlv/transport/webrtc";
7
- import { EventEmitter } from "eventemitter3";
8
- import { log } from "./utils/log.js";
9
- export const SESSION_STATE = {
10
- CREATED: "created",
11
- SIGNALING: "signaling",
12
- READY: "ready",
13
- LINKING: "linking",
14
- CONNECTED: "connected",
15
- DISCONNECTED: "disconnected",
16
- };
17
- /**
18
- * OpenLV Session
19
- *
20
- * https://openlv.sh/api/session
21
- */
22
- export const createSession = async (initParameters, signalLayer, onMessage) => {
23
- const emitter = new EventEmitter();
24
- const messages = new EventEmitter();
25
- const sessionId = "sessionId" in initParameters
26
- ? initParameters.sessionId
27
- : generateSessionId();
28
- const { encryptionKey, decryptionKey: { decrypt }, } = await initEncryptionKeys(initParameters);
29
- let relyingPublicKey;
30
- const handshakeKey = "k" in initParameters
31
- ? await deriveSymmetricKey(initParameters.k)
32
- : await generateHandshakeKey();
33
- const { hash, isHost } = await initHash("h" in initParameters ? initParameters.h : undefined, encryptionKey);
34
- let status = SESSION_STATE.CREATED;
35
- const protocol = initParameters.p;
36
- const server = initParameters.s;
37
- const updateStatus = (newStatus) => {
38
- log("updateStatus", newStatus);
39
- status = newStatus;
40
- emitter.emit("state_change", { status, signaling: signal.getState() });
41
- };
42
- const signaling = await signalLayer({
43
- topic: sessionId,
44
- url: server,
45
- });
46
- const signal = await signaling({
47
- h: hash,
48
- canEncrypt() {
49
- return relyingPublicKey !== undefined;
50
- },
51
- async encrypt(message) {
52
- if (!relyingPublicKey) {
53
- throw new Error("Relying party public key not found");
54
- }
55
- log(`encrypting to ${relyingPublicKey.toString()}`, message);
56
- return await relyingPublicKey.encrypt(message);
57
- },
58
- decrypt,
59
- publicKey: encryptionKey,
60
- k: handshakeKey,
61
- async rpDiscovered(rpKey) {
62
- const role = isHost ? "host" : "client";
63
- log(`rpKey discovered by ${role}`, rpKey);
64
- relyingPublicKey = await parseEncryptionKey(rpKey);
65
- },
66
- isHost,
67
- });
68
- const transport = webrtc({ isHost })({
69
- encrypt(message) {
70
- if (!relyingPublicKey) {
71
- throw new Error("Relying party public key not found");
72
- }
73
- return relyingPublicKey?.encrypt(message);
74
- },
75
- decrypt,
76
- isHost,
77
- onmessage: async (message) => {
78
- console.log("Session: received message from transport", message);
79
- // @ts-ignore
80
- if (message["type"] === "request") {
81
- // @ts-ignore
82
- const data = await onMessage(message["payload"]);
83
- const response = {
84
- type: "response",
85
- // @ts-ignore
86
- messageId: message["messageId"],
87
- payload: data,
88
- };
89
- await transport.send(response);
90
- }
91
- // @ts-ignore
92
- if (message["type"] === "response") {
93
- messages.emit("message", message);
94
- }
95
- },
96
- async subsend(message) {
97
- console.log("Session: sending trans msg to signal", message);
98
- const sessionMessage = {
99
- type: "request",
100
- messageId: crypto.randomUUID(),
101
- payload: message,
102
- };
103
- await signal.send(sessionMessage);
104
- },
105
- });
106
- transport.emitter.on("state_change", (state) => {
107
- log("transport state change", state);
108
- if (state === TRANSPORT_STATE.CONNECTED) {
109
- updateStatus(SESSION_STATE.CONNECTED);
110
- }
111
- });
112
- const startTransport = async () => {
113
- await transport.setup();
114
- };
115
- // let transport: TransportLayer | undefined;
116
- const onSignalMessage = async (message) => {
117
- log("Session: received message from signaling", message);
118
- const sessionMsg = message;
119
- if (sessionMsg.type === "response") {
120
- log("Session: received data message", sessionMsg.payload);
121
- messages.emit("message", sessionMsg);
122
- }
123
- if (sessionMsg.type === "request") {
124
- log("Session: received request message", sessionMsg.payload);
125
- transport.handle(sessionMsg.payload);
126
- }
127
- };
128
- return {
129
- connect: async () => {
130
- updateStatus(SESSION_STATE.SIGNALING);
131
- log("connecting to session, isHost:", isHost);
132
- // TODO: implement
133
- log("connecting to session");
134
- signal.on("message", onSignalMessage);
135
- signal.on("state_change", (state) => {
136
- log("signal state change", state);
137
- if (state === SIGNAL_STATE.READY) {
138
- updateStatus(SESSION_STATE.READY);
139
- }
140
- if ([
141
- SIGNAL_STATE.HANDSHAKE,
142
- SIGNAL_STATE.HANDSHAKE_PARTIAL,
143
- ].includes(state)) {
144
- updateStatus(SESSION_STATE.LINKING);
145
- }
146
- if (state === SIGNAL_STATE.ENCRYPTED) {
147
- // for now cuz we just use signaling call this a full connection
148
- // updateStatus("connected");
149
- startTransport();
150
- }
151
- });
152
- // TODO: handle errors in setup nicely in modal UI
153
- await signal.setup();
154
- },
155
- async close() {
156
- log("session teardown");
157
- await signal?.teardown();
158
- updateStatus(SESSION_STATE.DISCONNECTED);
159
- },
160
- getState() {
161
- return {
162
- status,
163
- signaling: signal.getState(),
164
- // transport: transport.getState(),
165
- };
166
- },
167
- getHandshakeParameters() {
168
- return {
169
- version: OPENLV_PROTOCOL_VERSION,
170
- sessionId,
171
- h: hash,
172
- k: handshakeKey.toString(),
173
- p: protocol,
174
- s: server,
175
- };
176
- },
177
- waitForLink: async () => {
178
- return new Promise((resolve) => {
179
- emitter.on("state_change", (state) => {
180
- if (state?.status === SESSION_STATE.CONNECTED) {
181
- resolve();
182
- }
183
- });
184
- });
185
- },
186
- async send(message, timeout = 5000) {
187
- const ready = signal.getState().state === SIGNAL_STATE.ENCRYPTED;
188
- // const transportReady = transport.getState() === TRANSPORT_STATE.CONNECTED;
189
- if (!ready) {
190
- throw new Error("Session not ready");
191
- }
192
- const randomID = crypto.randomUUID();
193
- const sessionMessage = {
194
- type: "request",
195
- messageId: randomID,
196
- payload: message,
197
- };
198
- // for now use signaling
199
- // await signal.send(sessionMessage);
200
- await transport.send(sessionMessage);
201
- return Promise.race([
202
- new Promise((resolve) => {
203
- messages.on("message", (message) => {
204
- if (message.messageId === randomID && message.type === "response") {
205
- resolve(message.payload);
206
- }
207
- });
208
- }),
209
- new Promise((resolve) => {
210
- setTimeout(() => {
211
- resolve(new Error("Timeout"));
212
- }, timeout);
213
- }),
214
- ]);
215
- },
216
- _internal: {
217
- signal,
218
- transport,
219
- },
220
- emitter,
221
- };
222
- };
223
- /**
224
- * Connect to a session from its openlv:// URL
225
- */
226
- export const connectSession = async (connectionUrl, onMessage) => {
227
- const initParameters = decodeConnectionURL(connectionUrl);
228
- const signaling = await dynamicSignalingLayer(initParameters.p);
229
- if (!signaling) {
230
- throw new Error(`Invalid signaling protocol: ${initParameters.p}`);
231
- }
232
- return createSession(initParameters, signaling, onMessage);
233
- };
234
- //# 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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"}