@openlv/transport 0.2.0 → 0.3.0

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/base.test.js CHANGED
@@ -1,4 +1,4 @@
1
- import { generateKeyPair } from "@openlv/core/encryption";
1
+ import { createPeerCipher, generateKeyPair } from "@openlv/core/encryption";
2
2
  import { describe, expect, it } from "vitest";
3
3
  import { createTransportBase, Status, } from "./index.js";
4
4
  const createFakeTransport = () => {
@@ -31,12 +31,12 @@ describe("createTransportBase", () => {
31
31
  expect(factory.transportId).toBe("fake");
32
32
  });
33
33
  it("relays negotiate events through subsend", async () => {
34
- const { encryptionKey, decryptionKey } = await generateKeyPair();
34
+ const keyPair = generateKeyPair();
35
+ const cipher = await createPeerCipher(keyPair, keyPair.publicKey);
35
36
  const { factory, getEmitter } = createFakeTransport();
36
37
  const relayed = [];
37
38
  const layer = factory.create({
38
- encrypt: encryptionKey.encrypt,
39
- decrypt: decryptionKey.decrypt,
39
+ cipher,
40
40
  isHost: true,
41
41
  onmessage: () => { },
42
42
  subsend: async (message) => {
@@ -54,12 +54,12 @@ describe("createTransportBase", () => {
54
54
  ]);
55
55
  });
56
56
  it("encrypts outgoing messages and decrypts incoming ones", async () => {
57
- const { encryptionKey, decryptionKey } = await generateKeyPair();
57
+ const keyPair = generateKeyPair();
58
+ const cipher = await createPeerCipher(keyPair, keyPair.publicKey);
58
59
  const { factory, sent, getEmitter } = createFakeTransport();
59
60
  const received = [];
60
61
  const layer = factory.create({
61
- encrypt: encryptionKey.encrypt,
62
- decrypt: decryptionKey.decrypt,
62
+ cipher,
63
63
  isHost: true,
64
64
  onmessage: (message) => {
65
65
  received.push(message);
@@ -78,11 +78,11 @@ describe("createTransportBase", () => {
78
78
  expect(received).toEqual([{ type: "request", messageId: "1", payload: { a: 1 } }]);
79
79
  });
80
80
  it("rejects sends before the transport is connected", async () => {
81
- const { encryptionKey, decryptionKey } = await generateKeyPair();
81
+ const keyPair = generateKeyPair();
82
+ const cipher = await createPeerCipher(keyPair, keyPair.publicKey);
82
83
  const { factory } = createFakeTransport();
83
84
  const layer = factory.create({
84
- encrypt: encryptionKey.encrypt,
85
- decrypt: decryptionKey.decrypt,
85
+ cipher,
86
86
  isHost: true,
87
87
  onmessage: () => { },
88
88
  subsend: async () => { },
@@ -1 +1 @@
1
- {"version":3,"file":"base.test.js","sourceRoot":"","sources":["../src/base.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { generateKeyPair } from \"@openlv/core/encryption\";\nimport { describe, expect, it } from \"vitest\";\n\nimport {\n createTransportBase,\n Status,\n type TransportMessage,\n} from \"./index.js\";\nimport type { TransportLayerBaseEmitter } from \"./layer.js\";\n\nconst createFakeTransport = () => {\n let emitter: TransportLayerBaseEmitter | undefined;\n const sent: string[] = [];\n\n const factory = createTransportBase(\"fake\", (parameters) => {\n emitter = parameters.emitter;\n\n return {\n setup: async () => {},\n teardown: async () => {},\n handle: async () => {},\n send: async (message) => {\n sent.push(message);\n },\n };\n });\n\n return {\n factory,\n sent,\n getEmitter: (): TransportLayerBaseEmitter => {\n if (!emitter) throw new Error(\"transport not created\");\n\n return emitter;\n },\n };\n};\n\ndescribe(\"createTransportBase\", () => {\n it(\"exposes the wire id on the factory and instance\", () => {\n const { factory } = createFakeTransport();\n\n expect(factory.transportId).toBe(\"fake\");\n });\n\n it(\"relays negotiate events through subsend\", async () => {\n const { encryptionKey, decryptionKey } = await generateKeyPair();\n const { factory, getEmitter } = createFakeTransport();\n const relayed: TransportMessage[] = [];\n\n const layer = factory.create({\n encrypt: encryptionKey.encrypt,\n decrypt: decryptionKey.decrypt,\n isHost: true,\n onmessage: () => {},\n subsend: async (message) => {\n relayed.push(message);\n },\n });\n\n expect(layer.type).toBe(\"fake\");\n await layer.setup();\n\n getEmitter().emit(\"negotiate\", { type: \"offer\", payload: \"sdp\" });\n getEmitter().emit(\"negotiate\", { type: \"candidate\", payload: \"cand\" });\n await Promise.resolve();\n\n expect(relayed).toEqual([\n { type: \"offer\", payload: \"sdp\" },\n { type: \"candidate\", payload: \"cand\" },\n ]);\n });\n\n it(\"encrypts outgoing messages and decrypts incoming ones\", async () => {\n const { encryptionKey, decryptionKey } = await generateKeyPair();\n const { factory, sent, getEmitter } = createFakeTransport();\n const received: object[] = [];\n\n const layer = factory.create({\n encrypt: encryptionKey.encrypt,\n decrypt: decryptionKey.decrypt,\n isHost: true,\n onmessage: (message) => {\n received.push(message);\n },\n subsend: async () => {},\n });\n\n await layer.setup();\n getEmitter().emit(\"connected\");\n expect(layer.status.get()).toBe(Status.CONNECTED);\n\n await layer.send({ type: \"request\", messageId: \"1\", payload: { a: 1 } });\n expect(sent).toHaveLength(1);\n // Ciphertext on the wire, not the plaintext envelope.\n expect(sent[0]).not.toContain(\"messageId\");\n\n getEmitter().emit(\"message\", sent[0]);\n await new Promise(resolve => setTimeout(resolve, 10));\n expect(received).toEqual([{ type: \"request\", messageId: \"1\", payload: { a: 1 } }]);\n });\n\n it(\"rejects sends before the transport is connected\", async () => {\n const { encryptionKey, decryptionKey } = await generateKeyPair();\n const { factory } = createFakeTransport();\n\n const layer = factory.create({\n encrypt: encryptionKey.encrypt,\n decrypt: decryptionKey.decrypt,\n isHost: true,\n onmessage: () => {},\n subsend: async () => {},\n });\n\n await layer.setup();\n await expect(layer.send({ a: 1 })).rejects.toThrow(\"Transport not connected\");\n });\n});\n"]}
1
+ {"version":3,"file":"base.test.js","sourceRoot":"","sources":["../src/base.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { createPeerCipher, generateKeyPair } from \"@openlv/core/encryption\";\nimport { describe, expect, it } from \"vitest\";\n\nimport {\n createTransportBase,\n Status,\n type TransportMessage,\n} from \"./index.js\";\nimport type { TransportLayerBaseEmitter } from \"./layer.js\";\n\nconst createFakeTransport = () => {\n let emitter: TransportLayerBaseEmitter | undefined;\n const sent: string[] = [];\n\n const factory = createTransportBase(\"fake\", (parameters) => {\n emitter = parameters.emitter;\n\n return {\n setup: async () => {},\n teardown: async () => {},\n handle: async () => {},\n send: async (message) => {\n sent.push(message);\n },\n };\n });\n\n return {\n factory,\n sent,\n getEmitter: (): TransportLayerBaseEmitter => {\n if (!emitter) throw new Error(\"transport not created\");\n\n return emitter;\n },\n };\n};\n\ndescribe(\"createTransportBase\", () => {\n it(\"exposes the wire id on the factory and instance\", () => {\n const { factory } = createFakeTransport();\n\n expect(factory.transportId).toBe(\"fake\");\n });\n\n it(\"relays negotiate events through subsend\", async () => {\n const keyPair = generateKeyPair();\n const cipher = await createPeerCipher(keyPair, keyPair.publicKey);\n const { factory, getEmitter } = createFakeTransport();\n const relayed: TransportMessage[] = [];\n\n const layer = factory.create({\n cipher,\n isHost: true,\n onmessage: () => {},\n subsend: async (message) => {\n relayed.push(message);\n },\n });\n\n expect(layer.type).toBe(\"fake\");\n await layer.setup();\n\n getEmitter().emit(\"negotiate\", { type: \"offer\", payload: \"sdp\" });\n getEmitter().emit(\"negotiate\", { type: \"candidate\", payload: \"cand\" });\n await Promise.resolve();\n\n expect(relayed).toEqual([\n { type: \"offer\", payload: \"sdp\" },\n { type: \"candidate\", payload: \"cand\" },\n ]);\n });\n\n it(\"encrypts outgoing messages and decrypts incoming ones\", async () => {\n const keyPair = generateKeyPair();\n const cipher = await createPeerCipher(keyPair, keyPair.publicKey);\n const { factory, sent, getEmitter } = createFakeTransport();\n const received: object[] = [];\n\n const layer = factory.create({\n cipher,\n isHost: true,\n onmessage: (message) => {\n received.push(message);\n },\n subsend: async () => {},\n });\n\n await layer.setup();\n getEmitter().emit(\"connected\");\n expect(layer.status.get()).toBe(Status.CONNECTED);\n\n await layer.send({ type: \"request\", messageId: \"1\", payload: { a: 1 } });\n expect(sent).toHaveLength(1);\n // Ciphertext on the wire, not the plaintext envelope.\n expect(sent[0]).not.toContain(\"messageId\");\n\n getEmitter().emit(\"message\", sent[0]);\n await new Promise(resolve => setTimeout(resolve, 10));\n expect(received).toEqual([{ type: \"request\", messageId: \"1\", payload: { a: 1 } }]);\n });\n\n it(\"rejects sends before the transport is connected\", async () => {\n const keyPair = generateKeyPair();\n const cipher = await createPeerCipher(keyPair, keyPair.publicKey);\n const { factory } = createFakeTransport();\n\n const layer = factory.create({\n cipher,\n isHost: true,\n onmessage: () => {},\n subsend: async () => {},\n });\n\n await layer.setup();\n await expect(layer.send({ a: 1 })).rejects.toThrow(\"Transport not connected\");\n });\n});\n"]}
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * without relying on centralized infrastructure.
6
6
  */
7
7
  import { type Observable } from "@openlv/core";
8
- import type { DecryptionKey, EncryptionKey } from "@openlv/core/encryption";
8
+ import type { Cipher } from "@openlv/core/encryption";
9
9
  import { EventEmitter } from "eventemitter3";
10
10
  import type { TransportLayerImplFunction } from "./layer.js";
11
11
  import type { WebRTCConfig } from "./webrtc/index.js";
@@ -22,14 +22,9 @@ export type TLayerEventMap = {
22
22
  };
23
23
  export type TransportLayerParameters = {
24
24
  isHost: boolean;
25
- encrypt: EncryptionKey["encrypt"];
26
- decrypt: DecryptionKey["decrypt"];
25
+ cipher: Cipher;
27
26
  subsend: (message: TransportMessage) => Promise<void>;
28
- onmessage: (message: {
29
- type: string;
30
- payload: object;
31
- messageId: string;
32
- }) => void;
27
+ onmessage: (message: object) => void;
33
28
  };
34
29
  /**
35
30
  * A transport negotiation message, relayed over signaling before the direct
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ export const Status = {
21
21
  */
22
22
  export const createTransportBase = (transportId, init) => ({
23
23
  transportId,
24
- create: ({ encrypt, decrypt, subsend, isHost, onmessage }) => {
24
+ create: ({ cipher, subsend, isHost, onmessage }) => {
25
25
  const emitter = new EventEmitter();
26
26
  const internalEmitter = new EventEmitter();
27
27
  const [status, setStatus] = observable(Status.STANDBY);
@@ -48,8 +48,12 @@ export const createTransportBase = (transportId, init) => ({
48
48
  // Peer data is untrusted until decrypted AND parsed; drop anything that
49
49
  // fails either step rather than surfacing an unhandled rejection.
50
50
  try {
51
- const data = await decrypt(message);
52
- onmessage(JSON.parse(data));
51
+ const data = await cipher.decrypt(message);
52
+ const parsed = JSON.parse(data);
53
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
54
+ throw new Error("Invalid transport message");
55
+ }
56
+ onmessage(parsed);
53
57
  }
54
58
  catch (error) {
55
59
  log("dropping undecryptable transport message", error);
@@ -62,7 +66,7 @@ export const createTransportBase = (transportId, init) => ({
62
66
  const send = async (message) => {
63
67
  if (status.get() !== Status.CONNECTED)
64
68
  throw new Error("Transport not connected");
65
- const payload = await encrypt(JSON.stringify(message));
69
+ const payload = await cipher.encrypt(JSON.stringify(message));
66
70
  await sendLayer(payload);
67
71
  };
68
72
  const setup = async () => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Open Lavatory Protocol - Decentralized Wallet Connection Library\n *\n * A privacy-first, peer-to-peer protocol for connecting dApps with wallets\n * without relying on centralized infrastructure.\n */\nimport { type Observable, observable } from \"@openlv/core\";\nimport type { DecryptionKey, EncryptionKey } from \"@openlv/core/encryption\";\nimport { EventEmitter } from \"eventemitter3\";\n\nimport type { TransportLayerBaseEventMap, TransportLayerImplFunction } from \"./layer.js\";\nimport { log } from \"./utils/log.js\";\nimport type { WebRTCConfig } from \"./webrtc/index.js\";\n\nexport const Status = {\n STANDBY: \"standby\",\n CONNECTING: \"connecting\",\n READY: \"ready\",\n CONNECTED: \"connected\",\n ERROR: \"error\",\n} as const;\nexport type Status\n = (typeof Status)[keyof typeof Status];\n\nexport type TLayerEventMap = {\n error: (reason?: string) => void;\n};\n\nexport type TransportLayerParameters = {\n isHost: boolean;\n encrypt: EncryptionKey[\"encrypt\"];\n decrypt: DecryptionKey[\"decrypt\"];\n subsend: (message: TransportMessage) => Promise<void>;\n onmessage: (message: { type: string; payload: object; messageId: string; }) => void;\n};\n\n/**\n * A transport negotiation message, relayed over signaling before the direct\n * connection exists. The shape of `type`/`payload` is owned by the selected\n * transport; unknown types must be ignored, not fatal.\n */\nexport type TransportMessage = {\n type: string;\n payload: string;\n};\nexport type TransportLayer = {\n type: TransportProtocol;\n setup: () => Promise<void>;\n teardown: () => Promise<void>;\n send: (message: object) => Promise<void>;\n handle: (message: TransportMessage) => Promise<void>;\n emitter: EventEmitter<TLayerEventMap>;\n status: Observable<Status>;\n};\nexport type TransportProtocol = \"wrtc\" | \"ws\" | (string & {});\nexport type TransportLayerFunction = {\n transportId: TransportProtocol;\n create: (parameters: TransportLayerParameters) => TransportLayer;\n};\nexport type Transport = (config?: WebRTCConfig) => TransportLayerFunction;\n\n/**\n * Base Transport Layer implementation\n *\n * https://openlv.sh/api/transport\n */\nexport const createTransportBase = (\n transportId: TransportProtocol,\n init: TransportLayerImplFunction,\n): TransportLayerFunction => ({\n transportId,\n create: ({ encrypt, decrypt, subsend, isHost, onmessage }) => {\n const emitter = new EventEmitter<TLayerEventMap>();\n const internalEmitter = new EventEmitter<TransportLayerBaseEventMap>();\n\n const [status, setStatus] = observable<Status>(Status.STANDBY);\n\n internalEmitter.on(\"negotiate\", async (message) => {\n try {\n await subsend(message);\n }\n catch (error) {\n log(\"failed to relay negotiation message\", error);\n }\n });\n internalEmitter.on(\"connected\", () => {\n log(\"onConnected\");\n setStatus(Status.CONNECTED);\n });\n internalEmitter.on(\"error\", (reason) => {\n log(\"transport error\", reason);\n // Surface the reason before the state flips so listeners reading\n // state on state_change already see it.\n emitter.emit(\"error\", reason);\n setStatus(Status.ERROR);\n });\n internalEmitter.on(\"message\", async (message) => {\n // Peer data is untrusted until decrypted AND parsed; drop anything that\n // fails either step rather than surfacing an unhandled rejection.\n try {\n const data = await decrypt(message);\n\n onmessage(JSON.parse(data) as { type: string; payload: object; messageId: string; });\n }\n catch (error) {\n log(\"dropping undecryptable transport message\", error);\n }\n });\n\n const {\n send: sendLayer,\n handle,\n ...channel\n } = init({\n emitter: internalEmitter,\n isHost,\n });\n\n const send = async (message: object) => {\n if (status.get() !== Status.CONNECTED)\n throw new Error(\"Transport not connected\");\n\n const payload = await encrypt(JSON.stringify(message));\n\n await sendLayer(payload);\n };\n\n const setup = async () => {\n setStatus(Status.CONNECTING);\n await channel.setup();\n setStatus(Status.READY);\n };\n\n const teardown = async () => {\n await channel.teardown();\n };\n\n return {\n type: transportId,\n setup,\n teardown,\n handle,\n send,\n emitter,\n status,\n };\n },\n});\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Open Lavatory Protocol - Decentralized Wallet Connection Library\n *\n * A privacy-first, peer-to-peer protocol for connecting dApps with wallets\n * without relying on centralized infrastructure.\n */\nimport { type Observable, observable } from \"@openlv/core\";\nimport type { Cipher } from \"@openlv/core/encryption\";\nimport { EventEmitter } from \"eventemitter3\";\n\nimport type { TransportLayerBaseEventMap, TransportLayerImplFunction } from \"./layer.js\";\nimport { log } from \"./utils/log.js\";\nimport type { WebRTCConfig } from \"./webrtc/index.js\";\n\nexport const Status = {\n STANDBY: \"standby\",\n CONNECTING: \"connecting\",\n READY: \"ready\",\n CONNECTED: \"connected\",\n ERROR: \"error\",\n} as const;\nexport type Status\n = (typeof Status)[keyof typeof Status];\n\nexport type TLayerEventMap = {\n error: (reason?: string) => void;\n};\n\nexport type TransportLayerParameters = {\n isHost: boolean;\n cipher: Cipher;\n subsend: (message: TransportMessage) => Promise<void>;\n onmessage: (message: object) => void;\n};\n\n/**\n * A transport negotiation message, relayed over signaling before the direct\n * connection exists. The shape of `type`/`payload` is owned by the selected\n * transport; unknown types must be ignored, not fatal.\n */\nexport type TransportMessage = {\n type: string;\n payload: string;\n};\nexport type TransportLayer = {\n type: TransportProtocol;\n setup: () => Promise<void>;\n teardown: () => Promise<void>;\n send: (message: object) => Promise<void>;\n handle: (message: TransportMessage) => Promise<void>;\n emitter: EventEmitter<TLayerEventMap>;\n status: Observable<Status>;\n};\nexport type TransportProtocol = \"wrtc\" | \"ws\" | (string & {});\nexport type TransportLayerFunction = {\n transportId: TransportProtocol;\n create: (parameters: TransportLayerParameters) => TransportLayer;\n};\nexport type Transport = (config?: WebRTCConfig) => TransportLayerFunction;\n\n/**\n * Base Transport Layer implementation\n *\n * https://openlv.sh/api/transport\n */\nexport const createTransportBase = (\n transportId: TransportProtocol,\n init: TransportLayerImplFunction,\n): TransportLayerFunction => ({\n transportId,\n create: ({ cipher, subsend, isHost, onmessage }) => {\n const emitter = new EventEmitter<TLayerEventMap>();\n const internalEmitter = new EventEmitter<TransportLayerBaseEventMap>();\n\n const [status, setStatus] = observable<Status>(Status.STANDBY);\n\n internalEmitter.on(\"negotiate\", async (message) => {\n try {\n await subsend(message);\n }\n catch (error) {\n log(\"failed to relay negotiation message\", error);\n }\n });\n internalEmitter.on(\"connected\", () => {\n log(\"onConnected\");\n setStatus(Status.CONNECTED);\n });\n internalEmitter.on(\"error\", (reason) => {\n log(\"transport error\", reason);\n // Surface the reason before the state flips so listeners reading\n // state on state_change already see it.\n emitter.emit(\"error\", reason);\n setStatus(Status.ERROR);\n });\n internalEmitter.on(\"message\", async (message) => {\n // Peer data is untrusted until decrypted AND parsed; drop anything that\n // fails either step rather than surfacing an unhandled rejection.\n try {\n const data = await cipher.decrypt(message);\n\n const parsed: unknown = JSON.parse(data);\n\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(\"Invalid transport message\");\n }\n\n onmessage(parsed);\n }\n catch (error) {\n log(\"dropping undecryptable transport message\", error);\n }\n });\n\n const {\n send: sendLayer,\n handle,\n ...channel\n } = init({\n emitter: internalEmitter,\n isHost,\n });\n\n const send = async (message: object) => {\n if (status.get() !== Status.CONNECTED)\n throw new Error(\"Transport not connected\");\n\n const payload = await cipher.encrypt(JSON.stringify(message));\n\n await sendLayer(payload);\n };\n\n const setup = async () => {\n setStatus(Status.CONNECTING);\n await channel.setup();\n setStatus(Status.READY);\n };\n\n const teardown = async () => {\n await channel.teardown();\n };\n\n return {\n type: transportId,\n setup,\n teardown,\n handle,\n send,\n emitter,\n status,\n };\n },\n});\n"]}
@@ -1,18 +1,16 @@
1
- import { generateKeyPair } from "@openlv/core/encryption";
1
+ import { createPeerCipher, generateKeyPair } from "@openlv/core/encryption";
2
2
  import { EventEmitter } from "eventemitter3";
3
3
  import { describe, expect, it } from "vitest";
4
4
  import { Status } from "./index.js";
5
5
  import { webrtc } from "./webrtc/index.js";
6
6
  describe("Transport", () => {
7
7
  it("should be able to create a transport", async () => {
8
- const { encryptionKey: publicKey, decryptionKey } = await generateKeyPair();
9
- const { encrypt } = publicKey;
10
- const { decrypt } = decryptionKey;
8
+ const keyPair = generateKeyPair();
9
+ const cipher = await createPeerCipher(keyPair, keyPair.publicKey);
11
10
  const signalA = new EventEmitter();
12
11
  const signalB = new EventEmitter();
13
12
  const transportA = webrtc().create({
14
- encrypt,
15
- decrypt,
13
+ cipher,
16
14
  subsend: async (m) => {
17
15
  signalA.emit("signal", m);
18
16
  },
@@ -22,8 +20,7 @@ describe("Transport", () => {
22
20
  },
23
21
  });
24
22
  const transportB = webrtc().create({
25
- encrypt,
26
- decrypt,
23
+ cipher,
27
24
  subsend: async (m) => {
28
25
  signalB.emit("signal", m);
29
26
  },
@@ -1 +1 @@
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 { EventEmitter } from \"eventemitter3\";\nimport { describe, expect, it } from \"vitest\";\n\nimport { Status } from \"./index.js\";\nimport { webrtc } from \"./webrtc/index.js\";\n\ndescribe(\"Transport\", () => {\n it(\"should be able to create a transport\", async () => {\n const { encryptionKey: publicKey, decryptionKey } = await generateKeyPair();\n const { encrypt } = publicKey;\n const { decrypt } = decryptionKey;\n const signalA = new EventEmitter<{ signal: string; message: object; }>();\n const signalB = new EventEmitter<{ signal: string; message: object; }>();\n\n const transportA = webrtc().create({\n encrypt,\n decrypt,\n subsend: async (m) => {\n signalA.emit(\"signal\", m);\n },\n isHost: true,\n onmessage: (m) => {\n signalA.emit(\"message\", m);\n },\n });\n const transportB = webrtc().create({\n encrypt,\n decrypt,\n subsend: async (m) => {\n signalB.emit(\"signal\", m);\n },\n isHost: false,\n onmessage: (m) => {\n signalB.emit(\"message\", m);\n },\n });\n\n signalA.on(\"signal\", (m) => {\n console.log(\"messageA\", m);\n transportB.handle(m);\n });\n signalB.on(\"signal\", (m) => {\n console.log(\"messageB\", m);\n transportA.handle(m);\n });\n\n console.log(\"test: setup\");\n await Promise.all([transportA.setup(), transportB.setup()]);\n\n console.log(\"test: waitFor connected\");\n await Promise.all([transportA, transportB].map(transport => new Promise<void>((resolve) => {\n if (transport.status.get() === Status.CONNECTED) return resolve();\n\n transport.status.subscribe((status) => {\n if (status === Status.CONNECTED) resolve();\n });\n })));\n\n console.log(\"test: connected\");\n\n const awaitedMessageAtB = new Promise<object>((resolve) => {\n signalB.on(\"message\", (m) => {\n console.log(\"messageB\", m);\n resolve(m);\n });\n });\n\n console.log(\"test: send message to A\");\n await transportA.send({ data: \"test_123\" });\n\n console.log(\"test: await message at B\");\n const messageAtB = await awaitedMessageAtB;\n\n expect(messageAtB).toEqual({ data: \"test_123\" });\n\n console.log(\"test: message at B\", messageAtB);\n const awaitedMessageAtA = new Promise<object>((resolve) => {\n signalA.on(\"message\", (m) => {\n console.log(\"messageA\", m);\n resolve(m);\n });\n });\n\n await transportB.send({ data: \"test_456\" });\n const messageAtA = await awaitedMessageAtA;\n\n expect(messageAtA).toEqual({ data: \"test_456\" });\n\n await Promise.all([transportA.teardown(), transportB.teardown()]);\n\n expect(transportA).toBeDefined();\n expect(transportB).toBeDefined();\n });\n});\n"]}
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { createPeerCipher, generateKeyPair } from \"@openlv/core/encryption\";\nimport { EventEmitter } from \"eventemitter3\";\nimport { describe, expect, it } from \"vitest\";\n\nimport { Status } from \"./index.js\";\nimport { webrtc } from \"./webrtc/index.js\";\n\ndescribe(\"Transport\", () => {\n it(\"should be able to create a transport\", async () => {\n const keyPair = generateKeyPair();\n const cipher = await createPeerCipher(keyPair, keyPair.publicKey);\n const signalA = new EventEmitter<{ signal: string; message: object; }>();\n const signalB = new EventEmitter<{ signal: string; message: object; }>();\n\n const transportA = webrtc().create({\n cipher,\n subsend: async (m) => {\n signalA.emit(\"signal\", m);\n },\n isHost: true,\n onmessage: (m) => {\n signalA.emit(\"message\", m);\n },\n });\n const transportB = webrtc().create({\n cipher,\n subsend: async (m) => {\n signalB.emit(\"signal\", m);\n },\n isHost: false,\n onmessage: (m) => {\n signalB.emit(\"message\", m);\n },\n });\n\n signalA.on(\"signal\", (m) => {\n console.log(\"messageA\", m);\n transportB.handle(m);\n });\n signalB.on(\"signal\", (m) => {\n console.log(\"messageB\", m);\n transportA.handle(m);\n });\n\n console.log(\"test: setup\");\n await Promise.all([transportA.setup(), transportB.setup()]);\n\n console.log(\"test: waitFor connected\");\n await Promise.all([transportA, transportB].map(transport => new Promise<void>((resolve) => {\n if (transport.status.get() === Status.CONNECTED) return resolve();\n\n transport.status.subscribe((status) => {\n if (status === Status.CONNECTED) resolve();\n });\n })));\n\n console.log(\"test: connected\");\n\n const awaitedMessageAtB = new Promise<object>((resolve) => {\n signalB.on(\"message\", (m) => {\n console.log(\"messageB\", m);\n resolve(m);\n });\n });\n\n console.log(\"test: send message to A\");\n await transportA.send({ data: \"test_123\" });\n\n console.log(\"test: await message at B\");\n const messageAtB = await awaitedMessageAtB;\n\n expect(messageAtB).toEqual({ data: \"test_123\" });\n\n console.log(\"test: message at B\", messageAtB);\n const awaitedMessageAtA = new Promise<object>((resolve) => {\n signalA.on(\"message\", (m) => {\n console.log(\"messageA\", m);\n resolve(m);\n });\n });\n\n await transportB.send({ data: \"test_456\" });\n const messageAtA = await awaitedMessageAtA;\n\n expect(messageAtA).toEqual({ data: \"test_456\" });\n\n await Promise.all([transportA.teardown(), transportB.teardown()]);\n\n expect(transportA).toBeDefined();\n expect(transportB).toBeDefined();\n });\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openlv/transport",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "keywords": [
5
5
  "open-lavatory"
6
6
  ],
@@ -42,7 +42,7 @@
42
42
  "eventemitter3": "^5.0.1",
43
43
  "globals": "^16.2.0",
44
44
  "ts-pattern": "^5",
45
- "@openlv/core": "0.2.0"
45
+ "@openlv/core": "0.3.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@vitest/browser-playwright": "^4.0.8",