@vex-chat/libvex 7.1.6 → 7.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/Client.d.ts +57 -3
- package/dist/Client.d.ts.map +1 -1
- package/dist/Client.js +683 -101
- package/dist/Client.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/Client.ts +915 -118
- package/src/__tests__/harness/shared-suite.ts +80 -1
- package/src/index.ts +11 -1
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* - `LIBVEX_DEBUG_DM=1` — logs DM/X3dh paths in `Client` to stderr (remove / gate off when done).
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
import type { ClientOptions, Message } from "../../index.js";
|
|
30
|
+
import type { CallEvent, ClientOptions, Message } from "../../index.js";
|
|
31
31
|
import type { Storage } from "../../Storage.js";
|
|
32
32
|
|
|
33
33
|
import { getCryptoProfile, setCryptoProfile } from "@vex-chat/crypto";
|
|
@@ -117,6 +117,64 @@ export function platformSuite(
|
|
|
117
117
|
expect(msg.extra).toBe(extra);
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
+
test("encrypted call invite arrives as call event", async () => {
|
|
121
|
+
class NativeIceCandidate {
|
|
122
|
+
toJSON() {
|
|
123
|
+
return {
|
|
124
|
+
candidate: "candidate-test",
|
|
125
|
+
sdpMid: "0",
|
|
126
|
+
sdpMLineIndex: 0,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
class NativeSessionDescription {
|
|
131
|
+
toJSON() {
|
|
132
|
+
return { sdp: "test-offer", type: "offer" };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const me = client.me.user();
|
|
137
|
+
let unexpectedMessages = 0;
|
|
138
|
+
const onMessage = (_msg: Message) => {
|
|
139
|
+
unexpectedMessages += 1;
|
|
140
|
+
};
|
|
141
|
+
client.on("message", onMessage);
|
|
142
|
+
try {
|
|
143
|
+
const callPromise = waitForCall(
|
|
144
|
+
client,
|
|
145
|
+
(event) =>
|
|
146
|
+
event.action === "invite" &&
|
|
147
|
+
event.fromDeviceID === client.me.device().deviceID,
|
|
148
|
+
`[${platformName}] encrypted self-call invite`,
|
|
149
|
+
);
|
|
150
|
+
const returned = await client.calls.startDM(me.userID, {
|
|
151
|
+
candidate: new NativeIceCandidate(),
|
|
152
|
+
description: new NativeSessionDescription(),
|
|
153
|
+
kind: "offer",
|
|
154
|
+
});
|
|
155
|
+
const incoming = await callPromise;
|
|
156
|
+
expect(returned.call.callID).toBe(incoming.call.callID);
|
|
157
|
+
expect(incoming.signal?.kind).toBe("offer");
|
|
158
|
+
expect(incoming.signal?.candidate).toEqual({
|
|
159
|
+
candidate: "candidate-test",
|
|
160
|
+
sdpMid: "0",
|
|
161
|
+
sdpMLineIndex: 0,
|
|
162
|
+
});
|
|
163
|
+
expect(incoming.signal?.description).toEqual({
|
|
164
|
+
sdp: "test-offer",
|
|
165
|
+
type: "offer",
|
|
166
|
+
});
|
|
167
|
+
expect(unexpectedMessages).toBe(0);
|
|
168
|
+
|
|
169
|
+
const active = await client.calls.active();
|
|
170
|
+
expect(
|
|
171
|
+
active.some((call) => call.callID === incoming.call.callID),
|
|
172
|
+
).toBe(true);
|
|
173
|
+
} finally {
|
|
174
|
+
client.off("message", onMessage);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
120
178
|
test("message history retrieve + delete", async () => {
|
|
121
179
|
const me = client.me.user();
|
|
122
180
|
const body = "history-test";
|
|
@@ -721,6 +779,27 @@ async function e2eWaitForPeerDeviceCount(
|
|
|
721
779
|
}
|
|
722
780
|
*/
|
|
723
781
|
|
|
782
|
+
async function waitForCall(
|
|
783
|
+
c: Client,
|
|
784
|
+
predicate: (event: CallEvent) => boolean,
|
|
785
|
+
label: string,
|
|
786
|
+
timeout = 10_000,
|
|
787
|
+
): Promise<CallEvent> {
|
|
788
|
+
return new Promise((resolve, reject) => {
|
|
789
|
+
const timer = setTimeout(() => {
|
|
790
|
+
reject(new Error(`${label} call timed out`));
|
|
791
|
+
}, timeout);
|
|
792
|
+
const onCall = (event: CallEvent) => {
|
|
793
|
+
if (predicate(event)) {
|
|
794
|
+
clearTimeout(timer);
|
|
795
|
+
c.off("call", onCall);
|
|
796
|
+
resolve(event);
|
|
797
|
+
}
|
|
798
|
+
};
|
|
799
|
+
c.on("call", onCall);
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
|
|
724
803
|
async function waitForMessage(
|
|
725
804
|
c: Client,
|
|
726
805
|
predicate: (m: Message) => boolean,
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
export { Client, DeviceApprovalRequiredError } from "./Client.js";
|
|
8
8
|
export type {
|
|
9
|
+
Calls,
|
|
9
10
|
Channel,
|
|
10
11
|
Channels,
|
|
11
12
|
ClientEvents,
|
|
@@ -96,4 +97,13 @@ export type {
|
|
|
96
97
|
UnsavedPreKey,
|
|
97
98
|
} from "./types/index.js";
|
|
98
99
|
// Re-export app-facing types
|
|
99
|
-
export type {
|
|
100
|
+
export type {
|
|
101
|
+
CallAction,
|
|
102
|
+
CallEvent,
|
|
103
|
+
CallParticipant,
|
|
104
|
+
CallSession,
|
|
105
|
+
CallSignalPayload,
|
|
106
|
+
IceServerConfig,
|
|
107
|
+
Invite,
|
|
108
|
+
Passkey,
|
|
109
|
+
} from "@vex-chat/types";
|