wip webrtc
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Martti Malmi 2023-12-21 11:56:49 +02:00
parent 0c2ed147b0
commit 1309937869
11 changed files with 569 additions and 7 deletions

View File

@ -38,6 +38,7 @@
"react-tag-input-component": "^2.0.2",
"react-textarea-autosize": "^8.4.0",
"recharts": "^2.8.0",
"socket.io-client": "^4.7.2",
"three": "^0.157.0",
"use-long-press": "^3.2.0",
"use-sync-external-store": "^1.2.0",

View File

@ -1,5 +1,6 @@
import { NostrEvent, OkResponse, SystemInterface } from "@snort/system";
import { removeUndefined } from "@snort/shared";
import {getWebRtcPool} from "@/webrtc";
export async function sendEventToRelays(
system: SystemInterface,
@ -8,6 +9,7 @@ export async function sendEventToRelays(
setResults?: (x: Array<OkResponse>) => void,
) {
console.log("sendEventToRelays", ev, customRelays);
getWebRtcPool()?.send(ev);
if (customRelays) {
return removeUndefined(
await Promise.all(

View File

@ -1,6 +1,7 @@
import "./index.css";
import "@szhsin/react-menu/dist/index.css";
import "./fonts/inter.css";
import "./webrtc";
import {
compress,

View File

@ -0,0 +1,106 @@
import { Socket } from "socket.io-client";
import EventEmitter from "eventemitter3";
export class WebRTCConnection extends EventEmitter {
private peerConnection: RTCPeerConnection;
private dataChannel: RTCDataChannel;
constructor(private socket: Socket, configuration: RTCConfiguration, public peerId: string) {
super();
this.peerConnection = new RTCPeerConnection(configuration);
this.dataChannel = this.peerConnection.createDataChannel("data");
this.registerPeerConnectionEvents();
this.setupDataChannel();
}
private log(...args: any[]): void {
console.log(this.peerId, ...args);
}
public async handleOffer(offer: RTCSessionDescriptionInit): Promise<void> {
this.log('Received offer', offer);
await this.peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
await this.sendLocalDescription('answer');
}
public async handleAnswer(answer: RTCSessionDescriptionInit): Promise<void> {
this.log('Received answer', answer);
await this.peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
}
public handleCandidate(candidate: RTCIceCandidateInit): void {
this.log('Received ICE candidate', candidate);
this.peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
}
private async sendLocalDescription(type: 'offer' | 'answer'): Promise<void> {
let description;
if (type === 'offer') {
description = await this.peerConnection.createOffer();
} else {
description = await this.peerConnection.createAnswer();
}
await this.peerConnection.setLocalDescription(description);
this.socket.emit(type, { [type]: description, recipient: this.peerId });
this.log(`Sent ${type}`, description);
}
private setupDataChannel(): void {
this.dataChannel.onopen = () => this.log('Data channel opened');
this.dataChannel.onclose = () => this.log('Data channel closed');
this.dataChannel.onmessage = event => this.handleDataChannelMessage(event);
}
private handleDataChannelMessage(event: MessageEvent): void {
this.log(`-> "${event.data}"`);
if (event.data === 'ping') {
this.send('pong');
} else {
try {
const data = JSON.parse(event.data);
this.emit('event', data);
} catch (e) {
// Ignore
}
}
}
public send(data: any): void {
if (this.dataChannel.readyState === 'open') {
this.log(`<- "${data}"`);
this.dataChannel.send(data);
}
}
public async handleHello(): Promise<void> {
if (this.peerConnection.connectionState === 'new') {
await this.sendLocalDescription('offer');
}
}
private registerPeerConnectionEvents(): void {
this.peerConnection.onicecandidate = event => {
if (event.candidate) {
this.log('Local ICE candidate:', event.candidate);
this.socket.emit('candidate', { candidate: event.candidate.toJSON(), recipient: this.peerId });
}
};
this.peerConnection.oniceconnectionstatechange = () => {
this.log('ICE Connection State Change:', this.peerConnection.iceConnectionState);
};
this.peerConnection.onconnectionstatechange = () => {
this.log('WebRTC Connection State Change:', this.peerConnection.connectionState);
};
this.peerConnection.ondatachannel = event => {
this.dataChannel = event.channel;
this.setupDataChannel();
};
}
public close(): void {
this.peerConnection.close();
}
}

View File

@ -0,0 +1,86 @@
import {io, Socket} from 'socket.io-client';
import {WebRTCConnection} from '@/webrtc/WebRTCConnection';
import EventEmitter from "eventemitter3";
const MAX_CONNECTIONS = 5;
class WebRTCPool extends EventEmitter {
private signalingServer: Socket;
private peers: Map<string, WebRTCConnection> = new Map();
private configuration: RTCConfiguration;
private peerId: string;
constructor(serverUrl: string, configuration: RTCConfiguration = {}, peerId: string) {
super();
this.signalingServer = io(serverUrl);
this.configuration = configuration;
this.peerId = peerId;
this.registerSocketEvents();
}
private sayHello(): void {
this.signalingServer.emit('hello', this.peerId);
}
public send(data: any, recipients?: string[]): void {
this.peers.forEach(conn => {
if (!recipients || recipients.includes(conn.peerId)) {
try {
conn.send(typeof data === 'string' ? data : JSON.stringify(data));
} catch (e) {
console.error(e);
}
}
});
}
public createConnection(peerId: string): WebRTCConnection {
if (this.peers.size >= MAX_CONNECTIONS) {
throw new Error('Maximum connections reached');
}
const connection = new WebRTCConnection(this.signalingServer, this.configuration, peerId);
connection.on('event', (event: any) => this.emit('event', event));
this.peers.set(peerId, connection);
return connection;
}
private handleConnectionEvent(sender: string, action: (connection: WebRTCConnection) => Promise<void>): void {
if (sender === this.peerId || this.peers.size >= MAX_CONNECTIONS) return;
const connection = this.peers.get(sender) ?? this.createConnection(sender);
action(connection);
}
private registerSocketEvents(): void {
this.signalingServer.on('connect', () => {
console.log('Connected to signaling server');
this.sayHello();
});
this.signalingServer.on('offer', ({offer, sender}: { offer: RTCSessionDescriptionInit; sender: string }) => {
this.handleConnectionEvent(sender, async conn => await conn.handleOffer(offer));
});
this.signalingServer.on('answer', ({answer, sender}: { answer: RTCSessionDescriptionInit; sender: string }) => {
this.handleConnectionEvent(sender, async conn => await conn.handleAnswer(answer));
});
this.signalingServer.on('candidate', ({candidate, sender}: { candidate: RTCIceCandidateInit; sender: string }) => {
this.handleConnectionEvent(sender, conn => conn.handleCandidate(candidate));
});
this.signalingServer.on('hello', (sender: string) => {
console.log('Received hello from', sender);
this.handleConnectionEvent(sender, conn => conn.handleHello());
});
}
public close(): void {
console.log('closing pool');
this.signalingServer.close();
for (const conn of this.peers.values()) {
conn.close();
}
}
}
export default WebRTCPool;

View File

@ -0,0 +1,25 @@
import {LoginStore} from "@/Login";
import WebRTCPool from "@/webrtc/WebRTCPool";
let publicKey: string | undefined;
let pool: WebRTCPool | undefined;
let interval: NodeJS.Timeout | undefined;
LoginStore.hook(() => {
const login = LoginStore.takeSnapshot();
if (login.publicKey && !login.readonly && login.publicKey !== publicKey) {
publicKey = login.publicKey;
if (location.hostname === 'localhost') {
pool?.close();
interval && clearInterval(interval);
pool = new WebRTCPool('http://localhost:3000', {
iceServers: [{ urls: 'stun:localhost:3478' }],
}, login.publicKey);
interval = setInterval(() => pool?.send('ping'), 10000);
}
}
});
export function getWebRtcPool(): WebRTCPool | undefined {
return pool;
}

View File

@ -193,7 +193,6 @@ export class NostrSystem extends EventEmitter<NostrSystemEvents> implements Syst
#onEvent(sub: string, ev: TaggedNostrEvent) {
this.#relayMetrics.onEvent(ev.relays[0]);
this.emit("event", ev);
if (!EventExt.isValid(ev)) {
this.#log("Rejecting invalid event %O", ev);
@ -207,6 +206,8 @@ export class NostrSystem extends EventEmitter<NostrSystemEvents> implements Syst
}
}
this.emit("event", ev);
for (const [, v] of this.Queries) {
v.handleEvent(sub, ev);
}

View File

@ -0,0 +1,8 @@
# webrtc-server
```
yarn
yarn start
```
Websocket (socket.io) based signaling server for WebRTC.

View File

@ -0,0 +1,56 @@
const PORT = process.env.PORT || 3000;
const io = require('socket.io')(PORT, {
cors: {
origin: "*",
methods: ["GET", "POST"]
}
});
const peerSocketMap = new Map();
const socketPeerMap = new Map();
io.on('connection', socket => {
console.log(`New client connected, socket ID: ${socket.id}`);
const emitToTarget = (eventType, data, recipient) => {
const targetSocketId = peerSocketMap.get(recipient);
const sender = socketPeerMap.get(socket.id);
if (sender && targetSocketId) {
io.to(targetSocketId).emit(eventType, {...data, sender});
}
};
socket.on('offer', data => emitToTarget('offer', data, data.recipient));
socket.on('answer', data => emitToTarget('answer', data, data.recipient));
socket.on('candidate', data => emitToTarget('candidate', data, data.recipient));
socket.on('hello', peerId => {
console.log(`Received hello from ${peerId}`);
peerSocketMap.set(peerId, socket.id);
socketPeerMap.set(socket.id, peerId);
socket.broadcast.emit('hello', peerId);
});
socket.on('disconnect', () => {
peerSocketMap.delete(socketPeerMap.get(socket.id));
socketPeerMap.delete(socket.id);
console.log(`Client disconnected, socket ID: ${socket.id}`);
});
});
console.log(`Signaling server running on port ${PORT}`);
const Ministun = require("ministun");
const stunConfig = {
udp4: true,
udp6: true,
port: 3478,
log: console.log,
err: console.err,
sw: true
};
const server = new Ministun(stunConfig);
console.log(`STUN server running on port ${stunConfig.port}`)

View File

@ -0,0 +1,11 @@
{
"name": "nostr-webrtc-server",
"dependencies": {
"ministun": "^1.0.6",
"nostr-tools": "^2.0.2",
"socket.io": "^4.7.2"
},
"scripts": {
"start": "node index.js"
}
}

277
yarn.lock
View File

@ -2557,7 +2557,14 @@ __metadata:
languageName: node
linkType: hard
"@noble/curves@npm:^1.0.0, @noble/curves@npm:^1.2.0, @noble/curves@npm:~1.2.0":
"@noble/ciphers@npm:0.2.0":
version: 0.2.0
resolution: "@noble/ciphers@npm:0.2.0"
checksum: fa6c14b66865cee83ee779a4ca4c8b39a6397425fae3f805d1766a2daf887d950d3771a68bb95e89cc3afbd595a219b44e8529aa4aaaad0ea5c030c1fb589ef4
languageName: node
linkType: hard
"@noble/curves@npm:1.2.0, @noble/curves@npm:^1.0.0, @noble/curves@npm:^1.2.0, @noble/curves@npm:~1.2.0":
version: 1.2.0
resolution: "@noble/curves@npm:1.2.0"
dependencies:
@ -2566,6 +2573,22 @@ __metadata:
languageName: node
linkType: hard
"@noble/curves@npm:~1.1.0":
version: 1.1.0
resolution: "@noble/curves@npm:1.1.0"
dependencies:
"@noble/hashes": 1.3.1
checksum: 2658cdd3f84f71079b4e3516c47559d22cf4b55c23ac8ee9d2b1f8e5b72916d9689e59820e0f9d9cb4a46a8423af5b56dc6bb7782405c88be06a015180508db5
languageName: node
linkType: hard
"@noble/hashes@npm:1.3.1":
version: 1.3.1
resolution: "@noble/hashes@npm:1.3.1"
checksum: 7fdefc0f7a0c1ec27acc6ff88841793e3f93ec4ce6b8a6a12bfc0dd70ae6b7c4c82fe305fdfeda1735d5ad4a9eebe761e6693b3d355689c559e91242f4bc95b1
languageName: node
linkType: hard
"@noble/hashes@npm:1.3.2, @noble/hashes@npm:^1.2.0, @noble/hashes@npm:^1.3.2, @noble/hashes@npm:~1.3.0, @noble/hashes@npm:~1.3.2":
version: 1.3.2
resolution: "@noble/hashes@npm:1.3.2"
@ -2573,6 +2596,13 @@ __metadata:
languageName: node
linkType: hard
"@noble/hashes@npm:~1.3.1":
version: 1.3.3
resolution: "@noble/hashes@npm:1.3.3"
checksum: 8a6496d1c0c64797339bc694ad06cdfaa0f9e56cd0c3f68ae3666cfb153a791a55deb0af9c653c7ed2db64d537aa3e3054629740d2f2338bb1dcb7ab60cd205b
languageName: node
linkType: hard
"@noble/secp256k1@npm:^1.7.0":
version: 1.7.1
resolution: "@noble/secp256k1@npm:1.7.1"
@ -2832,6 +2862,17 @@ __metadata:
languageName: node
linkType: hard
"@scure/bip32@npm:1.3.1":
version: 1.3.1
resolution: "@scure/bip32@npm:1.3.1"
dependencies:
"@noble/curves": ~1.1.0
"@noble/hashes": ~1.3.1
"@scure/base": ~1.1.0
checksum: 394d65f77a40651eba21a5096da0f4233c3b50d422864751d373fcf142eeedb94a1149f9ab1dbb078086dab2d0bc27e2b1afec8321bf22d4403c7df2fea5bfe2
languageName: node
linkType: hard
"@scure/bip32@npm:^1.3.0":
version: 1.3.2
resolution: "@scure/bip32@npm:1.3.2"
@ -2843,7 +2884,7 @@ __metadata:
languageName: node
linkType: hard
"@scure/bip39@npm:^1.1.1":
"@scure/bip39@npm:1.2.1, @scure/bip39@npm:^1.1.1":
version: 1.2.1
resolution: "@scure/bip39@npm:1.2.1"
dependencies:
@ -2943,6 +2984,7 @@ __metadata:
react-textarea-autosize: ^8.4.0
recharts: ^2.8.0
rollup-plugin-visualizer: ^5.9.2
socket.io-client: ^4.7.2
tailwindcss: ^3.3.3
three: ^0.157.0
tinybench: ^2.5.1
@ -3045,6 +3087,13 @@ __metadata:
languageName: unknown
linkType: soft
"@socket.io/component-emitter@npm:~3.1.0":
version: 3.1.0
resolution: "@socket.io/component-emitter@npm:3.1.0"
checksum: db069d95425b419de1514dffe945cc439795f6a8ef5b9465715acf5b8b50798e2c91b8719cbf5434b3fe7de179d6cdcd503c277b7871cb3dd03febb69bdd50fa
languageName: node
linkType: hard
"@stablelib/binary@npm:^1.0.1":
version: 1.0.1
resolution: "@stablelib/binary@npm:1.0.1"
@ -3340,6 +3389,22 @@ __metadata:
languageName: node
linkType: hard
"@types/cookie@npm:^0.4.1":
version: 0.4.1
resolution: "@types/cookie@npm:0.4.1"
checksum: 3275534ed69a76c68eb1a77d547d75f99fedc80befb75a3d1d03662fb08d697e6f8b1274e12af1a74c6896071b11510631ba891f64d30c78528d0ec45a9c1a18
languageName: node
linkType: hard
"@types/cors@npm:^2.8.12":
version: 2.8.17
resolution: "@types/cors@npm:2.8.17"
dependencies:
"@types/node": "*"
checksum: 469bd85e29a35977099a3745c78e489916011169a664e97c4c3d6538143b0a16e4cc72b05b407dc008df3892ed7bf595f9b7c0f1f4680e169565ee9d64966bde
languageName: node
linkType: hard
"@types/d3-array@npm:^3.0.3":
version: 3.2.1
resolution: "@types/d3-array@npm:3.2.1"
@ -3553,6 +3618,15 @@ __metadata:
languageName: node
linkType: hard
"@types/node@npm:>=10.0.0":
version: 20.10.5
resolution: "@types/node@npm:20.10.5"
dependencies:
undici-types: ~5.26.4
checksum: e216b679f545a8356960ce985a0e53c3a58fff0eacd855e180b9e223b8db2b5bd07b744a002b8c1f0c37f9194648ab4578533b5c12df2ec10cc02f61d20948d2
languageName: node
linkType: hard
"@types/parse-torrent-file@npm:*":
version: 4.0.6
resolution: "@types/parse-torrent-file@npm:4.0.6"
@ -3997,6 +4071,16 @@ __metadata:
languageName: node
linkType: hard
"accepts@npm:~1.3.4":
version: 1.3.8
resolution: "accepts@npm:1.3.8"
dependencies:
mime-types: ~2.1.34
negotiator: 0.6.3
checksum: 50c43d32e7b50285ebe84b613ee4a3aa426715a7d131b65b786e2ead0fd76b6b60091b9916d3478a75f11f162628a2139991b6c03ab3f1d9ab7c86075dc8eab4
languageName: node
linkType: hard
"accessor-fn@npm:1":
version: 1.5.0
resolution: "accessor-fn@npm:1.5.0"
@ -4444,6 +4528,13 @@ __metadata:
languageName: node
linkType: hard
"base64id@npm:2.0.0, base64id@npm:~2.0.0":
version: 2.0.0
resolution: "base64id@npm:2.0.0"
checksum: 581b1d37e6cf3738b7ccdd4d14fe2bfc5c238e696e2720ee6c44c183b838655842e22034e53ffd783f872a539915c51b0d4728a49c7cc678ac5a758e00d62168
languageName: node
linkType: hard
"bech32@npm:^1.1.2":
version: 1.1.4
resolution: "bech32@npm:1.1.4"
@ -4851,6 +4942,13 @@ __metadata:
languageName: node
linkType: hard
"cookie@npm:~0.4.1":
version: 0.4.2
resolution: "cookie@npm:0.4.2"
checksum: a00833c998bedf8e787b4c342defe5fa419abd96b32f4464f718b91022586b8f1bafbddd499288e75c037642493c83083da426c6a9080d309e3bd90fd11baa9b
languageName: node
linkType: hard
"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1":
version: 3.33.2
resolution: "core-js-compat@npm:3.33.2"
@ -4860,6 +4958,16 @@ __metadata:
languageName: node
linkType: hard
"cors@npm:~2.8.5":
version: 2.8.5
resolution: "cors@npm:2.8.5"
dependencies:
object-assign: ^4
vary: ^1
checksum: ced838404ccd184f61ab4fdc5847035b681c90db7ac17e428f3d81d69e2989d2b680cc254da0e2554f5ed4f8a341820a1ce3d1c16b499f6e2f47a1b9b07b5006
languageName: node
linkType: hard
"create-jest@npm:^29.7.0":
version: 29.7.0
resolution: "create-jest@npm:29.7.0"
@ -5169,7 +5277,7 @@ __metadata:
languageName: node
linkType: hard
"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.4":
"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:~4.3.1, debug@npm:~4.3.2":
version: 4.3.4
resolution: "debug@npm:4.3.4"
dependencies:
@ -5420,6 +5528,44 @@ __metadata:
languageName: node
linkType: hard
"engine.io-client@npm:~6.5.2":
version: 6.5.3
resolution: "engine.io-client@npm:6.5.3"
dependencies:
"@socket.io/component-emitter": ~3.1.0
debug: ~4.3.1
engine.io-parser: ~5.2.1
ws: ~8.11.0
xmlhttprequest-ssl: ~2.0.0
checksum: a72596fae99afbdb899926fccdb843f8fa790c69085b881dde121285a6935da2c2c665ebe88e0e6aa4285637782df84ac882084ff4892ad2430b059fc0045db0
languageName: node
linkType: hard
"engine.io-parser@npm:~5.2.1":
version: 5.2.1
resolution: "engine.io-parser@npm:5.2.1"
checksum: 55b0e8e18500f50c1573675c53597c5552554ead08d3f30ff19fde6409e48f882a8e01f84e9772cd155c18a1d653d06f6bf57b4e1f8b834c63c9eaf3b657b88e
languageName: node
linkType: hard
"engine.io@npm:~6.5.2":
version: 6.5.4
resolution: "engine.io@npm:6.5.4"
dependencies:
"@types/cookie": ^0.4.1
"@types/cors": ^2.8.12
"@types/node": ">=10.0.0"
accepts: ~1.3.4
base64id: 2.0.0
cookie: ~0.4.1
cors: ~2.8.5
debug: ~4.3.1
engine.io-parser: ~5.2.1
ws: ~8.11.0
checksum: d5b55cbac718c5b1c10800314379923f8c7ef9e3a8a60c6827ed86303d1154b81d354a89fdecf4cbb773515c82c84a98d3c791ff88279393b53625dd67299d30
languageName: node
linkType: hard
"entities@npm:^4.4.0":
version: 4.5.0
resolution: "entities@npm:4.5.0"
@ -7991,7 +8137,7 @@ __metadata:
languageName: node
linkType: hard
"mime-types@npm:^2.1.12":
"mime-types@npm:^2.1.12, mime-types@npm:~2.1.34":
version: 2.1.35
resolution: "mime-types@npm:2.1.35"
dependencies:
@ -8108,6 +8254,13 @@ __metadata:
languageName: node
linkType: hard
"ministun@npm:^1.0.6":
version: 1.0.6
resolution: "ministun@npm:1.0.6"
checksum: 8eeb3d47a1d0cdd4d348a23d32811ab629c3e566fe88481a5d2dc9cc07afb0b8a34c353b1d16b5a02b01a1a694e9f8e447f81544621bcc6c962adf41f6833d34
languageName: node
linkType: hard
"minizlib@npm:^2.1.1, minizlib@npm:^2.1.2":
version: 2.1.2
resolution: "minizlib@npm:2.1.2"
@ -8173,7 +8326,7 @@ __metadata:
languageName: node
linkType: hard
"negotiator@npm:^0.6.3":
"negotiator@npm:0.6.3, negotiator@npm:^0.6.3":
version: 0.6.3
resolution: "negotiator@npm:0.6.3"
checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9
@ -8280,6 +8433,43 @@ __metadata:
languageName: node
linkType: hard
"nostr-tools@npm:^2.0.2":
version: 2.0.2
resolution: "nostr-tools@npm:2.0.2"
dependencies:
"@noble/ciphers": 0.2.0
"@noble/curves": 1.2.0
"@noble/hashes": 1.3.1
"@scure/base": 1.1.1
"@scure/bip32": 1.3.1
"@scure/bip39": 1.2.1
nostr-wasm: v0.0.3
peerDependencies:
typescript: ">=5.0.0"
peerDependenciesMeta:
typescript:
optional: true
checksum: 2112eb37e4a710f2fc2d33b40290a28324d213d9d7051bb364ecba634d92eb1cb24ec37303876cde855cd2353213d273a8a49b31b400f9abb1b301ee54d71c37
languageName: node
linkType: hard
"nostr-wasm@npm:v0.0.3":
version: 0.0.3
resolution: "nostr-wasm@npm:0.0.3"
checksum: 28100b46610293be9f0cc0036f8dce1ef69493a7d007f79c7187e60ae0f9b5c21a124738cbe6a876e503dd422185eb6ae7863a4b6a1d3fc8ad10c5a827a3c212
languageName: node
linkType: hard
"nostr-webrtc-server@workspace:packages/webrtc-server":
version: 0.0.0-use.local
resolution: "nostr-webrtc-server@workspace:packages/webrtc-server"
dependencies:
ministun: ^1.0.6
nostr-tools: ^2.0.2
socket.io: ^4.7.2
languageName: unknown
linkType: soft
"npm-run-path@npm:^4.0.1":
version: 4.0.1
resolution: "npm-run-path@npm:4.0.1"
@ -8296,7 +8486,7 @@ __metadata:
languageName: node
linkType: hard
"object-assign@npm:^4.0.1, object-assign@npm:^4.1.1":
"object-assign@npm:^4, object-assign@npm:^4.0.1, object-assign@npm:^4.1.1":
version: 4.1.1
resolution: "object-assign@npm:4.1.1"
checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f
@ -9939,6 +10129,52 @@ __metadata:
languageName: node
linkType: hard
"socket.io-adapter@npm:~2.5.2":
version: 2.5.2
resolution: "socket.io-adapter@npm:2.5.2"
dependencies:
ws: ~8.11.0
checksum: 481251c3547221e57eb5cb247d0b1a3cde4d152a4c1c9051cc887345a7770e59f3b47f1011cac4499e833f01fcfc301ed13c4ec6e72f7dbb48a476375a6344cd
languageName: node
linkType: hard
"socket.io-client@npm:^4.7.2":
version: 4.7.2
resolution: "socket.io-client@npm:4.7.2"
dependencies:
"@socket.io/component-emitter": ~3.1.0
debug: ~4.3.2
engine.io-client: ~6.5.2
socket.io-parser: ~4.2.4
checksum: 8f0ab6b623e014d889bae0cd847ef7826658e8f131bd9367ee5ae4404bb52a6d7b1755b8fbe8e68799b60e92149370a732b381f913b155e40094facb135cd088
languageName: node
linkType: hard
"socket.io-parser@npm:~4.2.4":
version: 4.2.4
resolution: "socket.io-parser@npm:4.2.4"
dependencies:
"@socket.io/component-emitter": ~3.1.0
debug: ~4.3.1
checksum: 61540ef99af33e6a562b9effe0fad769bcb7ec6a301aba5a64b3a8bccb611a0abdbe25f469933ab80072582006a78ca136bf0ad8adff9c77c9953581285e2263
languageName: node
linkType: hard
"socket.io@npm:^4.7.2":
version: 4.7.2
resolution: "socket.io@npm:4.7.2"
dependencies:
accepts: ~1.3.4
base64id: ~2.0.0
cors: ~2.8.5
debug: ~4.3.2
engine.io: ~6.5.2
socket.io-adapter: ~2.5.2
socket.io-parser: ~4.2.4
checksum: 2dfac8983a75e100e889c3dafc83b21b75a9863d0d1ee79cdc60c4391d5d9dffcf3a86fc8deca7568032bc11c2572676335fd2e469c7982f40d19f1141d4b266
languageName: node
linkType: hard
"socks-proxy-agent@npm:^8.0.1":
version: 8.0.2
resolution: "socks-proxy-agent@npm:8.0.2"
@ -10975,6 +11211,13 @@ __metadata:
languageName: node
linkType: hard
"vary@npm:^1":
version: 1.1.2
resolution: "vary@npm:1.1.2"
checksum: ae0123222c6df65b437669d63dfa8c36cee20a504101b2fcd97b8bf76f91259c17f9f2b4d70a1e3c6bbcee7f51b28392833adb6b2770b23b01abec84e369660b
languageName: node
linkType: hard
"victory-vendor@npm:^36.6.8":
version: 36.6.12
resolution: "victory-vendor@npm:36.6.12"
@ -11548,6 +11791,21 @@ __metadata:
languageName: node
linkType: hard
"ws@npm:~8.11.0":
version: 8.11.0
resolution: "ws@npm:8.11.0"
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: ^5.0.2
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
checksum: 316b33aba32f317cd217df66dbfc5b281a2f09ff36815de222bc859e3424d83766d9eb2bd4d667de658b6ab7be151f258318fb1da812416b30be13103e5b5c67
languageName: node
linkType: hard
"xml-name-validator@npm:^4.0.0":
version: 4.0.0
resolution: "xml-name-validator@npm:4.0.0"
@ -11562,6 +11820,13 @@ __metadata:
languageName: node
linkType: hard
"xmlhttprequest-ssl@npm:~2.0.0":
version: 2.0.0
resolution: "xmlhttprequest-ssl@npm:2.0.0"
checksum: 1e98df67f004fec15754392a131343ea92e6ab5ac4d77e842378c5c4e4fd5b6a9134b169d96842cc19422d77b1606b8df84a5685562b3b698cb68441636f827e
languageName: node
linkType: hard
"y18n@npm:^5.0.5":
version: 5.0.8
resolution: "y18n@npm:5.0.8"